diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 2b62f114837..acb7bd3c475 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -302,3 +302,4 @@ eb7febe45865ba6b81f2ea68082262d0708a0b22 jdk9-b56
f25ee9f62427a9ba27418e5531a89754791a305b jdk9-b57
6e78dd9b121037719a065fe8fb25b936babdfecb jdk9-b58
39e8a131289e8386aa4c3e4b184faa812a7c0421 jdk9-b59
+9fa2185bee17462d1014538bff60af6e6f0b01e7 jdk9-b60
diff --git a/README-builds.html b/README-builds.html
index edc8f742d65..b0cc892f9c4 100644
--- a/README-builds.html
+++ b/README-builds.html
@@ -41,7 +41,8 @@
The build is now a "configure && make" style build
- Any GNU make 3.81 or newer should work
+ Any GNU make 3.81 or newer should work, except on
+ Windows where 4.0 or newer is recommended.
The build should scale, i.e. more processors should
@@ -358,8 +359,8 @@
For all systems:
- Be sure the GNU make utility is version 3.81 or newer,
- e.g. run "make -version"
+ Be sure the GNU make utility is version 3.81 (4.0 on
+ windows) or newer, e.g. run "make -version"
Install a
@@ -1726,10 +1727,10 @@
A few notes about using GNU make:
- You need GNU make version 3.81 or newer.
- If the GNU make utility on your systems is not
- 3.81 or newer,
- see "Building GNU make".
+ You need GNU make version 3.81 or newer. On Windows 4.0 or
+ newer is recommended.
+ If the GNU make utility on your systems is not of a suitable
+ version see "Building GNU make".
Place the location of the GNU make binary in the
diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4
index 02a096ed8c1..5eb945ef53b 100644
--- a/common/autoconf/basics.m4
+++ b/common/autoconf/basics.m4
@@ -658,8 +658,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR],
fi
OUTPUT_ROOT="$SRC_ROOT/build/${CONF_NAME}"
$MKDIR -p "$OUTPUT_ROOT"
- CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
- $MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
if test ! -d "$OUTPUT_ROOT"; then
AC_MSG_ERROR([Could not create build directory $OUTPUT_ROOT])
fi
@@ -702,6 +700,9 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR],
BASIC_FIXUP_PATH(OUTPUT_ROOT)
+ CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
+ $MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
+
AC_SUBST(SPEC, $OUTPUT_ROOT/spec.gmk)
AC_SUBST(CONF_NAME, $CONF_NAME)
AC_SUBST(OUTPUT_ROOT, $OUTPUT_ROOT)
@@ -730,6 +731,16 @@ AC_DEFUN([BASIC_CHECK_MAKE_VERSION],
[
MAKE_CANDIDATE="$1"
DESCRIPTION="$2"
+
+ # On Cygwin, we require a newer version of make than on other platforms
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ MAKE_VERSION_EXPR="-e 4\."
+ MAKE_REQUIRED_VERSION="4.0"
+ else
+ MAKE_VERSION_EXPR="-e 3\.8[[12]] -e 4\."
+ MAKE_REQUIRED_VERSION="3.81"
+ fi
+
if test "x$MAKE_CANDIDATE" != x; then
AC_MSG_NOTICE([Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION])
MAKE_VERSION_STRING=`$MAKE_CANDIDATE --version | $HEAD -n 1`
@@ -737,9 +748,9 @@ AC_DEFUN([BASIC_CHECK_MAKE_VERSION],
if test "x$IS_GNU_MAKE" = x; then
AC_MSG_NOTICE([Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring.])
else
- IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP -e '3\.8[[12]]' -e '4\.'`
+ IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP $MAKE_VERSION_EXPR`
if test "x$IS_MODERN_MAKE" = x; then
- AC_MSG_NOTICE([Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring.])
+ AC_MSG_NOTICE([Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring.])
else
if test "x$OPENJDK_BUILD_OS" = "xwindows"; then
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
@@ -803,7 +814,7 @@ AC_DEFUN([BASIC_CHECK_GNU_MAKE],
fi
BASIC_CHECK_MAKE_VERSION("$MAKE", [user supplied MAKE=$MAKE])
if test "x$FOUND_MAKE" = x; then
- AC_MSG_ERROR([The specified make (by MAKE=$MAKE) is not GNU make 3.81 or newer.])
+ AC_MSG_ERROR([The specified make (by MAKE=$MAKE) is not GNU make $MAKE_REQUIRED_VERSION or newer.])
fi
else
# Try our hardest to locate a correct version of GNU make
@@ -831,13 +842,13 @@ AC_DEFUN([BASIC_CHECK_GNU_MAKE],
fi
if test "x$FOUND_MAKE" = x; then
- AC_MSG_ERROR([Cannot find GNU make 3.81 or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure.])
+ AC_MSG_ERROR([Cannot find GNU make $MAKE_REQUIRED_VERSION or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure.])
fi
fi
MAKE=$FOUND_MAKE
AC_SUBST(MAKE)
- AC_MSG_NOTICE([Using GNU make 3.81 (or later) at $FOUND_MAKE (version: $MAKE_VERSION_STRING)])
+ AC_MSG_NOTICE([Using GNU make at $FOUND_MAKE (version: $MAKE_VERSION_STRING)])
BASIC_CHECK_MAKE_OUTPUT_SYNC
])
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index a7fc898624c..5d5e9fbee85 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -745,8 +745,6 @@ JT_HOME
JTREGEXE
USING_BROKEN_SUSE_LD
PACKAGE_PATH
-LDEXECXX
-LDEXE
USE_CLANG
HOTSPOT_LD
HOTSPOT_CXX
@@ -4365,7 +4363,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1428676283
+DATE_WHEN_GENERATED=1429271657
###############################################################################
#
@@ -15266,8 +15264,6 @@ $as_echo "in build directory with custom name" >&6; }
fi
OUTPUT_ROOT="$SRC_ROOT/build/${CONF_NAME}"
$MKDIR -p "$OUTPUT_ROOT"
- CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
- $MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
if test ! -d "$OUTPUT_ROOT"; then
as_fn_error $? "Could not create build directory $OUTPUT_ROOT" "$LINENO" 5
fi
@@ -15445,6 +15441,9 @@ $as_echo "$as_me: The path of OUTPUT_ROOT, which resolves as \"$path\", is inval
fi
+ CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
+ $MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
+
SPEC=$OUTPUT_ROOT/spec.gmk
CONF_NAME=$CONF_NAME
@@ -15530,6 +15529,16 @@ done
MAKE_CANDIDATE=""$MAKE""
DESCRIPTION="user supplied MAKE=$MAKE"
+
+ # On Cygwin, we require a newer version of make than on other platforms
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ MAKE_VERSION_EXPR="-e 4\."
+ MAKE_REQUIRED_VERSION="4.0"
+ else
+ MAKE_VERSION_EXPR="-e 3\.8[12] -e 4\."
+ MAKE_REQUIRED_VERSION="3.81"
+ fi
+
if test "x$MAKE_CANDIDATE" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&5
$as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&6;}
@@ -15539,10 +15548,10 @@ $as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRI
{ $as_echo "$as_me:${as_lineno-$LINENO}: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&5
$as_echo "$as_me: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&6;}
else
- IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP -e '3\.8[12]' -e '4\.'`
+ IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP $MAKE_VERSION_EXPR`
if test "x$IS_MODERN_MAKE" = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
-$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
+$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
else
if test "x$OPENJDK_BUILD_OS" = "xwindows"; then
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
@@ -15855,7 +15864,7 @@ $as_echo "$as_me: Rewriting FOUND_MAKE to \"$new_complete\"" >&6;}
fi
if test "x$FOUND_MAKE" = x; then
- as_fn_error $? "The specified make (by MAKE=$MAKE) is not GNU make 3.81 or newer." "$LINENO" 5
+ as_fn_error $? "The specified make (by MAKE=$MAKE) is not GNU make $MAKE_REQUIRED_VERSION or newer." "$LINENO" 5
fi
else
# Try our hardest to locate a correct version of GNU make
@@ -15907,6 +15916,16 @@ done
MAKE_CANDIDATE=""$CHECK_GMAKE""
DESCRIPTION="gmake in PATH"
+
+ # On Cygwin, we require a newer version of make than on other platforms
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ MAKE_VERSION_EXPR="-e 4\."
+ MAKE_REQUIRED_VERSION="4.0"
+ else
+ MAKE_VERSION_EXPR="-e 3\.8[12] -e 4\."
+ MAKE_REQUIRED_VERSION="3.81"
+ fi
+
if test "x$MAKE_CANDIDATE" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&5
$as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&6;}
@@ -15916,10 +15935,10 @@ $as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRI
{ $as_echo "$as_me:${as_lineno-$LINENO}: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&5
$as_echo "$as_me: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&6;}
else
- IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP -e '3\.8[12]' -e '4\.'`
+ IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP $MAKE_VERSION_EXPR`
if test "x$IS_MODERN_MAKE" = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
-$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
+$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
else
if test "x$OPENJDK_BUILD_OS" = "xwindows"; then
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
@@ -16281,6 +16300,16 @@ done
MAKE_CANDIDATE=""$CHECK_MAKE""
DESCRIPTION="make in PATH"
+
+ # On Cygwin, we require a newer version of make than on other platforms
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ MAKE_VERSION_EXPR="-e 4\."
+ MAKE_REQUIRED_VERSION="4.0"
+ else
+ MAKE_VERSION_EXPR="-e 3\.8[12] -e 4\."
+ MAKE_REQUIRED_VERSION="3.81"
+ fi
+
if test "x$MAKE_CANDIDATE" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&5
$as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&6;}
@@ -16290,10 +16319,10 @@ $as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRI
{ $as_echo "$as_me:${as_lineno-$LINENO}: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&5
$as_echo "$as_me: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&6;}
else
- IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP -e '3\.8[12]' -e '4\.'`
+ IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP $MAKE_VERSION_EXPR`
if test "x$IS_MODERN_MAKE" = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
-$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
+$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
else
if test "x$OPENJDK_BUILD_OS" = "xwindows"; then
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
@@ -16660,6 +16689,16 @@ done
MAKE_CANDIDATE=""$CHECK_TOOLSDIR_GMAKE""
DESCRIPTION="gmake in tools-dir"
+
+ # On Cygwin, we require a newer version of make than on other platforms
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ MAKE_VERSION_EXPR="-e 4\."
+ MAKE_REQUIRED_VERSION="4.0"
+ else
+ MAKE_VERSION_EXPR="-e 3\.8[12] -e 4\."
+ MAKE_REQUIRED_VERSION="3.81"
+ fi
+
if test "x$MAKE_CANDIDATE" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&5
$as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&6;}
@@ -16669,10 +16708,10 @@ $as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRI
{ $as_echo "$as_me:${as_lineno-$LINENO}: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&5
$as_echo "$as_me: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&6;}
else
- IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP -e '3\.8[12]' -e '4\.'`
+ IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP $MAKE_VERSION_EXPR`
if test "x$IS_MODERN_MAKE" = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
-$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
+$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
else
if test "x$OPENJDK_BUILD_OS" = "xwindows"; then
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
@@ -17033,6 +17072,16 @@ done
MAKE_CANDIDATE=""$CHECK_TOOLSDIR_MAKE""
DESCRIPTION="make in tools-dir"
+
+ # On Cygwin, we require a newer version of make than on other platforms
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ MAKE_VERSION_EXPR="-e 4\."
+ MAKE_REQUIRED_VERSION="4.0"
+ else
+ MAKE_VERSION_EXPR="-e 3\.8[12] -e 4\."
+ MAKE_REQUIRED_VERSION="3.81"
+ fi
+
if test "x$MAKE_CANDIDATE" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&5
$as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRIPTION" >&6;}
@@ -17042,10 +17091,10 @@ $as_echo "$as_me: Testing potential make at $MAKE_CANDIDATE, found using $DESCRI
{ $as_echo "$as_me:${as_lineno-$LINENO}: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&5
$as_echo "$as_me: Found potential make at $MAKE_CANDIDATE, however, this is not GNU Make. Ignoring." >&6;}
else
- IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP -e '3\.8[12]' -e '4\.'`
+ IS_MODERN_MAKE=`$ECHO $MAKE_VERSION_STRING | $GREP $MAKE_VERSION_EXPR`
if test "x$IS_MODERN_MAKE" = x; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
-$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version 3.81 or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&5
+$as_echo "$as_me: Found GNU make at $MAKE_CANDIDATE, however this is not version $MAKE_REQUIRED_VERSION or later. (it is: $MAKE_VERSION_STRING). Ignoring." >&6;}
else
if test "x$OPENJDK_BUILD_OS" = "xwindows"; then
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
@@ -17363,14 +17412,14 @@ $as_echo "$as_me: Rewriting FOUND_MAKE to \"$new_complete\"" >&6;}
fi
if test "x$FOUND_MAKE" = x; then
- as_fn_error $? "Cannot find GNU make 3.81 or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure." "$LINENO" 5
+ as_fn_error $? "Cannot find GNU make $MAKE_REQUIRED_VERSION or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure." "$LINENO" 5
fi
fi
MAKE=$FOUND_MAKE
- { $as_echo "$as_me:${as_lineno-$LINENO}: Using GNU make 3.81 (or later) at $FOUND_MAKE (version: $MAKE_VERSION_STRING)" >&5
-$as_echo "$as_me: Using GNU make 3.81 (or later) at $FOUND_MAKE (version: $MAKE_VERSION_STRING)" >&6;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Using GNU make at $FOUND_MAKE (version: $MAKE_VERSION_STRING)" >&5
+$as_echo "$as_me: Using GNU make at $FOUND_MAKE (version: $MAKE_VERSION_STRING)" >&6;}
# Check if make supports the output sync option and if so, setup using it.
@@ -40837,13 +40886,6 @@ $as_echo "$as_me: Rewriting BUILD_LD to \"$new_complete\"" >&6;}
fi
- # LDEXE is the linker to use, when creating executables. Not really used.
- # FIXME: These should just be removed!
- LDEXE="$LD"
- LDEXECXX="$LDCXX"
-
-
-
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 8ae516585e0..d9c172dc964 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -182,6 +182,7 @@ else
FULL_VERSION=$(RELEASE)-$(JDK_BUILD_NUMBER)
endif
JRE_RELEASE_VERSION:=$(FULL_VERSION)
+JDK_VERSION_FOR_MANIFEST := $(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION).$(if $(JDK_UPDATE_VERSION),$(JDK_UPDATE_VERSION),0).$(COOKED_BUILD_NUMBER)
# How to compile the code: release, fastdebug or slowdebug
DEBUG_LEVEL:=@DEBUG_LEVEL@
@@ -354,10 +355,6 @@ USING_BROKEN_SUSE_LD:=@USING_BROKEN_SUSE_LD@
LDFLAGS_JDKLIB:=@LDFLAGS_JDKLIB@
LDFLAGS_JDKLIB_SUFFIX:=@LDFLAGS_JDKLIB_SUFFIX@
-# On some platforms the linker cannot be used to create executables, thus
-# the need for a separate LDEXE command.
-LDEXE:=@FIXPATH@ @LDEXE@
-
# LDFLAGS used to link the jdk native launchers (C-code)
LDFLAGS_JDKEXE:=@LDFLAGS_JDKEXE@
LDFLAGS_JDKEXE_SUFFIX:=@LDFLAGS_JDKEXE_SUFFIX@
@@ -370,9 +367,6 @@ LDCXX:=@FIXPATH@ @LDCXX@
# The flags for linking libstdc++ linker.
LIBCXX:=@LIBCXX@
-# Sometimes a different linker is needed for c++ executables
-LDEXECXX:=@FIXPATH@ @LDEXECXX@
-
# Compiler and linker flags used when building native tests
CFLAGS_TESTLIB:=@CFLAGS_TESTLIB@
CXXFLAGS_TESTLIB:=@CXXFLAGS_TESTLIB@
diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4
index 7737ef8adf2..ed978d6a8fb 100644
--- a/common/autoconf/toolchain.m4
+++ b/common/autoconf/toolchain.m4
@@ -662,13 +662,6 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_LEGACY],
USE_CLANG=true
fi
AC_SUBST(USE_CLANG)
-
- # LDEXE is the linker to use, when creating executables. Not really used.
- # FIXME: These should just be removed!
- LDEXE="$LD"
- LDEXECXX="$LDCXX"
- AC_SUBST(LDEXE)
- AC_SUBST(LDEXECXX)
])
# Do some additional checks on the detected tools.
diff --git a/common/bin/unshuffle_list.txt b/common/bin/unshuffle_list.txt
index a27c192e7fc..0553eb826fc 100644
--- a/common/bin/unshuffle_list.txt
+++ b/common/bin/unshuffle_list.txt
@@ -1294,6 +1294,9 @@ jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.h : jdk/src/win
jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.c : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.c
jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.h : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.h
jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html : jdk/src/macosx/classes/com/apple/concurrent/package.html
+jdk/src/jdk.deploy.osx/macosx/classes/apple/applescript : jdk/src/macosx/classes/apple/applescript
+jdk/src/jdk.deploy.osx/macosx/classes/apple/security : jdk/src/macosx/classes/apple/security
+jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent : jdk/src/macosx/classes/com/apple/concurrent
jdk/src/jdk.deploy.osx/macosx/native/libapplescriptengine : jdk/src/macosx/native/apple/applescript
jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m
jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m : jdk/src/macosx/native/com/apple/concurrent/Dispatch.m
diff --git a/corba/.hgtags b/corba/.hgtags
index 263095cc353..a57f792d42f 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -302,3 +302,4 @@ ef4afd6832b00b8687832c2a36c90e43750ebe40 jdk9-b56
d8ebf1a5b18ccbc849f5bf0f80aa3d78583eee68 jdk9-b57
86dd5de1f5cb09073019bd629e22cfcd012d8b4b jdk9-b58
cda6ae062f85fac5555f4e1318885b0ecd998bd1 jdk9-b59
+caa330b275f39282793466529f6864766b31d9fd jdk9-b60
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java
index 886d1575896..c6eb5f7051a 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/corba/RequestImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,7 @@ import com.sun.corba.se.spi.presentation.rmi.StubAdapter;
import com.sun.corba.se.spi.logging.CORBALogDomains;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
import com.sun.corba.se.impl.corba.AsynchInvoke;
+import com.sun.corba.se.impl.transport.ManagedLocalsThread;
public class RequestImpl
extends Request
@@ -255,7 +256,7 @@ public class RequestImpl
public synchronized void send_deferred()
{
AsynchInvoke invokeObject = new AsynchInvoke(_orb, this, false);
- new Thread(invokeObject).start();
+ new ManagedLocalsThread(invokeObject).start();
}
public synchronized boolean poll_response()
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java
index e14b25ebb1b..8d4e68145a6 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/IIOPInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1768,43 +1768,59 @@ public class IIOPInputStream
switch (field.getTypeCode()) {
case 'B':
byte byteValue = orbStream.read_octet();
- bridge.putByte( o, field.getFieldID(), byteValue ) ;
- //reflective code: field.getField().setByte( o, byteValue ) ;
+ if (field.getField() != null) {
+ bridge.putByte( o, field.getFieldID(), byteValue ) ;
+ //reflective code: field.getField().setByte( o, byteValue ) ;
+ }
break;
case 'Z':
boolean booleanValue = orbStream.read_boolean();
- bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
- //reflective code: field.getField().setBoolean( o, booleanValue ) ;
+ if (field.getField() != null) {
+ bridge.putBoolean( o, field.getFieldID(), booleanValue ) ;
+ //reflective code: field.getField().setBoolean( o, booleanValue ) ;
+ }
break;
case 'C':
char charValue = orbStream.read_wchar();
- bridge.putChar( o, field.getFieldID(), charValue ) ;
- //reflective code: field.getField().setChar( o, charValue ) ;
+ if (field.getField() != null) {
+ bridge.putChar( o, field.getFieldID(), charValue ) ;
+ //reflective code: field.getField().setChar( o, charValue ) ;
+ }
break;
case 'S':
short shortValue = orbStream.read_short();
- bridge.putShort( o, field.getFieldID(), shortValue ) ;
- //reflective code: field.getField().setShort( o, shortValue ) ;
+ if (field.getField() != null) {
+ bridge.putShort( o, field.getFieldID(), shortValue ) ;
+ //reflective code: field.getField().setShort( o, shortValue ) ;
+ }
break;
case 'I':
int intValue = orbStream.read_long();
- bridge.putInt( o, field.getFieldID(), intValue ) ;
- //reflective code: field.getField().setInt( o, intValue ) ;
+ if (field.getField() != null) {
+ bridge.putInt( o, field.getFieldID(), intValue ) ;
+ //reflective code: field.getField().setInt( o, intValue ) ;
+ }
break;
case 'J':
long longValue = orbStream.read_longlong();
- bridge.putLong( o, field.getFieldID(), longValue ) ;
- //reflective code: field.getField().setLong( o, longValue ) ;
+ if (field.getField() != null) {
+ bridge.putLong( o, field.getFieldID(), longValue ) ;
+ //reflective code: field.getField().setLong( o, longValue ) ;
+ }
break;
case 'F' :
float floatValue = orbStream.read_float();
- bridge.putFloat( o, field.getFieldID(), floatValue ) ;
- //reflective code: field.getField().setFloat( o, floatValue ) ;
+ if (field.getField() != null) {
+ bridge.putFloat( o, field.getFieldID(), floatValue ) ;
+ //reflective code: field.getField().setFloat( o, floatValue ) ;
+ }
break;
case 'D' :
double doubleValue = orbStream.read_double();
- bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
- //reflective code: field.getField().setDouble( o, doubleValue ) ;
+ if (field.getField() != null) {
+ bridge.putDouble( o, field.getFieldID(), doubleValue ) ;
+ //reflective code: field.getField().setDouble( o, doubleValue ) ;
+ }
break;
default:
// XXX I18N, logging needed.
@@ -2217,9 +2233,6 @@ public class IIOPInputStream
if (o != null) {
for (int i = 0; i < primFields; ++i) {
- if (fields[i].getField() == null)
- continue;
-
inputPrimitiveField(o, cl, fields[i]);
}
}
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java
index 6908cad9a83..79ef01e8765 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
package com.sun.corba.se.impl.io;
import java.io.IOException;
+import java.io.NotActiveException;
import java.io.OutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectOutput;
@@ -154,7 +155,9 @@ public abstract class OutputStreamHook extends ObjectOutputStream
public ObjectOutputStream.PutField putFields()
throws IOException {
- putFields = new HookPutFields();
+ if (putFields == null) {
+ putFields = new HookPutFields();
+ }
return putFields;
}
@@ -175,8 +178,11 @@ public abstract class OutputStreamHook extends ObjectOutputStream
throws IOException {
writeObjectState.defaultWriteObject(this);
-
- putFields.write(this);
+ if (putFields != null) {
+ putFields.write(this);
+ } else {
+ throw new NotActiveException("no current PutField object");
+ }
}
abstract org.omg.CORBA_2_3.portable.OutputStream getOrbStream();
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java
index 7829d52a495..473cf6487ca 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/javax/rmi/CORBA/Util.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -112,6 +112,8 @@ import com.sun.corba.se.impl.util.JDKBridge;
import com.sun.corba.se.impl.logging.UtilSystemException;
import com.sun.corba.se.spi.logging.CORBALogDomains;
import sun.corba.SharedSecrets;
+import com.sun.corba.se.impl.transport.ManagedLocalsThread;
+
/**
* Provides utility methods that can be used by stubs and ties to
@@ -750,7 +752,7 @@ public class Util implements javax.rmi.CORBA.UtilDelegate
}
}
-class KeepAlive extends Thread
+class KeepAlive extends ManagedLocalsThread
{
boolean quit = false;
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java
index 0698aafef43..d10f4e3eccd 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -103,6 +103,7 @@ import com.sun.corba.se.impl.orbutil.concurrent.Sync ;
import com.sun.corba.se.impl.orbutil.concurrent.SyncUtil ;
import com.sun.corba.se.impl.orbutil.concurrent.ReentrantMutex ;
import com.sun.corba.se.impl.orbutil.concurrent.CondVar ;
+import com.sun.corba.se.impl.transport.ManagedLocalsThread;
/**
* POAImpl is the implementation of the Portable Object Adapter. It
@@ -516,7 +517,7 @@ public class POAImpl extends ObjectAdapterBase implements POA
// Converted from anonymous class to local class
// so that we can call performDestroy() directly.
- static class DestroyThread extends Thread {
+ static class DestroyThread extends ManagedLocalsThread {
private boolean wait ;
private boolean etherealize ;
private boolean debug ;
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java
index a044c14ea70..41100a4b3bd 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,7 @@ import com.sun.corba.se.spi.protocol.PIHandler ;
import com.sun.corba.se.impl.logging.POASystemException ;
import com.sun.corba.se.impl.orbutil.ORBUtility ;
+import com.sun.corba.se.impl.transport.ManagedLocalsThread;
/** POAManagerImpl is the implementation of the POAManager interface.
* Its public methods are activate(), hold_requests(), discard_requests()
@@ -357,7 +358,7 @@ public class POAManagerImpl extends org.omg.CORBA.LocalObject implements
if (wait_for_completion)
deactivator.run() ;
else {
- Thread thr = new Thread(deactivator) ;
+ Thread thr = new ManagedLocalsThread(deactivator) ;
thr.start() ;
}
} finally {
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java
index 6c40f741845..21a5c340612 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/oa/poa/POAPolicyMediatorImpl_R_USM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,6 @@
package com.sun.corba.se.impl.oa.poa ;
import java.util.Set ;
-
import org.omg.CORBA.SystemException ;
import org.omg.PortableServer.ServantActivator ;
@@ -50,6 +49,7 @@ import com.sun.corba.se.impl.javax.rmi.CORBA.Util ;
import com.sun.corba.se.spi.oa.OAInvocationInfo ;
import com.sun.corba.se.spi.oa.NullServant ;
+import com.sun.corba.se.impl.transport.ManagedLocalsThread;
/** Implementation of POARequesHandler that provides policy specific
* operations on the POA.
@@ -303,13 +303,14 @@ public class POAPolicyMediatorImpl_R_USM extends POAPolicyMediatorBase_R {
throw new WrongPolicy();
}
- class Etherealizer extends Thread {
+ class Etherealizer extends ManagedLocalsThread {
private POAPolicyMediatorImpl_R_USM mediator ;
private ActiveObjectMap.Key key ;
private AOMEntry entry ;
private Servant servant ;
private boolean debug ;
+
public Etherealizer( POAPolicyMediatorImpl_R_USM mediator,
ActiveObjectMap.Key key, AOMEntry entry, Servant servant,
boolean debug )
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java
index 8bda9dcbf0b..c619b8a9268 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orb/ORBImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -165,6 +165,7 @@ import com.sun.corba.se.impl.util.Utility;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
import com.sun.corba.se.impl.copyobject.CopierManagerImpl;
import com.sun.corba.se.impl.presentation.rmi.PresentationManagerImpl;
+import com.sun.corba.se.impl.transport.ManagedLocalsThread;
/**
* The JavaIDL ORB implementation.
@@ -691,7 +692,7 @@ public class ORBImpl extends com.sun.corba.se.spi.orb.ORB
for (int i = 0; i < req.length; i++) {
AsynchInvoke invokeObject = new AsynchInvoke( this,
(com.sun.corba.se.impl.corba.RequestImpl)req[i], true);
- new Thread(invokeObject).start();
+ new ManagedLocalsThread(invokeObject).start();
}
}
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java
index f98880bf68d..12a8127d061 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/threadpool/ThreadPoolImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,6 +54,7 @@ import com.sun.corba.se.spi.monitoring.LongMonitoredAttributeBase;
import com.sun.corba.se.impl.logging.ORBUtilSystemException;
import com.sun.corba.se.impl.orbutil.ORBConstants;
import com.sun.corba.se.spi.logging.CORBALogDomains;
+import com.sun.corba.se.impl.transport.ManagedLocalsThread;
public class ThreadPoolImpl implements ThreadPool
{
@@ -459,7 +460,7 @@ public class ThreadPoolImpl implements ThreadPool
}
- private class WorkerThread extends Thread implements Closeable
+ private class WorkerThread extends ManagedLocalsThread implements Closeable
{
private Work currentWork;
private int threadId = 0; // unique id for the thread
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/ManagedLocalsThread.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/ManagedLocalsThread.java
new file mode 100644
index 00000000000..b888de30228
--- /dev/null
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/ManagedLocalsThread.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.corba.se.impl.transport;
+
+import sun.misc.Unsafe;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * A thread that has it's thread locals, and inheritable thread
+ * locals erased on construction.
+ */
+public class ManagedLocalsThread extends Thread {
+ private static final Unsafe UNSAFE;
+ private static final long THREAD_LOCALS;
+ private static final long INHERITABLE_THREAD_LOCALS;
+
+ public ManagedLocalsThread () {
+ super();
+ }
+
+ public ManagedLocalsThread(String name) {
+ super(name);
+ eraseThreadLocals();
+ }
+ public ManagedLocalsThread(Runnable target) {
+ super(target);
+ eraseThreadLocals();
+ }
+
+ public ManagedLocalsThread(Runnable target, String name) {
+ super(target, name);
+ eraseThreadLocals();
+ }
+
+ public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) {
+ super(group, target, name);
+ eraseThreadLocals();
+ }
+
+ public ManagedLocalsThread(ThreadGroup group, String name) {
+ super(group, name);
+ eraseThreadLocals();
+ }
+
+ /**
+ * Drops all thread locals (and inherited thread locals).
+ */
+ public final void eraseThreadLocals() {
+ UNSAFE.putObject(this, THREAD_LOCALS, null);
+ UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
+ }
+
+ private static Unsafe getUnsafe() {
+ PrivilegedAction pa = () -> {
+ Class> unsafeClass = sun.misc.Unsafe.class;
+ try {
+ Field f = unsafeClass.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ return (Unsafe) f.get(null);
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ };
+ return AccessController.doPrivileged(pa);
+ }
+
+ private static long getThreadFieldOffset(String fieldName) {
+ PrivilegedAction pa = () -> {
+ Class> t = Thread.class;
+ long fieldOffset;
+ try {
+ fieldOffset = UNSAFE.objectFieldOffset(t
+ .getDeclaredField("inheritableThreadLocals"));
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ return fieldOffset;
+ };
+ return AccessController.doPrivileged(pa);
+ }
+
+ static {
+ UNSAFE = getUnsafe();
+ try {
+ THREAD_LOCALS = getThreadFieldOffset("threadLocals");
+ INHERITABLE_THREAD_LOCALS = getThreadFieldOffset("inheritableThreadLocals");
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+}
diff --git a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java
index 054071b7d8b..4acac0a176e 100644
--- a/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java
+++ b/corba/src/java.corba/share/classes/com/sun/corba/se/impl/transport/SelectorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,7 @@ import com.sun.corba.se.impl.orbutil.ORBUtility;
*/
class SelectorImpl
extends
- Thread
+ ManagedLocalsThread
implements
com.sun.corba.se.pept.transport.Selector
{
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index efc54cfd589..b651482f5ce 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -462,3 +462,4 @@ fd2d5ec7e7b16c7bf4043a7fe7cfd8af96b819e2 jdk9-b56
56a85ffe743d3f9d70ba25d6ce82ddd2ad1bf33c jdk9-b57
ee878f3d6732856f7725c590312bfbe2ffa52cc7 jdk9-b58
96bcaec07cb165782bae1b9a1f28450b37a10e3a jdk9-b59
+9c916db4bf3bc164a47b5a9cefe5ffd71e111f6a jdk9-b60
diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
index 4087a187512..871cc33d279 100644
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp
@@ -39,6 +39,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
protected:
protected:
+ using MacroAssembler::call_VM_leaf_base;
+
// Interpreter specific version of call_VM_base
virtual void call_VM_leaf_base(address entry_point,
int number_of_arguments);
diff --git a/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp
index fdcc502ca8b..1e22e935278 100644
--- a/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp
@@ -60,7 +60,10 @@ class RegisterImpl: public AbstractRegisterImpl {
bool has_byte_register() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_byte_registers; }
const char* name() const;
int encoding_nocheck() const { return (intptr_t)this; }
- unsigned long bit(bool yes = true) const { return yes << encoding(); }
+
+ // Return the bit which represents this register. This is intended
+ // to be ORed into a bitmask: for usage see class RegSet below.
+ unsigned long bit(bool should_set = true) const { return should_set ? 1 << encoding() : 0; }
};
// The integer registers of the aarch64 architecture
diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp
index 5cc8a6844ae..fdd2170faaa 100644
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp
@@ -731,10 +731,12 @@ class FindMethodsByErasedSig : public HierarchyVisitor {
Method* m = iklass->find_method(_method_name, _method_signature);
// private interface methods are not candidates for default methods
// invokespecial to private interface methods doesn't use default method logic
+ // private class methods are not candidates for default methods,
+ // private methods do not override default methods, so need to perform
+ // default method inheritance without including private methods
// The overpasses are your supertypes' errors, we do not include them
// future: take access controls into account for superclass methods
- if (m != NULL && !m->is_static() && !m->is_overpass() &&
- (!iklass->is_interface() || m->is_public())) {
+ if (m != NULL && !m->is_static() && !m->is_overpass() && !m->is_private()) {
if (_family == NULL) {
_family = new StatefulMethodFamily();
}
@@ -745,6 +747,9 @@ class FindMethodsByErasedSig : public HierarchyVisitor {
} else {
// This is the rule that methods in classes "win" (bad word) over
// methods in interfaces. This works because of single inheritance
+ // private methods in classes do not "win", they will be found
+ // first on searching, but overriding for invokevirtual needs
+ // to find default method candidates for the same signature
_family->set_target_if_empty(m);
}
}
diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp
index 8943a5e675f..6917b2e5f9c 100644
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp
@@ -250,7 +250,7 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references(
// Cleaner references to be temporary, and don't want to deal with
// possible incompatibilities arising from making it more visible.
phantom_count +=
- process_discovered_reflist(_discoveredCleanerRefs, NULL, false,
+ process_discovered_reflist(_discoveredCleanerRefs, NULL, true,
is_alive, keep_alive, complete_gc, task_executor);
}
diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp
index 5cfa70a73ae..3d9e0553429 100644
--- a/hotspot/src/share/vm/oops/klassVtable.cpp
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp
@@ -404,13 +404,15 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar
// get super_klass for method_holder for the found method
InstanceKlass* super_klass = super_method->method_holder();
- if (is_default
+ // private methods are also never overridden
+ if (!super_method->is_private() &&
+ (is_default
|| ((super_klass->is_override(super_method, target_loader, target_classname, THREAD))
|| ((klass->major_version() >= VTABLE_TRANSITIVE_OVERRIDE_VERSION)
&& ((super_klass = find_transitive_override(super_klass,
target_method, i, target_loader,
target_classname, THREAD))
- != (InstanceKlass*)NULL))))
+ != (InstanceKlass*)NULL)))))
{
// Package private methods always need a new entry to root their own
// overriding. They may also override other methods.
@@ -692,9 +694,15 @@ bool klassVtable::is_miranda_entry_at(int i) {
// check if a method is a miranda method, given a class's methods table,
// its default_method table and its super
// Miranda methods are calculated twice:
-// first: before vtable size calculation: including abstract and default
+// first: before vtable size calculation: including abstract and superinterface default
+// We include potential default methods to give them space in the vtable.
+// During the first run, the default_methods list is empty
// This is seen by default method creation
-// Second: recalculated during vtable initialization: only abstract
+// Second: recalculated during vtable initialization: only include abstract methods.
+// During the second run, default_methods is set up, so concrete methods from
+// superinterfaces with matching names/signatures to default_methods are already
+// in the default_methods list and do not need to be appended to the vtable
+// as mirandas
// This is seen by link resolution and selection.
// "miranda" means not static, not defined by this class.
// private methods in interfaces do not belong in the miranda list.
@@ -709,8 +717,9 @@ bool klassVtable::is_miranda(Method* m, Array* class_methods,
}
Symbol* name = m->name();
Symbol* signature = m->signature();
+ Method* mo;
- if (InstanceKlass::find_instance_method(class_methods, name, signature) == NULL) {
+ if ((mo = InstanceKlass::find_instance_method(class_methods, name, signature)) == NULL) {
// did not find it in the method table of the current class
if ((default_methods == NULL) ||
InstanceKlass::find_method(default_methods, name, signature) == NULL) {
@@ -719,7 +728,7 @@ bool klassVtable::is_miranda(Method* m, Array* class_methods,
return true;
}
- Method* mo = InstanceKlass::cast(super)->lookup_method(name, signature);
+ mo = InstanceKlass::cast(super)->lookup_method(name, signature);
while (mo != NULL && mo->access_flags().is_static()
&& mo->method_holder() != NULL
&& mo->method_holder()->super() != NULL)
@@ -731,6 +740,18 @@ bool klassVtable::is_miranda(Method* m, Array* class_methods,
return true;
}
}
+ } else {
+ // if the local class has a private method, the miranda will not
+ // override it, so a vtable slot is needed
+ if (mo->access_flags().is_private()) {
+
+ // Second round, weed out any superinterface methods that turned
+ // into default methods, i.e. were concrete not abstract in the end
+ if ((default_methods == NULL) ||
+ InstanceKlass::find_method(default_methods, name, signature) == NULL) {
+ return true;
+ }
+ }
}
return false;
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 320f67e9262..e2ba1c81050 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -2320,7 +2320,7 @@ bool Arguments::check_vm_args_consistency() {
"G1ConcMarkStepDurationMillis");
status = status && verify_interval(G1ConcRSHotCardLimit, 0, max_jubyte,
"G1ConcRSHotCardLimit");
- status = status && verify_interval(G1ConcRSLogCacheSize, 0, 31,
+ status = status && verify_interval(G1ConcRSLogCacheSize, 0, 27,
"G1ConcRSLogCacheSize");
status = status && verify_interval(StringDeduplicationAgeThreshold, 1, markOopDesc::max_age,
"StringDeduplicationAgeThreshold");
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index a771efc9b01..8cdd16ae918 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -302,3 +302,4 @@ d5b5a010a16688f188f5a9247ed873f5100b530c jdk9-b53
2c417f7d7b0dc98e887474884aa39f974894f0c2 jdk9-b57
270fb9a2dcb5ff3ef95da6d529fa35187026af0a jdk9-b58
a1a9d943446911a4a0f74f0d082c32094af944ae jdk9-b59
+c12db18748dacfccd6581ead29228c2cb6e51b34 jdk9-b60
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/XalanConstants.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/XalanConstants.java
index fce53d8ed24..7d2a6a9a665 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/XalanConstants.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/XalanConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -150,6 +150,16 @@ public final class XalanConstants {
*/
public static final String SP_MAX_ELEMENT_DEPTH = "jdk.xml.maxElementDepth";
+ /**
+ * JDK TransformerFactory and Transformer attribute that specifies a class
+ * loader that will be used for extension functions class loading
+ * Value: a "null", the default value, means that the default EF class loading
+ * path will be used.
+ * Instance of ClassLoader: the specified instance of ClassLoader will be used
+ * for extension functions loading during translation process
+ */
+ public static final String JDK_EXTENSION_CLASSLOADER = "jdk.xml.transform.extensionClassLoader";
+
//legacy System Properties
public final static String ENTITY_EXPANSION_LIMIT = "entityExpansionLimit";
public static final String ELEMENT_ATTRIBUTE_LIMIT = "elementAttributeLimit" ;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java
index 56bebd88e2c..7b55225f78a 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/FunctionCall.java
@@ -104,6 +104,9 @@ class FunctionCall extends Expression {
protected final static String EXSLT_STRINGS =
"http://exslt.org/strings";
+ protected final static String XALAN_CLASSPACKAGE_NAMESPACE =
+ "xalan://";
+
// Namespace format constants
protected final static int NAMESPACE_FORMAT_JAVA = 0;
protected final static int NAMESPACE_FORMAT_CLASS = 1;
@@ -900,8 +903,22 @@ class FunctionCall extends Expression {
if (_className != null && _className.length() > 0) {
final int nArgs = _arguments.size();
try {
- if (_clazz == null) {
- _clazz = ObjectFactory.findProviderClass(_className, true);
+ if (_clazz == null) {
+ final boolean isSecureProcessing = getXSLTC().isSecureProcessing();
+ final boolean isExtensionFunctionEnabled = getXSLTC()
+ .getFeature(FeatureManager.Feature.ORACLE_ENABLE_EXTENSION_FUNCTION);
+
+ //Check if FSP and SM - only then process with loading
+ if (namespace != null && isSecureProcessing
+ && isExtensionFunctionEnabled
+ && (namespace.equals(JAVA_EXT_XALAN)
+ || namespace.equals(JAVA_EXT_XSLTC)
+ || namespace.equals(JAVA_EXT_XALAN_OLD)
+ || namespace.startsWith(XALAN_CLASSPACKAGE_NAMESPACE))) {
+ _clazz = getXSLTC().loadExternalFunction(_className);
+ } else {
+ _clazz = ObjectFactory.findProviderClass(_className, true);
+ }
if (_clazz == null) {
final ErrorMsg msg =
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
index b6f81f7ba97..c5522aa5c5a 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/XSLTC.java
@@ -23,24 +23,6 @@
package com.sun.org.apache.xalan.internal.xsltc.compiler;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Vector;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import javax.xml.XMLConstants;
-
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xalan.internal.utils.FeatureManager;
@@ -50,7 +32,27 @@ import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
import com.sun.org.apache.xml.internal.dtm.DTM;
-
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import javax.xml.XMLConstants;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
@@ -152,12 +154,26 @@ public final class XSLTC {
private final FeatureManager _featureManager;
+ /**
+ * Extension function class loader variables
+ */
+
+ /* Class loader reference that will be used to external extension functions loading */
+ private ClassLoader _extensionClassLoader;
+
+ /**
+ * HashSet with the loaded classes
+ */
+ private final Map _externalExtensionFunctions;
+
/**
* XSLTC compiler constructor
*/
public XSLTC(boolean useServicesMechanism, FeatureManager featureManager) {
_parser = new Parser(this, useServicesMechanism);
_featureManager = featureManager;
+ _extensionClassLoader = null;
+ _externalExtensionFunctions = new HashMap<>();
}
/**
@@ -207,6 +223,8 @@ public final class XSLTC {
return _accessExternalDTD;
} else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
return _xmlSecurityManager;
+ } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) {
+ return _extensionClassLoader;
}
return null;
}
@@ -222,6 +240,11 @@ public final class XSLTC {
_accessExternalDTD = (String)value;
} else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
_xmlSecurityManager = (XMLSecurityManager)value;
+ } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) {
+ _extensionClassLoader = (ClassLoader) value;
+ /* Clear the external extension functions HashMap if extension class
+ loader was changed */
+ _externalExtensionFunctions.clear();
}
}
@@ -256,6 +279,41 @@ public final class XSLTC {
_bcelClasses = new Vector();
}
+ private void setExternalExtensionFunctions(String name, Class clazz) {
+ if (_isSecureProcessing && clazz != null && !_externalExtensionFunctions.containsKey(name)) {
+ _externalExtensionFunctions.put(name, clazz);
+ }
+ }
+
+ /*
+ * Function loads an external external extension functions.
+ * The filtering of function types (external,internal) takes place in FunctionCall class
+ *
+ */
+ Class loadExternalFunction(String name) throws ClassNotFoundException {
+ Class loaded = null;
+ //Check if the function is not loaded already
+ if (_externalExtensionFunctions.containsKey(name)) {
+ loaded = _externalExtensionFunctions.get(name);
+ } else if (_extensionClassLoader != null) {
+ loaded = Class.forName(name, true, _extensionClassLoader);
+ setExternalExtensionFunctions(name, loaded);
+ }
+ if (loaded == null) {
+ throw new ClassNotFoundException(name);
+ }
+ //Return loaded class
+ return (Class) loaded;
+ }
+
+ /*
+ * Returns unmodifiable view of HashMap with loaded external extension
+ * functions - will be needed for the TransformerImpl
+ */
+ public Map getExternalExtensionFunctions() {
+ return Collections.unmodifiableMap(_externalExtensionFunctions);
+ }
+
/**
* Initializes the compiler to produce a new translet
*/
@@ -283,6 +341,7 @@ public final class XSLTC {
-1, // LEVEL_MULTIPLE
-1 // LEVEL_ANY
};
+ _externalExtensionFunctions.clear();
}
/**
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java
index 500c3fce26a..cf83580147f 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java
@@ -602,6 +602,9 @@ public class ErrorMessages extends ListResourceBundle {
{ErrorMsg.JAXP_INVALID_ATTR_ERR,
"TransformerFactory does not recognise attribute ''{0}''."},
+ {ErrorMsg.JAXP_INVALID_ATTR_VALUE_ERR,
+ "Incorrect value specified for ''{0}'' attribute."},
+
/*
* Note to translators: "setResult()" and "startDocument()" are Java
* method names that should not be translated.
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java
index 102f354593e..4192cf2d7e6 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java
@@ -117,6 +117,7 @@ public final class ErrorMsg {
public static final String JAXP_NO_SOURCE_ERR = "JAXP_NO_SOURCE_ERR";
public static final String JAXP_COMPILE_ERR = "JAXP_COMPILE_ERR";
public static final String JAXP_INVALID_ATTR_ERR = "JAXP_INVALID_ATTR_ERR";
+ public static final String JAXP_INVALID_ATTR_VALUE_ERR = "JAXP_INVALID_ATTR_VALUE_ERR";
public static final String JAXP_SET_RESULT_ERR = "JAXP_SET_RESULT_ERR";
public static final String JAXP_NO_TRANSLET_ERR = "JAXP_NO_TRANSLET_ERR";
public static final String JAXP_NO_HANDLER_ERR = "JAXP_NO_HANDLER_ERR";
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java
index e6d9cc3cf95..1c8911e8413 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TemplatesImpl.java
@@ -24,27 +24,26 @@
package com.sun.org.apache.xalan.internal.xsltc.trax;
import com.sun.org.apache.xalan.internal.XalanConstants;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.Properties;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-import javax.xml.XMLConstants;
-import javax.xml.transform.Templates;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.URIResolver;
-
+import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
+import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.Translet;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;
-import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
-import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Map;
+import java.util.Properties;
+import javax.xml.XMLConstants;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.URIResolver;
/**
* @author Morten Jorgensen
@@ -131,8 +130,30 @@ public final class TemplatesImpl implements Templates, Serializable {
private String _accessExternalStylesheet = XalanConstants.EXTERNAL_ACCESS_DEFAULT;
static final class TransletClassLoader extends ClassLoader {
+
+ private final Map _loadedExternalExtensionFunctions;
+
TransletClassLoader(ClassLoader parent) {
super(parent);
+ _loadedExternalExtensionFunctions = null;
+ }
+
+ TransletClassLoader(ClassLoader parent,Map mapEF) {
+ super(parent);
+ _loadedExternalExtensionFunctions = mapEF;
+ }
+
+ public Class> loadClass(String name) throws ClassNotFoundException {
+ Class> ret = null;
+ // The _loadedExternalExtensionFunctions will be empty when the
+ // SecurityManager is not set and the FSP is turned off
+ if (_loadedExternalExtensionFunctions != null) {
+ ret = _loadedExternalExtensionFunctions.get(name);
+ }
+ if (ret == null) {
+ ret = super.loadClass(name);
+ }
+ return ret;
}
/**
@@ -330,7 +351,7 @@ public final class TemplatesImpl implements Templates, Serializable {
TransletClassLoader loader = (TransletClassLoader)
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
- return new TransletClassLoader(ObjectFactory.findClassLoader());
+ return new TransletClassLoader(ObjectFactory.findClassLoader(),_tfactory.getExternalExtensionsMap());
}
});
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
index 46866fdb0ad..7466ec069c2 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/trax/TransformerFactoryImpl.java
@@ -27,12 +27,12 @@ import com.sun.org.apache.xalan.internal.XalanConstants;
import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase;
+import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase.State;
import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
import com.sun.org.apache.xalan.internal.utils.SecuritySupport;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager;
import com.sun.org.apache.xalan.internal.utils.XMLSecurityPropertyManager.Property;
-import com.sun.org.apache.xalan.internal.utils.FeaturePropertyBase.State;
import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
import com.sun.org.apache.xalan.internal.xsltc.compiler.SourceLoader;
import com.sun.org.apache.xalan.internal.xsltc.compiler.XSLTC;
@@ -50,6 +50,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.Map;
import java.util.Properties;
import java.util.Vector;
import java.util.zip.ZipEntry;
@@ -57,7 +58,6 @@ import java.util.zip.ZipFile;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-
import javax.xml.transform.ErrorListener;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
@@ -231,6 +231,13 @@ public class TransformerFactoryImpl
private final FeatureManager _featureManager;
+ private ClassLoader _extensionClassLoader = null;
+
+ // Unmodifiable view of external extension function from xslt compiler
+ // It will be populated by user-specified extension functions during the
+ // type checking
+ private Map _xsltcExtensionFunctions;
+
/**
* javax.xml.transform.sax.TransformerFactory implementation.
*/
@@ -261,6 +268,12 @@ public class TransformerFactoryImpl
//Parser's security manager
_xmlSecurityManager = new XMLSecurityManager(true);
+ //Unmodifiable hash map with loaded external extension functions
+ _xsltcExtensionFunctions = null;
+ }
+
+ public Map getExternalExtensionsMap() {
+ return _xsltcExtensionFunctions;
}
/**
@@ -324,6 +337,8 @@ public class TransformerFactoryImpl
return Boolean.FALSE;
} else if (name.equals(XalanConstants.SECURITY_MANAGER)) {
return _xmlSecurityManager;
+ } else if (name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) {
+ return _extensionClassLoader;
}
/** Check to see if the property is managed by the security manager **/
@@ -439,6 +454,16 @@ public class TransformerFactoryImpl
return;
}
}
+ else if ( name.equals(XalanConstants.JDK_EXTENSION_CLASSLOADER)) {
+ if (value instanceof ClassLoader) {
+ _extensionClassLoader = (ClassLoader) value;
+ return;
+ } else {
+ final ErrorMsg err
+ = new ErrorMsg(ErrorMsg.JAXP_INVALID_ATTR_VALUE_ERR, "Extension Functions ClassLoader");
+ throw new IllegalArgumentException(err.toString());
+ }
+ }
if (_xmlSecurityManager != null &&
_xmlSecurityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, value)) {
@@ -881,7 +906,6 @@ public class TransformerFactoryImpl
// Reset the per-session attributes to their default values
// after each newTemplates() call.
resetTransientAttributes();
-
return new TemplatesImpl(bytecodes, transletClassName, null, _indentNumber, this);
}
}
@@ -898,8 +922,10 @@ public class TransformerFactoryImpl
xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, _accessExternalStylesheet);
xsltc.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, _accessExternalDTD);
xsltc.setProperty(XalanConstants.SECURITY_MANAGER, _xmlSecurityManager);
+ xsltc.setProperty(XalanConstants.JDK_EXTENSION_CLASSLOADER, _extensionClassLoader);
xsltc.init();
-
+ if (!_isNotSecureProcessing)
+ _xsltcExtensionFunctions = xsltc.getExternalExtensionFunctions();
// Set a document loader (for xsl:include/import) if defined
if (_uriResolver != null) {
xsltc.setSourceLoader(this);
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDOMImplementationImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDOMImplementationImpl.java
index 39b6929379b..892eb560ca9 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDOMImplementationImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDOMImplementationImpl.java
@@ -108,32 +108,6 @@ public class CoreDOMImplementationImpl
boolean anyVersion = version == null || version.length() == 0;
- // check if Xalan implementation is around and if yes report true for supporting
- // XPath API
- // if a plus sign "+" is prepended to any feature name, implementations
- // are considered in which the specified feature may not be directly
- // castable DOMImplementation.getFeature(feature, version). Without a
- // plus, only features whose interfaces are directly castable are considered.
- if ((feature.equalsIgnoreCase("+XPath"))
- && (anyVersion || version.equals("3.0"))) {
- try {
- Class xpathClass = ObjectFactory.findProviderClass(
- "com.sun.org.apache.xpath.internal.domapi.XPathEvaluatorImpl", true);
-
- // Check if the DOM XPath implementation implements
- // the interface org.w3c.dom.XPathEvaluator
- Class interfaces[] = xpathClass.getInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- if (interfaces[i].getName().equals(
- "org.w3c.dom.xpath.XPathEvaluator")) {
- return true;
- }
- }
- } catch (Exception e) {
- return false;
- }
- return true;
- }
if (feature.startsWith("+")) {
feature = feature.substring(1);
}
@@ -281,25 +255,7 @@ public class CoreDOMImplementationImpl
*/
public Object getFeature(String feature, String version) {
if (singleton.hasFeature(feature, version)) {
- if ((feature.equalsIgnoreCase("+XPath"))) {
- try {
- Class xpathClass = ObjectFactory.findProviderClass(
- "com.sun.org.apache.xpath.internal.domapi.XPathEvaluatorImpl", true);
- // Check if the DOM XPath implementation implements
- // the interface org.w3c.dom.XPathEvaluator
- Class interfaces[] = xpathClass.getInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- if (interfaces[i].getName().equals(
- "org.w3c.dom.xpath.XPathEvaluator")) {
- return xpathClass.newInstance();
- }
- }
- } catch (Exception e) {
- return null;
- }
- } else {
- return singleton;
- }
+ return singleton;
}
return null;
}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java
index 2fb6f8b225d..e1c2131197a 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/CoreDocumentImpl.java
@@ -498,44 +498,6 @@ extends ParentNode implements Document {
* @since DOM Level 3
*/
public Object getFeature(String feature, String version) {
-
- boolean anyVersion = version == null || version.length() == 0;
-
- // if a plus sign "+" is prepended to any feature name, implementations
- // are considered in which the specified feature may not be directly
- // castable DOMImplementation.getFeature(feature, version). Without a
- // plus, only features whose interfaces are directly castable are
- // considered.
- if ((feature.equalsIgnoreCase("+XPath"))
- && (anyVersion || version.equals("3.0"))) {
-
- // If an XPathEvaluator was created previously
- // return it otherwise create a new one.
- if (fXPathEvaluator != null) {
- return fXPathEvaluator;
- }
-
- try {
- Class xpathClass = ObjectFactory.findProviderClass (
- "com.sun.org.apache.xpath.internal.domapi.XPathEvaluatorImpl", true);
- Constructor xpathClassConstr =
- xpathClass.getConstructor(new Class[] { Document.class });
-
- // Check if the DOM XPath implementation implements
- // the interface org.w3c.dom.XPathEvaluator
- Class interfaces[] = xpathClass.getInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- if (interfaces[i].getName().equals(
- "org.w3c.dom.xpath.XPathEvaluator")) {
- fXPathEvaluator = xpathClassConstr.newInstance(new Object[] { this });
- return fXPathEvaluator;
- }
- }
- return null;
- } catch (Exception e) {
- return null;
- }
- }
return super.getFeature(feature, version);
}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/OutputFormat.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/OutputFormat.java
index 1d0db3fa57d..ecf2ab8a018 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/OutputFormat.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/OutputFormat.java
@@ -36,7 +36,6 @@ import java.io.UnsupportedEncodingException;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Node;
-import org.w3c.dom.html.HTMLDocument;
/**
@@ -273,45 +272,6 @@ public class OutputFormat
setIndenting( indenting );
}
-
- /**
- * Constructs a new output format with the proper method,
- * document type identifiers and media type for the specified
- * document.
- *
- * @param doc The document to output
- * @see #whichMethod
- */
- public OutputFormat( Document doc )
- {
- setMethod( whichMethod( doc ) );
- setDoctype( whichDoctypePublic( doc ), whichDoctypeSystem( doc ) );
- setMediaType( whichMediaType( getMethod() ) );
- }
-
-
- /**
- * Constructs a new output format with the proper method,
- * document type identifiers and media type for the specified
- * document, and with the specified encoding. If indent
- * is true, the document will be pretty printed with the default
- * indentation level and default line wrapping.
- *
- * @param doc The document to output
- * @param encoding The specified encoding
- * @param indenting True for pretty printing
- * @see #setEncoding
- * @see #setIndenting
- * @see #whichMethod
- */
- public OutputFormat( Document doc, String encoding, boolean indenting )
- {
- this( doc );
- setEncoding( encoding );
- setIndenting( indenting );
- }
-
-
/**
* Returns the method specified for this output format.
* Typically the method will be xml, html
@@ -840,110 +800,6 @@ public class OutputFormat
}
- /**
- * Determine the output method for the specified document.
- * If the document is an instance of {@link org.w3c.dom.html.HTMLDocument}
- * then the method is said to be html. If the root
- * element is 'html' and all text nodes preceding the root
- * element are all whitespace, then the method is said to be
- * html. Otherwise the method is xml.
- *
- * @param doc The document to check
- * @return The suitable method
- */
- public static String whichMethod( Document doc )
- {
- Node node;
- String value;
- int i;
-
- // If document is derived from HTMLDocument then the default
- // method is html.
- if ( doc instanceof HTMLDocument )
- return Method.HTML;
-
- // Lookup the root element and the text nodes preceding it.
- // If root element is html and all text nodes contain whitespace
- // only, the method is html.
-
- // FIXME (SM) should we care about namespaces here?
-
- node = doc.getFirstChild();
- while (node != null) {
- // If the root element is html, the method is html.
- if ( node.getNodeType() == Node.ELEMENT_NODE ) {
- if ( node.getNodeName().equalsIgnoreCase( "html" ) ) {
- return Method.HTML;
- } else if ( node.getNodeName().equalsIgnoreCase( "root" ) ) {
- return Method.FOP;
- } else {
- return Method.XML;
- }
- } else if ( node.getNodeType() == Node.TEXT_NODE ) {
- // If a text node preceding the root element contains
- // only whitespace, this might be html, otherwise it's
- // definitely xml.
- value = node.getNodeValue();
- for ( i = 0 ; i < value.length() ; ++i )
- if ( value.charAt( i ) != 0x20 && value.charAt( i ) != 0x0A &&
- value.charAt( i ) != 0x09 && value.charAt( i ) != 0x0D )
- return Method.XML;
- }
- node = node.getNextSibling();
- }
- // Anything else, the method is xml.
- return Method.XML;
- }
-
-
- /**
- * Returns the document type public identifier
- * specified for this document, or null.
- */
- public static String whichDoctypePublic( Document doc )
- {
- DocumentType doctype;
-
- /* DOM Level 2 was introduced into the code base*/
- doctype = doc.getDoctype();
- if ( doctype != null ) {
- // Note on catch: DOM Level 1 does not specify this method
- // and the code will throw a NoSuchMethodError
- try {
- return doctype.getPublicId();
- } catch ( Error except ) { }
- }
-
- if ( doc instanceof HTMLDocument )
- return DTD.XHTMLPublicId;
- return null;
- }
-
-
- /**
- * Returns the document type system identifier
- * specified for this document, or null.
- */
- public static String whichDoctypeSystem( Document doc )
- {
- DocumentType doctype;
-
- /* DOM Level 2 was introduced into the code base*/
- doctype = doc.getDoctype();
- if ( doctype != null ) {
- // Note on catch: DOM Level 1 does not specify this method
- // and the code will throw a NoSuchMethodError
- try {
- return doctype.getSystemId();
- } catch ( Error except ) { }
- }
-
- if ( doc instanceof HTMLDocument )
- return DTD.XHTMLSystemId;
- return null;
- }
-
-
/**
* Returns the suitable media format for a document
* output with the specified method.
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SafeThread.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SafeThread.java
new file mode 100644
index 00000000000..abb5b3cffc1
--- /dev/null
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/SafeThread.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.org.apache.xml.internal.utils;
+
+import sun.misc.Unsafe;
+
+/**
+ * This is a combination of ThreadControllerWrapper's inner class SafeThread
+ * that was introduced as a fix for CR 6607339
+ * and sun.misc.ManagedLocalsThread, a thread that has it's thread locals, and
+ * inheritable thread locals erased on construction. Except the run method,
+ * it is identical to sun.misc.ManagedLocalsThread.
+ */
+public class SafeThread extends Thread {
+
+ private static final Unsafe UNSAFE;
+ private static final long THREAD_LOCALS;
+ private static final long INHERITABLE_THREAD_LOCALS;
+
+ private volatile boolean ran = false;
+
+ public SafeThread(Runnable target) {
+ super(target);
+ eraseThreadLocals();
+ }
+
+ public SafeThread(Runnable target, String name) {
+ super(target, name);
+ eraseThreadLocals();
+ }
+
+ public SafeThread(ThreadGroup group, Runnable target, String name) {
+ super(group, target, name);
+ eraseThreadLocals();
+ }
+
+ public final void run() {
+ if (Thread.currentThread() != this) {
+ throw new IllegalStateException("The run() method in a"
+ + " SafeThread cannot be called from another thread.");
+ }
+ synchronized (this) {
+ if (!ran) {
+ ran = true;
+ } else {
+ throw new IllegalStateException("The run() method in a"
+ + " SafeThread cannot be called more than once.");
+ }
+ }
+ super.run();
+ }
+
+ /**
+ * Drops all thread locals (and inherited thread locals).
+ */
+ public final void eraseThreadLocals() {
+ UNSAFE.putObject(this, THREAD_LOCALS, null);
+ UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
+ }
+
+ static {
+ UNSAFE = Unsafe.getUnsafe();
+ Class> t = Thread.class;
+ try {
+ THREAD_LOCALS = UNSAFE.objectFieldOffset(t.getDeclaredField("threadLocals"));
+ INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset(t.getDeclaredField("inheritableThreadLocals"));
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+
+}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/ThreadControllerWrapper.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/ThreadControllerWrapper.java
index 2dc8782ae57..034500edacd 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/ThreadControllerWrapper.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/utils/ThreadControllerWrapper.java
@@ -3,11 +3,12 @@
* DO NOT REMOVE OR ALTER!
*/
/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
@@ -17,110 +18,73 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
- * $Id: ThreadControllerWrapper.java,v 1.2.4.1 2005/09/15 08:15:59 suresh_emailid Exp $
- */
package com.sun.org.apache.xml.internal.utils;
/**
- * A utility class that wraps the ThreadController, which is used
- * by IncrementalSAXSource for the incremental building of DTM.
+ * A utility class that wraps the ThreadController, which is used by
+ * IncrementalSAXSource for the incremental building of DTM.
*/
-public class ThreadControllerWrapper
-{
-
- /** The ThreadController pool */
- private static ThreadController m_tpool = new ThreadController();
-
- public static Thread runThread(Runnable runnable, int priority)
- {
- return m_tpool.run(runnable, priority);
- }
-
- public static void waitThread(Thread worker, Runnable task)
- throws InterruptedException
- {
- m_tpool.waitThread(worker, task);
- }
-
- /**
- * Thread controller utility class for incremental SAX source. Must
- * be overriden with a derived class to support thread pooling.
- *
- * All thread-related stuff is in this class.
- */
- public static class ThreadController
- {
+public class ThreadControllerWrapper {
/**
- * This class was introduced as a fix for CR 6607339.
+ * The ThreadController pool
*/
- final class SafeThread extends Thread {
- private volatile boolean ran = false;
+ private static ThreadController m_tpool = new ThreadController();
- public SafeThread(Runnable target) {
- super(target);
- }
+ public static Thread runThread(Runnable runnable, int priority) {
+ return m_tpool.run(runnable, priority);
+ }
- public final void run() {
- if (Thread.currentThread() != this) {
- throw new IllegalStateException("The run() method in a"
- + " SafeThread cannot be called from another thread.");
- }
- synchronized (this) {
- if (!ran) {
- ran = true;
- }
- else {
- throw new IllegalStateException("The run() method in a"
- + " SafeThread cannot be called more than once.");
- }
- }
- super.run();
- }
+ public static void waitThread(Thread worker, Runnable task)
+ throws InterruptedException {
+ m_tpool.waitThread(worker, task);
}
/**
- * Will get a thread from the pool, execute the task
- * and return the thread to the pool.
+ * Thread controller utility class for incremental SAX source. Must be
+ * overridden with a derived class to support thread pooling.
*
- * The return value is used only to wait for completion
- *
- *
- * NEEDSDOC @param task
- * @param priority if >0 the task will run with the given priority
- * ( doesn't seem to be used in xalan, since it's allways the default )
- * @return The thread that is running the task, can be used
- * to wait for completion
+ * All thread-related stuff is in this class.
*/
- public Thread run(Runnable task, int priority)
- {
+ public static class ThreadController {
- Thread t = new SafeThread(task);
+ /**
+ * Will get a thread from the pool, execute the task and return the
+ * thread to the pool.
+ *
+ * The return value is used only to wait for completion
+ *
+ *
+ * @param task the Runnable
+ *
+ * @param priority if >0 the task will run with the given priority (
+ * doesn't seem to be used in xalan, since it's always the default )
+ * @return The thread that is running the task, can be used to wait for
+ * completion
+ */
+ public Thread run(Runnable task, int priority) {
- t.start();
+ Thread t = new SafeThread(task);
+ t.start();
- // if( priority > 0 )
- // t.setPriority( priority );
- return t;
+ //if( priority > 0 )
+ // t.setPriority( priority );
+ return t;
+ }
+
+ /**
+ * Wait until the task is completed on the worker thread.
+ *
+ * @param worker worker thread
+ * @param task the Runnable
+ *
+ * @throws InterruptedException
+ */
+ public void waitThread(Thread worker, Runnable task)
+ throws InterruptedException {
+
+ // This should wait until the transformThread is considered not alive.
+ worker.join();
+ }
}
-
- /**
- * Wait until the task is completed on the worker
- * thread.
- *
- * NEEDSDOC @param worker
- * NEEDSDOC @param task
- *
- * @throws InterruptedException
- */
- public void waitThread(Thread worker, Runnable task)
- throws InterruptedException
- {
-
- // This should wait until the transformThread is considered not alive.
- worker.join();
- }
- }
-
}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Lexer.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Lexer.java
index 5af6f188f6d..82c78aec437 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Lexer.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/Lexer.java
@@ -637,26 +637,8 @@ class Lexer
}
else
{
- // To older XPath code it doesn't matter if
- // error() is called or errorForDOM3().
- m_processor.errorForDOM3(XPATHErrorResources.ER_PREFIX_MUST_RESOLVE,
- new String[] {prefix}); //"Prefix must resolve to a namespace: {0}";
-
-/** old code commented out 17-Sep-2004
-// error("Could not locate namespace for prefix: "+prefix);
-// m_processor.error(XPATHErrorResources.ER_PREFIX_MUST_RESOLVE,
-// new String[] {prefix}); //"Prefix must resolve to a namespace: {0}";
-*/
-
- /*** Old code commented out 10-Jan-2001
- addToTokenQueue(prefix);
- addToTokenQueue(":");
-
- String s = pat.substring(posOfNSSep + 1, posOfScan);
-
- if (s.length() > 0)
- addToTokenQueue(s);
- ***/
+ m_processor.error(XPATHErrorResources.ER_PREFIX_MUST_RESOLVE,
+ new String[] {prefix}); //"Prefix must resolve to a namespace: {0}";
}
return -1;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/XPathParser.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/XPathParser.java
index 1b55599c203..bfaa2bb0205 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/XPathParser.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/compiler/XPathParser.java
@@ -28,7 +28,6 @@ import javax.xml.transform.TransformerException;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
import com.sun.org.apache.xml.internal.utils.PrefixResolver;
import com.sun.org.apache.xpath.internal.XPathProcessorException;
-import com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception;
import com.sun.org.apache.xpath.internal.objects.XNumber;
import com.sun.org.apache.xpath.internal.objects.XString;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
@@ -622,50 +621,6 @@ public class XPathParser
}
}
- /**
- * This method is added to support DOM 3 XPath API.
- *
- * This method is exactly like error(String, Object[]); except that
- * the underlying TransformerException is
- * XpathStylesheetDOM3Exception (which extends TransformerException).
- *
- * So older XPath code in Xalan is not affected by this. To older XPath code
- * the behavior of whether error() or errorForDOM3() is called because it is
- * always catching TransformerException objects and is oblivious to
- * the new subclass of XPathStylesheetDOM3Exception. Older XPath code
- * runs as before.
- *
- * However, newer DOM3 XPath code upon catching a TransformerException can
- * can check if the exception is an instance of XPathStylesheetDOM3Exception
- * and take appropriate action.
- *
- * @param msg An error msgkey that corresponds to one of the constants found
- * in {@link com.sun.org.apache.xpath.internal.res.XPATHErrorResources}, which is
- * a key for a format string.
- * @param args An array of arguments represented in the format string, which
- * may be null.
- *
- * @throws TransformerException if the current ErrorListoner determines to
- * throw an exception.
- */
- void errorForDOM3(String msg, Object[] args) throws TransformerException
- {
-
- String fmsg = XSLMessages.createXPATHMessage(msg, args);
- ErrorListener ehandler = this.getErrorListener();
-
- TransformerException te = new XPathStylesheetDOM3Exception(fmsg, m_sourceLocator);
- if (null != ehandler)
- {
- // TO DO: Need to get stylesheet Locator from here.
- ehandler.fatalError(te);
- }
- else
- {
- // System.err.println(fmsg);
- throw te;
- }
- }
/**
* Dump the remaining token queue.
* Thanks to Craig for this.
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathEvaluatorImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathEvaluatorImpl.java
deleted file mode 100644
index 096a232e3a5..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathEvaluatorImpl.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2002-2005 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: XPathEvaluatorImpl.java,v 1.2.4.1 2005/09/10 04:04:07 jeffsuttor Exp $
- */
-
-package com.sun.org.apache.xpath.internal.domapi;
-
-import javax.xml.transform.TransformerException;
-
-import com.sun.org.apache.xml.internal.utils.PrefixResolver;
-import com.sun.org.apache.xpath.internal.XPath;
-import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
-import com.sun.org.apache.xpath.internal.res.XPATHMessages;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.xpath.XPathEvaluator;
-import org.w3c.dom.xpath.XPathException;
-import org.w3c.dom.xpath.XPathExpression;
-import org.w3c.dom.xpath.XPathNSResolver;
-
-/**
- *
- * The class provides an implementation of XPathEvaluator according
- * to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
- *
- *
- *
- * The evaluation of XPath expressions is provided by
- * XPathEvaluator, which will provide evaluation of XPath 1.0
- * expressions with no specialized extension functions or variables. It is
- * expected that the XPathEvaluator interface will be
- * implemented on the same object which implements the Document
- * interface in an implementation which supports the XPath DOM module.
- * XPathEvaluator implementations may be available from other
- * sources that may provide support for special extension functions or
- * variables which are not defined in this specification.
- *
- * @see org.w3c.dom.xpath.XPathEvaluator
- *
- * @xsl.usage internal
- */
-public final class XPathEvaluatorImpl implements XPathEvaluator {
-
- /**
- * This prefix resolver is created whenever null is passed to the
- * evaluate method. Its purpose is to satisfy the DOM L3 XPath API
- * requirement that if a null prefix resolver is used, an exception
- * should only be thrown when an attempt is made to resolve a prefix.
- */
- private class DummyPrefixResolver implements PrefixResolver {
-
- /**
- * Constructor for DummyPrefixResolver.
- */
- DummyPrefixResolver() {}
-
- /**
- * @exception DOMException
- * NAMESPACE_ERR: Always throws this exceptionn
- *
- * @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getNamespaceForPrefix(String, Node)
- */
- public String getNamespaceForPrefix(String prefix, Node context) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_RESOLVER, null);
- throw new DOMException(DOMException.NAMESPACE_ERR, fmsg); // Unable to resolve prefix with null prefix resolver.
- }
-
- /**
- * @exception DOMException
- * NAMESPACE_ERR: Always throws this exceptionn
- *
- * @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getNamespaceForPrefix(String)
- */
- public String getNamespaceForPrefix(String prefix) {
- return getNamespaceForPrefix(prefix,null);
- }
-
- /**
- * @see com.sun.org.apache.xml.internal.utils.PrefixResolver#handlesNullPrefixes()
- */
- public boolean handlesNullPrefixes() {
- return false;
- }
-
- /**
- * @see com.sun.org.apache.xml.internal.utils.PrefixResolver#getBaseIdentifier()
- */
- public String getBaseIdentifier() {
- return null;
- }
-
- }
-
- /**
- * The document to be searched to parallel the case where the XPathEvaluator
- * is obtained by casting a Document.
- */
- private final Document m_doc;
-
- /**
- * Constructor for XPathEvaluatorImpl.
- *
- * @param doc The document to be searched, to parallel the case where''
- * the XPathEvaluator is obtained by casting the document.
- */
- public XPathEvaluatorImpl(Document doc) {
- m_doc = doc;
- }
-
- /**
- * Constructor in the case that the XPath expression can be evaluated
- * without needing an XML document at all.
- *
- */
- public XPathEvaluatorImpl() {
- m_doc = null;
- }
-
- /**
- * Creates a parsed XPath expression with resolved namespaces. This is
- * useful when an expression will be reused in an application since it
- * makes it possible to compile the expression string into a more
- * efficient internal form and preresolve all namespace prefixes which
- * occur within the expression.
- *
- * @param expression The XPath expression string to be parsed.
- * @param resolver The resolver permits translation of
- * prefixes within the XPath expression into appropriate namespace URIs
- * . If this is specified as null, any namespace prefix
- * within the expression will result in DOMException
- * being thrown with the code NAMESPACE_ERR.
- * @return The compiled form of the XPath expression.
- * @exception XPathException
- * INVALID_EXPRESSION_ERR: Raised if the expression is not legal
- * according to the rules of the XPathEvaluatori
- * @exception DOMException
- * NAMESPACE_ERR: Raised if the expression contains namespace prefixes
- * which cannot be resolved by the specified
- * XPathNSResolver.
- *
- * @see org.w3c.dom.xpath.XPathEvaluator#createExpression(String, XPathNSResolver)
- */
- public XPathExpression createExpression(
- String expression,
- XPathNSResolver resolver)
- throws XPathException, DOMException {
-
- try {
-
- // If the resolver is null, create a dummy prefix resolver
- XPath xpath = new XPath(expression,null,
- ((null == resolver) ? new DummyPrefixResolver() : ((PrefixResolver)resolver)),
- XPath.SELECT);
-
- return new XPathExpressionImpl(xpath, m_doc);
-
- } catch (TransformerException e) {
- // Need to pass back exception code DOMException.NAMESPACE_ERR also.
- // Error found in DOM Level 3 XPath Test Suite.
- if(e instanceof XPathStylesheetDOM3Exception)
- throw new DOMException(DOMException.NAMESPACE_ERR,e.getMessageAndLocation());
- else
- throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,e.getMessageAndLocation());
-
- }
- }
-
- /**
- * Adapts any DOM node to resolve namespaces so that an XPath expression
- * can be easily evaluated relative to the context of the node where it
- * appeared within the document. This adapter works like the DOM Level 3
- * method lookupNamespaceURI on nodes in resolving the
- * namespaceURI from a given prefix using the current information available
- * in the node's hierarchy at the time lookupNamespaceURI is called, also
- * correctly resolving the implicit xml prefix.
- *
- * @param nodeResolver The node to be used as a context for namespace
- * resolution.
- * @return XPathNSResolver which resolves namespaces with
- * respect to the definitions in scope for a specified node.
- *
- * @see org.w3c.dom.xpath.XPathEvaluator#createNSResolver(Node)
- */
- public XPathNSResolver createNSResolver(Node nodeResolver) {
-
- return new XPathNSResolverImpl((nodeResolver.getNodeType() == Node.DOCUMENT_NODE)
- ? ((Document) nodeResolver).getDocumentElement() : nodeResolver);
- }
-
- /**
- * Evaluates an XPath expression string and returns a result of the
- * specified type if possible.
- *
- * @param expression The XPath expression string to be parsed and
- * evaluated.
- * @param contextNode The context is context node for the
- * evaluation of this XPath expression. If the XPathEvaluator was
- * obtained by casting the Document then this must be
- * owned by the same document and must be a Document,
- * Element, Attribute, Text,
- * CDATASection, Comment,
- * ProcessingInstruction, or XPathNamespace
- * node. If the context node is a Text or a
- * CDATASection, then the context is interpreted as the
- * whole logical text node as seen by XPath, unless the node is empty
- * in which case it may not serve as the XPath context.
- * @param resolver The resolver permits translation of
- * prefixes within the XPath expression into appropriate namespace URIs
- * . If this is specified as null, any namespace prefix
- * within the expression will result in DOMException
- * being thrown with the code NAMESPACE_ERR.
- * @param type If a specific type is specified, then the
- * result will be coerced to return the specified type relying on
- * XPath type conversions and fail if the desired coercion is not
- * possible. This must be one of the type codes of
- * XPathResult.
- * @param result The result specifies a specific result
- * object which may be reused and returned by this method. If this is
- * specified as nullor the implementation does not reuse
- * the specified result, a new result object will be constructed and
- * returned.For XPath 1.0 results, this object will be of type
- * XPathResult.
- * @return The result of the evaluation of the XPath expression.For XPath
- * 1.0 results, this object will be of type XPathResult.
- * @exception XPathException
- * INVALID_EXPRESSION_ERR: Raised if the expression is not legal
- * according to the rules of the XPathEvaluatori
- * TYPE_ERR: Raised if the result cannot be converted to return the
- * specified type.
- * @exception DOMException
- * NAMESPACE_ERR: Raised if the expression contains namespace prefixes
- * which cannot be resolved by the specified
- * XPathNSResolver.
- * WRONG_DOCUMENT_ERR: The Node is from a document that is not
- * supported by this XPathEvaluator.
- * NOT_SUPPORTED_ERR: The Node is not a type permitted as an XPath
- * context node.
- *
- * @see org.w3c.dom.xpath.XPathEvaluator#evaluate(String, Node, XPathNSResolver, short, XPathResult)
- */
- public Object evaluate(
- String expression,
- Node contextNode,
- XPathNSResolver resolver,
- short type,
- Object result)
- throws XPathException, DOMException {
-
- XPathExpression xpathExpression = createExpression(expression, resolver);
-
- return xpathExpression.evaluate(contextNode, type, result);
- }
-
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathExpressionImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathExpressionImpl.java
deleted file mode 100644
index 5c92d597e89..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathExpressionImpl.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2002-2005 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: XPathExpressionImpl.java,v 1.2.4.1 2005/09/10 04:06:55 jeffsuttor Exp $
- */
-
-
-package com.sun.org.apache.xpath.internal.domapi;
-
-import javax.xml.transform.TransformerException;
-
-import com.sun.org.apache.xpath.internal.XPath;
-import com.sun.org.apache.xpath.internal.XPathContext;
-import com.sun.org.apache.xpath.internal.objects.XObject;
-import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
-import com.sun.org.apache.xpath.internal.res.XPATHMessages;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.xpath.XPathException;
-import org.w3c.dom.xpath.XPathExpression;
-import org.w3c.dom.xpath.XPathNamespace;
-
-/**
- *
- * The class provides an implementation of XPathExpression according
- * to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
- *
- *
The XPathExpression interface represents a parsed and resolved
- * XPath expression.
- *
- * @see org.w3c.dom.xpath.XPathExpression
- *
- * @xsl.usage internal
- */
-class XPathExpressionImpl implements XPathExpression {
-
- /**
- * The xpath object that this expression wraps
- */
- final private XPath m_xpath;
-
- /**
- * The document to be searched to parallel the case where the XPathEvaluator
- * is obtained by casting a Document.
- */
- final private Document m_doc;
-
- /**
- * Constructor for XPathExpressionImpl.
- *
- * @param xpath The wrapped XPath object.
- * @param doc The document to be searched, to parallel the case where''
- * the XPathEvaluator is obtained by casting the document.
- */
- XPathExpressionImpl(XPath xpath, Document doc) {
- m_xpath = xpath;
- m_doc = doc;
- }
-
- /**
- *
- * This method provides an implementation XPathResult.evaluate according
- * to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
- *
- *
Evaluates this XPath expression and returns a result.
- * @param contextNode The context is context node for the
- * evaluation of this XPath expression.If the XPathEvaluator was
- * obtained by casting the Document then this must be
- * owned by the same document and must be a Document,
- * Element, Attribute, Text,
- * CDATASection, Comment,
- * ProcessingInstruction, or XPathNamespace
- * node.If the context node is a Text or a
- * CDATASection, then the context is interpreted as the
- * whole logical text node as seen by XPath, unless the node is empty
- * in which case it may not serve as the XPath context.
- * @param type If a specific type is specified, then the
- * result will be coerced to return the specified type relying on
- * XPath conversions and fail if the desired coercion is not possible.
- * This must be one of the type codes of XPathResult.
- * @param result The result specifies a specific result
- * object which may be reused and returned by this method. If this is
- * specified as nullor the implementation does not reuse
- * the specified result, a new result object will be constructed and
- * returned.For XPath 1.0 results, this object will be of type
- * XPathResult.
- * @return The result of the evaluation of the XPath expression.For XPath
- * 1.0 results, this object will be of type XPathResult.
- * @exception XPathException
- * TYPE_ERR: Raised if the result cannot be converted to return the
- * specified type.
- * @exception DOMException
- * WRONG_DOCUMENT_ERR: The Node is from a document that is not supported
- * by the XPathEvaluator that created this
- * XPathExpression.
- * NOT_SUPPORTED_ERR: The Node is not a type permitted as an XPath
- * context node.
- *
- * @see org.w3c.dom.xpath.XPathExpression#evaluate(Node, short, XPathResult)
- * @xsl.usage internal
- */
- public Object evaluate(
- Node contextNode,
- short type,
- Object result)
- throws XPathException, DOMException {
-
- // If the XPathEvaluator was determined by "casting" the document
- if (m_doc != null) {
-
- // Check that the context node is owned by the same document
- if ((contextNode != m_doc) && (!contextNode.getOwnerDocument().equals(m_doc))) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_WRONG_DOCUMENT, null);
- throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, fmsg);
- }
-
- // Check that the context node is an acceptable node type
- short nodeType = contextNode.getNodeType();
- if ((nodeType != Document.DOCUMENT_NODE) &&
- (nodeType != Document.ELEMENT_NODE) &&
- (nodeType != Document.ATTRIBUTE_NODE) &&
- (nodeType != Document.TEXT_NODE) &&
- (nodeType != Document.CDATA_SECTION_NODE) &&
- (nodeType != Document.COMMENT_NODE) &&
- (nodeType != Document.PROCESSING_INSTRUCTION_NODE) &&
- (nodeType != XPathNamespace.XPATH_NAMESPACE_NODE)) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_WRONG_NODETYPE, null);
- throw new DOMException(DOMException.NOT_SUPPORTED_ERR, fmsg);
- }
- }
-
- //
- // If the type is not a supported type, throw an exception and be
- // done with it!
- if (!XPathResultImpl.isValidType(type)) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INVALID_XPATH_TYPE, new Object[] {new Integer(type)});
- throw new XPathException(XPathException.TYPE_ERR,fmsg); // Invalid XPath type argument: {0}
- }
-
- // Cache xpath context?
- XPathContext xpathSupport = new XPathContext();
-
- // if m_document is not null, build the DTM from the document
- if (null != m_doc) {
- xpathSupport.getDTMHandleFromNode(m_doc);
- }
-
- XObject xobj = null;
- try {
- xobj = m_xpath.execute(xpathSupport, contextNode, null);
- } catch (TransformerException te) {
- // What should we do here?
- throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,te.getMessageAndLocation());
- }
-
- // Create a new XPathResult object
- // Reuse result object passed in?
- // The constructor will check the compatibility of type and xobj and
- // throw an exception if they are not compatible.
- return new XPathResultImpl(type,xobj,contextNode, m_xpath);
- }
-
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathNSResolverImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathNSResolverImpl.java
deleted file mode 100644
index 6c1106085b9..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathNSResolverImpl.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2002-2005 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: XPathNSResolverImpl.java,v 1.2.4.1 2005/09/10 04:13:19 jeffsuttor Exp $
- */
-
-package com.sun.org.apache.xpath.internal.domapi;
-
-import com.sun.org.apache.xml.internal.utils.PrefixResolverDefault;
-import org.w3c.dom.Node;
-import org.w3c.dom.xpath.XPathNSResolver;
-
-/**
- *
- * The class provides an implementation XPathNSResolver according
- * to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
- *
- *
The XPathNSResolver interface permit prefix
- * strings in the expression to be properly bound to
- * namespaceURI strings. XPathEvaluator can
- * construct an implementation of XPathNSResolver from a node,
- * or the interface may be implemented by any application.
- *
- * @see org.w3c.dom.xpath.XPathNSResolver
- * @xsl.usage internal
- */
-class XPathNSResolverImpl extends PrefixResolverDefault implements XPathNSResolver {
-
- /**
- * Constructor for XPathNSResolverImpl.
- * @param xpathExpressionContext
- */
- public XPathNSResolverImpl(Node xpathExpressionContext) {
- super(xpathExpressionContext);
- }
-
- /**
- * @see org.w3c.dom.xpath.XPathNSResolver#lookupNamespaceURI(String)
- */
- public String lookupNamespaceURI(String prefix) {
- return super.getNamespaceForPrefix(prefix);
- }
-
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathNamespaceImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathNamespaceImpl.java
deleted file mode 100644
index 41a1d16b301..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathNamespaceImpl.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2002-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: XPathNamespaceImpl.java,v 1.2.4.1 2005/09/10 04:10:02 jeffsuttor Exp $
- */
-
-
-package com.sun.org.apache.xpath.internal.domapi;
-
-import org.w3c.dom.Attr;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.xpath.XPathNamespace;
-
-import org.w3c.dom.UserDataHandler;
-
-/**
- *
- *
- * The XPathNamespace interface is returned by
- * XPathResult interfaces to represent the XPath namespace node
- * type that DOM lacks. There is no public constructor for this node type.
- * Attempts to place it into a hierarchy or a NamedNodeMap result in a
- * DOMException with the code HIERARCHY_REQUEST_ERR
- * . This node is read only, so methods or setting of attributes that would
- * mutate the node result in a DOMException with the code
- * NO_MODIFICATION_ALLOWED_ERR.
- *
The core specification describes attributes of the Node
- * interface that are different for different node node types but does not
- * describe XPATH_NAMESPACE_NODE, so here is a description of
- * those attributes for this node type. All attributes of Node
- * not described in this section have a null or
- * false value.
- *
ownerDocument matches the ownerDocument of the
- * ownerElement even if the element is later adopted.
- *
prefix is the prefix of the namespace represented by the
- * node.
- *
nodeName is the same as prefix.
- *
nodeType is equal to XPATH_NAMESPACE_NODE.
- *
namespaceURI is the namespace URI of the namespace
- * represented by the node.
- *
adoptNode, cloneNode, and
- * importNode fail on this node type by raising a
- * DOMException with the code NOT_SUPPORTED_ERR.In
- * future versions of the XPath specification, the definition of a namespace
- * node may be changed incomatibly, in which case incompatible changes to
- * field values may be required to implement versions beyond XPath 1.0.
- *
See also the Document Object Model (DOM) Level 3 XPath Specification.
- *
- * This implementation wraps the DOM attribute node that contained the
- * namespace declaration.
- * @xsl.usage internal
- */
-
-class XPathNamespaceImpl implements XPathNamespace {
-
- // Node that XPathNamespaceImpl wraps
- final private Node m_attributeNode;
-
- /**
- * Constructor for XPathNamespaceImpl.
- */
- XPathNamespaceImpl(Node node) {
- m_attributeNode = node;
- }
-
- /**
- * @see com.sun.org.apache.xalan.internal.dom3.xpath.XPathNamespace#getOwnerElement()
- */
- public Element getOwnerElement() {
- return ((Attr)m_attributeNode).getOwnerElement();
- }
-
- /**
- * @see org.w3c.dom.Node#getNodeName()
- */
- public String getNodeName() {
- return "#namespace";
- }
-
- /**
- * @see org.w3c.dom.Node#getNodeValue()
- */
- public String getNodeValue() throws DOMException {
- return m_attributeNode.getNodeValue();
- }
-
- /**
- * @see org.w3c.dom.Node#setNodeValue(String)
- */
- public void setNodeValue(String arg0) throws DOMException {
- }
-
- /**
- * @see org.w3c.dom.Node#getNodeType()
- */
- public short getNodeType() {
- return XPathNamespace.XPATH_NAMESPACE_NODE;
- }
-
- /**
- * @see org.w3c.dom.Node#getParentNode()
- */
- public Node getParentNode() {
- return m_attributeNode.getParentNode();
- }
-
- /**
- * @see org.w3c.dom.Node#getChildNodes()
- */
- public NodeList getChildNodes() {
- return m_attributeNode.getChildNodes();
- }
-
- /**
- * @see org.w3c.dom.Node#getFirstChild()
- */
- public Node getFirstChild() {
- return m_attributeNode.getFirstChild();
- }
-
- /**
- * @see org.w3c.dom.Node#getLastChild()
- */
- public Node getLastChild() {
- return m_attributeNode.getLastChild();
- }
-
- /**
- * @see org.w3c.dom.Node#getPreviousSibling()
- */
- public Node getPreviousSibling() {
- return m_attributeNode.getPreviousSibling();
- }
-
- /**
- * @see org.w3c.dom.Node#getNextSibling()
- */
- public Node getNextSibling() {
- return m_attributeNode.getNextSibling();
- }
-
- /**
- * @see org.w3c.dom.Node#getAttributes()
- */
- public NamedNodeMap getAttributes() {
- return m_attributeNode.getAttributes();
- }
-
- /**
- * @see org.w3c.dom.Node#getOwnerDocument()
- */
- public Document getOwnerDocument() {
- return m_attributeNode.getOwnerDocument();
- }
-
- /**
- * @see org.w3c.dom.Node#insertBefore(Node, Node)
- */
- public Node insertBefore(Node arg0, Node arg1) throws DOMException {
- return null;
- }
-
- /**
- * @see org.w3c.dom.Node#replaceChild(Node, Node)
- */
- public Node replaceChild(Node arg0, Node arg1) throws DOMException {
- return null;
- }
-
- /**
- * @see org.w3c.dom.Node#removeChild(Node)
- */
- public Node removeChild(Node arg0) throws DOMException {
- return null;
- }
-
- /**
- * @see org.w3c.dom.Node#appendChild(Node)
- */
- public Node appendChild(Node arg0) throws DOMException {
- return null;
- }
-
- /**
- * @see org.w3c.dom.Node#hasChildNodes()
- */
- public boolean hasChildNodes() {
- return false;
- }
-
- /**
- * @see org.w3c.dom.Node#cloneNode(boolean)
- */
- public Node cloneNode(boolean arg0) {
- throw new DOMException(DOMException.NOT_SUPPORTED_ERR,null);
- }
-
- /**
- * @see org.w3c.dom.Node#normalize()
- */
- public void normalize() {
- m_attributeNode.normalize();
- }
-
- /**
- * @see org.w3c.dom.Node#isSupported(String, String)
- */
- public boolean isSupported(String arg0, String arg1) {
- return m_attributeNode.isSupported(arg0, arg1);
- }
-
- /**
- * @see org.w3c.dom.Node#getNamespaceURI()
- */
- public String getNamespaceURI() {
-
- // For namespace node, the namespaceURI is the namespace URI
- // of the namespace represented by the node.
- return m_attributeNode.getNodeValue();
- }
-
- /**
- * @see org.w3c.dom.Node#getPrefix()
- */
- public String getPrefix() {
- return m_attributeNode.getPrefix();
- }
-
- /**
- * @see org.w3c.dom.Node#setPrefix(String)
- */
- public void setPrefix(String arg0) throws DOMException {
- }
-
- /**
- * @see org.w3c.dom.Node#getLocalName()
- */
- public String getLocalName() {
-
- // For namespace node, the local name is the same as the prefix
- return m_attributeNode.getPrefix();
- }
-
- /**
- * @see org.w3c.dom.Node#hasAttributes()
- */
- public boolean hasAttributes() {
- return m_attributeNode.hasAttributes();
- }
-
- public String getBaseURI ( ) {
- return null;
- }
-
- public short compareDocumentPosition(Node other) throws DOMException {
- return 0;
- }
-
- private String textContent;
-
- public String getTextContent() throws DOMException {
- return textContent;
- }
-
- public void setTextContent(String textContent) throws DOMException {
- this.textContent = textContent;
- }
-
- public boolean isSameNode(Node other) {
- return false;
- }
-
- public String lookupPrefix(String namespaceURI) {
- return ""; //PENDING
- }
-
- public boolean isDefaultNamespace(String namespaceURI) {
- return false;
- }
-
- public String lookupNamespaceURI(String prefix) {
- return null;
- }
-
- public boolean isEqualNode(Node arg) {
- return false;
- }
-
- public Object getFeature(String feature, String version) {
- return null; //PENDING
- }
-
- public Object setUserData(String key,
- Object data,
- UserDataHandler handler) {
- return null; //PENDING
- }
-
- public Object getUserData(String key) {
- return null;
- }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathResultImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathResultImpl.java
deleted file mode 100644
index 76576f4cc51..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathResultImpl.java
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
- */
-/*
- * Copyright 2002-2005 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/*
- * $Id: XPathResultImpl.java,v 1.2.4.1 2005/09/10 04:18:54 jeffsuttor Exp $
- */
-
-
-package com.sun.org.apache.xpath.internal.domapi;
-
-import javax.xml.transform.TransformerException;
-
-import com.sun.org.apache.xpath.internal.XPath;
-import com.sun.org.apache.xpath.internal.objects.XObject;
-import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
-import com.sun.org.apache.xpath.internal.res.XPATHMessages;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.events.Event;
-import org.w3c.dom.events.EventListener;
-import org.w3c.dom.events.EventTarget;
-import org.w3c.dom.traversal.NodeIterator;
-import org.w3c.dom.xpath.XPathException;
-import org.w3c.dom.xpath.XPathResult;
-
-/**
- *
- * The class provides an implementation XPathResult according
- * to the DOM L3 XPath Specification, Working Group Note 26 February 2004.
- *
- *
The XPathResult interface represents the result of the
- * evaluation of an XPath expression within the context of a particular
- * node. Since evaluation of an XPath expression can result in various
- * result types, this object makes it possible to discover and manipulate
- * the type and value of the result.
- *
- *
This implementation wraps an XObject.
- *
- * @see com.sun.org.apache.xpath.internal.objects.XObject
- * @see org.w3c.dom.xpath.XPathResult
- *
- * @xsl.usage internal
- */
-class XPathResultImpl implements XPathResult, EventListener {
-
- /**
- * The wrapped XObject
- */
- final private XObject m_resultObj;
-
- /**
- * The xpath object that wraps the expression used for this result.
- */
- final private XPath m_xpath;
-
- /**
- * This the type specified by the user during construction. Typically
- * the constructor will be called by com.sun.org.apache.xpath.internal.XPath.evaluate().
- */
- final private short m_resultType;
-
- private boolean m_isInvalidIteratorState = false;
-
- /**
- * Only used to attach a mutation event handler when specified
- * type is an iterator type.
- */
- final private Node m_contextNode;
-
- /**
- * The iterator, if this is an iterator type.
- */
- private NodeIterator m_iterator = null;;
-
- /**
- * The list, if this is a snapshot type.
- */
- private NodeList m_list = null;
-
-
- /**
- * Constructor for XPathResultImpl.
- *
- * For internal use only.
- */
- XPathResultImpl(short type, XObject result, Node contextNode, XPath xpath) {
- // Check that the type is valid
- if (!isValidType(type)) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INVALID_XPATH_TYPE, new Object[] {new Integer(type)});
- throw new XPathException(XPathException.TYPE_ERR,fmsg); // Invalid XPath type argument: {0}
- }
-
- // Result object should never be null!
- if (null == result) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_EMPTY_XPATH_RESULT, null);
- throw new XPathException(XPathException.INVALID_EXPRESSION_ERR,fmsg); // Empty XPath result object
- }
-
- this.m_resultObj = result;
- this.m_contextNode = contextNode;
- this.m_xpath = xpath;
-
- // If specified result was ANY_TYPE, determine XObject type
- if (type == ANY_TYPE) {
- this.m_resultType = getTypeFromXObject(result);
- } else {
- this.m_resultType = type;
- }
-
- // If the context node supports DOM Events and the type is one of the iterator
- // types register this result as an event listener
- if (((m_resultType == XPathResult.ORDERED_NODE_ITERATOR_TYPE) ||
- (m_resultType == XPathResult.UNORDERED_NODE_ITERATOR_TYPE))) {
- addEventListener();
-
- }// else can we handle iterator types if contextNode doesn't support EventTarget??
-
- // If this is an iterator type get the iterator
- if ((m_resultType == ORDERED_NODE_ITERATOR_TYPE) ||
- (m_resultType == UNORDERED_NODE_ITERATOR_TYPE) ||
- (m_resultType == ANY_UNORDERED_NODE_TYPE) ||
- (m_resultType == FIRST_ORDERED_NODE_TYPE)) {
-
- try {
- m_iterator = m_resultObj.nodeset();
- } catch (TransformerException te) {
- // probably not a node type
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INCOMPATIBLE_TYPES, new Object[] {m_xpath.getPatternString(), getTypeString(getTypeFromXObject(m_resultObj)),getTypeString(m_resultType)});
- throw new XPathException(XPathException.TYPE_ERR, fmsg); // "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be coerced into the specified XPathResultType of {2}."},
- }
-
- // If user requested ordered nodeset and result is unordered
- // need to sort...TODO
- // if ((m_resultType == ORDERED_NODE_ITERATOR_TYPE) &&
- // (!(((DTMNodeIterator)m_iterator).getDTMIterator().isDocOrdered()))) {
- //
- // }
-
- // If it's a snapshot type, get the nodelist
- } else if ((m_resultType == UNORDERED_NODE_SNAPSHOT_TYPE) ||
- (m_resultType == ORDERED_NODE_SNAPSHOT_TYPE)) {
- try {
- m_list = m_resultObj.nodelist();
- } catch (TransformerException te) {
- // probably not a node type
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_INCOMPATIBLE_TYPES, new Object[] {m_xpath.getPatternString(), getTypeString(getTypeFromXObject(m_resultObj)),getTypeString(m_resultType)});
- throw new XPathException(XPathException.TYPE_ERR, fmsg); // "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be coerced into the specified XPathResultType of {2}."},
- }
- }
- }
-
- /**
- * @see org.w3c.dom.xpath.XPathResult#getResultType()
- */
- public short getResultType() {
- return m_resultType;
- }
-
- /**
- * The value of this number result.
- * @exception XPathException
- * TYPE_ERR: raised if resultType is not
- * NUMBER_TYPE.
- * @see org.w3c.dom.xpath.XPathResult#getNumberValue()
- */
- public double getNumberValue() throws XPathException {
- if (getResultType() != NUMBER_TYPE) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_XPATHRESULTTYPE_TO_NUMBER, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
- throw new XPathException(XPathException.TYPE_ERR,fmsg);
-// "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be converted to a number"
- } else {
- try {
- return m_resultObj.num();
- } catch (Exception e) {
- // Type check above should prevent this exception from occurring.
- throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
- }
- }
- }
-
- /**
- * The value of this string result.
- * @exception XPathException
- * TYPE_ERR: raised if resultType is not
- * STRING_TYPE.
- *
- * @see org.w3c.dom.xpath.XPathResult#getStringValue()
- */
- public String getStringValue() throws XPathException {
- if (getResultType() != STRING_TYPE) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_STRING, new Object[] {m_xpath.getPatternString(), m_resultObj.getTypeString()});
- throw new XPathException(XPathException.TYPE_ERR,fmsg);
-// "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be converted to a string."
- } else {
- try {
- return m_resultObj.str();
- } catch (Exception e) {
- // Type check above should prevent this exception from occurring.
- throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
- }
- }
- }
-
- /**
- * @see org.w3c.dom.xpath.XPathResult#getBooleanValue()
- */
- public boolean getBooleanValue() throws XPathException {
- if (getResultType() != BOOLEAN_TYPE) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_BOOLEAN, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
- throw new XPathException(XPathException.TYPE_ERR,fmsg);
-// "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be converted to a boolean."
- } else {
- try {
- return m_resultObj.bool();
- } catch (TransformerException e) {
- // Type check above should prevent this exception from occurring.
- throw new XPathException(XPathException.TYPE_ERR,e.getMessage());
- }
- }
- }
-
- /**
- * The value of this single node result, which may be null.
- * @exception XPathException
- * TYPE_ERR: raised if resultType is not
- * ANY_UNORDERED_NODE_TYPE or
- * FIRST_ORDERED_NODE_TYPE.
- *
- * @see org.w3c.dom.xpath.XPathResult#getSingleNodeValue()
- */
- public Node getSingleNodeValue() throws XPathException {
-
- if ((m_resultType != ANY_UNORDERED_NODE_TYPE) &&
- (m_resultType != FIRST_ORDERED_NODE_TYPE)) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_CONVERT_TO_SINGLENODE, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
- throw new XPathException(XPathException.TYPE_ERR,fmsg);
-// "The XPathResult of XPath expression {0} has an XPathResultType of {1} which cannot be converted to a single node.
-// This method applies only to types ANY_UNORDERED_NODE_TYPE and FIRST_ORDERED_NODE_TYPE."
- }
-
- NodeIterator result = null;
- try {
- result = m_resultObj.nodeset();
- } catch (TransformerException te) {
- throw new XPathException(XPathException.TYPE_ERR,te.getMessage());
- }
-
- if (null == result) return null;
-
- Node node = result.nextNode();
-
- // Wrap "namespace node" in an XPathNamespace
- if (isNamespaceNode(node)) {
- return new XPathNamespaceImpl(node);
- } else {
- return node;
- }
- }
-
- /**
- * @see org.w3c.dom.xpath.XPathResult#getInvalidIteratorState()
- */
- public boolean getInvalidIteratorState() {
- return m_isInvalidIteratorState;
- }
-
- /**
- * The number of nodes in the result snapshot. Valid values for
- * snapshotItem indices are 0 to
- * snapshotLength-1 inclusive.
- * @exception XPathException
- * TYPE_ERR: raised if resultType is not
- * UNORDERED_NODE_SNAPSHOT_TYPE or
- * ORDERED_NODE_SNAPSHOT_TYPE.
- *
- * @see org.w3c.dom.xpath.XPathResult#getSnapshotLength()
- */
- public int getSnapshotLength() throws XPathException {
-
- if ((m_resultType != UNORDERED_NODE_SNAPSHOT_TYPE) &&
- (m_resultType != ORDERED_NODE_SNAPSHOT_TYPE)) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_CANT_GET_SNAPSHOT_LENGTH, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
- throw new XPathException(XPathException.TYPE_ERR,fmsg);
-// "The method getSnapshotLength cannot be called on the XPathResult of XPath expression {0} because its XPathResultType is {1}.
- }
-
- return m_list.getLength();
- }
-
- /**
- * Iterates and returns the next node from the node set or
- * nullif there are no more nodes.
- * @return Returns the next node.
- * @exception XPathException
- * TYPE_ERR: raised if resultType is not
- * UNORDERED_NODE_ITERATOR_TYPE or
- * ORDERED_NODE_ITERATOR_TYPE.
- * @exception DOMException
- * INVALID_STATE_ERR: The document has been mutated since the result was
- * returned.
- * @see org.w3c.dom.xpath.XPathResult#iterateNext()
- */
- public Node iterateNext() throws XPathException, DOMException {
- if ((m_resultType != UNORDERED_NODE_ITERATOR_TYPE) &&
- (m_resultType != ORDERED_NODE_ITERATOR_TYPE)) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NON_ITERATOR_TYPE, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
- throw new XPathException(XPathException.TYPE_ERR, fmsg);
-// "The method iterateNext cannot be called on the XPathResult of XPath expression {0} because its XPathResultType is {1}.
-// This method applies only to types UNORDERED_NODE_ITERATOR_TYPE and ORDERED_NODE_ITERATOR_TYPE."},
- }
-
- if (getInvalidIteratorState()) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_DOC_MUTATED, null);
- throw new DOMException(DOMException.INVALID_STATE_ERR,fmsg); // Document mutated since result was returned. Iterator is invalid.
- }
-
- Node node = m_iterator.nextNode();
- if(null == node)
- removeEventListener(); // JIRA 1673
- // Wrap "namespace node" in an XPathNamespace
- if (isNamespaceNode(node)) {
- return new XPathNamespaceImpl(node);
- } else {
- return node;
- }
- }
-
- /**
- * Returns the indexth item in the snapshot collection. If
- * index is greater than or equal to the number of nodes in
- * the list, this method returns null. Unlike the iterator
- * result, the snapshot does not become invalid, but may not correspond
- * to the current document if it is mutated.
- * @param index Index into the snapshot collection.
- * @return The node at the indexth position in the
- * NodeList, or null if that is not a valid
- * index.
- * @exception XPathException
- * TYPE_ERR: raised if resultType is not
- * UNORDERED_NODE_SNAPSHOT_TYPE or
- * ORDERED_NODE_SNAPSHOT_TYPE.
- *
- * @see org.w3c.dom.xpath.XPathResult#snapshotItem(int)
- */
- public Node snapshotItem(int index) throws XPathException {
-
- if ((m_resultType != UNORDERED_NODE_SNAPSHOT_TYPE) &&
- (m_resultType != ORDERED_NODE_SNAPSHOT_TYPE)) {
- String fmsg = XPATHMessages.createXPATHMessage(XPATHErrorResources.ER_NON_SNAPSHOT_TYPE, new Object[] {m_xpath.getPatternString(), getTypeString(m_resultType)});
- throw new XPathException(XPathException.TYPE_ERR, fmsg);
-// "The method snapshotItem cannot be called on the XPathResult of XPath expression {0} because its XPathResultType is {1}.
-// This method applies only to types UNORDERED_NODE_SNAPSHOT_TYPE and ORDERED_NODE_SNAPSHOT_TYPE."},
- }
-
- Node node = m_list.item(index);
-
- // Wrap "namespace node" in an XPathNamespace
- if (isNamespaceNode(node)) {
- return new XPathNamespaceImpl(node);
- } else {
- return node;
- }
- }
-
-
- /**
- * Check if the specified type is one of the supported types.
- * @param type The specified type
- *
- * @return true If the specified type is supported; otherwise, returns false.
- */
- static boolean isValidType( short type ) {
- switch (type) {
- case ANY_TYPE:
- case NUMBER_TYPE:
- case STRING_TYPE:
- case BOOLEAN_TYPE:
- case UNORDERED_NODE_ITERATOR_TYPE:
- case ORDERED_NODE_ITERATOR_TYPE:
- case UNORDERED_NODE_SNAPSHOT_TYPE:
- case ORDERED_NODE_SNAPSHOT_TYPE:
- case ANY_UNORDERED_NODE_TYPE:
- case FIRST_ORDERED_NODE_TYPE: return true;
- default: return false;
- }
- }
-
- /**
- * @see org.w3c.dom.events.EventListener#handleEvent(Event)
- */
- public void handleEvent(Event event) {
-
- if (event.getType().equals("DOMSubtreeModified")) {
- // invalidate the iterator
- m_isInvalidIteratorState = true;
-
- // deregister as a listener to reduce computational load
- removeEventListener();
- }
- }
-
- /**
- * Given a request type, return the equivalent string.
- * For diagnostic purposes.
- *
- * @return type string
- */
- private String getTypeString(int type)
- {
- switch (type) {
- case ANY_TYPE: return "ANY_TYPE";
- case ANY_UNORDERED_NODE_TYPE: return "ANY_UNORDERED_NODE_TYPE";
- case BOOLEAN_TYPE: return "BOOLEAN";
- case FIRST_ORDERED_NODE_TYPE: return "FIRST_ORDERED_NODE_TYPE";
- case NUMBER_TYPE: return "NUMBER_TYPE";
- case ORDERED_NODE_ITERATOR_TYPE: return "ORDERED_NODE_ITERATOR_TYPE";
- case ORDERED_NODE_SNAPSHOT_TYPE: return "ORDERED_NODE_SNAPSHOT_TYPE";
- case STRING_TYPE: return "STRING_TYPE";
- case UNORDERED_NODE_ITERATOR_TYPE: return "UNORDERED_NODE_ITERATOR_TYPE";
- case UNORDERED_NODE_SNAPSHOT_TYPE: return "UNORDERED_NODE_SNAPSHOT_TYPE";
- default: return "#UNKNOWN";
- }
- }
-
- /**
- * Given an XObject, determine the corresponding DOM XPath type
- *
- * @return type string
- */
- private short getTypeFromXObject(XObject object) {
- switch (object.getType()) {
- case XObject.CLASS_BOOLEAN: return BOOLEAN_TYPE;
- case XObject.CLASS_NODESET: return UNORDERED_NODE_ITERATOR_TYPE;
- case XObject.CLASS_NUMBER: return NUMBER_TYPE;
- case XObject.CLASS_STRING: return STRING_TYPE;
- // XPath 2.0 types
-// case XObject.CLASS_DATE:
-// case XObject.CLASS_DATETIME:
-// case XObject.CLASS_DTDURATION:
-// case XObject.CLASS_GDAY:
-// case XObject.CLASS_GMONTH:
-// case XObject.CLASS_GMONTHDAY:
-// case XObject.CLASS_GYEAR:
-// case XObject.CLASS_GYEARMONTH:
-// case XObject.CLASS_TIME:
-// case XObject.CLASS_YMDURATION: return STRING_TYPE; // treat all date types as strings?
-
- case XObject.CLASS_RTREEFRAG: return UNORDERED_NODE_ITERATOR_TYPE;
- case XObject.CLASS_NULL: return ANY_TYPE; // throw exception ?
- default: return ANY_TYPE; // throw exception ?
- }
-
- }
-
-/**
- * Given a node, determine if it is a namespace node.
- *
- * @param node
- *
- * @return boolean Returns true if this is a namespace node; otherwise, returns false.
- */
- private boolean isNamespaceNode(Node node) {
-
- if ((null != node) &&
- (node.getNodeType() == Node.ATTRIBUTE_NODE) &&
- (node.getNodeName().startsWith("xmlns:") || node.getNodeName().equals("xmlns"))) {
- return true;
- } else {
- return false;
- }
- }
-
-/**
- * Add m_contextNode to Event Listner to listen for Mutations Events
- *
- */
- private void addEventListener(){
- if(m_contextNode instanceof EventTarget)
- ((EventTarget)m_contextNode).addEventListener("DOMSubtreeModified",this,true);
-
- }
-
-
-/**
- * Remove m_contextNode to Event Listner to listen for Mutations Events
- *
- */
-private void removeEventListener(){
- if(m_contextNode instanceof EventTarget)
- ((EventTarget)m_contextNode).removeEventListener("DOMSubtreeModified",this,true);
-}
-
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathStylesheetDOM3Exception.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathStylesheetDOM3Exception.java
deleted file mode 100644
index c232003f98e..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/XPathStylesheetDOM3Exception.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code 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
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file and, per its terms, should not be removed:
- *
- * Copyright (c) 2002 World Wide Web Consortium,
- * (Massachusetts Institute of Technology, Institut National de
- * Recherche en Informatique et en Automatique, Keio University). All
- * Rights Reserved. This program is distributed under the W3C's Software
- * Intellectual Property License. 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 W3C License http://www.w3.org/Consortium/Legal/ for more details.
- */
-
-package com.sun.org.apache.xpath.internal.domapi;
-
-import javax.xml.transform.SourceLocator;
-import javax.xml.transform.TransformerException;
-
-/**
- *
- * A new exception to add support for DOM Level 3 XPath API.
- * This class is needed to throw a org.w3c.dom.DOMException with proper error code in
- * createExpression method of XPathEvaluatorImpl (a DOM Level 3 class).
- *
- * This class extends TransformerException because the error message includes information
- * about where the XPath problem is in the stylesheet as well as the XPath expression itself.
- *
- * @xsl.usage internal
- */
-final public class XPathStylesheetDOM3Exception extends TransformerException {
- public XPathStylesheetDOM3Exception(String msg, SourceLocator arg1)
- {
- super(msg, arg1);
- }
-}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/package.html b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/package.html
deleted file mode 100644
index f70d0c4fb25..00000000000
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/domapi/package.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
XPath domapi Package.
-
-
Implements DOM Level 3 XPath API
-
-
-
-
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSS2Properties.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSS2Properties.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSS2Properties.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSS2Properties.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSCharsetRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSCharsetRule.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSCharsetRule.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSCharsetRule.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSFontFaceRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSFontFaceRule.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSFontFaceRule.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSFontFaceRule.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSImportRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSImportRule.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSImportRule.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSImportRule.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSMediaRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSMediaRule.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSMediaRule.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSMediaRule.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSPageRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPageRule.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSPageRule.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPageRule.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSPrimitiveValue.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPrimitiveValue.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSPrimitiveValue.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSPrimitiveValue.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRule.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSRule.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRule.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSRuleList.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRuleList.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSRuleList.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSRuleList.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSStyleDeclaration.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleDeclaration.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSStyleDeclaration.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleDeclaration.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSStyleRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleRule.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSStyleRule.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleRule.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSStyleSheet.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleSheet.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSStyleSheet.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSStyleSheet.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSUnknownRule.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSUnknownRule.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSUnknownRule.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSUnknownRule.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSValue.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValue.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSValue.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValue.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSValueList.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValueList.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/CSSValueList.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/CSSValueList.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/Counter.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Counter.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/Counter.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Counter.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/DOMImplementationCSS.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DOMImplementationCSS.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/DOMImplementationCSS.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DOMImplementationCSS.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/DocumentCSS.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DocumentCSS.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/DocumentCSS.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/DocumentCSS.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/ElementCSSInlineStyle.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ElementCSSInlineStyle.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/ElementCSSInlineStyle.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ElementCSSInlineStyle.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/RGBColor.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/RGBColor.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/RGBColor.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/RGBColor.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/Rect.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Rect.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/Rect.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/Rect.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/css/ViewCSS.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ViewCSS.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/css/ViewCSS.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/css/ViewCSS.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLAnchorElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAnchorElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLAnchorElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAnchorElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLAppletElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAppletElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLAppletElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAppletElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLAreaElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAreaElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLAreaElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLAreaElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLBRElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBRElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLBRElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBRElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLBaseElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLBaseElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLBaseFontElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseFontElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLBaseFontElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBaseFontElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLBodyElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBodyElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLBodyElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLBodyElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLButtonElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLButtonElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLButtonElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLButtonElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLCollection.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLCollection.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLCollection.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLCollection.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDListElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDListElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDListElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDListElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDOMImplementation.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDOMImplementation.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDOMImplementation.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDOMImplementation.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDirectoryElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDirectoryElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDirectoryElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDirectoryElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDivElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDivElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDivElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDivElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDocument.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDocument.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLDocument.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLDocument.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFieldSetElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFieldSetElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFieldSetElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFieldSetElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFontElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFontElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFontElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFontElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFormElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFormElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFormElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFormElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFrameElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFrameElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFrameSetElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameSetElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLFrameSetElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLFrameSetElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLHRElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHRElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLHRElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHRElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLHeadElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLHeadElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLHeadingElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadingElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLHeadingElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHeadingElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLHtmlElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHtmlElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLHtmlElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLHtmlElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLIFrameElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIFrameElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLIFrameElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIFrameElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLImageElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLImageElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLImageElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLImageElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLInputElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLInputElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLInputElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLInputElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLIsIndexElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIsIndexElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLIsIndexElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLIsIndexElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLLIElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLIElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLLIElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLIElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLLabelElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLabelElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLLabelElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLabelElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLLegendElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLegendElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLLegendElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLegendElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLLinkElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLinkElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLLinkElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLLinkElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLMapElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMapElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLMapElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMapElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLMenuElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMenuElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLMenuElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMenuElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLMetaElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMetaElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLMetaElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLMetaElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLModElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLModElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLModElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLModElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLOListElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOListElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLOListElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOListElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLObjectElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLObjectElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLObjectElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLObjectElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLOptGroupElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptGroupElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLOptGroupElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptGroupElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLOptionElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptionElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLOptionElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLOptionElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLParagraphElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParagraphElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLParagraphElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParagraphElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLParamElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParamElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLParamElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLParamElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLPreElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLPreElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLPreElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLPreElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLQuoteElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLQuoteElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLQuoteElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLQuoteElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLScriptElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLScriptElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLScriptElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLScriptElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLSelectElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLSelectElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLSelectElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLSelectElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLStyleElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLStyleElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLStyleElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLStyleElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableCaptionElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCaptionElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableCaptionElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCaptionElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableCellElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCellElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableCellElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableCellElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableColElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableColElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableColElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableColElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableRowElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableRowElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableRowElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableRowElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableSectionElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableSectionElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTableSectionElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTableSectionElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTextAreaElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTextAreaElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTextAreaElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTextAreaElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTitleElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTitleElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLTitleElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLTitleElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLUListElement.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLUListElement.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/html/HTMLUListElement.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/html/HTMLUListElement.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/DocumentStyle.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/DocumentStyle.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/DocumentStyle.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/DocumentStyle.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/LinkStyle.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/LinkStyle.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/LinkStyle.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/LinkStyle.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/MediaList.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/MediaList.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/MediaList.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/MediaList.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/StyleSheet.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheet.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/StyleSheet.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheet.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/StyleSheetList.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheetList.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/stylesheets/StyleSheetList.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/stylesheets/StyleSheetList.java
diff --git a/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/COPYRIGHT.html b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/COPYRIGHT.html
new file mode 100644
index 00000000000..c7e0e497a5f
--- /dev/null
+++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/COPYRIGHT.html
@@ -0,0 +1,106 @@
+
+
+
+ The DOM bindings are published under the W3C Software Copyright Notice
+ and License. The software license requires "Notice of any changes or
+ modifications to the W3C files, including the date changes were made."
+ Consequently, modified versions of the DOM bindings must document that
+ they do not conform to the W3C standard; in the case of the IDL
+ definitions, the pragma prefix can no longer be 'w3c.org'; in the case of
+ the Java language binding, the package names can no longer be in the
+ 'org.w3c' package.
+
+ This W3C work (including software, documents, or other related items) is
+ being provided by the copyright holders under the following license. By
+ obtaining, using and/or copying this work, you (the licensee) agree that
+ you have read, understood, and will comply with the following terms and
+ conditions:
+
+
+ Permission to use, copy, and modify this software and its documentation,
+ with or without modification, for any purpose and without fee or
+ royalty is hereby granted, provided that you include the following on ALL
+ copies of the software and documentation or portions thereof, including
+ modifications, that you make:
+
+
+
+ The full text of this NOTICE in a location viewable to users of the
+ redistributed or derivative work.
+
+ Notice of any changes or modifications to the W3C files, including the
+ date changes were made. (We recommend you provide URIs to the location
+ from which the code is derived.)
+
+
+
+ THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT
+ HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED,
+ INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS
+ FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR
+ DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
+ TRADEMARKS OR OTHER RIGHTS.
+
+
+ COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
+ CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR
+ DOCUMENTATION.
+
+
+ The name and trademarks of copyright holders may NOT be used in
+ advertising or publicity pertaining to the software without specific,
+ written prior permission. Title to copyright in this software and any
+ associated documentation will at all times remain with copyright
+ holders.
+
+
+
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathEvaluator.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathEvaluator.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathEvaluator.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathEvaluator.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathException.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathException.java
similarity index 97%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathException.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathException.java
index 75121d48025..2a13869df45 100644
--- a/jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathException.java
+++ b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathException.java
@@ -47,6 +47,8 @@ package org.w3c.dom.xpath;
*
See also the Document Object Model (DOM) Level 3 XPath Specification.
*/
public class XPathException extends RuntimeException {
+ private static final long serialVersionUID = 3471034171575979943L;
+
public XPathException(short code, String message) {
super(message);
this.code = code;
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathExpression.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathExpression.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathExpression.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathExpression.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathNSResolver.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathNSResolver.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathNSResolver.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathNSResolver.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathNamespace.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathNamespace.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathNamespace.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathNamespace.java
diff --git a/jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathResult.java b/jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathResult.java
similarity index 100%
rename from jaxp/src/java.xml/share/classes/org/w3c/dom/xpath/XPathResult.java
rename to jaxp/src/jdk.xml.dom/share/classes/org/w3c/dom/xpath/XPathResult.java
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/AbstractCharacterDataTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/AbstractCharacterDataTest.java
new file mode 100644
index 00000000000..c1ef1140136
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/AbstractCharacterDataTest.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+import static org.w3c.dom.DOMException.INDEX_SIZE_ERR;
+import static org.w3c.dom.ptests.DOMTestUtil.DOMEXCEPTION_EXPECTED;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.DOMException;
+import org.xml.sax.SAXException;
+
+/*
+ * @summary common test for the CharacterData Interface
+ */
+public abstract class AbstractCharacterDataTest extends JAXPFileBaseTest {
+ @DataProvider(name = "data-for-length")
+ public Object[][] getDataForTestLength() {
+ return new Object[][] {
+ { "", 0 },
+ { "test", 4 } };
+ }
+
+ /*
+ * Verify getLength method works as the spec, for an empty string, should
+ * return zero
+ */
+ @Test(dataProvider = "data-for-length")
+ public void testGetLength(String text, int length) throws Exception {
+ CharacterData cd = createCharacterData(text);
+ assertEquals(cd.getLength(), length);
+
+ }
+
+ /*
+ * Test appendData method and verify by getData method.
+ */
+ @Test
+ public void testAppendData() throws Exception {
+ CharacterData cd = createCharacterData("DOM");
+ cd.appendData("2");
+ assertEquals(cd.getData(), "DOM2");
+
+ }
+
+ @DataProvider(name = "data-for-delete")
+ public Object[][] getDataForTestDelete() {
+ return new Object[][] {
+ { "DOM", 2, 1, "DO" },
+ { "DOM", 0, 2, "M" },
+ { "DOM", 2, 3, "DO" } };
+ }
+
+ /*
+ * Verify deleteData method works as the spec.
+ */
+ @Test(dataProvider = "data-for-delete")
+ public void testDeleteData(String text, int offset, int count, String result) throws Exception {
+ CharacterData cd = createCharacterData(text);
+ cd.deleteData(offset, count);
+ assertEquals(cd.getData(), result);
+ }
+
+ @DataProvider(name = "data-for-replace")
+ public Object[][] getDataForTestReplace() {
+ return new Object[][] {
+ { "DOM", 0, 3, "SAX", "SAX" },
+ { "DOM", 1, 1, "AA", "DAAM" },
+ { "DOM", 1, 2, "A", "DA" },
+ { "DOM", 2, 2, "SAX", "DOSAX" } };
+ }
+
+ /*
+ * Verify replaceData method works as the spec.
+ */
+ @Test(dataProvider = "data-for-replace")
+ public void testReplaceData(String text, int offset, int count, String arg, String result) throws Exception {
+ CharacterData cd = createCharacterData(text);
+ cd.replaceData(offset, count, arg);
+ assertEquals(cd.getData(), result);
+ }
+
+ @DataProvider(name = "data-for-replace-neg")
+ public Object[][] getDataForTestReplaceNeg() {
+ return new Object[][] {
+ { "DOM", -1, 3, "SAX" }, //offset if neg
+ { "DOM", 0, -1, "SAX" }, //count is neg
+ { "DOM", 4, 1, "SAX" } };//offset is greater than length
+ }
+
+ /*
+ * Test for replaceData method: verifies that DOMException with
+ * INDEX_SIZE_ERR is thrown if offset or count is out of the bound.
+ */
+ @Test(dataProvider = "data-for-replace-neg")
+ public void testReplaceDataNeg(String text, int offset, int count, String arg) throws Exception {
+ CharacterData cd = createCharacterData(text);
+ try {
+ cd.replaceData(offset, count, arg);
+ fail(DOMEXCEPTION_EXPECTED);
+ } catch (DOMException e) {
+ assertEquals(e.code, INDEX_SIZE_ERR);
+ }
+ }
+
+ @DataProvider(name = "data-for-insert")
+ public Object[][] getDataForTestInsert() {
+ return new Object[][] {
+ { "DOM", 0, "SAX", "SAXDOM" },
+ { "DOM", 3, "SAX", "DOMSAX" } };
+ }
+
+ /*
+ * Verify insertData method works as the spec.
+ */
+ @Test(dataProvider = "data-for-insert")
+ public void testInsertData(String text, int offset, String arg, String result) throws Exception {
+ CharacterData cd = createCharacterData(text);
+ cd.insertData(offset, arg);
+ assertEquals(cd.getData(), result);
+ }
+
+ @DataProvider(name = "data-for-insert-neg")
+ public Object[][] getDataForTestInsertNeg() {
+ return new Object[][] {
+ { "DOM", -1 }, //offset is neg
+ { "DOM", 4 } };//offset is greater than length
+ }
+
+ /*
+ * Test for insertData method: verifies that DOMException with
+ * INDEX_SIZE_ERR is thrown if offset is out of the bound.
+ */
+ @Test(dataProvider = "data-for-insert-neg")
+ public void testInsertDataNeg(String text, int offset) throws Exception {
+ CharacterData cd = createCharacterData(text);
+ try {
+ cd.insertData(offset, "TEST");
+ fail(DOMEXCEPTION_EXPECTED);
+ } catch (DOMException e) {
+ assertEquals(e.code, INDEX_SIZE_ERR);
+ }
+ }
+
+ /*
+ * Test setData method and verify by getData method.
+ */
+ @Test
+ public void testSetData() throws Exception {
+ CharacterData cd = createCharacterData("DOM");
+ cd.setData("SAX");
+ assertEquals(cd.getData(), "SAX");
+ }
+
+ @DataProvider(name = "data-for-substring")
+ public Object[][] getDataForTestSubstring() {
+ return new Object[][] {
+ { "DOM Level 2", 0, 3, "DOM" },
+ { "DOM", 0, 3, "DOM" },
+ { "DOM", 2, 5, "M" } };
+ }
+
+ /*
+ * Verify substringData method works as the spec.
+ */
+ @Test(dataProvider = "data-for-substring")
+ public void testSubstringData(String text, int offset, int count, String result) throws Exception {
+ CharacterData cd = createCharacterData(text);
+ String retStr = cd.substringData(offset, count);
+ assertEquals(retStr, result);
+ }
+
+ @DataProvider(name = "data-for-substring-neg")
+ public Object[][] getDataForTestSubstringNeg() {
+ return new Object[][] {
+ { "DOM Level 2", -1, 3 }, //offset is neg
+ { "DOM", 0, -1 }, //count is neg
+ { "DOM", 3, 1 } }; //offset exceeds length
+ }
+
+ /*
+ * Test for substringData method: verifies that DOMException with
+ * INDEX_SIZE_ERR is thrown if offset or count is out of the bound.
+ */
+ @Test(dataProvider = "data-for-substring-neg")
+ public void testSubstringDataNeg(String text, int offset, int count) throws Exception {
+ CharacterData cd = createCharacterData(text);
+ try {
+ cd.substringData(offset, count);
+ fail(DOMEXCEPTION_EXPECTED);
+ } catch (DOMException e) {
+ assertEquals(e.code, INDEX_SIZE_ERR);
+ }
+
+ }
+
+ /*
+ * Return a concrete CharacterData instance.
+ */
+ abstract protected CharacterData createCharacterData(String text) throws IOException, SAXException, ParserConfigurationException;
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/AttrTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/AttrTest.java
new file mode 100644
index 00000000000..b166c307a81
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/AttrTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOM;
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+
+
+/*
+ * @summary Test for the Attr Interface
+ */
+public class AttrTest extends JAXPFileBaseTest {
+ /*
+ * Verify getName method against both existing Attr and new Attr.
+ */
+ @Test
+ public void testGetName() throws Exception {
+ Document document = createDOM("Attr01.xml");
+ //test a new created Attr
+ Attr attr = document.createAttribute("newAttribute");
+ assertEquals(attr.getName(), "newAttribute");
+
+ //test a Attr loaded from xml file
+ Element elemNode = (Element) document.getElementsByTagName("book").item(1);
+ Attr attr2 = (Attr) elemNode.getAttributes().item(0);
+ assertEquals(attr2.getName(), "category1");
+ }
+
+ /*
+ * Verify getOwnerElement method against both existing Attr and new Attr.
+ */
+ @Test
+ public void testGetOwnerElement() throws Exception {
+ Document document = createDOM("Attr01.xml");
+
+ //test Attr loaded from xml file
+ Element elemNode = (Element) document.getElementsByTagName("book").item(1);
+ NamedNodeMap nnMap = elemNode.getAttributes();
+ for (int i = 0; i < nnMap.getLength(); i++) {
+ Attr attr = (Attr) nnMap.item(i);
+ assertEquals(attr.getOwnerElement().getNodeName(), "book");
+ }
+
+ //test an Attr without owner node
+ Attr attr = document.createAttribute("newAttribute");
+ assertNull(attr.getOwnerElement());
+
+ }
+
+ /*
+ * Verify getSpecified method works as the spec.
+ */
+ @Test
+ public void testGetSpecified1() throws Exception {
+ Document document = createDOM("Attr01.xml");
+
+ Element elemNode = (Element) document.getElementsByTagName("book").item(1);
+ Attr attr = elemNode.getAttributeNode("category1");
+ assertTrue(attr.getSpecified());
+
+ }
+
+ /*
+ * In this xml file, the dtd has the value for the attrribute, but the xml
+ * element does not specify the value for the attrribute, as per the spec it
+ * should return false.
+ */
+ @Test
+ public void testGetSpecified2() throws Exception {
+
+ Document document = createDOM("Attr2.xml");
+ Element elemNode = (Element) document.getElementsByTagName("Name").item(0);
+ Attr attr = elemNode.getAttributeNode("type");
+
+ assertFalse(attr.getSpecified());
+ }
+
+ /*
+ * Creating a new attribute, the owner element is null since the attribute
+ * has just been created, getSpecified should return true.
+ */
+ @Test
+ public void testNewCreatedAttribute() throws Exception {
+ Document document = createDOM("Attr01.xml");
+ Attr attr = document.createAttribute("newAttribute");
+ assertTrue(attr.getSpecified());
+ assertNull(attr.getOwnerElement());
+
+ }
+
+ /*
+ * The xml file includes the dtd having the IMPLIED value for the attrribute
+ * and the xml element does not specify the value. As per the spec it should
+ * not be seen as a part of the structure model hence getAttributeNode
+ * rerurn null if the attribute is even found.
+ */
+ @Test
+ public void testIMPLIEDAttribute() throws Exception {
+ Document document = createDOM("Attr3.xml");
+ Element elemNode = (Element) document.getElementsByTagName("Name").item(0);
+ Attr attr = elemNode.getAttributeNode("type");
+ assertNull(attr);
+ }
+
+ /*
+ * Test setValue method and verify by getValue method.
+ */
+ @Test
+ public void testSetValue() throws Exception {
+ Document document = createDOM("Attr01.xml");
+ Attr attr = document.createAttribute("newAttribute");
+ attr.setValue("newVal");
+ assertEquals(attr.getValue(), "newVal");
+
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/CommentTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/CommentTest.java
new file mode 100644
index 00000000000..daf585bf09b
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/CommentTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.w3c.dom.ptests.DOMTestUtil.createNewDocument;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/*
+ * @summary Test for Comment implementation returned by Document.createComment(String)
+ */
+public class CommentTest extends AbstractCharacterDataTest {
+ @Override
+ protected CharacterData createCharacterData(String text) throws IOException, SAXException, ParserConfigurationException {
+ Document document = createNewDocument();
+ return document.createComment(text);
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DocumentTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DocumentTest.java
new file mode 100644
index 00000000000..90dd8cc64a8
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DocumentTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
+import static javax.xml.XMLConstants.XML_NS_URI;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+import static org.w3c.dom.DOMException.NAMESPACE_ERR;
+import static org.w3c.dom.ptests.DOMTestUtil.DOMEXCEPTION_EXPECTED;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOMWithNS;
+import static org.w3c.dom.ptests.DOMTestUtil.createNewDocument;
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/*
+ * @summary Test createAttributeNS, getElementsByTagNameNS and createElementNS method of Document
+ */
+public class DocumentTest extends JAXPFileBaseTest {
+
+ @DataProvider(name = "invalid-nsuri")
+ public Object[][] getInvalidNamespaceURI() {
+ return new Object[][] {
+ { " ", "xml:novel" }, //blank
+ { "hello", "xml:novel" }, //unqualified
+ { null, "xml:novel" }, //null
+ { "", "xmlns:novel" } };//empty
+ }
+
+ /*
+ * Test for createAttributeNS method: verifies that DOMException is thrown
+ * if reserved prefixes are used with an arbitrary namespace name.
+ */
+ @Test(dataProvider = "invalid-nsuri", expectedExceptions = DOMException.class)
+ public void testCreateAttributeNSNeg(String namespaceURI, String name) throws Exception {
+ Document document = createDOMWithNS("DocumentTest01.xml");
+ document.createAttributeNS(namespaceURI, name);
+ }
+
+ @DataProvider(name = "valid-nsuri")
+ public Object[][] getValidNamespaceURI() {
+ return new Object[][] {
+ { XML_NS_URI, "xml:novel" },
+ { XMLNS_ATTRIBUTE_NS_URI, "xmlns:novel" },
+ { "urn:BooksAreUs.org:BookInfo", "attributeNew"},
+ { "urn:BooksAreUs.org:BookInfonew", "attributeNew"} };
+ }
+
+ /*
+ * Verify the Attr from createAttributeNS.
+ */
+ @Test(dataProvider = "valid-nsuri")
+ public void testCreateAttributeNS(String namespaceURI, String name) throws Exception {
+ Document document = createDOMWithNS("DocumentTest01.xml");
+ Attr attr = document.createAttributeNS(namespaceURI, name);
+ assertEquals(attr.getNamespaceURI(), namespaceURI);
+ assertEquals(attr.getName(), name);
+ }
+
+ @DataProvider(name = "elementName")
+ public Object[][] getElementName() {
+ return new Object[][] {
+ { "author", 1 },
+ { "b:author", 0 } };
+ }
+
+ /*
+ * Verify the NodeList from getElementsByTagNameNS.
+ */
+ @Test(dataProvider = "elementName")
+ public void testGetElementsByTagNameNS(String localName, int number) throws Exception {
+ Document document = createDOMWithNS("DocumentTest01.xml");
+ NodeList nodeList = document.getElementsByTagNameNS("urn:BooksAreUs.org:BookInfo", localName);
+ assertEquals(nodeList.getLength(), number);
+ }
+
+ /*
+ * Test for createElementNS method: verifies that DOMException is thrown
+ * if reserved prefixes are used with an arbitrary namespace name.
+ */
+ @Test(dataProvider = "invalid-nsuri")
+ public void testCreateElementNSNeg(String namespaceURI, String name) throws Exception {
+ Document document = createDOMWithNS("DocumentTest01.xml");
+ try {
+ document.createElementNS(namespaceURI, name);
+ fail(DOMEXCEPTION_EXPECTED);
+ } catch (DOMException e) {
+ assertEquals(e.code, NAMESPACE_ERR);
+ }
+ }
+
+ /*
+ * Test createElementNS method works as the spec.
+ */
+ @Test
+ public void testCreateElementNS() throws Exception {
+ final String nsURI = "http://www.books.com";
+ final String name = "b:novel";
+ final String localName = "novel";
+ Document document = createDOMWithNS("DocumentTest01.xml");
+ Element element = document.createElementNS(nsURI, name);
+ assertEquals(element.getNamespaceURI(), nsURI);
+ assertEquals(element.getNodeName(), name);
+ assertEquals(element.getLocalName(), localName);
+ }
+
+ /*
+ * Test createAttributeNS and then append it with setAttributeNode.
+ */
+ @Test
+ public void testAddNewAttributeNode() throws Exception {
+ Document document = createDOMWithNS("DocumentTest01.xml");
+
+ NodeList nodeList = document.getElementsByTagNameNS("http://www.w3.org/TR/REC-html40", "body");
+ NodeList childList = nodeList.item(0).getChildNodes();
+ Element child = (Element) childList.item(1);
+ Attr a = document.createAttributeNS("urn:BooksAreUs.org:BookInfo", "attributeNew");
+ child.setAttributeNode(a);
+ assertNotNull(child.getAttributeNodeNS("urn:BooksAreUs.org:BookInfo", "attributeNew"));
+ }
+
+ /*
+ * Test createElementNS and then append it with appendChild.
+ */
+ @Test
+ public void testAddNewElement() throws Exception {
+ Document document = createDOMWithNS("DocumentTest01.xml");
+
+ NodeList nodeList = document.getElementsByTagNameNS("http://www.w3.org/TR/REC-html40", "body");
+ NodeList childList = nodeList.item(0).getChildNodes();
+ Element child = (Element) childList.item(1);
+ Element elem = document.createElementNS("urn:BooksAreUs.org:BookInfonew", "newElement");
+ assertNotNull(child.appendChild(elem));
+ }
+
+ /*
+ * Test createElement with unqualified xml name.
+ */
+ @Test(expectedExceptions = DOMException.class)
+ public void testCreateElementNeg() throws Exception {
+ Document doc = createNewDocument();
+ doc.createElement("!nc$%^*(!");
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DocumentTypeTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DocumentTypeTest.java
new file mode 100644
index 00000000000..d260d1f7c8e
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DocumentTypeTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOM;
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import org.w3c.dom.DocumentType;
+import org.w3c.dom.NamedNodeMap;
+
+/*
+ * @summary Test DocumentType
+ */
+public class DocumentTypeTest extends JAXPFileBaseTest {
+
+ /*
+ * Test testGetEntities method, and verify the entity items.
+ */
+ @Test
+ public void testGetEntities() throws Exception {
+ DocumentType documentType = createDOM("DocumentType01.xml").getDoctype();
+ NamedNodeMap namedNodeMap = documentType.getEntities();
+ // should return both external and internal. Parameter entities are not
+ // contained. Duplicates are discarded.
+ assertEquals(namedNodeMap.getLength(), 3);
+ assertEquals(namedNodeMap.item(0).getNodeName(), "author");
+ assertEquals(namedNodeMap.item(1).getNodeName(), "test");
+ assertEquals(namedNodeMap.item(2).getNodeName(), "writer");
+ }
+
+ /*
+ * Test getNotations method, and verify the notation items.
+ */
+ @Test
+ public void testGetNotations() throws Exception {
+ DocumentType documentType = createDOM("DocumentType03.xml").getDoctype();
+ NamedNodeMap nm = documentType.getNotations();
+ assertEquals(nm.getLength(), 2); // should return 2 because the notation
+ // name is repeated and
+ // it considers only the first
+ // occurence
+ assertEquals(nm.item(0).getNodeName(), "gs");
+ assertEquals(nm.item(1).getNodeName(), "name");
+ }
+
+ /*
+ * Test getName method.
+ */
+ @Test
+ public void testGetName() throws Exception {
+ DocumentType documentType = createDOM("DocumentType03.xml").getDoctype();
+ assertEquals(documentType.getName(), "note");
+ }
+
+ /*
+ * Test getSystemId and getPublicId method.
+ */
+ @Test
+ public void testGetSystemId() throws Exception {
+ DocumentType documentType = createDOM("DocumentType05.xml").getDoctype();
+ assertEquals(documentType.getSystemId(), "DocumentBuilderImpl02.dtd");
+ Assert.assertNull(documentType.getPublicId());
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DomImplementationTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DomImplementationTest.java
new file mode 100644
index 00000000000..fb6ec4b5ea4
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/DomImplementationTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.w3c.dom.ptests.DOMTestUtil.createNewDocument;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+
+/*
+ * @summary Test DomImplementation API
+ */
+public class DomImplementationTest extends JAXPBaseTest {
+ /*
+ * Test createDocument method with a namespace uri, qualified name and null
+ * for the doctype
+ */
+ @Test
+ public void testCreateDocument() throws ParserConfigurationException {
+ final String nsURI = "http://www.document.com";
+ final String name = "document:localName";
+ DOMImplementation domImpl = getDOMImplementation();
+ Document document = domImpl.createDocument(nsURI, name, null);
+ assertEquals(document.getDocumentElement().getNamespaceURI(), nsURI);
+ assertEquals(document.getDocumentElement().getNodeName(), name);
+ }
+
+ /*
+ * Test createDocumentType method with name, public id and system id.
+ */
+ @Test
+ public void testCreateDocumentType01() throws ParserConfigurationException {
+ final String name = "document:localName";
+ final String publicId = "pubid";
+ final String systemId = "sysid";
+
+ DOMImplementation domImpl = getDOMImplementation();
+ DocumentType documentType = domImpl.createDocumentType(name, publicId, systemId);
+ verifyDocumentType(documentType, name, publicId, systemId);
+ }
+
+
+ /*
+ * Test createDocument method using a DocumentType, verify the document will
+ * take that Doctype.
+ */
+ @Test
+ public void testCreateDocumentType02() throws ParserConfigurationException {
+ final String name = "document:localName";
+ final String publicId = "-//W3C//DTD HTML 4.0 Transitional//EN";
+ final String systemId = "http://www.w3.org/TR/REC-html40/loose.dtd";
+ DOMImplementation domImpl = getDOMImplementation();
+
+ DocumentType documentType = domImpl.createDocumentType(name, publicId, systemId);
+ Document document = domImpl.createDocument("http://www.document.com", "document:localName", documentType);
+ verifyDocumentType(document.getDoctype(), name, publicId, systemId);
+ }
+
+ @DataProvider(name = "feature-supported")
+ public Object[][] getFeatureSupportedList() throws ParserConfigurationException {
+ DOMImplementation impl = getDOMImplementation();
+ return new Object[][] {
+ { impl, "XML", "2.0", true },
+ { impl, "HTML", "2.0", false },
+ { impl, "Views", "2.0", false },
+ { impl, "StyleSheets", "2.0", false },
+ { impl, "CSS", "2.0", false },
+ { impl, "CSS2", "2.0", false },
+ { impl, "Events", "2.0", true },
+ { impl, "UIEvents", "2.0", false },
+ { impl, "MouseEvents", "2.0", false },
+ { impl, "HTMLEvents", "2.0", false },
+ { impl, "Traversal", "2.0", true },
+ { impl, "Range", "2.0", true },
+ { impl, "Core", "2.0", true },
+ { impl, "XML", "", true } };
+ }
+
+
+ /*
+ * Verify DOMImplementation for feature supporting.
+ */
+ @Test(dataProvider = "feature-supported")
+ public void testHasFeature(DOMImplementation impl, String feature, String version, boolean isSupported) {
+ assertEquals(impl.hasFeature(feature,version), isSupported);
+ }
+
+
+ private DOMImplementation getDOMImplementation() throws ParserConfigurationException {
+ return createNewDocument().getImplementation();
+ }
+
+
+ private void verifyDocumentType(DocumentType documentType, String name, String publicId, String systemId) {
+ assertEquals(documentType.getPublicId(), publicId);
+ assertEquals(documentType.getSystemId(), systemId);
+ assertEquals(documentType.getName(), name);
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/ElementTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/ElementTest.java
new file mode 100644
index 00000000000..2e4841f438a
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/ElementTest.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static javax.xml.XMLConstants.XML_NS_URI;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+import static org.w3c.dom.DOMException.INUSE_ATTRIBUTE_ERR;
+import static org.w3c.dom.ptests.DOMTestUtil.DOMEXCEPTION_EXPECTED;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOM;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOMWithNS;
+import static org.w3c.dom.ptests.DOMTestUtil.createNewDocument;
+
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/*
+ * @summary Test for the methods of Element Interface
+ */
+public class ElementTest extends JAXPFileBaseTest {
+ @Test
+ public void testGetAttributeNS() throws Exception {
+ Document document = createDOMWithNS("ElementSample01.xml");
+ Element elemNode = (Element) document.getElementsByTagName("book").item(0);
+ String s = elemNode.getAttributeNS("urn:BooksAreUs.org:BookInfo", "category");
+ assertEquals(s, "research");
+ }
+
+ @Test
+ public void testGetAttributeNodeNS() throws Exception {
+ Document document = createDOMWithNS("ElementSample01.xml");
+ Element elemNode = (Element) document.getElementsByTagName("book").item(0);
+ Attr attr = elemNode.getAttributeNodeNS("urn:BooksAreUs.org:BookInfo", "category");
+ assertEquals(attr.getValue(), "research");
+
+ }
+
+ /*
+ * Test getAttributeNode to get a Attr and then remove it successfully by
+ * removeAttributeNode.
+ */
+ @Test
+ public void testRemoveAttributeNode() throws Exception {
+ Document document = createDOMWithNS("ElementSample01.xml");
+ Element elemNode = (Element) document.getElementsByTagName("book").item(1);
+ Attr attr = elemNode.getAttributeNode("category1");
+ assertEquals(attr.getValue(), "research");
+
+ assertEquals(elemNode.getTagName(), "book");
+ elemNode.removeAttributeNode(attr);
+ assertEquals(elemNode.getAttribute("category1"), "");
+ }
+
+ /*
+ * Test removing an Attribute Node with removeAttributeNS(String
+ * namespaceURI, String localName).
+ */
+ @Test
+ public void testRemoveAttributeNS() throws Exception {
+ final String nsURI = "urn:BooksAreUs.org:BookInfo";
+ final String localName = "category";
+ Document document = createDOMWithNS("ElementSample01.xml");
+ Element elemNode = (Element) document.getElementsByTagName("book").item(0);
+ elemNode.removeAttributeNS(nsURI, localName);
+
+ assertNull(elemNode.getAttributeNodeNS(nsURI, localName));
+ }
+
+ /*
+ * Test getFirstChild and getLastChild.
+ */
+ @Test
+ public void testGetChild() throws Exception {
+ Document document = createDOMWithNS("ElementSample01.xml");
+ Element elemNode = (Element) document.getElementsByTagName("b:aaa").item(0);
+ elemNode.normalize();
+ Node firstChild = elemNode.getFirstChild();
+ Node lastChild = elemNode.getLastChild();
+ assertEquals(firstChild.getNodeValue(), "fjfjf");
+ assertEquals(lastChild.getNodeValue(), "fjfjf");
+ }
+
+ /*
+ * Test setAttributeNode with an Attr from createAttribute.
+ */
+ @Test
+ public void testSetAttributeNode() throws Exception {
+ final String attrName = "myAttr";
+ final String attrValue = "attrValue";
+ Document document = createDOM("ElementSample02.xml");
+ Element elemNode = document.createElement("pricetag2");
+ Attr myAttr = document.createAttribute(attrName);
+ myAttr.setValue(attrValue);
+
+ assertNull(elemNode.setAttributeNode(myAttr));
+ assertEquals(elemNode.getAttribute(attrName), attrValue);
+ }
+
+ @DataProvider(name = "attribute")
+ public Object[][] getAttributeData() {
+ return new Object[][] {
+ { "thisisname", "thisisitsvalue" },
+ { "style", "font-Family" } };
+ }
+
+ @Test(dataProvider = "attribute")
+ public void testSetAttribute(String name, String value) throws Exception {
+ Document document = createDOM("ElementSample02.xml");
+ Element elemNode = document.createElement("pricetag2");
+ elemNode.setAttribute(name, value);
+ assertEquals(elemNode.getAttribute(name), value);
+ }
+
+ /*
+ * Negative test for setAttribute, null is not a valid name.
+ */
+ @Test(expectedExceptions = DOMException.class)
+ public void testSetAttributeNeg() throws Exception {
+ Document document = createDOM("ElementSample02.xml");
+ Element elemNode = document.createElement("pricetag2");
+ elemNode.setAttribute(null, null);
+ }
+
+ /*
+ * Test setAttributeNode, newAttr can't be an attribute of another Element
+ * object, must explicitly clone Attr nodes to re-use them in other
+ * elements.
+ */
+ @Test
+ public void testDuplicateAttributeNode() throws Exception {
+ final String name = "testAttrName";
+ final String value = "testAttrValue";
+ Document document = createNewDocument();
+ Attr attr = document.createAttribute(name);
+ attr.setValue(value);
+
+ Element element1 = document.createElement("AFirstElement");
+ element1.setAttributeNode(attr);
+ Element element2 = document.createElement("ASecondElement");
+ Attr attr2 = (Attr) attr.cloneNode(true);
+ element2.setAttributeNode(attr2);
+ assertEquals(element1.getAttribute(name), element2.getAttribute(name));
+
+ Element element3 = document.createElement("AThirdElement");
+ try {
+ element3.setAttributeNode(attr);
+ fail(DOMEXCEPTION_EXPECTED);
+ } catch (DOMException doe) {
+ assertEquals(doe.code, INUSE_ATTRIBUTE_ERR);
+ }
+ }
+
+ /*
+ * If not setting the namsepace aware method of DocumentBuilderFactory to
+ * true, can't retrieve element by namespace and local name.
+ */
+ @Test
+ public void testNamespaceAware() throws Exception {
+ Document document = createDOM("ElementSample02.xml");
+
+ NodeList nl = document.getElementsByTagNameNS("urn:BooksAreUs.org:BookInfo", "author");
+ assertNull(nl.item(0));
+
+ nl = document.getDocumentElement().getElementsByTagNameNS("urn:BooksAreUs.org:BookInfo", "author");
+ assertNull(nl.item(0));
+ }
+
+ @DataProvider(name = "nsattribute")
+ public Object[][] getNSAttributeData() {
+ return new Object[][] {
+ { "h:html", "html", "attrValue" },
+ { "b:style", "style", "attrValue" } };
+ }
+
+ /*
+ * setAttributeNodeNS and verify it with getAttributeNS.
+ */
+ @Test(dataProvider = "nsattribute")
+ public void testSetAttributeNodeNS(String qualifiedName, String localName, String value) throws Exception {
+ Document document = createDOM("ElementSample03.xml");
+ Element elemNode = document.createElement("pricetag2");
+ Attr myAttr = document.createAttributeNS(XML_NS_URI, qualifiedName);
+ myAttr.setValue(value);
+ assertNull(elemNode.setAttributeNodeNS(myAttr));
+ assertEquals(elemNode.getAttributeNS(XML_NS_URI, localName), value);
+ }
+
+ @Test
+ public void testHasAttributeNS() throws Exception {
+ Document document = createDOMWithNS("ElementSample04.xml");
+ NodeList nodeList = document.getElementsByTagName("body");
+ NodeList childList = nodeList.item(0).getChildNodes();
+ Element child = (Element) childList.item(7);
+ assertTrue(child.hasAttributeNS("urn:BooksAreUs.org:BookInfo", "style"));
+ }
+
+ @Test
+ public void testToString() throws Exception {
+ final String xml =
+ ""
+ + ""
+ + ""
+ + " \n"
+ + " "
+ + " "
+ + "";
+
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
+ Element root = doc.getDocumentElement();
+
+ assertEquals(root.toString(), "[datacenterlist: null]");
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/EntityChildTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/EntityChildTest.java
new file mode 100644
index 00000000000..099b7c1fc83
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/EntityChildTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.w3c.dom.ptests.DOMTestUtil.XML_DIR;
+
+import java.io.File;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/*
+ * @summary Test DOM Parser: parsing an xml file that contains external entities.
+ */
+public class EntityChildTest extends JAXPFileBaseTest {
+
+ @Test
+ public void test() throws Exception {
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setValidating(true);
+ DocumentBuilder docBuilder = dbf.newDocumentBuilder();
+ Document document = docBuilder.parse(new File(XML_DIR + "entitychild.xml"));
+
+ Element root = document.getDocumentElement();
+ NodeList n = root.getElementsByTagName("table");
+ NodeList nl = n.item(0).getChildNodes();
+ assertEquals(n.getLength(), 1);
+ assertEquals(nl.getLength(), 3);
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NamedNodeMapTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NamedNodeMapTest.java
new file mode 100644
index 00000000000..49037f80c88
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NamedNodeMapTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOMWithNS;
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/*
+ * @summary Test for the methods of NamedNodeMap Interface
+ */
+public class NamedNodeMapTest extends JAXPFileBaseTest {
+ /*
+ * Test setNamedItemNS method with a node having the same namespaceURI and
+ * qualified name as an existing one, and then test with a non-existing node.
+ */
+ @Test
+ public void testSetNamedItemNS() throws Exception {
+ final String nsURI = "urn:BooksAreUs.org:BookInfo";
+ Document document = createDOMWithNS("NamedNodeMap01.xml");
+ NodeList nodeList = document.getElementsByTagName("body");
+ nodeList = nodeList.item(0).getChildNodes();
+ Node n = nodeList.item(3);
+
+ NamedNodeMap namedNodeMap = n.getAttributes();
+
+ // creating an Attribute using createAttributeNS
+ // method having the same namespaceURI
+ // and the same qualified name as the existing one in the xml file
+ Attr attr = document.createAttributeNS(nsURI, "b:style");
+ // setting to a new Value
+ attr.setValue("newValue");
+ Node replacedAttr = namedNodeMap.setNamedItemNS(attr); // return the replaced attr
+ assertEquals(replacedAttr.getNodeValue(), "font-family");
+ Node updatedAttr = namedNodeMap.getNamedItemNS(nsURI, "style");
+ assertEquals(updatedAttr.getNodeValue(), "newValue");
+
+
+ // creating a non existing attribute node
+ attr = document.createAttributeNS(nsURI, "b:newNode");
+ attr.setValue("newValue");
+
+ assertNull(namedNodeMap.setNamedItemNS(attr)); // return null
+
+ // checking if the node could be accessed
+ // using the getNamedItemNS method
+ Node newAttr = namedNodeMap.getNamedItemNS(nsURI, "newNode");
+ assertEquals(newAttr.getNodeValue(), "newValue");
+ }
+
+ /*
+ * Verify getNamedItemNS works as the spec
+ */
+ @Test
+ public void testGetNamedItemNS() throws Exception {
+ Document document = createDOMWithNS("NamedNodeMap03.xml");
+ NodeList nodeList = document.getElementsByTagName("body");
+ nodeList = nodeList.item(0).getChildNodes();
+ Node n = nodeList.item(7);
+ NamedNodeMap namedNodeMap = n.getAttributes();
+ Node node = namedNodeMap.getNamedItemNS("urn:BooksAreUs.org:BookInfo", "aaa");
+ assertEquals(node.getNodeValue(), "value");
+
+ }
+
+ /*
+ * Test setNamedItem method with a node having the same name as an existing
+ * one, and then test with a non-existing node.
+ */
+ @Test
+ public void testSetNamedItem() throws Exception {
+ Document document = createDOMWithNS("NamedNodeMap03.xml");
+ NodeList nodeList = document.getElementsByTagName("body");
+ nodeList = nodeList.item(0).getChildNodes();
+ Node n = nodeList.item(1);
+
+ NamedNodeMap namedNodeMap = n.getAttributes();
+ Attr attr = document.createAttribute("name");
+ Node replacedAttr = namedNodeMap.setNamedItem(attr);
+ assertEquals(replacedAttr.getNodeValue(), "attributeValue");
+ Node updatedAttrNode = namedNodeMap.getNamedItem("name");
+ assertEquals(updatedAttrNode.getNodeValue(), "");
+
+ Attr newAttr = document.createAttribute("nonExistingName");
+ assertNull(namedNodeMap.setNamedItem(newAttr));
+ Node newAttrNode = namedNodeMap.getNamedItem("nonExistingName");
+ assertEquals(newAttrNode.getNodeValue(), "");
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NodeListTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NodeListTest.java
new file mode 100644
index 00000000000..4aa51f76665
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NodeListTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOM;
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/*
+ * @summary Verifies a bug found in jaxp1.0.1 and 1.1FCS. After going out of
+ * bound, the last element of a NodeList returns null. The bug has been fixed
+ * in jaxp 1.1.1 build.
+ */
+public class NodeListTest extends JAXPFileBaseTest {
+
+ @DataProvider(name = "xml")
+ public Object[][] getTestData() {
+ return new Object[][] { { "nodelist.xml", "document" }, { "Node01.xml", "body" } };
+ }
+
+ @Test(dataProvider = "xml")
+ public void lastItemTest(String xmlFileName, String nodeName) throws Exception {
+ Document document = createDOM(xmlFileName);
+
+ NodeList nl = document.getElementsByTagName(nodeName);
+ int n = nl.getLength();
+
+ Element elem1 = (Element) nl.item(n - 1);
+ nl.item(n);
+ Element elem3 = (Element) nl.item(n - 1);
+ assertEquals(elem3, elem1);
+
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NodeTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NodeTest.java
new file mode 100644
index 00000000000..dddc2ce24b0
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NodeTest.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static jaxp.library.JAXPTestUtilities.compareWithGold;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertTrue;
+import static org.w3c.dom.ptests.DOMTestUtil.GOLDEN_DIR;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOM;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOMWithNS;
+import static org.w3c.dom.ptests.DOMTestUtil.createNewDocument;
+
+import java.io.File;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/*
+ * @summary Test Node interface
+ */
+public class NodeTest extends JAXPFileBaseTest {
+ @DataProvider(name = "feature-supported")
+ public Object[][] getFeatureSupportedList() throws Exception {
+ Document document = createDOMWithNS("Node01.xml");
+ Node node = document.getElementsByTagName("body").item(0);
+ return new Object[][] {
+ { node, "XML", "2.0", true },
+ { node, "HTML", "2.0", false },
+ { node, "Views", "2.0", false },
+ { node, "StyleSheets", "2.0", false },
+ { node, "CSS", "2.0", false },
+ { node, "CSS2", "2.0", false },
+ { node, "Events", "2.0", true },
+ { node, "UIEvents", "2.0", false },
+ { node, "MouseEvents", "2.0", false },
+ { node, "HTMLEvents", "2.0", false },
+ { node, "Traversal", "2.0", true },
+ { node, "Range", "2.0", true } };
+ }
+
+ /*
+ * Verify Node for feature supporting.
+ */
+ @Test(dataProvider = "feature-supported")
+ public void testHasFeature(Node node, String feature, String version, boolean supported) {
+ assertEquals(node.isSupported(feature, version), supported);
+ }
+
+ /*
+ * Test normalize method will merge adjacent Text nodes.
+ */
+ @Test
+ public void testNormalize() throws Exception {
+ Document document = createDOM("Node05.xml");
+
+ Element root = document.getDocumentElement();
+
+ Node node = document.getElementsByTagName("title").item(0);
+ node.appendChild(document.createTextNode("test"));
+ root.normalize();
+ assertEquals(node.getChildNodes().item(0).getNodeValue(), "Typographytest");
+ }
+
+ /*
+ * Test cloneNode deeply, and the clone node can be appended on the same document.
+ */
+ @Test
+ public void testCloneNode() throws Exception {
+ Document document = createDOMWithNS("Node02.xml");
+
+ NodeList nodeList = document.getElementsByTagName("body");
+ Node node = nodeList.item(0);
+ Node cloneNode = node.cloneNode(true);
+
+ assertTrue(node.isEqualNode(cloneNode));
+ assertNotEquals(node, cloneNode);
+
+ nodeList = document.getElementsByTagName("html");
+ Node node2 = nodeList.item(0);
+ node2.appendChild(cloneNode);
+ }
+
+ /*
+ * Test importing node from one document to another.
+ */
+ @Test
+ public void testImportNode() throws Exception {
+ Document document = createDOMWithNS("Node02.xml");
+ Document otherDocument = createDOMWithNS("ElementSample01.xml");
+
+ NodeList otherNodeList = otherDocument.getElementsByTagName("body");
+ Node importedNode = otherNodeList.item(0);
+ Node clone = importedNode.cloneNode(true);
+
+ Node retNode = document.importNode(importedNode, true);
+ assertTrue(clone.isEqualNode(importedNode)); //verify importedNode is not changed
+ assertNotEquals(retNode, importedNode);
+ assertTrue(importedNode.isEqualNode(retNode));
+
+ retNode = document.importNode(importedNode, false);
+ assertTrue(clone.isEqualNode(importedNode)); //verify importedNode is not changed
+ assertEquals(retNode.getNodeName(), importedNode.getNodeName());
+ assertFalse(importedNode.isEqualNode(retNode));
+ }
+
+ /*
+ * Test inserting a document fragment before a particular node.
+ */
+ @Test
+ public void testInsertBefore() throws Exception {
+ Document document = createDOM("Node04.xml");
+
+ Element parentElement = (Element) document.getElementsByTagName("to").item(0);
+ Element element = (Element) document.getElementsByTagName("sender").item(0);
+ parentElement.insertBefore(createTestDocumentFragment(document), element);
+
+ String outputfile = "InsertBefore.out";
+ String goldfile = GOLDEN_DIR + "InsertBeforeGF.out";
+ outputXml(document, outputfile);
+ assertTrue(compareWithGold(goldfile, outputfile));
+ }
+
+
+ /*
+ * Test replacing a particular node with a document fragment.
+ */
+ @Test
+ public void testReplaceChild() throws Exception {
+ Document document = createDOM("Node04.xml");
+
+ Element parentElement = (Element) document.getElementsByTagName("to").item(0);
+ Element element = (Element) document.getElementsByTagName("sender").item(0);
+ parentElement.replaceChild(createTestDocumentFragment(document), element);
+
+ String outputfile = "ReplaceChild3.out";
+ String goldfile = GOLDEN_DIR + "ReplaceChild3GF.out";
+ outputXml(document, outputfile);
+ assertTrue(compareWithGold(goldfile, outputfile));
+ }
+
+ /*
+ * This test case checks for the replaceChild replacing a particular node
+ * with a node which was created from a different document than the one
+ * which is trying to use this method. It should throw a DOMException.
+ */
+ @Test(expectedExceptions = DOMException.class)
+ public void testReplaceChildNeg() throws Exception {
+ Document document = createDOM("Node04.xml");
+ Document doc2 = createNewDocument();
+
+ Element parentElement = (Element) document.getElementsByTagName("to").item(0);
+ Element element = (Element) document.getElementsByTagName("sender").item(0);
+ parentElement.replaceChild(createTestDocumentFragment(doc2), element);
+ }
+
+ private DocumentFragment createTestDocumentFragment(Document document) {
+ DocumentFragment docFragment = document.createDocumentFragment();
+ Element elem = document.createElement("dfElement");
+ elem.appendChild(document.createTextNode("Text in it"));
+ docFragment.appendChild(elem);
+ return docFragment;
+ }
+
+ private void outputXml(Document document, String outputFileName) throws TransformerFactoryConfigurationError, TransformerException {
+ DOMSource domSource = new DOMSource(document);
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ StreamResult streamResult = new StreamResult(new File(outputFileName));
+ transformer.transform(domSource, streamResult);
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NotationTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NotationTest.java
new file mode 100644
index 00000000000..eea6ab41b47
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/NotationTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOM;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Notation;
+import org.xml.sax.SAXException;
+
+/*
+ * @summary Test for Notation interface
+ */
+public class NotationTest extends JAXPFileBaseTest {
+ /*
+ * Test getSystemId method.
+ */
+ @Test
+ public void testGetSystemId() throws Exception {
+ assertEquals(findNotation("gs").getSystemId(), "http://who.knows.where/");
+ }
+
+ /*
+ * Test getPublicId method.
+ */
+ @Test
+ public void testGetPublicId() throws Exception {
+ assertEquals(findNotation("pubname").getPublicId(), "pubId");
+ }
+
+ //find notation in Notation01.xml
+ private Notation findNotation(String name) throws SAXException, IOException, ParserConfigurationException {
+ Document document = createDOM("Notation01.xml");
+ NamedNodeMap nm = document.getDoctype().getNotations();
+ for (int i = 0; i < nm.getLength(); i++) {
+ if (nm.item(i).getNodeName().equals(name)) {
+ return (Notation) nm.item(i);
+ }
+ }
+ throw new RuntimeException("Notation: '" + name + "' not found.");
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/PITest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/PITest.java
new file mode 100644
index 00000000000..15bd6876c36
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/PITest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOMWithNS;
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.ProcessingInstruction;
+
+/*
+ * @summary Test for the methods of Processing Instruction
+ */
+public class PITest extends JAXPFileBaseTest {
+ /*
+ * Test getData, setData and getTarget methods
+ */
+ @Test
+ public void test() throws Exception {
+ Document document = createDOMWithNS("PITest01.xml");
+ ProcessingInstruction pi = document.createProcessingInstruction("PI", "processing");
+ assertEquals(pi.getData(), "processing");
+ assertEquals(pi.getTarget(), "PI");
+
+ pi.setData("newProcessing");
+ assertEquals(pi.getData(), "newProcessing");
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/TextTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/TextTest.java
new file mode 100644
index 00000000000..7932114b519
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/TextTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static org.testng.Assert.assertEquals;
+import static org.w3c.dom.ptests.DOMTestUtil.createDOMWithNS;
+import static org.w3c.dom.ptests.DOMTestUtil.createNewDocument;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.SAXException;
+
+/*
+ * @summary Test for Text implementation returned by Document.createTextNode(String)
+ */
+public class TextTest extends AbstractCharacterDataTest {
+ /*
+ * Verify splitText method works as the spec.
+ */
+ @Test
+ public void testSplitText() throws Exception {
+ Document document = createDOMWithNS("Text01.xml");
+
+ NodeList nodeList = document.getElementsByTagName("p");
+ Node node = nodeList.item(0);
+ Text textNode = document.createTextNode("This is a text node");
+ node.appendChild(textNode);
+ int rawChildNum = node.getChildNodes().getLength();
+
+ textNode.splitText(0);
+ int increased = node.getChildNodes().getLength() - rawChildNum;
+ assertEquals(increased, 1);
+
+ }
+
+ @Override
+ protected CharacterData createCharacterData(String text) throws IOException, SAXException, ParserConfigurationException {
+ Document document = createNewDocument();
+ return document.createTextNode(text);
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/TypeInfoTest.java b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/TypeInfoTest.java
new file mode 100644
index 00000000000..f68dd919e0d
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/ptests/TypeInfoTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import static org.testng.Assert.assertEquals;
+
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.TypeInfo;
+import org.xml.sax.InputSource;
+
+/*
+ * @summary Test getTypeName and getTypeNamespace methods of TypeInfo interface
+ */
+public class TypeInfoTest extends JAXPBaseTest {
+ /*
+ * Get the TypeInfo of the root element, and verify it.
+ */
+ @Test
+ public void test() throws Exception {
+ TypeInfo typeInfo = getTypeOfRoot(SCHEMA_INSTANCE, "\n" + "\n");
+
+ assertEquals(typeInfo.getTypeName(), "Test");
+ assertEquals(typeInfo.getTypeNamespace(), "testNS");
+
+ }
+
+ private TypeInfo getTypeOfRoot(String schemaText, String docText) throws Exception {
+ Element root = getRoot(schemaText, docText);
+ return root.getSchemaTypeInfo();
+ }
+
+ private Element getRoot(String schemaText, String docText) throws Exception {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+
+ InputSource inSchema = new InputSource(new StringReader(schemaText));
+ inSchema.setSystemId("schema.xsd");
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(true);
+ dbf.setAttribute(SCHEMA_LANGUAGE, W3C_XML_SCHEMA_NS_URI);
+ dbf.setAttribute(SCHEMA_SOURCE, inSchema);
+
+ DocumentBuilder parser = dbf.newDocumentBuilder();
+
+ InputSource inSource = new InputSource(new StringReader(docText));
+ inSource.setSystemId("doc.xml");
+ Document document = parser.parse(inSource);
+
+ return document.getDocumentElement();
+ }
+
+ private static final String SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
+
+ private static final String SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
+
+ /*
+ * Schema instance
+ */
+ private static final String SCHEMA_INSTANCE =
+ "\n"
+ + "\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + "\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + "\n"
+ + " \n"
+ + "\n"
+ + " \n"
+ + "\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + "\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + "\n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + " \n"
+ + "\n"
+ + "\n";
+
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr01.xml
new file mode 100644
index 00000000000..62224035142
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr01.xml
@@ -0,0 +1,18 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+ Numerical Analysis of Partial Differential Equations
+ Numerical Analysis of Partial Differential Equations
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr2.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr2.xml
new file mode 100644
index 00000000000..8439a564c00
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr2.xml
@@ -0,0 +1,11 @@
+
+
+
+
+]>
+
+
+ World's best book
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr3.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr3.xml
new file mode 100644
index 00000000000..527c68dd691
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Attr3.xml
@@ -0,0 +1,10 @@
+
+
+
+]>
+
+
+ World's best book
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Comment01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Comment01.xml
new file mode 100644
index 00000000000..80f7b74eb9e
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Comment01.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentBuilderImpl02.dtd b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentBuilderImpl02.dtd
new file mode 100644
index 00000000000..28b8a7b586a
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentBuilderImpl02.dtd
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentTest01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentTest01.xml
new file mode 100644
index 00000000000..15b61585623
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentTest01.xml
@@ -0,0 +1,12 @@
+
+
+
+ Typography
+
+
+ Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType01.xml
new file mode 100644
index 00000000000..348e73f30f1
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType01.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+]>
+
+&writer;
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType03.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType03.xml
new file mode 100644
index 00000000000..de62c6db2e6
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType03.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+]>
+
+lll
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType05.dtd b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType05.dtd
new file mode 100644
index 00000000000..28b8a7b586a
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType05.dtd
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType05.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType05.xml
new file mode 100644
index 00000000000..89e09643844
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/DocumentType05.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ Publishers of the Music of New York Women Composers
+
+ The Publishers
+
+
+ Alfred Publishing
+ &w;
+ 15535 Morrison
+ South Oaks CA 91403
+
+
+
+ eXtensible Markup Language
+
+
+
+
+
+ Publishers are not noted in report by time.
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample01.xml
new file mode 100644
index 00000000000..62224035142
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample01.xml
@@ -0,0 +1,18 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+ Numerical Analysis of Partial Differential Equations
+ Numerical Analysis of Partial Differential Equations
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample02.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample02.xml
new file mode 100644
index 00000000000..e1c0b4352d5
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample02.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample03.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample03.xml
new file mode 100644
index 00000000000..9fdef74cf64
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample03.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample04.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample04.xml
new file mode 100644
index 00000000000..b4a307254ef
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ElementSample04.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ this is it
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/NamedNodeMap01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/NamedNodeMap01.xml
new file mode 100644
index 00000000000..07906e988b7
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/NamedNodeMap01.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/NamedNodeMap03.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/NamedNodeMap03.xml
new file mode 100644
index 00000000000..2e4b9d1588f
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/NamedNodeMap03.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node01.xml
new file mode 100644
index 00000000000..07906e988b7
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node01.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node02.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node02.xml
new file mode 100644
index 00000000000..2e4b9d1588f
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node02.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node04.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node04.xml
new file mode 100644
index 00000000000..d7dd873ffb5
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node04.xml
@@ -0,0 +1,8 @@
+
+
+
+John
+
+message
+ weekend!
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node05.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node05.xml
new file mode 100644
index 00000000000..d32c19dce44
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Node05.xml
@@ -0,0 +1,6 @@
+
+
+
+ Typography
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Notation01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Notation01.xml
new file mode 100644
index 00000000000..dd26b3ef82e
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Notation01.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+]>
+
+lll
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/PITest01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/PITest01.xml
new file mode 100644
index 00000000000..07906e988b7
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/PITest01.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
Welcome to the world of typography! Here is a book that you may find useful.
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Text01.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Text01.xml
new file mode 100644
index 00000000000..80f7b74eb9e
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/Text01.xml
@@ -0,0 +1,15 @@
+
+
+
+ Typography
+
+
+
+
+ Digital Typography
+ Donald Knuth
+ fjfjf
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ee.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ee.xml
new file mode 100644
index 00000000000..7370d56ebf7
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/ee.xml
@@ -0,0 +1,7 @@
+
+
+
+
+&mkm;
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/entitychild.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/entitychild.xml
new file mode 100644
index 00000000000..6e2e0e90be7
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/entitychild.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+]>
+
+
+ⅇ
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/nodelist.xml b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/nodelist.xml
new file mode 100644
index 00000000000..fbdbfe6830b
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/nodelist.xml
@@ -0,0 +1,2 @@
+
+onenode
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/out/InsertBeforeGF.out b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/out/InsertBeforeGF.out
new file mode 100644
index 00000000000..53cb987a33a
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/out/InsertBeforeGF.out
@@ -0,0 +1,7 @@
+
+
+Text in itJohn
+
+message
+ weekend!
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/out/ReplaceChild3GF.out b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/out/ReplaceChild3GF.out
new file mode 100644
index 00000000000..4199e493fc2
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/org/w3c/dom/xmlfiles/out/ReplaceChild3GF.out
@@ -0,0 +1,7 @@
+
+
+Text in it
+
+message
+ weekend!
+
diff --git a/jaxp/test/javax/xml/jaxp/libs/org/w3c/dom/ptests/DOMTestUtil.java b/jaxp/test/javax/xml/jaxp/libs/org/w3c/dom/ptests/DOMTestUtil.java
new file mode 100644
index 00000000000..6b32aa36e74
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/libs/org/w3c/dom/ptests/DOMTestUtil.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom.ptests;
+
+import static jaxp.library.JAXPTestUtilities.FILE_SEP;
+import static jaxp.library.JAXPTestUtilities.getPathByClassName;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/*
+ * This class defines the path constant and common method
+ */
+public class DOMTestUtil {
+ /*
+ * XML source file directory.
+ */
+ public static final String XML_DIR = getPathByClassName(DOMTestUtil.class, ".." + FILE_SEP + "xmlfiles");
+
+ /*
+ * Golden validation files directory.
+ */
+ public static final String GOLDEN_DIR = getPathByClassName(DOMTestUtil.class, ".." + FILE_SEP + "xmlfiles" + FILE_SEP + "out");
+
+ /*
+ * Error Message for DOMException being expected.
+ */
+ public static final String DOMEXCEPTION_EXPECTED = "Should throw DOMException";
+
+ /*
+ * Create DOM Document from an xml file.
+ */
+ public static Document createDOM(String xmlFileName) throws SAXException, IOException, ParserConfigurationException {
+ return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(XML_DIR + xmlFileName));
+ }
+
+ /*
+ * Create DOM Document from an xml file with setNamespaceAware(true).
+ */
+ public static Document createDOMWithNS(String xmlFileName) throws IOException, SAXException, ParserConfigurationException {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ return dbf.newDocumentBuilder().parse(new File(XML_DIR + xmlFileName));
+ }
+
+ /*
+ * Create a new DOM Document.
+ */
+ public static Document createNewDocument() throws ParserConfigurationException {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ return db.newDocument();
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/DOMXPathTest.java b/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/DOMXPathTest.java
new file mode 100644
index 00000000000..fa92dc7175b
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/org/w3c/dom/DOMXPathTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.w3c.dom;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/*
+ * @bug 8042244
+ * @summary Verifies that the experimental DOM L3 XPath implementation is no longer available.
+ */
+public class DOMXPathTest {
+ /*
+ Verifies that DOMImplementation::hasFeature returns false and getFeature
+ returns null for DOM L3 XPath.
+ */
+ @Test
+ public void test() throws ParserConfigurationException {
+ DOMImplementation domImpl = DocumentBuilderFactory.newInstance()
+ .newDocumentBuilder()
+ .getDOMImplementation();
+
+ Assert.assertFalse(domImpl.hasFeature("+XPath", "3.0"));
+ Assert.assertEquals(domImpl.getFeature("+XPath", "3.0"), null);
+ }
+}
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 28dbe7d8a58..7f0b86b9195 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -305,3 +305,4 @@ b4f913b48e699980bd11fe19cce134d0adb4c31c jdk9-b56
17c4241395e97312bd75e7acd693ffcdd41ae993 jdk9-b57
1e06b36bb396c0495e0774f1c6b0356d03847659 jdk9-b58
8a9ebae410bc388668fc203e559b5407bde757eb jdk9-b59
+f31835b59035377a220efc5a248b90f090ee1689 jdk9-b60
diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/ClassFactory.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/ClassFactory.java
index 7bdffc4051e..4347bff9f07 100644
--- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/ClassFactory.java
+++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/ClassFactory.java
@@ -30,6 +30,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.ref.WeakReference;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
@@ -85,19 +87,25 @@ public final class ClassFactory {
if(consRef!=null)
cons = consRef.get();
if(cons==null) {
- try {
- cons = clazz.getDeclaredConstructor(emptyClass);
- } catch (NoSuchMethodException e) {
- logger.log(Level.INFO,"No default constructor found on "+clazz,e);
- NoSuchMethodError exp;
- if(clazz.getDeclaringClass()!=null && !Modifier.isStatic(clazz.getModifiers())) {
- exp = new NoSuchMethodError(Messages.NO_DEFAULT_CONSTRUCTOR_IN_INNER_CLASS.format(clazz.getName()));
- } else {
- exp = new NoSuchMethodError(e.getMessage());
+ cons = AccessController.doPrivileged(new PrivilegedAction>() {
+ @Override
+ public Constructor run() {
+ try {
+ return clazz.getDeclaredConstructor(emptyClass);
+ } catch (NoSuchMethodException e) {
+ logger.log(Level.INFO,"No default constructor found on "+clazz,e);
+ NoSuchMethodError exp;
+ if(clazz.getDeclaringClass()!=null && !Modifier.isStatic(clazz.getModifiers())) {
+ exp = new NoSuchMethodError(Messages.NO_DEFAULT_CONSTRUCTOR_IN_INNER_CLASS
+ .format(clazz.getName()));
+ } else {
+ exp = new NoSuchMethodError(e.getMessage());
+ }
+ exp.initCause(e);
+ throw exp;
+ }
}
- exp.initCause(e);
- throw exp;
- }
+ });
int classMod = clazz.getModifiers();
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/Engine.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/Engine.java
index 516f51107c0..29b94bf98c2 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/Engine.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/Engine.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -108,7 +108,8 @@ public class Engine {
}
public Thread newThread(Runnable r) {
- Thread t = new Thread(null, r, namePrefix + threadNumber.getAndIncrement(), 0);
+ Thread t = ThreadHelper.createNewThread(r);
+ t.setName(namePrefix + threadNumber.getAndIncrement());
if (!t.isDaemon()) {
t.setDaemon(true);
}
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java
new file mode 100644
index 00000000000..1c74d10a220
--- /dev/null
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.xml.internal.ws.api.pipe;
+
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Simple utility class to instantiate correct Thread instance
+ * depending on runtime context (jdk/non-jdk usage)
+ *
+ * @author miroslav.kos@oracle.com
+ */
+final class ThreadHelper {
+
+ private static final String SAFE_THREAD_NAME = "sun.misc.ManagedLocalsThread";
+ private static final Constructor THREAD_CONSTRUCTOR;
+
+ // no instantiating wanted
+ private ThreadHelper() {
+ }
+
+ static {
+ THREAD_CONSTRUCTOR = AccessController.doPrivileged(
+ new PrivilegedAction () {
+ @Override
+ public Constructor run() {
+ try {
+ Class cls = Class.forName(SAFE_THREAD_NAME);
+ if (cls != null) {
+ return cls.getConstructor(Runnable.class);
+ }
+ } catch (ClassNotFoundException ignored) {
+ } catch (NoSuchMethodException ignored) {
+ }
+ return null;
+ }
+ }
+ );
+ }
+
+ static Thread createNewThread(final Runnable r) {
+ if (isJDKInternal()) {
+ return AccessController.doPrivileged(
+ new PrivilegedAction() {
+ @Override
+ public Thread run() {
+ try {
+ return (Thread) THREAD_CONSTRUCTOR.newInstance(r);
+ } catch (Exception e) {
+ return new Thread(r);
+ }
+ }
+ }
+ );
+ } else {
+ return new Thread(r);
+ }
+ }
+
+ private static boolean isJDKInternal() {
+ String className = ThreadHelper.class.getName();
+ return className.contains(".internal.");
+ }
+}
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/client/WSServiceDelegate.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/client/WSServiceDelegate.java
index 1c054547a4e..2b384af2919 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/client/WSServiceDelegate.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/client/WSServiceDelegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -894,15 +894,6 @@ public class WSServiceDelegate extends WSService {
return wsdlService;
}
- static class DaemonThreadFactory implements ThreadFactory {
- @Override
- public Thread newThread(Runnable r) {
- Thread daemonThread = new Thread(r);
- daemonThread.setDaemon(Boolean.TRUE);
- return daemonThread;
- }
- }
-
protected static final WebServiceFeature[] EMPTY_FEATURES = new WebServiceFeature[0];
private static ClassLoader getDelegatingLoader(ClassLoader loader1, ClassLoader loader2) {
diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/spi/db/BindingHelper.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/spi/db/BindingHelper.java
index 84047b67d24..a69edb430a5 100644
--- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/spi/db/BindingHelper.java
+++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/spi/db/BindingHelper.java
@@ -36,9 +36,6 @@ import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
//TODO DOMHeader DOMMessage SAAJMessage StatefulInstanceResolver
import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
-//TODO MtomCodec
-import com.sun.xml.internal.bind.v2.runtime.output.Encoded;
-
//TODO ExceptionBean
import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
diff --git a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPConstants.java b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPConstants.java
index ee1582ed285..7c6a640bee8 100644
--- a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPConstants.java
+++ b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/wsdl/document/soap/SOAPConstants.java
@@ -25,8 +25,6 @@
package com.sun.tools.internal.ws.wsdl.document.soap;
-import com.sun.xml.internal.ws.encoding.soap.streaming.SOAPNamespaceConstants;
-
import javax.xml.namespace.QName;
/**
@@ -37,7 +35,9 @@ import javax.xml.namespace.QName;
public interface SOAPConstants {
// namespace URIs
- public static final String URI_ENVELOPE = SOAPNamespaceConstants.ENVELOPE;
+ public static final String URI_ENVELOPE =
+ "http://schemas.xmlsoap.org/soap/envelope/";
+
public static final String NS_WSDL_SOAP =
"http://schemas.xmlsoap.org/wsdl/soap/";
public static final String NS_SOAP_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 0b955733484..94cd8c38a85 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -302,3 +302,4 @@ d49e247dade61f29f771f09b2105857492241156 jdk9-b55
c76339e86ea7da5d9ac7856f3fae9ef73eef04a2 jdk9-b57
36fc65e80d811ee43aedfc69284224b86a403662 jdk9-b58
48ee960f29df93a9b2a895621321358a86909086 jdk9-b59
+84c5527f742bc64562e47d3149c16197fe1c4c1a jdk9-b60
diff --git a/jdk/make/CompileDemos.gmk b/jdk/make/CompileDemos.gmk
index 2d10867948f..3328dbc6cf4 100644
--- a/jdk/make/CompileDemos.gmk
+++ b/jdk/make/CompileDemos.gmk
@@ -45,7 +45,7 @@ DEMO_SHARE_SRC := $(JDK_TOPDIR)/src/demo/share
DEMO_CLOSED_SHARE_SRC := $(JDK_TOPDIR)/src/closed/demo/share
DEMO_SOLARIS_SRC := $(JDK_TOPDIR)/src/demo/solaris
DEMO_OS_TYPE_SRC := $(JDK_TOPDIR)/src/demo/$(OPENJDK_TARGET_OS_TYPE)
-VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc
+GLOBAL_VERSION_INFO_RESOURCE := $(JDK_TOPDIR)/src/java.base/windows/native/common/version.rc
##################################################################################################
@@ -230,11 +230,8 @@ define SetupJVMTIDemo
$$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/README.txt, $2)) \
$$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/sample.makefile.txt, $2))
BUILD_DEMO_JVMTI_$1_EXTRA_INC := $$(addprefix -I, $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC))
- BUILD_DEMO_JVMTI_$1_LANG := C
- ifneq (, $4)
- BUILD_DEMO_JVMTI_$1_LANG := $4
- endif
ifeq (C++, $4)
+ BUILD_DEMO_JVMTI_$1_TOOLCHAIN := TOOLCHAIN_LINK_CXX
$1_EXTRA_CXX := $(LDFLAGS_CXX_JDK) $(LIBCXX)
endif
@@ -254,7 +251,7 @@ define SetupJVMTIDemo
# Remove the -incremental:no setting to get .ilk-files like in the old build.
$$(eval $$(call SetupNativeCompilation,BUILD_DEMO_JVMTI_$1, \
SRC := $(DEMO_SHARE_SRC)/jvmti/$1 $$(BUILD_DEMO_JVMTI_$1_EXTRA_SRC), \
- LANG := $$(BUILD_DEMO_JVMTI_$1_LANG), \
+ TOOLCHAIN := $$(BUILD_DEMO_JVMTI_$1_TOOLCHAIN), \
OPTIMIZATION := LOW, \
CXXFLAGS := $$($1_CXXFLAGS), \
DISABLED_WARNINGS_gcc := $(10), \
@@ -267,7 +264,7 @@ define SetupJVMTIDemo
LDFLAGS_SUFFIX_windows := $6, \
LDFLAGS_SUFFIX_solaris := $7 -lc, \
LDFLAGS_SUFFIX_linux := $8, \
- VERSIONINFO_RESOURCE := $(VERSION_INFO_RESOURCE), \
+ VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $$(RC_FLAGS) \
-D "JDK_FNAME=$1.dll" \
-D "JDK_INTERNAL_NAME=$1" \
@@ -398,7 +395,6 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
$(eval $(call SetupNativeCompilation,BUILD_LIBPOLLER, \
SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(SHARED_LIBRARY_FLAGS) \
-I$(SUPPORT_OUTPUTDIR)/demo/classes/jni/Poller, \
diff --git a/jdk/make/Tools.gmk b/jdk/make/Tools.gmk
index 07ac66339a0..0d56ccbb827 100644
--- a/jdk/make/Tools.gmk
+++ b/jdk/make/Tools.gmk
@@ -163,9 +163,7 @@ $(eval $(call SetupCopyFiles,COPY_JIMAGE_SERVICE_PROVIDER, \
ifeq ($(OPENJDK_TARGET_OS), solaris)
$(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_LD), \
+ TOOLCHAIN := TOOLCHAIN_BUILD, \
LDFLAGS := -lelf, \
OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
@@ -173,9 +171,7 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
$(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_LD), \
+ TOOLCHAIN := TOOLCHAIN_BUILD, \
LDFLAGS := -lelf, \
OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk
index f1728f33edb..46687333361 100644
--- a/jdk/make/copy/Copy-java.base.gmk
+++ b/jdk/make/copy/Copy-java.base.gmk
@@ -170,9 +170,6 @@ POLICY_SRC_LIST :=
ifeq ($(OPENJDK_TARGET_OS), windows)
POLICY_SRC_LIST += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/conf/security/java.policy
- ifndef OPENJDK
- POLICY_SRC_LIST += $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/conf/security/java.policy
- endif
endif
POLICY_SRC_LIST += $(POLICY_SRC)
diff --git a/jdk/make/copy/Copy-jdk.accessibility.gmk b/jdk/make/copy/Copy-jdk.accessibility.gmk
new file mode 100644
index 00000000000..4c089c16883
--- /dev/null
+++ b/jdk/make/copy/Copy-jdk.accessibility.gmk
@@ -0,0 +1,47 @@
+#
+# Copyright (c) 2104, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include CopyCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+ TARGETS += $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgeCallbacks.h \
+ $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgeCalls.h \
+ $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgePackages.h \
+ $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgeCalls.c \
+ $(CONF_DST_DIR)/accessibility.properties
+
+ $(INCLUDE_DST_OS_DIR)/bridge/%: \
+ $(JDK_TOPDIR)/src/jdk.accessibility/windows/native/include/bridge/%
+ $(install-file)
+
+ $(CONF_DST_DIR)/accessibility.properties: \
+ $(JDK_TOPDIR)/src/jdk.accessibility/windows/conf/accessibility.properties
+ $(install-file)
+
+endif
+
+################################################################################
diff --git a/jdk/make/data/swingbeaninfo/SwingBeanInfo.template b/jdk/make/data/swingbeaninfo/SwingBeanInfo.template
index 9c1a133f67f..e0c83c0e2cf 100644
--- a/jdk/make/data/swingbeaninfo/SwingBeanInfo.template
+++ b/jdk/make/data/swingbeaninfo/SwingBeanInfo.template
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -92,25 +92,38 @@ public class @(BeanClassName)BeanInfo extends javax.swing.SwingBeanInfoBase {
/**
* @return an icon of the specified kind for @(BeanClassName)
*/
- public Image getIcon(int kind) {
+ public Image getIcon(final int kind) {
Image i;
switch (kind){
case ICON_COLOR_32x32:
- i = loadImage("beaninfo/images/@(BeanClassName)Color32.gif");
- return ((i == null) ? loadImage("beaninfo/images/JComponentColor32.gif") : i);
+ i = loadStandardImage("beaninfo/images/@(BeanClassName)Color32.gif");
+ return ((i == null) ? loadStandardImage("beaninfo/images/JComponentColor32.gif") : i);
case ICON_COLOR_16x16:
- i = loadImage("beaninfo/images/@(BeanClassName)Color16.gif");
- return ((i == null) ? loadImage("beaninfo/images/JComponentColor16.gif") : i);
+ i = loadStandardImage("beaninfo/images/@(BeanClassName)Color16.gif");
+ return ((i == null) ? loadStandardImage("beaninfo/images/JComponentColor16.gif") : i);
case ICON_MONO_32x32:
- i = loadImage("beaninfo/images/@(BeanClassName)Mono32.gif");
- return ((i == null) ? loadImage("beaninfo/images/JComponentMono32.gif") : i);
+ i = loadStandardImage("beaninfo/images/@(BeanClassName)Mono32.gif");
+ return ((i == null) ? loadStandardImage("beaninfo/images/JComponentMono32.gif") : i);
case ICON_MONO_16x16:
- i = loadImage("beaninfo/images/@(BeanClassName)Mono16.gif");
- return ((i == null) ? loadImage("beaninfo/images/JComponentMono16.gif") : i);
+ i = loadStandardImage("beaninfo/images/@(BeanClassName)Mono16.gif");
+ return ((i == null) ? loadStandardImage("beaninfo/images/JComponentMono16.gif") : i);
default:
return super.getIcon(kind);
}
}
+
+ /**
+ * This is a utility method to help in loading standard icon images.
+ *
+ * @param resourceName A pathname relative to the directory holding the
+ * class file of the current class
+ * @return an image object. May be null if the load failed.
+ * @see java.beans.SimpleBeanInfo#loadImage(String)
+ */
+ private Image loadStandardImage(final String resourceName) {
+ return java.security.AccessController.doPrivileged(
+ (java.security.PrivilegedAction) () -> loadImage(resourceName));
+ }
}
diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk
index c0489f3a97d..7762a284952 100644
--- a/jdk/make/gensrc/GensrcMisc.gmk
+++ b/jdk/make/gensrc/GensrcMisc.gmk
@@ -63,9 +63,7 @@ SOR_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSRC_SOR_SRC)/$(GENSRC_SOR_SRC_FILE) |
$(eval $(call SetupNativeCompilation,BUILD_GENSRC_SOR_EXE, \
SRC := $(GENSRC_SOR_SRC), \
INCLUDE_FILES := $(GENSRC_SOR_SRC_FILE), \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_LD), \
+ TOOLCHAIN := TOOLCHAIN_BUILD, \
OBJECT_DIR := $(GENSRC_SOR_BIN), \
OUTPUT_DIR := $(GENSRC_SOR_BIN), \
PROGRAM := genSocketOptionRegistry))
@@ -101,9 +99,7 @@ ifneq ($(OPENJDK_TARGET_OS), windows)
$(eval $(call SetupNativeCompilation,BUILD_GENSRC_UC_EXE, \
SRC := $(GENSRC_UC_SRC), \
INCLUDE_FILES := $(GENSRC_UC_SRC_FILE), \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_CC), \
+ TOOLCHAIN := TOOLCHAIN_BUILD, \
CFLAGS := $(filter -D%, $(CFLAGS_JDKEXE)), \
OBJECT_DIR := $(GENSRC_UC_BIN), \
OUTPUT_DIR := $(GENSRC_UC_BIN), \
@@ -142,9 +138,7 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
$(eval $(call SetupNativeCompilation,BUILD_GENSRC_SOL_EXE, \
SRC := $(GENSRC_SOL_SRC), \
INCLUDE_FILES := $(GENSRC_SOL_SRC_FILE), \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_CC), \
+ TOOLCHAIN := TOOLCHAIN_BUILD, \
OBJECT_DIR := $(GENSRC_SOL_BIN), \
OUTPUT_DIR := $(GENSRC_SOL_BIN), \
PROGRAM := genSolarisConstants))
diff --git a/jdk/make/launcher/Launcher-java.base.gmk b/jdk/make/launcher/Launcher-java.base.gmk
index d117ad3b2ca..b0defc603f8 100644
--- a/jdk/make/launcher/Launcher-java.base.gmk
+++ b/jdk/make/launcher/Launcher-java.base.gmk
@@ -103,7 +103,6 @@ ifneq ($(BUILD_JEXEC_SRC), )
$(eval $(call SetupNativeCompilation,BUILD_JEXEC, \
SRC := $(BUILD_JEXEC_SRC), \
INCLUDE_FILES := jexec.c, \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKEXE) \
$(BUILD_JEXEC_INC), \
@@ -144,7 +143,6 @@ ifeq ($(BUILD_JSPAWNHELPER), 1)
$(eval $(call SetupNativeCompilation,BUILD_JSPAWNHELPER, \
SRC := $(BUILD_JSPAWNHELPER_SRC), \
INCLUDE_FILES := jspawnhelper.c, \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKEXE) $(JSPAWNHELPER_CFLAGS), \
LDFLAGS := $(LDFLAGS_JDKEXE) $(LINK_JSPAWNHELPER_FLAGS), \
diff --git a/jdk/make/launcher/Launcher-jdk.accessibility.gmk b/jdk/make/launcher/Launcher-jdk.accessibility.gmk
new file mode 100644
index 00000000000..dc34a3fee7b
--- /dev/null
+++ b/jdk/make/launcher/Launcher-jdk.accessibility.gmk
@@ -0,0 +1,61 @@
+#
+# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LauncherCommon.gmk
+
+################################################################################
+# jabswitch
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+
+ JABSWITCH_SRC := $(JDK_TOPDIR)/src/jdk.accessibility/windows/native/jabswitch
+ ACCESSBRIDGE_SRC := $(JDK_TOPDIR)/src/jdk.accessibility/windows/native/common
+
+ $(eval $(call SetupNativeCompilation,BUILD_JABSWITCH, \
+ SRC := $(JABSWITCH_SRC), \
+ INCLUDE_FILES := jabswitch.cpp, \
+ CFLAGS := $(filter-out -Zc:wchar_t-, $(CFLAGS_JDKEXE)) -Zc:wchar_t \
+ -analyze- -Od -Gd -D_WINDOWS \
+ -D_UNICODE -DUNICODE -RTC1 -EHsc, \
+ DISABLED_WARNINGS_microsoft := 4267, \
+ LDFLAGS := $(LDFLAGS_JDKEXE) \
+ Advapi32.lib Version.lib User32.lib, \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/jdk.accessibility/jabswitch, \
+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/jdk.accessibility, \
+ PROGRAM := jabswitch, \
+ DEBUG_SYMBOLS := true, \
+ VERSIONINFO_RESOURCE := $(ACCESSBRIDGE_SRC)/AccessBridgeStatusWindow.RC, \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=jabswitch.exe" \
+ -D "JDK_INTERNAL_NAME=jabswitch" \
+ -D "JDK_FTYPE=0x01L", \
+ MANIFEST := $(JABSWITCH_SRC)/jabswitch.manifest, \
+ MANIFEST_VERSION := $(JDK_VERSION_FOR_MANIFEST), \
+ ))
+
+ TARGETS += $(BUILD_JABSWITCH)
+endif
+
+################################################################################
diff --git a/jdk/make/launcher/Launcher-jdk.pack200.gmk b/jdk/make/launcher/Launcher-jdk.pack200.gmk
index affdbdb26eb..391272a76fb 100644
--- a/jdk/make/launcher/Launcher-jdk.pack200.gmk
+++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk
@@ -56,23 +56,28 @@ else
endif
-UNPACKEXE_LANG := C
ifeq ($(OPENJDK_TARGET_OS), solaris)
- UNPACKEXE_LANG := C++
+ UNPACKEXE_TOOLCHAIN := TOOLCHAIN_LINK_CXX
endif
+UNPACK_MAPFILE_DIR := $(JDK_TOPDIR)/make/mapfiles/libunpack
+UNPACK_MAPFILE_PLATFORM_FILE := \
+ $(UNPACK_MAPFILE_DIR)/mapfile-vers-unpack200-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH)
+
# The linker on older SuSE distros (e.g. on SLES 10) complains with:
# "Invalid version tag `SUNWprivate_1.1'. Only anonymous version tag is allowed in executable."
# if feeded with a version script which contains named tags.
ifeq ($(USING_BROKEN_SUSE_LD), yes)
- UNPACK_MAPFILE = $(JDK_TOPDIR)/make/mapfiles/libunpack/mapfile-vers-unpack200.anonymous
+ UNPACK_MAPFILE := $(UNPACK_MAPFILE_DIR)/mapfile-vers-unpack200.anonymous
+else ifneq ($(wildcard $(UNPACK_MAPFILE_PLATFORM_FILE)), )
+ UNPACK_MAPFILE := $(UNPACK_MAPFILE_PLATFORM_FILE)
else
- UNPACK_MAPFILE = $(JDK_TOPDIR)/make/mapfiles/libunpack/mapfile-vers-unpack200
+ UNPACK_MAPFILE := $(UNPACK_MAPFILE_DIR)/mapfile-vers-unpack200
endif
$(eval $(call SetupNativeCompilation,BUILD_UNPACKEXE, \
SRC := $(UNPACKEXE_SRC), \
- LANG := $(UNPACKEXE_LANG), \
+ TOOLCHAIN := $(UNPACKEXE_TOOLCHAIN), \
OPTIMIZATION := LOW, \
CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \
CFLAGS_release := -DPRODUCT, \
@@ -96,7 +101,9 @@ $(eval $(call SetupNativeCompilation,BUILD_UNPACKEXE, \
-D "JDK_INTERNAL_NAME=unpack200" \
-D "JDK_FTYPE=0x1L", \
DEBUG_SYMBOLS := true, \
- MANIFEST := $(JDK_TOPDIR)/src/jdk.pack200/windows/native/unpack200/unpack200_proto.exe.manifest))
+ MANIFEST := $(JDK_TOPDIR)/src/jdk.pack200/windows/native/unpack200/unpack200_proto.exe.manifest, \
+ MANIFEST_VERSION := $(JDK_VERSION_FOR_MANIFEST), \
+))
ifneq ($(USE_EXTERNAL_LIBZ), true)
diff --git a/jdk/make/launcher/LauncherCommon.gmk b/jdk/make/launcher/LauncherCommon.gmk
index 09ffcffdb34..1e504f5231a 100644
--- a/jdk/make/launcher/LauncherCommon.gmk
+++ b/jdk/make/launcher/LauncherCommon.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -161,7 +161,6 @@ define SetupLauncher
$(call SetupNativeCompilation,BUILD_LAUNCHER_$1, \
SRC := $(LAUNCHER_SRC), \
INCLUDE_FILES := main.c, \
- LANG := C, \
OPTIMIZATION := $$($1_OPTIMIZATION_ARG), \
CFLAGS := $$($1_CFLAGS) \
$(LAUNCHER_CFLAGS) \
@@ -199,7 +198,9 @@ define SetupLauncher
-D "JDK_FTYPE=0x1L" \
$7, \
MANIFEST := $(JAVA_MANIFEST), \
- CODESIGN := $$($1_CODESIGN))
+ MANIFEST_VERSION := $(JDK_VERSION_FOR_MANIFEST), \
+ CODESIGN := $$($1_CODESIGN), \
+ )
TARGETS += $$(BUILD_LAUNCHER_$1)
diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk
index c7ce8d9c202..254f446a000 100644
--- a/jdk/make/lib/Awt2dLibraries.gmk
+++ b/jdk/make/lib/Awt2dLibraries.gmk
@@ -51,7 +51,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBMLIB_IMAGE, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBMLIB_SRC), \
EXCLUDE_FILES := mlib_c_ImageBlendTable.c, \
- LANG := C, \
OPTIMIZATION := HIGHEST, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(BUILD_LIBMLIB_CFLAGS), \
@@ -124,7 +123,6 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc)
LIBRARY := mlib_image_v, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBMLIB_IMAGE_V_SRC), \
- LANG := C, \
EXCLUDE_FILES := $(BUILD_LIBMLIB_IMAGE_V_EXFILES), \
OPTIMIZATION := HIGHEST, \
CFLAGS := -xarch=sparcvis \
@@ -204,8 +202,6 @@ ifneq ($(OPENJDK_TARGET_OS), solaris)
LIBAWT_CFLAGS += -DMLIB_NO_LIBSUNMATH
endif
-LIBAWT_LANG := C
-
ifeq ($(OPENJDK_TARGET_OS), windows)
LIBAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/native/common/font \
$(JDK_TOPDIR)/src/java.desktop/share/native/common/java2d/opengl \
@@ -222,7 +218,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
awt/image/cvutils/img_colors.c \
#
- LIBAWT_LANG := C++
LIBAWT_CFLAGS += -EHsc -DUNICODE -D_UNICODE
ifeq ($(OPENJDK_TARGET_CPU_BITS), 64)
LIBAWT_CFLAGS += -DMLIB_OS64BIT
@@ -247,7 +242,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBAWT, \
SRC := $(LIBAWT_DIRS), \
EXCLUDES := $(LIBAWT_EXCLUDES), \
EXCLUDE_FILES := $(LIBAWT_EXFILES), \
- LANG := $(LIBAWT_LANG), \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_CFLAGS), \
DISABLED_WARNINGS_gcc := sign-compare unused-result maybe-uninitialized \
@@ -355,7 +349,6 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBAWT_XAWT_DIRS), \
EXCLUDES := $(LIBAWT_XAWT_EXCLUDES), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_XAWT_CFLAGS) \
$(X_CFLAGS), \
@@ -413,7 +406,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBLCMS, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBLCMS_SRC), \
INCLUDE_FILES := $(BUILD_LIBLCMS_INCLUDE_FILES), \
- LANG := C, \
OPTIMIZATION := HIGHEST, \
CFLAGS := $(filter-out -xc99=%none, $(CFLAGS_JDKLIB)) \
$(SHARED_LIBRARY_FLAGS) $(LIBLCMS_CPPFLAGS) \
@@ -496,7 +488,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVAJPEG, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJAVAJPEG_SRC), \
INCLUDE_FILES := $(BUILD_LIBJAVAJPEG_INCLUDE_FILES), \
- LANG := C, \
OPTIMIZATION := HIGHEST, \
CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJAVAJPEG_SRC)) \
$(LIBJAVA_HEADER_FLAGS) \
@@ -564,7 +555,6 @@ ifeq ($(BUILD_HEADLESS), true)
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBAWT_HEADLESS_DIRS), \
EXCLUDES := $(LIBAWT_HEADLESS_EXCLUDES), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
-DHEADLESS=true \
@@ -651,7 +641,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBFONTMANAGER, \
SRC := $(LIBFONTMANAGER_SRC), \
EXCLUDE_FILES := $(LIBFONTMANAGER_EXCLUDE_FILES) \
AccelGlyphCache.c, \
- LANG := C++, \
+ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBFONTMANAGER_CFLAGS), \
OPTIMIZATION := $(LIBFONTMANAGER_OPTIMIZATION), \
@@ -712,7 +702,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJAWT_SRC), \
INCLUDE_FILES := $(LIBJAWT_INCLUDE_FILES), \
- LANG := C++, \
OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKLIB) \
-EHsc -DUNICODE -D_UNICODE \
@@ -771,7 +760,6 @@ else # OPENJDK_TARGET_OS not windows
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJAWT_SRC), \
INCLUDE_FILES := $(JAWT_FILES), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJAWT_CFLAGS), \
@@ -889,7 +877,6 @@ ifndef BUILD_HEADLESS_ONLY
SRC := $(LIBSPLASHSCREEN_DIRS), \
EXCLUDE_FILES := imageioJPEG.c jpegdecoder.c pngtest.c, \
EXCLUDES := $(LIBSPLASHSCREEN_EXCLUDES), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(LIBSPLASHSCREEN_CFLAGS) $(CFLAGS_JDKLIB) \
$(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS), \
@@ -958,7 +945,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBRARY := awt_lwawt, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBAWT_LWAWT_DIRS), \
- LANG := C, \
INCLUDE_FILES := $(LIBAWT_LWAWT_FILES), \
EXCLUDE_FILES := $(LIBAWT_LWAWT_EXFILES), \
EXCLUDES := $(LIBAWT_LWAWT_EXCLUDES), \
@@ -1008,7 +994,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBRARY := osxui, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(JDK_TOPDIR)/src/java.desktop/macosx/native/libosxui, \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
-I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libosxui \
diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk
index 02ea309b107..ed6d75ce2be 100644
--- a/jdk/make/lib/CoreLibraries.gmk
+++ b/jdk/make/lib/CoreLibraries.gmk
@@ -43,7 +43,6 @@ ifneq ($(OPENJDK_TARGET_OS), macosx)
STATIC_LIBRARY := fdlibm, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
SRC := $(LIBFDLIBM_SRC), \
- LANG := C, \
OPTIMIZATION := $(BUILD_LIBFDLIBM_OPTIMIZATION), \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBFDLIBM_CFLAGS), \
CFLAGS_windows_debug := -DLOGGING, \
@@ -62,7 +61,6 @@ else
LIBRARY := fdlibm, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libfdlibm, \
SRC := $(LIBFDLIBM_SRC), \
- LANG := C, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBFDLIBM_CFLAGS), \
LDFLAGS := -nostdlib -r -arch x86_64, \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libfdlibm, \
@@ -93,7 +91,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBVERIFY, \
LIBRARY := verify, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(JDK_TOPDIR)/src/java.base/share/native/libverify, \
- LANG := C, \
OPTIMIZATION := $(LIBVERIFY_OPTIMIZATION), \
CFLAGS := $(CFLAGS_JDKLIB), \
DISABLED_WARNINGS_microsoft := 4244 4267, \
@@ -146,7 +143,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \
LIBRARY := java, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJAVA_SRC_DIRS), \
- LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJAVA_CFLAGS), \
@@ -206,7 +202,6 @@ endif
$(eval $(call SetupNativeCompilation,BUILD_LIBZIP, \
LIBRARY := zip, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
- LANG := C, \
OPTIMIZATION := LOW, \
SRC := $(JDK_TOPDIR)/src/java.base/share/native/libzip, \
EXCLUDES := $(LIBZIP_EXCLUDES), \
@@ -314,7 +309,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \
SRC := $(LIBJLI_SRC_DIRS), \
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
- LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(LIBJLI_CFLAGS), \
DISABLED_WARNINGS_solstudio := E_ASM_DISABLES_OPTIMIZATION, \
@@ -363,7 +357,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
SRC := $(LIBJLI_SRC_DIRS), \
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
- LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
ARFLAGS := $(ARFLAGS), \
@@ -383,7 +376,6 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx)
SRC := $(LIBJLI_SRC_DIRS), \
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
- LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \
LDFLAGS := -nostdlib -r, \
@@ -403,7 +395,6 @@ else ifeq ($(OPENJDK_TARGET_OS), aix)
SRC := $(LIBJLI_SRC_DIRS), \
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
- LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
ARFLAGS := $(ARFLAGS), \
diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk
index 4aaec5ce5e2..5b668c87872 100644
--- a/jdk/make/lib/Lib-java.instrument.gmk
+++ b/jdk/make/lib/Lib-java.instrument.gmk
@@ -57,7 +57,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBINSTRUMENT, \
LIBRARY := instrument, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBINSTRUMENT_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(LIBINSTRUMENT_CFLAGS) $(CFLAGS_WARNINGS_ARE_ERRORS), \
CFLAGS_debug := -DJPLIS_LOGGING, \
diff --git a/jdk/make/lib/Lib-java.management.gmk b/jdk/make/lib/Lib-java.management.gmk
index e0e6f1d9476..29d5c081665 100644
--- a/jdk/make/lib/Lib-java.management.gmk
+++ b/jdk/make/lib/Lib-java.management.gmk
@@ -72,7 +72,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBMANAGEMENT_SRC), \
EXCLUDE_FILES := $(BUILD_LIBMANAGEMENT_EXCLUDES), \
- LANG := C, \
OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) $(BUILD_LIBMANAGEMENT_CFLAGS), \
MAPFILE := $(LIBMANAGEMENT_MAPFILE), \
diff --git a/jdk/make/lib/Lib-java.prefs.gmk b/jdk/make/lib/Lib-java.prefs.gmk
index 1ed2b6b13a8..d12d7eff7dd 100644
--- a/jdk/make/lib/Lib-java.prefs.gmk
+++ b/jdk/make/lib/Lib-java.prefs.gmk
@@ -37,7 +37,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBPREFS, \
LIBRARY := prefs, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBPREF_SRC_DIRS), \
- LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBPREF_SRC_DIRS)) \
$(LIBJAVA_HEADER_FLAGS), \
diff --git a/jdk/make/lib/Lib-java.security.jgss.gmk b/jdk/make/lib/Lib-java.security.jgss.gmk
index c2cee4e109b..401d0e7c0e9 100644
--- a/jdk/make/lib/Lib-java.security.jgss.gmk
+++ b/jdk/make/lib/Lib-java.security.jgss.gmk
@@ -36,7 +36,6 @@ ifneq ($(OPENJDK_TARGET_OS), windows)
LIBRARY := j2gss, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJ2GSS_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2GSS_SRC)) \
$(LIBJAVA_HEADER_FLAGS) \
@@ -79,7 +78,6 @@ ifneq ($(BUILD_CRYPTO), no)
LIBRARY := $(BUILD_LIBKRB5_NAME), \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBKRB5_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(addprefix -I, $(BUILD_LIBKRB5_SRC)) \
diff --git a/jdk/make/lib/Lib-java.smartcardio.gmk b/jdk/make/lib/Lib-java.smartcardio.gmk
index b08fb077819..82dfbfd55c1 100644
--- a/jdk/make/lib/Lib-java.smartcardio.gmk
+++ b/jdk/make/lib/Lib-java.smartcardio.gmk
@@ -37,7 +37,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJ2PCSC, \
LIBRARY := j2pcsc, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJ2PCSC_SRC), \
- LANG := C, \
CFLAGS_unix := -D__sun_jdk, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBJ2PCSC_CPPFLAGS), \
diff --git a/jdk/make/lib/Lib-jdk.accessibility.gmk b/jdk/make/lib/Lib-jdk.accessibility.gmk
new file mode 100644
index 00000000000..a689c89c65c
--- /dev/null
+++ b/jdk/make/lib/Lib-jdk.accessibility.gmk
@@ -0,0 +1,135 @@
+#
+# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+
+ ROOT_SRCDIR := $(JDK_TOPDIR)/src/jdk.accessibility/windows/native
+ JAVA_AB_SRCDIR := $(ROOT_SRCDIR)/libjavaaccessbridge $(ROOT_SRCDIR)/common
+ WIN_AB_SRCDIR := $(ROOT_SRCDIR)/libwindowsaccessbridge $(ROOT_SRCDIR)/common
+ SYSINFO_SRCDIR := $(ROOT_SRCDIR)/libjabsysinfo
+ ACCESSBRIDGE_CFLAGS := -I$(SUPPORT_OUTPUTDIR)/headers/jdk.accessibility \
+ -I$(JDK_TOPDIR)/src/java.desktop/windows/native/include \
+ -I$(JDK_TOPDIR)/src/java.desktop/share/native/include
+
+ define SetupJavaDLL
+ # Parameter 1 Suffix
+ # Parameter 2 ACCESSBRIDGE_ARCH_ suffix
+
+ $(call SetupNativeCompilation,BUILD_JAVAACCESSBRIDGE$1, \
+ LIBRARY = javaaccessbridge$1, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(JAVA_AB_SRCDIR), \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS) \
+ $(addprefix -I,$(JAVA_AB_SRCDIR)) \
+ -I$(JDK_TOPDIR)/src/jdk.accessibility/windows/native/include/bridge \
+ -DACCESSBRIDGE_ARCH_$2, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) kernel32.lib user32.lib gdi32.lib \
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib \
+ $(SUPPORT_OUTPUTDIR)/native/java.desktop/libjawt/jawt.lib \
+ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \
+ -subsystem:windows, \
+ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=javaaccessbridge$1.dll" \
+ -D "JDK_INTERNAL_NAME=javaaccessbridge$1" \
+ -D "JDK_FTYPE=0x02L", \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjavaaccessbridge$1, \
+ DEBUG_SYMBOLS := true)
+
+ $$(BUILD_JAVAACCESSBRIDGE$1): $(SUPPORT_OUTPUTDIR)/native/java.desktop/libjawt/jawt.lib
+
+ TARGETS += $$(BUILD_JAVAACCESSBRIDGE$1)
+ endef
+
+ define SetupWinDLL
+ # Parameter 1 Suffix
+ # Parameter 2 ACCESSBRIDGE_ARCH_ suffix
+ $(call SetupNativeCompilation,BUILD_WINDOWSACCESSBRIDGE$1, \
+ LIBRARY = windowsaccessbridge$1, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(WIN_AB_SRCDIR), \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(filter-out -MD, $(CFLAGS_JDKLIB)) -MT $(ACCESSBRIDGE_CFLAGS) \
+ $(addprefix -I,$(WIN_AB_SRCDIR)) \
+ -I$(JDK_TOPDIR)/src/jdk.accessibility/windows/native/include/bridge \
+ -DACCESSBRIDGE_ARCH_$2, \
+ LDFLAGS := $(LDFLAGS_JDKLIB) kernel32.lib user32.lib gdi32.lib \
+ winspool.lib comdlg32.lib advapi32.lib shell32.lib \
+ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib \
+ -subsystem:windows \
+ -def:$(ROOT_SRCDIR)/libwindowsaccessbridge/WinAccessBridge.DEF, \
+ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=windowsaccessbridge$1.dll" \
+ -D "JDK_INTERNAL_NAME=windowsaccessbridge$1" \
+ -D "JDK_FTYPE=0x02L", \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libwindowsaccessbridge$1, \
+ DEBUG_SYMBOLS := true)
+
+ TARGETS += $$(BUILD_WINDOWSACCESSBRIDGE$1)
+
+ endef
+
+ define SetupAccessBridgeSysInfo
+
+ $(call SetupNativeCompilation,BUILD_ACCESSBRIDGESYSINFO, \
+ LIBRARY = jabsysinfo, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(SYSINFO_SRCDIR), \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) $(ACCESSBRIDGE_CFLAGS), \
+ LDFLAGS := $(LDFLAGS_JDKLIB) \
+ -subsystem:windows -machine:I386, \
+ VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \
+ RC_FLAGS := $(RC_FLAGS) \
+ -D "JDK_FNAME=jabsysinfo.dll" \
+ -D "JDK_INTERNAL_NAME=jabsysinfo" \
+ -D "JDK_FTYPE=0x02L", \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lib/libjabsysinfo, \
+ DEBUG_SYMBOLS := true)
+
+ TARGETS += $$(BUILD_ACCESSBRIDGESYSINFO)
+
+ endef
+
+ ifeq ($(OPENJDK_TARGET_CPU_BITS), 32)
+ $(eval $(call SetupAccessBridgeSysInfo))
+ $(eval $(call SetupJavaDLL,-32,32))
+ $(eval $(call SetupJavaDLL,,LEGACY))
+ $(eval $(call SetupWinDLL,-32,32))
+ $(eval $(call SetupWinDLL,,LEGACY))
+ else
+ $(eval $(call SetupJavaDLL,,64))
+ $(eval $(call SetupWinDLL,-64,64))
+ endif
+
+endif
+
+################################################################################
diff --git a/jdk/make/lib/Lib-jdk.attach.gmk b/jdk/make/lib/Lib-jdk.attach.gmk
index 3950b4a7474..c64867c070d 100644
--- a/jdk/make/lib/Lib-jdk.attach.gmk
+++ b/jdk/make/lib/Lib-jdk.attach.gmk
@@ -32,7 +32,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \
LIBRARY := attach, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
-I$(SUPPORT_OUTPUTDIR)/headers/jdk.attach \
diff --git a/jdk/make/lib/Lib-jdk.crypto.ec.gmk b/jdk/make/lib/Lib-jdk.crypto.ec.gmk
index 564eb402ae0..5781b777d1e 100644
--- a/jdk/make/lib/Lib-jdk.crypto.ec.gmk
+++ b/jdk/make/lib/Lib-jdk.crypto.ec.gmk
@@ -47,7 +47,7 @@ ifeq ($(ENABLE_INTREE_EC), yes)
LIBRARY := sunec, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBSUNEC_SRC), \
- LANG := C++, \
+ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
OPTIMIZATION := LOW, \
CFLAGS := $(filter-out $(ECC_JNI_SOLSPARC_FILTER), $(CFLAGS_JDKLIB)) \
$(BUILD_LIBSUNEC_FLAGS) \
diff --git a/jdk/make/lib/Lib-jdk.crypto.mscapi.gmk b/jdk/make/lib/Lib-jdk.crypto.mscapi.gmk
index bc7d1a9fe3a..a2816dfc26b 100644
--- a/jdk/make/lib/Lib-jdk.crypto.mscapi.gmk
+++ b/jdk/make/lib/Lib-jdk.crypto.mscapi.gmk
@@ -35,7 +35,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
LIBRARY := sunmscapi, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBSUNMSCAPI_SRC), \
- LANG := C++, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
-I$(LIBSUNMSCAPI_SRC), \
diff --git a/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk b/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk
index 0672aa3a359..748b131045c 100644
--- a/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk
+++ b/jdk/make/lib/Lib-jdk.crypto.pkcs11.gmk
@@ -34,7 +34,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJ2PKCS11, \
LIBRARY := j2pkcs11, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJ2PKCS11_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(addprefix -I, $(LIBJ2PKCS11_SRC)) \
$(LIBJAVA_HEADER_FLAGS) \
diff --git a/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk b/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk
index f66bd4554f9..22b865657a3 100644
--- a/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk
+++ b/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk
@@ -35,7 +35,6 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
LIBRARY := j2ucrypto, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJ2UCRYPTO_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(addprefix -I, $(LIBJ2UCRYPTO_SRC)), \
diff --git a/jdk/make/lib/Lib-jdk.deploy.osx.gmk b/jdk/make/lib/Lib-jdk.deploy.osx.gmk
index f68b9c065e3..51c56355b5b 100644
--- a/jdk/make/lib/Lib-jdk.deploy.osx.gmk
+++ b/jdk/make/lib/Lib-jdk.deploy.osx.gmk
@@ -35,7 +35,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBRARY := AppleScriptEngine, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBAPPLESCRIPTENGINE_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
-I$(LIBAPPLESCRIPTENGINE_SRC) \
@@ -68,7 +67,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBRARY := osx, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBOSX_DIRS), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBOSX_CFLAGS), \
diff --git a/jdk/make/lib/Lib-jdk.hprof.agent.gmk b/jdk/make/lib/Lib-jdk.hprof.agent.gmk
index 040abc35680..7c43331b33c 100644
--- a/jdk/make/lib/Lib-jdk.hprof.agent.gmk
+++ b/jdk/make/lib/Lib-jdk.hprof.agent.gmk
@@ -45,7 +45,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBHPROF, \
LIBRARY := hprof, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBHPROF_SRC), \
- LANG := C, \
OPTIMIZATION := $(LIBHPROF_OPTIMIZATION), \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
$(BUILD_LIBHPROF_CFLAGS), \
@@ -75,7 +74,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA_CRW_DEMO, \
LIBRARY := java_crw_demo, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJAVA_CRW_DEMO_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
$(addprefix -I, $(LIBJAVA_CRW_DEMO_SRC)), \
diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk
index e46a7276b71..eb1de3b43c1 100644
--- a/jdk/make/lib/Lib-jdk.jdi.gmk
+++ b/jdk/make/lib/Lib-jdk.jdi.gmk
@@ -43,7 +43,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
LIBRARY := dt_shmem, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBDT_SHMEM_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) -DUSE_MMAP \
$(LIBDT_SHMEM_CPPFLAGS), \
diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
index 75c5d3b6830..0743ac85a97 100644
--- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
+++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
@@ -40,7 +40,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBDT_SOCKET, \
LIBRARY := dt_socket, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBDT_SOCKET_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_CFLAGS_WARNINGS_ARE_ERRORS) -DUSE_MMAP \
$(LIBDT_SOCKET_CPPFLAGS), \
@@ -77,7 +76,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJDWP, \
LIBRARY := jdwp, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJDWP_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) -DJDWP_LOGGING \
$(LIBJDWP_CPPFLAGS) \
diff --git a/jdk/make/lib/Lib-jdk.pack200.gmk b/jdk/make/lib/Lib-jdk.pack200.gmk
index 105f1f8b713..e9baaa3dbef 100644
--- a/jdk/make/lib/Lib-jdk.pack200.gmk
+++ b/jdk/make/lib/Lib-jdk.pack200.gmk
@@ -32,7 +32,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBUNPACK, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(JDK_TOPDIR)/src/jdk.pack200/share/native/libunpack \
$(JDK_TOPDIR)/src/jdk.pack200/share/native/common-unpack, \
- LANG := C++, \
+ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKLIB) \
-DNO_ZLIB -DUNPACK_JNI -DFULL \
diff --git a/jdk/make/lib/Lib-jdk.sctp.gmk b/jdk/make/lib/Lib-jdk.sctp.gmk
index 61e236e94ff..15db8b3b380 100644
--- a/jdk/make/lib/Lib-jdk.sctp.gmk
+++ b/jdk/make/lib/Lib-jdk.sctp.gmk
@@ -41,7 +41,6 @@ ifeq ($(OPENJDK_TARGET_OS_TYPE), unix)
LIBRARY := sctp, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(JDK_TOPDIR)/src/jdk.sctp/$(OPENJDK_TARGET_OS_TYPE)/native/libsctp, \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
-I $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnio/ch \
diff --git a/jdk/make/lib/Lib-jdk.security.auth.gmk b/jdk/make/lib/Lib-jdk.security.auth.gmk
index 80f05da0298..61cd9a66d5c 100644
--- a/jdk/make/lib/Lib-jdk.security.auth.gmk
+++ b/jdk/make/lib/Lib-jdk.security.auth.gmk
@@ -42,7 +42,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAAS, \
LIBRARY := $(LIBJAAS_NAME), \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(call FindSrcDirsForLib, jdk.security.auth, jaas), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.security.auth, \
MAPFILE := $(LIBJAAS_MAPFILE), \
diff --git a/jdk/make/lib/NetworkingLibraries.gmk b/jdk/make/lib/NetworkingLibraries.gmk
index 4231121123e..0f4709301f6 100644
--- a/jdk/make/lib/NetworkingLibraries.gmk
+++ b/jdk/make/lib/NetworkingLibraries.gmk
@@ -29,7 +29,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNET, \
LIBRARY := net, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBNET_SRC_DIRS), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
$(LIBJAVA_HEADER_FLAGS) $(addprefix -I, $(LIBNET_SRC_DIRS)), \
diff --git a/jdk/make/lib/NioLibraries.gmk b/jdk/make/lib/NioLibraries.gmk
index fd973ccc535..71a65138a9d 100644
--- a/jdk/make/lib/NioLibraries.gmk
+++ b/jdk/make/lib/NioLibraries.gmk
@@ -65,7 +65,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNIO, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBNIO_SRC), \
EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \
- LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(BUILD_LIBNIO_CFLAGS), \
diff --git a/jdk/make/lib/PlatformLibraries.gmk b/jdk/make/lib/PlatformLibraries.gmk
index 0035b1dfbbb..74d535d9095 100644
--- a/jdk/make/lib/PlatformLibraries.gmk
+++ b/jdk/make/lib/PlatformLibraries.gmk
@@ -33,7 +33,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBRARY := osxapp, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBOSXAPP_SRC), \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(addprefix -I, $(LIBOSXAPP_SRC)) \
diff --git a/jdk/make/lib/SoundLibraries.gmk b/jdk/make/lib/SoundLibraries.gmk
index f123d179d7a..07bd1f28637 100644
--- a/jdk/make/lib/SoundLibraries.gmk
+++ b/jdk/make/lib/SoundLibraries.gmk
@@ -35,8 +35,6 @@ LIBJSOUND_CFLAGS := \
LIBJSOUND_SRC_FILES := Utilities.c Platform.c
-LIBJSOUND_LANG := C
-
EXTRA_SOUND_JNI_LIBS :=
LIBJSOUND_MIDIFILES := \
@@ -81,7 +79,7 @@ ifeq ($(OPENJDK_TARGET_OS), aix)
endif # OPENJDK_TARGET_OS aix
ifeq ($(OPENJDK_TARGET_OS), macosx)
- LIBJSOUND_LANG := C++
+ LIBJSOUND_TOOLCHAIN := TOOLCHAIN_LINK_CXX
LIBJSOUND_CFLAGS += -DX_PLATFORM=X_MACOSX \
-DUSE_PORTS=TRUE \
-DUSE_DAUDIO=TRUE \
@@ -124,7 +122,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJSOUND, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJSOUND_SRC_DIRS), \
INCLUDE_FILES := $(LIBJSOUND_SRC_FILES), \
- LANG := $(LIBJSOUND_LANG), \
+ TOOLCHAIN := $(LIBJSOUND_TOOLCHAIN), \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJSOUND_CFLAGS), \
@@ -169,7 +167,6 @@ ifneq ($(filter jsoundalsa, $(EXTRA_SOUND_JNI_LIBS)), )
PLATFORM_API_LinuxOS_ALSA_MidiOut.c \
PLATFORM_API_LinuxOS_ALSA_MidiUtils.c \
PLATFORM_API_LinuxOS_ALSA_Ports.c, \
- LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(ALSA_CFLAGS) \
$(LIBJSOUND_CFLAGS) \
@@ -201,7 +198,6 @@ ifneq ($(filter jsoundds, $(EXTRA_SOUND_JNI_LIBS)), )
SRC := $(LIBJSOUND_SRC_DIRS), \
INCLUDE_FILES := Utilities.c $(LIBJSOUND_DAUDIOFILES) \
PLATFORM_API_WinOS_DirectSound.cpp, \
- LANG := C++, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
$(LIBJSOUND_CFLAGS) \
diff --git a/jdk/make/mapfiles/launchers/mapfile-x86_64 b/jdk/make/mapfiles/launchers/mapfile-x86_64
index 61c2d1cc3f2..5700d67f2a0 100644
--- a/jdk/make/mapfiles/launchers/mapfile-x86_64
+++ b/jdk/make/mapfiles/launchers/mapfile-x86_64
@@ -34,6 +34,14 @@ SUNWprivate_1.1 {
_environ;
__environ_lock;
+ # These are needed by the c runtime in SS12u4
+ ___Argv;
+ __xargv;
+ __xargc;
+ _start;
+ __longdouble_used;
+ _lib_version;
+
local:
*;
};
diff --git a/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc b/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc
new file mode 100644
index 00000000000..63f2a41a478
--- /dev/null
+++ b/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-sparc
@@ -0,0 +1,41 @@
+#
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# Define library interface.
+
+SUNWprivate_1.1 {
+ global:
+ # These are needed by the c runtime in SS12u4
+ _environ;
+ __environ_lock;
+ ___Argv;
+ __xargv;
+ __xargc;
+ _start;
+ _lib_version;
+
+ local:
+ *;
+};
diff --git a/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-x86 b/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-x86
new file mode 100644
index 00000000000..60220b18ad3
--- /dev/null
+++ b/jdk/make/mapfiles/libunpack/mapfile-vers-unpack200-solaris-x86
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code 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
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# Define library interface.
+
+SUNWprivate_1.1 {
+ global:
+ # These are needed by the c runtime in SS12u4
+ _environ;
+ __environ_lock;
+ ___Argv;
+ __xargv;
+ __xargc;
+ _start;
+ __longdouble_used;
+ _lib_version;
+
+ local:
+ *;
+};
diff --git a/jdk/make/src/classes/build/tools/module/ext.modules b/jdk/make/src/classes/build/tools/module/ext.modules
index 934d4e9ba16..70e3bf49b0c 100644
--- a/jdk/make/src/classes/build/tools/module/ext.modules
+++ b/jdk/make/src/classes/build/tools/module/ext.modules
@@ -4,7 +4,7 @@ java.corba
java.transaction
java.xml.bind
java.xml.ws
-jdk.accessbridge
+jdk.accessibility
jdk.crypto.ec
jdk.crypto.mscapi
jdk.crypto.pkcs11
diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java
index 0ce3358aaad..c912a3f04f0 100644
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/RSACipher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -350,7 +350,7 @@ public final class RSACipher extends CipherSpi {
switch (mode) {
case MODE_SIGN:
data = padding.pad(buffer, 0, bufOfs);
- return RSACore.rsa(data, privateKey);
+ return RSACore.rsa(data, privateKey, true);
case MODE_VERIFY:
byte[] verifyBuffer = RSACore.convert(buffer, 0, bufOfs);
data = RSACore.rsa(verifyBuffer, publicKey);
@@ -360,7 +360,7 @@ public final class RSACipher extends CipherSpi {
return RSACore.rsa(data, publicKey);
case MODE_DECRYPT:
byte[] decryptBuffer = RSACore.convert(buffer, 0, bufOfs);
- data = RSACore.rsa(decryptBuffer, privateKey);
+ data = RSACore.rsa(decryptBuffer, privateKey, false);
return padding.unpad(data);
default:
throw new AssertionError("Internal error");
diff --git a/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java b/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java
index 6ae2262c5aa..cd84e62619d 100644
--- a/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java
+++ b/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java
@@ -28,6 +28,7 @@ package java.lang.ref;
import java.security.PrivilegedAction;
import java.security.AccessController;
import sun.misc.JavaLangAccess;
+import sun.misc.ManagedLocalsThread;
import sun.misc.SharedSecrets;
import sun.misc.VM;
@@ -126,7 +127,7 @@ final class Finalizer extends FinalReference
* The localized names come from the subclasses's
* getContents implementations, while the time zone
@@ -96,16 +79,12 @@ public abstract class TimeZoneNamesBundle extends OpenListResourceBundle {
*/
@Override
public Object handleGetObject(String key) {
- return handleGetObject(key, 5);
- }
-
- private String[] handleGetObject(String key, int n) {
String[] contents = (String[]) super.handleGetObject(key);
- if (contents == null) {
+ if (Objects.isNull(contents)) {
return null;
}
- int clen = Math.min(n - 1, contents.length);
- String[] tmpobj = new String[clen+1];
+ int clen = contents.length;
+ String[] tmpobj = new String[7];
tmpobj[0] = key;
System.arraycopy(contents, 0, tmpobj, 1, clen);
return tmpobj;
diff --git a/jdk/src/java.base/share/classes/sun/util/resources/en/TimeZoneNames_en_IE.java b/jdk/src/java.base/share/classes/sun/util/resources/en/TimeZoneNames_en_IE.java
index ce91613f6ba..14a74e860ad 100644
--- a/jdk/src/java.base/share/classes/sun/util/resources/en/TimeZoneNames_en_IE.java
+++ b/jdk/src/java.base/share/classes/sun/util/resources/en/TimeZoneNames_en_IE.java
@@ -47,7 +47,8 @@ public final class TimeZoneNames_en_IE extends TimeZoneNamesBundle {
protected final Object[][] getContents() {
return new Object[][] {
{"Europe/London", new String[] {"Greenwich Mean Time", "GMT",
- "Irish Summer Time", "IST" /*Dublin*/}},
+ "Irish Summer Time", "IST", /*Dublin*/
+ "Irish Time", "IT" /*Dublin*/}},
};
}
}
diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security
index 1d05aae8eba..b863516a481 100644
--- a/jdk/src/java.base/share/conf/security/java.security
+++ b/jdk/src/java.base/share/conf/security/java.security
@@ -533,4 +533,4 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024
#
# Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
-jdk.tls.disabledAlgorithms=SSLv3
+jdk.tls.disabledAlgorithms=SSLv3, RC4
diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
index eec35ea9518..28fc83a0b31 100644
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java
@@ -40,6 +40,7 @@ import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import sun.misc.ManagedLocalsThread;
/**
* A multi-threaded implementation of Selector for Windows.
@@ -403,7 +404,7 @@ final class WindowsSelectorImpl extends SelectorImpl {
}
// Represents a helper thread used for select.
- private final class SelectThread extends Thread {
+ private final class SelectThread extends ManagedLocalsThread {
private final int index; // index of this thread
final SubSelector subSelector;
private long lastRun = 0; // last run number
diff --git a/jdk/src/java.base/windows/conf/security/java.policy b/jdk/src/java.base/windows/conf/security/java.policy
index 01d7bef3f43..cff0be5af98 100644
--- a/jdk/src/java.base/windows/conf/security/java.policy
+++ b/jdk/src/java.base/windows/conf/security/java.policy
@@ -6,3 +6,7 @@ grant codeBase "jrt:/jdk.crypto.mscapi" {
permission java.security.SecurityPermission "clearProviderProperties.SunMSCAPI";
permission java.security.SecurityPermission "removeProviderProperty.SunMSCAPI";
};
+
+grant codeBase "jrt:/jdk.accessibility" {
+ permission java.security.AllPermission;
+};
diff --git a/jdk/src/java.base/windows/native/launcher/java.manifest b/jdk/src/java.base/windows/native/launcher/java.manifest
index 52f997e8b39..906624bd6fa 100644
--- a/jdk/src/java.base/windows/native/launcher/java.manifest
+++ b/jdk/src/java.base/windows/native/launcher/java.manifest
@@ -4,12 +4,12 @@
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
>
-Java(TM) SE PROGRAM process
+Java(TM) SE process= 6;
+ if (dtzi.TimeZoneKeyName[0] != 0) {
+ if (dtzi.DynamicDaylightTimeDisabled) {
+ customZoneName(dtzi.Bias, winZoneName);
+ return VALUE_GMTOFFSET;
+ }
+ wcstombs(winZoneName, dtzi.TimeZoneKeyName, MAX_ZONE_CHAR);
+ return VALUE_KEY;
+ }
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
- KEY_READ, (PHKEY)&hKey);
- if (ret == ERROR_SUCCESS) {
- DWORD val;
- DWORD bufSize;
+ /*
+ * If TimeZoneKeyName is not available, check whether StandardName
+ * is available to fall back to the older API GetTimeZoneInformation.
+ * If not, directly read the value from registry keys.
+ */
+ if (dtzi.StandardName[0] == 0) {
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
+ KEY_READ, (PHKEY)&hKey);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
+ }
/*
* Determine if auto-daylight time adjustment is turned off.
*/
- valueType = 0;
bufSize = sizeof(val);
- ret = RegQueryValueExA(hKey, "DisableAutoDaylightTimeSet",
- NULL, &valueType, (LPBYTE) &val, &bufSize);
- /*
- * Vista uses the different key name.
- */
+ ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", NULL,
+ &valueType, (LPBYTE) &val, &bufSize);
if (ret != ERROR_SUCCESS) {
- bufSize = sizeof(val);
- ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled",
- NULL, &valueType, (LPBYTE) &val, &bufSize);
+ goto err;
}
-
- if (ret == ERROR_SUCCESS) {
- int daylightSavingsUpdateDisabledOther = val == 1 && tzi.DaylightDate.wMonth != 0;
- int daylightSavingsUpdateDisabledVista = val == 1;
- int daylightSavingsUpdateDisabled = isVista ? daylightSavingsUpdateDisabledVista : daylightSavingsUpdateDisabledOther;
-
- if (daylightSavingsUpdateDisabled) {
- (void) RegCloseKey(hKey);
- customZoneName(tzi.Bias, winZoneName);
- return VALUE_GMTOFFSET;
- }
- }
-
/*
- * Vista has the key for the current "Time Zones" entry.
+ * Return a custom time zone name if auto-daylight time adjustment
+ * is disabled.
*/
- if (isVista) {
- valueType = 0;
- bufSize = MAX_ZONE_CHAR;
- ret = RegQueryValueExA(hKey, "TimeZoneKeyName", NULL,
- &valueType, (LPBYTE) winZoneName, &bufSize);
- if (ret != ERROR_SUCCESS) {
- goto err;
- }
+ if (val == 1) {
+ customZoneName(dtzi.Bias, winZoneName);
(void) RegCloseKey(hKey);
- return VALUE_KEY;
+ return VALUE_GMTOFFSET;
}
- /*
- * Win32 problem: If the length of the standard time name is equal
- * to (or probably longer than) 32 in the registry,
- * GetTimeZoneInformation() on NT returns a null string as its
- * standard time name. We need to work around this problem by
- * getting the same information from the TimeZoneInformation
- * registry. The function on Win98 seems to return its key name.
- * We can't do anything in that case.
- */
- if (tzi.StandardName[0] == 0) {
- bufSize = sizeof(stdNameInReg);
- ret = getValueInRegistry(hKey, STANDARD_NAME, &valueType,
- (LPBYTE) stdNameInReg, &bufSize);
- if (ret != ERROR_SUCCESS) {
- goto err;
- }
- stdNamePtr = stdNameInReg;
+ bufSize = MAX_ZONE_CHAR;
+ ret = RegQueryValueExA(hKey, "TimeZoneKeyName", NULL,
+ &valueType, (LPBYTE) winZoneName, &bufSize);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
}
(void) RegCloseKey(hKey);
- }
-
- /*
- * Open the "Time Zones" registry.
- */
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NT_TZ_KEY, 0, KEY_READ, (PHKEY)&hKey);
- if (ret != ERROR_SUCCESS) {
- ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_TZ_KEY, 0, KEY_READ, (PHKEY)&hKey);
+ return VALUE_KEY;
+ } else {
/*
- * If both failed, then give up.
+ * Fall back to GetTimeZoneInformation
*/
- if (ret != ERROR_SUCCESS) {
- return VALUE_UNKNOWN;
- }
- }
+ TIME_ZONE_INFORMATION tzi;
+ HANDLE hSubKey = NULL;
+ DWORD nSubKeys, i;
+ ULONG valueType;
+ TCHAR subKeyName[MAX_ZONE_CHAR];
+ TCHAR szValue[MAX_ZONE_CHAR];
+ WCHAR stdNameInReg[MAX_ZONE_CHAR];
+ TziValue tempTzi;
+ WCHAR *stdNamePtr = tzi.StandardName;
+ DWORD valueSize;
+ int onlyMapID;
- /*
- * Get the number of subkeys of the "Time Zones" registry for
- * enumeration.
- */
- ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, &nSubKeys,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- if (ret != ERROR_SUCCESS) {
- goto err;
- }
-
- /*
- * Compare to the "Std" value of each subkey and find the entry that
- * matches the current control panel setting.
- */
- onlyMapID = 0;
- for (i = 0; i < nSubKeys; ++i) {
- DWORD size = sizeof(subKeyName);
- ret = RegEnumKeyEx(hKey, i, subKeyName, &size, NULL, NULL, NULL, NULL);
- if (ret != ERROR_SUCCESS) {
- goto err;
- }
- ret = RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, (PHKEY)&hSubKey);
- if (ret != ERROR_SUCCESS) {
+ timeType = GetTimeZoneInformation(&tzi);
+ if (timeType == TIME_ZONE_ID_INVALID) {
goto err;
}
- size = sizeof(szValue);
- ret = getValueInRegistry(hSubKey, STD_NAME, &valueType,
- szValue, &size);
- if (ret != ERROR_SUCCESS) {
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_CURRENT_TZ_KEY, 0,
+ KEY_READ, (PHKEY)&hKey);
+ if (ret == ERROR_SUCCESS) {
/*
- * NT 4.0 SP3 fails here since it doesn't have the "Std"
- * entry in the Time Zones registry.
+ * Determine if auto-daylight time adjustment is turned off.
*/
- RegCloseKey(hSubKey);
- onlyMapID = 1;
- ret = RegOpenKeyExW(hKey, stdNamePtr, 0, KEY_READ, (PHKEY)&hSubKey);
+ bufSize = sizeof(val);
+ ret = RegQueryValueExA(hKey, "DynamicDaylightTimeDisabled", NULL,
+ &valueType, (LPBYTE) &val, &bufSize);
+ if (ret == ERROR_SUCCESS) {
+ if (val == 1 && tzi.DaylightDate.wMonth != 0) {
+ (void) RegCloseKey(hKey);
+ customZoneName(tzi.Bias, winZoneName);
+ return VALUE_GMTOFFSET;
+ }
+ }
+
+ /*
+ * Win32 problem: If the length of the standard time name is equal
+ * to (or probably longer than) 32 in the registry,
+ * GetTimeZoneInformation() on NT returns a null string as its
+ * standard time name. We need to work around this problem by
+ * getting the same information from the TimeZoneInformation
+ * registry.
+ */
+ if (tzi.StandardName[0] == 0) {
+ bufSize = sizeof(stdNameInReg);
+ ret = getValueInRegistry(hKey, STANDARD_NAME, &valueType,
+ (LPBYTE) stdNameInReg, &bufSize);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
+ }
+ stdNamePtr = stdNameInReg;
+ }
+ (void) RegCloseKey(hKey);
+ }
+
+ /*
+ * Open the "Time Zones" registry.
+ */
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, NT_TZ_KEY, 0, KEY_READ, (PHKEY)&hKey);
+ if (ret != ERROR_SUCCESS) {
+ ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_TZ_KEY, 0, KEY_READ, (PHKEY)&hKey);
+ /*
+ * If both failed, then give up.
+ */
+ if (ret != ERROR_SUCCESS) {
+ return VALUE_UNKNOWN;
+ }
+ }
+
+ /*
+ * Get the number of subkeys of the "Time Zones" registry for
+ * enumeration.
+ */
+ ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, &nSubKeys,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
+ }
+
+ /*
+ * Compare to the "Std" value of each subkey and find the entry that
+ * matches the current control panel setting.
+ */
+ onlyMapID = 0;
+ for (i = 0; i < nSubKeys; ++i) {
+ DWORD size = sizeof(subKeyName);
+ ret = RegEnumKeyEx(hKey, i, subKeyName, &size, NULL, NULL, NULL, NULL);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
+ }
+ ret = RegOpenKeyEx(hKey, subKeyName, 0, KEY_READ, (PHKEY)&hSubKey);
if (ret != ERROR_SUCCESS) {
goto err;
}
- break;
- }
- if (wcscmp((WCHAR *)szValue, stdNamePtr) == 0) {
- /*
- * Some localized Win32 platforms use a same name to
- * different time zones. So, we can't rely only on the name
- * here. We need to check GMT offsets and transition dates
- * to make sure it's the registry of the current time
- * zone.
- */
- DWORD tziValueSize = sizeof(tempTzi);
- ret = RegQueryValueEx(hSubKey, "TZI", NULL, &valueType,
- (unsigned char *) &tempTzi, &tziValueSize);
- if (ret == ERROR_SUCCESS) {
- if ((tzi.Bias != tempTzi.bias) ||
- (memcmp((const void *) &tzi.StandardDate,
- (const void *) &tempTzi.stdDate,
- sizeof(SYSTEMTIME)) != 0)) {
- goto out;
+ size = sizeof(szValue);
+ ret = getValueInRegistry(hSubKey, STD_NAME, &valueType,
+ szValue, &size);
+ if (ret != ERROR_SUCCESS) {
+ /*
+ * NT 4.0 SP3 fails here since it doesn't have the "Std"
+ * entry in the Time Zones registry.
+ */
+ RegCloseKey(hSubKey);
+ onlyMapID = 1;
+ ret = RegOpenKeyExW(hKey, stdNamePtr, 0, KEY_READ, (PHKEY)&hSubKey);
+ if (ret != ERROR_SUCCESS) {
+ goto err;
}
+ break;
+ }
- if (tzi.DaylightBias != 0) {
- if ((tzi.DaylightBias != tempTzi.dstBias) ||
- (memcmp((const void *) &tzi.DaylightDate,
- (const void *) &tempTzi.dstDate,
+ if (wcscmp((WCHAR *)szValue, stdNamePtr) == 0) {
+ /*
+ * Some localized Win32 platforms use a same name to
+ * different time zones. So, we can't rely only on the name
+ * here. We need to check GMT offsets and transition dates
+ * to make sure it's the registry of the current time
+ * zone.
+ */
+ DWORD tziValueSize = sizeof(tempTzi);
+ ret = RegQueryValueEx(hSubKey, "TZI", NULL, &valueType,
+ (unsigned char *) &tempTzi, &tziValueSize);
+ if (ret == ERROR_SUCCESS) {
+ if ((tzi.Bias != tempTzi.bias) ||
+ (memcmp((const void *) &tzi.StandardDate,
+ (const void *) &tempTzi.stdDate,
sizeof(SYSTEMTIME)) != 0)) {
goto out;
}
+
+ if (tzi.DaylightBias != 0) {
+ if ((tzi.DaylightBias != tempTzi.dstBias) ||
+ (memcmp((const void *) &tzi.DaylightDate,
+ (const void *) &tempTzi.dstDate,
+ sizeof(SYSTEMTIME)) != 0)) {
+ goto out;
+ }
+ }
}
+
+ /*
+ * found matched record, terminate search
+ */
+ strcpy(winZoneName, subKeyName);
+ break;
}
-
- /*
- * found matched record, terminate search
- */
- strcpy(winZoneName, subKeyName);
- break;
+ out:
+ (void) RegCloseKey(hSubKey);
}
- out:
- (void) RegCloseKey(hSubKey);
- }
- /*
- * Get the "MapID" value of the registry to be able to eliminate
- * duplicated key names later.
- */
- valueSize = MAX_MAPID_LENGTH;
- ret = RegQueryValueExA(hSubKey, "MapID", NULL, &valueType, winMapID, &valueSize);
- (void) RegCloseKey(hSubKey);
- (void) RegCloseKey(hKey);
-
- if (ret != ERROR_SUCCESS) {
/*
- * Vista doesn't have mapID. VALUE_UNKNOWN should be returned
- * only for Windows NT.
+ * Get the "MapID" value of the registry to be able to eliminate
+ * duplicated key names later.
*/
- if (onlyMapID == 1) {
- return VALUE_UNKNOWN;
+ valueSize = MAX_MAPID_LENGTH;
+ ret = RegQueryValueExA(hSubKey, "MapID", NULL, &valueType, winMapID, &valueSize);
+ (void) RegCloseKey(hSubKey);
+ (void) RegCloseKey(hKey);
+
+ if (ret != ERROR_SUCCESS) {
+ /*
+ * Vista doesn't have mapID. VALUE_UNKNOWN should be returned
+ * only for Windows NT.
+ */
+ if (onlyMapID == 1) {
+ return VALUE_UNKNOWN;
+ }
}
}
diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java
index b0713215077..7aa82f51a9e 100644
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaFileSystemModel.java
@@ -25,15 +25,16 @@
package com.apple.laf;
+
import java.beans.*;
import java.io.File;
import java.util.*;
-
import javax.swing.*;
import javax.swing.event.ListDataEvent;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.AbstractTableModel;
+import sun.misc.ManagedLocalsThread;
/**
* NavServices-like implementation of a file Table
*
@@ -42,7 +43,7 @@ import javax.swing.table.AbstractTableModel;
@SuppressWarnings("serial") // Superclass is not serializable across versions
class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeListener {
private final JTable fFileList;
- private LoadFilesThread loadThread = null;
+ private FilesLoader filesLoader = null;
private Vector files = null;
JFileChooser filechooser = null;
@@ -141,9 +142,9 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi
public void runWhenDone(final Runnable runnable){
synchronized (fileCacheLock) {
- if (loadThread != null) {
- if (loadThread.isAlive()) {
- loadThread.queuedTasks.add(runnable);
+ if (filesLoader != null) {
+ if (filesLoader.loadThread.isAlive()) {
+ filesLoader.queuedTasks.add(runnable);
return;
}
}
@@ -160,9 +161,9 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi
return;
}
- if (loadThread != null) {
+ if (filesLoader != null) {
// interrupt
- loadThread.interrupt();
+ filesLoader.loadThread.interrupt();
}
fetchID++;
@@ -173,8 +174,7 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi
fileCache = new Vector(50);
}
- loadThread = new LoadFilesThread(currentDirectory, fetchID);
- loadThread.start();
+ filesLoader = new FilesLoader(currentDirectory, fetchID);
}
public int getColumnCount() {
@@ -373,17 +373,25 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi
}
}
- class LoadFilesThread extends Thread {
- Vector queuedTasks = new Vector();
+ class FilesLoader implements Runnable {
+ Vector queuedTasks = new Vector<>();
File currentDirectory = null;
int fid;
+ Thread loadThread;
- public LoadFilesThread(final File currentDirectory, final int fid) {
- super("Aqua L&F File Loading Thread");
+ public FilesLoader(final File currentDirectory, final int fid) {
this.currentDirectory = currentDirectory;
this.fid = fid;
+ String name = "Aqua L&F File Loading Thread";
+ if (System.getSecurityManager() == null) {
+ this.loadThread = new Thread(FilesLoader.this, name);
+ } else {
+ this.loadThread = new ManagedLocalsThread(FilesLoader.this, name);
+ }
+ this.loadThread.start();
}
+ @Override
public void run() {
final Vector runnables = new Vector(10);
final FileSystemView fileSystem = filechooser.getFileSystemView();
@@ -415,7 +423,7 @@ class AquaFileSystemModel extends AbstractTableModel implements PropertyChangeLi
runnables.addElement(runnable);
SwingUtilities.invokeLater(runnable);
chunk = new Vector(10);
- if (isInterrupted()) {
+ if (loadThread.isInterrupted()) {
// interrupted, cancel all runnables
cancelRunnables(runnables);
return;
diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollPaneUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollPaneUI.java
index ee0bf7cdf54..0729321552d 100644
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollPaneUI.java
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaScrollPaneUI.java
@@ -29,6 +29,7 @@ import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.basic.BasicScrollPaneUI;
public class AquaScrollPaneUI extends javax.swing.plaf.basic.BasicScrollPaneUI {
public static ComponentUI createUI(final JComponent x) {
@@ -39,28 +40,9 @@ public class AquaScrollPaneUI extends javax.swing.plaf.basic.BasicScrollPaneUI {
return new XYMouseWheelHandler();
}
- // This is a grody hack to trick BasicScrollPaneUI into scrolling horizontally
- // when we notice that the shift key is down. This should be removed when AWT/Swing
- // becomes aware of multi-axis scroll wheels.
- protected class XYMouseWheelHandler extends javax.swing.plaf.basic.BasicScrollPaneUI.MouseWheelHandler {
+ protected class XYMouseWheelHandler extends BasicScrollPaneUI.MouseWheelHandler {
public void mouseWheelMoved(final MouseWheelEvent e) {
- JScrollBar vScrollBar = null;
- boolean wasVisible = false;
-
- if (e.isShiftDown()) {
- vScrollBar = scrollpane.getVerticalScrollBar();
- if (vScrollBar != null) {
- wasVisible = vScrollBar.isVisible();
- vScrollBar.setVisible(false);
- }
- }
-
super.mouseWheelMoved(e);
-
- if (wasVisible) {
- vScrollBar.setVisible(true);
- }
-
// Consume the event even when the scrollBar is invisible
// see #7124320
e.consume();
diff --git a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java
index 272999ee6b9..341af9ff347 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java
@@ -42,6 +42,7 @@ import sun.awt.FontConfiguration;
import sun.awt.HeadlessToolkit;
import sun.awt.util.ThreadGroupUtils;
import sun.lwawt.macosx.*;
+import sun.misc.InnocuousThread;
public final class CFontManager extends SunFontManager {
private static Hashtable genericFonts = new Hashtable();
@@ -211,14 +212,18 @@ public final class CFontManager extends SunFontManager {
});
}
};
- AccessController.doPrivileged(
- (PrivilegedAction) () -> {
- /* The thread must be a member of a thread group
- * which will not get GCed before VM exit.
- * Make its parent the top-level thread group.
- */
- ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
- fileCloser = new Thread(rootTG, fileCloserRunnable);
+ AccessController.doPrivileged((PrivilegedAction) () -> {
+ if (System.getSecurityManager() == null) {
+ /* The thread must be a member of a thread group
+ * which will not get GCed before VM exit.
+ * Make its parent the top-level thread group.
+ */
+ ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
+ fileCloser = new Thread(rootTG, fileCloserRunnable);
+ } else {
+ /* InnocuousThread is a member of a correct TG by default */
+ fileCloser = new InnocuousThread(fileCloserRunnable);
+ }
fileCloser.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(fileCloser);
return null;
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWCheckboxPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWCheckboxPeer.java
index c3b91a2fa86..fe85cce8081 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWCheckboxPeer.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWCheckboxPeer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -132,7 +132,9 @@ final class LWCheckboxPeer
@Override
public void setState(final boolean state) {
synchronized (getDelegateLock()) {
+ getDelegate().getCurrentButton().removeItemListener(this);
getDelegate().setSelected(state);
+ getDelegate().getCurrentButton().addItemListener(this);
}
repaintPeer();
}
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java
index 315a19a7ff3..9aea94cdc6c 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java
@@ -35,6 +35,7 @@ import java.security.*;
import java.util.*;
import sun.awt.*;
+import sun.misc.InnocuousThread;
import sun.print.*;
import sun.awt.util.ThreadGroupUtils;
@@ -71,22 +72,32 @@ public abstract class LWToolkit extends SunToolkit implements Runnable {
*/
protected final void init() {
AWTAutoShutdown.notifyToolkitThreadBusy();
-
- ThreadGroup rootTG = AccessController.doPrivileged(
- (PrivilegedAction) ThreadGroupUtils::getRootThreadGroup);
-
- Runtime.getRuntime().addShutdownHook(
- new Thread(rootTG, () -> {
+ AccessController.doPrivileged((PrivilegedAction) () -> {
+ Runnable shutdownRunnable = () -> {
shutdown();
waitForRunState(STATE_CLEANUP);
- })
- );
-
- Thread toolkitThread = new Thread(rootTG, this, "AWT-LW");
- toolkitThread.setDaemon(true);
- toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
- toolkitThread.start();
+ };
+ Thread shutdown;
+ if (System.getSecurityManager() == null) {
+ shutdown = new Thread(ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable);
+ } else {
+ shutdown = new InnocuousThread(shutdownRunnable);
+ }
+ shutdown.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(shutdown);
+ String name = "AWT-LW";
+ Thread toolkitThread;
+ if (System.getSecurityManager() == null) {
+ toolkitThread = new Thread(ThreadGroupUtils.getRootThreadGroup(), LWToolkit.this, name);
+ } else {
+ toolkitThread = new InnocuousThread(LWToolkit.this, name);
+ }
+ toolkitThread.setDaemon(true);
+ toolkitThread.setPriority(Thread.NORM_PRIORITY + 1);
+ toolkitThread.start();
+ return null;
+ });
waitForRunState(STATE_MESSAGELOOP);
}
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java
index 386c8c7bb7f..d8656c58750 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java
@@ -1296,6 +1296,12 @@ public class LWWindowPeer
}
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
+
+ if (!becomesFocused && kfmPeer.getCurrentFocusedWindow() != getTarget()) {
+ // late window focus lost event - ingoring
+ return;
+ }
+
kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null);
int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS;
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CClipboard.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CClipboard.java
index b657aee8ed9..19f9a408220 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CClipboard.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CClipboard.java
@@ -56,6 +56,18 @@ final class CClipboard extends SunClipboard {
// Leaving Empty, as WClipboard.clearNativeContext is empty as well.
}
+ @Override
+ public synchronized Transferable getContents(Object requestor) {
+ checkPasteboardAndNotify();
+ return super.getContents(requestor);
+ }
+
+ @Override
+ protected synchronized Transferable getContextContents() {
+ checkPasteboardAndNotify();
+ return super.getContextContents();
+ }
+
@Override
protected void setContentsNative(Transferable contents) {
FlavorTable flavorMap = getDefaultFlavorTable();
@@ -116,13 +128,20 @@ final class CClipboard extends SunClipboard {
private native void declareTypes(long[] formats, SunClipboard newOwner);
private native void setData(byte[] data, long format);
+ void checkPasteboardAndNotify() {
+ if (checkPasteboardWithoutNotification()) {
+ notifyChanged();
+ lostOwnershipNow(null);
+ }
+ }
+
/**
* Invokes native check whether a change count on the general pasteboard is different
* than when we set it. The different count value means the current owner lost
* pasteboard ownership and someone else put data on the clipboard.
* @since 1.7
*/
- native void checkPasteboard();
+ native boolean checkPasteboardWithoutNotification();
/*** Native Callbacks ***/
private void notifyLostOwnership() {
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java
index 20c48cd4133..0f4224bb803 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CDragSourceContextPeer.java
@@ -31,7 +31,6 @@ import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.event.*;
import java.awt.image.*;
-import java.awt.peer.*;
import javax.swing.*;
import javax.swing.text.*;
@@ -44,6 +43,7 @@ import sun.awt.dnd.*;
import sun.lwawt.LWComponentPeer;
import sun.lwawt.LWWindowPeer;
import sun.lwawt.PlatformWindow;
+import sun.misc.ManagedLocalsThread;
public final class CDragSourceContextPeer extends SunDragSourceContextPeer {
@@ -164,28 +164,29 @@ public final class CDragSourceContextPeer extends SunDragSourceContextPeer {
// are posted during dragging by native event handlers.
try {
- Thread dragThread = new Thread() {
- public void run() {
- final long nativeDragSource = getNativeContext();
- try {
- doDragging(nativeDragSource);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- releaseNativeDragSource(nativeDragSource);
- fDragImage = null;
- if (fDragCImage != null) {
- fDragCImage.dispose();
- fDragCImage = null;
- }
+ Runnable dragRunnable = () -> {
+ final long nativeDragSource = getNativeContext();
+ try {
+ doDragging(nativeDragSource);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ releaseNativeDragSource(nativeDragSource);
+ fDragImage = null;
+ if (fDragCImage != null) {
+ fDragCImage.dispose();
+ fDragCImage = null;
}
}
};
-
+ Thread dragThread;
+ if (System.getSecurityManager() == null) {
+ dragThread = new Thread(dragRunnable);
+ } else {
+ dragThread = new ManagedLocalsThread(dragRunnable);
+ }
dragThread.start();
- }
-
- catch (Exception e) {
+ } catch (Exception e) {
final long nativeDragSource = getNativeContext();
setNativeContext(0);
releaseNativeDragSource(nativeDragSource);
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
index fed9957502a..e1895c2e2f0 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java
@@ -123,7 +123,7 @@ public class CEmbeddedFrame extends EmbeddedFrame {
// it won't be invoced if focuse is moved to a html element
// on the same page.
CClipboard clipboard = (CClipboard) Toolkit.getDefaultToolkit().getSystemClipboard();
- clipboard.checkPasteboard();
+ clipboard.checkPasteboardAndNotify();
}
if (parentWindowActive) {
responder.handleWindowFocusEvent(focused, null);
@@ -164,7 +164,7 @@ public class CEmbeddedFrame extends EmbeddedFrame {
}
// ignore focus "lost" native request as it may mistakenly
// deactivate active window (see 8001161)
- if (globalFocusedWindow == this && parentWindowActive) {
+ if (globalFocusedWindow == this) {
responder.handleWindowFocusEvent(parentWindowActive, null);
}
}
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java
index cc31b532f76..0e8ee1e1fc4 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java
@@ -37,6 +37,7 @@ import java.io.*;
import sun.awt.CausedFocusEvent.Cause;
import sun.awt.AWTAccessor;
import sun.java2d.pipe.Region;
+import sun.misc.ManagedLocalsThread;
import sun.security.action.GetBooleanAction;
class CFileDialog implements FileDialogPeer {
@@ -119,7 +120,11 @@ class CFileDialog implements FileDialogPeer {
if (visible) {
// Java2 Dialog class requires peer to run code in a separate thread
// and handles keeping the call modal
- new Thread(new Task()).start(); // invokes my 'run' method, below...
+ if (System.getSecurityManager() == null) {
+ new Thread(new Task()).start();
+ } else {
+ new ManagedLocalsThread(new Task()).start();
+ }
}
// We hide ourself before "show" returns - setVisible(false)
// doesn't apply
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java
index 8dfe7e1e51e..6ff3ec01e0e 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterDialogPeer.java
@@ -29,6 +29,7 @@ import java.awt.*;
import java.awt.dnd.*;
import sun.lwawt.*;
+import sun.misc.ManagedLocalsThread;
public class CPrinterDialogPeer extends LWWindowPeer {
static {
@@ -53,13 +54,16 @@ public class CPrinterDialogPeer extends LWWindowPeer {
public void setVisible(boolean visible) {
if (visible) {
- new Thread(new Runnable() {
- public void run() {
- CPrinterDialog printerDialog = (CPrinterDialog)fTarget;
- printerDialog.setRetVal(printerDialog.showDialog());
- printerDialog.setVisible(false);
- }
- }).start();
+ Runnable task = () -> {
+ CPrinterDialog printerDialog = (CPrinterDialog)fTarget;
+ printerDialog.setRetVal(printerDialog.showDialog());
+ printerDialog.setVisible(false);
+ };
+ if (System.getSecurityManager() == null) {
+ new Thread(task).start();
+ } else {
+ new ManagedLocalsThread(task).start();
+ }
}
}
diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java
index ede3bec7b73..b82094d5b7d 100644
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java
@@ -39,6 +39,7 @@ import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.PageRanges;
import sun.java2d.*;
+import sun.misc.ManagedLocalsThread;
import sun.print.*;
public final class CPrinterJob extends RasterPrinterJob {
@@ -731,9 +732,12 @@ public final class CPrinterJob extends RasterPrinterJob {
// upcall from native
private static void detachPrintLoop(final long target, final long arg) {
- new Thread() { public void run() {
- _safePrintLoop(target, arg);
- }}.start();
+ Runnable task = () -> _safePrintLoop(target, arg);
+ if (System.getSecurityManager() == null) {
+ new Thread(task).start();
+ } else {
+ new ManagedLocalsThread(task).start();
+ }
}
private static native void _safePrintLoop(long target, long arg);
diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m
index 15ae6db79dc..fceb2d72682 100644
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m
@@ -107,6 +107,19 @@
}
}
+- (BOOL) checkPasteboardWithoutNotification:(id)application {
+ AWT_ASSERT_APPKIT_THREAD;
+
+ NSInteger newChangeCount = [[NSPasteboard generalPasteboard] changeCount];
+
+ if (self.changeCount != newChangeCount) {
+ self.changeCount = newChangeCount;
+ return YES;
+ } else {
+ return NO;
+ }
+}
+
@end
/*
@@ -260,21 +273,20 @@ JNF_COCOA_EXIT(env);
return returnValue;
}
-/*
- * Class: sun_lwawt_macosx_CClipboard
- * Method: checkPasteboard
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboard
-(JNIEnv *env, jobject inObject )
-{
-JNF_COCOA_ENTER(env);
-
- [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
- [[CClipboard sharedClipboard] checkPasteboard:nil];
- }];
-
-JNF_COCOA_EXIT(env);
-}
-
-
+/*
+ * Class: sun_lwawt_macosx_CClipboard
+ * Method: checkPasteboard
+ * Signature: ()V
+ */
+JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_CClipboard_checkPasteboardWithoutNotification
+(JNIEnv *env, jobject inObject)
+{
+ __block BOOL ret = NO;
+ JNF_COCOA_ENTER(env);
+ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
+ ret = [[CClipboard sharedClipboard] checkPasteboardWithoutNotification:nil];
+ }];
+
+ JNF_COCOA_EXIT(env);
+ return ret;
+}
\ No newline at end of file
diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java
index 356c0c092f9..b660f272e2c 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/stream/StreamCloser.java
@@ -25,7 +25,12 @@
package com.sun.imageio.stream;
+import sun.awt.util.ThreadGroupUtils;
+import sun.misc.InnocuousThread;
+
import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Set;
import java.util.WeakHashMap;
import javax.imageio.stream.ImageInputStream;
@@ -81,27 +86,25 @@ public class StreamCloser {
}
};
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
- /* The thread must be a member of a thread group
- * which will not get GCed before VM exit.
- * Make its parent the top-level thread group.
- */
- ThreadGroup tg =
- Thread.currentThread().getThreadGroup();
- for (ThreadGroup tgn = tg;
- tgn != null;
- tg = tgn, tgn = tg.getParent());
- streamCloser = new Thread(tg, streamCloserRunnable);
- /* Set context class loader to null in order to avoid
- * keeping a strong reference to an application classloader.
- */
- streamCloser.setContextClassLoader(null);
- Runtime.getRuntime().addShutdownHook(streamCloser);
- return null;
- }
- });
+ AccessController.doPrivileged((PrivilegedAction) () -> {
+ if (System.getSecurityManager() == null) {
+ /* The thread must be a member of a thread group
+ * which will not get GCed before VM exit.
+ * Make its parent the top-level thread group.
+ */
+ ThreadGroup tg = ThreadGroupUtils.getRootThreadGroup();
+ streamCloser = new Thread(tg, streamCloserRunnable);
+ } else {
+ /* InnocuousThread is a member of a correct TG by default */
+ streamCloser = new InnocuousThread(streamCloserRunnable);
+ }
+ /* Set context class loader to null in order to avoid
+ * keeping a strong reference to an application classloader.
+ */
+ streamCloser.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(streamCloser);
+ return null;
+ });
}
}
}
diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java
index 16eef680706..82708f571e5 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java
@@ -68,7 +68,7 @@ public class WindowsDesktopManager extends DefaultDesktopManager
if (currentFrame != null && f != currentFrame) {
// If the current frame is maximized, transfer that
// attribute to the frame being activated.
- if (currentFrame.isMaximum() &&
+ if (!currentFrame.isClosed() && currentFrame.isMaximum() &&
(f.getClientProperty("JInternalFrame.frameType") !=
"optionDialog") ) {
//Special case. If key binding was used to select next
diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java
index ee81a15f637..0a666b12e25 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsLookAndFeel.java
@@ -64,6 +64,7 @@ import sun.awt.SunToolkit;
import sun.awt.OSInfo;
import sun.awt.shell.ShellFolder;
import sun.font.FontUtilities;
+import sun.misc.ManagedLocalsThread;
import sun.security.action.GetPropertyAction;
import sun.swing.DefaultLayoutStyle;
@@ -2037,7 +2038,11 @@ public class WindowsLookAndFeel extends BasicLookAndFeel
if (audioRunnable != null) {
// Runnable appears to block until completed playing, hence
// start up another thread to handle playing.
- new Thread(audioRunnable).start();
+ if (System.getSecurityManager() == null) {
+ new Thread(audioRunnable).start();
+ } else {
+ new ManagedLocalsThread(audioRunnable).start();
+ }
}
}
}
diff --git a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java
index ec505959a31..347f2943155 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/WindowsRootPaneUI.java
@@ -197,6 +197,10 @@ public class WindowsRootPaneUI extends BasicRootPaneUI {
root = null;
winAncestor = null;
} else {
+ if (WindowsLookAndFeel.isMnemonicHidden() && ev.isAltDown()) {
+ WindowsLookAndFeel.setMnemonicHidden(false);
+ WindowsGraphicsUtils.repaintMnemonicsInWindow(winAncestor);
+ }
altKeyPressed = false;
}
return false;
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java
index 8382f15e8c2..63eaba1c4ec 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java
@@ -25,6 +25,9 @@
package com.sun.media.sound;
+import sun.misc.InnocuousThread;
+import sun.misc.ManagedLocalsThread;
+
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.File;
@@ -144,7 +147,13 @@ final class JSSecurityManager {
final String threadName,
final boolean isDaemon, final int priority,
final boolean doStart) {
- Thread thread = new Thread(runnable);
+ Thread thread;
+ if (System.getSecurityManager() == null) {
+ thread = new Thread(runnable);
+ } else {
+ thread = new ManagedLocalsThread(runnable);
+ }
+
if (threadName != null) {
thread.setName(threadName);
}
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java
index 1a07a23ec6f..a5fdd4e9f86 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftAudioPusher.java
@@ -24,6 +24,8 @@
*/
package com.sun.media.sound;
+import sun.misc.ManagedLocalsThread;
+
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
@@ -53,7 +55,11 @@ public final class SoftAudioPusher implements Runnable {
if (active)
return;
active = true;
- audiothread = new Thread(this);
+ if (System.getSecurityManager() == null) {
+ audiothread = new Thread(this);
+ } else {
+ audiothread = new ManagedLocalsThread(this);
+ }
audiothread.setDaemon(true);
audiothread.setPriority(Thread.MAX_PRIORITY);
audiothread.start();
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java
index 0f5ff294574..85c615e1801 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftJitterCorrector.java
@@ -24,12 +24,13 @@
*/
package com.sun.media.sound;
-import java.io.EOFException;
-import java.io.IOException;
-import java.io.InputStream;
+import sun.misc.ManagedLocalsThread;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
/**
* A jitter corrector to be used with SoftAudioPusher.
@@ -215,7 +216,11 @@ public final class SoftJitterCorrector extends AudioInputStream {
}
};
- thread = new Thread(runnable);
+ if (System.getSecurityManager() == null) {
+ thread = new Thread(runnable);
+ } else {
+ thread = new ManagedLocalsThread(runnable);
+ }
thread.setDaemon(true);
thread.setPriority(Thread.MAX_PRIORITY);
thread.start();
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java
index e895ead074f..81c33ff788b 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java
@@ -25,6 +25,8 @@
package com.sun.media.sound;
+import sun.misc.ManagedLocalsThread;
+
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -139,7 +141,11 @@ public final class SoftSynthesizer implements AudioSynthesizer,
pusher = null;
jitter_stream = null;
sourceDataLine = null;
- new Thread(runnable).start();
+ if (System.getSecurityManager() == null) {
+ new Thread(runnable).start();
+ } else {
+ new ManagedLocalsThread(runnable).start();
+ }
}
return len;
}
diff --git a/jdk/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java b/jdk/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java
index 01e42428a73..8297188f1f9 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/AWTEventMulticaster.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1088,6 +1088,7 @@ public class AWTEventMulticaster implements
* contains only the specified listener. If no such listeners are chained,
* this method returns an empty array.
*
+ * @param the listener type
* @param l the specified java.util.EventListener
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
diff --git a/jdk/src/java.desktop/share/classes/java/awt/Component.java b/jdk/src/java.desktop/share/classes/java/awt/Component.java
index a5e8dfee50c..72e473d8465 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/Component.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java
@@ -4316,9 +4316,12 @@ public abstract class Component implements ImageObserver, MenuContainer,
*/
protected boolean validatedContents; // = false
/**
- * Size of the back buffers
+ * Width of the back buffers
*/
protected int width;
+ /**
+ * Height of the back buffers
+ */
protected int height;
/**
@@ -6013,6 +6016,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
*
* If no such listeners exist, this method returns an empty array.
*
+ * @param the type of the listeners
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* java.util.EventListener
diff --git a/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java b/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java
index 5bf91e6ab8c..dd9ea860ec2 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/EventDispatchThread.java
@@ -30,6 +30,8 @@ import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
+
+import sun.misc.ManagedLocalsThread;
import sun.util.logging.PlatformLogger;
import sun.awt.dnd.SunDragSourceContextPeer;
@@ -53,7 +55,7 @@ import sun.awt.dnd.SunDragSourceContextPeer;
*
* @since 1.1
*/
-class EventDispatchThread extends Thread {
+class EventDispatchThread extends ManagedLocalsThread {
private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
@@ -65,7 +67,7 @@ class EventDispatchThread extends Thread {
private ArrayList eventFilters = new ArrayList();
EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
- super(group, name);
+ super(group, null, name);
setEventQueue(queue);
}
diff --git a/jdk/src/java.desktop/share/classes/java/awt/GridBagLayout.java b/jdk/src/java.desktop/share/classes/java/awt/GridBagLayout.java
index 1624700353f..7c86dcc1f67 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/GridBagLayout.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/GridBagLayout.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -353,7 +353,7 @@ import java.util.Arrays;
* }
* }
*
- *
+ *
* @author Doug Stein
* @author Bill Spitzak (orignial NeWS & OLIT implementation)
* @see java.awt.GridBagConstraints
@@ -770,7 +770,7 @@ java.io.Serializable {
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
- *
+ *
* @return the value 0.5f to indicate centered
*/
public float getLayoutAlignmentX(Container parent) {
@@ -783,7 +783,7 @@ java.io.Serializable {
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
- *
+ *
* @return the value 0.5f to indicate centered
*/
public float getLayoutAlignmentY(Container parent) {
diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java b/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java
index 64b1db9bf06..f9f9f28da0d 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/MenuComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -328,6 +328,7 @@ public abstract class MenuComponent implements java.io.Serializable {
* Its use is discouraged, and it may not be supported
* in the future.
* @param evt the event which is to take place
+ * @return unconditionally returns false
* @deprecated As of JDK version 1.1, replaced by {@link
* #dispatchEvent(AWTEvent) dispatchEvent}.
*/
diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuContainer.java b/jdk/src/java.desktop/share/classes/java/awt/MenuContainer.java
index 8ba5e70245b..995c7d4ceb6 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/MenuContainer.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/MenuContainer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -50,6 +50,7 @@ public interface MenuContainer {
* Posts an event to the listeners.
*
* @param evt the event to dispatch
+ * @return the results of posting the event
* @deprecated As of JDK version 1.1
* replaced by dispatchEvent(AWTEvent).
*/
diff --git a/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java b/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java
index ab797f4dd1a..e70ec305cdf 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/MenuItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -595,6 +595,7 @@ public class MenuItem extends MenuComponent implements Accessible {
*
* If no such listeners exist, this method returns an empty array.
*
+ * @param the type of the listeners
* @param listenerType the type of listeners requested; this parameter
* should specify an interface that descends from
* java.util.EventListener
diff --git a/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java b/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java
index 985c946f422..9b3ad9b5777 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/Toolkit.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1766,6 +1766,7 @@ public abstract class Toolkit {
*
* subclasses should override this to provide their own implementation
*
+ * @param the type of DragGestureRecognizer to create
* @param abstractRecognizerClass The abstract class of the required recognizer
* @param ds The DragSource
* @param c The Component target for the DragGestureRecognizer
@@ -1867,7 +1868,9 @@ public abstract class Toolkit {
}
/**
- * an opportunity to lazily evaluate desktop property values.
+ * An opportunity to lazily evaluate desktop property values.
+ * @return the desktop property or null
+ * @param name the name
*/
protected Object lazilyLoadDesktopProperty(String name) {
return null;
@@ -1947,8 +1950,14 @@ public abstract class Toolkit {
return desktopPropsSupport.getPropertyChangeListeners(propertyName);
}
+ /**
+ * The desktop properties.
+ */
protected final Map desktopProperties =
new HashMap();
+ /**
+ * The desktop properties change support.
+ */
protected final PropertyChangeSupport desktopPropsSupport =
Toolkit.createPropertyChangeSupport(this);
diff --git a/jdk/src/java.desktop/share/classes/java/awt/Window.java b/jdk/src/java.desktop/share/classes/java/awt/Window.java
index 5f819cda87a..56ca461a90b 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/Window.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2789,6 +2789,7 @@ public class Window extends Container implements Accessible {
/**
* @deprecated As of J2SE 1.4, replaced by
* {@link Component#applyComponentOrientation Component.applyComponentOrientation}.
+ * @param rb the resource bundle
*/
@Deprecated
public void applyResourceBundle(ResourceBundle rb) {
@@ -2798,6 +2799,7 @@ public class Window extends Container implements Accessible {
/**
* @deprecated As of J2SE 1.4, replaced by
* {@link Component#applyComponentOrientation Component.applyComponentOrientation}.
+ * @param rbName the resource name
*/
@Deprecated
public void applyResourceBundle(String rbName) {
diff --git a/jdk/src/java.desktop/share/classes/java/awt/doc-files/Modality.html b/jdk/src/java.desktop/share/classes/java/awt/doc-files/Modality.html
index 19695f00177..242e96b914f 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/doc-files/Modality.html
+++ b/jdk/src/java.desktop/share/classes/java/awt/doc-files/Modality.html
@@ -1,5 +1,5 @@
RGB case.
*
@@ -1426,23 +1462,23 @@ png_init_read_transformations(png_structp png_ptr)
* png_set_background, along with the bit depth, then the code has a record
* of exactly what color space the background is currently in.
*/
- if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
{
/* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
- * the file was greyscale the background value is gray.
+ * the file was grayscale the background value is gray.
*/
- if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
}
- else if (png_ptr->transformations & PNG_COMPOSE)
+ else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
{
/* PNG_COMPOSE: png_set_background was called with need_expand false,
* so the color is in the color space of the output or png_set_alpha_mode
* was called and the color is black. Ignore RGB_TO_GRAY because that
* happens before GRAY_TO_RGB.
*/
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
{
if (png_ptr->background.red == png_ptr->background.green &&
png_ptr->background.red == png_ptr->background.blue)
@@ -1452,7 +1488,8 @@ png_init_read_transformations(png_structp png_ptr)
}
}
}
-#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */
+#endif /* READ_EXPAND && READ_BACKGROUND */
+#endif /* READ_GRAY_TO_RGB */
/* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
* can be performed directly on the palette, and some (such as rgb to gray)
@@ -1473,10 +1510,10 @@ png_init_read_transformations(png_structp png_ptr)
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
defined(PNG_READ_EXPAND_16_SUPPORTED)
- if ((png_ptr->transformations & PNG_EXPAND_16) &&
- (png_ptr->transformations & PNG_COMPOSE) &&
- !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- png_ptr->bit_depth != 16)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
+ png_ptr->bit_depth != 16)
{
/* TODO: fix this. Because the expand_16 operation is after the compose
* handling the background color must be 8, not 16, bits deep, but the
@@ -1488,14 +1525,36 @@ png_init_read_transformations(png_structp png_ptr)
* NOTE: this discards the low 16 bits of the user supplied background
* color, but until expand_16 works properly there is no choice!
*/
-# define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16))
+# define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
CHOP(png_ptr->background.red);
CHOP(png_ptr->background.green);
CHOP(png_ptr->background.blue);
CHOP(png_ptr->background.gray);
# undef CHOP
}
-#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
+#endif /* READ_BACKGROUND && READ_EXPAND_16 */
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+ (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
+ defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
+ if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
+ png_ptr->bit_depth == 16)
+ {
+ /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
+ * component this will also happen after PNG_COMPOSE and so the background
+ * color must be pre-expanded here.
+ *
+ * TODO: fix this too.
+ */
+ png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
+ png_ptr->background.green =
+ (png_uint_16)(png_ptr->background.green * 257);
+ png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
+ png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
+ }
+#endif
/* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
* background support (see the comments in scripts/pnglibconf.dfa), this
@@ -1524,27 +1583,36 @@ png_init_read_transformations(png_structp png_ptr)
* file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
* tables.
*/
- if ((png_ptr->transformations & PNG_GAMMA)
- || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
- && (png_gamma_significant(png_ptr->gamma) ||
- png_gamma_significant(png_ptr->screen_gamma)))
- || ((png_ptr->transformations & PNG_COMPOSE)
- && (png_gamma_significant(png_ptr->gamma)
- || png_gamma_significant(png_ptr->screen_gamma)
+ if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
+ ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
+ (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
+ png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
+ ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
+ png_gamma_significant(png_ptr->screen_gamma) != 0
# ifdef PNG_READ_BACKGROUND_SUPPORTED
- || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
- && png_gamma_significant(png_ptr->background_gamma))
+ || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
+ png_gamma_significant(png_ptr->background_gamma) != 0)
# endif
- )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
- && png_gamma_significant(png_ptr->screen_gamma))
- )
+ )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
+ png_gamma_significant(png_ptr->screen_gamma) != 0))
{
png_build_gamma_table(png_ptr, png_ptr->bit_depth);
#ifdef PNG_READ_BACKGROUND_SUPPORTED
- if (png_ptr->transformations & PNG_COMPOSE)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
{
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ /* Issue a warning about this combination: because RGB_TO_GRAY is
+ * optimized to do the gamma transform if present yet do_background has
+ * to do the same thing if both options are set a
+ * double-gamma-correction happens. This is true in all versions of
+ * libpng to date.
+ */
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
+ png_warning(png_ptr,
+ "libpng does not support gamma+background+rgb_to_gray");
+
+ if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
{
/* We don't get to here unless there is a tRNS chunk with non-opaque
* entries - see the checking code at the start of this function.
@@ -1576,8 +1644,8 @@ png_init_read_transformations(png_structp png_ptr)
break;
case PNG_BACKGROUND_GAMMA_FILE:
- g = png_reciprocal(png_ptr->gamma);
- gs = png_reciprocal2(png_ptr->gamma,
+ g = png_reciprocal(png_ptr->colorspace.gamma);
+ gs = png_reciprocal2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma);
break;
@@ -1592,7 +1660,7 @@ png_init_read_transformations(png_structp png_ptr)
break;
}
- if (png_gamma_significant(gs))
+ if (png_gamma_significant(gs) != 0)
{
back.red = png_gamma_8bit_correct(png_ptr->background.red,
gs);
@@ -1609,7 +1677,7 @@ png_init_read_transformations(png_structp png_ptr)
back.blue = (png_byte)png_ptr->background.blue;
}
- if (png_gamma_significant(g))
+ if (png_gamma_significant(g) != 0)
{
back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
g);
@@ -1663,7 +1731,7 @@ png_init_read_transformations(png_structp png_ptr)
/* Prevent the transformations being done again.
*
- * NOTE: this is highly dubious; it zaps the transformations in
+ * NOTE: this is highly dubious; it removes the transformations in
* place. This seems inconsistent with the general treatment of the
* transformations elsewhere.
*/
@@ -1673,8 +1741,9 @@ png_init_read_transformations(png_structp png_ptr)
/* 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;
+ int gs_sig, g_sig;
+ png_fixed_point g = PNG_FP_1; /* Correction to linear */
+ png_fixed_point gs = PNG_FP_1; /* Correction to screen */
switch (png_ptr->background_gamma_type)
{
@@ -1684,8 +1753,9 @@ png_init_read_transformations(png_structp png_ptr)
break;
case PNG_BACKGROUND_GAMMA_FILE:
- g = png_reciprocal(png_ptr->gamma);
- gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
+ g = png_reciprocal(png_ptr->colorspace.gamma);
+ gs = png_reciprocal2(png_ptr->colorspace.gamma,
+ png_ptr->screen_gamma);
break;
case PNG_BACKGROUND_GAMMA_UNIQUE:
@@ -1698,34 +1768,45 @@ png_init_read_transformations(png_structp png_ptr)
png_error(png_ptr, "invalid background gamma type");
}
- png_ptr->background_1.gray = png_gamma_correct(png_ptr,
- png_ptr->background.gray, g);
+ g_sig = png_gamma_significant(g);
+ gs_sig = png_gamma_significant(gs);
- png_ptr->background.gray = png_gamma_correct(png_ptr,
- png_ptr->background.gray, gs);
+ if (g_sig != 0)
+ png_ptr->background_1.gray = png_gamma_correct(png_ptr,
+ png_ptr->background.gray, g);
+
+ if (gs_sig != 0)
+ 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);
+ if (g_sig != 0)
+ {
+ 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.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_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);
+ if (gs_sig != 0)
+ {
+ 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.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);
+ png_ptr->background.blue = png_gamma_correct(png_ptr,
+ png_ptr->background.blue, gs);
+ }
}
else
@@ -1737,20 +1818,29 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->background.red = png_ptr->background.green
= png_ptr->background.blue = png_ptr->background.gray;
}
+
+ /* The background is now in screen gamma: */
+ png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
} /* color_type != PNG_COLOR_TYPE_PALETTE */
}/* png_ptr->transformations & PNG_BACKGROUND */
else
/* Transformation does not include PNG_BACKGROUND */
-#endif /* PNG_READ_BACKGROUND_SUPPORTED */
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+#endif /* READ_BACKGROUND */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
+ && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
+ (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
+#endif
+ )
{
png_colorp palette = png_ptr->palette;
int num_palette = png_ptr->num_palette;
int i;
- /*NOTE: there are other transformations that should probably be in here
- * too.
+ /* NOTE: there are other transformations that should probably be in
+ * here too.
*/
for (i = 0; i < num_palette; i++)
{
@@ -1766,11 +1856,11 @@ png_init_read_transformations(png_structp png_ptr)
#ifdef PNG_READ_BACKGROUND_SUPPORTED
else
#endif
-#endif /* PNG_READ_GAMMA_SUPPORTED */
+#endif /* READ_GAMMA */
#ifdef PNG_READ_BACKGROUND_SUPPORTED
/* No GAMMA transformation (see the hanging else 4 lines above) */
- if ((png_ptr->transformations & PNG_COMPOSE) &&
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
{
int i;
@@ -1805,35 +1895,53 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->transformations &= ~PNG_COMPOSE;
}
-#endif /* PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_BACKGROUND */
#ifdef PNG_READ_SHIFT_SUPPORTED
- if ((png_ptr->transformations & PNG_SHIFT) &&
+ if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) == 0 &&
(png_ptr->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;
+ int i;
+ int istop = png_ptr->num_palette;
+ int shift = 8 - png_ptr->sig_bit.red;
- if (sr < 0 || sr > 8)
- sr = 0;
+ png_ptr->transformations &= ~PNG_SHIFT;
- if (sg < 0 || sg > 8)
- sg = 0;
+ /* significant bits can be in the range 1 to 7 for a meaninful result, if
+ * the number of significant bits is 0 then no shift is done (this is an
+ * error condition which is silently ignored.)
+ */
+ if (shift > 0 && shift < 8)
+ for (i=0; ipalette[i].red;
- if (sb < 0 || sb > 8)
- sb = 0;
+ component >>= shift;
+ png_ptr->palette[i].red = (png_byte)component;
+ }
- for (i = 0; i < istop; i++)
- {
- png_ptr->palette[i].red >>= sr;
- png_ptr->palette[i].green >>= sg;
- png_ptr->palette[i].blue >>= sb;
- }
+ shift = 8 - png_ptr->sig_bit.green;
+ if (shift > 0 && shift < 8)
+ for (i=0; ipalette[i].green;
+
+ component >>= shift;
+ png_ptr->palette[i].green = (png_byte)component;
+ }
+
+ shift = 8 - png_ptr->sig_bit.blue;
+ if (shift > 0 && shift < 8)
+ for (i=0; ipalette[i].blue;
+
+ component >>= shift;
+ png_ptr->palette[i].blue = (png_byte)component;
+ }
}
-#endif /* PNG_READ_SHIFT_SUPPORTED */
+#endif /* READ_SHIFT */
}
/* Modify the info structure to reflect the transformations. The
@@ -1841,12 +1949,12 @@ png_init_read_transformations(png_structp png_ptr)
* assuming the transformations result in valid PNG data.
*/
void /* PRIVATE */
-png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
+png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_read_transform_info");
#ifdef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND)
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
{
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
@@ -1868,9 +1976,9 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
}
else
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
{
- if (png_ptr->transformations & PNG_EXPAND_tRNS)
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
}
if (info_ptr->bit_depth < 8)
@@ -1886,7 +1994,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
/* The following is almost certainly wrong unless the background value is in
* the screen space!
*/
- if (png_ptr->transformations & PNG_COMPOSE)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
info_ptr->background = png_ptr->background;
#endif
@@ -1895,20 +2003,24 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
* however it seems that the code in png_init_read_transformations, which has
* been called before this from png_read_update_info->png_read_start_row
* sometimes does the gamma transform and cancels the flag.
+ *
+ * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
+ * the screen_gamma value. The following probably results in weirdness if
+ * the info_ptr is used by the app after the rows have been read.
*/
- info_ptr->gamma = png_ptr->gamma;
+ info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
#endif
if (info_ptr->bit_depth == 16)
{
# ifdef PNG_READ_16BIT_SUPPORTED
# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_SCALE_16_TO_8)
+ if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
info_ptr->bit_depth = 8;
# endif
# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_16_TO_8)
+ if ((png_ptr->transformations & PNG_16_TO_8) != 0)
info_ptr->bit_depth = 8;
# endif
@@ -1926,7 +2038,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->bit_depth = 8;
# else
-# if PNG_READ_SCALE_16_TO_8_SUPPORTED
+# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
png_ptr->transformations |= PNG_SCALE_16_TO_8;
info_ptr->bit_depth = 8;
# else
@@ -1934,25 +2046,27 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
CONFIGURATION ERROR: you must enable at least one 16 to 8 method
# endif
# endif
-#endif /* !READ_16BIT_SUPPORTED */
+#endif /* !READ_16BIT */
}
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
- info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
+ info_ptr->color_type = (png_byte)(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;
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
+ info_ptr->color_type = (png_byte)(info_ptr->color_type &
+ ~PNG_COLOR_MASK_COLOR);
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
- if (png_ptr->transformations & PNG_QUANTIZE)
+ if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
{
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)
+ png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
{
info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
}
@@ -1960,54 +2074,57 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
- info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
+ info_ptr->bit_depth == 8 &&
+ info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
info_ptr->bit_depth = 16;
}
#endif
#ifdef PNG_READ_PACK_SUPPORTED
- if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
+ if ((png_ptr->transformations & PNG_PACK) != 0 &&
+ (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)
+ else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
info_ptr->channels = 3;
else
info_ptr->channels = 1;
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_STRIP_ALPHA)
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
{
- info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
+ info_ptr->color_type = (png_byte)(info_ptr->color_type &
+ ~PNG_COLOR_MASK_ALPHA);
info_ptr->num_trans = 0;
}
#endif
- if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
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)))
+ if ((png_ptr->transformations & PNG_FILLER) != 0 &&
+ (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)
+ if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
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 ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
{
if (info_ptr->bit_depth < png_ptr->user_transform_depth)
info_ptr->bit_depth = png_ptr->user_transform_depth;
@@ -2031,291 +2148,11 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
png_ptr->info_rowbytes = info_ptr->rowbytes;
#ifndef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr)
+ if (png_ptr != NULL)
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)
- {
- /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
- * error is incredibly rare and incredibly easy to debug without this
- * information.
- */
- png_error(png_ptr, "NULL row buffer");
- }
-
- /* The following is debugging; prior to 1.5.4 the code was never compiled in;
- * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
- * PNG_WARN_UNINITIALIZED_ROW removed. In 1.5 the new flag is set only for
- * selected new APIs to ensure that there is no API change.
- */
- if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
- !(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 (but not enabled until 1.5.4).
- */
- png_error(png_ptr, "Uninitialized row");
- }
-
-#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->transformations & PNG_STRIP_ALPHA) &&
- !(png_ptr->transformations & PNG_COMPOSE) &&
- (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
- png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
- 0 /* at_start == false, because SWAP_ALPHA happens later */);
-#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
-
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
- if (png_ptr->transformations & PNG_COMPOSE)
- png_do_compose(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
- if ((png_ptr->transformations & PNG_GAMMA) &&
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
- !((png_ptr->transformations & PNG_COMPOSE) &&
- ((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);
-#endif
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
- (png_ptr->transformations & PNG_COMPOSE) &&
- (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
- png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
- 0 /* at_start == false, because SWAP_ALPHA happens later */);
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
- if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
- (png_ptr->row_info.color_type & PNG_COLOR_MASK_ALPHA))
- png_do_encode_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_SCALE_16_TO_8)
- png_do_scale_16_to_8(&(png_ptr->row_info), png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
- /* There is no harm in doing both of these because only one has any effect,
- * by putting the 'scale' option first if the app asks for scale (either by
- * calling the API or in a TRANSFORM flag) this is what happens.
- */
- 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_EXPAND_16_SUPPORTED
- /* Do the expansion now, after all the arithmetic has been done. Notice
- * that previous transformations can handle the PNG_EXPAND_16 flag if this
- * is efficient (particularly true in the case of gamma correction, where
- * better accuracy results faster!)
- */
- if (png_ptr->transformations & PNG_EXPAND_16)
- png_do_expand_16(&png_ptr->row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- /*NOTE: moved here in 1.5.4 (from much later in this list.) */
- 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_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_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
@@ -2323,7 +2160,7 @@ png_do_read_transformations(png_structp png_ptr)
* the numbers 0 or 1. If you would rather they contain 0 and 255, use
* png_do_shift() after this.
*/
-void /* PRIVATE */
+static void
png_do_unpack(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_unpack");
@@ -2421,109 +2258,132 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
* a row of bit depth 8, but only 5 are significant, this will shift
* the values back to 0 through 31.
*/
-void /* PRIVATE */
+static void
png_do_unshift(png_row_infop row_info, png_bytep row,
png_const_color_8p sig_bits)
{
+ int color_type;
+
png_debug(1, "in png_do_unshift");
- if (
- row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+ /* The palette case has already been handled in the _init routine. */
+ color_type = row_info->color_type;
+
+ if (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;
+ int bit_depth = row_info->bit_depth;
- if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+ if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
- 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;
+ shift[channels++] = bit_depth - sig_bits->red;
+ shift[channels++] = bit_depth - sig_bits->green;
+ shift[channels++] = bit_depth - sig_bits->blue;
}
else
{
- shift[channels++] = row_info->bit_depth - sig_bits->gray;
+ shift[channels++] = bit_depth - sig_bits->gray;
}
- if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
- shift[channels++] = row_info->bit_depth - sig_bits->alpha;
+ shift[channels++] = bit_depth - sig_bits->alpha;
}
- for (c = 0; c < channels; c++)
{
- if (shift[c] <= 0)
- shift[c] = 0;
+ int c, have_shift;
- else
- value = 1;
+ for (c = have_shift = 0; c < channels; ++c)
+ {
+ /* A shift of more than the bit depth is an error condition but it
+ * gets ignored here.
+ */
+ if (shift[c] <= 0 || shift[c] >= bit_depth)
+ shift[c] = 0;
+
+ else
+ have_shift = 1;
+ }
+
+ if (have_shift == 0)
+ return;
}
- if (!value)
- return;
-
- switch (row_info->bit_depth)
+ switch (bit_depth)
{
default:
+ /* Must be 1bpp gray: should not be here! */
+ /* NOTREACHED */
break;
case 2:
+ /* Must be 2bpp gray */
+ /* assert(channels == 1 && shift[0] == 1) */
{
- png_bytep bp;
- png_size_t i;
- png_size_t istop = row_info->rowbytes;
+ png_bytep bp = row;
+ png_bytep bp_end = bp + row_info->rowbytes;
- for (bp = row, i = 0; i < istop; i++)
+ while (bp < bp_end)
{
- *bp >>= 1;
- *bp++ &= 0x55;
+ int b = (*bp >> 1) & 0x55;
+ *bp++ = (png_byte)b;
}
break;
}
case 4:
+ /* Must be 4bpp gray */
+ /* assert(channels == 1) */
{
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]));
+ png_bytep bp_end = bp + row_info->rowbytes;
+ int gray_shift = shift[0];
+ int mask = 0xf >> gray_shift;
- for (i = 0; i < istop; i++)
+ mask |= mask << 4;
+
+ while (bp < bp_end)
{
- *bp >>= shift[0];
- *bp++ &= mask;
+ int b = (*bp >> gray_shift) & mask;
+ *bp++ = (png_byte)b;
}
break;
}
case 8:
+ /* Single byte components, G, GA, RGB, RGBA */
{
png_bytep bp = row;
- png_uint_32 i;
- png_uint_32 istop = row_width * channels;
+ png_bytep bp_end = bp + row_info->rowbytes;
+ int channel = 0;
- for (i = 0; i < istop; i++)
+ while (bp < bp_end)
{
- *bp++ >>= shift[i%channels];
+ int b = *bp >> shift[channel];
+ if (++channel >= channels)
+ channel = 0;
+ *bp++ = (png_byte)b;
}
break;
}
#ifdef PNG_READ_16BIT_SUPPORTED
case 16:
+ /* Double byte components, G, GA, RGB, RGBA */
{
png_bytep bp = row;
- png_uint_32 i;
- png_uint_32 istop = channels * row_width;
+ png_bytep bp_end = bp + row_info->rowbytes;
+ int channel = 0;
- for (i = 0; i < istop; i++)
+ while (bp < bp_end)
{
- value = (png_uint_16)((*bp << 8) + *(bp + 1));
- value >>= shift[i%channels];
+ int value = (bp[0] << 8) + bp[1];
+
+ value >>= shift[channel];
+ if (++channel >= channels)
+ channel = 0;
*bp++ = (png_byte)(value >> 8);
*bp++ = (png_byte)(value & 0xff);
}
@@ -2537,7 +2397,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Scale rows of bit depth 16 down to 8 accurately */
-void /* PRIVATE */
+static void
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_scale_16_to_8");
@@ -2545,7 +2405,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
if (row_info->bit_depth == 16)
{
png_bytep sp = row; /* source */
- png_bytep dp = row; /* destinaton */
+ png_bytep dp = row; /* destination */
png_bytep ep = sp + row_info->rowbytes; /* end+1 */
while (sp < ep)
@@ -2595,7 +2455,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-void /* PRIVATE */
+static void
/* Simply discard the low byte. This was the default behavior prior
* to libpng-1.5.4.
*/
@@ -2606,7 +2466,7 @@ png_do_chop(png_row_infop row_info, png_bytep row)
if (row_info->bit_depth == 16)
{
png_bytep sp = row; /* source */
- png_bytep dp = row; /* destinaton */
+ png_bytep dp = row; /* destination */
png_bytep ep = sp + row_info->rowbytes; /* end+1 */
while (sp < ep)
@@ -2623,7 +2483,7 @@ png_do_chop(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_read_swap_alpha");
@@ -2720,7 +2580,7 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_uint_32 row_width;
@@ -2822,7 +2682,7 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
#ifdef PNG_READ_FILLER_SUPPORTED
/* Add filler channel if we have RGB color */
-void /* PRIVATE */
+static void
png_do_read_filler(png_row_infop row_info, png_bytep row,
png_uint_32 filler, png_uint_32 flags)
{
@@ -2841,7 +2701,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
if (row_info->bit_depth == 8)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from G to GX */
png_bytep sp = row + (png_size_t)row_width;
@@ -2876,7 +2736,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from GG to GGXX */
png_bytep sp = row + (png_size_t)row_width * 2;
@@ -2918,7 +2778,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
if (row_info->bit_depth == 8)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from RGB to RGBX */
png_bytep sp = row + (png_size_t)row_width * 3;
@@ -2957,7 +2817,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from RRGGBB to RRGGBBXX */
png_bytep sp = row + (png_size_t)row_width * 6;
@@ -3009,7 +2869,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand grayscale files to RGB, with or without alpha */
-void /* PRIVATE */
+static void
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
{
png_uint_32 i;
@@ -3018,7 +2878,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
png_debug(1, "in png_do_gray_to_rgb");
if (row_info->bit_depth >= 8 &&
- !(row_info->color_type & PNG_COLOR_MASK_COLOR))
+ (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{
@@ -3086,7 +2946,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
}
}
}
- row_info->channels += (png_byte)2;
+ row_info->channels = (png_byte)(row_info->channels + 2);
row_info->color_type |= PNG_COLOR_MASK_COLOR;
row_info->pixel_depth = (png_byte)(row_info->channels *
row_info->bit_depth);
@@ -3097,269 +2957,242 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
#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:
- *
+ * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
+ * (THIS LINK IS DEAD June 2008 but
+ * versions dated 1998 through November 2002 have been archived at
+ * http://web.archive.org/web/20000816232553/http://www.inforamp.net/
+ * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
* 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.
+ * Poynton's current link (as of January 2003 through July 2011):
+ *
+ * has changed the numbers slightly:
*
- * Other integer coefficents can be used via png_set_rgb_to_gray().
+ * Y = 0.2126*R + 0.7152*G + 0.0722*B
+ *
+ * which can be expressed with integers as
+ *
+ * Y = (6966 * R + 23436 * G + 2366 * B)/32768
+ *
+ * Historically, however, libpng uses numbers derived from the ITU-R Rec 709
+ * end point chromaticities and the D65 white point. Depending on the
+ * precision used for the D65 white point this produces a variety of different
+ * numbers, however if the four decimal place value used in ITU-R Rec 709 is
+ * used (0.3127,0.3290) the Y calculation would be:
+ *
+ * Y = (6968 * R + 23435 * G + 2366 * B)/32768
+ *
+ * While this is correct the rounding results in an overflow for white, because
+ * the sum of the rounded coefficients is 32769, not 32768. Consequently
+ * libpng uses, instead, the closest non-overflowing approximation:
+ *
+ * Y = (6968 * R + 23434 * G + 2366 * B)/32768
+ *
+ * Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
+ * (including an sRGB chunk) then the chromaticities are used to calculate the
+ * coefficients. See the chunk handling in pngrutil.c for more information.
+ *
+ * In all cases the calculation is to be done in a linear colorspace. If no
+ * gamma information is available to correct the encoding of the original RGB
+ * values this results in an implicit assumption that the original PNG RGB
+ * values were linear.
+ *
+ * Other integer coefficents can be used via png_set_rgb_to_gray(). Because
+ * the API takes just red and green coefficients the blue coefficient is
+ * calculated to make the sum 32768. This will result in different rounding
+ * to that used above.
*/
-int /* PRIVATE */
-png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
+static int
+png_do_rgb_to_gray(png_structrp 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))
+ if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
+ (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
- 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;
+ PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
+ PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
+ PNG_CONST png_uint_32 bc = 32768 - rc - gc;
+ PNG_CONST png_uint_32 row_width = row_info->width;
+ PNG_CONST int have_alpha =
+ (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ if (row_info->bit_depth == 8)
{
- if (row_info->bit_depth == 8)
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ /* Notice that gamma to/from 1 are not necessarily inverses (if
+ * there is an overall gamma correction). Prior to 1.5.5 this code
+ * checked the linearized values for equality; this doesn't match
+ * the documentation, the original values must be checked.
+ */
+ if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
{
-#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;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
{
- png_bytep sp = row;
- png_bytep dp = row;
+ png_byte red = *(sp++);
+ png_byte green = *(sp++);
+ png_byte blue = *(sp++);
- for (i = 0; i < row_width; i++)
+ if (red != green || red != blue)
{
- 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++)];
+ red = png_ptr->gamma_to_1[red];
+ green = png_ptr->gamma_to_1[green];
+ blue = png_ptr->gamma_to_1[blue];
- 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);
+ rgb_error |= 1;
+ *(dp++) = png_ptr->gamma_from_1[
+ (rc*red + gc*green + bc*blue + 16384)>>15];
}
- }
- else
-#endif
- {
- png_bytep sp = row;
- png_bytep dp = row;
- for (i = 0; i < row_width; i++)
+
+ else
{
- png_byte red = *(sp++);
- png_byte green = *(sp++);
- png_byte blue = *(sp++);
+ /* If there is no overall correction the table will not be
+ * set.
+ */
+ if (png_ptr->gamma_table != NULL)
+ red = png_ptr->gamma_table[red];
- if (red != green || red != blue)
- {
- rgb_error |= 1;
- *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
- }
-
- else
- *(dp++) = *(sp - 1);
+ *(dp++) = red;
}
+
+ if (have_alpha != 0)
+ *(dp++) = *(sp++);
}
}
-
- 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
+ else
#endif
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
{
- 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)
{
- 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);
+ rgb_error |= 1;
+ /* NOTE: this is the historical approach which simply
+ * truncates the results.
+ */
+ *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
}
+
+ else
+ *(dp++) = red;
+
+ if (have_alpha != 0)
+ *(dp++) = *(sp++);
}
}
}
- if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+
+ else /* RGB bit_depth == 16 */
{
- if (row_info->bit_depth == 8)
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
{
-#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;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
{
- 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)
{
- 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;
+ if (png_ptr->gamma_16_table != NULL)
+ w = png_ptr->gamma_16_table[(red & 0xff)
+ >> png_ptr->gamma_shift][red >> 8];
else
- {
- png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
- png_ptr->gamma_shift][red>>8];
+ w = red;
+ }
- png_uint_16 green_1 =
- png_ptr->gamma_16_to_1[(green&0xff) >>
- png_ptr->gamma_shift][green>>8];
+ 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 + 16384)>>15);
+ w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+ png_ptr->gamma_shift][gray16 >> 8];
+ rgb_error |= 1;
+ }
- png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
- png_ptr->gamma_shift][blue>>8];
+ *(dp++) = (png_byte)((w>>8) & 0xff);
+ *(dp++) = (png_byte)(w & 0xff);
- 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 */
+ if (have_alpha != 0)
+ {
+ *(dp++) = *(sp++);
*(dp++) = *(sp++);
}
}
- else
+ }
+ else
#endif
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
{
- 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;
+
+ /* From 1.5.5 in the 16 bit case do the accurate conversion even
+ * in the 'fast' case - this is because this is where the code
+ * ends up when handling linear 16 bit data.
+ */
+ gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
+ 15);
+ *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
+ *(dp++) = (png_byte)(gray16 & 0xff);
+
+ if (have_alpha != 0)
{
- 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++);
*(dp++) = *(sp++);
}
}
}
}
- row_info->channels -= 2;
+
+ row_info->channels = (png_byte)(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 *
@@ -3369,73 +3202,15 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
return rgb_error;
}
#endif
-#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
-#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-/* 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. This API is not used internally.
- */
-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;
- }
-}
-#endif
-
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-#ifdef PNG_READ_BACKGROUND_SUPPORTED
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_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_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+static void
+png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
#ifdef PNG_READ_GAMMA_SUPPORTED
png_const_bytep gamma_table = png_ptr->gamma_table;
@@ -3445,12 +3220,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
int gamma_shift = png_ptr->gamma_shift;
+ int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
#endif
png_bytep sp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
- int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
int shift;
png_debug(1, "in png_do_compose");
@@ -3471,11 +3246,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x01)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 7;
sp++;
@@ -3499,20 +3275,22 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x03)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
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);
+ unsigned int p = (*sp >> shift) & 0x03;
+ unsigned int g = (gamma_table [p | (p << 2) |
+ (p << 4) | (p << 6)] >> 6) & 0x03;
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= g << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 6;
sp++;
@@ -3533,11 +3311,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x03)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 6;
sp++;
@@ -3562,20 +3341,22 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x0f)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
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);
+ unsigned int p = (*sp >> shift) & 0x0f;
+ unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
+ 0x0f;
+ unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+ tmp |= g << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 4;
sp++;
@@ -3596,11 +3377,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x0f)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 4;
sp++;
@@ -3656,8 +3438,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (v == png_ptr->trans_color.gray)
{
/* Background is already in screen gamma */
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
- *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
+ *(sp + 1) = (png_byte)(png_ptr->background.gray
+ & 0xff);
}
else
@@ -3680,8 +3464,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (v == png_ptr->trans_color.gray)
{
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
- *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
+ *(sp + 1) = (png_byte)(png_ptr->background.gray
+ & 0xff);
}
}
}
@@ -3761,9 +3547,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Background is already in screen gamma */
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -3804,9 +3593,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
}
@@ -3843,7 +3635,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_to_1[*sp];
png_composite(w, v, a, png_ptr->background_1.gray);
- if (!optimize)
+ if (optimize == 0)
w = gamma_from_1[w];
*sp = w;
}
@@ -3861,7 +3653,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp = (png_byte)png_ptr->background.gray;
else if (a < 0xff)
- png_composite(*sp, *sp, a, png_ptr->background_1.gray);
+ png_composite(*sp, *sp, a, png_ptr->background.gray);
}
}
}
@@ -3889,7 +3681,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
else if (a == 0)
{
/* Background is already in screen gamma */
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
}
@@ -3899,7 +3692,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
png_composite_16(v, g, a, png_ptr->background_1.gray);
- if (optimize)
+ if (optimize != 0)
w = v;
else
w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
@@ -3919,7 +3712,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (a == 0)
{
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
}
@@ -3928,7 +3722,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
png_uint_16 g, v;
g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
- png_composite_16(v, g, a, png_ptr->background_1.gray);
+ png_composite_16(v, g, a, png_ptr->background.gray);
*sp = (png_byte)((v >> 8) & 0xff);
*(sp + 1) = (png_byte)(v & 0xff);
}
@@ -3972,17 +3766,17 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_to_1[*sp];
png_composite(w, v, a, png_ptr->background_1.red);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*sp = w;
v = gamma_to_1[*(sp + 1)];
png_composite(w, v, a, png_ptr->background_1.green);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*(sp + 1) = w;
v = gamma_to_1[*(sp + 2)];
png_composite(w, v, a, png_ptr->background_1.blue);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*(sp + 2) = w;
}
}
@@ -4049,9 +3843,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Background is already in screen gamma */
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -4061,23 +3858,26 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
png_composite_16(w, v, a, png_ptr->background_1.red);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
+ 8];
*sp = (png_byte)((w >> 8) & 0xff);
*(sp + 1) = (png_byte)(w & 0xff);
v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
png_composite_16(w, v, a, png_ptr->background_1.green);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
+ 8];
*(sp + 2) = (png_byte)((w >> 8) & 0xff);
*(sp + 3) = (png_byte)(w & 0xff);
v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
png_composite_16(w, v, a, png_ptr->background_1.blue);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >>
+ 8];
*(sp + 4) = (png_byte)((w >> 8) & 0xff);
*(sp + 5) = (png_byte)(w & 0xff);
@@ -4098,9 +3898,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -4137,7 +3940,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
}
}
}
-#endif
+#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
#ifdef PNG_READ_GAMMA_SUPPORTED
/* Gamma correct the image, avoiding the alpha channel. Make sure
@@ -4146,8 +3949,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
* 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_structp png_ptr)
+static void
+png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
png_const_bytep gamma_table = png_ptr->gamma_table;
png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
@@ -4347,14 +4150,14 @@ png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
* linear.) Called only with color types that have an alpha channel. Needs the
* from_1 tables.
*/
-void /* PRIVATE */
-png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+static void
+png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
png_uint_32 row_width = row_info->width;
png_debug(1, "in png_do_encode_alpha");
- if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
if (row_info->bit_depth == 8)
{
@@ -4413,7 +4216,7 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Expands a palette row to an RGB or RGBA row depending
* upon whether you supply trans and num_trans.
*/
-void /* PRIVATE */
+static void
png_do_expand_palette(png_row_infop row_info, png_bytep row,
png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
{
@@ -4566,7 +4369,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
/* 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 */
+static void
png_do_expand(png_row_infop row_info, png_bytep row,
png_const_color_16p trans_color)
{
@@ -4580,7 +4383,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
{
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{
- png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
+ unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
if (row_info->bit_depth < 8)
{
@@ -4588,7 +4391,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
{
case 1:
{
- gray = (png_uint_16)((gray & 0x01) * 0xff);
+ gray = (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);
@@ -4616,7 +4419,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 2:
{
- gray = (png_uint_16)((gray & 0x03) * 0x55);
+ gray = (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);
@@ -4641,7 +4444,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 4:
{
- gray = (png_uint_16)((gray & 0x0f) * 0x11);
+ gray = (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);
@@ -4694,8 +4497,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
else if (row_info->bit_depth == 16)
{
- png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
- png_byte gray_low = (png_byte)(gray & 0xff);
+ unsigned int gray_high = (gray >> 8) & 0xff;
+ unsigned int gray_low = gray & 0xff;
sp = row + row_info->rowbytes - 1;
dp = row + (row_info->rowbytes << 1) - 1;
for (i = 0; i < row_width; i++)
@@ -4724,7 +4527,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
row_width);
}
}
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
+ trans_color != NULL)
{
if (row_info->bit_depth == 8)
{
@@ -4793,10 +4597,10 @@ png_do_expand(png_row_infop row_info, png_bytep row,
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
-/* If the bit depth is 8 and the colour type is not a palette type expand the
+/* If the bit depth is 8 and the color type is not a palette type expand the
* whole row to 16 bits. Has no effect otherwise.
*/
-void /* PRIVATE */
+static void
png_do_expand_16(png_row_infop row_info, png_bytep row)
{
if (row_info->bit_depth == 8 &&
@@ -4824,7 +4628,7 @@ png_do_expand_16(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
-void /* PRIVATE */
+static void
png_do_quantize(png_row_infop row_info, png_bytep row,
png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
{
@@ -4915,70 +4719,304 @@ png_do_quantize(png_row_infop row_info, png_bytep row,
}
}
}
-#endif /* PNG_READ_QUANTIZE_SUPPORTED */
-#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
+#endif /* READ_QUANTIZE */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing */
+/* 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_intrapixel(png_row_infop row_info, png_bytep row)
+png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{
- png_debug(1, "in png_do_read_intrapixel");
+ png_debug(1, "in png_do_read_transformations");
- if (
- (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ if (png_ptr->row_buf == NULL)
{
- int bytes_per_pixel;
- png_uint_32 row_width = row_info->width;
+ /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
+ * error is incredibly rare and incredibly easy to debug without this
+ * information.
+ */
+ png_error(png_ptr, "NULL row buffer");
+ }
- if (row_info->bit_depth == 8)
+ /* The following is debugging; prior to 1.5.4 the code was never compiled in;
+ * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
+ * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for
+ * all transformations, however in practice the ROW_INIT always gets done on
+ * demand, if necessary.
+ */
+ if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
+ (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
+ {
+ /* 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 (but not enabled until 1.5.4).
+ */
+ png_error(png_ptr, "Uninitialized row");
+ }
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
{
- 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);
- }
+ png_do_expand_palette(row_info, png_ptr->row_buf + 1,
+ png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
}
- else if (row_info->bit_depth == 16)
+
+ else
{
- 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;
+ if (png_ptr->num_trans != 0 &&
+ (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
+ png_do_expand(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->trans_color));
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);
- }
+ png_do_expand(row_info, png_ptr->row_buf + 1,
+ NULL);
}
}
+#endif
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) == 0 &&
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ 0 /* at_start == false, because SWAP_ALPHA happens later */);
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
+ {
+ int rgb_error =
+ png_do_rgb_to_gray(png_ptr, row_info,
+ png_ptr->row_buf + 1);
+
+ if (rgb_error != 0)
+ {
+ 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) != 0 &&
+ (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
+ png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
+ png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ /* Because RGB_TO_GRAY does the gamma transform. */
+ (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+ /* Because PNG_COMPOSE does the gamma transform if there is something to
+ * do (if there is an alpha channel or transparency.)
+ */
+ !((png_ptr->transformations & PNG_COMPOSE) &&
+ ((png_ptr->num_trans != 0) ||
+ (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
+#endif
+ /* Because png_init_read_transformations transforms the palette, unless
+ * RGB_TO_GRAY will do the transform.
+ */
+ (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
+ png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ 0 /* at_start == false, because SWAP_ALPHA happens later */);
+#endif
+
+#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
+ if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
+ (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
+ png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
+ if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
+ png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
+ /* There is no harm in doing both of these because only one has any effect,
+ * by putting the 'scale' option first if the app asks for scale (either by
+ * calling the API or in a TRANSFORM flag) this is what happens.
+ */
+ if ((png_ptr->transformations & PNG_16_TO_8) != 0)
+ png_do_chop(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_QUANTIZE_SUPPORTED
+ if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
+ {
+ png_do_quantize(row_info, png_ptr->row_buf + 1,
+ png_ptr->palette_lookup, png_ptr->quantize_index);
+
+ if (row_info->rowbytes == 0)
+ png_error(png_ptr, "png_do_quantize returned rowbytes=0");
+ }
+#endif /* READ_QUANTIZE */
+
+#ifdef PNG_READ_EXPAND_16_SUPPORTED
+ /* Do the expansion now, after all the arithmetic has been done. Notice
+ * that previous transformations can handle the PNG_EXPAND_16 flag if this
+ * is efficient (particularly true in the case of gamma correction, where
+ * better accuracy results faster!)
+ */
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
+ png_do_expand_16(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* NOTE: moved here in 1.5.4 (from much later in this list.) */
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
+ (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
+ png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_INVERT_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
+ png_do_invert(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
+ png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
+ png_do_unshift(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->shift));
+#endif
+
+#ifdef PNG_READ_PACK_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACK) != 0)
+ png_do_unpack(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Added at libpng-1.5.10 */
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
+ png_do_check_palette_indexes(png_ptr, row_info);
+#endif
+
+#ifdef PNG_READ_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ png_do_bgr(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ png_do_packswap(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_FILLER_SUPPORTED
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_do_read_filler(row_info, png_ptr->row_buf + 1,
+ (png_uint_32)png_ptr->filler, png_ptr->flags);
+#endif
+
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
+ png_do_read_swap_alpha(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) != 0)
+ png_do_swap(row_info, png_ptr->row_buf + 1);
+#endif
+#endif
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
+ {
+ if (png_ptr->read_user_transform_fn != NULL)
+ (*(png_ptr->read_user_transform_fn)) /* User read transform function */
+ (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 != 0)
+ row_info->bit_depth = png_ptr->user_transform_depth;
+
+ if (png_ptr->user_transform_channels != 0)
+ row_info->channels = png_ptr->user_transform_channels;
+#endif
+ row_info->pixel_depth = (png_byte)(row_info->bit_depth *
+ row_info->channels);
+
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
+ }
+#endif
}
-#endif /* PNG_MNG_FEATURES_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED */
+
+#endif /* READ_TRANSFORMS */
+#endif /* READ */
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
index 4a023090f87..68e5caff89c 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
@@ -29,8 +29,8 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -46,10 +46,8 @@
#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_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
{
png_uint_32 uval = png_get_uint_32(buf);
@@ -68,7 +66,7 @@ png_get_uint_31(png_structp png_ptr, png_const_bytep buf)
#define PNG_FIXED_ERROR (-1)
static png_fixed_point /* PRIVATE */
-png_get_fixed_point(png_structp png_ptr, png_const_bytep buf)
+png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf)
{
png_uint_32 uval = png_get_uint_32(buf);
@@ -115,10 +113,10 @@ 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 */
+ if ((uval & 0x80000000) == 0) /* non-negative */
return uval;
- uval = (uval ^ 0xffffffffL) + 1; /* 2's complement: -x = ~x+1 */
+ uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */
return -(png_int_32)uval;
}
@@ -126,7 +124,7 @@ png_get_int_32)(png_const_bytep buf)
png_uint_16 (PNGAPI
png_get_uint_16)(png_const_bytep buf)
{
- /* ANSI-C requires an int value to accommodate at least 16 bits so this
+ /* 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.)
@@ -138,11 +136,11 @@ png_get_uint_16)(png_const_bytep buf)
return (png_uint_16)val;
}
-#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */
+#endif /* READ_INT_FUNCTIONS */
/* Read and check the PNG file signature */
void /* PRIVATE */
-png_read_sig(png_structp png_ptr, png_infop info_ptr)
+png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
{
png_size_t num_checked, num_to_check;
@@ -161,7 +159,7 @@ png_read_sig(png_structp png_ptr, png_infop info_ptr)
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 (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
{
if (num_checked < 4 &&
png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
@@ -177,7 +175,7 @@ png_read_sig(png_structp png_ptr, png_infop info_ptr)
* 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_read_chunk_header(png_structrp png_ptr)
{
png_byte buf[8];
png_uint_32 length;
@@ -193,14 +191,14 @@ png_read_chunk_header(png_structp png_ptr)
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_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
- png_debug2(0, "Reading %s chunk, length = %u",
- png_ptr->chunk_name, length);
+ png_debug2(0, "Reading %lx chunk, length = %lu",
+ (unsigned long)png_ptr->chunk_name, (unsigned long)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);
+ png_calculate_crc(png_ptr, buf + 4, 4);
/* Check to see if chunk name is valid. */
png_check_chunk_name(png_ptr, png_ptr->chunk_name);
@@ -214,7 +212,7 @@ png_read_chunk_header(png_structp png_ptr)
/* 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)
+png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)
{
if (png_ptr == NULL)
return;
@@ -224,41 +222,40 @@ png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t 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
+ * are reading an 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_crc_finish(png_structrp 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)
+ /* The size of the local buffer for inflate is a good guess as to a
+ * reasonable size to use for buffering reads from the application.
+ */
+ while (skip > 0)
{
- png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+ png_uint_32 len;
+ png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
+
+ len = (sizeof tmpbuf);
+ if (len > skip)
+ len = skip;
+ skip -= len;
+
+ png_crc_read(png_ptr, tmpbuf, len);
}
- if (i)
+ if (png_crc_error(png_ptr) != 0)
{
- 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)))
+ if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ?
+ (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0 :
+ (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE) != 0)
{
png_chunk_warning(png_ptr, "CRC error");
}
else
- {
- png_chunk_benign_error(png_ptr, "CRC error");
- return (0);
- }
+ png_chunk_error(png_ptr, "CRC error");
return (1);
}
@@ -270,22 +267,22 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip)
* the data it has read thus far.
*/
int /* PRIVATE */
-png_crc_error(png_structp png_ptr)
+png_crc_error(png_structrp 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_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
{
if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
(PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
need_crc = 0;
}
- else /* critical */
+ else /* critical */
{
- if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+ if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
need_crc = 0;
}
@@ -296,7 +293,7 @@ png_crc_error(png_structp png_ptr)
/* The chunk CRC must be serialized in a single I/O call. */
png_read_data(png_ptr, crc_bytes, 4);
- if (need_crc)
+ if (need_crc != 0)
{
crc = png_get_uint_32(crc_bytes);
return ((int)(crc != png_ptr->crc));
@@ -306,252 +303,522 @@ png_crc_error(png_structp png_ptr)
return (0);
}
-#ifdef PNG_READ_COMPRESSED_TEXT_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)
+#if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
+ defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\
+ defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\
+ defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED)
+/* Manage the read buffer; this simply reallocates the buffer if it is not small
+ * enough (or if it is not allocated). The routine returns a pointer to the
+ * buffer; if an error occurs and 'warn' is set the routine returns NULL, else
+ * it will call png_error (via png_malloc) on failure. (warn == 2 means
+ * 'silent').
+ */
+static png_bytep
+png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
{
- png_size_t count = 0;
+ png_bytep buffer = png_ptr->read_buffer;
- /* 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)
+ if (buffer != NULL && new_size > png_ptr->read_buffer_size)
{
- int ret, avail;
+ png_ptr->read_buffer = NULL;
+ png_ptr->read_buffer = NULL;
+ png_ptr->read_buffer_size = 0;
+ png_free(png_ptr, buffer);
+ buffer = NULL;
+ }
- /* 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 (buffer == NULL)
+ {
+ buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size));
+
+ if (buffer != NULL)
{
- 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;
- }
+ png_ptr->read_buffer = buffer;
+ png_ptr->read_buffer_size = new_size;
}
- /* 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)
+ else if (warn < 2) /* else silent */
{
- png_size_t space = avail; /* > 0, see above */
+ if (warn != 0)
+ png_chunk_warning(png_ptr, "insufficient memory to read chunk");
- if (output != 0 && output_size > count)
- {
- png_size_t copy = output_size - count;
+ else
+ png_chunk_error(png_ptr, "insufficient memory to read chunk");
+ }
+ }
- if (space < copy)
- copy = space;
+ return buffer;
+}
+#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */
- png_memcpy(output + count, png_ptr->zbuf, copy);
- }
- count += space;
+/* png_inflate_claim: claim the zstream for some nefarious purpose that involves
+ * decompression. Returns Z_OK on success, else a zlib error code. It checks
+ * the owner but, in final release builds, just issues a warning if some other
+ * chunk apparently owns the stream. Prior to release it does a png_error.
+ */
+static int
+png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
+{
+ if (png_ptr->zowner != 0)
+ {
+ char msg[64];
+
+ PNG_STRING_FROM_CHUNK(msg, png_ptr->zowner);
+ /* So the message that results is " using zstream"; this is an
+ * internal error, but is very useful for debugging. i18n requirements
+ * are minimal.
+ */
+ (void)png_safecat(msg, (sizeof msg), 4, " using zstream");
+#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
+ png_chunk_warning(png_ptr, msg);
+ png_ptr->zowner = 0;
+#else
+ png_chunk_error(png_ptr, msg);
+#endif
+ }
+
+ /* Implementation note: unlike 'png_deflate_claim' this internal function
+ * does not take the size of the data as an argument. Some efficiency could
+ * be gained by using this when it is known *if* the zlib stream itself does
+ * not record the number; however, this is an illusion: the original writer
+ * of the PNG may have selected a lower window size, and we really must
+ * follow that because, for systems with with limited capabilities, we
+ * would otherwise reject the application's attempts to use a smaller window
+ * size (zlib doesn't have an interface to say "this or lower"!).
+ *
+ * inflateReset2 was added to zlib 1.2.4; before this the window could not be
+ * reset, therefore it is necessary to always allocate the maximum window
+ * size with earlier zlibs just in case later compressed chunks need it.
+ */
+ {
+ int ret; /* zlib return code */
+#if PNG_ZLIB_VERNUM >= 0x1240
+
+# if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_MAXIMUM_INFLATE_WINDOW)
+ int window_bits;
+
+ if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) ==
+ PNG_OPTION_ON)
+ window_bits = 15;
+
+ else
+ window_bits = 0;
+# else
+# define window_bits 0
+# endif
+#endif
+
+ /* Set this for safety, just in case the previous owner left pointers to
+ * memory allocations.
+ */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->zstream.avail_out = 0;
+
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
+ {
+#if PNG_ZLIB_VERNUM < 0x1240
+ ret = inflateReset(&png_ptr->zstream);
+#else
+ ret = inflateReset2(&png_ptr->zstream, window_bits);
+#endif
+ }
+
+ else
+ {
+#if PNG_ZLIB_VERNUM < 0x1240
+ ret = inflateInit(&png_ptr->zstream);
+#else
+ ret = inflateInit2(&png_ptr->zstream, window_bits);
+#endif
+
+ if (ret == Z_OK)
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
}
if (ret == Z_OK)
- continue;
+ png_ptr->zowner = owner;
- /* Termination conditions - always reset the zstream, it
- * must be left in inflateInit state.
+ else
+ png_zstream_error(png_ptr, ret);
+
+ return ret;
+ }
+
+#ifdef window_bits
+# undef window_bits
+#endif
+}
+
+#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
+/* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to
+ * allow the caller to do multiple calls if required. If the 'finish' flag is
+ * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must
+ * be returned or there has been a problem, otherwise Z_SYNC_FLUSH is used and
+ * Z_OK or Z_STREAM_END will be returned on success.
+ *
+ * The input and output sizes are updated to the actual amounts of data consumed
+ * or written, not the amount available (as in a z_stream). The data pointers
+ * are not changed, so the next input is (data+input_size) and the next
+ * available output is (output+output_size).
+ */
+static int
+png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish,
+ /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr,
+ /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr)
+{
+ if (png_ptr->zowner == owner) /* Else not claimed */
+ {
+ int ret;
+ png_alloc_size_t avail_out = *output_size_ptr;
+ png_uint_32 avail_in = *input_size_ptr;
+
+ /* 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 reduces the amount of data accessed
+ * at each step and that may give the OS more time to page it in.
*/
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
+ /* avail_in and avail_out are set below from 'size' */
png_ptr->zstream.avail_in = 0;
- inflateReset(&png_ptr->zstream);
+ png_ptr->zstream.avail_out = 0;
- 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.
+ /* Read directly into the output if it is available (this is set to
+ * a local buffer below if output is NULL).
*/
-# ifdef PNG_WARNINGS_SUPPORTED
+ if (output != NULL)
+ png_ptr->zstream.next_out = output;
+
+ do
{
- png_const_charp msg;
+ uInt avail;
+ Byte local_buffer[PNG_INFLATE_BUF_SIZE];
- if (png_ptr->zstream.msg != 0)
- msg = png_ptr->zstream.msg;
+ /* zlib INPUT BUFFER */
+ /* 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 of 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.
+ */
+ avail_in += png_ptr->zstream.avail_in; /* not consumed last time */
- else switch (ret)
+ avail = ZLIB_IO_MAX;
+
+ if (avail_in < avail)
+ avail = (uInt)avail_in; /* safe: < than ZLIB_IO_MAX */
+
+ avail_in -= avail;
+ png_ptr->zstream.avail_in = avail;
+
+ /* zlib OUTPUT BUFFER */
+ avail_out += png_ptr->zstream.avail_out; /* not written last time */
+
+ avail = ZLIB_IO_MAX; /* maximum zlib can process */
+
+ if (output == NULL)
{
- case Z_BUF_ERROR:
- msg = "Buffer error in compressed datastream";
- break;
-
- case Z_DATA_ERROR:
- msg = "Data error in compressed datastream";
- break;
-
- default:
- msg = "Incomplete compressed datastream";
- break;
+ /* Reset the output buffer each time round if output is NULL and
+ * make available the full buffer, up to 'remaining_space'
+ */
+ png_ptr->zstream.next_out = local_buffer;
+ if ((sizeof local_buffer) < avail)
+ avail = (sizeof local_buffer);
}
- png_chunk_warning(png_ptr, msg);
- }
-# endif
+ if (avail_out < avail)
+ avail = (uInt)avail_out; /* safe: < ZLIB_IO_MAX */
- /* 0 means an error - notice that this code simply ignores
- * zero length compressed chunks as a result.
+ png_ptr->zstream.avail_out = avail;
+ avail_out -= avail;
+
+ /* zlib inflate call */
+ /* In fact 'avail_out' may be 0 at this point, that happens at the end
+ * of the read when the final LZ end code was not passed at the end of
+ * the previous chunk of input data. Tell zlib if we have reached the
+ * end of the output buffer.
+ */
+ ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH :
+ (finish ? Z_FINISH : Z_SYNC_FLUSH));
+ } while (ret == Z_OK);
+
+ /* For safety kill the local buffer pointer now */
+ if (output == NULL)
+ png_ptr->zstream.next_out = NULL;
+
+ /* Claw back the 'size' and 'remaining_space' byte counts. */
+ avail_in += png_ptr->zstream.avail_in;
+ avail_out += png_ptr->zstream.avail_out;
+
+ /* Update the input and output sizes; the updated values are the amount
+ * consumed or written, effectively the inverse of what zlib uses.
*/
- return 0;
+ if (avail_out > 0)
+ *output_size_ptr -= avail_out;
+
+ if (avail_in > 0)
+ *input_size_ptr -= avail_in;
+
+ /* Ensure png_ptr->zstream.msg is set (even in the success case!) */
+ png_zstream_error(png_ptr, ret);
+ return ret;
+ }
+
+ else
+ {
+ /* This is a bad internal error. The recovery assigns to the zstream msg
+ * pointer, which is not owned by the caller, but this is safe; it's only
+ * used on errors!
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");
+ return Z_STREAM_ERROR;
}
}
/*
- * Decompress trailing data in a chunk. The assumption is that chunkdata
+ * Decompress trailing data in a chunk. The assumption is that read_buffer
* 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)
+static int
+png_decompress_chunk(png_structrp png_ptr,
+ png_uint_32 chunklength, png_uint_32 prefix_size,
+ png_alloc_size_t *newlength /* must be initialized to the maximum! */,
+ int terminate /*add a '\0' to the end of the uncompressed data*/)
{
- /* The caller should guarantee this */
- if (prefix_size > chunklength)
+ /* TODO: implement different limits for different types of chunk.
+ *
+ * The caller supplies *newlength set to the maximum length of the
+ * uncompressed data, but this routine allocates space for the prefix and
+ * maybe a '\0' terminator too. We have to assume that 'prefix_size' is
+ * limited only by the maximum chunk size.
+ */
+ png_alloc_size_t limit = PNG_SIZE_MAX;
+
+# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
+ if (png_ptr->user_chunk_malloc_max > 0 &&
+ png_ptr->user_chunk_malloc_max < limit)
+ limit = png_ptr->user_chunk_malloc_max;
+# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+ if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+ limit = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
+
+ if (limit >= prefix_size + (terminate != 0))
{
- /* The recovery is to delete the chunk. */
- png_warning(png_ptr, "invalid chunklength");
- prefix_size = 0; /* To delete everything */
- }
+ int ret;
- 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 */
+ limit -= prefix_size + (terminate != 0);
- /* 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 (limit < *newlength)
+ *newlength = limit;
- /* 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
+ /* Now try to claim the stream. */
+ ret = png_inflate_claim(png_ptr, png_ptr->chunk_name);
+
+ if (ret == Z_OK)
{
- /* 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);
+ png_uint_32 lzsize = chunklength - prefix_size;
- if (text != NULL)
+ ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
+ /* input: */ png_ptr->read_buffer + prefix_size, &lzsize,
+ /* output: */ NULL, newlength);
+
+ if (ret == Z_STREAM_END)
{
- 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)
+ /* Use 'inflateReset' here, not 'inflateReset2' because this
+ * preserves the previously decided window size (otherwise it would
+ * be necessary to store the previous window size.) In practice
+ * this doesn't matter anyway, because png_inflate will call inflate
+ * with Z_FINISH in almost all cases, so the window will not be
+ * maintained.
+ */
+ if (inflateReset(&png_ptr->zstream) == Z_OK)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = text;
- *newlength = prefix_size + expanded_size;
- return; /* The success return! */
+ /* Because of the limit checks above we know that the new,
+ * expanded, size will fit in a size_t (let alone an
+ * png_alloc_size_t). Use png_malloc_base here to avoid an
+ * extra OOM message.
+ */
+ png_alloc_size_t new_size = *newlength;
+ png_alloc_size_t buffer_size = prefix_size + new_size +
+ (terminate != 0);
+ png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr,
+ buffer_size));
+
+ if (text != NULL)
+ {
+ ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
+ png_ptr->read_buffer + prefix_size, &lzsize,
+ text + prefix_size, newlength);
+
+ if (ret == Z_STREAM_END)
+ {
+ if (new_size == *newlength)
+ {
+ if (terminate != 0)
+ text[prefix_size + *newlength] = 0;
+
+ if (prefix_size > 0)
+ memcpy(text, png_ptr->read_buffer, prefix_size);
+
+ {
+ png_bytep old_ptr = png_ptr->read_buffer;
+
+ png_ptr->read_buffer = text;
+ png_ptr->read_buffer_size = buffer_size;
+ text = old_ptr; /* freed below */
+ }
+ }
+
+ else
+ {
+ /* The size changed on the second read, there can be no
+ * guarantee that anything is correct at this point.
+ * The 'msg' pointer has been set to "unexpected end of
+ * LZ stream", which is fine, but return an error code
+ * that the caller won't accept.
+ */
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+ }
+ }
+
+ else if (ret == Z_OK)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN; /* for safety */
+
+ /* Free the text pointer (this is the old read_buffer on
+ * success)
+ */
+ png_free(png_ptr, text);
+ text = NULL;
+
+ /* This really is very benign, but it's still an error because
+ * the extra space may otherwise be used as a Trojan Horse.
+ */
+ if (ret == Z_STREAM_END &&
+ chunklength - prefix_size != lzsize)
+ png_chunk_benign_error(png_ptr, "extra compressed data");
+ }
+
+ else
+ {
+ /* Out of memory allocating the buffer */
+ ret = Z_MEM_ERROR;
+ png_zstream_error(png_ptr, Z_MEM_ERROR);
+ }
}
- png_warning(png_ptr, "png_inflate logic error");
- png_free(png_ptr, text);
+ else
+ {
+ /* inflateReset failed, store the error message */
+ png_zstream_error(png_ptr, ret);
+
+ if (ret == Z_STREAM_END)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+ }
}
- else
- png_warning(png_ptr, "Not enough memory to decompress chunk");
+ else if (ret == Z_OK)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+
+ /* Release the claimed stream */
+ png_ptr->zowner = 0;
}
+
+ else /* the claim failed */ if (ret == Z_STREAM_END) /* impossible! */
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+
+ return ret;
}
- else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
+ else
{
- PNG_WARNING_PARAMETERS(p)
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type);
- png_formatted_warning(png_ptr, p, "Unknown zTXt compression type @1");
-
- /* The recovery is to simply drop the data. */
+ /* Application/configuration limits exceeded */
+ png_zstream_error(png_ptr, Z_MEM_ERROR);
+ return Z_MEM_ERROR;
}
-
- /* 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 /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */
+#endif /* READ_COMPRESSED_TEXT */
+
+#ifdef PNG_READ_iCCP_SUPPORTED
+/* Perform a partial read and decompress, producing 'avail_out' bytes and
+ * reading from the current chunk as required.
+ */
+static int
+png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,
+ png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size,
+ int finish)
+{
+ if (png_ptr->zowner == png_ptr->chunk_name)
+ {
+ int ret;
+
+ /* next_in and avail_in must have been initialized by the caller. */
+ png_ptr->zstream.next_out = next_out;
+ png_ptr->zstream.avail_out = 0; /* set in the loop */
+
+ do
+ {
+ if (png_ptr->zstream.avail_in == 0)
+ {
+ if (read_size > *chunk_bytes)
+ read_size = (uInt)*chunk_bytes;
+ *chunk_bytes -= read_size;
+
+ if (read_size > 0)
+ png_crc_read(png_ptr, read_buffer, read_size);
+
+ png_ptr->zstream.next_in = read_buffer;
+ png_ptr->zstream.avail_in = read_size;
+ }
+
+ if (png_ptr->zstream.avail_out == 0)
+ {
+ uInt avail = ZLIB_IO_MAX;
+ if (avail > *out_size)
+ avail = (uInt)*out_size;
+ *out_size -= avail;
+
+ png_ptr->zstream.avail_out = avail;
+ }
+
+ /* Use Z_SYNC_FLUSH when there is no more chunk data to ensure that all
+ * the available output is produced; this allows reading of truncated
+ * streams.
+ */
+ ret = inflate(&png_ptr->zstream,
+ *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH));
+ }
+ while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0));
+
+ *out_size += png_ptr->zstream.avail_out;
+ png_ptr->zstream.avail_out = 0; /* Should not be required, but is safe */
+
+ /* Ensure the error message pointer is always set: */
+ png_zstream_error(png_ptr, ret);
+ return ret;
+ }
+
+ else
+ {
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");
+ return Z_STREAM_ERROR;
+ }
+}
+#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_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[13];
png_uint_32 width, height;
@@ -560,12 +827,12 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_IHDR");
- if (png_ptr->mode & PNG_HAVE_IHDR)
- png_error(png_ptr, "Out of place IHDR");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) != 0)
+ png_chunk_error(png_ptr, "out of place");
/* Check the length */
if (length != 13)
- png_error(png_ptr, "Invalid IHDR chunk");
+ png_chunk_error(png_ptr, "invalid");
png_ptr->mode |= PNG_HAVE_IHDR;
@@ -614,8 +881,7 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
/* Set up other useful info */
- png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
- png_ptr->channels);
+ 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);
@@ -626,7 +892,7 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Read and check the palette */
void /* PRIVATE */
-png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_color palette[PNG_MAX_PALETTE_LENGTH];
int num, i;
@@ -636,26 +902,33 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_PLTE");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before PLTE");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ /* Moved to before the 'after IDAT' check below because otherwise duplicate
+ * PLTE chunks are potentially ignored (the spec says there shall not be more
+ * than one PLTE, the error is not treated as benign, so this check trumps
+ * the requirement that PLTE appears before IDAT.)
+ */
+ else if ((png_ptr->mode & PNG_HAVE_PLTE) != 0)
+ png_chunk_error(png_ptr, "duplicate");
+
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid PLTE after IDAT");
+ /* This is benign because the non-benign error happened before, when an
+ * IDAT was encountered in a color-mapped image with no PLTE.
+ */
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
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))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
- png_warning(png_ptr,
- "Ignoring PLTE chunk in grayscale PNG");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "ignored in grayscale PNG");
return;
}
@@ -669,19 +942,18 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
{
+ png_crc_finish(png_ptr, length);
+
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
- {
- png_warning(png_ptr, "Invalid palette chunk");
- png_crc_finish(png_ptr, length);
- return;
- }
+ png_chunk_benign_error(png_ptr, "invalid");
else
- {
- png_error(png_ptr, "Invalid palette chunk");
- }
+ png_chunk_error(png_ptr, "invalid");
+
+ return;
}
+ /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
num = (int)length / 3;
#ifdef PNG_POINTER_INDEXING_SUPPORTED
@@ -720,214 +992,196 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
- else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
+ else if (png_crc_error(png_ptr) != 0) /* 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).
+ *
+ * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the
+ * chunk type to determine whether to check the ancillary or the critical
+ * flags.
*/
- if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
+ if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE) == 0)
{
- if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
- {
- png_chunk_benign_error(png_ptr, "CRC error");
- }
+ if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) != 0)
+ return;
else
- {
- png_chunk_warning(png_ptr, "CRC error");
- return;
- }
+ png_chunk_error(png_ptr, "CRC error");
}
/* Otherwise, we (optionally) emit a warning and use the chunk. */
- else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
- {
+ else if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0)
png_chunk_warning(png_ptr, "CRC error");
- }
}
#endif
+ /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its
+ * own copy of the palette. This has the side effect that when png_start_row
+ * is called (this happens after any call to png_read_update_info) the
+ * info_ptr palette gets changed. This is extremely unexpected and
+ * confusing.
+ *
+ * Fix this by not sharing the palette in this way.
+ */
png_set_PLTE(png_ptr, info_ptr, palette, num);
+ /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before
+ * IDAT. Prior to 1.6.0 this was not checked; instead the code merely
+ * checked the apparent validity of a tRNS chunk inserted before PLTE on a
+ * palette PNG. 1.6.0 attempts to rigorously follow the standard and
+ * therefore does a benign error if the erroneous condition is detected *and*
+ * cancels the tRNS if the benign error returns. The alternative is to
+ * amend the standard since it would be rather hypocritical of the standards
+ * maintainers to ignore it.
+ */
#ifdef PNG_READ_tRNS_SUPPORTED
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ if (png_ptr->num_trans > 0 ||
+ (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0))
{
- 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;
- }
+ /* Cancel this because otherwise it would be used if the transforms
+ * require it. Don't cancel the 'valid' flag because this would prevent
+ * detection of duplicate chunks.
+ */
+ png_ptr->num_trans = 0;
- 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;
- }
- }
+ if (info_ptr != NULL)
+ info_ptr->num_trans = 0;
+
+ png_chunk_benign_error(png_ptr, "tRNS must be after");
}
#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
+ png_chunk_benign_error(png_ptr, "hIST must be after");
+#endif
+
+#ifdef PNG_READ_bKGD_SUPPORTED
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
+ png_chunk_benign_error(png_ptr, "bKGD must be after");
+#endif
}
void /* PRIVATE */
-png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_IEND(png_structrp png_ptr, png_inforp 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");
- }
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0 ||
+ (png_ptr->mode & PNG_HAVE_IDAT) == 0)
+ png_chunk_error(png_ptr, "out of place");
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 */
+ if (length != 0)
+ png_chunk_benign_error(png_ptr, "invalid");
+
+ PNG_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_handle_gAMA(png_structrp png_ptr, png_inforp 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");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- 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);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 4)
{
- png_warning(png_ptr, "Incorrect gAMA chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 4);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 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_PARAMETERS(p)
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, igamma);
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect gAMA value @1 when sRGB is also present");
- 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);
+ png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma);
+ png_colorspace_sync(png_ptr, info_ptr);
}
#endif
#ifdef PNG_READ_sBIT_SUPPORTED
void /* PRIVATE */
-png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t truelen;
+ unsigned int truelen, i;
+ png_byte sample_depth;
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) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sBIT");
-
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid sBIT after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->mode & PNG_HAVE_PLTE)
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) != 0)
{
- /* 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);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
truelen = 3;
+ sample_depth = 8;
+ }
else
- truelen = (png_size_t)png_ptr->channels;
+ {
+ truelen = png_ptr->channels;
+ sample_depth = png_ptr->bit_depth;
+ }
if (length != truelen || length > 4)
{
- png_warning(png_ptr, "Incorrect sBIT chunk length");
+ png_chunk_benign_error(png_ptr, "invalid");
png_crc_finish(png_ptr, length);
return;
}
+ buf[0] = buf[1] = buf[2] = buf[3] = sample_depth;
png_crc_read(png_ptr, buf, truelen);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ for (i=0; i sample_depth)
+ {
+ png_chunk_benign_error(png_ptr, "invalid");
+ return;
+ }
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_ptr->sig_bit.red = buf[0];
png_ptr->sig_bit.green = buf[1];
@@ -950,377 +1204,416 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_cHRM_SUPPORTED
void /* PRIVATE */
-png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_cHRM(png_structrp png_ptr, png_inforp 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_xy xy;
png_debug(1, "in png_handle_cHRM");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before cHRM");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- 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);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 32)
{
- png_warning(png_ptr, "Incorrect cHRM chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 32);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 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);
+ xy.whitex = png_get_fixed_point(NULL, buf);
+ xy.whitey = png_get_fixed_point(NULL, buf + 4);
+ xy.redx = png_get_fixed_point(NULL, buf + 8);
+ xy.redy = png_get_fixed_point(NULL, buf + 12);
+ xy.greenx = png_get_fixed_point(NULL, buf + 16);
+ xy.greeny = png_get_fixed_point(NULL, buf + 20);
+ xy.bluex = png_get_fixed_point(NULL, buf + 24);
+ xy.bluey = 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)
+ if (xy.whitex == PNG_FIXED_ERROR ||
+ xy.whitey == PNG_FIXED_ERROR ||
+ xy.redx == PNG_FIXED_ERROR ||
+ xy.redy == PNG_FIXED_ERROR ||
+ xy.greenx == PNG_FIXED_ERROR ||
+ xy.greeny == PNG_FIXED_ERROR ||
+ xy.bluex == PNG_FIXED_ERROR ||
+ xy.bluey == PNG_FIXED_ERROR)
{
- png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities");
+ png_chunk_benign_error(png_ptr, "invalid values");
return;
}
-#ifdef PNG_READ_sRGB_SUPPORTED
- if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
+ return;
+
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0)
{
- 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_PARAMETERS(p)
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, x_white);
- png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_fixed, y_white);
- png_warning_parameter_signed(p, 3, PNG_NUMBER_FORMAT_fixed, x_red);
- png_warning_parameter_signed(p, 4, PNG_NUMBER_FORMAT_fixed, y_red);
- png_warning_parameter_signed(p, 5, PNG_NUMBER_FORMAT_fixed, x_green);
- png_warning_parameter_signed(p, 6, PNG_NUMBER_FORMAT_fixed, y_green);
- png_warning_parameter_signed(p, 7, PNG_NUMBER_FORMAT_fixed, x_blue);
- png_warning_parameter_signed(p, 8, PNG_NUMBER_FORMAT_fixed, y_blue);
-
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect cHRM white(@1,@2) r(@3,@4)g(@5,@6)b(@7,@8) "
- "when sRGB is also present");
- }
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
-#endif /* PNG_READ_sRGB_SUPPORTED */
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- /* Store the _white values as default coefficients for the rgb to gray
- * operation if it is supported.
- */
- if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
- {
- /* png_set_background has not been called, the coefficients must be in
- * range for the following to work without overflow.
- */
- if (y_red <= (1<<17) && y_green <= (1<<17) && y_blue <= (1<<17))
- {
- /* The y values are chromaticities: Y/X+Y+Z, the weights for the gray
- * transformation are simply the normalized Y values for red, green and
- * blue scaled by 32768.
- */
- png_uint_32 w = y_red + y_green + y_blue;
-
- png_ptr->rgb_to_gray_red_coeff = (png_uint_16)(((png_uint_32)y_red *
- 32768)/w);
- png_ptr->rgb_to_gray_green_coeff = (png_uint_16)(((png_uint_32)y_green
- * 32768)/w);
- png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(((png_uint_32)y_blue *
- 32768)/w);
- }
- }
-#endif
-
- png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red,
- x_green, y_green, x_blue, y_blue);
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+ (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy,
+ 1/*prefer cHRM values*/);
+ png_colorspace_sync(png_ptr, info_ptr);
}
#endif
#ifdef PNG_READ_sRGB_SUPPORTED
void /* PRIVATE */
-png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- int intent;
- png_byte buf[1];
+ png_byte intent;
png_debug(1, "in png_handle_sRGB");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sRGB");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- 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);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 1)
{
- png_warning(png_ptr, "Incorrect sRGB chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, buf, 1);
+ png_crc_read(png_ptr, &intent, 1);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- intent = buf[0];
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
+ return;
- /* Check for bad intent */
- if (intent >= PNG_sRGB_INTENT_LAST)
+ /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
+ * this.
+ */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) != 0)
{
- png_warning(png_ptr, "Unknown sRGB intent");
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ png_chunk_benign_error(png_ptr, "too many profiles");
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_PARAMETERS(p)
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed,
- info_ptr->gamma);
-
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect gAMA value @1 when sRGB is also present");
- }
- }
-#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);
+ (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent);
+ png_colorspace_sync(png_ptr, info_ptr);
}
-#endif /* PNG_READ_sRGB_SUPPORTED */
+#endif /* READ_sRGB */
#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_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+/* Note: this does not properly handle profiles 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_const_charp errmsg = NULL; /* error message output, or no error */
+ int finished = 0; /* crc checked */
png_debug(1, "in png_handle_iCCP");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before iCCP");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
+ {
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
+ return;
+ }
+
+ /* Consistent with all the above colorspace handling an obviously *invalid*
+ * chunk is just ignored, so does not invalidate the color space. An
+ * alternative is to set the 'invalid' flags at the start of this routine
+ * and only clear them in they were not set before and all the tests pass.
+ * The minimum 'deflate' stream is assumed to be just the 2 byte header and
+ * 4 byte checksum. The keyword must be at least one character and there is
+ * a terminator (0) byte and the compression method.
+ */
+ if (length < 9)
+ {
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too short");
+ return;
+ }
+
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
{
- 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))
+ /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
+ * this.
+ */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0)
{
- png_warning(png_ptr, "Duplicate iCCP chunk");
+ uInt read_length, keyword_length;
+ char keyword[81];
+
+ /* Find the keyword; the keyword plus separator and compression method
+ * bytes can be at most 81 characters long.
+ */
+ read_length = 81; /* maximum */
+ if (read_length > length)
+ read_length = (uInt)length;
+
+ png_crc_read(png_ptr, (png_bytep)keyword, read_length);
+ length -= read_length;
+
+ keyword_length = 0;
+ while (keyword_length < 80 && keyword_length < read_length &&
+ keyword[keyword_length] != 0)
+ ++keyword_length;
+
+ /* TODO: make the keyword checking common */
+ if (keyword_length >= 1 && keyword_length <= 79)
+ {
+ /* We only understand '0' compression - deflate - so if we get a
+ * different value we can't safely decode the chunk.
+ */
+ if (keyword_length+1 < read_length &&
+ keyword[keyword_length+1] == PNG_COMPRESSION_TYPE_BASE)
+ {
+ read_length -= keyword_length+2;
+
+ if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK)
+ {
+ Byte profile_header[132];
+ Byte local_buffer[PNG_INFLATE_BUF_SIZE];
+ png_alloc_size_t size = (sizeof profile_header);
+
+ png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2);
+ png_ptr->zstream.avail_in = read_length;
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length, profile_header, &size,
+ 0/*finish: don't, because the output is too small*/);
+
+ if (size == 0)
+ {
+ /* We have the ICC profile header; do the basic header checks.
+ */
+ const png_uint_32 profile_length =
+ png_get_uint_32(profile_header);
+
+ if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
+ keyword, profile_length) != 0)
+ {
+ /* The length is apparently ok, so we can check the 132
+ * byte header.
+ */
+ if (png_icc_check_header(png_ptr, &png_ptr->colorspace,
+ keyword, profile_length, profile_header,
+ png_ptr->color_type) != 0)
+ {
+ /* Now read the tag table; a variable size buffer is
+ * needed at this point, allocate one for the whole
+ * profile. The header check has already validated
+ * that none of these stuff will overflow.
+ */
+ const png_uint_32 tag_count = png_get_uint_32(
+ profile_header+128);
+ png_bytep profile = png_read_buffer(png_ptr,
+ profile_length, 2/*silent*/);
+
+ if (profile != NULL)
+ {
+ memcpy(profile, profile_header,
+ (sizeof profile_header));
+
+ size = 12 * tag_count;
+
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length,
+ profile + (sizeof profile_header), &size, 0);
+
+ /* Still expect a buffer error because we expect
+ * there to be some tag data!
+ */
+ if (size == 0)
+ {
+ if (png_icc_check_tag_table(png_ptr,
+ &png_ptr->colorspace, keyword, profile_length,
+ profile) != 0)
+ {
+ /* The profile has been validated for basic
+ * security issues, so read the whole thing in.
+ */
+ size = profile_length - (sizeof profile_header)
+ - 12 * tag_count;
+
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length,
+ profile + (sizeof profile_header) +
+ 12 * tag_count, &size, 1/*finish*/);
+
+ if (length > 0 && !(png_ptr->flags &
+ PNG_FLAG_BENIGN_ERRORS_WARN))
+ errmsg = "extra compressed data";
+
+ /* But otherwise allow extra data: */
+ else if (size == 0)
+ {
+ if (length > 0)
+ {
+ /* This can be handled completely, so
+ * keep going.
+ */
+ png_chunk_warning(png_ptr,
+ "extra compressed data");
+ }
+
+ png_crc_finish(png_ptr, length);
+ finished = 1;
+
+# ifdef PNG_sRGB_SUPPORTED
+ /* Check for a match against sRGB */
+ png_icc_set_sRGB(png_ptr,
+ &png_ptr->colorspace, profile,
+ png_ptr->zstream.adler);
+# endif
+
+ /* Steal the profile for info_ptr. */
+ if (info_ptr != NULL)
+ {
+ png_free_data(png_ptr, info_ptr,
+ PNG_FREE_ICCP, 0);
+
+ info_ptr->iccp_name = png_voidcast(char*,
+ png_malloc_base(png_ptr,
+ keyword_length+1));
+ if (info_ptr->iccp_name != NULL)
+ {
+ memcpy(info_ptr->iccp_name, keyword,
+ keyword_length+1);
+ info_ptr->iccp_proflen =
+ profile_length;
+ info_ptr->iccp_profile = profile;
+ png_ptr->read_buffer = NULL; /*steal*/
+ info_ptr->free_me |= PNG_FREE_ICCP;
+ info_ptr->valid |= PNG_INFO_iCCP;
+ }
+
+ else
+ {
+ png_ptr->colorspace.flags |=
+ PNG_COLORSPACE_INVALID;
+ errmsg = "out of memory";
+ }
+ }
+
+ /* else the profile remains in the read
+ * buffer which gets reused for subsequent
+ * chunks.
+ */
+
+ if (info_ptr != NULL)
+ png_colorspace_sync(png_ptr, info_ptr);
+
+ if (errmsg == NULL)
+ {
+ png_ptr->zowner = 0;
+ return;
+ }
+ }
+
+ else if (size > 0)
+ errmsg = "truncated";
+
+ else
+ errmsg = png_ptr->zstream.msg;
+ }
+
+ /* else png_icc_check_tag_table output an error */
+ }
+
+ else /* profile truncated */
+ errmsg = png_ptr->zstream.msg;
+ }
+
+ else
+ errmsg = "out of memory";
+ }
+
+ /* else png_icc_check_header output an error */
+ }
+
+ /* else png_icc_check_length output an error */
+ }
+
+ else /* profile truncated */
+ errmsg = png_ptr->zstream.msg;
+
+ /* Release the stream */
+ png_ptr->zowner = 0;
+ }
+
+ else /* png_inflate_claim failed */
+ errmsg = png_ptr->zstream.msg;
+ }
+
+ else
+ errmsg = "bad compression method"; /* or missing */
+ }
+
+ else
+ errmsg = "bad keyword";
+ }
+
+ else
+ errmsg = "too many profiles";
+
+ /* Failure: the reason is in 'errmsg' */
+ if (finished == 0)
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_WARNING_PARAMETERS(p)
-
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
-
- png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_u, profile_size);
- png_warning_parameter_unsigned(p, 2, PNG_NUMBER_FORMAT_u, profile_length);
- png_formatted_warning(png_ptr, p,
- "Ignoring iCCP chunk with declared size = @1 and actual length = @2");
- 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;
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ if (errmsg != NULL) /* else already output */
+ png_chunk_benign_error(png_ptr, errmsg);
}
-#endif /* PNG_READ_iCCP_SUPPORTED */
+#endif /* READ_iCCP */
#ifdef PNG_READ_sPLT_SUPPORTED
void /* PRIVATE */
-png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
/* Note: this does not properly handle chunks that are > 64K under DOS */
{
- png_bytep entry_start;
+ png_bytep entry_start, buffer;
png_sPLT_t new_palette;
png_sPLT_entryp pp;
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)
@@ -1338,55 +1631,53 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sPLT");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid sPLT after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
#ifdef PNG_MAX_MALLOC_64K
- if (length > (png_uint_32)65535L)
+ if (length > 65535U)
{
- png_warning(png_ptr, "sPLT chunk too large to fit in memory");
- skip = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too large to fit in memory");
+ return;
}
#endif
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+ if (buffer == NULL)
+ {
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
+ return;
+ }
+
/* 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);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, skip))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, skip) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00;
+ buffer[length] = 0;
- for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
- entry_start++)
+ for (entry_start = buffer; *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)
+ if (entry_start > buffer + length - 2)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_warning(png_ptr, "malformed sPLT chunk");
return;
}
@@ -1394,23 +1685,19 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
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.)
+ * chunk data length.
*/
- data_length = length - (png_uint_32)(entry_start -
- (png_bytep)png_ptr->chunkdata);
+ data_length = length - (png_uint_32)(entry_start - buffer);
/* Integrity-check the data length */
- if (data_length % entry_size)
+ if ((data_length % entry_size) != 0)
{
- 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);
+ max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry));
if (dl > max_dl)
{
@@ -1421,7 +1708,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
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));
+ png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry)));
if (new_palette.entries == NULL)
{
@@ -1479,38 +1766,36 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#endif
/* Discard all chunk data except the name and stash that */
- new_palette.name = png_ptr->chunkdata;
+ new_palette.name = (png_charp)buffer;
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 */
+#endif /* READ_sPLT */
#ifdef PNG_READ_tRNS_SUPPORTED
void /* PRIVATE */
-png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_tRNS(png_structrp png_ptr, png_inforp 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");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid tRNS after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)
{
- png_warning(png_ptr, "Duplicate tRNS chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
@@ -1520,8 +1805,8 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != 2)
{
- png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
@@ -1536,12 +1821,12 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != 6)
{
- png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, buf, (png_size_t)length);
+ png_crc_read(png_ptr, buf, 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);
@@ -1550,44 +1835,43 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
- if (!(png_ptr->mode & PNG_HAVE_PLTE))
+ if ((png_ptr->mode & PNG_HAVE_PLTE) == 0)
{
- /* 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");
+ /* TODO: is this actually an error in the ISO spec? */
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- if (length == 0)
+ if (length > png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH ||
+ length == 0)
{
- png_warning(png_ptr, "Zero length tRNS chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, readbuf, (png_size_t)length);
+ png_crc_read(png_ptr, readbuf, 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);
+ png_chunk_benign_error(png_ptr, "invalid with alpha channel");
return;
}
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
{
png_ptr->num_trans = 0;
return;
}
+ /* TODO: this is a horrible side effect in the palette case because the
+ * png_struct ends up with a pointer to the tRNS buffer owned by the
+ * png_info. Fix this.
+ */
png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
&(png_ptr->trans_color));
}
@@ -1595,43 +1879,37 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_bKGD_SUPPORTED
void /* PRIVATE */
-png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t truelen;
+ unsigned int truelen;
png_byte buf[6];
png_color_16 background;
png_debug(1, "in png_handle_bKGD");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before bKGD");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
+ (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0))
{
- png_warning(png_ptr, "Invalid bKGD after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
{
- 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);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
truelen = 1;
- else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
truelen = 6;
else
@@ -1639,14 +1917,14 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != truelen)
{
- png_warning(png_ptr, "Incorrect bKGD chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, truelen);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
/* We convert the index value into RGB components so that we can allow
@@ -1658,11 +1936,11 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
background.index = buf[0];
- if (info_ptr && info_ptr->num_palette)
+ if (info_ptr != NULL && info_ptr->num_palette != 0)
{
if (buf[0] >= info_ptr->num_palette)
{
- png_warning(png_ptr, "Incorrect bKGD chunk index value");
+ png_chunk_benign_error(png_ptr, "invalid index");
return;
}
@@ -1677,7 +1955,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
background.gray = 0;
}
- else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
+ else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */
{
background.index = 0;
background.red =
@@ -1701,44 +1979,37 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_hIST_SUPPORTED
void /* PRIVATE */
-png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_hIST(png_structrp png_ptr, png_inforp 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");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0)
{
- png_warning(png_ptr, "Invalid hIST after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (!(png_ptr->mode & PNG_HAVE_PLTE))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
{
- 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);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
num = length / 2 ;
- if (num != (unsigned int)png_ptr->num_palette || num >
- (unsigned int)PNG_MAX_PALETTE_LENGTH)
+ if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH)
{
- png_warning(png_ptr, "Incorrect hIST chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
@@ -1750,7 +2021,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
readbuf[i] = png_get_uint_16(buf);
}
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
png_set_hIST(png_ptr, info_ptr, readbuf);
@@ -1759,7 +2030,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_pHYs_SUPPORTED
void /* PRIVATE */
-png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[9];
png_uint_32 res_x, res_y;
@@ -1767,33 +2038,33 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_pHYs");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before pHYs");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid pHYs after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
- png_warning(png_ptr, "Duplicate pHYs chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (length != 9)
{
- png_warning(png_ptr, "Incorrect pHYs chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 9);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
res_x = png_get_uint_32(buf);
@@ -1805,7 +2076,7 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_oFFs_SUPPORTED
void /* PRIVATE */
-png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[9];
png_int_32 offset_x, offset_y;
@@ -1813,33 +2084,33 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_oFFs");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before oFFs");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid oFFs after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
- png_warning(png_ptr, "Duplicate oFFs chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (length != 9)
{
- png_warning(png_ptr, "Incorrect oFFs chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 9);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
offset_x = png_get_int_32(buf);
@@ -1852,71 +2123,64 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#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_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_int_32 X0, X1;
png_byte type, nparams;
- png_charp buf, units, endptr;
+ png_bytep buffer, 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");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid pCAL after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) != 0)
{
- png_warning(png_ptr, "Duplicate pCAL chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
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)
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+
+ if (buffer == NULL)
{
- png_warning(png_ptr, "No memory for pCAL purpose");
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = (png_size_t)length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
+ buffer[length] = 0; /* Null terminate the last string */
png_debug(3, "Finding end of pCAL purpose string");
- for (buf = png_ptr->chunkdata; *buf; buf++)
+ for (buf = buffer; *buf; buf++)
/* Empty loop */ ;
- endptr = png_ptr->chunkdata + slength;
+ endptr = buffer + length;
/* 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;
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
@@ -1936,15 +2200,13 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
(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;
+ png_chunk_benign_error(png_ptr, "invalid parameter count");
return;
}
else if (type >= PNG_EQUATION_LAST)
{
- png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+ png_chunk_benign_error(png_ptr, "unrecognized equation type");
}
for (buf = units; *buf; buf++)
@@ -1952,43 +2214,37 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(3, "Allocating pCAL parameters array");
- params = (png_charpp)png_malloc_warn(png_ptr,
- (png_size_t)(nparams * png_sizeof(png_charp)));
+ params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
+ nparams * (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");
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
/* Get pointers to the start of each parameter string. */
- for (i = 0; i < (int)nparams; i++)
+ for (i = 0; i < 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++)
+ for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; 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);
+ png_chunk_benign_error(png_ptr, "invalid data");
return;
}
}
- png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
- units, params);
+ png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams,
+ (png_charp)units, params);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_free(png_ptr, params);
}
#endif
@@ -1996,67 +2252,61 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#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_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t slength, i;
+ png_bytep buffer;
+ png_size_t 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");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid sCAL after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
- png_warning(png_ptr, "Duplicate sCAL chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
/* Need unit type, width, \0, height: minimum 4 bytes */
else if (length < 4)
{
- png_warning(png_ptr, "sCAL chunk too short");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
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);
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
- if (png_ptr->chunkdata == NULL)
+ if (buffer == NULL)
{
- png_warning(png_ptr, "Out of memory while processing sCAL chunk");
+ png_chunk_benign_error(png_ptr, "out of memory");
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 */
+ png_crc_read(png_ptr, buffer, length);
+ buffer[length] = 0; /* Null terminate the last string */
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
/* Validate the unit. */
- if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2)
+ if (buffer[0] != 1 && buffer[0] != 2)
{
- png_warning(png_ptr, "Invalid sCAL ignored: invalid unit");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ png_chunk_benign_error(png_ptr, "invalid unit");
return;
}
@@ -2066,70 +2316,65 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
i = 1;
state = 0;
- if (!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");
+ if (png_check_fp_number((png_const_charp)buffer, length, &state, &i) == 0 ||
+ i >= length || buffer[i++] != 0)
+ png_chunk_benign_error(png_ptr, "bad width format");
- else if (!PNG_FP_IS_POSITIVE(state))
- png_warning(png_ptr, "Invalid sCAL chunk ignored: non-positive width");
+ else if (PNG_FP_IS_POSITIVE(state) == 0)
+ png_chunk_benign_error(png_ptr, "non-positive width");
else
{
png_size_t heighti = i;
state = 0;
- if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
- i != slength)
- png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format");
+ if (png_check_fp_number((png_const_charp)buffer, length,
+ &state, &i) == 0 || i != length)
+ png_chunk_benign_error(png_ptr, "bad height format");
- else if (!PNG_FP_IS_POSITIVE(state))
- png_warning(png_ptr,
- "Invalid sCAL chunk ignored: non-positive height");
+ else if (PNG_FP_IS_POSITIVE(state) == 0)
+ png_chunk_benign_error(png_ptr, "non-positive height");
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);
+ png_set_sCAL_s(png_ptr, info_ptr, buffer[0],
+ (png_charp)buffer+1, (png_charp)buffer+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_handle_tIME(png_structrp png_ptr, png_inforp 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");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) != 0)
{
- png_warning(png_ptr, "Duplicate tIME chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
if (length != 7)
{
- png_warning(png_ptr, "Incorrect tIME chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 7);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
mod_time.second = buf[6];
@@ -2146,14 +2391,13 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#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_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_textp text_ptr;
+ png_text text_info;
+ png_bytep buffer;
png_charp key;
png_charp text;
png_uint_32 skip = 0;
- png_size_t slength;
- int ret;
png_debug(1, "in png_handle_tEXt");
@@ -2168,84 +2412,59 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
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);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before tEXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
#ifdef PNG_MAX_MALLOC_64K
- if (length > (png_uint_32)65535L)
+ if (length > 65535U)
{
- png_warning(png_ptr, "tEXt chunk too large to fit in memory");
- skip = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too large to fit in memory");
+ return;
}
#endif
- png_free(png_ptr, png_ptr->chunkdata);
+ buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
-
- if (png_ptr->chunkdata == NULL)
+ if (buffer == NULL)
{
- png_warning(png_ptr, "No memory to process text chunk");
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = (png_size_t)length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, skip))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, skip) != 0)
return;
- }
- key = png_ptr->chunkdata;
-
- key[slength] = 0x00;
+ key = (png_charp)buffer;
+ key[length] = 0;
for (text = key; *text; text++)
/* Empty loop to find end of key */ ;
- if (text != key + slength)
+ if (text != key + length)
text++;
- text_ptr = (png_textp)png_malloc_warn(png_ptr,
- png_sizeof(png_text));
+ text_info.compression = PNG_TEXT_COMPRESSION_NONE;
+ text_info.key = key;
+ text_info.lang = NULL;
+ text_info.lang_key = NULL;
+ text_info.itxt_length = 0;
+ text_info.text = text;
+ text_info.text_length = strlen(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)
+ if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) != 0)
png_warning(png_ptr, "Insufficient memory to process text chunk");
}
#endif
@@ -2253,13 +2472,11 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#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_handle_zTXt(png_structrp png_ptr, png_inforp 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_const_charp errmsg = NULL;
+ png_bytep buffer;
+ png_uint_32 keyword_length;
png_debug(1, "in png_handle_zTXt");
@@ -2274,123 +2491,101 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
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);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before zTXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
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)
+ buffer = png_read_buffer(png_ptr, length, 2/*silent*/);
+
+ if (buffer == NULL)
{
- 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");
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = (png_size_t)length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00;
+ /* TODO: also check that the keyword contents match the spec! */
+ for (keyword_length = 0;
+ keyword_length < length && buffer[keyword_length] != 0;
+ ++keyword_length)
+ /* Empty loop to find end of name */ ;
- for (text = png_ptr->chunkdata; *text; text++)
- /* Empty loop */ ;
+ if (keyword_length > 79 || keyword_length < 1)
+ errmsg = "bad keyword";
- /* 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;
- }
+ /* zTXt must have some LZ data after the keyword, although it may expand to
+ * zero bytes; we need a '\0' at the end of the keyword, the compression type
+ * then the LZ data:
+ */
+ else if (keyword_length + 3 > length)
+ errmsg = "truncated";
+
+ else if (buffer[keyword_length+1] != PNG_COMPRESSION_TYPE_BASE)
+ errmsg = "unknown compression type";
else
{
- comp_type = *(++text);
+ png_alloc_size_t uncompressed_length = PNG_SIZE_MAX;
- if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
- {
- png_warning(png_ptr, "Unknown compression type in zTXt chunk");
- comp_type = PNG_TEXT_COMPRESSION_zTXt;
- }
+ /* TODO: at present png_decompress_chunk imposes a single application
+ * level memory limit, this should be split to different values for iCCP
+ * and text chunks.
+ */
+ if (png_decompress_chunk(png_ptr, length, keyword_length+2,
+ &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
+ {
+ png_text text;
- text++; /* Skip the compression_method byte */
+ /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except
+ * for the extra compression type byte and the fact that it isn't
+ * necessarily '\0' terminated.
+ */
+ buffer = png_ptr->read_buffer;
+ buffer[uncompressed_length+(keyword_length+2)] = 0;
+
+ text.compression = PNG_TEXT_COMPRESSION_zTXt;
+ text.key = (png_charp)buffer;
+ text.text = (png_charp)(buffer + keyword_length+2);
+ text.text_length = uncompressed_length;
+ text.itxt_length = 0;
+ text.lang = NULL;
+ text.lang_key = NULL;
+
+ if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
+ errmsg = "insufficient memory";
+ }
+
+ else
+ errmsg = png_ptr->zstream.msg;
}
- 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");
+ if (errmsg != NULL)
+ png_chunk_benign_error(png_ptr, errmsg);
}
#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_handle_iTXt(png_structrp png_ptr, png_inforp 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_const_charp errmsg = NULL;
+ png_bytep buffer;
+ png_uint_32 prefix_length;
png_debug(1, "in png_handle_iTXt");
@@ -2405,274 +2600,393 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
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);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before iTXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
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)
+ buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
+
+ if (buffer == NULL)
{
- 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");
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = (png_size_t)length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00;
-
- for (lang = png_ptr->chunkdata; *lang; lang++)
+ /* First the keyword. */
+ for (prefix_length=0;
+ prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
/* Empty loop */ ;
- lang++; /* Skip NUL separator */
+ /* Perform a basic check on the keyword length here. */
+ if (prefix_length > 79 || prefix_length < 1)
+ errmsg = "bad keyword";
- /* iTXt must have a language tag (possibly empty), two compression bytes,
- * translated keyword (possibly empty), and possibly some text after the
- * keyword
+ /* Expect keyword, compression flag, compression type, language, translated
+ * keyword (both may be empty but are 0 terminated) then the text, which may
+ * be empty.
*/
+ else if (prefix_length + 5 > length)
+ errmsg = "truncated";
- if (lang >= png_ptr->chunkdata + slength - 3)
+ else if (buffer[prefix_length+1] == 0 ||
+ (buffer[prefix_length+1] == 1 &&
+ buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE))
{
- png_warning(png_ptr, "Truncated iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
+ int compressed = buffer[prefix_length+1] != 0;
+ png_uint_32 language_offset, translated_keyword_offset;
+ png_alloc_size_t uncompressed_length = 0;
+
+ /* Now the language tag */
+ prefix_length += 3;
+ language_offset = prefix_length;
+
+ for (; prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
+ /* Empty loop */ ;
+
+ /* WARNING: the length may be invalid here, this is checked below. */
+ translated_keyword_offset = ++prefix_length;
+
+ for (; prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
+ /* Empty loop */ ;
+
+ /* prefix_length should now be at the trailing '\0' of the translated
+ * keyword, but it may already be over the end. None of this arithmetic
+ * can overflow because chunks are at most 2^31 bytes long, but on 16-bit
+ * systems the available allocation may overflow.
+ */
+ ++prefix_length;
+
+ if (compressed == 0 && prefix_length <= length)
+ uncompressed_length = length - prefix_length;
+
+ else if (compressed != 0 && prefix_length < length)
+ {
+ uncompressed_length = PNG_SIZE_MAX;
+
+ /* TODO: at present png_decompress_chunk imposes a single application
+ * level memory limit, this should be split to different values for
+ * iCCP and text chunks.
+ */
+ if (png_decompress_chunk(png_ptr, length, prefix_length,
+ &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
+ buffer = png_ptr->read_buffer;
+
+ else
+ errmsg = png_ptr->zstream.msg;
+ }
+
+ else
+ errmsg = "truncated";
+
+ if (errmsg == NULL)
+ {
+ png_text text;
+
+ buffer[uncompressed_length+prefix_length] = 0;
+
+ if (compressed == 0)
+ text.compression = PNG_ITXT_COMPRESSION_NONE;
+
+ else
+ text.compression = PNG_ITXT_COMPRESSION_zTXt;
+
+ text.key = (png_charp)buffer;
+ text.lang = (png_charp)buffer + language_offset;
+ text.lang_key = (png_charp)buffer + translated_keyword_offset;
+ text.text = (png_charp)buffer + prefix_length;
+ text.text_length = 0;
+ text.itxt_length = uncompressed_length;
+
+ if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
+ errmsg = "insufficient memory";
+ }
}
else
- {
- comp_flag = *lang++;
- comp_type = *lang++;
- }
+ errmsg = "bad compression info";
- 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");
+ if (errmsg != NULL)
+ png_chunk_benign_error(png_ptr, errmsg);
}
#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
- )
+/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
+static int
+png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
+{
+ png_alloc_size_t limit = PNG_SIZE_MAX;
+
+ if (png_ptr->unknown_chunk.data != NULL)
{
-#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_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
+ }
- png_memcpy((png_charp)png_ptr->unknown_chunk.name,
- (png_charp)png_ptr->chunk_name,
- png_sizeof(png_ptr->unknown_chunk.name));
+# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
+ if (png_ptr->user_chunk_malloc_max > 0 &&
+ png_ptr->user_chunk_malloc_max < limit)
+ limit = png_ptr->user_chunk_malloc_max;
- png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
- = '\0';
+# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+ if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+ limit = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
- png_ptr->unknown_chunk.size = (png_size_t)length;
+ if (length <= limit)
+ {
+ PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
+ /* The following is safe because of the PNG_SIZE_MAX init above */
+ png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/;
+ /* 'mode' is a flag array, only the bottom four bits matter here */
+ png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/;
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);
+ /* Do a 'warn' here - it is handled below. */
+ png_ptr->unknown_chunk.data = png_voidcast(png_bytep,
+ png_malloc_warn(png_ptr, 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;
+ if (png_ptr->unknown_chunk.data == NULL && length > 0)
+ {
+ /* This is benign because we clean up correctly */
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "unknown chunk exceeds memory limits");
+ return 0;
}
else
-#endif
- skip = length;
+ {
+ if (length > 0)
+ png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length);
+ png_crc_finish(png_ptr, 0);
+ return 1;
+ }
+}
+#endif /* READ_UNKNOWN_CHUNKS */
- png_crc_finish(png_ptr, skip);
+/* Handle an unknown, or known but disabled, chunk */
+void /* PRIVATE */
+png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
+ png_uint_32 length, int keep)
+{
+ int handled = 0; /* the chunk was handled */
-#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
- PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
-#endif
+ png_debug(1, "in png_handle_unknown");
+
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+ /* NOTE: this code is based on the code in libpng-1.4.12 except for fixing
+ * the bug which meant that setting a non-default behavior for a specific
+ * chunk would be ignored (the default was always used unless a user
+ * callback was installed).
+ *
+ * 'keep' is the value from the png_chunk_unknown_handling, the setting for
+ * this specific chunk_name, if PNG_HANDLE_AS_UNKNOWN_SUPPORTED, if not it
+ * will always be PNG_HANDLE_CHUNK_AS_DEFAULT and it needs to be set here.
+ * This is just an optimization to avoid multiple calls to the lookup
+ * function.
+ */
+# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name);
+# endif
+# endif
+
+ /* One of the following methods will read the chunk or skip it (at least one
+ * of these is always defined because this is the only way to switch on
+ * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+ */
+# ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+ /* The user callback takes precedence over the chunk keep value, but the
+ * keep value is still required to validate a save of a critical chunk.
+ */
+ if (png_ptr->read_user_chunk_fn != NULL)
+ {
+ if (png_cache_unknown_chunk(png_ptr, length) != 0)
+ {
+ /* Callback to user unknown chunk handler */
+ int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr,
+ &png_ptr->unknown_chunk);
+
+ /* ret is:
+ * negative: An error occured, png_chunk_error will be called.
+ * zero: The chunk was not handled, the chunk will be discarded
+ * unless png_set_keep_unknown_chunks has been used to set
+ * a 'keep' behavior for this particular chunk, in which
+ * case that will be used. A critical chunk will cause an
+ * error at this point unless it is to be saved.
+ * positive: The chunk was handled, libpng will ignore/discard it.
+ */
+ if (ret < 0)
+ png_chunk_error(png_ptr, "error in user chunk");
+
+ else if (ret == 0)
+ {
+ /* If the keep value is 'default' or 'never' override it, but
+ * still error out on critical chunks unless the keep value is
+ * 'always' While this is weird it is the behavior in 1.4.12.
+ * A possible improvement would be to obey the value set for the
+ * chunk, but this would be an API change that would probably
+ * damage some applications.
+ *
+ * The png_app_warning below catches the case that matters, where
+ * the application has not set specific save or ignore for this
+ * chunk or global save or ignore.
+ */
+ if (keep < PNG_HANDLE_CHUNK_IF_SAFE)
+ {
+# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE)
+ {
+ png_chunk_warning(png_ptr, "Saving unknown chunk:");
+ png_app_warning(png_ptr,
+ "forcing save of an unhandled chunk;"
+ " please call png_set_keep_unknown_chunks");
+ /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */
+ }
+# endif
+ keep = PNG_HANDLE_CHUNK_IF_SAFE;
+ }
+ }
+
+ else /* chunk was handled */
+ {
+ handled = 1;
+ /* Critical chunks can be safely discarded at this point. */
+ keep = PNG_HANDLE_CHUNK_NEVER;
+ }
+ }
+
+ else
+ keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */
+ }
+
+ else
+ /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */
+# endif /* READ_USER_CHUNKS */
+
+# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
+ {
+ /* keep is currently just the per-chunk setting, if there was no
+ * setting change it to the global default now (not that this may
+ * still be AS_DEFAULT) then obtain the cache of the chunk if required,
+ * if not simply skip the chunk.
+ */
+ if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT)
+ keep = png_ptr->unknown_default;
+
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
+ PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
+ {
+ if (png_cache_unknown_chunk(png_ptr, length) == 0)
+ keep = PNG_HANDLE_CHUNK_NEVER;
+ }
+
+ else
+ png_crc_finish(png_ptr, length);
+ }
+# else
+# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
+# error no method to support READ_UNKNOWN_CHUNKS
+# endif
+
+ {
+ /* If here there is no read callback pointer set and no support is
+ * compiled in to just save the unknown chunks, so simply skip this
+ * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then
+ * the app has erroneously asked for unknown chunk saving when there
+ * is no support.
+ */
+ if (keep > PNG_HANDLE_CHUNK_NEVER)
+ png_app_error(png_ptr, "no unknown chunk support available");
+
+ png_crc_finish(png_ptr, length);
+ }
+# endif
+
+# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+ /* Now store the chunk in the chunk list if appropriate, and if the limits
+ * permit it.
+ */
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
+ PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
+ {
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ switch (png_ptr->user_chunk_cache_max)
+ {
+ case 2:
+ png_ptr->user_chunk_cache_max = 1;
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
+ /* FALL THROUGH */
+ case 1:
+ /* NOTE: prior to 1.6.0 this case resulted in an unknown critical
+ * chunk being skipped, now there will be a hard error below.
+ */
+ break;
+
+ default: /* not at limit */
+ --(png_ptr->user_chunk_cache_max);
+ /* FALL THROUGH */
+ case 0: /* no limit */
+# endif /* USER_LIMITS */
+ /* Here when the limit isn't reached or when limits are compiled
+ * out; store the chunk.
+ */
+ png_set_unknown_chunks(png_ptr, info_ptr,
+ &png_ptr->unknown_chunk, 1);
+ handled = 1;
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ break;
+ }
+# endif
+ }
+# else /* no store support: the chunk must be handled by the user callback */
+ PNG_UNUSED(info_ptr)
+# endif
+
+ /* Regardless of the error handling below the cached data (if any) can be
+ * freed now. Notice that the data is not freed if there is a png_error, but
+ * it will be freed by destroy_read_struct.
+ */
+ if (png_ptr->unknown_chunk.data != NULL)
+ png_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
+
+#else /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */
+ /* There is no support to read an unknown chunk, so just skip it. */
+ png_crc_finish(png_ptr, length);
+ PNG_UNUSED(info_ptr)
+ PNG_UNUSED(keep)
+#endif /* !READ_UNKNOWN_CHUNKS */
+
+ /* Check for unhandled critical chunks */
+ if (handled == 0 && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
+ png_chunk_error(png_ptr, "unhandled critical chunk");
}
/* This function is called to verify that a chunk name is valid.
@@ -2682,267 +2996,527 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
* 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.
+/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is:
+ *
+ * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
*/
void /* PRIVATE */
-png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name)
{
+ int i;
+
+ png_debug(1, "in png_check_chunk_name");
+
+ for (i=1; i<=4; ++i)
+ {
+ int c = chunk_name & 0xff;
+
+ if (c < 65 || c > 122 || (c > 90 && c < 97))
+ png_chunk_error(png_ptr, "invalid chunk type");
+
+ chunk_name >>= 8;
+ }
+}
+
+/* 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 'display' value; if 'display' is true then the whole row
+ * (dp) is filled from the start by replicating the available pixels. If
+ * 'display' is false only those pixels present in the pass are filled in.
+ */
+void /* PRIVATE */
+png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
+{
+ unsigned int pixel_depth = png_ptr->transformed_pixel_depth;
+ png_const_bytep sp = png_ptr->row_buf + 1;
+ png_alloc_size_t row_width = png_ptr->width;
+ unsigned int pass = png_ptr->pass;
+ png_bytep end_ptr = 0;
+ png_byte end_byte = 0;
+ unsigned int end_mask;
+
png_debug(1, "in png_combine_row");
- /* Added in 1.5.4: the row_info should match the information returned by any
- * call to png_read_update_info at this point. Do not continue if we got
+ /* Added in 1.5.6: it should not be possible to enter this routine until at
+ * least one row has been read from the PNG data and transformed.
+ */
+ if (pixel_depth == 0)
+ png_error(png_ptr, "internal row logic error");
+
+ /* Added in 1.5.4: the pixel depth should match the information returned by
+ * any call to png_read_update_info at this point. Do not continue if we got
* this wrong.
*/
if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes !=
- PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width))
+ PNG_ROWBYTES(pixel_depth, row_width))
png_error(png_ptr, "internal row size calculation error");
- if (mask == 0xff)
+ /* Don't expect this to ever happen: */
+ if (row_width == 0)
+ png_error(png_ptr, "internal row width error");
+
+ /* Preserve the last byte in cases where only part of it will be overwritten,
+ * the multiply below may overflow, we don't care because ANSI-C guarantees
+ * we get the low bits.
+ */
+ end_mask = (pixel_depth * row_width) & 7;
+ if (end_mask != 0)
{
- png_memcpy(row, png_ptr->row_buf + 1,
- PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
+ /* end_ptr == NULL is a flag to say do nothing */
+ end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1;
+ end_byte = *end_ptr;
+# ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ /* little-endian byte */
+ end_mask = 0xff << end_mask;
+
+ else /* big-endian byte */
+# endif
+ end_mask = 0xff >> end_mask;
+ /* end_mask is now the bits to *keep* from the destination row */
}
- else
+ /* For non-interlaced images this reduces to a memcpy(). A memcpy()
+ * will also happen if interlacing isn't supported or if the application
+ * does not call png_set_interlace_handling(). In the latter cases the
+ * caller just gets a sequence of the unexpanded rows from each interlace
+ * pass.
+ */
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0 &&
+ pass < 6 && (display == 0 ||
+ /* The following copies everything for 'display' on passes 0, 2 and 4. */
+ (display == 1 && (pass & 1) != 0)))
{
- switch (png_ptr->row_info.pixel_depth)
+ /* Narrow images may have no bits in a pass; the caller should handle
+ * this, but this test is cheap:
+ */
+ if (row_width <= PNG_PASS_START_COL(pass))
+ return;
+
+ if (pixel_depth < 8)
{
- 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;
+ /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit
+ * into 32 bits, then a single loop over the bytes using the four byte
+ * values in the 32-bit mask can be used. For the 'display' option the
+ * expanded mask may also not require any masking within a byte. To
+ * make this work the PACKSWAP option must be taken into account - it
+ * simply requires the pixels to be reversed in each byte.
+ *
+ * The 'regular' case requires a mask for each of the first 6 passes,
+ * the 'display' case does a copy for the even passes in the range
+ * 0..6. This has already been handled in the test above.
+ *
+ * The masks are arranged as four bytes with the first byte to use in
+ * the lowest bits (little-endian) regardless of the order (PACKSWAP or
+ * not) of the pixels in each byte.
+ *
+ * NOTE: the whole of this logic depends on the caller of this function
+ * only calling it on rows appropriate to the pass. This function only
+ * understands the 'x' logic; the 'y' logic is handled by the caller.
+ *
+ * The following defines allow generation of compile time constant bit
+ * masks for each pixel depth and each possibility of swapped or not
+ * swapped bytes. Pass 'p' is in the range 0..6; 'x', a pixel index,
+ * is in the range 0..7; and the result is 1 if the pixel is to be
+ * copied in the pass, 0 if not. 'S' is for the sparkle method, 'B'
+ * for the block method.
+ *
+ * With some compilers a compile time expression of the general form:
+ *
+ * (shift >= 32) ? (a >> (shift-32)) : (b >> shift)
+ *
+ * Produces warnings with values of 'shift' in the range 33 to 63
+ * because the right hand side of the ?: expression is evaluated by
+ * the compiler even though it isn't used. Microsoft Visual C (various
+ * versions) and the Intel C compiler are known to do this. To avoid
+ * this the following macros are used in 1.5.6. This is a temporary
+ * solution to avoid destabilizing the code during the release process.
+ */
+# if PNG_USE_COMPILE_TIME_MASKS
+# define PNG_LSR(x,s) ((x)>>((s) & 0x1f))
+# define PNG_LSL(x,s) ((x)<<((s) & 0x1f))
+# else
+# define PNG_LSR(x,s) ((x)>>(s))
+# define PNG_LSL(x,s) ((x)<<(s))
+# endif
+# define S_COPY(p,x) (((p)<4 ? PNG_LSR(0x80088822,(3-(p))*8+(7-(x))) :\
+ PNG_LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1)
+# define B_COPY(p,x) (((p)<4 ? PNG_LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\
+ PNG_LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1)
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP)
- {
- s_start = 0;
- s_end = 7;
- s_inc = 1;
- }
+ /* Return a mask for pass 'p' pixel 'x' at depth 'd'. The mask is
+ * little endian - the first pixel is at bit 0 - however the extra
+ * parameter 's' can be set to cause the mask position to be swapped
+ * within each byte, to match the PNG format. This is done by XOR of
+ * the shift with 7, 6 or 4 for bit depths 1, 2 and 4.
+ */
+# define PIXEL_MASK(p,x,d,s) \
+ (PNG_LSL(((PNG_LSL(1U,(d)))-1),(((x)*(d))^((s)?8-(d):0))))
+
+ /* Hence generate the appropriate 'block' or 'sparkle' pixel copy mask.
+ */
+# define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0)
+# define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0)
+
+ /* Combine 8 of these to get the full mask. For the 1-bpp and 2-bpp
+ * cases the result needs replicating, for the 4-bpp case the above
+ * generates a full 32 bits.
+ */
+# define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1)))
+
+# define S_MASK(p,d,s) MASK_EXPAND(S_MASKx(p,0,d,s) + S_MASKx(p,1,d,s) +\
+ S_MASKx(p,2,d,s) + S_MASKx(p,3,d,s) + S_MASKx(p,4,d,s) +\
+ S_MASKx(p,5,d,s) + S_MASKx(p,6,d,s) + S_MASKx(p,7,d,s), d)
+
+# define B_MASK(p,d,s) MASK_EXPAND(B_MASKx(p,0,d,s) + B_MASKx(p,1,d,s) +\
+ B_MASKx(p,2,d,s) + B_MASKx(p,3,d,s) + B_MASKx(p,4,d,s) +\
+ B_MASKx(p,5,d,s) + B_MASKx(p,6,d,s) + B_MASKx(p,7,d,s), d)
+
+#if PNG_USE_COMPILE_TIME_MASKS
+ /* Utility macros to construct all the masks for a depth/swap
+ * combination. The 's' parameter says whether the format is PNG
+ * (big endian bytes) or not. Only the three odd-numbered passes are
+ * required for the display/block algorithm.
+ */
+# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\
+ S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) }
+
+# define B_MASKS(d,s) { B_MASK(1,d,s), B_MASK(3,d,s), B_MASK(5,d,s) }
+
+# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2))
+
+ /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and
+ * then pass:
+ */
+ static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
+ {
+ /* Little-endian byte masks for PACKSWAP */
+ { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) },
+ /* Normal (big-endian byte) masks - PNG format */
+ { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) }
+ };
+
+ /* display_mask has only three entries for the odd passes, so index by
+ * pass>>1.
+ */
+ static PNG_CONST png_uint_32 display_mask[2][3][3] =
+ {
+ /* Little-endian byte masks for PACKSWAP */
+ { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) },
+ /* Normal (big-endian byte) masks - PNG format */
+ { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) }
+ };
+
+# define MASK(pass,depth,display,png)\
+ ((display)?display_mask[png][DEPTH_INDEX(depth)][pass>>1]:\
+ row_mask[png][DEPTH_INDEX(depth)][pass])
+
+#else /* !PNG_USE_COMPILE_TIME_MASKS */
+ /* This is the runtime alternative: it seems unlikely that this will
+ * ever be either smaller or faster than the compile time approach.
+ */
+# define MASK(pass,depth,display,png)\
+ ((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png))
+#endif /* !USE_COMPILE_TIME_MASKS */
+
+ /* Use the appropriate mask to copy the required bits. In some cases
+ * the byte mask will be 0 or 0xff; optimize these cases. row_width is
+ * the number of pixels, but the code copies bytes, so it is necessary
+ * to special case the end.
+ */
+ png_uint_32 pixels_per_byte = 8 / pixel_depth;
+ png_uint_32 mask;
+
+# ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ mask = MASK(pass, pixel_depth, display, 0);
else
-#endif
- {
- s_start = 7;
- s_end = 0;
- s_inc = -1;
- }
+# endif
+ mask = MASK(pass, pixel_depth, display, 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:
+ for (;;)
{
- 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;
+ png_uint_32 m;
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP)
+ /* It doesn't matter in the following if png_uint_32 has more than
+ * 32 bits because the high bits always match those in m<<24; it is,
+ * however, essential to use OR here, not +, because of this.
+ */
+ m = mask;
+ mask = (m >> 8) | (m << 24); /* rotate right to good compilers */
+ m &= 0xff;
+
+ if (m != 0) /* something to copy */
{
- 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++;
- }
-
+ if (m != 0xff)
+ *dp = (png_byte)((*dp & ~m) | (*sp & m));
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;
+ *dp = *sp;
}
- else
-#endif
- {
- s_start = 4;
- s_end = 0;
- s_inc = -4;
- }
- shift = s_start;
+ /* NOTE: this may overwrite the last byte with garbage if the image
+ * is not an exact number of bytes wide; libpng has always done
+ * this.
+ */
+ if (row_width <= pixels_per_byte)
+ break; /* May need to restore part of the last byte */
- 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;
+ row_width -= pixels_per_byte;
+ ++dp;
+ ++sp;
}
}
+
+ else /* pixel_depth >= 8 */
+ {
+ unsigned int bytes_to_copy, bytes_to_jump;
+
+ /* Validate the depth - it must be a multiple of 8 */
+ if (pixel_depth & 7)
+ png_error(png_ptr, "invalid user transform pixel depth");
+
+ pixel_depth >>= 3; /* now in bytes */
+ row_width *= pixel_depth;
+
+ /* Regardless of pass number the Adam 7 interlace always results in a
+ * fixed number of pixels to copy then to skip. There may be a
+ * different number of pixels to skip at the start though.
+ */
+ {
+ unsigned int offset = PNG_PASS_START_COL(pass) * pixel_depth;
+
+ row_width -= offset;
+ dp += offset;
+ sp += offset;
+ }
+
+ /* Work out the bytes to copy. */
+ if (display != 0)
+ {
+ /* When doing the 'block' algorithm the pixel in the pass gets
+ * replicated to adjacent pixels. This is why the even (0,2,4,6)
+ * passes are skipped above - the entire expanded row is copied.
+ */
+ bytes_to_copy = (1<<((6-pass)>>1)) * pixel_depth;
+
+ /* But don't allow this number to exceed the actual row width. */
+ if (bytes_to_copy > row_width)
+ bytes_to_copy = (unsigned int)/*SAFE*/row_width;
+ }
+
+ else /* normal row; Adam7 only ever gives us one pixel to copy. */
+ bytes_to_copy = pixel_depth;
+
+ /* In Adam7 there is a constant offset between where the pixels go. */
+ bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth;
+
+ /* And simply copy these bytes. Some optimization is possible here,
+ * depending on the value of 'bytes_to_copy'. Special case the low
+ * byte counts, which we know to be frequent.
+ *
+ * Notice that these cases all 'return' rather than 'break' - this
+ * avoids an unnecessary test on whether to restore the last byte
+ * below.
+ */
+ switch (bytes_to_copy)
+ {
+ case 1:
+ for (;;)
+ {
+ *dp = *sp;
+
+ if (row_width <= bytes_to_jump)
+ return;
+
+ dp += bytes_to_jump;
+ sp += bytes_to_jump;
+ row_width -= bytes_to_jump;
+ }
+
+ case 2:
+ /* There is a possibility of a partial copy at the end here; this
+ * slows the code down somewhat.
+ */
+ do
+ {
+ dp[0] = sp[0], dp[1] = sp[1];
+
+ if (row_width <= bytes_to_jump)
+ return;
+
+ sp += bytes_to_jump;
+ dp += bytes_to_jump;
+ row_width -= bytes_to_jump;
+ }
+ while (row_width > 1);
+
+ /* And there can only be one byte left at this point: */
+ *dp = *sp;
+ return;
+
+ case 3:
+ /* This can only be the RGB case, so each copy is exactly one
+ * pixel and it is not necessary to check for a partial copy.
+ */
+ for (;;)
+ {
+ dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2];
+
+ if (row_width <= bytes_to_jump)
+ return;
+
+ sp += bytes_to_jump;
+ dp += bytes_to_jump;
+ row_width -= bytes_to_jump;
+ }
+
+ default:
+#if PNG_ALIGN_TYPE != PNG_ALIGN_NONE
+ /* Check for double byte alignment and, if possible, use a
+ * 16-bit copy. Don't attempt this for narrow images - ones that
+ * are less than an interlace panel wide. Don't attempt it for
+ * wide bytes_to_copy either - use the memcpy there.
+ */
+ if (bytes_to_copy < 16 /*else use memcpy*/ &&
+ png_isaligned(dp, png_uint_16) &&
+ png_isaligned(sp, png_uint_16) &&
+ bytes_to_copy % (sizeof (png_uint_16)) == 0 &&
+ bytes_to_jump % (sizeof (png_uint_16)) == 0)
+ {
+ /* Everything is aligned for png_uint_16 copies, but try for
+ * png_uint_32 first.
+ */
+ if (png_isaligned(dp, png_uint_32) != 0 &&
+ png_isaligned(sp, png_uint_32) != 0 &&
+ bytes_to_copy % (sizeof (png_uint_32)) == 0 &&
+ bytes_to_jump % (sizeof (png_uint_32)) == 0)
+ {
+ png_uint_32p dp32 = png_aligncast(png_uint_32p,dp);
+ png_const_uint_32p sp32 = png_aligncastconst(
+ png_const_uint_32p, sp);
+ size_t skip = (bytes_to_jump-bytes_to_copy) /
+ (sizeof (png_uint_32));
+
+ do
+ {
+ size_t c = bytes_to_copy;
+ do
+ {
+ *dp32++ = *sp32++;
+ c -= (sizeof (png_uint_32));
+ }
+ while (c > 0);
+
+ if (row_width <= bytes_to_jump)
+ return;
+
+ dp32 += skip;
+ sp32 += skip;
+ row_width -= bytes_to_jump;
+ }
+ while (bytes_to_copy <= row_width);
+
+ /* Get to here when the row_width truncates the final copy.
+ * There will be 1-3 bytes left to copy, so don't try the
+ * 16-bit loop below.
+ */
+ dp = (png_bytep)dp32;
+ sp = (png_const_bytep)sp32;
+ do
+ *dp++ = *sp++;
+ while (--row_width > 0);
+ return;
+ }
+
+ /* Else do it in 16-bit quantities, but only if the size is
+ * not too large.
+ */
+ else
+ {
+ png_uint_16p dp16 = png_aligncast(png_uint_16p, dp);
+ png_const_uint_16p sp16 = png_aligncastconst(
+ png_const_uint_16p, sp);
+ size_t skip = (bytes_to_jump-bytes_to_copy) /
+ (sizeof (png_uint_16));
+
+ do
+ {
+ size_t c = bytes_to_copy;
+ do
+ {
+ *dp16++ = *sp16++;
+ c -= (sizeof (png_uint_16));
+ }
+ while (c > 0);
+
+ if (row_width <= bytes_to_jump)
+ return;
+
+ dp16 += skip;
+ sp16 += skip;
+ row_width -= bytes_to_jump;
+ }
+ while (bytes_to_copy <= row_width);
+
+ /* End of row - 1 byte left, bytes_to_copy > row_width: */
+ dp = (png_bytep)dp16;
+ sp = (png_const_bytep)sp16;
+ do
+ *dp++ = *sp++;
+ while (--row_width > 0);
+ return;
+ }
+ }
+#endif /* ALIGN_TYPE code */
+
+ /* The true default - use a memcpy: */
+ for (;;)
+ {
+ memcpy(dp, sp, bytes_to_copy);
+
+ if (row_width <= bytes_to_jump)
+ return;
+
+ sp += bytes_to_jump;
+ dp += bytes_to_jump;
+ row_width -= bytes_to_jump;
+ if (bytes_to_copy > row_width)
+ bytes_to_copy = (unsigned int)/*SAFE*/row_width;
+ }
+ }
+
+ /* NOT REACHED*/
+ } /* pixel_depth >= 8 */
+
+ /* Here if pixel_depth < 8 to check 'end_ptr' below. */
}
+ else
+#endif /* READ_INTERLACING */
+
+ /* If here then the switch above wasn't used so just memcpy the whole row
+ * from the temporary row buffer (notice that this overwrites the end of the
+ * destination row if it is a partial byte.)
+ */
+ memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width));
+
+ /* Restore the overwritten bits from the last byte if necessary. */
+ if (end_ptr != NULL)
+ *end_ptr = (png_byte)((end_byte & end_mask) | (*end_ptr & ~end_mask));
}
#ifdef PNG_READ_INTERLACING_SUPPORTED
void /* PRIVATE */
-png_do_read_interlace(png_structp png_ptr)
+png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
+ png_uint_32 transformations /* Because these may affect the byte layout */)
{
- 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};
+ static 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)
@@ -2965,7 +3539,7 @@ png_do_read_interlace(png_structp png_ptr)
int j;
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)((row_info->width + 7) & 0x07);
dshift = (int)((final_width + 7) & 0x07);
@@ -2989,8 +3563,9 @@ png_do_read_interlace(png_structp png_ptr)
v = (png_byte)((*sp >> sshift) & 0x01);
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0x7f7f >> (7 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3024,7 +3599,7 @@ png_do_read_interlace(png_structp png_ptr)
png_uint_32 i;
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)(((row_info->width + 3) & 0x03) << 1);
dshift = (int)(((final_width + 3) & 0x03) << 1);
@@ -3051,8 +3626,9 @@ png_do_read_interlace(png_structp png_ptr)
v = (png_byte)((*sp >> sshift) & 0x03);
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0x3f3f >> (6 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3086,7 +3662,7 @@ png_do_read_interlace(png_structp png_ptr)
int jstop = png_pass_inc[pass];
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)(((row_info->width + 1) & 0x01) << 2);
dshift = (int)(((final_width + 1) & 0x01) << 2);
@@ -3107,13 +3683,14 @@ png_do_read_interlace(png_structp png_ptr)
for (i = 0; i < row_info->width; i++)
{
- png_byte v = (png_byte)((*sp >> sshift) & 0xf);
+ png_byte v = (png_byte)((*sp >> sshift) & 0x0f);
int j;
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0xf0f >> (4 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3136,6 +3713,7 @@ png_do_read_interlace(png_structp png_ptr)
}
break;
}
+
default:
{
png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
@@ -3150,14 +3728,14 @@ png_do_read_interlace(png_structp png_ptr)
for (i = 0; i < row_info->width; i++)
{
- png_byte v[8];
+ png_byte v[8]; /* SAFE; pixel_depth does not exceed 64 */
int j;
- png_memcpy(v, sp, pixel_bytes);
+ memcpy(v, sp, pixel_bytes);
for (j = 0; j < jstop; j++)
{
- png_memcpy(dp, v, pixel_bytes);
+ memcpy(dp, v, pixel_bytes);
dp -= pixel_bytes;
}
@@ -3166,6 +3744,7 @@ png_do_read_interlace(png_structp png_ptr)
break;
}
}
+
row_info->width = final_width;
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
}
@@ -3173,167 +3752,427 @@ png_do_read_interlace(png_structp png_ptr)
PNG_UNUSED(transformations) /* Silence compiler warning */
#endif
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
+#endif /* READ_INTERLACING */
+
+static void
+png_read_filter_row_sub(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ 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_UNUSED(prev_row)
+
+ for (i = bpp; i < istop; i++)
+ {
+ *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
+ rp++;
+ }
+}
+
+static void
+png_read_filter_row_up(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ 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++;
+ }
+}
+
+static void
+png_read_filter_row_avg(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_size_t i;
+ png_bytep rp = row;
+ png_const_bytep pp = 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++) / 2 )) & 0xff);
+
+ rp++;
+ }
+
+ for (i = 0; i < istop; i++)
+ {
+ *rp = (png_byte)(((int)(*rp) +
+ (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
+
+ rp++;
+ }
+}
+
+static void
+png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_bytep rp_end = row + row_info->rowbytes;
+ int a, c;
+
+ /* First pixel/byte */
+ c = *prev_row++;
+ a = *row + c;
+ *row++ = (png_byte)a;
+
+ /* Remainder */
+ while (row < rp_end)
+ {
+ int b, pa, pb, pc, p;
+
+ a &= 0xff; /* From previous iteration or start */
+ b = *prev_row++;
+
+ 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
+
+ /* Find the best predictor, the least of pa, pb, pc favoring the earlier
+ * ones in the case of a tie.
+ */
+ if (pb < pa) pa = pb, a = b;
+ if (pc < pa) a = c;
+
+ /* Calculate the current pixel in a, and move the previous row pixel to c
+ * for the next time round the loop
+ */
+ c = b;
+ a += *row;
+ *row++ = (png_byte)a;
+ }
+}
+
+static void
+png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ int bpp = (row_info->pixel_depth + 7) >> 3;
+ png_bytep rp_end = row + bpp;
+
+ /* Process the first pixel in the row completely (this is the same as 'up'
+ * because there is only one candidate predictor for the first row).
+ */
+ while (row < rp_end)
+ {
+ int a = *row + *prev_row++;
+ *row++ = (png_byte)a;
+ }
+
+ /* Remainder */
+ rp_end += row_info->rowbytes - bpp;
+
+ while (row < rp_end)
+ {
+ int a, b, c, pa, pb, pc, p;
+
+ c = *(prev_row - bpp);
+ a = *(row - bpp);
+ b = *prev_row++;
+
+ 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 (pb < pa) pa = pb, a = b;
+ if (pc < pa) a = c;
+
+ a += *row;
+ *row++ = (png_byte)a;
+ }
+}
+
+static void
+png_init_filter_functions(png_structrp pp)
+ /* This function is called once for every PNG image (except for PNG images
+ * that only use PNG_FILTER_VALUE_NONE for all rows) to set the
+ * implementations required to reverse the filtering of PNG rows. Reversing
+ * the filter is the first transformation performed on the row data. It is
+ * performed in place, therefore an implementation can be selected based on
+ * the image pixel format. If the implementation depends on image width then
+ * take care to ensure that it works correctly if the image is interlaced -
+ * interlacing causes the actual row width to vary.
+ */
+{
+ unsigned int bpp = (pp->pixel_depth + 7) >> 3;
+
+ pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub;
+ pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up;
+ pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg;
+ if (bpp == 1)
+ pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+ png_read_filter_row_paeth_1byte_pixel;
+ else
+ pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+ png_read_filter_row_paeth_multibyte_pixel;
+
+#ifdef PNG_FILTER_OPTIMIZATIONS
+ /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to
+ * call to install hardware optimizations for the above functions; simply
+ * replace whatever elements of the pp->read_filter[] array with a hardware
+ * specific (or, for that matter, generic) optimization.
+ *
+ * To see an example of this examine what configure.ac does when
+ * --enable-arm-neon is specified on the command line.
+ */
+ PNG_FILTER_OPTIMIZATIONS(pp, bpp);
+#endif
+}
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_read_filter_row(png_structrp pp, 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)
+ /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define
+ * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic
+ * implementations. See png_init_filter_functions above.
+ */
+ if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST)
{
- case PNG_FILTER_VALUE_NONE:
- break;
+ if (pp->read_filter[0] == NULL)
+ png_init_filter_functions(pp);
- 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;
+ pp->read_filter[filter-1](row_info, row, prev_row);
}
}
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
void /* PRIVATE */
-png_read_finish_row(png_structp png_ptr)
+png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
+ png_alloc_size_t avail_out)
+{
+ /* Loop reading IDATs and decompressing the result into output[avail_out] */
+ png_ptr->zstream.next_out = output;
+ png_ptr->zstream.avail_out = 0; /* safety: set below */
+
+ if (output == NULL)
+ avail_out = 0;
+
+ do
+ {
+ int ret;
+ png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
+
+ if (png_ptr->zstream.avail_in == 0)
+ {
+ uInt avail_in;
+ png_bytep buffer;
+
+ while (png_ptr->idat_size == 0)
+ {
+ png_crc_finish(png_ptr, 0);
+
+ png_ptr->idat_size = png_read_chunk_header(png_ptr);
+ /* This is an error even in the 'check' case because the code just
+ * consumed a non-IDAT header.
+ */
+ if (png_ptr->chunk_name != png_IDAT)
+ png_error(png_ptr, "Not enough image data");
+ }
+
+ avail_in = png_ptr->IDAT_read_size;
+
+ if (avail_in > png_ptr->idat_size)
+ avail_in = (uInt)png_ptr->idat_size;
+
+ /* A PNG with a gradually increasing IDAT size will defeat this attempt
+ * to minimize memory usage by causing lots of re-allocs, but
+ * realistically doing IDAT_read_size re-allocs is not likely to be a
+ * big problem.
+ */
+ buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/);
+
+ png_crc_read(png_ptr, buffer, avail_in);
+ png_ptr->idat_size -= avail_in;
+
+ png_ptr->zstream.next_in = buffer;
+ png_ptr->zstream.avail_in = avail_in;
+ }
+
+ /* And set up the output side. */
+ if (output != NULL) /* standard read */
+ {
+ uInt out = ZLIB_IO_MAX;
+
+ if (out > avail_out)
+ out = (uInt)avail_out;
+
+ avail_out -= out;
+ png_ptr->zstream.avail_out = out;
+ }
+
+ else /* after last row, checking for end */
+ {
+ png_ptr->zstream.next_out = tmpbuf;
+ png_ptr->zstream.avail_out = (sizeof tmpbuf);
+ }
+
+ /* Use NO_FLUSH; this gives zlib the maximum opportunity to optimize the
+ * process. If the LZ stream is truncated the sequential reader will
+ * terminally damage the stream, above, by reading the chunk header of the
+ * following chunk (it then exits with png_error).
+ *
+ * TODO: deal more elegantly with truncated IDAT lists.
+ */
+ ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
+
+ /* Take the unconsumed output back. */
+ if (output != NULL)
+ avail_out += png_ptr->zstream.avail_out;
+
+ else /* avail_out counts the extra bytes */
+ avail_out += (sizeof tmpbuf) - png_ptr->zstream.avail_out;
+
+ png_ptr->zstream.avail_out = 0;
+
+ if (ret == Z_STREAM_END)
+ {
+ /* Do this for safety; we won't read any more into this row. */
+ png_ptr->zstream.next_out = NULL;
+
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+
+ if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
+ png_chunk_benign_error(png_ptr, "Extra compressed data");
+ break;
+ }
+
+ if (ret != Z_OK)
+ {
+ png_zstream_error(png_ptr, ret);
+
+ if (output != NULL)
+ png_chunk_error(png_ptr, png_ptr->zstream.msg);
+
+ else /* checking */
+ {
+ png_chunk_benign_error(png_ptr, png_ptr->zstream.msg);
+ return;
+ }
+ }
+ } while (avail_out > 0);
+
+ if (avail_out > 0)
+ {
+ /* The stream ended before the image; this is the same as too few IDATs so
+ * should be handled the same way.
+ */
+ if (output != NULL)
+ png_error(png_ptr, "Not enough image data");
+
+ else /* the deflate stream contained extra data */
+ png_chunk_benign_error(png_ptr, "Too much image data");
+ }
+}
+
+void /* PRIVATE */
+png_read_finish_IDAT(png_structrp png_ptr)
+{
+ /* We don't need any more data and the stream should have ended, however the
+ * LZ end code may actually not have been processed. In this case we must
+ * read it otherwise stray unread IDAT data or, more likely, an IDAT chunk
+ * may still remain to be consumed.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
+ {
+ /* The NULL causes png_read_IDAT_data to swallow any remaining bytes in
+ * the compressed stream, but the stream may be damaged too, so even after
+ * this call we may need to terminate the zstream ownership.
+ */
+ png_read_IDAT_data(png_ptr, NULL, 0);
+ png_ptr->zstream.next_out = NULL; /* safety */
+
+ /* Now clear everything out for safety; the following may not have been
+ * done.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
+ {
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+ }
+ }
+
+ /* If the zstream has not been released do it now *and* terminate the reading
+ * of the final IDAT chunk.
+ */
+ if (png_ptr->zowner == png_IDAT)
+ {
+ /* Always do this; the pointers otherwise point into the read buffer. */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+
+ /* Now we no longer own the zstream. */
+ png_ptr->zowner = 0;
+
+ /* The slightly weird semantics of the sequential IDAT reading is that we
+ * are always in or at the end of an IDAT chunk, so we always need to do a
+ * crc_finish here. If idat_size is non-zero we also need to read the
+ * spurious bytes at the end of the chunk now.
+ */
+ (void)png_crc_finish(png_ptr, png_ptr->idat_size);
+ }
+}
+
+void /* PRIVATE */
+png_read_finish_row(png_structrp 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte 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 */
+ static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
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)
+ if (png_ptr->interlaced != 0)
{
png_ptr->row_number = 0;
- png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+ /* TO DO: don't do this if prev_row isn't needed (requires
+ * read-ahead of the next row's filter byte.
+ */
+ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
do
{
@@ -3347,7 +4186,7 @@ png_read_finish_row(png_structp png_ptr)
png_pass_start[png_ptr->pass]) /
png_pass_inc[png_ptr->pass];
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
{
png_ptr->num_rows = (png_ptr->height +
png_pass_yinc[png_ptr->pass] - 1 -
@@ -3363,108 +4202,40 @@ png_read_finish_row(png_structp png_ptr)
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;
+ /* Here after at the end of the last row of the last pass. */
+ png_read_finish_IDAT(png_ptr);
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
void /* PRIVATE */
-png_read_start_row(png_structp png_ptr)
+png_read_start_row(png_structrp 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte 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
+ static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
int max_pixel_depth;
png_size_t row_bytes;
png_debug(1, "in png_read_start_row");
- png_ptr->zstream.avail_in = 0;
+
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
png_init_read_transformations(png_ptr);
#endif
-#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
png_pass_ystart[0]) / png_pass_yinc[0];
@@ -3478,7 +4249,6 @@ png_read_start_row(png_structp png_ptr)
}
else
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
{
png_ptr->num_rows = png_ptr->height;
png_ptr->iwidth = png_ptr->width;
@@ -3486,17 +4256,27 @@ png_read_start_row(png_structp png_ptr)
max_pixel_depth = png_ptr->pixel_depth;
+ /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpler set of
+ * calculations to calculate the final pixel depth, then
+ * png_do_read_transforms actually does the transforms. This means that the
+ * code which effectively calculates this value is actually repeated in three
+ * separate places. They must all match. Innocent changes to the order of
+ * transformations can and will break libpng in a way that causes memory
+ * overwrites.
+ *
+ * TODO: fix this.
+ */
#ifdef PNG_READ_PACK_SUPPORTED
- if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
+ if ((png_ptr->transformations & PNG_PACK) != 0 && png_ptr->bit_depth < 8)
max_pixel_depth = 8;
#endif
#ifdef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND)
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
max_pixel_depth = 32;
else
@@ -3508,13 +4288,13 @@ png_read_start_row(png_structp png_ptr)
if (max_pixel_depth < 8)
max_pixel_depth = 8;
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
max_pixel_depth *= 2;
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
{
max_pixel_depth *= 4;
max_pixel_depth /= 3;
@@ -3524,13 +4304,13 @@ png_read_start_row(png_structp png_ptr)
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND_16)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
{
# ifdef PNG_READ_EXPAND_SUPPORTED
/* In fact it is an error if it isn't supported, but checking is
* the safe way.
*/
- if (png_ptr->transformations & PNG_EXPAND)
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
{
if (png_ptr->bit_depth < 16)
max_pixel_depth *= 2;
@@ -3542,12 +4322,9 @@ png_read_start_row(png_structp png_ptr)
#endif
#ifdef PNG_READ_FILLER_SUPPORTED
- if (png_ptr->transformations & (PNG_FILLER))
+ if ((png_ptr->transformations & (PNG_FILLER)) != 0)
{
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
- max_pixel_depth = 32;
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+ if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
{
if (max_pixel_depth <= 8)
max_pixel_depth = 16;
@@ -3556,7 +4333,8 @@ png_read_start_row(png_structp png_ptr)
max_pixel_depth = 32;
}
- else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
+ png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
if (max_pixel_depth <= 32)
max_pixel_depth = 32;
@@ -3568,14 +4346,15 @@ png_read_start_row(png_structp png_ptr)
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
{
if (
#ifdef PNG_READ_EXPAND_SUPPORTED
- (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
+ (png_ptr->num_trans != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) != 0) ||
#endif
#ifdef PNG_READ_FILLER_SUPPORTED
- (png_ptr->transformations & (PNG_FILLER)) ||
+ (png_ptr->transformations & (PNG_FILLER)) != 0 ||
#endif
png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
@@ -3608,16 +4387,22 @@ png_read_start_row(png_structp png_ptr)
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
{
- int user_pixel_depth = png_ptr->user_transform_depth*
+ 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;
+ max_pixel_depth = user_pixel_depth;
}
#endif
+ /* This value is stored in png_struct and double checked in the row read
+ * code.
+ */
+ png_ptr->maximum_pixel_depth = (png_byte)max_pixel_depth;
+ png_ptr->transformed_pixel_depth = 0; /* calculated on demand */
+
/* Align the width on the next larger 8 pixels. Mainly used
* for interlacing
*/
@@ -3636,28 +4421,39 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
if (row_bytes + 48 > png_ptr->old_big_row_buf_size)
{
png_free(png_ptr, png_ptr->big_row_buf);
+ png_free(png_ptr, png_ptr->big_prev_row);
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
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->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48);
- png_ptr->old_big_row_buf_size = row_bytes + 48;
+ png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, 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.
+ * of padding before and after row_buf; treat prev_row similarly.
+ * NOTE: the alignment is to the start of the pixels, one beyond the start
+ * of the buffer, because of the filter byte. Prior to libpng 1.5.6 this
+ * was incorrect; the filter byte was aligned, which had the exact
+ * opposite effect of that intended.
*/
- png_ptr->row_buf = png_ptr->big_row_buf + 32 -
- (((png_alloc_size_t)png_ptr->big_row_buf + 15) & 0x0F);
+ {
+ png_bytep temp = png_ptr->big_row_buf + 32;
+ int extra = (int)((temp - (png_bytep)0) & 0x0f);
+ png_ptr->row_buf = temp - extra - 1/*filter byte*/;
+
+ temp = png_ptr->big_prev_row + 32;
+ extra = (int)((temp - (png_bytep)0) & 0x0f);
+ png_ptr->prev_row = temp - extra - 1/*filter byte*/;
+ }
- 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;
+ /* Use 31 bytes of padding before and 17 bytes after row_buf. */
+ png_ptr->row_buf = png_ptr->big_row_buf + 31;
+ png_ptr->prev_row = png_ptr->big_prev_row + 31;
#endif
png_ptr->old_big_row_buf_size = row_bytes + 48;
}
@@ -3670,16 +4466,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
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);
+ 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);
@@ -3689,6 +4476,27 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
png_debug1(3, "irowbytes = %lu",
(unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
+ /* The sequential reader needs a buffer for IDAT, but the progressive reader
+ * does not, so free the read buffer now regardless; the sequential reader
+ * reallocates it on demand.
+ */
+ if (png_ptr->read_buffer != 0)
+ {
+ png_bytep buffer = png_ptr->read_buffer;
+
+ png_ptr->read_buffer_size = 0;
+ png_ptr->read_buffer = NULL;
+ png_free(png_ptr, buffer);
+ }
+
+ /* Finally claim the zstream for the inflate of the IDAT data, use the bits
+ * value from the stream (note that this will result in a fatal error if the
+ * IDAT stream has a bogus deflate header window_bits value, but this should
+ * not be happening any longer!)
+ */
+ if (png_inflate_claim(png_ptr, png_IDAT) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+
png_ptr->flags |= PNG_FLAG_ROW_INIT;
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
index 819605f5025..d2c89b2a55f 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
@@ -29,8 +29,8 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -50,51 +50,84 @@
#ifdef PNG_bKGD_SUPPORTED
void PNGAPI
-png_set_bKGD(png_structp png_ptr, png_infop info_ptr,
+png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_color_16p background)
{
png_debug1(1, "in %s storage function", "bKGD");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || background == NULL)
return;
- png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16));
+ info_ptr->background = *background;
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_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp 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_xy xy;
+
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;
- }
+ xy.redx = red_x;
+ xy.redy = red_y;
+ xy.greenx = green_x;
+ xy.greeny = green_y;
+ xy.bluex = blue_x;
+ xy.bluey = blue_y;
+ xy.whitex = white_x;
+ xy.whitey = white_y;
+
+ if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
+ 2/* override with app values*/) != 0)
+ info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
+}
+
+void PNGFAPI
+png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_fixed_point int_red_X, png_fixed_point int_red_Y,
+ png_fixed_point int_red_Z, png_fixed_point int_green_X,
+ png_fixed_point int_green_Y, png_fixed_point int_green_Z,
+ png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
+ png_fixed_point int_blue_Z)
+{
+ png_XYZ XYZ;
+
+ png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ XYZ.red_X = int_red_X;
+ XYZ.red_Y = int_red_Y;
+ XYZ.red_Z = int_red_Z;
+ XYZ.green_X = int_green_X;
+ XYZ.green_Y = int_green_Y;
+ XYZ.green_Z = int_green_Z;
+ XYZ.blue_X = int_blue_X;
+ XYZ.blue_Y = int_blue_Y;
+ XYZ.blue_Z = int_blue_Z;
+
+ if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
+ &XYZ, 2) != 0)
+ info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
+png_set_cHRM(png_const_structrp png_ptr, png_inforp 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)
{
@@ -108,41 +141,44 @@ png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
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 */
+void PNGAPI
+png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
+ double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
+ double blue_X, double blue_Y, double blue_Z)
+{
+ png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
+ png_fixed(png_ptr, red_X, "cHRM Red X"),
+ png_fixed(png_ptr, red_Y, "cHRM Red Y"),
+ png_fixed(png_ptr, red_Z, "cHRM Red Z"),
+ png_fixed(png_ptr, green_X, "cHRM Red X"),
+ png_fixed(png_ptr, green_Y, "cHRM Red Y"),
+ png_fixed(png_ptr, green_Z, "cHRM Red Z"),
+ png_fixed(png_ptr, blue_X, "cHRM Red X"),
+ png_fixed(png_ptr, blue_Y, "cHRM Red Y"),
+ png_fixed(png_ptr, blue_Z, "cHRM Red Z"));
+}
+# endif /* FLOATING_POINT */
+
+#endif /* cHRM */
#ifdef PNG_gAMA_SUPPORTED
void PNGFAPI
-png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
- file_gamma)
+png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_fixed_point file_gamma)
{
png_debug1(1, "in %s storage function", "gAMA");
if (png_ptr == NULL || info_ptr == NULL)
return;
- /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
- * occur. Since the fixed point representation is assymetrical it is
- * possible for 1/gamma to overflow the limit of 21474 and this means the
- * gamma value must be at least 5/100000 and hence at most 20000.0. For
- * safety the limits here are a little narrower. The values are 0.00016 to
- * 6250.0, which are truely ridiculous gammma values (and will produce
- * displays that are all black or all white.)
- */
- if (file_gamma < 16 || file_gamma > 625000000)
- png_warning(png_ptr, "Out of range gamma value ignored");
-
- else
- {
- info_ptr->gamma = file_gamma;
- info_ptr->valid |= PNG_INFO_gAMA;
- }
+ png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
+png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
{
png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
"png_set_gAMA"));
@@ -152,7 +188,8 @@ png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
#ifdef PNG_hIST_SUPPORTED
void PNGAPI
-png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist)
+png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_const_uint_16p hist)
{
int i;
@@ -175,26 +212,26 @@ png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist)
/* 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));
+ info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
+ PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16))));
- if (png_ptr->hist == NULL)
+ if (info_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;
+
+ for (i = 0; i < info_ptr->num_palette; i++)
+ info_ptr->hist[i] = hist[i];
+
+ info_ptr->valid |= PNG_INFO_hIST;
}
#endif
void PNGAPI
-png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
+png_set_IHDR(png_const_structrp png_ptr, png_inforp 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)
@@ -219,32 +256,23 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
info_ptr->channels = 1;
- else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
info_ptr->channels = 3;
else
info_ptr->channels = 1;
- if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
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);
+ 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_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
png_int_32 offset_x, png_int_32 offset_y, int unit_type)
{
png_debug1(1, "in %s storage function", "oFFs");
@@ -261,7 +289,7 @@ png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_pCAL_SUPPORTED
void PNGAPI
-png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
+png_set_pCAL(png_const_structrp png_ptr, png_inforp 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)
{
@@ -270,10 +298,11 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
png_debug1(1, "in %s storage function", "pCAL");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
+ || (nparams > 0 && params == NULL))
return;
- length = png_strlen(purpose) + 1;
+ length = strlen(purpose) + 1;
png_debug1(3, "allocating purpose for info (%lu bytes)",
(unsigned long)length);
@@ -283,12 +312,19 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
if (type < 0 || type > 3)
png_error(png_ptr, "Invalid pCAL equation type");
+ if (nparams < 0 || nparams > 255)
+ png_error(png_ptr, "Invalid pCAL parameter count");
+
/* Validate params[nparams] */
for (i=0; ipcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
+ info_ptr->pcal_purpose = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, length));
if (info_ptr->pcal_purpose == NULL)
{
@@ -296,7 +332,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
return;
}
- png_memcpy(info_ptr->pcal_purpose, purpose, length);
+ memcpy(info_ptr->pcal_purpose, purpose, length);
png_debug(3, "storing X0, X1, type, and nparams in info");
info_ptr->pcal_X0 = X0;
@@ -304,11 +340,12 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
info_ptr->pcal_type = (png_byte)type;
info_ptr->pcal_nparams = (png_byte)nparams;
- length = png_strlen(units) + 1;
+ length = 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);
+ info_ptr->pcal_units = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, length));
if (info_ptr->pcal_units == NULL)
{
@@ -316,10 +353,10 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
return;
}
- png_memcpy(info_ptr->pcal_units, units, length);
+ 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)));
+ info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
+ (png_size_t)((nparams + 1) * (sizeof (png_charp)))));
if (info_ptr->pcal_params == NULL)
{
@@ -327,11 +364,11 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
return;
}
- png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
+ memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp)));
for (i = 0; i < nparams; i++)
{
- length = png_strlen(params[i]) + 1;
+ length = strlen(params[i]) + 1;
png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
(unsigned long)length);
@@ -343,7 +380,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
return;
}
- png_memcpy(info_ptr->pcal_params[i], params[i], length);
+ memcpy(info_ptr->pcal_params[i], params[i], length);
}
info_ptr->valid |= PNG_INFO_pCAL;
@@ -353,7 +390,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sCAL_SUPPORTED
void PNGAPI
-png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
int unit, png_const_charp swidth, png_const_charp sheight)
{
png_size_t lengthw = 0, lengthh = 0;
@@ -369,11 +406,11 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
if (unit != 1 && unit != 2)
png_error(png_ptr, "Invalid sCAL unit");
- if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 ||
+ if (swidth == NULL || (lengthw = 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 ||
+ if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
png_error(png_ptr, "Invalid sCAL height");
@@ -383,7 +420,8 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
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);
+ info_ptr->scal_s_width = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, lengthw));
if (info_ptr->scal_s_width == NULL)
{
@@ -391,13 +429,14 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
return;
}
- png_memcpy(info_ptr->scal_s_width, swidth, lengthw);
+ 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);
+ info_ptr->scal_s_height = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, lengthh));
if (info_ptr->scal_s_height == NULL)
{
@@ -408,7 +447,7 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
return;
}
- png_memcpy(info_ptr->scal_s_height, sheight, lengthh);
+ memcpy(info_ptr->scal_s_height, sheight, lengthh);
info_ptr->valid |= PNG_INFO_sCAL;
info_ptr->free_me |= PNG_FREE_SCAL;
@@ -416,8 +455,8 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
# 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_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
+ double width, double height)
{
png_debug1(1, "in %s storage function", "sCAL");
@@ -434,9 +473,9 @@ png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
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_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
PNG_sCAL_PRECISION);
- png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height,
+ png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
PNG_sCAL_PRECISION);
png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
@@ -446,7 +485,7 @@ png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
# ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
-png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
+png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
png_fixed_point width, png_fixed_point height)
{
png_debug1(1, "in %s storage function", "sCAL");
@@ -464,8 +503,8 @@ png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
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_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);
}
@@ -475,7 +514,7 @@ png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
#ifdef PNG_pHYs_SUPPORTED
void PNGAPI
-png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
+png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
png_debug1(1, "in %s storage function", "pHYs");
@@ -491,7 +530,7 @@ png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
#endif
void PNGAPI
-png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
+png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
png_const_colorp palette, int num_palette)
{
@@ -526,6 +565,9 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
/* 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.
+ *
+ * 1.6.0: the above statement appears to be incorrect; something has to set
+ * the palette inside png_struct on read.
*/
png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
@@ -533,10 +575,11 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
* 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_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
+ PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
- png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
+ if (num_palette > 0)
+ memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
info_ptr->palette = png_ptr->palette;
info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
@@ -547,34 +590,34 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sBIT_SUPPORTED
void PNGAPI
-png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
+png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_color_8p sig_bit)
{
png_debug1(1, "in %s storage function", "sBIT");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
return;
- png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
+ info_ptr->sig_bit = *sig_bit;
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_set_sRGB(png_const_structrp png_ptr, png_inforp 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)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
void PNGAPI
-png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
+png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
int srgb_intent)
{
png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
@@ -582,71 +625,87 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
if (png_ptr == NULL || info_ptr == NULL)
return;
- png_set_sRGB(png_ptr, info_ptr, srgb_intent);
+ if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
+ srgb_intent) != 0)
+ {
+ /* This causes the gAMA and cHRM to be written too */
+ info_ptr->colorspace.flags |=
+ PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+ }
-# ifdef PNG_gAMA_SUPPORTED
- png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
-# 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 */
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
#endif /* sRGB */
#ifdef PNG_iCCP_SUPPORTED
void PNGAPI
-png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
+png_set_iCCP(png_const_structrp png_ptr, png_inforp 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_size_t 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 (compression_type != PNG_COMPRESSION_TYPE_BASE)
+ png_app_error(png_ptr, "Invalid iCCP compression method");
+
+ /* Set the colorspace first because this validates the profile; do not
+ * override previously set app cHRM or gAMA here (because likely as not the
+ * application knows better than libpng what the correct values are.) Pass
+ * the info_ptr color_type field to png_colorspace_set_ICC because in the
+ * write case it has not yet been stored in png_ptr.
+ */
+ {
+ int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
+ proflen, profile, info_ptr->color_type);
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
+
+ /* Don't do any of the copying if the profile was bad, or inconsistent. */
+ if (result == 0)
+ return;
+
+ /* But do write the gAMA and cHRM chunks from the profile. */
+ info_ptr->colorspace.flags |=
+ PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+ }
+
+ length = strlen(name)+1;
+ new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
if (new_iccp_name == NULL)
{
- png_warning(png_ptr, "Insufficient memory to process iCCP chunk");
+ png_benign_error(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);
+ memcpy(new_iccp_name, name, length);
+ new_iccp_profile = png_voidcast(png_bytep,
+ png_malloc_warn(png_ptr, proflen));
if (new_iccp_profile == NULL)
{
- png_free (png_ptr, new_iccp_name);
- png_warning(png_ptr,
+ png_free(png_ptr, new_iccp_name);
+ new_iccp_name = NULL;
+ png_benign_error(png_ptr,
"Insufficient memory to process iCCP profile");
return;
}
- png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);
+ memcpy(new_iccp_profile, profile, 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;
}
@@ -654,74 +713,81 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
#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)
+png_set_text(png_const_structrp png_ptr, png_inforp 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)
+ if (ret != 0)
png_error(png_ptr, "Insufficient memory to store text");
}
int /* PRIVATE */
-png_set_text_2(png_structp png_ptr, png_infop info_ptr,
+png_set_text_2(png_const_structrp png_ptr, png_inforp 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));
+ png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" :
+ (unsigned long)png_ptr->chunk_name);
- if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
+ if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
return(0);
/* Make sure we have enough space in the "text" array in info_struct
- * to hold all of the incoming text_ptr objects.
+ * to hold all of the incoming text_ptr objects. This compare can't overflow
+ * because max_text >= num_text (anyway, subtract of two positive integers
+ * can't overflow in any case.)
*/
- if (info_ptr->num_text + num_text > info_ptr->max_text)
+ if (num_text > info_ptr->max_text - info_ptr->num_text)
{
- if (info_ptr->text != NULL)
+ int old_num_text = info_ptr->num_text;
+ int max_text;
+ png_textp new_text = NULL;
+
+ /* Calculate an appropriate max_text, checking for overflow. */
+ max_text = old_num_text;
+ if (num_text <= INT_MAX - max_text)
{
- png_textp old_text;
- int old_max;
+ max_text += num_text;
- 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)));
+ /* Round up to a multiple of 8 */
+ if (max_text < INT_MAX-8)
+ max_text = (max_text + 8) & ~0x7;
- if (info_ptr->text == NULL)
- {
- png_free(png_ptr, old_text);
- return(1);
- }
+ else
+ max_text = INT_MAX;
- png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
- png_sizeof(png_text)));
- png_free(png_ptr, old_text);
+ /* Now allocate a new array and copy the old members in; this does all
+ * the overflow checks.
+ */
+ new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
+ info_ptr->text, old_num_text, max_text-old_num_text,
+ sizeof *new_text));
}
- else
+ if (new_text == NULL)
{
- 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_chunk_report(png_ptr, "too many text chunks",
+ PNG_CHUNK_WRITE_ERROR);
+ return 1;
}
- png_debug1(3, "allocated %d entries for info_ptr->text",
- info_ptr->max_text);
+ png_free(png_ptr, info_ptr->text);
+
+ info_ptr->text = new_text;
+ info_ptr->free_me |= PNG_FREE_TEXT;
+ info_ptr->max_text = max_text;
+ /* num_text is adjusted below as the entries are copied in */
+
+ png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
}
+
for (i = 0; i < num_text; i++)
{
- png_size_t text_length, key_len;
- png_size_t lang_len, lang_key_len;
+ size_t text_length, key_len;
+ size_t lang_len, lang_key_len;
png_textp textp = &(info_ptr->text[info_ptr->num_text]);
if (text_ptr[i].key == NULL)
@@ -730,11 +796,12 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
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");
+ png_chunk_report(png_ptr, "text compression mode is out of range",
+ PNG_CHUNK_WRITE_ERROR);
continue;
}
- key_len = png_strlen(text_ptr[i].key);
+ key_len = strlen(text_ptr[i].key);
if (text_ptr[i].compression <= 0)
{
@@ -748,20 +815,21 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
/* Set iTXt data */
if (text_ptr[i].lang != NULL)
- lang_len = png_strlen(text_ptr[i].lang);
+ lang_len = 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);
+ lang_key_len = strlen(text_ptr[i].lang_key);
else
lang_key_len = 0;
}
# else /* PNG_iTXt_SUPPORTED */
{
- png_warning(png_ptr, "iTXt chunk not supported");
+ png_chunk_report(png_ptr, "iTXt chunk not supported",
+ PNG_CHUNK_WRITE_ERROR);
continue;
}
# endif
@@ -780,32 +848,35 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
else
{
- text_length = png_strlen(text_ptr[i].text);
+ text_length = 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));
+ textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr,
+ key_len + text_length + lang_len + lang_key_len + 4));
if (textp->key == NULL)
- return(1);
+ {
+ png_chunk_report(png_ptr, "text chunk: out of memory",
+ PNG_CHUNK_WRITE_ERROR);
+ 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));
+ memcpy(textp->key, text_ptr[i].key, 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);
+ 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);
+ 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;
}
@@ -817,9 +888,8 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
textp->text = textp->key + key_len + 1;
}
- if (text_length)
- png_memcpy(textp->text, text_ptr[i].text,
- (png_size_t)(text_length));
+ if (text_length != 0)
+ memcpy(textp->text, text_ptr[i].text, text_length);
*(textp->text + text_length) = '\0';
@@ -840,28 +910,39 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
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_set_tIME(png_const_structrp png_ptr, png_inforp 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))
+ if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
+ (png_ptr->mode & PNG_WROTE_tIME) != 0)
return;
- png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
+ if (mod_time->month == 0 || mod_time->month > 12 ||
+ mod_time->day == 0 || mod_time->day > 31 ||
+ mod_time->hour > 23 || mod_time->minute > 59 ||
+ mod_time->second > 60)
+ {
+ png_warning(png_ptr, "Ignoring invalid time value");
+ return;
+ }
+
+ info_ptr->mod_time = *mod_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_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
{
png_debug1(1, "in %s storage function", "tRNS");
@@ -874,16 +955,20 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
/* 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.
+ *
+ * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
+ * relies on png_set_tRNS storing the information in png_struct
+ * (otherwise it won't be there for the code in pngrtran.c).
*/
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);
+ png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
+ png_malloc(png_ptr, 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);
+ memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
}
if (trans_color != NULL)
@@ -891,16 +976,15 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
int sample_max = (1 << info_ptr->bit_depth);
if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
- (int)trans_color->gray > sample_max) ||
+ 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)))
+ (trans_color->red > sample_max ||
+ trans_color->green > sample_max ||
+ 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));
+ info_ptr->trans_color = *trans_color;
if (num_trans == 0)
num_trans = 1;
@@ -918,8 +1002,8 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sPLT_SUPPORTED
void PNGAPI
-png_set_sPLT(png_structp png_ptr,
- png_infop info_ptr, png_const_sPLT_tp entries, int nentries)
+png_set_sPLT(png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
/*
* entries - array of png_sPLT_t structures
* to be added to the list of palettes
@@ -930,220 +1014,455 @@ png_set_sPLT(png_structp png_ptr,
*/
{
png_sPLT_tp np;
- int i;
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == 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));
+ /* Use the internal realloc function, which checks for all the possible
+ * overflows. Notice that the parameters are (int) and (size_t)
+ */
+ np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
+ info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
+ sizeof *np));
if (np == NULL)
{
- png_warning(png_ptr, "No memory for sPLT palettes");
+ /* Out of memory or too many chunks */
+ png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
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;
+ info_ptr->splt_palettes = np;
+ info_ptr->free_me |= PNG_FREE_SPLT;
- for (i = 0; i < nentries; i++)
+ np += info_ptr->splt_palettes_num;
+
+ do
{
- png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
- png_const_sPLT_tp from = entries + i;
- png_uint_32 length;
+ png_size_t length;
- length = png_strlen(from->name) + 1;
- to->name = (png_charp)png_malloc_warn(png_ptr, (png_size_t)length);
-
- if (to->name == NULL)
+ /* Skip invalid input entries */
+ if (entries->name == NULL || entries->entries == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing sPLT chunk");
+ /* png_handle_sPLT doesn't do this, so this is an app error */
+ png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
+ /* Just skip the invalid entry */
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)));
+ np->depth = entries->depth;
- if (to->entries == NULL)
+ /* In the event of out-of-memory just return - there's no point keeping
+ * on trying to add sPLT chunks.
+ */
+ length = strlen(entries->name) + 1;
+ np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));
+
+ if (np->name == NULL)
+ break;
+
+ memcpy(np->name, entries->name, length);
+
+ /* IMPORTANT: we have memory now that won't get freed if something else
+ * goes wrong; this code must free it. png_malloc_array produces no
+ * warnings; use a png_chunk_report (below) if there is an error.
+ */
+ np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
+ entries->nentries, sizeof (png_sPLT_entry)));
+
+ if (np->entries == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing sPLT chunk");
- png_free(png_ptr, to->name);
- to->name = NULL;
- continue;
+ png_free(png_ptr, np->name);
+ np->name = NULL;
+ break;
}
- png_memcpy(to->entries, from->entries,
- from->nentries * png_sizeof(png_sPLT_entry));
+ np->nentries = entries->nentries;
+ /* This multiply can't overflow because png_malloc_array has already
+ * checked it when doing the allocation.
+ */
+ memcpy(np->entries, entries->entries,
+ entries->nentries * sizeof (png_sPLT_entry));
- to->nentries = from->nentries;
- to->depth = from->depth;
+ /* Note that 'continue' skips the advance of the out pointer and out
+ * count, so an invalid entry is not added.
+ */
+ info_ptr->valid |= PNG_INFO_sPLT;
+ ++(info_ptr->splt_palettes_num);
+ ++np;
+ }
+ while (++entries, --nentries);
+
+ if (nentries > 0)
+ png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
+}
+#endif /* sPLT */
+
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+static png_byte
+check_location(png_const_structrp png_ptr, int location)
+{
+ location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
+
+ /* New in 1.6.0; copy the location and check it. This is an API
+ * change; previously the app had to use the
+ * png_set_unknown_chunk_location API below for each chunk.
+ */
+ if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ /* Write struct, so unknown chunks come from the app */
+ png_app_warning(png_ptr,
+ "png_set_unknown_chunks now expects a valid location");
+ /* Use the old behavior */
+ location = (png_byte)(png_ptr->mode &
+ (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
}
- 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 */
+ /* This need not be an internal error - if the app calls
+ * png_set_unknown_chunks on a read pointer it must get the location right.
+ */
+ if (location == 0)
+ png_error(png_ptr, "invalid location in png_set_unknown_chunks");
+
+ /* Now reduce the location to the top-most set bit by removing each least
+ * significant bit in turn.
+ */
+ while (location != (location & -location))
+ location &= ~(location & -location);
+
+ /* The cast is safe because 'location' is a bit mask and only the low four
+ * bits are significant.
+ */
+ return (png_byte)location;
+}
-#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_set_unknown_chunks(png_const_structrp png_ptr,
+ png_inforp 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)
+ if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
+ unknowns == NULL)
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));
+ /* Check for the failure cases where support has been disabled at compile
+ * time. This code is hardly ever compiled - it's here because
+ * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
+ * code) but may be meaningless if the read or write handling of unknown
+ * chunks is not compiled in.
+ */
+# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
+ defined(PNG_READ_SUPPORTED)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+ png_app_error(png_ptr, "no unknown chunk support on read");
+ return;
+ }
+# endif
+# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
+ defined(PNG_WRITE_SUPPORTED)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ png_app_error(png_ptr, "no unknown chunk support on write");
+ return;
+ }
+# endif
+
+ /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
+ * unknown critical chunks could be lost with just a warning resulting in
+ * undefined behavior. Now png_chunk_report is used to provide behavior
+ * appropriate to read or write.
+ */
+ np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
+ info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
+ sizeof *np));
if (np == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing unknown chunk");
+ png_chunk_report(png_ptr, "too many unknown chunks",
+ PNG_CHUNK_WRITE_ERROR);
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;
+ info_ptr->unknown_chunks = np; /* safe because it is initialized */
+ info_ptr->free_me |= PNG_FREE_UNKN;
- for (i = 0; i < num_unknowns; i++)
+ np += info_ptr->unknown_chunks_num;
+
+ /* Increment unknown_chunks_num each time round the loop to protect the
+ * just-allocated chunk data.
+ */
+ for (; num_unknowns > 0; --num_unknowns, ++unknowns)
{
- png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
- png_const_unknown_chunkp from = unknowns + i;
+ memcpy(np->name, unknowns->name, (sizeof np->name));
+ np->name[(sizeof np->name)-1] = '\0';
+ np->location = check_location(png_ptr, unknowns->location);
- 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;
+ if (unknowns->size == 0)
+ {
+ np->data = NULL;
+ np->size = 0;
+ }
else
{
- to->data = (png_bytep)png_malloc_warn(png_ptr,
- (png_size_t)from->size);
+ np->data = png_voidcast(png_bytep,
+ png_malloc_base(png_ptr, unknowns->size));
- if (to->data == NULL)
+ if (np->data == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing unknown chunk");
- to->size = 0;
+ png_chunk_report(png_ptr, "unknown chunk: out of memory",
+ PNG_CHUNK_WRITE_ERROR);
+ /* But just skip storing the unknown chunk */
+ continue;
}
- else
- png_memcpy(to->data, from->data, from->size);
+ memcpy(np->data, unknowns->data, unknowns->size);
+ np->size = unknowns->size;
}
- }
- info_ptr->unknown_chunks = np;
- info_ptr->unknown_chunks_num += num_unknowns;
- info_ptr->free_me |= PNG_FREE_UNKN;
+ /* These increments are skipped on out-of-memory for the data - the
+ * unknown chunk entry gets overwritten if the png_chunk_report returns.
+ * This is correct in the read case (the chunk is just dropped.)
+ */
+ ++np;
+ ++(info_ptr->unknown_chunks_num);
+ }
}
void PNGAPI
-png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
+png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp 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;
+ /* This API is pretty pointless in 1.6.0 because the location can be set
+ * before the call to png_set_unknown_chunks.
+ *
+ * TODO: add a png_app_warning in 1.7
+ */
+ if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
+ chunk < info_ptr->unknown_chunks_num)
+ {
+ if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
+ {
+ png_app_error(png_ptr, "invalid unknown chunk location");
+ /* Fake out the pre 1.6.0 behavior: */
+ if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */
+ location = PNG_AFTER_IDAT;
+
+ else
+ location = PNG_HAVE_IHDR; /* also undocumented */
+ }
+
+ info_ptr->unknown_chunks[chunk].location =
+ check_location(png_ptr, 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_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
{
png_debug(1, "in png_permit_mng_features");
if (png_ptr == NULL)
- return (png_uint_32)0;
+ return 0;
- png_ptr->mng_features_permitted =
- (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
+ png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
- return (png_uint_32)png_ptr->mng_features_permitted;
+ return 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)
+static unsigned int
+add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
{
- png_bytep new_list, p;
- int i, old_num_chunks;
+ unsigned int i;
+
+ /* Utility function: update the 'keep' state of a chunk if it is already in
+ * the list, otherwise add it to the list.
+ */
+ for (i=0; i= PNG_HANDLE_CHUNK_LAST)
{
- 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;
-
+ png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
return;
}
- if (chunk_list == NULL)
- return;
+ if (num_chunks_in <= 0)
+ {
+ png_ptr->unknown_default = keep;
+
+ /* '0' means just set the flags, so stop here */
+ if (num_chunks_in == 0)
+ return;
+ }
+
+ if (num_chunks_in < 0)
+ {
+ /* Ignore all unknown chunks and all chunks recognized by
+ * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
+ */
+ static PNG_CONST png_byte chunks_to_ignore[] = {
+ 98, 75, 71, 68, '\0', /* bKGD */
+ 99, 72, 82, 77, '\0', /* cHRM */
+ 103, 65, 77, 65, '\0', /* gAMA */
+ 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 */
+ 115, 82, 71, 66, '\0', /* sRGB */
+ 116, 69, 88, 116, '\0', /* tEXt */
+ 116, 73, 77, 69, '\0', /* tIME */
+ 122, 84, 88, 116, '\0' /* zTXt */
+ };
+
+ chunk_list = chunks_to_ignore;
+ num_chunks = (unsigned int)/*SAFE*/(sizeof chunks_to_ignore)/5U;
+ }
+
+ else /* num_chunks_in > 0 */
+ {
+ if (chunk_list == NULL)
+ {
+ /* Prior to 1.6.0 this was silently ignored, now it is an app_error
+ * which can be switched off.
+ */
+ png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
+ return;
+ }
+
+ num_chunks = num_chunks_in;
+ }
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)
+ old_num_chunks = 0;
- if (png_ptr->chunk_list != NULL)
+ /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
+ */
+ if (num_chunks + old_num_chunks > UINT_MAX/5)
{
- 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_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
+ return;
}
- png_memcpy(new_list + 5*old_num_chunks, chunk_list,
- (png_size_t)(5*num_chunks));
+ /* If these chunks are being reset to the default then no more memory is
+ * required because add_one_chunk above doesn't extend the list if the 'keep'
+ * parameter is the default.
+ */
+ if (keep != 0)
+ {
+ new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
+ 5 * (num_chunks + old_num_chunks)));
- for (p = new_list + 5*old_num_chunks + 4, i = 0; i 0)
+ memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
+ }
- png_ptr->num_chunk_list = old_num_chunks + num_chunks;
- png_ptr->chunk_list = new_list;
- png_ptr->free_me |= PNG_FREE_LIST;
+ else if (old_num_chunks > 0)
+ new_list = png_ptr->chunk_list;
+
+ else
+ new_list = NULL;
+
+ /* Add the new chunks together with each one's handling code. If the chunk
+ * already exists the code is updated, otherwise the chunk is added to the
+ * end. (In libpng 1.6.0 order no longer matters because this code enforces
+ * the earlier convention that the last setting is the one that is used.)
+ */
+ if (new_list != NULL)
+ {
+ png_const_bytep inlist;
+ png_bytep outlist;
+ unsigned int i;
+
+ for (i=0; ichunk_list != new_list)
+ png_free(png_ptr, new_list);
+
+ new_list = NULL;
+ }
+ }
+
+ else
+ num_chunks = 0;
+
+ png_ptr->num_chunk_list = num_chunks;
+
+ if (png_ptr->chunk_list != new_list)
+ {
+ if (png_ptr->chunk_list != NULL)
+ png_free(png_ptr, png_ptr->chunk_list);
+
+ png_ptr->chunk_list = new_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_set_read_user_chunk_fn(png_structrp 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");
@@ -1158,64 +1477,90 @@ png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
+png_set_rows(png_const_structrp png_ptr, png_inforp 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))
+ if (info_ptr->row_pointers != NULL &&
+ (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)
+ if (row_pointers != NULL)
info_ptr->valid |= PNG_INFO_IDAT;
}
#endif
void PNGAPI
-png_set_compression_buffer_size(png_structp png_ptr, png_size_t size)
+png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
{
if (png_ptr == NULL)
return;
- png_free(png_ptr, png_ptr->zbuf);
+ if (size == 0 || size > PNG_UINT_31_MAX)
+ png_error(png_ptr, "invalid compression buffer size");
- 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 */
- }
+# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+ png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
+ return;
+ }
+# endif
- else
- png_ptr->zbuf_size = (uInt)size;
+# ifdef PNG_WRITE_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ if (png_ptr->zowner != 0)
+ {
+ png_warning(png_ptr,
+ "Compression buffer size cannot be changed because it is in use");
+ return;
+ }
- png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
+ if (size > ZLIB_IO_MAX)
+ {
+ png_warning(png_ptr,
+ "Compression buffer size limited to system maximum");
+ size = ZLIB_IO_MAX; /* must fit */
+ }
- /* 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;
+ else if (size < 6)
+ {
+ /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
+ * if this is permitted.
+ */
+ png_warning(png_ptr,
+ "Compression buffer size cannot be reduced below 6");
+ return;
+ }
+
+ if (png_ptr->zbuffer_size != size)
+ {
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
+ png_ptr->zbuffer_size = (uInt)size;
+ }
+ }
+# endif
}
void PNGAPI
-png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
+png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
{
- if (png_ptr && info_ptr)
+ if (png_ptr != NULL && info_ptr != NULL)
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_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
png_uint_32 user_height_max)
{
/* Images with dimensions larger than these limits will be
@@ -1231,35 +1576,64 @@ png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_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)
+png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
{
- if (png_ptr)
+ if (png_ptr != NULL)
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_set_chunk_malloc_max (png_structrp png_ptr,
png_alloc_size_t user_chunk_malloc_max)
{
- if (png_ptr)
+ if (png_ptr != NULL)
png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
}
-#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
+#endif /* ?SET_USER_LIMITS */
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
-png_set_benign_errors(png_structp png_ptr, int allowed)
+png_set_benign_errors(png_structrp png_ptr, int allowed)
{
png_debug(1, "in png_set_benign_errors");
- if (allowed)
- png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
+ /* If allowed is 1, png_benign_error() is treated as a warning.
+ *
+ * If allowed is 0, png_benign_error() is treated as an error (which
+ * is the default behavior if png_set_benign_errors() is not called).
+ */
+
+ if (allowed != 0)
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
+ PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
else
- png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
+ png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
+ PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
}
-#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* BENIGN_ERRORS */
+
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Whether to report invalid palette index; added at libng-1.5.10.
+ * It is possible for an indexed (color-type==3) PNG file to contain
+ * pixels with invalid (out-of-range) indexes if the PLTE chunk has
+ * fewer entries than the image's bit-depth would allow. We recover
+ * from this gracefully by filling any incomplete palette with zeros
+ * (opaque black). By default, when this occurs libpng will issue
+ * a benign error. This API can be used to override that behavior.
+ */
+void PNGAPI
+png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
+{
+ png_debug(1, "in png_set_check_for_invalid_index");
+
+ if (allowed > 0)
+ png_ptr->num_palette_max = 0;
+
+ else
+ png_ptr->num_palette_max = -1;
+}
+#endif
+#endif /* READ || WRITE */
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
index 6a587e34b58..8670a5a4e8d 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
@@ -29,11 +29,11 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2013 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.4 [July 7, 2011]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -52,13 +52,130 @@
* in this structure and is required for decompressing the LZ compressed
* data in PNG files.
*/
+#ifndef ZLIB_CONST
+ /* We must ensure that zlib uses 'const' in declarations. */
+# define ZLIB_CONST
+#endif
#include "zlib.h"
+#ifdef const
+ /* zlib.h sometimes #defines const to nothing, undo this. */
+# undef const
+#endif
+
+/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
+ * with older builds.
+ */
+#if ZLIB_VERNUM < 0x1260
+# define PNGZ_MSG_CAST(s) png_constcast(char*,s)
+# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b)
+#else
+# define PNGZ_MSG_CAST(s) (s)
+# define PNGZ_INPUT_CAST(b) (b)
+#endif
+
+/* 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
+
+#ifdef PNG_WRITE_SUPPORTED
+/* The type of a compression buffer list used by the write code. */
+typedef struct png_compression_buffer
+{
+ struct png_compression_buffer *next;
+ png_byte output[1]; /* actually zbuf_size */
+} png_compression_buffer, *png_compression_bufferp;
+
+#define PNG_COMPRESSION_BUFFER_SIZE(pp)\
+ (offsetof(png_compression_buffer, output) + (pp)->zbuffer_size)
+#endif
+
+/* Colorspace support; structures used in png_struct, png_info and in internal
+ * functions to hold and communicate information about the color space.
+ *
+ * PNG_COLORSPACE_SUPPORTED is only required if the application will perform
+ * colorspace corrections, otherwise all the colorspace information can be
+ * skipped and the size of libpng can be reduced (significantly) by compiling
+ * out the colorspace support.
+ */
+#ifdef PNG_COLORSPACE_SUPPORTED
+/* The chromaticities of the red, green and blue colorants and the chromaticity
+ * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
+ */
+typedef struct png_xy
+{
+ png_fixed_point redx, redy;
+ png_fixed_point greenx, greeny;
+ png_fixed_point bluex, bluey;
+ png_fixed_point whitex, whitey;
+} png_xy;
+
+/* The same data as above but encoded as CIE XYZ values. When this data comes
+ * from chromaticities the sum of the Y values is assumed to be 1.0
+ */
+typedef struct png_XYZ
+{
+ png_fixed_point red_X, red_Y, red_Z;
+ png_fixed_point green_X, green_Y, green_Z;
+ png_fixed_point blue_X, blue_Y, blue_Z;
+} png_XYZ;
+#endif /* COLORSPACE */
+
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+/* A colorspace is all the above plus, potentially, profile information,
+ * however at present libpng does not use the profile internally so it is only
+ * stored in the png_info struct (if iCCP is supported.) The rendering intent
+ * is retained here and is checked.
+ *
+ * The file gamma encoding information is also stored here and gamma correction
+ * is done by libpng, whereas color correction must currently be done by the
+ * application.
+ */
+typedef struct png_colorspace
+{
+#ifdef PNG_GAMMA_SUPPORTED
+ png_fixed_point gamma; /* File gamma */
+#endif
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+ png_xy end_points_xy; /* End points as chromaticities */
+ png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */
+ png_uint_16 rendering_intent; /* Rendering intent of a profile */
+#endif
+
+ /* Flags are always defined to simplify the code. */
+ png_uint_16 flags; /* As defined below */
+} png_colorspace, * PNG_RESTRICT png_colorspacerp;
+
+typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
+
+/* General flags for the 'flags' field */
+#define PNG_COLORSPACE_HAVE_GAMMA 0x0001
+#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002
+#define PNG_COLORSPACE_HAVE_INTENT 0x0004
+#define PNG_COLORSPACE_FROM_gAMA 0x0008
+#define PNG_COLORSPACE_FROM_cHRM 0x0010
+#define PNG_COLORSPACE_FROM_sRGB 0x0020
+#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040
+#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */
+#define PNG_COLORSPACE_INVALID 0x8000
+#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags))
+#endif /* COLORSPACE || GAMMA */
struct png_struct_def
{
#ifdef PNG_SETJMP_SUPPORTED
- jmp_buf longjmp_buffer; /* used in png_error */
+ jmp_buf jmp_buf_local; /* New name in 1.6.0 for jmp_buf in png_struct */
png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */
+ jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */
+ size_t jmp_buf_size; /* size of the above, if allocated */
#endif
png_error_ptr error_fn; /* function for printing errors and aborting */
#ifdef PNG_WARNINGS_SUPPORTED
@@ -91,22 +208,12 @@ struct png_struct_def
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) */
+ png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
+ z_stream zstream; /* decompression structure */
+
#ifdef PNG_WRITE_SUPPORTED
-
-/* Added in 1.5.4: state to keep track of whether the zstream has been
- * initialized and if so whether it is for IDAT or some other chunk.
- */
-#define PNG_ZLIB_UNINITIALIZED 0
-#define PNG_ZLIB_FOR_IDAT 1
-#define PNG_ZLIB_FOR_TEXT 2 /* anything other than IDAT */
-#define PNG_ZLIB_USE_MASK 3 /* bottom two bits */
-#define PNG_ZLIB_IN_USE 4 /* a flag value */
-
- png_uint_32 zlib_state; /* State of zlib initialization */
-/* End of material added at libpng 1.5.4 */
+ png_compression_bufferp zbuffer_list; /* Created on demand during write */
+ uInt zbuffer_size; /* size of the actual buffer */
int zlib_level; /* holds zlib compression level */
int zlib_method; /* holds zlib compression method */
@@ -115,8 +222,7 @@ struct png_struct_def
int zlib_strategy; /* holds zlib compression strategy */
#endif
/* Added at libpng 1.5.4 */
-#if defined(PNG_WRITE_COMPRESSED_TEXT_SUPPORTED) || \
- defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED)
+#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
int zlib_text_level; /* holds zlib compression level */
int zlib_text_method; /* holds zlib compression method */
int zlib_text_window_bits; /* holds zlib compression window bits */
@@ -124,6 +230,14 @@ struct png_struct_def
int zlib_text_strategy; /* holds zlib compression strategy */
#endif
/* End of material added at libpng 1.5.4 */
+/* Added at libpng 1.6.0 */
+#ifdef PNG_WRITE_SUPPORTED
+ int zlib_set_level; /* Actual values set into the zstream on write */
+ int zlib_set_method;
+ int zlib_set_window_bits;
+ int zlib_set_mem_level;
+ int zlib_set_strategy;
+#endif
png_uint_32 width; /* width of image in pixels */
png_uint_32 height; /* height of image in pixels */
@@ -132,21 +246,32 @@ struct png_struct_def
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_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */
+ png_bytep prev_row; /* buffer to save previous (unfiltered) row.
+ * This is a pointer into big_prev_row
+ */
+ png_bytep row_buf; /* buffer to save current (unfiltered) row.
+ * This is a pointer into big_row_buf
+ */
+#ifdef PNG_WRITE_SUPPORTED
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 */
+#endif
png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */
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 */
+
+/* Added at libpng-1.5.10 */
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ int num_palette_max; /* maximum palette index found in IDAT */
+#endif
+
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 */
@@ -154,12 +279,17 @@ struct png_struct_def
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 usr_bit_depth; /* bit depth of users row: write only */
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 */
+#ifdef PNG_WRITE_SUPPORTED
+ png_byte usr_channels; /* channels at start of write: write only */
+#endif
png_byte sig_bytes; /* magic bytes read/written from start of file */
-
+ png_byte maximum_pixel_depth;
+ /* pixel depth used for the row buffers */
+ png_byte transformed_pixel_depth;
+ /* pixel depth after read/write transforms */
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_uint_16 filler; /* filler bytes for pixel expansion */
#endif
@@ -172,7 +302,7 @@ struct png_struct_def
#ifdef PNG_READ_GAMMA_SUPPORTED
png_color_16 background_1; /* background normalized to gamma 1.0 */
#endif
-#endif /* PNG_bKGD_SUPPORTED */
+#endif /* bKGD */
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_flush_ptr output_flush_fn; /* Function for flushing output */
@@ -180,19 +310,20 @@ struct png_struct_def
png_uint_32 flush_rows; /* number of rows written since last flush */
#endif
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_GAMMA_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_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
+ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
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 /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
@@ -228,14 +359,7 @@ struct png_struct_def
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 */
+#endif /* PROGRESSIVE_READ */
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
/* For the Borland special 64K segment handler */
@@ -251,10 +375,6 @@ struct png_struct_def
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 */
@@ -265,9 +385,17 @@ struct png_struct_def
png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */
#endif
+ /* Options */
+#ifdef PNG_SET_OPTION_SUPPORTED
+ png_byte options; /* On/off state (up to 4 options) */
+#endif
+
+#if PNG_LIBPNG_VER < 10700
+/* To do: remove this from libpng-1.7 */
#ifdef PNG_TIME_RFC1123_SUPPORTED
char time_buffer[29]; /* String to hold RFC 1123 time text */
#endif
+#endif
/* New members added in libpng-1.0.6 */
@@ -275,27 +403,31 @@ struct png_struct_def
#ifdef PNG_USER_CHUNKS_SUPPORTED
png_voidp user_chunk_ptr;
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
#endif
+#endif
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- int num_chunk_list;
- png_bytep chunk_list;
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ int unknown_default; /* As PNG_HANDLE_* */
+ unsigned int num_chunk_list; /* Number of entries in the list */
+ png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name
+ * followed by a PNG_HANDLE_* byte */
#endif
/* New members added in libpng-1.0.3 */
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte rgb_to_gray_status;
+ /* Added in libpng 1.5.5 to record setting of coefficients: */
+ png_byte rgb_to_gray_coefficients_set;
/* 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;
+ /* deleted in 1.5.5: 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)
+#if defined(PNG_MNG_FEATURES_SUPPORTED)
/* Changed from png_byte to png_uint_32 at version 1.2.0 */
png_uint_32 mng_features_permitted;
#endif
@@ -345,21 +477,41 @@ struct png_struct_def
#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. */
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+ /* Temporary storage for unknown chunk that the library doesn't recognize,
+ * used while reading the chunk.
+ */
png_unknown_chunk unknown_chunk;
#endif
-/* New members added in libpng-1.2.26 */
+/* New member added in libpng-1.2.26 */
png_size_t old_big_row_buf_size;
- png_size_t old_prev_row_size;
+#ifdef PNG_READ_SUPPORTED
/* New member added in libpng-1.2.30 */
- png_charp chunkdata; /* buffer for reading chunk data */
+ png_bytep read_buffer; /* buffer for reading chunk data */
+ png_alloc_size_t read_buffer_size; /* current size of the buffer */
+#endif
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ uInt IDAT_read_size; /* limit on read buffer size for IDAT */
+#endif
#ifdef PNG_IO_STATE_SUPPORTED
/* New member added in libpng-1.4.0 */
png_uint_32 io_state;
#endif
+
+/* New member added in libpng-1.5.6 */
+ png_bytep big_prev_row;
+
+/* New member added in libpng-1.5.7 */
+ void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
+ png_bytep row, png_const_bytep prev_row);
+
+#ifdef PNG_READ_SUPPORTED
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+ png_colorspace colorspace;
+#endif
+#endif
};
#endif /* PNGSTRUCT_H */
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngtest.c b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngtest.c
index 227181fbf96..fdd51acd04d 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngtest.c
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngtest.c
@@ -29,8 +29,8 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -61,16 +61,50 @@
#define _POSIX_SOURCE 1
-#include "zlib.h"
+#include
+#include
+#include
+
+/* Defined so I can write to a file on gui/windowing platforms */
+/* #define STDERR stderr */
+#define STDERR stdout /* For DOS */
+
#include "png.h"
+
+/* 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
+ *
+ * pngtest allocates a single row buffer for each row and overwrites it,
+ * therefore if the write side doesn't support the writing of interlaced images
+ * nothing can be done for an interlaced image (and the code below will fail
+ * horribly trying to write extra data after writing garbage).
+ */
+#if defined PNG_READ_SUPPORTED && /* else nothing can be done */\
+ defined PNG_READ_bKGD_SUPPORTED &&\
+ defined PNG_READ_cHRM_SUPPORTED &&\
+ defined PNG_READ_gAMA_SUPPORTED &&\
+ defined PNG_READ_oFFs_SUPPORTED &&\
+ defined PNG_READ_pCAL_SUPPORTED &&\
+ defined PNG_READ_pHYs_SUPPORTED &&\
+ defined PNG_READ_sBIT_SUPPORTED &&\
+ defined PNG_READ_sCAL_SUPPORTED &&\
+ defined PNG_READ_sRGB_SUPPORTED &&\
+ defined PNG_READ_tEXt_SUPPORTED &&\
+ defined PNG_READ_tIME_SUPPORTED &&\
+ defined PNG_READ_zTXt_SUPPORTED &&\
+ defined PNG_WRITE_INTERLACING_SUPPORTED
+
+#ifdef PNG_ZLIB_HEADER
+# include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
+#else
+# include "zlib.h"
+#endif
+
/* 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)
+#define FCLOSE(file) fclose(file)
#ifndef PNG_STDIO_SUPPORTED
typedef FILE * png_FILE_p;
@@ -95,17 +129,6 @@ typedef FILE * png_FILE_p;
# 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
*/
@@ -126,30 +149,34 @@ 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 */
+static int strict = 0;
+static int relaxed = 0;
+static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */
+static int error_count = 0; /* count calls to png_error */
+static int warning_count = 0; /* count calls to png_warning */
/* 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
+/* Defines for unknown chunk handling if required. */
+#ifndef PNG_HANDLE_CHUNK_ALWAYS
+# define PNG_HANDLE_CHUNK_ALWAYS 3
+#endif
+#ifndef PNG_HANDLE_CHUNK_IF_SAFE
+# define PNG_HANDLE_CHUNK_IF_SAFE 2
+#endif
+
+/* Utility to save typing/errors, the argument must be a name */
+#define MEMZERO(var) ((void)memset(&var, 0, sizeof var))
+
/* 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
+static 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)
@@ -173,9 +200,8 @@ read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
fprintf(stdout, "r");
}
-void PNGCBAPI
-write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
-void PNGCBAPI
+#ifdef PNG_WRITE_SUPPORTED
+static 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)
@@ -183,6 +209,7 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
fprintf(stdout, "w");
}
+#endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
@@ -191,9 +218,7 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
* 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
+static void PNGCBAPI
count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data)
{
if (png_ptr != NULL && row_info != NULL)
@@ -208,9 +233,7 @@ count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data)
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
+static void PNGCBAPI
count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
{
png_bytep dp = data;
@@ -288,7 +311,8 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
png_uint_32 n, nstop;
int channel;
int color_channels = row_info->channels;
- if (row_info->color_type > 3)color_channels--;
+ if (row_info->color_type > 3)
+ color_channels--;
for (n = 0, nstop=row_info->width; nfile_name != NULL)
+ name = test->file_name;
+
+ fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
}
/* This is the default error handling function. Note that replacements for
@@ -566,12 +483,14 @@ pngtest_warning(png_structp png_ptr, png_const_charp message)
static void PNGCBAPI
pngtest_error(png_structp png_ptr, png_const_charp message)
{
+ ++error_count;
+
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 */
@@ -590,9 +509,9 @@ typedef struct memory_information
{
png_alloc_size_t size;
png_voidp pointer;
- struct memory_information FAR *next;
+ struct memory_information *next;
} memory_information;
-typedef memory_information FAR *memory_infop;
+typedef memory_information *memory_infop;
static memory_infop pinformation = NULL;
static int current_allocation = 0;
@@ -622,7 +541,7 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)
memory_infop pinfo;
png_set_mem_fn(png_ptr, NULL, NULL, NULL);
pinfo = (memory_infop)png_malloc(png_ptr,
- png_sizeof(*pinfo));
+ (sizeof *pinfo));
pinfo->size = size;
current_allocation += size;
total_allocation += size;
@@ -648,9 +567,9 @@ PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)
pinfo->next = pinformation;
pinformation = pinfo;
/* Make sure the caller isn't assuming zeroed memory. */
- png_memset(pinfo->pointer, 0xdd, pinfo->size);
+ memset(pinfo->pointer, 0xdd, pinfo->size);
- if (verbose)
+ if (verbose != 0)
printf("png_malloc %lu bytes at %p\n", (unsigned long)size,
pinfo->pointer);
@@ -675,7 +594,7 @@ png_debug_free(png_structp png_ptr, png_voidp ptr)
/* Unlink the element from the list. */
{
- memory_infop FAR *ppinfo = &pinformation;
+ memory_infop *ppinfo = &pinformation;
for (;;)
{
@@ -689,15 +608,16 @@ png_debug_free(png_structp png_ptr, png_voidp ptr)
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);
+ memset(ptr, 0x55, pinfo->size);
+ if (pinfo != NULL)
+ free(pinfo);
pinfo = NULL;
break;
}
if (pinfo->next == NULL)
{
- fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr);
+ fprintf(STDERR, "Pointer %p not found\n", ptr);
break;
}
@@ -706,35 +626,84 @@ png_debug_free(png_structp png_ptr, png_voidp ptr)
}
/* Finally free the data. */
- if (verbose)
+ if (verbose != 0)
printf("Freeing %p\n", ptr);
- png_free_default(png_ptr, ptr);
+ if (ptr != NULL)
+ free(ptr);
ptr = NULL;
}
-#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */
+#endif /* USER_MEM && DEBUG */
/* END of code to test memory allocation/deallocation */
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
/* 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)
+static struct user_chunk_data
{
- png_uint_32
- *my_user_chunk_data;
+ png_const_infop info_ptr;
+ png_uint_32 vpAg_width, vpAg_height;
+ png_byte vpAg_units;
+ png_byte sTER_mode;
+ int location[2];
+}
+user_chunk_data;
+
+/* Used for location and order; zero means nothing. */
+#define have_sTER 0x01
+#define have_vpAg 0x02
+#define before_PLTE 0x10
+#define before_IDAT 0x20
+#define after_IDAT 0x40
+
+static void
+init_callback_info(png_const_infop info_ptr)
+{
+ MEMZERO(user_chunk_data);
+ user_chunk_data.info_ptr = info_ptr;
+}
+
+static int
+set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
+{
+ int location;
+
+ if ((data->location[0] & what) != 0 || (data->location[1] & what) != 0)
+ return 0; /* already have one of these */
+
+ /* Find where we are (the code below zeroes info_ptr to indicate that the
+ * chunks before the first IDAT have been read.)
+ */
+ if (data->info_ptr == NULL) /* after IDAT */
+ location = what | after_IDAT;
+
+ else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE) != 0)
+ location = what | before_IDAT;
+
+ else
+ location = what | before_PLTE;
+
+ if (data->location[0] == 0)
+ data->location[0] = location;
+
+ else
+ data->location[1] = location;
+
+ return 1; /* handled */
+}
+
+static int PNGCBAPI
+read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
+{
+ struct user_chunk_data *my_user_chunk_data =
+ (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
+
+ if (my_user_chunk_data == NULL)
+ png_error(png_ptr, "lost user chunk pointer");
/* Return one of the following:
* return (-n); chunk had an error
@@ -759,9 +728,14 @@ static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr,
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 (set_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
+ {
+ my_user_chunk_data->sTER_mode=chunk->data[0];
+ return (1);
+ }
+
+ else
+ return (0); /* duplicate sTER - give it to libpng */
}
if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */
@@ -773,30 +747,126 @@ static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr,
if (chunk->size != 9)
return (-1); /* Error return */
- my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr);
+ if (set_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
+ return (0); /* duplicate vpAg */
- 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];
+ my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data);
+ my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4);
+ my_user_chunk_data->vpAg_units = chunk->data[8];
return (1);
-
}
+
+#ifdef PNG_WRITE_SUPPORTED
+static void
+write_sTER_chunk(png_structp write_ptr)
+{
+ png_byte sTER[5] = {115, 84, 69, 82, '\0'};
+
+ if (verbose != 0)
+ fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);
+
+ png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);
+}
+
+static void
+write_vpAg_chunk(png_structp write_ptr)
+{
+ png_byte vpAg[5] = {118, 112, 65, 103, '\0'};
+
+ png_byte vpag_chunk_data[9];
+
+ if (verbose != 0)
+ fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n",
+ (unsigned long)user_chunk_data.vpAg_width,
+ (unsigned long)user_chunk_data.vpAg_height,
+ user_chunk_data.vpAg_units);
+
+ png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);
+ png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);
+ vpag_chunk_data[8] = user_chunk_data.vpAg_units;
+ png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);
+}
+
+static void
+write_chunks(png_structp write_ptr, int location)
+{
+ int i;
+
+ /* Notice that this preserves the original chunk order, however chunks
+ * intercepted by the callback will be written *after* chunks passed to
+ * libpng. This will actually reverse a pair of sTER chunks or a pair of
+ * vpAg chunks, resulting in an error later. This is not worth worrying
+ * about - the chunks should not be duplicated!
+ */
+ for (i=0; i<2; ++i)
+ {
+ if (user_chunk_data.location[i] == (location | have_sTER))
+ write_sTER_chunk(write_ptr);
+
+ else if (user_chunk_data.location[i] == (location | have_vpAg))
+ write_vpAg_chunk(write_ptr);
+ }
+}
+#endif /* WRITE */
+#else /* !READ_USER_CHUNKS */
+# define write_chunks(pp,loc) ((void)0)
#endif
/* END of code to demonstrate user chunk support */
+/* START of code to check that libpng has the required text support; this only
+ * checks for the write support because if read support is missing the chunk
+ * will simply not be reported back to pngtest.
+ */
+#ifdef PNG_TEXT_SUPPORTED
+static void
+pngtest_check_text_support(png_const_structp png_ptr, png_textp text_ptr,
+ int num_text)
+{
+ while (num_text > 0)
+ {
+ switch (text_ptr[--num_text].compression)
+ {
+ case PNG_TEXT_COMPRESSION_NONE:
+ break;
+
+ case PNG_TEXT_COMPRESSION_zTXt:
+# ifndef PNG_WRITE_zTXt_SUPPORTED
+ ++unsupported_chunks;
+# endif
+ break;
+
+ case PNG_ITXT_COMPRESSION_NONE:
+ case PNG_ITXT_COMPRESSION_zTXt:
+# ifndef PNG_WRITE_iTXt_SUPPORTED
+ ++unsupported_chunks;
+# endif
+ break;
+
+ default:
+ /* This is an error */
+ png_error(png_ptr, "invalid text chunk compression field");
+ break;
+ }
+ }
+}
+#endif
+/* END of code to check that libpng has the required text support */
+
/* Test one file */
-int
+static 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 */
+ pngtest_error_parameters error_parameters;
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;
+ int interlace_preserved = 1;
#else
png_structp write_ptr = NULL;
png_infop write_info_ptr = NULL;
@@ -805,17 +875,11 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_bytep row_buf;
png_uint_32 y;
png_uint_32 width, height;
- int num_pass, pass;
+ int num_pass = 1, pass;
int bit_depth, color_type;
-#ifdef PNG_SETJMP_SUPPORTED
-#ifdef USE_FAR_KEYWORD
- jmp_buf tmp_jmpbuf;
-#endif
-#endif
-
- char inbuf[256], outbuf[256];
row_buf = NULL;
+ error_parameters.file_name = inname;
if ((fpin = fopen(inname, "rb")) == NULL)
{
@@ -839,20 +903,9 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
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
+ png_set_error_fn(read_ptr, &error_parameters, pngtest_error,
+ pngtest_warning);
-#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 =
@@ -862,10 +915,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
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
+ png_set_error_fn(write_ptr, &error_parameters, pngtest_error,
+ pngtest_warning);
#endif
pngtest_debug("Allocating read_info, write_info and end_info structures");
read_info_ptr = png_create_info_struct(read_ptr);
@@ -875,13 +926,15 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
write_end_info_ptr = png_create_info_struct(write_ptr);
#endif
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+ init_callback_info(read_info_ptr);
+ png_set_read_user_chunk_fn(read_ptr, &user_chunk_data,
+ read_user_chunk_callback);
+#endif
+
#ifdef PNG_SETJMP_SUPPORTED
pngtest_debug("Setting jmpbuf for read struct");
-#ifdef USE_FAR_KEYWORD
- if (setjmp(tmp_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);
@@ -895,18 +948,11 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
FCLOSE(fpout);
return (1);
}
-#ifdef USE_FAR_KEYWORD
- png_memcpy(png_jmpbuf(read_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
-#endif
#ifdef PNG_WRITE_SUPPORTED
pngtest_debug("Setting jmpbuf for write struct");
-#ifdef USE_FAR_KEYWORD
- if (setjmp(tmp_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);
@@ -918,12 +964,34 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
FCLOSE(fpout);
return (1);
}
+#endif
+#endif
-#ifdef USE_FAR_KEYWORD
- png_memcpy(png_jmpbuf(write_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
-#endif
+ if (strict != 0)
+ {
+ /* Treat png_benign_error() as errors on read */
+ png_set_benign_errors(read_ptr, 0);
+
+#ifdef PNG_WRITE_SUPPORTED
+ /* Treat them as errors on write */
+ png_set_benign_errors(write_ptr, 0);
#endif
+
+ /* if strict is not set, then app warnings and errors are treated as
+ * warnings in release builds, but not in unstable builds; this can be
+ * changed with '--relaxed'.
+ */
+ }
+
+ else if (relaxed != 0)
+ {
+ /* Allow application (pngtest) errors and warnings to pass */
+ png_set_benign_errors(read_ptr, 1);
+
+#ifdef PNG_WRITE_SUPPORTED
+ png_set_benign_errors(write_ptr, 1);
#endif
+ }
pngtest_debug("Initializing input and output streams");
#ifdef PNG_STDIO_SUPPORTED
@@ -943,14 +1011,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
# endif
#endif
-#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
- /* Normally one would use Z_DEFAULT_STRATEGY for text compression.
- * This is here just to make pngtest replicate the results from libpng
- * versions prior to 1.5.4, and to test this new API.
- */
- png_set_text_compression_strategy(write_ptr, Z_FILTERED);
-#endif
-
if (status_dots_requested == 1)
{
#ifdef PNG_WRITE_SUPPORTED
@@ -982,36 +1042,65 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
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
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ /* Preserve all the unknown chunks, if possible. If this is disabled then,
+ * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use
+ * libpng to *save* the unknown chunks on read (because we can't switch the
+ * save option on!)
+ *
+ * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all
+ * unknown chunks and write will write them all.
+ */
+#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
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,
+ png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS,
NULL, 0);
+#endif
#endif
pngtest_debug("Reading info struct");
png_read_info(read_ptr, read_info_ptr);
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+ /* This is a bit of a hack; there is no obvious way in the callback function
+ * to determine that the chunks before the first IDAT have been read, so
+ * remove the info_ptr (which is only used to determine position relative to
+ * PLTE) here to indicate that we are after the IDAT.
+ */
+ user_chunk_data.info_ptr = NULL;
+#endif
+
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))
+ &color_type, &interlace_type, &compression_type, &filter_type) != 0)
{
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);
+#ifndef PNG_READ_INTERLACING_SUPPORTED
+ /* num_pass will not be set below, set it here if the image is
+ * interlaced: what happens is that write interlacing is *not* turned
+ * on an the partial interlaced rows are written directly.
+ */
+ switch (interlace_type)
+ {
+ case PNG_INTERLACE_NONE:
+ num_pass = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ num_pass = 7;
+ break;
+
+ default:
+ png_error(read_ptr, "invalid interlace type");
+ /*NOT REACHED*/
+ }
#endif
}
}
@@ -1022,7 +1111,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
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))
+ &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
{
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);
@@ -1033,7 +1122,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{
png_fixed_point gamma;
- if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma))
+ if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma) != 0)
png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
}
#endif
@@ -1045,7 +1134,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
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))
+ &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
{
png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
red_y, green_x, green_y, blue_x, blue_y);
@@ -1056,7 +1145,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{
double gamma;
- if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
+ if (png_get_gAMA(read_ptr, read_info_ptr, &gamma) != 0)
png_set_gAMA(write_ptr, write_info_ptr, gamma);
}
#endif
@@ -1070,7 +1159,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
int compression_type;
if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
- &profile, &proflen))
+ &profile, &proflen) != 0)
{
png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
profile, proflen);
@@ -1081,7 +1170,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{
int intent;
- if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
+ if (png_get_sRGB(read_ptr, read_info_ptr, &intent) != 0)
png_set_sRGB(write_ptr, write_info_ptr, intent);
}
#endif
@@ -1089,14 +1178,14 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_colorp palette;
int num_palette;
- if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
+ if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0)
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))
+ if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0)
{
png_set_bKGD(write_ptr, write_info_ptr, background);
}
@@ -1106,7 +1195,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{
png_uint_16p hist;
- if (png_get_hIST(read_ptr, read_info_ptr, &hist))
+ if (png_get_hIST(read_ptr, read_info_ptr, &hist) != 0)
png_set_hIST(write_ptr, write_info_ptr, hist);
}
#endif
@@ -1116,7 +1205,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
int unit_type;
if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,
- &unit_type))
+ &unit_type) != 0)
{
png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
}
@@ -1130,7 +1219,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
int type, nparams;
if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
- &nparams, &units, ¶ms))
+ &nparams, &units, ¶ms) != 0)
{
png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
nparams, units, params);
@@ -1142,7 +1231,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
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))
+ if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y,
+ &unit_type) != 0)
png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
}
#endif
@@ -1150,18 +1240,19 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{
png_color_8p sig_bit;
- if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
+ if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit) != 0)
png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
}
#endif
#ifdef PNG_sCAL_SUPPORTED
-#ifdef PNG_FLOATING_POINT_SUPPORTED
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
+ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
{
int unit;
double scal_width, scal_height;
if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
- &scal_height))
+ &scal_height) != 0)
{
png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
}
@@ -1173,7 +1264,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_charp scal_width, scal_height;
if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
- &scal_height))
+ &scal_height) != 0)
{
png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width,
scal_height);
@@ -1190,6 +1281,21 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
{
pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
+
+ pngtest_check_text_support(read_ptr, text_ptr, num_text);
+
+ if (verbose != 0)
+ {
+ int i;
+
+ printf("\n");
+ for (i=0; i 0)
{
pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
+
+ pngtest_check_text_support(read_ptr, text_ptr, num_text);
+
+ if (verbose != 0)
+ {
+ int i;
+
+ printf("\n");
+ for (i=0; i 0)
+ {
+ /* We don't really expect to get here because of the setjmp handling
+ * above, but this is safe.
+ */
+ fprintf(STDERR, "\n %s: %d libpng errors found (%d warnings)",
+ inname, error_count, warning_count);
+
+ if (strict != 0)
+ return (1);
+ }
+
+# ifdef PNG_WRITE_SUPPORTED
+ /* If there we no write support nothing was written! */
+ else if (unsupported_chunks > 0)
+ {
+ fprintf(STDERR, "\n %s: unsupported chunks (%d)%s",
+ inname, unsupported_chunks, strict ? ": IGNORED --strict!" : "");
+ }
+# endif
+
+ else if (warning_count > 0)
+ {
+ fprintf(STDERR, "\n %s: %d libpng warnings found",
+ inname, warning_count);
+
+ if (strict != 0)
+ return (1);
+ }
+
pngtest_debug("Opening files for comparison");
if ((fpin = fopen(inname, "rb")) == NULL)
{
@@ -1480,61 +1629,84 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
return (1);
}
- for (;;)
+#ifdef PNG_WRITE_SUPPORTED /* else nothing was written */
+ if (interlace_preserved != 0) /* else the files will be changed */
{
- 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)
+ for (;;)
{
- fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
- inname, outname);
+ static int wrote_question = 0;
+ png_size_t num_in, num_out;
+ char inbuf[256], outbuf[256];
- if (wrote_question == 0)
+ num_in = fread(inbuf, 1, sizeof inbuf, fpin);
+ num_out = fread(outbuf, 1, sizeof outbuf, fpout);
+
+ if (num_in != num_out)
{
- 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;
- }
+ fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
+ inname, outname);
- 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,
+ if (wrote_question == 0 && unsupported_chunks == 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;
+ 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);
+
+ if (strict != 0 && unsupported_chunks == 0)
+ return (1);
+
+ else
+ return (0);
}
- FCLOSE(fpin);
- FCLOSE(fpout);
- return (0);
+ if (num_in == 0)
+ break;
+
+ if (memcmp(inbuf, outbuf, num_in))
+ {
+ fprintf(STDERR, "\nFiles %s and %s are different\n", inname,
+ outname);
+
+ if (wrote_question == 0 && unsupported_chunks == 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);
+
+ /* NOTE: the unsupported_chunks escape is permitted here because
+ * unsupported text chunk compression will result in the compression
+ * mode being changed (to NONE) yet, in the test case, the result
+ * can be exactly the same size!
+ */
+ if (strict != 0 && unsupported_chunks == 0)
+ return (1);
+
+ else
+ return (0);
+ }
}
}
+#endif /* WRITE */
FCLOSE(fpin);
FCLOSE(fpout);
@@ -1614,6 +1786,24 @@ main(int argc, char *argv[])
inname = argv[2];
}
+ else if (strcmp(argv[1], "--strict") == 0)
+ {
+ status_dots_requested = 0;
+ verbose = 1;
+ inname = argv[2];
+ strict++;
+ relaxed = 0;
+ }
+
+ else if (strcmp(argv[1], "--relaxed") == 0)
+ {
+ status_dots_requested = 0;
+ verbose = 1;
+ inname = argv[2];
+ strict = 0;
+ relaxed++;
+ }
+
else
{
inname = argv[1];
@@ -1621,10 +1811,11 @@ main(int argc, char *argv[])
}
}
- if (!multiple && argc == 3 + verbose)
+ if (multiple == 0 && argc == 3 + verbose)
outname = argv[2 + verbose];
- if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2))
+ if ((multiple == 0 && argc > 3 + verbose) ||
+ (multiple != 0 && argc < 2))
{
fprintf(STDERR,
"usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
@@ -1636,7 +1827,7 @@ main(int argc, char *argv[])
exit(1);
}
- if (multiple)
+ if (multiple != 0)
{
int i;
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
@@ -1646,6 +1837,9 @@ main(int argc, char *argv[])
{
int kerror;
fprintf(STDERR, "\n Testing %s:", argv[i]);
+#if PNG_DEBUG > 0
+ fprintf(STDERR, "\n");
+#endif
kerror = test_one_file(argv[i], outname);
if (kerror == 0)
{
@@ -1660,7 +1854,7 @@ main(int argc, char *argv[])
#endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
for (k = 0; k<256; k++)
- if (filters_used[k])
+ if (filters_used[k] != 0)
fprintf(STDERR, " Filter %d was used %lu times\n",
k, (unsigned long)filters_used[k]);
#endif
@@ -1669,7 +1863,7 @@ main(int argc, char *argv[])
fprintf(STDERR, " tIME = %s\n", tIME_string);
tIME_chunk_present = 0;
-#endif /* PNG_TIME_RFC1123_SUPPORTED */
+#endif /* TIME_RFC1123 */
}
else
@@ -1691,9 +1885,9 @@ main(int argc, char *argv[])
while (pinfo != NULL)
{
- fprintf(STDERR, " %lu bytes at %x\n",
+ fprintf(STDERR, " %lu bytes at %p\n",
(unsigned long)pinfo->size,
- (unsigned int)pinfo->pointer);
+ pinfo->pointer);
pinfo = pinfo->next;
}
}
@@ -1727,7 +1921,12 @@ main(int argc, char *argv[])
status_dots_requested = 0;
if (i == 0 || verbose == 1 || ierror != 0)
+ {
fprintf(STDERR, "\n Testing %s:", inname);
+#if PNG_DEBUG > 0
+ fprintf(STDERR, "\n");
+#endif
+ }
kerror = test_one_file(inname, outname);
@@ -1746,21 +1945,26 @@ main(int argc, char *argv[])
#endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
for (k = 0; k<256; k++)
- if (filters_used[k])
+ if (filters_used[k] != 0)
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 */
+#endif /* TIME_RFC1123 */
}
}
else
{
if (verbose == 0 && i != 2)
+ {
fprintf(STDERR, "\n Testing %s:", inname);
+#if PNG_DEBUG > 0
+ fprintf(STDERR, "\n");
+#endif
+ }
fprintf(STDERR, " FAIL\n");
ierror += kerror;
@@ -1779,8 +1983,8 @@ main(int argc, char *argv[])
while (pinfo != NULL)
{
- fprintf(STDERR, " %lu bytes at %x\n",
- (unsigned long)pinfo->size, (unsigned int)pinfo->pointer);
+ fprintf(STDERR, " %lu bytes at %p\n",
+ (unsigned long)pinfo->size, pinfo->pointer);
pinfo = pinfo->next;
}
}
@@ -1820,6 +2024,16 @@ main(int argc, char *argv[])
return (int)(ierror != 0);
}
+#else
+int
+main(void)
+{
+ fprintf(STDERR,
+ " test ignored because libpng was not built with read support\n");
+ /* And skip this test */
+ return PNG_LIBPNG_VER < 10600 ? 0 : 77;
+}
+#endif
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_5_4 Your_png_h_is_not_version_1_5_4;
+typedef png_libpng_version_1_6_16 Your_png_h_is_not_version_1_6_16;
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
index b59fc695bed..5b95db8c66b 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
@@ -29,8 +29,8 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -46,7 +46,7 @@
#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_set_bgr(png_structrp png_ptr)
{
png_debug(1, "in png_set_bgr");
@@ -60,7 +60,7 @@ png_set_bgr(png_structp png_ptr)
#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_set_swap(png_structrp png_ptr)
{
png_debug(1, "in png_set_swap");
@@ -75,7 +75,7 @@ png_set_swap(png_structp png_ptr)
#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_set_packing(png_structrp png_ptr)
{
png_debug(1, "in png_set_packing");
@@ -85,7 +85,9 @@ png_set_packing(png_structp png_ptr)
if (png_ptr->bit_depth < 8)
{
png_ptr->transformations |= PNG_PACK;
- png_ptr->usr_bit_depth = 8;
+# ifdef PNG_WRITE_SUPPORTED
+ png_ptr->usr_bit_depth = 8;
+# endif
}
}
#endif
@@ -93,7 +95,7 @@ png_set_packing(png_structp png_ptr)
#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_set_packswap(png_structrp png_ptr)
{
png_debug(1, "in png_set_packswap");
@@ -107,7 +109,7 @@ png_set_packswap(png_structp png_ptr)
#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_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
{
png_debug(1, "in png_set_shift");
@@ -122,11 +124,11 @@ png_set_shift(png_structp png_ptr, png_const_color_8p true_bits)
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
defined(PNG_WRITE_INTERLACING_SUPPORTED)
int PNGAPI
-png_set_interlace_handling(png_structp png_ptr)
+png_set_interlace_handling(png_structrp png_ptr)
{
png_debug(1, "in png_set_interlace handling");
- if (png_ptr && png_ptr->interlaced)
+ if (png_ptr != 0 && png_ptr->interlaced != 0)
{
png_ptr->transformations |= PNG_INTERLACE;
return (7);
@@ -143,44 +145,91 @@ png_set_interlace_handling(png_structp png_ptr)
* that don't like bytes as parameters.
*/
void PNGAPI
-png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_filler");
if (png_ptr == NULL)
return;
+ /* In libpng 1.6 it is possible to determine whether this is a read or write
+ * operation and therefore to do more checking here for a valid call.
+ */
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+# ifdef PNG_READ_FILLER_SUPPORTED
+ /* On read png_set_filler is always valid, regardless of the base PNG
+ * format, because other transformations can give a format where the
+ * filler code can execute (basically an 8 or 16-bit component RGB or G
+ * format.)
+ *
+ * NOTE: usr_channels is not used by the read code! (This has led to
+ * confusion in the past.) The filler is only used in the read code.
+ */
+ png_ptr->filler = (png_uint_16)filler;
+# else
+ png_app_error(png_ptr, "png_set_filler not supported on read");
+ PNG_UNUSED(filler) /* not used in the write case */
+ return;
+# endif
+ }
+
+ else /* write */
+ {
+# ifdef PNG_WRITE_FILLER_SUPPORTED
+ /* On write the usr_channels parameter must be set correctly at the
+ * start to record the number of channels in the app-supplied data.
+ */
+ switch (png_ptr->color_type)
+ {
+ case PNG_COLOR_TYPE_RGB:
+ png_ptr->usr_channels = 4;
+ break;
+
+ case PNG_COLOR_TYPE_GRAY:
+ if (png_ptr->bit_depth >= 8)
+ {
+ png_ptr->usr_channels = 2;
+ break;
+ }
+
+ else
+ {
+ /* There simply isn't any code in libpng to strip out bits
+ * from bytes when the components are less than a byte in
+ * size!
+ */
+ png_app_error(png_ptr,
+ "png_set_filler is invalid for low bit depth gray output");
+ return;
+ }
+
+ default:
+ png_app_error(png_ptr,
+ "png_set_filler: inappropriate color type");
+ return;
+ }
+# else
+ png_app_error(png_ptr, "png_set_filler not supported on write");
+ return;
+# endif
+ }
+
+ /* Here on success - libpng supports the operation, set the transformation
+ * and the flag to say where the filler channel is.
+ */
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_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_add_alpha");
@@ -188,7 +237,9 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
return;
png_set_filler(png_ptr, filler, filler_loc);
- png_ptr->transformations |= PNG_ADD_ALPHA;
+ /* The above may fail to do anything. */
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_ptr->transformations |= PNG_ADD_ALPHA;
}
#endif
@@ -196,7 +247,7 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
void PNGAPI
-png_set_swap_alpha(png_structp png_ptr)
+png_set_swap_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_swap_alpha");
@@ -210,7 +261,7 @@ png_set_swap_alpha(png_structp png_ptr)
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
void PNGAPI
-png_set_invert_alpha(png_structp png_ptr)
+png_set_invert_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_invert_alpha");
@@ -223,7 +274,7 @@ png_set_invert_alpha(png_structp png_ptr)
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
void PNGAPI
-png_set_invert_mono(png_structp png_ptr)
+png_set_invert_mono(png_structrp png_ptr)
{
png_debug(1, "in png_set_invert_mono");
@@ -304,9 +355,16 @@ png_do_swap(png_row_infop row_info, png_bytep row)
for (i = 0; i < istop; i++, rp += 2)
{
+#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
+ /* Feature added to libpng-1.6.11 for testing purposes, not
+ * enabled by default.
+ */
+ *(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
+#else
png_byte t = *rp;
*rp = *(rp + 1);
*(rp + 1) = t;
+#endif
}
}
}
@@ -448,7 +506,7 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
*rp = table[*rp];
}
}
-#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
+#endif /* PACKSWAP || WRITE_PACKSWAP */
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
@@ -480,7 +538,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
if (row_info->bit_depth == 8)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channel and, for sp, the filler */
sp += 2, ++dp;
@@ -494,7 +552,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
else if (row_info->bit_depth == 16)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channel and, for sp, the filler */
sp += 4, dp += 2;
@@ -520,7 +578,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
if (row_info->bit_depth == 8)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channels and, for sp, the filler */
sp += 4, dp += 3;
@@ -534,7 +592,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
else if (row_info->bit_depth == 16)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channels and, for sp, the filler */
sp += 8, dp += 6;
@@ -575,7 +633,7 @@ 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))
+ if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_uint_32 row_width = row_info->width;
if (row_info->bit_depth == 8)
@@ -645,19 +703,133 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
#endif
}
}
-#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
+#endif /* READ_BGR || WRITE_BGR */
+
+#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
+ defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
+/* Added at libpng-1.5.10 */
+void /* PRIVATE */
+png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
+{
+ if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
+ png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
+ {
+ /* Calculations moved outside switch in an attempt to stop different
+ * compiler warnings. 'padding' is in *bits* within the last byte, it is
+ * an 'int' because pixel_depth becomes an 'int' in the expression below,
+ * and this calculation is used because it avoids warnings that other
+ * forms produced on either GCC or MSVC.
+ */
+ int padding = (-row_info->pixel_depth * row_info->width) & 7;
+ png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
+
+ switch (row_info->bit_depth)
+ {
+ case 1:
+ {
+ /* in this case, all bytes must be 0 so we don't need
+ * to unpack the pixels except for the rightmost one.
+ */
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ if (*rp >> padding != 0)
+ png_ptr->num_palette_max = 1;
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 2:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ int i = ((*rp >> padding) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 2) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 4) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 6) & 0x03);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 4:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ int i = ((*rp >> padding) & 0x0f);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ i = (((*rp >> padding) >> 4) & 0x0f);
+
+ if (i > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = i;
+
+ padding = 0;
+ }
+
+ break;
+ }
+
+ case 8:
+ {
+ for (; rp > png_ptr->row_buf; rp--)
+ {
+ if (*rp > png_ptr->num_palette_max)
+ png_ptr->num_palette_max = (int) *rp;
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+}
+#endif /* CHECK_FOR_INVALID_INDEX */
#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
+png_set_user_transform_info(png_structrp 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;
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
+ {
+ png_app_error(png_ptr,
+ "info change after png_start_read_image or png_read_update_info");
+ return;
+ }
+#endif
+
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;
@@ -671,20 +843,20 @@ png_set_user_transform_info(png_structp png_ptr, png_voidp
*/
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
png_voidp PNGAPI
-png_get_user_transform_ptr(png_const_structp png_ptr)
+png_get_user_transform_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
- return ((png_voidp)png_ptr->user_transform_ptr);
+ return png_ptr->user_transform_ptr;
}
#endif
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
png_uint_32 PNGAPI
-png_get_current_row_number(png_const_structp png_ptr)
+png_get_current_row_number(png_const_structrp png_ptr)
{
- /* See the comments in png.h - this is the sub-image row when reading and
+ /* See the comments in png.h - this is the sub-image row when reading an
* interlaced image.
*/
if (png_ptr != NULL)
@@ -694,13 +866,12 @@ png_get_current_row_number(png_const_structp png_ptr)
}
png_byte PNGAPI
-png_get_current_pass_number(png_const_structp png_ptr)
+png_get_current_pass_number(png_const_structrp png_ptr)
{
if (png_ptr != NULL)
return png_ptr->pass;
return 8; /* invalid */
}
-#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
-#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
- PNG_WRITE_USER_TRANSFORM_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* USER_TRANSFORM_INFO */
+#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
+#endif /* READ || WRITE */
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwio.c b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwio.c
index 2f94f8c9572..017a9d7b31b 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwio.c
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwio.c
@@ -29,8 +29,8 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -58,11 +58,12 @@
*/
void /* PRIVATE */
-png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length)
+png_write_data(png_structrp 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);
+ (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data),
+ length);
else
png_error(png_ptr, "Call to NULL write function");
@@ -74,7 +75,6 @@ png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length)
* 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)
{
@@ -88,64 +88,6 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
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
@@ -154,7 +96,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
*/
#ifdef PNG_WRITE_FLUSH_SUPPORTED
void /* PRIVATE */
-png_flush(png_structp png_ptr)
+png_flush(png_structrp png_ptr)
{
if (png_ptr->output_flush_fn != NULL)
(*(png_ptr->output_flush_fn))(png_ptr);
@@ -169,7 +111,7 @@ png_default_flush(png_structp png_ptr)
if (png_ptr == NULL)
return;
- io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
+ io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr));
fflush(io_ptr);
}
# endif
@@ -205,7 +147,7 @@ png_default_flush(png_structp png_ptr)
* *FILE structure.
*/
void PNGAPI
-png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
+png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
{
if (png_ptr == NULL)
@@ -235,8 +177,11 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
# else
png_ptr->output_flush_fn = output_flush_fn;
# endif
-#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+#else
+ PNG_UNUSED(output_flush_fn)
+#endif /* WRITE_FLUSH */
+#ifdef PNG_READ_SUPPORTED
/* It is an error to read while writing a png file */
if (png_ptr->read_data_fn != NULL)
{
@@ -246,37 +191,6 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_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 */
+}
+#endif /* WRITE */
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwrite.c b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwrite.c
index bdc14670964..1d39e7490f7 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwrite.c
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwrite.c
@@ -29,8 +29,8 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -40,9 +40,65 @@
*/
#include "pngpriv.h"
+#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+# include
+#endif
#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+/* Write out all the unknown chunks for the current given location */
+static void
+write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
+ unsigned int where)
+{
+ if (info_ptr->unknown_chunks_num != 0)
+ {
+ png_const_unknown_chunkp up;
+
+ png_debug(5, "writing extra chunks");
+
+ for (up = info_ptr->unknown_chunks;
+ up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+ ++up)
+ if ((up->location & where) != 0)
+ {
+ /* If per-chunk unknown chunk handling is enabled use it, otherwise
+ * just write the chunks the application has set.
+ */
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ int keep = png_handle_as_unknown(png_ptr, up->name);
+
+ /* NOTE: this code is radically different from the read side in the
+ * matter of handling an ancillary unknown chunk. In the read side
+ * the default behavior is to discard it, in the code below the default
+ * behavior is to write it. Critical chunks are, however, only
+ * written if explicitly listed or if the default is set to write all
+ * unknown chunks.
+ *
+ * The default handling is also slightly weird - it is not possible to
+ * stop the writing of all unsafe-to-copy chunks!
+ *
+ * TODO: REVIEW: this would seem to be a bug.
+ */
+ if (keep != PNG_HANDLE_CHUNK_NEVER &&
+ ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
+ keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
+ png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
+#endif
+ {
+ /* TODO: review, what is wrong with a zero length unknown chunk? */
+ 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 /* WRITE_UNKNOWN_CHUNKS */
+
/* 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
@@ -53,21 +109,21 @@
* them in png_write_end(), and compressing them.
*/
void PNGAPI
-png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
+png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp 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))
+ if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
{
/* 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))
+ if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \
+ png_ptr->mng_features_permitted != 0)
{
png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
png_ptr->mng_features_permitted = 0;
@@ -79,75 +135,88 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
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);
+ info_ptr->interlace_type
#else
- 0);
+ 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.
+ *
+ * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
+ * the chunks will be written if the WRITE routine is there and information
+ * is available in the COLORSPACE. (See png_colorspace_sync_info in png.c
+ * for where the valid flags get set.)
+ *
+ * Under certain circumstances the colorspace can be invalidated without
+ * syncing the info_struct 'valid' flags; this happens if libpng detects and
+ * error and calls png_error while the color space is being set, yet the
+ * application continues writing the PNG. So check the 'invalid' flag here
+ * too.
*/
-#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);
+#ifdef PNG_GAMMA_SUPPORTED
+# ifdef PNG_WRITE_gAMA_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
+ (info_ptr->valid & PNG_INFO_gAMA) != 0)
+ png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
+# endif
#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_COLORSPACE_SUPPORTED
+ /* Write only one of sRGB or an ICC profile. If a profile was supplied
+ * and it matches one of the known sRGB ones issue a warning.
+ */
+# ifdef PNG_WRITE_iCCP_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->valid & PNG_INFO_iCCP) != 0)
+ {
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
+ png_app_warning(png_ptr,
+ "profile matches sRGB but writing iCCP instead");
+# endif
+
+ png_write_iCCP(png_ptr, info_ptr->iccp_name,
+ info_ptr->iccp_profile);
+ }
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ else
+# endif
+# endif
+
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->valid & PNG_INFO_sRGB) != 0)
+ png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
+# endif /* WRITE_sRGB */
+#endif /* COLORSPACE */
+
#ifdef PNG_WRITE_sBIT_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sBIT)
+ if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
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);
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+# ifdef PNG_WRITE_cHRM_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 &&
+ (info_ptr->valid & PNG_INFO_cHRM) != 0)
+ png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
+# endif
#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->location & PNG_AFTER_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);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
#endif
+
png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
}
}
void PNGAPI
-png_write_info(png_structp png_ptr, png_infop info_ptr)
+png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
{
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
int i;
@@ -160,19 +229,19 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
png_write_info_before_PLTE(png_ptr, info_ptr);
- if (info_ptr->valid & PNG_INFO_PLTE)
+ if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
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)
+ else if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) !=0)
png_error(png_ptr, "Valid palette required for paletted images");
#ifdef PNG_WRITE_tRNS_SUPPORTED
- if (info_ptr->valid & PNG_INFO_tRNS)
+ if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
{
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel (in tRNS) */
- if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
int j;
@@ -186,42 +255,42 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
}
#endif
#ifdef PNG_WRITE_bKGD_SUPPORTED
- if (info_ptr->valid & PNG_INFO_bKGD)
+ if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
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)
+ if ((info_ptr->valid & PNG_INFO_hIST) != 0)
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)
+ if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
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)
+ if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
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)
+ if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
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)
+ if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
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)
+ if ((info_ptr->valid & PNG_INFO_tIME) != 0)
{
png_write_tIME(png_ptr, &(info_ptr->mod_time));
png_ptr->mode |= PNG_WROTE_tIME;
@@ -229,7 +298,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#endif /* tIME */
#ifdef PNG_WRITE_sPLT_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sPLT)
+ if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
#endif /* sPLT */
@@ -251,11 +320,14 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->text[i].lang,
info_ptr->text[i].lang_key,
info_ptr->text[i].text);
+ /* Mark this chunk as written */
+ if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ else
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
- png_warning(png_ptr, "Unable to write international text");
+ 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 */
@@ -264,13 +336,12 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#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);
+ info_ptr->text[i].text, info_ptr->text[i].compression);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#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)
@@ -291,29 +362,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#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->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);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
#endif
}
@@ -323,16 +372,21 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
* comments, I suggest writing them here, and compressing them.
*/
void PNGAPI
-png_write_end(png_structp png_ptr, png_infop info_ptr)
+png_write_end(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_write_end");
if (png_ptr == NULL)
return;
- if (!(png_ptr->mode & PNG_HAVE_IDAT))
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
png_error(png_ptr, "No IDATs written into file");
+#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ if (png_ptr->num_palette_max > png_ptr->num_palette)
+ png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
+#endif
+
/* See if user wants us to write information chunks */
if (info_ptr != NULL)
{
@@ -341,8 +395,8 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
#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))
+ if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
+ (png_ptr->mode & PNG_WROTE_tIME) == 0)
png_write_tIME(png_ptr, &(info_ptr->mod_time));
#endif
@@ -363,11 +417,14 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
info_ptr->text[i].lang,
info_ptr->text[i].lang_key,
info_ptr->text[i].text);
+ /* Mark this chunk as written */
+ if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ else
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#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)
@@ -375,13 +432,12 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
#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);
+ info_ptr->text[i].text, info_ptr->text[i].compression);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#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)
@@ -390,37 +446,16 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
/* 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
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);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
#endif
}
@@ -428,6 +463,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
/* 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
@@ -443,9 +479,8 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
}
#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_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
{
png_debug(1, "in png_convert_from_struct_tm");
@@ -474,103 +509,75 @@ 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));
+#ifndef PNG_USER_MEM_SUPPORTED
+ png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, NULL, NULL, NULL);
+#else
+ 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 tmp_jmpbuf;
-#endif
-#endif
-
- 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(tmp_jmpbuf))
-#else
- if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */
-#endif
-#ifdef USE_FAR_KEYWORD
- png_memcpy(png_jmpbuf(png_ptr), tmp_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 (!png_user_version_check(png_ptr, user_png_ver))
- png_cleanup_needed = 1;
-
- /* Initialize zbuf - compression buffer */
- png_ptr->zbuf_size = PNG_ZBUF_SIZE;
-
- if (!png_cleanup_needed)
+ png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
+#endif /* USER_MEM */
+ if (png_ptr != NULL)
{
- png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr,
- png_ptr->zbuf_size);
- if (png_ptr->zbuf == NULL)
- png_cleanup_needed = 1;
+ /* Set the zlib control values to defaults; they can be overridden by the
+ * application after the struct has been created.
+ */
+ png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
+
+ /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
+ * pngwutil.c defaults it according to whether or not filters will be
+ * used, and ignores this setting.
+ */
+ png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
+ png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
+ png_ptr->zlib_mem_level = 8;
+ png_ptr->zlib_window_bits = 15;
+ png_ptr->zlib_method = 8;
+
+#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
+ png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
+ png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
+ png_ptr->zlib_text_mem_level = 8;
+ png_ptr->zlib_text_window_bits = 15;
+ png_ptr->zlib_text_method = 8;
+#endif /* WRITE_COMPRESSED_TEXT */
+
+ /* This is a highly dubious configuration option; by default it is off,
+ * but it may be appropriate for private builds that are testing
+ * extensions not conformant to the current specification, or of
+ * applications that must not fail to write at all costs!
+ */
+#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
+ /* In stable builds only warn if an application error can be completely
+ * handled.
+ */
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
+#endif
+
+ /* App warnings are warnings in release (or release candidate) builds but
+ * are errors during development.
+ */
+#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
+ png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
+#endif
+
+ /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
+ * do it itself) avoiding setting the default function if it is not
+ * required.
+ */
+ png_set_write_fn(png_ptr, NULL, NULL, NULL);
}
- 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);
+ return png_ptr;
}
@@ -580,7 +587,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
* "write" the image seven times.
*/
void PNGAPI
-png_write_rows(png_structp png_ptr, png_bytepp row,
+png_write_rows(png_structrp png_ptr, png_bytepp row,
png_uint_32 num_rows)
{
png_uint_32 i; /* row counter */
@@ -602,7 +609,7 @@ png_write_rows(png_structp png_ptr, png_bytepp row,
* if you are writing an interlaced image.
*/
void PNGAPI
-png_write_image(png_structp png_ptr, png_bytepp image)
+png_write_image(png_structrp png_ptr, png_bytepp image)
{
png_uint_32 i; /* row index */
int pass, num_pass; /* pass variables */
@@ -632,10 +639,78 @@ png_write_image(png_structp png_ptr, png_bytepp image)
}
}
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Performs intrapixel differencing */
+static void
+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) != 0)
+ {
+ 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 /* WRITE_16BIT */
+ }
+}
+#endif /* MNG_FEATURES */
+
/* Called by user to write a row of image data */
void PNGAPI
-png_write_row(png_structp png_ptr, png_const_bytep row)
+png_write_row(png_structrp png_ptr, png_const_bytep row)
{
+ /* 1.5.6: moved from png_struct to be a local structure: */
+ png_row_info row_info;
+
if (png_ptr == NULL)
return;
@@ -646,44 +721,44 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
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))
+ if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
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)
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
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)
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
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)
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
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)
+ if ((png_ptr->transformations & PNG_PACK) != 0)
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)
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
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)
+ if ((png_ptr->transformations & PNG_BGR) != 0)
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)
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
#endif
@@ -692,12 +767,13 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced and not interested in row, return */
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
switch (png_ptr->pass)
{
case 0:
- if (png_ptr->row_number & 0x07)
+ if ((png_ptr->row_number & 0x07) != 0)
{
png_write_finish_row(png_ptr);
return;
@@ -705,7 +781,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 1:
- if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
+ if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5)
{
png_write_finish_row(png_ptr);
return;
@@ -721,7 +797,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 3:
- if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
+ if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3)
{
png_write_finish_row(png_ptr);
return;
@@ -737,7 +813,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 5:
- if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
+ if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2)
{
png_write_finish_row(png_ptr);
return;
@@ -745,7 +821,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 6:
- if (!(png_ptr->row_number & 0x01))
+ if ((png_ptr->row_number & 0x01) == 0)
{
png_write_finish_row(png_ptr);
return;
@@ -759,36 +835,31 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#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);
+ row_info.color_type = png_ptr->color_type;
+ row_info.width = png_ptr->usr_width;
+ row_info.channels = png_ptr->usr_channels;
+ row_info.bit_depth = png_ptr->usr_bit_depth;
+ row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels);
+ row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
- 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);
+ png_debug1(3, "row_info->color_type = %d", row_info.color_type);
+ png_debug1(3, "row_info->width = %u", row_info.width);
+ png_debug1(3, "row_info->channels = %d", row_info.channels);
+ png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth);
+ png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth);
+ png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)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);
+ memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Handle interlacing */
if (png_ptr->interlaced && png_ptr->pass < 6 &&
- (png_ptr->transformations & PNG_INTERLACE))
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
- png_do_write_interlace(&(png_ptr->row_info),
- png_ptr->row_buf + 1, png_ptr->pass);
+ png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
/* This should always get caught above, but still ... */
- if (!(png_ptr->row_info.width))
+ if (row_info.width == 0)
{
png_write_finish_row(png_ptr);
return;
@@ -798,10 +869,17 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
/* Handle other transformations */
- if (png_ptr->transformations)
- png_do_write_transformations(png_ptr);
+ if (png_ptr->transformations != 0)
+ png_do_write_transformations(png_ptr, &row_info);
#endif
+ /* At this point the row_info pixel depth must match the 'transformed' depth,
+ * which is also the output depth.
+ */
+ if (row_info.pixel_depth != png_ptr->pixel_depth ||
+ row_info.pixel_depth != png_ptr->transformed_pixel_depth)
+ png_error(png_ptr, "internal write transform logic error");
+
#ifdef PNG_MNG_FEATURES_SUPPORTED
/* Write filter_method 64 (intrapixel differencing) only if
* 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
@@ -812,16 +890,24 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
* 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) &&
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
{
/* Intrapixel differencing */
- png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1);
}
#endif
+/* Added at libpng-1.5.10 */
+#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Check for out-of-range palette index */
+ if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
+ png_do_check_palette_indexes(png_ptr, &row_info);
+#endif
+
/* Find a filter if necessary, filter the row and write it out. */
- png_write_find_filter(png_ptr, &(png_ptr->row_info));
+ png_write_find_filter(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);
@@ -830,7 +916,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#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_set_flush(png_structrp png_ptr, int nrows)
{
png_debug(1, "in png_set_flush");
@@ -842,10 +928,8 @@ png_set_flush(png_structp png_ptr, int nrows)
/* Flush the current output buffers now */
void PNGAPI
-png_write_flush(png_structp png_ptr)
+png_write_flush(png_structrp png_ptr)
{
- int wrote_IDAT;
-
png_debug(1, "in png_write_flush");
if (png_ptr == NULL)
@@ -855,146 +939,41 @@ png_write_flush(png_structp png_ptr)
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);
- 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_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
png_ptr->flush_rows = 0;
png_flush(png_ptr);
}
-#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+#endif /* WRITE_FLUSH */
-/* Free all memory used by the write */
-void PNGAPI
-png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */
+#endif
+
+/* Free any memory used in png_ptr struct without freeing the struct itself. */
+static void
+png_write_destroy(png_structrp png_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;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_error_ptr warning_fn;
-#endif
- 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 */
- if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
deflateEnd(&png_ptr->zstream);
/* Free our memory. png_free checks NULL for us. */
- png_free(png_ptr, png_ptr->zbuf);
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
png_free(png_ptr, png_ptr->row_buf);
+ png_ptr->row_buf = NULL;
#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);
+ png_ptr->prev_row = NULL;
+ png_ptr->sub_row = NULL;
+ png_ptr->up_row = NULL;
+ png_ptr->avg_row = NULL;
+ png_ptr->paeth_row = NULL;
#endif
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
@@ -1002,41 +981,51 @@ png_write_destroy(png_structp png_ptr)
png_reset_filter_heuristics(png_ptr);
png_free(png_ptr, png_ptr->filter_costs);
png_free(png_ptr, png_ptr->inv_filter_costs);
+ png_ptr->filter_costs = NULL;
+ png_ptr->inv_filter_costs = NULL;
#endif
-#ifdef PNG_SETJMP_SUPPORTED
- /* Reset structure */
- png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ png_free(png_ptr, png_ptr->chunk_list);
+ png_ptr->chunk_list = NULL;
#endif
- error_fn = png_ptr->error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- warning_fn = png_ptr->warning_fn;
-#endif
- error_ptr = png_ptr->error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- free_fn = png_ptr->free_fn;
-#endif
+ /* The error handling and memory handling information is left intact at this
+ * point: the jmp_buf may still have to be freed. See png_destroy_png_struct
+ * for how this happens.
+ */
+}
- png_memset(png_ptr, 0, png_sizeof(png_struct));
+/* Free all memory used by the write.
+ * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
+ * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free
+ * the passed in info_structs but it would quietly fail to free any of the data
+ * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it
+ * has no png_ptr.)
+ */
+void PNGAPI
+png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+{
+ png_debug(1, "in png_destroy_write_struct");
- png_ptr->error_fn = error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_ptr->warning_fn = warning_fn;
-#endif
- png_ptr->error_ptr = error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr->free_fn = free_fn;
-#endif
+ if (png_ptr_ptr != NULL)
+ {
+ png_structrp png_ptr = *png_ptr_ptr;
-#ifdef PNG_SETJMP_SUPPORTED
- png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf));
-#endif
+ if (png_ptr != NULL) /* added in libpng 1.6.0 */
+ {
+ png_destroy_info_struct(png_ptr, info_ptr_ptr);
+
+ *png_ptr_ptr = NULL;
+ png_write_destroy(png_ptr);
+ png_destroy_png_struct(png_ptr);
+ }
+ }
}
/* 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_set_filter(png_structrp png_ptr, int method, int filters)
{
png_debug(1, "in png_set_filter");
@@ -1044,7 +1033,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
return;
#ifdef PNG_MNG_FEATURES_SUPPORTED
- if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(method == PNG_INTRAPIXEL_DIFFERENCING))
method = PNG_FILTER_TYPE_BASE;
@@ -1056,8 +1045,9 @@ png_set_filter(png_structp png_ptr, int method, int filters)
#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 7: png_app_error(png_ptr, "Unknown row filter for method 0");
+ /* FALL THROUGH */
+#endif /* WRITE_FILTER */
case PNG_FILTER_VALUE_NONE:
png_ptr->do_filter = PNG_FILTER_NONE; break;
@@ -1078,8 +1068,8 @@ png_set_filter(png_structp png_ptr, int method, int filters)
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 */
+ png_app_error(png_ptr, "Unknown row filter for method 0");
+#endif /* WRITE_FILTER */
}
/* If we have allocated the row_buf, this means we have already started
@@ -1094,14 +1084,16 @@ png_set_filter(png_structp png_ptr, int method, int filters)
if (png_ptr->row_buf != NULL)
{
#ifdef PNG_WRITE_FILTER_SUPPORTED
- if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
+ if ((png_ptr->do_filter & PNG_FILTER_SUB) != 0 &&
+ 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->do_filter & PNG_FILTER_UP) != 0 &&
+ png_ptr->up_row == NULL)
{
if (png_ptr->prev_row == NULL)
{
@@ -1118,7 +1110,8 @@ png_set_filter(png_structp png_ptr, int method, int filters)
}
}
- if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
+ if ((png_ptr->do_filter & PNG_FILTER_AVG) != 0 &&
+ png_ptr->avg_row == NULL)
{
if (png_ptr->prev_row == NULL)
{
@@ -1135,7 +1128,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
}
}
- if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
+ if ((png_ptr->do_filter & PNG_FILTER_PAETH) != 0 &&
png_ptr->paeth_row == NULL)
{
if (png_ptr->prev_row == NULL)
@@ -1153,7 +1146,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
}
if (png_ptr->do_filter == PNG_NO_FILTERS)
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+#endif /* WRITE_FILTER */
png_ptr->do_filter = PNG_FILTER_NONE;
}
}
@@ -1171,7 +1164,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */
/* Convenience reset API. */
static void
-png_reset_filter_heuristics(png_structp png_ptr)
+png_reset_filter_heuristics(png_structrp 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
@@ -1204,7 +1197,7 @@ png_reset_filter_heuristics(png_structp png_ptr)
}
static int
-png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
+png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method,
int num_weights)
{
if (png_ptr == NULL)
@@ -1224,7 +1217,7 @@ png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
if (num_weights > 0)
{
png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_byte) * num_weights));
+ (png_uint_32)((sizeof (png_byte)) * num_weights));
/* To make sure that the weighting starts out fairly */
for (i = 0; i < num_weights; i++)
@@ -1233,10 +1226,10 @@ png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
}
png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
+ (png_uint_32)((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));
+ (png_uint_32)((sizeof (png_uint_16)) * num_weights));
for (i = 0; i < num_weights; i++)
{
@@ -1254,10 +1247,10 @@ png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
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_uint_32)((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));
+ (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
}
for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
@@ -1287,7 +1280,7 @@ png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
/* Provide floating and fixed point APIs */
#ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
+png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
int num_weights, png_const_doublep filter_weights,
png_const_doublep filter_costs)
{
@@ -1296,7 +1289,7 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
/* 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))
+ if (png_init_filter_heuristics(png_ptr, heuristic_method, num_weights) == 0)
return;
/* If using the weighted method copy in the weights. */
@@ -1342,7 +1335,7 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
#ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
-png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
+png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
int num_weights, png_const_fixed_point_p filter_weights,
png_const_fixed_point_p filter_costs)
{
@@ -1351,7 +1344,7 @@ png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
/* 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))
+ if (png_init_filter_heuristics(png_ptr, heuristic_method, num_weights) == 0)
return;
/* If using the weighted method copy in the weights. */
@@ -1405,40 +1398,40 @@ png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
}
}
#endif /* FIXED_POINT */
-#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+#endif /* WRITE_WEIGHTED_FILTER */
void PNGAPI
-png_set_compression_level(png_structp png_ptr, int level)
+png_set_compression_level(png_structrp 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_set_compression_mem_level(png_structrp 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_set_compression_strategy(png_structrp png_ptr, int strategy)
{
png_debug(1, "in png_set_compression_strategy");
if (png_ptr == NULL)
return;
+ /* The flag setting here prevents the libpng dynamic selection of strategy.
+ */
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
png_ptr->zlib_strategy = strategy;
}
@@ -1447,80 +1440,81 @@ png_set_compression_strategy(png_structp png_ptr, int strategy)
* smaller value of window_bits if it can do so safely.
*/
void PNGAPI
-png_set_compression_window_bits(png_structp png_ptr, int window_bits)
+png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
{
if (png_ptr == NULL)
return;
+ /* Prior to 1.6.0 this would warn but then set the window_bits value, this
+ * meant that negative window bits values could be selected which would cause
+ * libpng to write a non-standard PNG file with raw deflate or gzip
+ * compressed IDAT or ancillary chunks. Such files can be read and there is
+ * no warning on read, so this seems like a very bad idea.
+ */
if (window_bits > 15)
+ {
png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
+ window_bits = 15;
+ }
else if (window_bits < 8)
+ {
png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+ window_bits = 8;
+ }
-#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_set_compression_method(png_structrp png_ptr, int method)
{
png_debug(1, "in png_set_compression_method");
if (png_ptr == NULL)
return;
+ /* This would produce an invalid PNG file if it worked, but it doesn't and
+ * deflate will fault it, so it is harmless to just warn here.
+ */
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;
}
/* The following were added to libpng-1.5.4 */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
void PNGAPI
-png_set_text_compression_level(png_structp png_ptr, int level)
+png_set_text_compression_level(png_structrp png_ptr, int level)
{
png_debug(1, "in png_set_text_compression_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_LEVEL;
png_ptr->zlib_text_level = level;
}
void PNGAPI
-png_set_text_compression_mem_level(png_structp png_ptr, int mem_level)
+png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level)
{
png_debug(1, "in png_set_text_compression_mem_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL;
png_ptr->zlib_text_mem_level = mem_level;
}
void PNGAPI
-png_set_text_compression_strategy(png_structp png_ptr, int strategy)
+png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
{
png_debug(1, "in png_set_text_compression_strategy");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_STRATEGY;
png_ptr->zlib_text_strategy = strategy;
}
@@ -1528,32 +1522,28 @@ png_set_text_compression_strategy(png_structp png_ptr, int strategy)
* smaller value of window_bits if it can do so safely.
*/
void PNGAPI
-png_set_text_compression_window_bits(png_structp png_ptr, int window_bits)
+png_set_text_compression_window_bits(png_structrp 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");
+ window_bits = 15;
+ }
else if (window_bits < 8)
+ {
png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+ window_bits = 8;
+ }
-#ifndef WBITS_8_OK
- /* Avoid libpng bug with 256-byte windows */
- if (window_bits == 8)
- {
- png_warning(png_ptr, "Text compression window is being reset to 512");
- window_bits = 9;
- }
-
-#endif
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS;
png_ptr->zlib_text_window_bits = window_bits;
}
void PNGAPI
-png_set_text_compression_method(png_structp png_ptr, int method)
+png_set_text_compression_method(png_structrp png_ptr, int method)
{
png_debug(1, "in png_set_text_compression_method");
@@ -1563,14 +1553,13 @@ png_set_text_compression_method(png_structp png_ptr, int method)
if (method != 8)
png_warning(png_ptr, "Only compression method 8 is supported by PNG");
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_METHOD;
png_ptr->zlib_text_method = method;
}
-#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
+#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
/* end of API added to libpng-1.5.4 */
void PNGAPI
-png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
+png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
{
if (png_ptr == NULL)
return;
@@ -1580,7 +1569,7 @@ png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr 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
+png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
write_user_transform_fn)
{
png_debug(1, "in png_set_write_user_transform_fn");
@@ -1596,88 +1585,899 @@ png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_write_png(png_structp png_ptr, png_infop info_ptr,
+png_write_png(png_structrp png_ptr, png_inforp info_ptr,
int transforms, voidp params)
{
if (png_ptr == NULL || info_ptr == NULL)
return;
+ if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
+ {
+ png_app_error(png_ptr, "no rows for png_write_image to write");
+ 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)
+ if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
+#ifdef PNG_WRITE_INVERT_SUPPORTED
png_set_invert_mono(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
#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);
+ if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
#endif
-#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes */
- if (transforms & PNG_TRANSFORM_PACKING)
- png_set_packing(png_ptr);
+ if ((transforms & PNG_TRANSFORM_PACKING) != 0)
+#ifdef PNG_WRITE_PACK_SUPPORTED
+ png_set_packing(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
#endif
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
/* Swap location of alpha bytes from ARGB to RGBA */
- if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+ if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
png_set_swap_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
#endif
+ /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
+ * RGB, note that the code expects the input color type to be G or RGB; no
+ * alpha channel.
+ */
+ if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
+ PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0)
+ {
#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);
+ if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
+ {
+ if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
+ png_app_error(png_ptr,
+ "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
- else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
- png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+ /* Continue if ignored - this is the pre-1.6.10 behavior */
+ png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+ }
+
+ else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
#endif
+ }
-#ifdef PNG_WRITE_BGR_SUPPORTED
/* Flip BGR pixels to RGB */
- if (transforms & PNG_TRANSFORM_BGR)
+ if ((transforms & PNG_TRANSFORM_BGR) != 0)
+#ifdef PNG_WRITE_BGR_SUPPORTED
png_set_bgr(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
#endif
-#ifdef PNG_WRITE_SWAP_SUPPORTED
/* Swap bytes of 16-bit files to most significant byte first */
- if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+ if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
+#ifdef PNG_WRITE_SWAP_SUPPORTED
png_set_swap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
#endif
-#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
/* Swap bits of 1, 2, 4 bit packed pixel formats */
- if (transforms & PNG_TRANSFORM_PACKSWAP)
+ if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
png_set_packswap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
#endif
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel from opacity to transparency */
- if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+ if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
png_set_invert_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
#endif
/* ----------------------- end of transformations ------------------- */
/* Write the bits */
- if (info_ptr->valid & PNG_INFO_IDAT)
- png_write_image(png_ptr, info_ptr->row_pointers);
+ 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 */
+
+
+#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
+#ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
+/* Initialize the write structure - general purpose utility. */
+static int
+png_image_write_init(png_imagep image)
+{
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
+ png_safe_error, png_safe_warning);
+
+ if (png_ptr != NULL)
+ {
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr != NULL)
+ {
+ png_controlp control = png_voidcast(png_controlp,
+ png_malloc_warn(png_ptr, (sizeof *control)));
+
+ if (control != NULL)
+ {
+ memset(control, 0, (sizeof *control));
+
+ control->png_ptr = png_ptr;
+ control->info_ptr = info_ptr;
+ control->for_write = 1;
+
+ image->opaque = control;
+ return 1;
+ }
+
+ /* Error clean up */
+ png_destroy_info_struct(png_ptr, &info_ptr);
+ }
+
+ png_destroy_write_struct(&png_ptr, NULL);
+ }
+
+ return png_image_error(image, "png_image_write_: out of memory");
+}
+
+/* Arguments to png_image_write_main: */
+typedef struct
+{
+ /* Arguments: */
+ png_imagep image;
+ png_const_voidp buffer;
+ png_int_32 row_stride;
+ png_const_voidp colormap;
+ int convert_to_8bit;
+ /* Local variables: */
+ png_const_voidp first_row;
+ ptrdiff_t row_bytes;
+ png_voidp local_row;
+} png_image_write_control;
+
+/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
+ * do any necessary byte swapping. The component order is defined by the
+ * png_image format value.
+ */
+static int
+png_write_image_16bit(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+
+ png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
+ display->first_row);
+ png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
+ png_uint_16p row_end;
+ const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+ int aindex = 0;
+ png_uint_32 y = image->height;
+
+ if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ aindex = -1;
+ ++input_row; /* To point to the first component */
+ ++output_row;
+ }
+
+ else
+# endif
+ aindex = channels;
+ }
+
+ else
+ png_error(png_ptr, "png_write_image: internal call error");
+
+ /* Work out the output row end and count over this, note that the increment
+ * above to 'row' means that row_end can actually be beyond the end of the
+ * row; this is correct.
+ */
+ row_end = output_row + image->width * (channels+1);
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_uint_16p out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ const png_uint_16 alpha = in_ptr[aindex];
+ png_uint_32 reciprocal = 0;
+ int c;
+
+ out_ptr[aindex] = alpha;
+
+ /* Calculate a reciprocal. The correct calculation is simply
+ * component/alpha*65535 << 15. (I.e. 15 bits of precision); this
+ * allows correct rounding by adding .5 before the shift. 'reciprocal'
+ * is only initialized when required.
+ */
+ if (alpha > 0 && alpha < 65535)
+ reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
+
+ c = channels;
+ do /* always at least one channel */
+ {
+ png_uint_16 component = *in_ptr++;
+
+ /* The following gives 65535 for an alpha of 0, which is fine,
+ * otherwise if 0/0 is represented as some other value there is more
+ * likely to be a discontinuity which will probably damage
+ * compression when moving from a fully transparent area to a
+ * nearly transparent one. (The assumption here is that opaque
+ * areas tend not to be 0 intensity.)
+ */
+ if (component >= alpha)
+ component = 65535;
+
+ /* component 0 && alpha < 65535)
+ {
+ png_uint_32 calc = component * reciprocal;
+ calc += 16384; /* round to nearest */
+ component = (png_uint_16)(calc >> 15);
+ }
+
+ *out_ptr++ = component;
+ }
+ while (--c > 0);
+
+ /* Skip to next component (skip the intervening alpha channel) */
+ ++in_ptr;
+ ++out_ptr;
+ }
+
+ png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ }
+
+ return 1;
+}
+
+/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
+ * is present it must be removed from the components, the components are then
+ * written in sRGB encoding. No components are added or removed.
+ *
+ * Calculate an alpha reciprocal to reverse pre-multiplication. As above the
+ * calculation can be done to 15 bits of accuracy; however, the output needs to
+ * be scaled in the range 0..255*65535, so include that scaling here.
+ */
+#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
+
+static png_byte
+png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
+ png_uint_32 reciprocal/*from the above macro*/)
+{
+ /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
+ * is represented as some other value there is more likely to be a
+ * discontinuity which will probably damage compression when moving from a
+ * fully transparent area to a nearly transparent one. (The assumption here
+ * is that opaque areas tend not to be 0 intensity.)
+ *
+ * There is a rounding problem here; if alpha is less than 128 it will end up
+ * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the
+ * output change for this too.
+ */
+ if (component >= alpha || alpha < 128)
+ return 255;
+
+ /* component 0)
+ {
+ /* The test is that alpha/257 (rounded) is less than 255, the first value
+ * that becomes 255 is 65407.
+ * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
+ * be exact!) [Could also test reciprocal != 0]
+ */
+ if (alpha < 65407)
+ {
+ component *= reciprocal;
+ component += 64; /* round to nearest */
+ component >>= 7;
+ }
+
+ else
+ component *= 255;
+
+ /* Convert the component to sRGB. */
+ return (png_byte)PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ else
+ return 0;
+}
+
+static int
+png_write_image_8bit(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+
+ png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
+ display->first_row);
+ png_bytep output_row = png_voidcast(png_bytep, display->local_row);
+ png_uint_32 y = image->height;
+ const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+
+ if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ png_bytep row_end;
+ int aindex;
+
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ aindex = -1;
+ ++input_row; /* To point to the first component */
+ ++output_row;
+ }
+
+ else
+# endif
+ aindex = channels;
+
+ /* Use row_end in place of a loop counter: */
+ row_end = output_row + image->width * (channels+1);
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_bytep out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ png_uint_16 alpha = in_ptr[aindex];
+ png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
+ png_uint_32 reciprocal = 0;
+ int c;
+
+ /* Scale and write the alpha channel. */
+ out_ptr[aindex] = alphabyte;
+
+ if (alphabyte > 0 && alphabyte < 255)
+ reciprocal = UNP_RECIPROCAL(alpha);
+
+ c = channels;
+ do /* always at least one channel */
+ *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
+ while (--c > 0);
+
+ /* Skip to next component (skip the intervening alpha channel) */
+ ++in_ptr;
+ ++out_ptr;
+ } /* while out_ptr < row_end */
+
+ png_write_row(png_ptr, png_voidcast(png_const_bytep,
+ display->local_row));
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ } /* while y */
+ }
+
+ else
+ {
+ /* No alpha channel, so the row_end really is the end of the row and it
+ * is sufficient to loop over the components one by one.
+ */
+ png_bytep row_end = output_row + image->width * channels;
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_bytep out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ png_uint_32 component = *in_ptr++;
+
+ component *= 255;
+ *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ png_write_row(png_ptr, output_row);
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ }
+ }
+
+ return 1;
+}
+
+static void
+png_image_set_PLTE(png_image_write_control *display)
+{
+ const png_imagep image = display->image;
+ const void *cmap = display->colormap;
+ const int entries = image->colormap_entries > 256 ? 256 :
+ (int)image->colormap_entries;
+
+ /* NOTE: the caller must check for cmap != NULL and entries != 0 */
+ const png_uint_32 format = image->format;
+ const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
+
+# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
+ defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
+ const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ (format & PNG_FORMAT_FLAG_ALPHA) != 0;
+# else
+# define afirst 0
+# endif
+
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+# else
+# define bgr 0
+# endif
+
+ int i, num_trans;
+ png_color palette[256];
+ png_byte tRNS[256];
+
+ memset(tRNS, 255, (sizeof tRNS));
+ memset(palette, 0, (sizeof palette));
+
+ for (i=num_trans=0; i= 3) /* RGB */
+ {
+ palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[(2 ^ bgr)]);
+ palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[1]);
+ palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[bgr]);
+ }
+
+ else /* Gray */
+ palette[i].blue = palette[i].red = palette[i].green =
+ (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
+ }
+
+ else /* alpha */
+ {
+ png_uint_16 alpha = entry[afirst ? 0 : channels-1];
+ png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
+ png_uint_32 reciprocal = 0;
+
+ /* Calculate a reciprocal, as in the png_write_image_8bit code above
+ * this is designed to produce a value scaled to 255*65535 when
+ * divided by 128 (i.e. asr 7).
+ */
+ if (alphabyte > 0 && alphabyte < 255)
+ reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
+
+ tRNS[i] = alphabyte;
+ if (alphabyte < 255)
+ num_trans = i+1;
+
+ if (channels >= 3) /* RGB */
+ {
+ palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
+ alpha, reciprocal);
+ palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
+ reciprocal);
+ palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
+ reciprocal);
+ }
+
+ else /* gray */
+ palette[i].blue = palette[i].red = palette[i].green =
+ png_unpremultiply(entry[afirst], alpha, reciprocal);
+ }
+ }
+
+ else /* Color-map has sRGB values */
+ {
+ png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
+
+ entry += i * channels;
+
+ switch (channels)
+ {
+ case 4:
+ tRNS[i] = entry[afirst ? 0 : 3];
+ if (tRNS[i] < 255)
+ num_trans = i+1;
+ /* FALL THROUGH */
+ case 3:
+ palette[i].blue = entry[afirst + (2 ^ bgr)];
+ palette[i].green = entry[afirst + 1];
+ palette[i].red = entry[afirst + bgr];
+ break;
+
+ case 2:
+ tRNS[i] = entry[1 ^ afirst];
+ if (tRNS[i] < 255)
+ num_trans = i+1;
+ /* FALL THROUGH */
+ case 1:
+ palette[i].blue = palette[i].red = palette[i].green =
+ entry[afirst];
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+# ifdef afirst
+# undef afirst
+# endif
+# ifdef bgr
+# undef bgr
+# endif
+
+ png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
+ entries);
+
+ if (num_trans > 0)
+ png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
+ num_trans, NULL);
+
+ image->colormap_entries = entries;
+}
+
+static int
+png_image_write_main(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+ png_uint_32 format = image->format;
+
+ /* The following four ints are actually booleans */
+ int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
+ int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
+ int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
+ int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
+
+# ifdef PNG_BENIGN_ERRORS_SUPPORTED
+ /* Make sure we error out on any bad situation */
+ png_set_benign_errors(png_ptr, 0/*error*/);
+# endif
+
+ /* Default the 'row_stride' parameter if required. */
+ if (display->row_stride == 0)
+ display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+
+ /* Set the required transforms then write the rows in the correct order. */
+ if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+ {
+ if (display->colormap != NULL && image->colormap_entries > 0)
+ {
+ png_uint_32 entries = image->colormap_entries;
+
+ png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
+ entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
+ PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_image_set_PLTE(display);
+ }
+
+ else
+ png_error(image->opaque->png_ptr,
+ "no color-map for color-mapped image");
+ }
+
+ else
+ png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
+ write_16bit ? 16 : 8,
+ ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
+ ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ /* Counter-intuitively the data transformations must be called *after*
+ * png_write_info, not before as in the read code, but the 'set' functions
+ * must still be called before. Just set the color space information, never
+ * write an interlaced image.
+ */
+
+ if (write_16bit != 0)
+ {
+ /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
+ png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
+
+ if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
+ png_set_cHRM_fixed(png_ptr, info_ptr,
+ /* color x y */
+ /* white */ 31270, 32900,
+ /* red */ 64000, 33000,
+ /* green */ 30000, 60000,
+ /* blue */ 15000, 6000
+ );
+ }
+
+ else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
+ png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
+
+ /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
+ * space must still be gamma encoded.
+ */
+ else
+ png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
+
+ /* Write the file header. */
+ png_write_info(png_ptr, info_ptr);
+
+ /* Now set up the data transformations (*after* the header is written),
+ * remove the handled transformations from the 'format' flags for checking.
+ *
+ * First check for a little endian system if writing 16 bit files.
+ */
+ if (write_16bit != 0)
+ {
+ PNG_CONST png_uint_16 le = 0x0001;
+
+ if ((*(png_const_bytep) & le) != 0)
+ png_set_swap(png_ptr);
+ }
+
+# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_BGR) != 0)
+ {
+ if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
+ png_set_bgr(png_ptr);
+ format &= ~PNG_FORMAT_FLAG_BGR;
+ }
+# endif
+
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ png_set_swap_alpha(png_ptr);
+ format &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
+# endif
+
+ /* If there are 16 or fewer color-map entries we wrote a lower bit depth
+ * above, but the application data is still byte packed.
+ */
+ if (colormap != 0 && image->colormap_entries <= 16)
+ png_set_packing(png_ptr);
+
+ /* That should have handled all (both) the transforms. */
+ if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
+ PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
+ png_error(png_ptr, "png_write_image: unsupported transformation");
+
+ {
+ png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
+ ptrdiff_t row_bytes = display->row_stride;
+
+ if (linear != 0)
+ row_bytes *= (sizeof (png_uint_16));
+
+ if (row_bytes < 0)
+ row += (image->height-1) * (-row_bytes);
+
+ display->first_row = row;
+ display->row_bytes = row_bytes;
+ }
+
+ /* Apply 'fast' options if the flag is set. */
+ if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
+ {
+ png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
+ /* NOTE: determined by experiment using pngstest, this reflects some
+ * balance between the time to write the image once and the time to read
+ * it about 50 times. The speed-up in pngstest was about 10-20% of the
+ * total (user) time on a heavily loaded system.
+ */
+ png_set_compression_level(png_ptr, 3);
+ }
+
+ /* Check for the cases that currently require a pre-transform on the row
+ * before it is written. This only applies when the input is 16-bit and
+ * either there is an alpha channel or it is converted to 8-bit.
+ */
+ if ((linear != 0 && alpha != 0 ) ||
+ (colormap == 0 && display->convert_to_8bit != 0))
+ {
+ png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
+ png_get_rowbytes(png_ptr, info_ptr)));
+ int result;
+
+ display->local_row = row;
+ if (write_16bit != 0)
+ result = png_safe_execute(image, png_write_image_16bit, display);
+ else
+ result = png_safe_execute(image, png_write_image_8bit, display);
+ display->local_row = NULL;
+
+ png_free(png_ptr, row);
+
+ /* Skip the 'write_end' on error: */
+ if (result == 0)
+ return 0;
+ }
+
+ /* Otherwise this is the case where the input is in a format currently
+ * supported by the rest of the libpng write code; call it directly.
+ */
+ else
+ {
+ png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
+ ptrdiff_t row_bytes = display->row_bytes;
+ png_uint_32 y = image->height;
+
+ while (y-- > 0)
+ {
+ png_write_row(png_ptr, row);
+ row += row_bytes;
+ }
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ return 1;
+}
+
+int PNGAPI
+png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
+ const void *buffer, png_int_32 row_stride, const void *colormap)
+{
+ /* Write the image to the given (FILE*). */
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file != NULL)
+ {
+ if (png_image_write_init(image) != 0)
+ {
+ png_image_write_control display;
+ int result;
+
+ /* This is slightly evil, but png_init_io doesn't do anything other
+ * than this and we haven't changed the standard IO functions so
+ * this saves a 'safe' function.
+ */
+ image->opaque->png_ptr->io_ptr = file;
+
+ memset(&display, 0, (sizeof display));
+ display.image = image;
+ display.buffer = buffer;
+ display.row_stride = row_stride;
+ display.colormap = colormap;
+ display.convert_to_8bit = convert_to_8bit;
+
+ result = png_safe_execute(image, png_image_write_main, &display);
+ png_image_free(image);
+ return result;
+ }
+
+ else
+ return 0;
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_write_to_stdio: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
+
+ else
+ return 0;
+}
+
+int PNGAPI
+png_image_write_to_file(png_imagep image, const char *file_name,
+ int convert_to_8bit, const void *buffer, png_int_32 row_stride,
+ const void *colormap)
+{
+ /* Write the image to the named file. */
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file_name != NULL)
+ {
+ FILE *fp = fopen(file_name, "wb");
+
+ if (fp != NULL)
+ {
+ if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
+ row_stride, colormap) != 0)
+ {
+ int error; /* from fflush/fclose */
+
+ /* Make sure the file is flushed correctly. */
+ if (fflush(fp) == 0 && ferror(fp) == 0)
+ {
+ if (fclose(fp) == 0)
+ return 1;
+
+ error = errno; /* from fclose */
+ }
+
+ else
+ {
+ error = errno; /* from fflush or ferror */
+ (void)fclose(fp);
+ }
+
+ (void)remove(file_name);
+ /* The image has already been cleaned up; this is just used to
+ * set the error (because the original write succeeded).
+ */
+ return png_image_error(image, strerror(error));
+ }
+
+ else
+ {
+ /* Clean up: just the opened file. */
+ (void)fclose(fp);
+ (void)remove(file_name);
+ return 0;
+ }
+ }
+
+ else
+ return png_image_error(image, strerror(errno));
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_write_to_file: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
+
+ else
+ return 0;
+}
+#endif /* STDIO */
+#endif /* SIMPLIFIED_WRITE */
+#endif /* WRITE */
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwtran.c b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwtran.c
index 579057dcefd..ef015aeb7b9 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwtran.c
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwtran.c
@@ -29,8 +29,8 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -42,90 +42,14 @@
#include "pngpriv.h"
#ifdef PNG_WRITE_SUPPORTED
-
#ifdef PNG_WRITE_TRANSFORMS_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_channel(&(png_ptr->row_info), png_ptr->row_buf + 1,
- !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
-#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 */
+static void
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
{
png_debug(1, "in png_do_pack");
@@ -270,7 +194,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
* would pass 3 as bit_depth, and this routine would translate the
* data to 0 to 15.
*/
-void /* PRIVATE */
+static void
png_do_shift(png_row_infop row_info, png_bytep row,
png_const_color_8p bit_depth)
{
@@ -281,7 +205,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
int shift_start[4], shift_dec[4];
int channels = 0;
- if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+ if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
shift_start[channels] = row_info->bit_depth - bit_depth->red;
shift_dec[channels] = bit_depth->red;
@@ -303,7 +227,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
channels++;
}
- if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
shift_dec[channels] = bit_depth->alpha;
@@ -315,7 +239,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
{
png_bytep bp = row;
png_size_t i;
- png_byte mask;
+ unsigned int mask;
png_size_t row_bytes = row_info->rowbytes;
if (bit_depth->gray == 1 && row_info->bit_depth == 2)
@@ -329,20 +253,22 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (i = 0; i < row_bytes; i++, bp++)
{
- png_uint_16 v;
int j;
+ unsigned int v, out;
v = *bp;
- *bp = 0;
+ out = 0;
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
{
if (j > 0)
- *bp |= (png_byte)((v << j) & 0xff);
+ out |= v << j;
else
- *bp |= (png_byte)((v >> (-j)) & mask);
+ out |= (v >> (-j)) & mask;
}
+
+ *bp = (png_byte)(out & 0xff);
}
}
@@ -355,21 +281,23 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (i = 0; i < istop; i++, bp++)
{
- png_uint_16 v;
+ const unsigned int c = i%channels;
int j;
- int c = (int)(i%channels);
+ unsigned int v, out;
v = *bp;
- *bp = 0;
+ out = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
- *bp |= (png_byte)((v << j) & 0xff);
+ out |= v << j;
else
- *bp |= (png_byte)((v >> (-j)) & 0xff);
+ out |= v >> (-j);
}
+
+ *bp = (png_byte)(out & 0xff);
}
}
@@ -381,22 +309,22 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (bp = row, i = 0; i < istop; i++)
{
- int c = (int)(i%channels);
- png_uint_16 value, v;
+ const unsigned int c = i%channels;
int j;
+ unsigned int value, v;
- v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
+ v = png_get_uint_16(bp);
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);
+ value |= v << j;
else
- value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
+ value |= v >> (-j);
}
- *bp++ = (png_byte)(value >> 8);
+ *bp++ = (png_byte)((value >> 8) & 0xff);
*bp++ = (png_byte)(value & 0xff);
}
}
@@ -405,7 +333,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_swap_alpha");
@@ -453,7 +381,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save[1];
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
@@ -492,14 +420,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save[1];
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
}
}
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_invert_alpha");
@@ -549,7 +477,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)(255 - *(sp++));
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
@@ -587,75 +515,88 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)(255 - *(sp++));
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
}
}
#endif
-#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing */
+/* Transform the data according to the user's wishes. The order of
+ * transformations is significant.
+ */
void /* PRIVATE */
-png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
{
- png_debug(1, "in png_do_write_intrapixel");
+ png_debug(1, "in png_do_write_transformations");
- 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 (png_ptr == NULL)
+ return;
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 3;
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
+ if (png_ptr->write_user_transform_fn != NULL)
+ (*(png_ptr->write_user_transform_fn)) /* User write transform
+ function */
+ (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
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 4;
+#ifdef PNG_WRITE_FILLER_SUPPORTED
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
+#endif
- else
- return;
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ png_do_packswap(row_info, png_ptr->row_buf + 1);
+#endif
- 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_PACK_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACK) != 0)
+ png_do_pack(row_info, png_ptr->row_buf + 1,
+ (png_uint_32)png_ptr->bit_depth);
+#endif
-#ifdef PNG_WRITE_16BIT_SUPPORTED
- else if (row_info->bit_depth == 16)
- {
- png_bytep rp;
- png_uint_32 i;
+#ifdef PNG_WRITE_SWAP_SUPPORTED
+# ifdef PNG_16BIT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
+ png_do_swap(row_info, png_ptr->row_buf + 1);
+# endif
+#endif
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 6;
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
+ png_do_shift(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->shift));
+#endif
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 8;
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
+ png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
+#endif
- else
- return;
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
+ png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
+#endif
- 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 */
- }
+#ifdef PNG_WRITE_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ png_do_bgr(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_WRITE_INVERT_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
+ png_do_invert(row_info, png_ptr->row_buf + 1);
+#endif
}
-#endif /* PNG_MNG_FEATURES_SUPPORTED */
-#endif /* PNG_WRITE_SUPPORTED */
+#endif /* WRITE_TRANSFORMS */
+#endif /* WRITE */
diff --git a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwutil.c b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwutil.c
index 91634671e7c..66a8812d790 100644
--- a/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwutil.c
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/libpng/pngwutil.c
@@ -29,8 +29,8 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.5.4 [July 7, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 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.)
*
@@ -57,23 +57,6 @@ png_save_uint_32(png_bytep buf, png_uint_32 i)
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.
@@ -93,7 +76,7 @@ png_save_uint_16(png_bytep buf, unsigned int i)
* bytes have already been written.
*/
void PNGAPI
-png_write_sig(png_structp png_ptr)
+png_write_sig(png_structrp png_ptr)
{
png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
@@ -110,39 +93,20 @@ png_write_sig(png_structp png_ptr)
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,
+static void
+png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
png_uint_32 length)
{
png_byte buf[8];
- png_debug2(0, "Writing %s chunk, length = %lu", chunk_name,
- (unsigned long)length);
+#if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
+ PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
+ png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
+#endif
if (png_ptr == NULL)
return;
@@ -156,16 +120,16 @@ png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_name,
/* 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);
+ png_save_uint_32(buf + 4, chunk_name);
+ png_write_data(png_ptr, buf, 8);
/* Put the chunk name into png_ptr->chunk_name */
- png_memcpy(png_ptr->chunk_name, chunk_name, 4);
+ png_ptr->chunk_name = chunk_name;
/* Reset the crc and run it over the chunk name */
png_reset_crc(png_ptr);
- png_calculate_crc(png_ptr, chunk_name, 4);
+ png_calculate_crc(png_ptr, buf + 4, 4);
#ifdef PNG_IO_STATE_SUPPORTED
/* Inform the I/O callback that chunk data will (possibly) be written.
@@ -175,13 +139,20 @@ png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_name,
#endif
}
-/* Write the data of a PNG chunk started with png_write_chunk_start().
+void PNGAPI
+png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
+ png_uint_32 length)
+{
+ png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
+}
+
+/* Write the data of a PNG chunk started with png_write_chunk_header().
* 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().
+ * given to png_write_chunk_header().
*/
void PNGAPI
-png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
+png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
png_size_t length)
{
/* Write the data, and run the CRC over it */
@@ -193,15 +164,15 @@ png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
png_write_data(png_ptr, data, length);
/* Update the CRC after writing the data,
- * in case that the user I/O routine alters it.
+ * in case the user I/O routine alters it.
*/
png_calculate_crc(png_ptr, data, length);
}
}
-/* Finish a chunk started with png_write_chunk_start(). */
+/* Finish a chunk started with png_write_chunk_header(). */
void PNGAPI
-png_write_chunk_end(png_structp png_ptr)
+png_write_chunk_end(png_structrp png_ptr)
{
png_byte buf[4];
@@ -220,468 +191,601 @@ png_write_chunk_end(png_structp png_ptr)
png_write_data(png_ptr, buf, (png_size_t)4);
}
-/* Initialize the compressor for the appropriate type of compression. */
-static void
-png_zlib_claim(png_structp png_ptr, png_uint_32 state)
-{
- if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE))
- {
- /* If already initialized for 'state' do not re-init. */
- if (png_ptr->zlib_state != state)
- {
- int ret = Z_OK;
- png_const_charp who = "-";
-
- /* If actually initialized for another state do a deflateEnd. */
- if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
- {
- ret = deflateEnd(&png_ptr->zstream);
- who = "end";
- png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
- }
-
- /* zlib itself detects an incomplete state on deflateEnd */
- if (ret == Z_OK) switch (state)
- {
-# ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
- case PNG_ZLIB_FOR_TEXT:
- ret = deflateInit2(&png_ptr->zstream,
- png_ptr->zlib_text_level, png_ptr->zlib_text_method,
- png_ptr->zlib_text_window_bits,
- png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy);
- who = "text";
- break;
-# endif
-
- case PNG_ZLIB_FOR_IDAT:
- 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);
- who = "IDAT";
- break;
-
- default:
- png_error(png_ptr, "invalid zlib state");
- }
-
- if (ret == Z_OK)
- png_ptr->zlib_state = state;
-
- else /* an error in deflateEnd or deflateInit2 */
- {
- size_t pos = 0;
- char msg[64];
-
- pos = png_safecat(msg, sizeof msg, pos,
- "zlib failed to initialize compressor (");
- pos = png_safecat(msg, sizeof msg, pos, who);
-
- switch (ret)
- {
- case Z_VERSION_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") version error");
- break;
-
- case Z_STREAM_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") stream error");
- break;
-
- case Z_MEM_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") memory error");
- break;
-
- default:
- pos = png_safecat(msg, sizeof msg, pos, ") unknown error");
- break;
- }
-
- png_error(png_ptr, msg);
- }
- }
-
- /* Here on success, claim the zstream: */
- png_ptr->zlib_state |= PNG_ZLIB_IN_USE;
- }
-
- else
- png_error(png_ptr, "zstream already in use (internal error)");
-}
-
-/* The opposite: release the stream. It is also reset, this API will warn on
- * error but will not fail.
+/* 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.
*/
static void
-png_zlib_release(png_structp png_ptr)
+png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
+ png_const_bytep data, png_size_t length)
{
- if (png_ptr->zlib_state & PNG_ZLIB_IN_USE)
+ if (png_ptr == NULL)
+ return;
+
+ /* On 64 bit architectures 'length' may not fit in a png_uint_32. */
+ if (length > PNG_UINT_31_MAX)
+ png_error(png_ptr, "length exceeds PNG maximum");
+
+ png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
+ png_write_chunk_data(png_ptr, data, length);
+ png_write_chunk_end(png_ptr);
+}
+
+/* This is the API that calls the internal function above. */
+void PNGAPI
+png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
+ png_const_bytep data, png_size_t length)
+{
+ png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
+ length);
+}
+
+/* This is used below to find the size of an image to pass to png_deflate_claim,
+ * so it only needs to be accurate if the size is less than 16384 bytes (the
+ * point at which a lower LZ window size can be used.)
+ */
+static png_alloc_size_t
+png_image_size(png_structrp png_ptr)
+{
+ /* Only return sizes up to the maximum of a png_uint_32; do this by limiting
+ * the width and height used to 15 bits.
+ */
+ png_uint_32 h = png_ptr->height;
+
+ if (png_ptr->rowbytes < 32768 && h < 32768)
{
- int ret = deflateReset(&png_ptr->zstream);
-
- png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE;
-
- if (ret != Z_OK)
+ if (png_ptr->interlaced != 0)
{
- png_const_charp err;
- PNG_WARNING_PARAMETERS(p)
+ /* Interlacing makes the image larger because of the replication of
+ * both the filter byte and the padding to a byte boundary.
+ */
+ png_uint_32 w = png_ptr->width;
+ unsigned int pd = png_ptr->pixel_depth;
+ png_alloc_size_t cb_base;
+ int pass;
- switch (ret)
+ for (cb_base=0, pass=0; pass<=6; ++pass)
{
- case Z_VERSION_ERROR:
- err = "version";
- break;
+ png_uint_32 pw = PNG_PASS_COLS(w, pass);
- case Z_STREAM_ERROR:
- err = "stream";
- break;
-
- case Z_MEM_ERROR:
- err = "memory";
- break;
-
- default:
- err = "unknown";
- break;
+ if (pw > 0)
+ cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
}
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret);
- png_warning_parameter(p, 2, err);
-
- if (png_ptr->zstream.msg)
- err = png_ptr->zstream.msg;
- else
- err = "[no zlib message]";
-
- png_warning_parameter(p, 3, err);
-
- png_formatted_warning(png_ptr, p,
- "zlib failed to reset compressor: @1(@2): @3");
+ return cb_base;
}
+
+ else
+ return (png_ptr->rowbytes+1) * h;
}
else
- png_warning(png_ptr, "zstream not in use (internal error)");
+ return 0xffffffffU;
+}
+
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ /* This is the code to hack the first two bytes of the deflate stream (the
+ * deflate header) to correct the windowBits value to match the actual data
+ * size. Note that the second argument is the *uncompressed* size but the
+ * first argument is the *compressed* data (and it must be deflate
+ * compressed.)
+ */
+static void
+optimize_cmf(png_bytep data, png_alloc_size_t data_size)
+{
+ /* Optimize the CMF field in the zlib stream. The resultant zlib stream is
+ * still compliant to the stream specification.
+ */
+ if (data_size <= 16384) /* else windowBits must be 15 */
+ {
+ unsigned int z_cmf = data[0]; /* zlib compression method and flags */
+
+ if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
+ {
+ unsigned int z_cinfo;
+ unsigned int half_z_window_size;
+
+ z_cinfo = z_cmf >> 4;
+ half_z_window_size = 1U << (z_cinfo + 7);
+
+ if (data_size <= half_z_window_size) /* else no change */
+ {
+ unsigned int tmp;
+
+ do
+ {
+ half_z_window_size >>= 1;
+ --z_cinfo;
+ }
+ while (z_cinfo > 0 && data_size <= half_z_window_size);
+
+ z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
+
+ data[0] = (png_byte)z_cmf;
+ tmp = data[1] & 0xe0;
+ tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
+ data[1] = (png_byte)tmp;
+ }
+ }
+ }
+}
+#endif /* WRITE_OPTIMIZE_CMF */
+
+/* Initialize the compressor for the appropriate type of compression. */
+static int
+png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
+ png_alloc_size_t data_size)
+{
+ if (png_ptr->zowner != 0)
+ {
+#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
+ char msg[64];
+
+ PNG_STRING_FROM_CHUNK(msg, owner);
+ msg[4] = ':';
+ msg[5] = ' ';
+ PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner);
+ /* So the message that results is " using zstream"; this is an
+ * internal error, but is very useful for debugging. i18n requirements
+ * are minimal.
+ */
+ (void)png_safecat(msg, (sizeof msg), 10, " using zstream");
+#endif
+#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
+ png_warning(png_ptr, msg);
+
+ /* Attempt sane error recovery */
+ if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */
+ {
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT");
+ return Z_STREAM_ERROR;
+ }
+
+ png_ptr->zowner = 0;
+#else
+ png_error(png_ptr, msg);
+#endif
+ }
+
+ {
+ int level = png_ptr->zlib_level;
+ int method = png_ptr->zlib_method;
+ int windowBits = png_ptr->zlib_window_bits;
+ int memLevel = png_ptr->zlib_mem_level;
+ int strategy; /* set below */
+ int ret; /* zlib return code */
+
+ if (owner == png_IDAT)
+ {
+ if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0)
+ strategy = png_ptr->zlib_strategy;
+
+ else if (png_ptr->do_filter != PNG_FILTER_NONE)
+ strategy = PNG_Z_DEFAULT_STRATEGY;
+
+ else
+ strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
+ }
+
+ else
+ {
+#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
+ level = png_ptr->zlib_text_level;
+ method = png_ptr->zlib_text_method;
+ windowBits = png_ptr->zlib_text_window_bits;
+ memLevel = png_ptr->zlib_text_mem_level;
+ strategy = png_ptr->zlib_text_strategy;
+#else
+ /* If customization is not supported the values all come from the
+ * IDAT values except for the strategy, which is fixed to the
+ * default. (This is the pre-1.6.0 behavior too, although it was
+ * implemented in a very different way.)
+ */
+ strategy = Z_DEFAULT_STRATEGY;
+#endif
+ }
+
+ /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
+ * happening just pass 32768 as the data_size parameter. Notice that zlib
+ * requires an extra 262 bytes in the window in addition to the data to be
+ * able to see the whole of the data, so if data_size+262 takes us to the
+ * next windowBits size we need to fix up the value later. (Because even
+ * though deflate needs the extra window, inflate does not!)
+ */
+ if (data_size <= 16384)
+ {
+ /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
+ * work round a Microsoft Visual C misbehavior which, contrary to C-90,
+ * widens the result of the following shift to 64-bits if (and,
+ * apparently, only if) it is used in a test.
+ */
+ unsigned int half_window_size = 1U << (windowBits-1);
+
+ while (data_size + 262 <= half_window_size)
+ {
+ half_window_size >>= 1;
+ --windowBits;
+ }
+ }
+
+ /* Check against the previous initialized values, if any. */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 &&
+ (png_ptr->zlib_set_level != level ||
+ png_ptr->zlib_set_method != method ||
+ png_ptr->zlib_set_window_bits != windowBits ||
+ png_ptr->zlib_set_mem_level != memLevel ||
+ png_ptr->zlib_set_strategy != strategy))
+ {
+ if (deflateEnd(&png_ptr->zstream) != Z_OK)
+ png_warning(png_ptr, "deflateEnd failed (ignored)");
+
+ png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
+ }
+
+ /* For safety clear out the input and output pointers (currently zlib
+ * doesn't use them on Init, but it might in the future).
+ */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->zstream.avail_out = 0;
+
+ /* Now initialize if required, setting the new parameters, otherwise just
+ * to a simple reset to the previous parameters.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
+ ret = deflateReset(&png_ptr->zstream);
+
+ else
+ {
+ ret = deflateInit2(&png_ptr->zstream, level, method, windowBits,
+ memLevel, strategy);
+
+ if (ret == Z_OK)
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
+ }
+
+ /* The return code is from either deflateReset or deflateInit2; they have
+ * pretty much the same set of error codes.
+ */
+ if (ret == Z_OK)
+ png_ptr->zowner = owner;
+
+ else
+ png_zstream_error(png_ptr, ret);
+
+ return ret;
+ }
+}
+
+/* Clean up (or trim) a linked list of compression buffers. */
+void /* PRIVATE */
+png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
+{
+ png_compression_bufferp list = *listp;
+
+ if (list != NULL)
+ {
+ *listp = NULL;
+
+ do
+ {
+ png_compression_bufferp next = list->next;
+
+ png_free(png_ptr, list);
+ list = next;
+ }
+ while (list != NULL);
+ }
}
#ifdef PNG_WRITE_COMPRESSED_TEXT_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.
+ * set up by the caller to allow access to the relevant local variables.
+ *
+ * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
+ * temporary buffers. From 1.6.0 it is retained in png_struct so that it will
+ * be correctly freed in the event of a write error (previous implementations
+ * just leaked memory.)
*/
-
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 */
+ png_const_bytep input; /* The uncompressed input data */
+ png_alloc_size_t input_len; /* Its length */
+ png_uint_32 output_len; /* Final compressed length */
+ png_byte output[1024]; /* First block of 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)
+static void
+png_text_compress_init(compression_state *comp, png_const_bytep input,
+ png_alloc_size_t input_len)
+{
+ comp->input = input;
+ comp->input_len = input_len;
+ comp->output_len = 0;
+}
+
+/* Compress the data in the compression state input */
+static int
+png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
+ compression_state *comp, png_uint_32 prefix_len)
{
int ret;
- comp->num_output_ptr = 0;
- comp->max_output_ptr = 0;
- comp->output_ptr = NULL;
- comp->input = NULL;
- comp->input_len = text_len;
-
- /* We may just want to pass the text right through */
- if (compression == PNG_TEXT_COMPRESSION_NONE)
- {
- comp->input = (png_const_bytep)text;
- return((int)text_len);
- }
-
- if (compression >= PNG_TEXT_COMPRESSION_LAST)
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d,
- compression);
- png_formatted_warning(png_ptr, p, "Unknown compression type @1");
- }
-
- /* 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.
+ /* To find the length of the output it is necessary to first compress the
+ * input. The result is buffered rather than using the two-pass algorithm
+ * that is used on the inflate side; deflate is assumed to be slower and a
+ * PNG writer is assumed to have more memory available than a PNG reader.
*
- * 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).
+ * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
+ * upper limit on the output size, but it is always bigger than the input
+ * size so it is likely to be more efficient to use this linked-list
+ * approach.
*/
- png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT);
+ ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
- /* Set up the compression buffers */
- /* TODO: the following cast hides a potential overflow problem. */
- png_ptr->zstream.avail_in = (uInt)text_len;
+ if (ret != Z_OK)
+ return ret;
- /* 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
+ /* Set up the compression buffers, we need a loop here to avoid overflowing a
+ * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited
+ * by the output buffer size, so there is no need to check that. Since this
+ * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
+ * in size.
+ */
{
- /* Compress the data */
- ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+ png_compression_bufferp *end = &png_ptr->zbuffer_list;
+ png_alloc_size_t input_len = comp->input_len; /* may be zero! */
+ png_uint_32 output_len;
- if (ret != Z_OK)
+ /* zlib updates these for us: */
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
+ png_ptr->zstream.avail_in = 0; /* Set below */
+ png_ptr->zstream.next_out = comp->output;
+ png_ptr->zstream.avail_out = (sizeof comp->output);
+
+ output_len = png_ptr->zstream.avail_out;
+
+ do
{
- /* Error */
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
+ uInt avail_in = ZLIB_IO_MAX;
- else
- png_error(png_ptr, "zlib error");
- }
+ if (avail_in > input_len)
+ avail_in = (uInt)input_len;
- /* 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)
+ input_len -= avail_in;
+
+ png_ptr->zstream.avail_in = avail_in;
+
+ if (png_ptr->zstream.avail_out == 0)
{
- int old_max;
+ png_compression_buffer *next;
- old_max = comp->max_output_ptr;
- comp->max_output_ptr = comp->num_output_ptr + 4;
- if (comp->output_ptr != NULL)
+ /* Chunk data is limited to 2^31 bytes in length, so the prefix
+ * length must be counted here.
+ */
+ if (output_len + prefix_len > PNG_UINT_31_MAX)
{
- 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);
+ ret = Z_MEM_ERROR;
+ break;
}
- 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)
+ /* Need a new (malloc'ed) buffer, but there may be one present
+ * already.
+ */
+ next = *end;
+ if (next == NULL)
{
- int old_max;
+ next = png_voidcast(png_compression_bufferp, png_malloc_base
+ (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
- old_max = comp->max_output_ptr;
- comp->max_output_ptr = comp->num_output_ptr + 4;
- if (comp->output_ptr != NULL)
+ if (next == 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);
+ ret = Z_MEM_ERROR;
+ break;
}
- else
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)(comp->max_output_ptr *
- png_sizeof(png_charp)));
+ /* Link in this buffer (so that it will be freed later) */
+ next->next = NULL;
+ *end = next;
}
- /* 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_ptr->zstream.next_out = next->output;
+ png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
+ output_len += png_ptr->zstream.avail_out;
- 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;
+ /* Move 'end' to the next buffer pointer. */
+ end = &next->next;
}
+
+ /* Compress the data */
+ ret = deflate(&png_ptr->zstream,
+ input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
+
+ /* Claw back input data that was not consumed (because avail_in is
+ * reset above every time round the loop).
+ */
+ input_len += png_ptr->zstream.avail_in;
+ png_ptr->zstream.avail_in = 0; /* safety */
}
- else if (ret != Z_STREAM_END)
+ while (ret == Z_OK);
+
+ /* There may be some space left in the last output buffer. This needs to
+ * be subtracted from output_len.
+ */
+ output_len -= png_ptr->zstream.avail_out;
+ png_ptr->zstream.avail_out = 0; /* safety */
+ comp->output_len = output_len;
+
+ /* Now double check the output length, put in a custom message if it is
+ * too long. Otherwise ensure the z_stream::msg pointer is set to
+ * something.
+ */
+ if (output_len + prefix_len >= PNG_UINT_31_MAX)
{
- /* 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");
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long");
+ ret = Z_MEM_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;
+ else
+ png_zstream_error(png_ptr, ret);
- if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
- text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
+ /* Reset zlib for another zTXt/iTXt or image data */
+ png_ptr->zowner = 0;
- return((int)text_len);
+ /* The only success case is Z_STREAM_END, input_len must be 0; if not this
+ * is an internal error.
+ */
+ if (ret == Z_STREAM_END && input_len == 0)
+ {
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ /* Fix up the deflate header, if required */
+ optimize_cmf(comp->output, comp->input_len);
+#endif
+ /* But Z_OK is returned, not Z_STREAM_END; this allows the claim
+ * function above to return Z_STREAM_END on an error (though it never
+ * does in the current versions of zlib.)
+ */
+ return Z_OK;
+ }
+
+ else
+ return ret;
+ }
}
/* Ship the compressed text out via chunk writes */
-static void /* PRIVATE */
-png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
+static void
+png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
{
- int i;
+ png_uint_32 output_len = comp->output_len;
+ png_const_bytep output = comp->output;
+ png_uint_32 avail = (sizeof comp->output);
+ png_compression_buffer *next = png_ptr->zbuffer_list;
- /* Handle the no-compression case */
- if (comp->input)
+ for (;;)
{
- png_write_chunk_data(png_ptr, comp->input, comp->input_len);
+ if (avail > output_len)
+ avail = output_len;
- return;
+ png_write_chunk_data(png_ptr, output, avail);
+
+ output_len -= avail;
+
+ if (output_len == 0 || next == NULL)
+ break;
+
+ avail = png_ptr->zbuffer_size;
+ output = next->output;
+ next = next->next;
}
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
- if (comp->input_len >= 2 && comp->input_len < 16384)
+ /* This is an internal error; 'next' must have been NULL! */
+ if (output_len > 0)
+ png_error(png_ptr, "error writing ancillary chunked compressed data");
+}
+#endif /* WRITE_COMPRESSED_TEXT */
+
+#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' buffer must be 80 characters in size (for the keyword plus a
+ * trailing '\0'). If this routine returns 0 then there was no keyword, or a
+ * valid one could not be generated, and the caller must png_error.
+ */
+static png_uint_32
+png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
+{
+ png_const_charp orig_key = key;
+ png_uint_32 key_len = 0;
+ int bad_character = 0;
+ int space = 1;
+
+ png_debug(1, "in png_check_keyword");
+
+ if (key == NULL)
{
- unsigned int z_cmf; /* zlib compression method and flags */
+ *new_key = 0;
+ return 0;
+ }
- /* Optimize the CMF field in the zlib stream. This hack of the zlib
- * stream is compliant to the stream specification.
- */
+ while (*key && key_len < 79)
+ {
+ png_byte ch = (png_byte)(0xff & *key++);
- if (comp->num_output_ptr)
- z_cmf = comp->output_ptr[0][0];
- else
- z_cmf = png_ptr->zbuf[0];
+ if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
+ *new_key++ = ch, ++key_len, space = 0;
- if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
+ else if (space == 0)
{
- unsigned int z_cinfo;
- unsigned int half_z_window_size;
- png_size_t uncompressed_text_size = comp->input_len;
+ /* A space or an invalid character when one wasn't seen immediately
+ * before; output just a space.
+ */
+ *new_key++ = 32, ++key_len, space = 1;
- z_cinfo = z_cmf >> 4;
- half_z_window_size = 1 << (z_cinfo + 7);
-
- while (uncompressed_text_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 (comp->num_output_ptr)
- {
-
- if (comp->output_ptr[0][0] != z_cmf)
- {
- int tmp;
-
- comp->output_ptr[0][0] = (png_byte)z_cmf;
- tmp = comp->output_ptr[0][1] & 0xe0;
- tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
- comp->output_ptr[0][1] = (png_byte)tmp;
- }
- }
- else
- {
- int tmp;
-
- png_ptr->zbuf[0] = (png_byte)z_cmf;
- tmp = png_ptr->zbuf[1] & 0xe0;
- tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
- png_ptr->zbuf[1] = (png_byte)tmp;
- }
+ /* If the character was not a space then it is invalid. */
+ if (ch != 32)
+ bad_character = ch;
}
- else
- png_error(png_ptr,
- "Invalid zlib compression method or flags in non-IDAT chunk");
+ else if (bad_character == 0)
+ bad_character = ch; /* just skip it, record the first error */
}
-#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
- /* Write saved output buffers, if any */
- for (i = 0; i < comp->num_output_ptr; i++)
+ if (key_len > 0 && space != 0) /* trailing space */
{
- 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]);
+ --key_len, --new_key;
+ if (bad_character == 0)
+ bad_character = 32;
}
- if (comp->max_output_ptr != 0)
- png_free(png_ptr, comp->output_ptr);
+ /* Terminate the keyword */
+ *new_key = 0;
- /* 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));
+ if (key_len == 0)
+ return 0;
- /* Reset zlib for another zTXt/iTXt or image data */
- png_zlib_release(png_ptr);
+#ifdef PNG_WARNINGS_SUPPORTED
+ /* Try to only output one warning per keyword: */
+ if (*key != 0) /* keyword too long */
+ png_warning(png_ptr, "keyword truncated");
+
+ else if (bad_character != 0)
+ {
+ PNG_WARNING_PARAMETERS(p)
+
+ png_warning_parameter(p, 1, orig_key);
+ png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
+
+ png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
+ }
+#endif /* WARNINGS */
+
+ return key_len;
}
-#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
+#endif /* WRITE_TEXT || WRITE_pCAL || WRITE_iCCP || WRITE_sPLT */
/* 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,
+png_write_IHDR(png_structrp 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;
-
png_byte buf[13]; /* Buffer to store the IHDR info */
png_debug(1, "in png_write_IHDR");
@@ -772,8 +876,8 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
*/
if (
#ifdef PNG_MNG_FEATURES_SUPPORTED
- !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
- ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
+ !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
+ ((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)) &&
@@ -823,14 +927,9 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
buf[12] = (png_byte)interlace_type;
/* Write the chunk */
- png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
+ png_write_complete_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->do_filter) == PNG_NO_FILTERS)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
png_ptr->bit_depth < 8)
@@ -840,55 +939,6 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
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;
-
-#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
-#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY))
- png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL))
- png_ptr->zlib_text_level = png_ptr->zlib_level;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL))
- png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS))
- png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD))
- png_ptr->zlib_text_method = png_ptr->zlib_method;
-#else
- png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
- png_ptr->zlib_text_level = png_ptr->zlib_level;
- png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
- png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
- png_ptr->zlib_text_method = png_ptr->zlib_method;
-#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
-#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
-
- /* Record that the compressor has not yet been initialized. */
- png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
-
png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
}
@@ -897,10 +947,9 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
* structure.
*/
void /* PRIVATE */
-png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
+png_write_PLTE(png_structrp 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];
@@ -909,7 +958,7 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
if ((
#ifdef PNG_MNG_FEATURES_SUPPORTED
- !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
+ (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 &&
#endif
num_pal == 0) || num_pal > 256)
{
@@ -925,7 +974,7 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
}
}
- if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
png_warning(png_ptr,
"Ignoring request to write a PLTE chunk in grayscale PNG");
@@ -936,7 +985,7 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
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));
+ png_write_chunk_header(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++)
@@ -966,127 +1015,192 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
png_ptr->mode |= PNG_HAVE_PLTE;
}
-/* Write an IDAT chunk */
+/* This is similar to png_text_compress, above, except that it does not require
+ * all of the data at once and, instead of buffering the compressed result,
+ * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out
+ * because it calls the write interface. As a result it does its own error
+ * reporting and does not return an error code. In the event of error it will
+ * just call png_error. The input data length may exceed 32-bits. The 'flush'
+ * parameter is exactly the same as that to deflate, with the following
+ * meanings:
+ *
+ * Z_NO_FLUSH: normal incremental output of compressed data
+ * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
+ * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
+ *
+ * The routine manages the acquire and release of the png_ptr->zstream by
+ * checking and (at the end) clearing png_ptr->zowner; it does some sanity
+ * checks on the 'mode' flags while doing this.
+ */
void /* PRIVATE */
-png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
+png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
+ png_alloc_size_t input_len, int flush)
{
- PNG_IDAT;
-
- png_debug(1, "in png_write_IDAT");
-
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
- if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
- png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ if (png_ptr->zowner != png_IDAT)
{
- /* Optimize the CMF field in the zlib stream. This hack of the zlib
- * stream is compliant to the stream specification.
+ /* First time. Ensure we have a temporary buffer for compression and
+ * trim the buffer list if it has more than one entry to free memory.
+ * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
+ * created at this point, but the check here is quick and safe.
*/
- unsigned int z_cmf = data[0]; /* zlib compression method and flags */
-
- if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
+ if (png_ptr->zbuffer_list == NULL)
{
- /* 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)
- {
- /* Compute the maximum possible length of the datastream */
-
- /* Number of pixels, plus for each row a filter byte
- * and possibly a padding byte, so increase the maximum
- * size to account for these.
- */
- unsigned int z_cinfo;
- unsigned int half_z_window_size;
- png_uint_32 uncompressed_idat_size = png_ptr->height *
- ((png_ptr->width *
- png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
-
- /* If it's interlaced, each block of 8 rows is sent as up to
- * 14 rows, i.e., 6 additional rows, each with a filter byte
- * and possibly a padding byte
- */
- if (png_ptr->interlaced)
- uncompressed_idat_size += ((png_ptr->height + 7)/8) *
- (png_ptr->bit_depth < 8 ? 12 : 6);
-
- z_cinfo = z_cmf >> 4;
- 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;
- }
- }
+ png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
+ png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
+ png_ptr->zbuffer_list->next = NULL;
}
else
- png_error(png_ptr,
- "Invalid zlib compression method or flags in IDAT");
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);
+
+ /* It is a terminal error if we can't claim the zstream. */
+ if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+
+ /* The output state is maintained in png_ptr->zstream, so it must be
+ * initialized here after the claim.
+ */
+ png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
+ png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
}
-#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
- png_write_chunk(png_ptr, png_IDAT, data, length);
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- /* Prior to 1.5.4 this code was replicated in every caller (except at the
- * end, where it isn't technically necessary). Since this function has
- * flushed the data we can safely reset the zlib output buffer here.
+ /* Now loop reading and writing until all the input is consumed or an error
+ * terminates the operation. The _out values are maintained across calls to
+ * this function, but the input must be reset each time.
*/
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
+ png_ptr->zstream.avail_in = 0; /* set below */
+ for (;;)
+ {
+ int ret;
+
+ /* INPUT: from the row data */
+ uInt avail = ZLIB_IO_MAX;
+
+ if (avail > input_len)
+ avail = (uInt)input_len; /* safe because of the check */
+
+ png_ptr->zstream.avail_in = avail;
+ input_len -= avail;
+
+ ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);
+
+ /* Include as-yet unconsumed input */
+ input_len += png_ptr->zstream.avail_in;
+ png_ptr->zstream.avail_in = 0;
+
+ /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
+ * that these two zstream fields are preserved across the calls, therefore
+ * there is no need to set these up on entry to the loop.
+ */
+ if (png_ptr->zstream.avail_out == 0)
+ {
+ png_bytep data = png_ptr->zbuffer_list->output;
+ uInt size = png_ptr->zbuffer_size;
+
+ /* Write an IDAT containing the data then reset the buffer. The
+ * first IDAT may need deflate header optimization.
+ */
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
+ png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ optimize_cmf(data, png_image_size(png_ptr));
+#endif
+
+ png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+ png_ptr->mode |= PNG_HAVE_IDAT;
+
+ png_ptr->zstream.next_out = data;
+ png_ptr->zstream.avail_out = size;
+
+ /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
+ * the same flush parameter until it has finished output, for NO_FLUSH
+ * it doesn't matter.
+ */
+ if (ret == Z_OK && flush != Z_NO_FLUSH)
+ continue;
+ }
+
+ /* The order of these checks doesn't matter much; it just affects which
+ * possible error might be detected if multiple things go wrong at once.
+ */
+ if (ret == Z_OK) /* most likely return code! */
+ {
+ /* If all the input has been consumed then just return. If Z_FINISH
+ * was used as the flush parameter something has gone wrong if we get
+ * here.
+ */
+ if (input_len == 0)
+ {
+ if (flush == Z_FINISH)
+ png_error(png_ptr, "Z_OK on Z_FINISH with output space");
+
+ return;
+ }
+ }
+
+ else if (ret == Z_STREAM_END && flush == Z_FINISH)
+ {
+ /* This is the end of the IDAT data; any pending output must be
+ * flushed. For small PNG files we may still be at the beginning.
+ */
+ png_bytep data = png_ptr->zbuffer_list->output;
+ uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
+
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
+ png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ optimize_cmf(data, png_image_size(png_ptr));
+#endif
+
+ png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+ png_ptr->zstream.avail_out = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
+
+ png_ptr->zowner = 0; /* Release the stream */
+ return;
+ }
+
+ else
+ {
+ /* This is an error condition. */
+ png_zstream_error(png_ptr, ret);
+ png_error(png_ptr, png_ptr->zstream.msg);
+ }
+ }
}
/* Write an IEND chunk */
void /* PRIVATE */
-png_write_IEND(png_structp png_ptr)
+png_write_IEND(png_structrp png_ptr)
{
- PNG_IEND;
-
png_debug(1, "in png_write_IEND");
- png_write_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
+ png_write_complete_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_write_gAMA_fixed(png_structrp 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);
+ png_write_complete_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_write_sRGB(png_structrp png_ptr, int srgb_intent)
{
- PNG_sRGB;
png_byte buf[1];
png_debug(1, "in png_write_sRGB");
@@ -1096,104 +1210,79 @@ png_write_sRGB(png_structp png_ptr, int srgb_intent)
"Invalid sRGB rendering intent specified");
buf[0]=(png_byte)srgb_intent;
- png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
+ png_write_complete_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_write_iCCP(png_structrp png_ptr, png_const_charp name,
+ png_const_bytep profile)
{
- PNG_iCCP;
- png_size_t name_len;
- png_charp new_name;
+ png_uint_32 name_len;
+ png_uint_32 profile_len;
+ png_byte new_name[81]; /* 1 byte for the compression byte */
compression_state comp;
- int embedded_profile_len = 0;
+ png_uint_32 temp;
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");
-
+ /* These are all internal problems: the profile should have been checked
+ * before when it was stored.
+ */
if (profile == NULL)
- profile_len = 0;
+ png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
- 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)) );
+ profile_len = png_get_uint_32(profile);
+
+ if (profile_len < 132)
+ png_error(png_ptr, "ICC profile too short");
+
+ temp = (png_uint_32) (*(profile+8));
+ if (temp > 3 && (profile_len & 0x03))
+ png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
- if (embedded_profile_len < 0)
{
- png_warning(png_ptr,
- "Embedded profile length in iCCP chunk is negative");
+ png_uint_32 embedded_profile_len = png_get_uint_32(profile);
- png_free(png_ptr, new_name);
- return;
+ if (profile_len != embedded_profile_len)
+ png_error(png_ptr, "Profile length does not match profile");
}
- if (profile_len < embedded_profile_len)
- {
- png_warning(png_ptr,
- "Embedded profile length too large in iCCP chunk");
+ name_len = png_check_keyword(png_ptr, name, new_name);
- png_free(png_ptr, new_name);
- return;
- }
+ if (name_len == 0)
+ png_error(png_ptr, "iCCP: invalid keyword");
- 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);
+ new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
/* 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));
+ ++name_len;
- new_name[name_len + 1] = 0x00;
+ png_text_compress_init(&comp, profile, profile_len);
- png_write_chunk_data(png_ptr, (png_bytep)new_name,
- (png_size_t)(name_len + 2));
+ /* Allow for keyword terminator and compression byte */
+ if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
- if (profile_len)
- {
- comp.input_len = profile_len;
- png_write_compressed_data_out(png_ptr, &comp);
- }
+ png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
+
+ png_write_chunk_data(png_ptr, new_name, name_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_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
{
- PNG_sPLT;
- png_size_t name_len;
- png_charp new_name;
+ png_uint_32 name_len;
+ png_byte new_name[80];
png_byte entrybuf[10];
png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
png_size_t palette_size = entry_size * spalette->nentries;
@@ -1204,11 +1293,13 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_debug(1, "in png_write_sPLT");
- if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
- return;
+ name_len = png_check_keyword(png_ptr, spalette->name, new_name);
+
+ if (name_len == 0)
+ png_error(png_ptr, "sPLT: invalid keyword");
/* Make sure we include the NULL after the name */
- png_write_chunk_start(png_ptr, png_sPLT,
+ png_write_chunk_header(png_ptr, png_sPLT,
(png_uint_32)(name_len + 2 + palette_size));
png_write_chunk_data(png_ptr, (png_bytep)new_name,
@@ -1238,7 +1329,7 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_save_uint_16(entrybuf + 8, ep->frequency);
}
- png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+ png_write_chunk_data(png_ptr, entrybuf, entry_size);
}
#else
ep=spalette->entries;
@@ -1262,28 +1353,26 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_save_uint_16(entrybuf + 8, ep[i].frequency);
}
- png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+ png_write_chunk_data(png_ptr, entrybuf, 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_write_sBIT(png_structrp 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)
+ if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_byte maxbits;
@@ -1316,7 +1405,7 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
size = 1;
}
- if (color_type & PNG_COLOR_MASK_ALPHA)
+ if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
{
@@ -1327,53 +1416,42 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
buf[size++] = sbit->alpha;
}
- png_write_chunk(png_ptr, png_sBIT, buf, size);
+ png_write_complete_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_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
{
- 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_int_32(buf, xy->whitex);
+ png_save_int_32(buf + 4, xy->whitey);
- png_save_uint_32(buf + 8, (png_uint_32)red_x);
- png_save_uint_32(buf + 12, (png_uint_32)red_y);
+ png_save_int_32(buf + 8, xy->redx);
+ png_save_int_32(buf + 12, xy->redy);
- png_save_uint_32(buf + 16, (png_uint_32)green_x);
- png_save_uint_32(buf + 20, (png_uint_32)green_y);
+ png_save_int_32(buf + 16, xy->greenx);
+ png_save_int_32(buf + 20, xy->greeny);
- png_save_uint_32(buf + 24, (png_uint_32)blue_x);
- png_save_uint_32(buf + 28, (png_uint_32)blue_y);
+ png_save_int_32(buf + 24, xy->bluex);
+ png_save_int_32(buf + 28, xy->bluey);
- png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
- }
+ png_write_complete_chunk(png_ptr, png_cHRM, buf, 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_write_tRNS(png_structrp 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");
@@ -1382,12 +1460,14 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
{
if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
{
- png_warning(png_ptr, "Invalid number of transparent colors specified");
+ png_app_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);
+ png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
+ (png_size_t)num_trans);
}
else if (color_type == PNG_COLOR_TYPE_GRAY)
@@ -1395,14 +1475,14 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
/* One 16 bit value */
if (tran->gray >= (1 << png_ptr->bit_depth))
{
- png_warning(png_ptr,
+ png_app_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);
+ png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
}
else if (color_type == PNG_COLOR_TYPE_RGB)
@@ -1412,22 +1492,22 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
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]))
+ if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
#else
- if (buf[0] | buf[2] | buf[4])
+ if ((buf[0] | buf[2] | buf[4]) != 0)
#endif
{
- png_warning(png_ptr,
+ png_app_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);
+ png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
}
else
{
- png_warning(png_ptr, "Can't write tRNS with an alpha channel");
+ png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
}
}
#endif
@@ -1435,9 +1515,8 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
#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_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
{
- PNG_bKGD;
png_byte buf[6];
png_debug(1, "in png_write_bKGD");
@@ -1446,8 +1525,8 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
{
if (
#ifdef PNG_MNG_FEATURES_SUPPORTED
- (png_ptr->num_palette ||
- (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
+ (png_ptr->num_palette != 0 ||
+ (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
#endif
back->index >= png_ptr->num_palette)
{
@@ -1456,18 +1535,18 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
}
buf[0] = back->index;
- png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
+ png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
}
- else if (color_type & PNG_COLOR_MASK_COLOR)
+ else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
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]))
+ if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
#else
- if (buf[0] | buf[2] | buf[4])
+ if ((buf[0] | buf[2] | buf[4]) != 0)
#endif
{
png_warning(png_ptr,
@@ -1476,7 +1555,7 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
return;
}
- png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
+ png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
}
else
@@ -1490,7 +1569,7 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
}
png_save_uint_16(buf, back->gray);
- png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
+ png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
}
}
#endif
@@ -1498,9 +1577,8 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
#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_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
{
- PNG_hIST;
int i;
png_byte buf[3];
@@ -1515,7 +1593,7 @@ png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
return;
}
- png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
+ png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
for (i = 0; i < num_hist; i++)
{
@@ -1527,236 +1605,93 @@ png_write_hIST(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)
-/* 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))
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x,
- (png_byte)*ikp);
- png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1");
- *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_write_tEXt(png_structrp 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_uint_32 key_len;
+ png_byte new_key[80];
png_debug(1, "in png_write_tEXt");
- if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
- return;
+ key_len = png_check_keyword(png_ptr, key, new_key);
+
+ if (key_len == 0)
+ png_error(png_ptr, "tEXt: invalid keyword");
if (text == NULL || *text == '\0')
text_len = 0;
else
- text_len = png_strlen(text);
+ text_len = strlen(text);
+
+ if (text_len > PNG_UINT_31_MAX - (key_len+1))
+ png_error(png_ptr, "tEXt: text too long");
/* 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));
+ png_write_chunk_header(png_ptr, png_tEXt,
+ (png_uint_32)/*checked above*/(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));
+ png_write_chunk_data(png_ptr, new_key, key_len + 1);
- if (text_len)
- png_write_chunk_data(png_ptr, (png_const_bytep)text,
- (png_size_t)text_len);
+ if (text_len != 0)
+ png_write_chunk_data(png_ptr, (png_const_bytep)text, 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_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
+ int compression)
{
- PNG_zTXt;
- png_size_t key_len;
- png_byte buf;
- png_charp new_key;
+ png_uint_32 key_len;
+ png_byte new_key[81];
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)
+ if (compression == PNG_TEXT_COMPRESSION_NONE)
{
- png_free(png_ptr, new_key);
+ png_write_tEXt(png_ptr, key, text, 0);
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;
- }
+ if (compression != PNG_TEXT_COMPRESSION_zTXt)
+ png_error(png_ptr, "zTXt: invalid compression type");
- text_len = png_strlen(text);
+ key_len = png_check_keyword(png_ptr, key, new_key);
+
+ if (key_len == 0)
+ png_error(png_ptr, "zTXt: invalid keyword");
+
+ /* Add the compression method and 1 for the keyword separator. */
+ new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
+ ++key_len;
/* Compute the compressed data; do it now for the length */
- text_len = png_text_compress(png_ptr, text, text_len, compression,
- &comp);
+ png_text_compress_init(&comp, (png_const_bytep)text,
+ text == NULL ? 0 : strlen(text));
+
+ if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
/* Write start of chunk */
- png_write_chunk_start(png_ptr, png_zTXt,
- (png_uint_32)(key_len+text_len + 2));
+ png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
/* 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);
+ png_write_chunk_data(png_ptr, new_key, key_len);
/* Write the compressed data */
- comp.input_len = text_len;
png_write_compressed_data_out(png_ptr, &comp);
/* Close the chunk */
@@ -1767,104 +1702,109 @@ png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
#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_write_iTXt(png_structrp 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];
+ png_uint_32 key_len, prefix_len;
+ png_size_t lang_len, lang_key_len;
+ png_byte new_key[82];
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;
+ key_len = png_check_keyword(png_ptr, key, new_key);
- if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
- return;
+ if (key_len == 0)
+ png_error(png_ptr, "iTXt: invalid keyword");
- if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0)
+ /* Set the compression flag */
+ switch (compression)
{
- png_warning(png_ptr, "Empty language field in iTXt chunk");
- new_lang = NULL;
- lang_len = 0;
+ case PNG_ITXT_COMPRESSION_NONE:
+ case PNG_TEXT_COMPRESSION_NONE:
+ compression = new_key[++key_len] = 0; /* no compression */
+ break;
+
+ case PNG_TEXT_COMPRESSION_zTXt:
+ case PNG_ITXT_COMPRESSION_zTXt:
+ compression = new_key[++key_len] = 1; /* compressed */
+ break;
+
+ default:
+ png_error(png_ptr, "iTXt: invalid compression");
}
- 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));
+ new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
+ ++key_len; /* for the keywod separator */
/* 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.
+ * any non-Latin-1 characters except for NEWLINE. ISO PNG, however,
+ * specifies that the text is UTF-8 and this really doesn't require any
+ * checking.
+ *
* The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+ *
+ * TODO: validate the language tag correctly (see the spec.)
*/
- png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1));
+ if (lang == NULL) lang = ""; /* empty language is valid */
+ lang_len = strlen(lang)+1;
+ if (lang_key == NULL) lang_key = ""; /* may be empty */
+ lang_key_len = strlen(lang_key)+1;
+ if (text == NULL) text = ""; /* may be empty */
- /* Set the compression flag */
- if (compression == PNG_ITXT_COMPRESSION_NONE ||
- compression == PNG_TEXT_COMPRESSION_NONE)
- cbuf[0] = 0;
+ prefix_len = key_len;
+ if (lang_len > PNG_UINT_31_MAX-prefix_len)
+ prefix_len = PNG_UINT_31_MAX;
+ else
+ prefix_len = (png_uint_32)(prefix_len + lang_len);
- else /* compression == PNG_ITXT_COMPRESSION_zTXt */
- cbuf[0] = 1;
+ if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
+ prefix_len = PNG_UINT_31_MAX;
+ else
+ prefix_len = (png_uint_32)(prefix_len + lang_key_len);
- /* Set the compression method */
- cbuf[1] = 0;
+ png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
- png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
+ if (compression != 0)
+ {
+ if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+ }
- cbuf[0] = 0;
- png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf),
- (png_size_t)(lang_len + 1));
+ else
+ {
+ if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
+ png_error(png_ptr, "iTXt: uncompressed text too long");
- png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf),
- (png_size_t)(lang_key_len + 1));
+ /* So the string will fit in a chunk: */
+ comp.output_len = (png_uint_32)/*SAFE*/comp.input_len;
+ }
- png_write_compressed_data_out(png_ptr, &comp);
+ png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
+
+ png_write_chunk_data(png_ptr, new_key, key_len);
+
+ png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
+
+ png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
+
+ if (compression != 0)
+ png_write_compressed_data_out(png_ptr, &comp);
+
+ else
+ png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.input_len);
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,
+png_write_oFFs(png_structrp 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");
@@ -1876,52 +1816,57 @@ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_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);
+ png_write_complete_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_write_pCAL(png_structrp 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_uint_32 purpose_len;
+ png_size_t units_len, total_len;
+ png_size_tp params_len;
png_byte buf[10];
- png_charp new_purpose;
+ png_byte new_purpose[80];
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");
+ png_error(png_ptr, "Unrecognized equation type for pCAL chunk");
+
+ purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);
+
+ if (purpose_len == 0)
+ png_error(png_ptr, "pCAL: invalid keyword");
+
+ ++purpose_len; /* terminator */
- 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);
+ units_len = 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)));
+ params_len = (png_size_tp)png_malloc(png_ptr,
+ (png_alloc_size_t)(nparams * (sizeof (png_size_t))));
/* 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);
+ params_len[i] = 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];
+ total_len += 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_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
+ png_write_chunk_data(png_ptr, new_purpose, purpose_len);
png_save_int_32(buf, X0);
png_save_int_32(buf + 4, X1);
buf[8] = (png_byte)type;
@@ -1929,12 +1874,9 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
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_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
}
png_free(png_ptr, params_len);
@@ -1945,17 +1887,16 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
#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_write_sCAL_s(png_structrp 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);
+ wlen = strlen(width);
+ hlen = strlen(height);
total_len = wlen + hlen + 2;
if (total_len > 64)
@@ -1965,22 +1906,21 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
}
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 */
+ memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */
+ 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);
+ png_write_complete_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_write_pHYs(png_structrp 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");
@@ -1992,7 +1932,7 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 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);
+ png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
}
#endif
@@ -2001,9 +1941,8 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
* 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_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
{
- PNG_tIME;
png_byte buf[7];
png_debug(1, "in png_write_tIME");
@@ -2023,40 +1962,44 @@ png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
buf[5] = mod_time->minute;
buf[6] = mod_time->second;
- png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
+ png_write_complete_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)
+png_write_start_row(png_structrp 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
- png_size_t buf_size;
+ png_alloc_size_t buf_size;
+ int usr_pixel_depth;
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);
+ usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
+ buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
+
+ /* 1.5.6: added to allow checking in the row write code. */
+ png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
+ png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
/* Set up row buffer */
- png_ptr->row_buf = (png_bytep)png_malloc(png_ptr,
- (png_alloc_size_t)buf_size);
+ png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
@@ -2070,13 +2013,13 @@ png_write_start_row(png_structp png_ptr)
}
/* 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))
+ if ((png_ptr->do_filter &
+ (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0)
{
/* Set up previous row buffer */
- png_ptr->prev_row = (png_bytep)png_calloc(png_ptr,
- (png_alloc_size_t)buf_size);
+ png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
- if (png_ptr->do_filter & PNG_FILTER_UP)
+ if ((png_ptr->do_filter & PNG_FILTER_UP) != 0)
{
png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1);
@@ -2084,7 +2027,7 @@ png_write_start_row(png_structp png_ptr)
png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
}
- if (png_ptr->do_filter & PNG_FILTER_AVG)
+ if ((png_ptr->do_filter & PNG_FILTER_AVG) != 0)
{
png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1);
@@ -2092,7 +2035,7 @@ png_write_start_row(png_structp png_ptr)
png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
}
- if (png_ptr->do_filter & PNG_FILTER_PAETH)
+ if ((png_ptr->do_filter & PNG_FILTER_PAETH) != 0)
{
png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1);
@@ -2100,13 +2043,13 @@ png_write_start_row(png_structp png_ptr)
png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
}
}
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+#endif /* WRITE_FILTER */
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced, we need to set up width and height of pass */
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
{
png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
png_pass_ystart[0]) / png_pass_yinc[0];
@@ -2128,34 +2071,28 @@ png_write_start_row(png_structp png_ptr)
png_ptr->num_rows = png_ptr->height;
png_ptr->usr_width = png_ptr->width;
}
-
- png_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT);
- 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)
+png_write_finish_row(png_structrp 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
- int ret;
-
png_debug(1, "in png_write_finish_row");
/* Next row */
@@ -2167,10 +2104,10 @@ png_write_finish_row(png_structp png_ptr)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced, go to next pass */
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
png_ptr->row_number = 0;
- if (png_ptr->transformations & PNG_INTERLACE)
+ if ((png_ptr->transformations & PNG_INTERLACE) != 0)
{
png_ptr->pass++;
}
@@ -2195,7 +2132,7 @@ png_write_finish_row(png_structp png_ptr)
png_pass_ystart[png_ptr->pass]) /
png_pass_yinc[png_ptr->pass];
- if (png_ptr->transformations & PNG_INTERLACE)
+ if ((png_ptr->transformations & PNG_INTERLACE) != 0)
break;
} while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
@@ -2206,7 +2143,7 @@ png_write_finish_row(png_structp png_ptr)
if (png_ptr->pass < 7)
{
if (png_ptr->prev_row != NULL)
- png_memset(png_ptr->prev_row, 0,
+ memset(png_ptr->prev_row, 0,
(png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
png_ptr->usr_bit_depth, png_ptr->width)) + 1);
@@ -2217,42 +2154,7 @@ png_write_finish_row(png_structp png_ptr)
/* 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);
- }
-
- png_zlib_release(png_ptr);
- png_ptr->zstream.data_type = Z_BINARY;
+ png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
}
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
@@ -2269,10 +2171,10 @@ 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};
+ static PNG_CONST png_byte 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};
+ static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_write_interlace");
@@ -2416,7 +2318,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
/* Move the pixel */
if (dp != sp)
- png_memcpy(dp, sp, pixel_bytes);
+ memcpy(dp, sp, pixel_bytes);
/* Next pixel */
dp += pixel_bytes;
@@ -2440,14 +2342,16 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
* been specified by the application, and then writes the row out with the
* chosen filter.
*/
-static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row);
+static void
+png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
+ png_size_t row_bytes);
#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_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
{
png_bytep best_row;
#ifdef PNG_WRITE_FILTER_SUPPORTED
@@ -2456,7 +2360,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
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;
+ int num_p_filters = png_ptr->num_prev_filters;
#endif
png_debug(1, "in png_write_find_filter");
@@ -2507,7 +2411,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
/* 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)
+ if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE)
{
png_bytep rp;
png_uint_32 sum = 0;
@@ -2583,7 +2487,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
best_row = png_ptr->sub_row;
}
- else if (filter_to_do & PNG_FILTER_SUB)
+ else if ((filter_to_do & PNG_FILTER_SUB) != 0)
{
png_bytep rp, dp, lp;
png_uint_32 sum = 0, lmins = mins;
@@ -2704,7 +2608,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
best_row = png_ptr->up_row;
}
- else if (filter_to_do & PNG_FILTER_UP)
+ else if ((filter_to_do & PNG_FILTER_UP) != 0)
{
png_bytep rp, dp, pp;
png_uint_32 sum = 0, lmins = mins;
@@ -2818,7 +2722,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
best_row = png_ptr->avg_row;
}
- else if (filter_to_do & PNG_FILTER_AVG)
+ else if ((filter_to_do & PNG_FILTER_AVG) != 0)
{
png_bytep rp, dp, pp, lp;
png_uint_32 sum = 0, lmins = mins;
@@ -2920,7 +2824,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
}
/* Paeth filter */
- if (filter_to_do == PNG_FILTER_PAETH)
+ if ((filter_to_do == PNG_FILTER_PAETH) != 0)
{
png_bytep rp, dp, pp, cp, lp;
png_size_t i;
@@ -2959,7 +2863,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
best_row = png_ptr->paeth_row;
}
- else if (filter_to_do & PNG_FILTER_PAETH)
+ else if ((filter_to_do & PNG_FILTER_PAETH) != 0)
{
png_bytep rp, dp, pp, cp, lp;
png_uint_32 sum = 0, lmins = mins;
@@ -3029,7 +2933,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
pc = (p + pc) < 0 ? -(p + pc) : p + pc;
#endif
p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
-#else /* PNG_SLOW_PAETH */
+#else /* SLOW_PAETH */
p = a + b - c;
pa = abs(p - a);
pb = abs(p - b);
@@ -3043,7 +2947,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
else
p = c;
-#endif /* PNG_SLOW_PAETH */
+#endif /* SLOW_PAETH */
v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
@@ -3092,10 +2996,10 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
best_row = png_ptr->paeth_row;
}
}
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
- /* Do the actual writing of the filtered row data from the chosen filter. */
+#endif /* WRITE_FILTER */
- png_write_filtered_row(png_ptr, best_row);
+ /* Do the actual writing of the filtered row data from the chosen filter. */
+ png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
#ifdef PNG_WRITE_FILTER_SUPPORTED
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
@@ -3112,74 +3016,20 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
png_ptr->prev_filters[j] = best_row[0];
}
#endif
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+#endif /* WRITE_FILTER */
}
/* Do the actual writing of a previously filtered row. */
static void
-png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
+png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
+ png_size_t full_row_length/*includes filter byte*/)
{
- 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);
- }
- /* Repeat until all data has been compressed */
- } while (avail > 0 || png_ptr->zstream.avail_in > 0);
+ png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
/* Swap the current and previous rows */
if (png_ptr->prev_row != NULL)
@@ -3202,6 +3052,6 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
{
png_write_flush(png_ptr);
}
-#endif
+#endif /* WRITE_FLUSH */
}
-#endif /* PNG_WRITE_SUPPORTED */
+#endif /* WRITE */
diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java
index fad3b3b6c09..8c0dc54a3b8 100644
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/GtkFileDialogPeer.java
@@ -29,6 +29,7 @@ import java.awt.peer.FileDialogPeer;
import java.io.File;
import java.io.FilenameFilter;
import sun.awt.AWTAccessor;
+import sun.misc.ManagedLocalsThread;
/**
* FileDialogPeer for the GtkFileChooser.
@@ -111,13 +112,16 @@ final class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer {
XToolkit.awtLock();
try {
if (b) {
- Thread t = new Thread() {
- public void run() {
- showNativeDialog();
- fd.setVisible(false);
- }
+ Runnable task = () -> {
+ showNativeDialog();
+ fd.setVisible(false);
};
- t.start();
+ if (System.getSecurityManager() == null) {
+ new Thread(task).start();
+ } else {
+ new ManagedLocalsThread(task).start();
+ }
+
} else {
quit();
fd.setVisible(false);
diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java
index 41d0ef0f2d0..33cc44fccec 100644
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java
@@ -29,6 +29,9 @@ import java.awt.*;
import java.awt.event.*;
import java.awt.peer.TrayIconPeer;
import sun.awt.*;
+import sun.misc.InnocuousThread;
+import sun.misc.ManagedLocalsThread;
+
import java.awt.image.*;
import java.text.BreakIterator;
import java.util.concurrent.ArrayBlockingQueue;
@@ -338,7 +341,7 @@ public abstract class InfoWindow extends Window {
lineLabels[i].setBackground(Color.white);
}
- displayer.start();
+ displayer.thread.start();
}
public void display(String caption, String text, String messageType) {
@@ -415,7 +418,7 @@ public abstract class InfoWindow extends Window {
}
public void dispose() {
- displayer.interrupt();
+ displayer.thread.interrupt();
super.dispose();
}
@@ -444,16 +447,23 @@ public abstract class InfoWindow extends Window {
}
}
- private class Displayer extends Thread {
+ private class Displayer implements Runnable {
final int MAX_CONCURRENT_MSGS = 10;
ArrayBlockingQueue messageQueue = new ArrayBlockingQueue(MAX_CONCURRENT_MSGS);
boolean isDisplayed;
+ final Thread thread;
Displayer() {
- setDaemon(true);
+ if (System.getSecurityManager() == null) {
+ this.thread = new Thread(this);
+ } else {
+ this.thread = new ManagedLocalsThread(this);
+ }
+ this.thread.setDaemon(true);
}
+ @Override
public void run() {
while (true) {
Message msg = null;
diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java
index bfe94c9f27c..3adbc8d35c5 100644
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java
@@ -266,21 +266,26 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
awtUnlock();
}
PrivilegedAction a = () -> {
- Thread shutdownThread = new Thread(ThreadGroupUtils.getRootThreadGroup(), "XToolkt-Shutdown-Thread") {
- public void run() {
- XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
- if (peer != null) {
- peer.dispose();
- }
- if (xs != null) {
- ((XAWTXSettings)xs).dispose();
- }
- freeXKB();
- if (log.isLoggable(PlatformLogger.Level.FINE)) {
- dumpPeers();
- }
- }
- };
+ Runnable r = () -> {
+ XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance();
+ if (peer != null) {
+ peer.dispose();
+ }
+ if (xs != null) {
+ ((XAWTXSettings)xs).dispose();
+ }
+ freeXKB();
+ if (log.isLoggable(PlatformLogger.Level.FINE)) {
+ dumpPeers();
+ }
+ };
+ String name = "XToolkt-Shutdown-Thread";
+ Thread shutdownThread;
+ if (System.getSecurityManager() == null) {
+ shutdownThread = new Thread(ThreadGroupUtils.getRootThreadGroup(), r, name);
+ } else {
+ shutdownThread = new InnocuousThread(r, name);
+ }
shutdownThread.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(shutdownThread);
return null;
@@ -326,7 +331,13 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
XWM.init();
toolkitThread = AccessController.doPrivileged((PrivilegedAction) () -> {
- Thread thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), XToolkit.this, "AWT-XAWT");
+ String name = "AWT-XAWT";
+ Thread thread;
+ if (System.getSecurityManager() == null) {
+ thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), XToolkit.this, name);
+ } else {
+ thread = new InnocuousThread(XToolkit.this, name);
+ }
thread.setContextClassLoader(null);
thread.setPriority(Thread.NORM_PRIORITY + 1);
thread.setDaemon(true);
diff --git a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
index 009035326d9..93511617183 100644
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
@@ -43,6 +43,7 @@ import sun.java2d.xr.XRGraphicsConfig;
import sun.java2d.loops.SurfaceType;
import sun.awt.util.ThreadGroupUtils;
+import sun.misc.InnocuousThread;
/**
* This is an implementation of a GraphicsDevice object for a single
@@ -428,7 +429,6 @@ public class X11GraphicsDevice
// hook will have no effect)
shutdownHookRegistered = true;
PrivilegedAction a = () -> {
- ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
Runnable r = () -> {
Window old = getFullScreenWindow();
if (old != null) {
@@ -436,7 +436,13 @@ public class X11GraphicsDevice
setDisplayMode(origDisplayMode);
}
};
- Thread t = new Thread(rootTG, r,"Display-Change-Shutdown-Thread-"+screen);
+ String name = "Display-Change-Shutdown-Thread-" + screen;
+ Thread t;
+ if (System.getSecurityManager() == null) {
+ t = new Thread(ThreadGroupUtils.getRootThreadGroup(), r, name);
+ } else {
+ t = new InnocuousThread(r, name);
+ }
t.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(t);
return null;
diff --git a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
index 96acd53d58a..e40ba274b46 100644
--- a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
+++ b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java
@@ -25,6 +25,8 @@
package sun.print;
+import sun.misc.ManagedLocalsThread;
+
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
@@ -211,7 +213,12 @@ public class PrintServiceLookupProvider extends PrintServiceLookup
public PrintServiceLookupProvider() {
// start the printer listener thread
if (pollServices) {
- PrinterChangeListener thr = new PrinterChangeListener();
+ Thread thr;
+ if (System.getSecurityManager() == null) {
+ thr = new Thread(new PrinterChangeListener());
+ } else {
+ thr = new ManagedLocalsThread(new PrinterChangeListener());
+ }
thr.setDaemon(true);
thr.start();
IPPPrintService.debug_println(debugPrefix+"polling turned on");
@@ -934,8 +941,9 @@ public class PrintServiceLookupProvider extends PrintServiceLookup
}
}
- private class PrinterChangeListener extends Thread {
+ private class PrinterChangeListener implements Runnable {
+ @Override
public void run() {
int refreshSecs;
while (true) {
@@ -954,7 +962,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup
refreshSecs = minRefreshTime;
}
try {
- sleep(refreshSecs * 1000);
+ Thread.sleep(refreshSecs * 1000);
} catch (InterruptedException e) {
break;
}
diff --git a/jdk/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c b/jdk/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c
index 85a93042f1d..ed3bfaa1108 100644
--- a/jdk/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c
+++ b/jdk/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -281,9 +281,7 @@ SplashCreateWindow(Splash * splash) {
/* for changing the visible shape of a window to an nonrectangular form */
void
SplashUpdateShape(Splash * splash) {
- if (!shapeSupported)
- return;
- if (!splash->maskRequired) {
+ if (splash->currentFrame < 0 || !shapeSupported || !splash->maskRequired) {
return;
}
XShapeCombineRectangles(splash->display, splash->window, ShapeClip, 0, 0,
@@ -324,6 +322,10 @@ ByteOrderToX(int byteOrder) {
void
SplashRedrawWindow(Splash * splash) {
+ if (splash->currentFrame < 0) {
+ return;
+ }
+
XImage *ximage;
// making this method redraw a part of the image does not make
diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java
index 1f3e2c3e987..52d198f034c 100644
--- a/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java
@@ -41,6 +41,7 @@ import java.util.stream.Stream;
import static sun.awt.shell.Win32ShellFolder2.*;
import sun.awt.OSInfo;
import sun.awt.util.ThreadGroupUtils;
+import sun.misc.InnocuousThread;
// NOTE: This class supersedes Win32ShellFolderManager, which was removed
// from distribution after version 1.4.2.
@@ -516,26 +517,22 @@ final class Win32ShellFolderManager2 extends ShellFolderManager {
private static Thread comThread;
private ComInvoker() {
- super(1, 1, 0, TimeUnit.DAYS, new LinkedBlockingQueue());
+ super(1, 1, 0, TimeUnit.DAYS, new LinkedBlockingQueue<>());
allowCoreThreadTimeOut(false);
setThreadFactory(this);
- final Runnable shutdownHook = new Runnable() {
- public void run() {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Void run() {
- shutdownNow();
- return null;
- }
- });
- }
- };
- AccessController.doPrivileged(new PrivilegedAction() {
- public Void run() {
- Runtime.getRuntime().addShutdownHook(
- new Thread(shutdownHook)
- );
- return null;
+ final Runnable shutdownHook = () -> AccessController.doPrivileged((PrivilegedAction) () -> {
+ shutdownNow();
+ return null;
+ });
+ AccessController.doPrivileged((PrivilegedAction) () -> {
+ Thread t;
+ if (System.getSecurityManager() == null) {
+ t = new Thread(ThreadGroupUtils.getRootThreadGroup(), shutdownHook);
+ } else {
+ t = new InnocuousThread(shutdownHook);
}
+ Runtime.getRuntime().addShutdownHook(t);
+ return null;
});
}
@@ -550,17 +547,22 @@ final class Win32ShellFolderManager2 extends ShellFolderManager {
}
}
};
- comThread = AccessController.doPrivileged((PrivilegedAction) () -> {
- /* The thread must be a member of a thread group
- * which will not get GCed before VM exit.
- * Make its parent the top-level thread group.
- */
- ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
- Thread thread = new Thread(rootTG, comRun, "Swing-Shell");
- thread.setDaemon(true);
- return thread;
- }
- );
+ comThread = AccessController.doPrivileged((PrivilegedAction) () -> {
+ String name = "Swing-Shell";
+ Thread thread;
+ if (System.getSecurityManager() == null) {
+ /* The thread must be a member of a thread group
+ * which will not get GCed before VM exit.
+ * Make its parent the top-level thread group.
+ */
+ thread = new Thread(ThreadGroupUtils.getRootThreadGroup(), comRun, name);
+ } else {
+ /* InnocuousThread is a member of a correct TG by default */
+ thread = new InnocuousThread(comRun, name);
+ }
+ thread.setDaemon(true);
+ return thread;
+ });
return comThread;
}
diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java
index beeb1031332..81a28c6b7d3 100644
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java
@@ -36,6 +36,7 @@ import java.util.MissingResourceException;
import java.util.Vector;
import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
+import sun.misc.ManagedLocalsThread;
final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
@@ -97,12 +98,11 @@ final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
@Override
public void show() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- _show();
- }
- }).start();
+ if (System.getSecurityManager() == null) {
+ new Thread(this::_show).start();
+ } else {
+ new ManagedLocalsThread(this::_show).start();
+ }
}
@Override
diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java
index 78a1c04cf12..7a146d965cd 100644
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPageDialogPeer.java
@@ -25,6 +25,8 @@
package sun.awt.windows;
+import sun.misc.ManagedLocalsThread;
+
final class WPageDialogPeer extends WPrintDialogPeer {
WPageDialogPeer(WPageDialog target) {
@@ -39,20 +41,22 @@ final class WPageDialogPeer extends WPrintDialogPeer {
@Override
public void show() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- // Call pageSetup even with no printer installed, this
- // will display Windows error dialog and return false.
- try {
- ((WPrintDialog)target).setRetVal(_show());
- } catch (Exception e) {
- // No exception should be thrown by native dialog code,
- // but if it is we need to trap it so the thread does
- // not hide is called and the thread doesn't hang.
- }
- ((WPrintDialog)target).setVisible(false);
- }
- }).start();
+ Runnable runnable = () -> {
+ // Call pageSetup even with no printer installed, this
+ // will display Windows error dialog and return false.
+ try {
+ ((WPrintDialog)target).setRetVal(_show());
+ } catch (Exception e) {
+ // No exception should be thrown by native dialog code,
+ // but if it is we need to trap it so the thread does
+ // not hide is called and the thread doesn't hang.
+ }
+ ((WPrintDialog)target).setVisible(false);
+ };
+ if (System.getSecurityManager() == null) {
+ new Thread(runnable).start();
+ } else {
+ new ManagedLocalsThread(runnable).start();
+ }
}
}
diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java
index d1efab01404..2f728f18899 100644
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java
@@ -32,6 +32,7 @@ import java.awt.dnd.DropTarget;
import java.util.Vector;
import sun.awt.CausedFocusEvent;
import sun.awt.AWTAccessor;
+import sun.misc.ManagedLocalsThread;
class WPrintDialogPeer extends WWindowPeer implements DialogPeer {
@@ -67,19 +68,21 @@ class WPrintDialogPeer extends WWindowPeer implements DialogPeer {
@Override
public void show() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- ((WPrintDialog)target).setRetVal(_show());
- } catch (Exception e) {
- // No exception should be thrown by native dialog code,
- // but if it is we need to trap it so the thread does
- // not hide is called and the thread doesn't hang.
- }
- ((WPrintDialog)target).setVisible(false);
+ Runnable runnable = () -> {
+ try {
+ ((WPrintDialog)target).setRetVal(_show());
+ } catch (Exception e) {
+ // No exception should be thrown by native dialog code,
+ // but if it is we need to trap it so the thread does
+ // not hide is called and the thread doesn't hang.
}
- }).start();
+ ((WPrintDialog)target).setVisible(false);
+ };
+ if (System.getSecurityManager() == null) {
+ new Thread(runnable).start();
+ } else {
+ new ManagedLocalsThread(runnable).start();
+ }
}
synchronized void setHWnd(long hwnd) {
diff --git a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java
index 7915982c95a..50207fd0f52 100644
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java
@@ -49,6 +49,7 @@ import sun.awt.datatransfer.DataTransferer;
import sun.java2d.d3d.D3DRenderQueue;
import sun.java2d.opengl.OGLRenderQueue;
+import sun.misc.InnocuousThread;
import sun.print.PrintJob2D;
import java.awt.dnd.DragSource;
@@ -247,11 +248,17 @@ public final class WToolkit extends SunToolkit implements Runnable {
*/
AWTAutoShutdown.notifyToolkitThreadBusy();
- // Find a root TG and attach Appkit thread to it
+ // Find a root TG and attach toolkit thread to it
ThreadGroup rootTG = AccessController.doPrivileged(
(PrivilegedAction) ThreadGroupUtils::getRootThreadGroup);
if (!startToolkitThread(this, rootTG)) {
- Thread toolkitThread = new Thread(rootTG, this, "AWT-Windows");
+ String name = "AWT-Windows";
+ Thread toolkitThread;
+ if (System.getSecurityManager() == null) {
+ toolkitThread = new Thread(rootTG, this, name);
+ } else {
+ toolkitThread = new InnocuousThread(this, name);
+ }
toolkitThread.setDaemon(true);
toolkitThread.start();
}
@@ -278,7 +285,12 @@ public final class WToolkit extends SunToolkit implements Runnable {
private void registerShutdownHook() {
AccessController.doPrivileged((PrivilegedAction) () -> {
- Thread shutdown = new Thread(ThreadGroupUtils.getRootThreadGroup(), this::shutdown);
+ Thread shutdown;
+ if (System.getSecurityManager() == null) {
+ shutdown = new Thread(ThreadGroupUtils.getRootThreadGroup(), this::shutdown);
+ } else {
+ shutdown = new InnocuousThread(this::shutdown);
+ }
shutdown.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(shutdown);
return null;
diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java
index 1ab30124296..fd4bd592402 100644
--- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java
+++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java
@@ -48,6 +48,7 @@ import sun.java2d.SurfaceData;
import sun.java2d.windows.GDIWindowSurfaceData;
import sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData;
import sun.java2d.windows.WindowsFlags;
+import sun.misc.InnocuousThread;
/**
* This class handles rendering to the screen with the D3D pipeline.
@@ -92,22 +93,25 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager
public D3DScreenUpdateManager() {
done = false;
- AccessController.doPrivileged(
- (PrivilegedAction) () -> {
- ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
- Thread shutdown = new Thread(rootTG, () -> {
- done = true;
- wakeUpUpdateThread();
- });
- shutdown.setContextClassLoader(null);
- try {
- Runtime.getRuntime().addShutdownHook(shutdown);
- } catch (Exception e) {
- done = true;
- }
- return null;
- }
- );
+ AccessController.doPrivileged((PrivilegedAction) () -> {
+ Runnable shutdownRunnable = () -> {
+ done = true;
+ wakeUpUpdateThread();
+ };
+ Thread shutdown;
+ if (System.getSecurityManager() == null) {
+ shutdown = new Thread(ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable);
+ } else {
+ shutdown = new InnocuousThread(shutdownRunnable);
+ }
+ shutdown.setContextClassLoader(null);
+ try {
+ Runtime.getRuntime().addShutdownHook(shutdown);
+ } catch (Exception e) {
+ done = true;
+ }
+ return null;
+ });
}
/**
@@ -345,17 +349,21 @@ public class D3DScreenUpdateManager extends ScreenUpdateManager
*/
private synchronized void startUpdateThread() {
if (screenUpdater == null) {
- screenUpdater = AccessController.doPrivileged(
- (PrivilegedAction) () -> {
- ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();
- Thread t = new Thread(rootTG,
- D3DScreenUpdateManager.this,
- "D3D Screen Updater");
- // REMIND: should it be higher?
- t.setPriority(Thread.NORM_PRIORITY + 2);
- t.setDaemon(true);
- return t;
- });
+ screenUpdater = AccessController.doPrivileged((PrivilegedAction) () -> {
+ Thread t;
+ String name = "D3D Screen Updater";
+ if (System.getSecurityManager() == null) {
+ t = new Thread(ThreadGroupUtils.getRootThreadGroup(),
+ D3DScreenUpdateManager.this,
+ name);
+ } else {
+ t = new InnocuousThread(D3DScreenUpdateManager.this, name);
+ }
+ // REMIND: should it be higher?
+ t.setPriority(Thread.NORM_PRIORITY + 2);
+ t.setDaemon(true);
+ return t;
+ });
screenUpdater.start();
} else {
wakeUpUpdateThread();
diff --git a/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java b/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java
index b3f56c8b55c..903673efdbf 100644
--- a/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java
+++ b/jdk/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java
@@ -25,6 +25,8 @@
package sun.print;
+import sun.misc.ManagedLocalsThread;
+
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -97,7 +99,12 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
return;
}
// start the printer listener thread
- PrinterChangeListener thr = new PrinterChangeListener();
+ Thread thr;
+ if (System.getSecurityManager() == null) {
+ thr = new Thread(new PrinterChangeListener());
+ } else {
+ thr = new ManagedLocalsThread(new PrinterChangeListener());
+ }
thr.setDaemon(true);
thr.start();
} /* else condition ought to never happen! */
@@ -316,12 +323,13 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
return defaultPrintService;
}
- class PrinterChangeListener extends Thread {
+ class PrinterChangeListener implements Runnable {
long chgObj;
PrinterChangeListener() {
chgObj = notifyFirstPrinterChange(null);
}
+ @Override
public void run() {
if (chgObj != -1) {
while (true) {
diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_InputTextInfor.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_InputTextInfor.cpp
index 4ccf0d55e3e..de9248f1372 100644
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_InputTextInfor.cpp
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_InputTextInfor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -310,6 +310,8 @@ int AwtInputTextInfor::GetClauseInfor(int*& lpBndClauseW, jstring*& lpReadingCla
readingMergedClauseW = new jstring[cMergedClauseW];
} catch (std::bad_alloc&) {
delete [] bndMergedClauseW;
+ delete [] bndClauseW;
+ delete [] readingClauseW;
throw;
}
@@ -394,6 +396,8 @@ int AwtInputTextInfor::GetAttributeInfor(int*& lpBndAttrW, BYTE*& lpValAttrW) {
valMergedAttrW = new BYTE[cMergedAttrW];
} catch (std::bad_alloc&) {
delete [] bndMergedAttrW;
+ delete [] bndAttrW;
+ delete [] valAttrW;
throw;
}
bndMergedAttrW[0] = 0;
diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp
index 7952f1e7382..ef376f31a3b 100644
--- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp
+++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TrayIcon.cpp
@@ -709,7 +709,7 @@ void AwtTrayIcon::SetToolTip(LPCTSTR tooltip)
{
if (tooltip == NULL) {
m_nid.szTip[0] = '\0';
- } else if (lstrlen(tooltip) > TRAY_ICON_TOOLTIP_MAX_SIZE) {
+ } else if (lstrlen(tooltip) >= TRAY_ICON_TOOLTIP_MAX_SIZE) {
_tcsncpy(m_nid.szTip, tooltip, TRAY_ICON_TOOLTIP_MAX_SIZE);
m_nid.szTip[TRAY_ICON_TOOLTIP_MAX_SIZE - 1] = '\0';
} else {
@@ -814,7 +814,7 @@ void AwtTrayIcon::DisplayMessage(LPCTSTR caption, LPCTSTR text, LPCTSTR msgType)
if (caption[0] == '\0') {
m_nid.szInfoTitle[0] = '\0';
- } else if (lstrlen(caption) > TRAY_ICON_BALLOON_TITLE_MAX_SIZE) {
+ } else if (lstrlen(caption) >= TRAY_ICON_BALLOON_TITLE_MAX_SIZE) {
_tcsncpy(m_nid.szInfoTitle, caption, TRAY_ICON_BALLOON_TITLE_MAX_SIZE);
m_nid.szInfoTitle[TRAY_ICON_BALLOON_TITLE_MAX_SIZE - 1] = '\0';
@@ -827,7 +827,7 @@ void AwtTrayIcon::DisplayMessage(LPCTSTR caption, LPCTSTR text, LPCTSTR msgType)
m_nid.szInfo[0] = ' ';
m_nid.szInfo[1] = '\0';
- } else if (lstrlen(text) > TRAY_ICON_BALLOON_INFO_MAX_SIZE) {
+ } else if (lstrlen(text) >= TRAY_ICON_BALLOON_INFO_MAX_SIZE) {
_tcsncpy(m_nid.szInfo, text, TRAY_ICON_BALLOON_INFO_MAX_SIZE);
m_nid.szInfo[TRAY_ICON_BALLOON_INFO_MAX_SIZE - 1] = '\0';
diff --git a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
index 0f536b202e9..972b74a7efb 100644
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java
@@ -34,6 +34,7 @@ import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import sun.misc.JavaAWTAccess;
+import sun.misc.ManagedLocalsThread;
import sun.misc.SharedSecrets;
/**
@@ -248,7 +249,7 @@ public class LogManager {
// This private class is used as a shutdown hook.
// It does a "reset" to close all open handlers.
- private class Cleaner extends Thread {
+ private class Cleaner extends ManagedLocalsThread {
private Cleaner() {
/* Set context class loader to null in order to avoid
diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java
index b8549f255a9..85f248311cb 100644
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientCommunicatorAdmin.java
@@ -30,6 +30,7 @@ import java.io.InterruptedIOException;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
+import sun.misc.ManagedLocalsThread;
public abstract class ClientCommunicatorAdmin {
private static volatile long threadNo = 1;
@@ -40,7 +41,11 @@ public abstract class ClientCommunicatorAdmin {
if (period > 0) {
checker = new Checker();
- Thread t = new Thread(checker, "JMX client heartbeat " + ++threadNo);
+ Thread t = new ManagedLocalsThread(
+ checker,
+ "JMX client heartbeat " + (++threadNo)
+ );
+
t.setDaemon(true);
t.start();
} else
diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java
index 4d3ba6db0d8..05abd0ceeb5 100644
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java
@@ -52,6 +52,7 @@ import javax.management.remote.TargetedNotification;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
import java.rmi.UnmarshalException;
+import sun.misc.ManagedLocalsThread;
public abstract class ClientNotifForwarder {
@@ -90,10 +91,8 @@ public abstract class ClientNotifForwarder {
throw new IllegalArgumentException("More than one command");
this.command = command;
if (thread == null) {
- thread = new Thread() {
-
- @Override
- public void run() {
+ thread = new ManagedLocalsThread(
+ ()-> {
while (true) {
Runnable r;
synchronized (LinearExecutor.this) {
@@ -107,10 +106,10 @@ public abstract class ClientNotifForwarder {
}
r.run();
}
- }
- };
+ },
+ "ClientNotifForwarder-" + ++threadId
+ );
thread.setDaemon(true);
- thread.setName("ClientNotifForwarder-" + ++threadId);
thread.start();
}
}
diff --git a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java
index bb09f62bdb9..f943bf5ce68 100644
--- a/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java
+++ b/jdk/src/java.management/share/classes/com/sun/jmx/remote/internal/ServerCommunicatorAdmin.java
@@ -25,9 +25,9 @@
package com.sun.jmx.remote.internal;
-import java.io.IOException;
import com.sun.jmx.remote.util.ClassLogger;
+import sun.misc.ManagedLocalsThread;
public abstract class ServerCommunicatorAdmin {
public ServerCommunicatorAdmin(long timeout) {
@@ -42,7 +42,7 @@ public abstract class ServerCommunicatorAdmin {
timestamp = 0;
if (timeout < Long.MAX_VALUE) {
Runnable timeoutTask = new Timeout();
- final Thread t = new Thread(timeoutTask);
+ final Thread t = new ManagedLocalsThread(timeoutTask);
t.setName("JMX server connection timeout " + t.getId());
// If you change this name you will need to change a unit test
// (NoServerTimeoutTest)
diff --git a/jdk/src/java.management/share/classes/javax/management/AttributeValueExp.java b/jdk/src/java.management/share/classes/javax/management/AttributeValueExp.java
index f2d6f7684db..66475a899bf 100644
--- a/jdk/src/java.management/share/classes/javax/management/AttributeValueExp.java
+++ b/jdk/src/java.management/share/classes/javax/management/AttributeValueExp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -93,11 +93,10 @@ public class AttributeValueExp implements ValueExp {
*
* @return The ValueExp.
*
- * @exception BadAttributeValueExpException
- * @exception InvalidApplicationException
- * @exception BadStringOperationException
- * @exception BadBinaryOpValueExpException
- *
+ * @throws BadStringOperationException {@inheritDoc}
+ * @throws BadBinaryOpValueExpException {@inheritDoc}
+ * @throws BadAttributeValueExpException {@inheritDoc}
+ * @throws InvalidApplicationException {@inheritDoc}
*/
@Override
public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException,
diff --git a/jdk/src/java.management/share/classes/javax/management/DescriptorKey.java b/jdk/src/java.management/share/classes/javax/management/DescriptorKey.java
index c9bd8b2963c..814e234d35c 100644
--- a/jdk/src/java.management/share/classes/javax/management/DescriptorKey.java
+++ b/jdk/src/java.management/share/classes/javax/management/DescriptorKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -168,5 +168,9 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DescriptorKey {
+ /**
+ * Returns the descriptor key.
+ * @return the descriptor key
+ */
String value();
}
diff --git a/jdk/src/java.management/share/classes/javax/management/DynamicMBean.java b/jdk/src/java.management/share/classes/javax/management/DynamicMBean.java
index 80e3007e7fd..129fb99a3f5 100644
--- a/jdk/src/java.management/share/classes/javax/management/DynamicMBean.java
+++ b/jdk/src/java.management/share/classes/javax/management/DynamicMBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@ public interface DynamicMBean {
*
* @return The value of the attribute retrieved.
*
- * @exception AttributeNotFoundException
+ * @exception AttributeNotFoundException if specified attribute does not exist or cannot be retrieved
* @exception MBeanException Wraps a java.lang.Exception thrown by the MBean's getter.
* @exception ReflectionException Wraps a java.lang.Exception thrown while trying to invoke the getter.
*
@@ -58,8 +58,8 @@ public interface DynamicMBean {
* @param attribute The identification of the attribute to
* be set and the value it is to be set to.
*
- * @exception AttributeNotFoundException
- * @exception InvalidAttributeValueException
+ * @exception AttributeNotFoundException if specified attribute does not exist or cannot be retrieved
+ * @exception InvalidAttributeValueException if value specified is not valid for the attribute
* @exception MBeanException Wraps a java.lang.Exception thrown by the MBean's setter.
* @exception ReflectionException Wraps a java.lang.Exception thrown while trying to invoke the MBean's setter.
*
diff --git a/jdk/src/java.management/share/classes/javax/management/ImmutableDescriptor.java b/jdk/src/java.management/share/classes/javax/management/ImmutableDescriptor.java
index 60e75fab315..eb0a02d41dd 100644
--- a/jdk/src/java.management/share/classes/javax/management/ImmutableDescriptor.java
+++ b/jdk/src/java.management/share/classes/javax/management/ImmutableDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,8 @@ public class ImmutableDescriptor implements Descriptor {
/**
* Construct a descriptor containing the given fields and values.
*
+ * @param fieldNames the field names
+ * @param fieldValues the field values
* @throws IllegalArgumentException if either array is null, or
* if the arrays have different sizes, or
* if a field name is null or empty, or if the same field name
@@ -81,6 +83,7 @@ public class ImmutableDescriptor implements Descriptor {
* is {@code a=b=c} then the field name is {@code a} and its value
* is {@code b=c}.
*
+ * @param fields the field names
* @throws IllegalArgumentException if the parameter is null, or
* if a field name is empty, or if the same field name appears
* more than once, or if one of the strings does not contain
@@ -94,6 +97,7 @@ public class ImmutableDescriptor implements Descriptor {
*
Construct a descriptor where the names and values of the fields
* are the keys and values of the given Map.
*
+ * @param fields the field names and values
* @throws IllegalArgumentException if the parameter is null, or
* if a field name is null or empty, or if the same field name appears
* more than once (which can happen because field names are not case
diff --git a/jdk/src/java.management/share/classes/javax/management/QueryExp.java b/jdk/src/java.management/share/classes/javax/management/QueryExp.java
index e4f76577a6f..819855ee5e4 100644
--- a/jdk/src/java.management/share/classes/javax/management/QueryExp.java
+++ b/jdk/src/java.management/share/classes/javax/management/QueryExp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -53,10 +53,13 @@ public interface QueryExp extends Serializable {
*
* @return True if the query was successfully applied to the MBean, false otherwise
*
- * @exception BadStringOperationException
- * @exception BadBinaryOpValueExpException
- * @exception BadAttributeValueExpException
- * @exception InvalidApplicationException
+ * @throws BadStringOperationException when an invalid string
+ * operation is passed to a method for constructing a query
+ * @throws BadBinaryOpValueExpException when an invalid expression
+ * is passed to a method for constructing a query
+ * @throws BadAttributeValueExpException when an invalid MBean
+ * attribute is passed to a query constructing method
+ * @throws InvalidApplicationException when an invalid apply is attempted
*/
public boolean apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException,
BadAttributeValueExpException, InvalidApplicationException ;
diff --git a/jdk/src/java.management/share/classes/javax/management/StandardEmitterMBean.java b/jdk/src/java.management/share/classes/javax/management/StandardEmitterMBean.java
index 250d109679a..c4ead04d5f4 100644
--- a/jdk/src/java.management/share/classes/javax/management/StandardEmitterMBean.java
+++ b/jdk/src/java.management/share/classes/javax/management/StandardEmitterMBean.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,7 @@ public class StandardEmitterMBean extends StandardMBean
* that will have no effect on this object's
* {@code getNotificationInfo()}.
*
+ * @param the implementation type of the MBean
* @param implementation the implementation of the MBean interface.
* @param mbeanInterface a Standard MBean interface.
* @param emitter the object that will handle notifications.
@@ -129,6 +130,7 @@ public class StandardEmitterMBean extends StandardMBean
* that will have no effect on this object's
* {@code getNotificationInfo()}.
*
+ * @param the implementation type of the MBean
* @param implementation the implementation of the MBean interface.
* @param mbeanInterface a Standard MBean interface.
* @param isMXBean If true, the {@code mbeanInterface} parameter
diff --git a/jdk/src/java.management/share/classes/javax/management/StringValueExp.java b/jdk/src/java.management/share/classes/javax/management/StringValueExp.java
index 629117fb228..ed9b3c3539e 100644
--- a/jdk/src/java.management/share/classes/javax/management/StringValueExp.java
+++ b/jdk/src/java.management/share/classes/javax/management/StringValueExp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -95,11 +95,12 @@ public class StringValueExp implements ValueExp {
*
* @return The ValueExp.
*
- * @exception BadStringOperationException
- * @exception BadBinaryOpValueExpException
- * @exception BadAttributeValueExpException
- * @exception InvalidApplicationException
+ * @throws BadStringOperationException {@inheritDoc}
+ * @throws BadBinaryOpValueExpException {@inheritDoc}
+ * @throws BadAttributeValueExpException {@inheritDoc}
+ * @throws InvalidApplicationException {@inheritDoc}
*/
+ @Override
public ValueExp apply(ObjectName name) throws BadStringOperationException, BadBinaryOpValueExpException,
BadAttributeValueExpException, InvalidApplicationException {
return this;
diff --git a/jdk/src/java.management/share/classes/javax/management/ValueExp.java b/jdk/src/java.management/share/classes/javax/management/ValueExp.java
index 7a0619122de..1afe1b6a44f 100644
--- a/jdk/src/java.management/share/classes/javax/management/ValueExp.java
+++ b/jdk/src/java.management/share/classes/javax/management/ValueExp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -80,10 +80,13 @@ public interface ValueExp extends java.io.Serializable {
*
* @return The ValueExp.
*
- * @exception BadStringOperationException
- * @exception BadBinaryOpValueExpException
- * @exception BadAttributeValueExpException
- * @exception InvalidApplicationException
+ * @throws BadStringOperationException when an invalid string
+ * operation is passed to a method for constructing a query
+ * @throws BadBinaryOpValueExpException when an invalid expression
+ * is passed to a method for constructing a query
+ * @throws BadAttributeValueExpException when an invalid MBean
+ * attribute is passed to a query constructing method
+ * @throws InvalidApplicationException when an invalid apply is attempted
*/
public ValueExp apply(ObjectName name)
throws BadStringOperationException, BadBinaryOpValueExpException,
diff --git a/jdk/src/java.management/share/classes/javax/management/modelmbean/ModelMBeanInfo.java b/jdk/src/java.management/share/classes/javax/management/modelmbean/ModelMBeanInfo.java
index 8894ae882f7..642cddd3d27 100644
--- a/jdk/src/java.management/share/classes/javax/management/modelmbean/ModelMBeanInfo.java
+++ b/jdk/src/java.management/share/classes/javax/management/modelmbean/ModelMBeanInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -307,6 +307,7 @@ public interface ModelMBeanInfo
/**
* Creates and returns a copy of this object.
+ * @return a copy of this object
*/
public java.lang.Object clone();
diff --git a/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java b/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java
index bf89b06cb9f..6276fb33b50 100644
--- a/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java
+++ b/jdk/src/java.management/share/classes/javax/management/monitor/Monitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,7 @@ import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import static javax.management.monitor.MonitorNotification.*;
+import sun.misc.ManagedLocalsThread;
/**
* Defines the part common to all monitor MBeans.
@@ -386,7 +387,7 @@ public abstract class Monitor
*
* @return The name of the monitor MBean registered.
*
- * @exception Exception
+ * @exception Exception if something goes wrong
*/
public ObjectName preRegister(MBeanServer server, ObjectName name)
throws Exception {
@@ -415,7 +416,7 @@ public abstract class Monitor
*
* Stops the monitor.
*
- * @exception Exception
+ * @exception Exception if something goes wrong
*/
public void preDeregister() throws Exception {
@@ -1636,12 +1637,12 @@ public abstract class Monitor
}
public Thread newThread(Runnable r) {
- Thread t = new Thread(group,
- r,
- namePrefix +
- threadNumber.getAndIncrement() +
- nameSuffix,
- 0);
+ Thread t = new ManagedLocalsThread(
+ group,
+ r,
+ namePrefix + threadNumber.getAndIncrement() + nameSuffix
+ );
+
t.setDaemon(true);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
diff --git a/jdk/src/java.management/share/classes/javax/management/openmbean/ArrayType.java b/jdk/src/java.management/share/classes/javax/management/openmbean/ArrayType.java
index 2d12347044a..53665e8f2f9 100644
--- a/jdk/src/java.management/share/classes/javax/management/openmbean/ArrayType.java
+++ b/jdk/src/java.management/share/classes/javax/management/openmbean/ArrayType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -793,6 +793,7 @@ public class ArrayType extends OpenType {
* array type description = 3-dimension array of java.lang.String
* }
*
+ * @param the Java type that described instances must have
* @param elementType the open type of element values contained
* in the arrays described by this ArrayType
* instance; must be an instance of either
@@ -800,7 +801,7 @@ public class ArrayType extends OpenType {
* TabularType or another ArrayType
* with a SimpleType, CompositeType
* or TabularType as its elementType.
- *
+ * @return an {@code ArrayType} instance
* @throws OpenDataException if elementType's className is not
* one of the allowed Java class names for open
* data.
@@ -834,12 +835,14 @@ public class ArrayType extends OpenType {
* array type description = 3-dimension array of int
* }
*
+ * @param the Java type that described instances must have
* @param arrayClass a primitive array class such as {@code int[].class},
* {@code boolean[][].class}, etc. The {@link
* #getElementOpenType()} method of the returned
* {@code ArrayType} returns the {@link SimpleType}
* corresponding to the wrapper type of the primitive
* type of the array.
+ * @return an {@code ArrayType} instance
*
* @throws IllegalArgumentException if arrayClass is not
* a primitive array.
diff --git a/jdk/src/java.management/share/classes/javax/management/timer/Timer.java b/jdk/src/java.management/share/classes/javax/management/timer/Timer.java
index 461b68e0dbd..b199e8e258a 100644
--- a/jdk/src/java.management/share/classes/javax/management/timer/Timer.java
+++ b/jdk/src/java.management/share/classes/javax/management/timer/Timer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -195,7 +195,7 @@ public class Timer extends NotificationBroadcasterSupport
*
* @return The name of the timer MBean registered.
*
- * @exception java.lang.Exception
+ * @exception java.lang.Exception if something goes wrong
*/
public ObjectName preRegister(MBeanServer server, ObjectName name)
throws java.lang.Exception {
@@ -217,7 +217,7 @@ public class Timer extends NotificationBroadcasterSupport
*
* Stops the timer.
*
- * @exception java.lang.Exception
+ * @exception java.lang.Exception if something goes wrong
*/
public void preDeregister() throws java.lang.Exception {
diff --git a/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java b/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java
index a22873a0700..a90705d577a 100644
--- a/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java
+++ b/jdk/src/java.management/share/classes/sun/management/jdp/JdpController.java
@@ -34,6 +34,7 @@ import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import sun.management.VMManagement;
+import sun.misc.ManagedLocalsThread;
/**
* JdpController is responsible to create and manage a broadcast loop
@@ -219,7 +220,7 @@ public final class JdpController {
controller = new JDPControllerRunner(bcast, packet, pause);
- Thread t = new Thread(controller, "JDP broadcaster");
+ Thread t = new ManagedLocalsThread(controller, "JDP broadcaster");
t.setDaemon(true);
t.start();
}
diff --git a/jdk/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java b/jdk/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java
index 6553ff6ed78..dc54a0d539b 100644
--- a/jdk/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java
+++ b/jdk/src/java.prefs/macosx/classes/java/util/prefs/MacOSXPreferencesFile.java
@@ -31,6 +31,7 @@ import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import java.lang.ref.WeakReference;
+import sun.misc.ManagedLocalsThread;
/*
@@ -343,7 +344,7 @@ class MacOSXPreferencesFile {
{
if (timer == null) {
timer = new Timer(true); // daemon
- Thread flushThread = new Thread() {
+ Thread flushThread = new ManagedLocalsThread() {
@Override
public void run() {
flushWorld();
diff --git a/jdk/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java b/jdk/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java
index a840dffab95..fd3ba69902a 100644
--- a/jdk/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java
+++ b/jdk/src/java.prefs/share/classes/java/util/prefs/AbstractPreferences.java
@@ -29,6 +29,7 @@ import java.util.*;
import java.io.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import sun.misc.ManagedLocalsThread;
// These imports needed only as a workaround for a JavaDoc bug
import java.lang.Integer;
import java.lang.Long;
@@ -1470,7 +1471,7 @@ public abstract class AbstractPreferences extends Preferences {
* A single background thread ("the event notification thread") monitors
* the event queue and delivers events that are placed on the queue.
*/
- private static class EventDispatchThread extends Thread {
+ private static class EventDispatchThread extends ManagedLocalsThread {
public void run() {
while(true) {
// Wait on eventQueue till an event is present
diff --git a/jdk/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java b/jdk/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java
index 7bcd1d3ad24..9d412ed7f67 100644
--- a/jdk/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java
+++ b/jdk/src/java.prefs/unix/classes/java/util/prefs/FileSystemPreferences.java
@@ -30,7 +30,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException;
-
+import sun.misc.ManagedLocalsThread;
import sun.util.logging.PlatformLogger;
/**
@@ -450,7 +450,7 @@ class FileSystemPreferences extends AbstractPreferences {
// Add shutdown hook to flush cached prefs on normal termination
AccessController.doPrivileged(new PrivilegedAction() {
public Void run() {
- Runtime.getRuntime().addShutdownHook(new Thread() {
+ Runtime.getRuntime().addShutdownHook(new ManagedLocalsThread() {
public void run() {
syncTimer.cancel();
syncWorld();
diff --git a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/Card.java b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/Card.java
index b91738f0056..49ec9d48edc 100644
--- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/Card.java
+++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/Card.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -69,6 +69,7 @@ public abstract class Card {
* Returns the CardChannel for the basic logical channel. The basic
* logical channel has a channel number of 0.
*
+ * @return the CardChannel for the basic logical channel
* @throws SecurityException if a SecurityManager exists and the
* caller does not have the required
* {@linkplain CardPermission permission}
@@ -82,6 +83,7 @@ public abstract class Card {
* opened by issuing a MANAGE CHANNEL command that should use
* the format [00 70 00 00 01].
*
+ * @return the logical channel which has been opened
* @throws SecurityException if a SecurityManager exists and the
* caller does not have the required
* {@linkplain CardPermission permission}
@@ -137,6 +139,7 @@ public abstract class Card {
*
* @param controlCode the control code of the command
* @param command the command data
+ * @return the response from the terminal device
*
* @throws SecurityException if a SecurityManager exists and the
* caller does not have the required
diff --git a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardTerminal.java b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardTerminal.java
index 740681890f6..eb5f305ffcd 100644
--- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardTerminal.java
+++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardTerminal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -83,6 +83,7 @@ public abstract class CardTerminal {
* @throws SecurityException if a SecurityManager exists and the
* caller does not have the required
* {@linkplain CardPermission permission}
+ * @return the card the connection has been established with
*/
public abstract Card connect(String protocol) throws CardException;
diff --git a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardTerminals.java b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardTerminals.java
index 94801368e79..f471b43b547 100644
--- a/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardTerminals.java
+++ b/jdk/src/java.smartcardio/share/classes/javax/smartcardio/CardTerminals.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -105,6 +105,7 @@ public abstract class CardTerminals {
* Returns the terminal with the specified name or null if no such
* terminal exists.
*
+ * @param name the terminal name
* @return the terminal with the specified name or null if no such
* terminal exists.
*
diff --git a/jdk/src/java.transaction/share/classes/javax/transaction/InvalidTransactionException.java b/jdk/src/java.transaction/share/classes/javax/transaction/InvalidTransactionException.java
index 5d0c699b887..761b577fc6c 100644
--- a/jdk/src/java.transaction/share/classes/javax/transaction/InvalidTransactionException.java
+++ b/jdk/src/java.transaction/share/classes/javax/transaction/InvalidTransactionException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,10 +39,17 @@ package javax.transaction;
@SuppressWarnings("serial") // serialVersionUID intentionally omitted
public class InvalidTransactionException extends java.rmi.RemoteException {
+ /**
+ * Constructs an {@code InvalidTransactionException}.
+ */
public InvalidTransactionException() {
super();
}
+ /**
+ * Constructs an {@code InvalidTransactionException}.
+ * @param msg the detail message
+ */
public InvalidTransactionException(String msg) {
super(msg);
}
diff --git a/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRequiredException.java b/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRequiredException.java
index ee2ccbb8040..7be9b2b6c6b 100644
--- a/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRequiredException.java
+++ b/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRequiredException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,10 +38,17 @@ package javax.transaction;
@SuppressWarnings("serial") // serialVersionUID intentionally omitted
public class TransactionRequiredException extends java.rmi.RemoteException {
+ /**
+ * Constructs a {@code TransactionRequiredException}.
+ */
public TransactionRequiredException() {
super();
}
+ /**
+ * Constructs a {@code TransactionRequiredException}.
+ * @param msg the detail message
+ */
public TransactionRequiredException(String msg) {
super(msg);
}
diff --git a/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRolledbackException.java b/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRolledbackException.java
index 73ee335beee..2b4f6ad865d 100644
--- a/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRolledbackException.java
+++ b/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRolledbackException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,10 +41,17 @@ package javax.transaction;
@SuppressWarnings("serial") // serialVersionUID intentionally omitted
public class TransactionRolledbackException extends java.rmi.RemoteException {
+ /**
+ * Constructs a {@code TransactionRolledbackException}.
+ */
public TransactionRolledbackException() {
super();
}
+ /**
+ * Constructs a {@code TransactionRolledbackException}.
+ * @param msg the detail message
+ */
public TransactionRolledbackException(String msg) {
super(msg);
}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java
new file mode 100644
index 00000000000..7b0f8c29e06
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java
@@ -0,0 +1,1526 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.accessibility.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import sun.awt.AWTPermissions;
+
+/**
+ *
The {@code AWTEventMonitor} implements a suite of listeners that are
+ * conditionally installed on every AWT component instance in the Java
+ * Virtual Machine. The events captured by these listeners are made
+ * available through a unified set of listeners supported by {@code AWTEventMonitor}.
+ * With this, all the individual events on each of the AWT component
+ * instances are funneled into one set of listeners broken down by category
+ * (see {@link EventID} for the categories).
+ *
This class depends upon {@link EventQueueMonitor}, which provides the base
+ * level support for capturing the top-level containers as they are created.
+ */
+
+@jdk.Exported
+public class AWTEventMonitor {
+
+ static private boolean runningOnJDK1_4 = false;
+
+ /**
+ * The current component with keyboard focus.
+ *
+ * @see #getComponentWithFocus
+ *
+ * @deprecated This field is unused; to get the component with focus use the
+ * getComponentWithFocus method.
+ */
+ @Deprecated
+ static protected Component componentWithFocus = null;
+
+ static private Component componentWithFocus_private = null;
+
+ // Low-level listeners
+ /**
+ * The current list of registered ComponentListener classes.
+ *
+ * @see #addComponentListener
+ * @see #removeComponentListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected ComponentListener componentListener = null;
+
+ static private ComponentListener componentListener_private = null;
+
+ /**
+ * The current list of registered ContainerListener classes.
+ *
+ * @see #addContainerListener
+ * @see #removeContainerListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected ContainerListener containerListener = null;
+
+ static private ContainerListener containerListener_private = null;
+
+ /**
+ * The current list of registered FocusListener classes.
+ *
+ * @see #addFocusListener
+ * @see #removeFocusListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected FocusListener focusListener = null;
+
+ static private FocusListener focusListener_private = null;
+
+ /**
+ * The current list of registered KeyListener classes.
+ *
+ * @see #addKeyListener
+ * @see #removeKeyListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected KeyListener keyListener = null;
+
+ static private KeyListener keyListener_private = null;
+
+ /**
+ * The current list of registered MouseListener classes.
+ *
+ * @see #addMouseListener
+ * @see #removeMouseListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected MouseListener mouseListener = null;
+
+ static private MouseListener mouseListener_private = null;
+
+ /**
+ * The current list of registered MouseMotionListener classes.
+ *
+ * @see #addMouseMotionListener
+ * @see #removeMouseMotionListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected MouseMotionListener mouseMotionListener = null;
+
+ static private MouseMotionListener mouseMotionListener_private = null;
+
+ /**
+ * The current list of registered WindowListener classes.
+ *
+ * @see #addWindowListener
+ * @see #removeWindowListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected WindowListener windowListener = null;
+
+ static private WindowListener windowListener_private = null;
+
+
+ // Semantic listeners
+ /**
+ * The current list of registered ActionListener classes.
+ *
+ * @see #addActionListener
+ * @see #removeActionListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected ActionListener actionListener = null;
+
+ static private ActionListener actionListener_private = null;
+
+ /**
+ * The current list of registered AdjustmentListener classes.
+ *
+ * @see #addAdjustmentListener
+ * @see #removeAdjustmentListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected AdjustmentListener adjustmentListener = null;
+
+ static private AdjustmentListener adjustmentListener_private = null;
+
+ /**
+ * The current list of registered ItemListener classes.
+ *
+ * @see #addItemListener
+ * @see #removeItemListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected ItemListener itemListener = null;
+
+ static private ItemListener itemListener_private = null;
+
+ /**
+ * The current list of registered TextListener classes.
+ *
+ * @see #addTextListener
+ * @see #removeTextListener
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected TextListener textListener = null;
+
+ static private TextListener textListener_private = null;
+
+
+ /**
+ * The actual listener that is installed on the component instances.
+ * This listener calls the other registered listeners when an event
+ * occurs. By doing things this way, the actual number of listeners
+ * installed on a component instance is drastically reduced.
+ *
+ * @deprecated This field is unused.
+ */
+ @Deprecated
+ static protected AWTEventsListener awtListener = new AWTEventsListener();
+
+ static private final AWTEventsListener awtListener_private = new AWTEventsListener();
+
+ /**
+ * Returns the component that currently has keyboard focus. The return
+ * value can be null.
+ *
+ * @return the component that has keyboard focus
+ */
+ static public Component getComponentWithFocus() {
+ return componentWithFocus_private;
+ }
+
+ /*
+ * Check permissions
+ */
+ static private void checkInstallPermission() {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkPermission(AWTPermissions.ALL_AWT_EVENTS_PERMISSION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#COMPONENT COMPONENT}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeComponentListener
+ */
+ static public void addComponentListener(ComponentListener l) {
+ if (componentListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.COMPONENT);
+ }
+ componentListener_private = AWTEventMulticaster.add(componentListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#COMPONENT COMPONENT} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addComponentListener
+ */
+ static public void removeComponentListener(ComponentListener l) {
+ componentListener_private = AWTEventMulticaster.remove(componentListener_private, l);
+ if (componentListener_private == null) {
+ awtListener_private.removeListeners(EventID.COMPONENT);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#CONTAINER CONTAINER}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeContainerListener
+ */
+ static public void addContainerListener(ContainerListener l) {
+ containerListener_private = AWTEventMulticaster.add(containerListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#CONTAINER CONTAINER} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addContainerListener
+ */
+ static public void removeContainerListener(ContainerListener l) {
+ containerListener_private = AWTEventMulticaster.remove(containerListener_private, l);
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#FOCUS FOCUS} events
+ * on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeFocusListener
+ */
+ static public void addFocusListener(FocusListener l) {
+ focusListener_private = AWTEventMulticaster.add(focusListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives {@link EventID#FOCUS FOCUS}
+ * events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addFocusListener
+ */
+ static public void removeFocusListener(FocusListener l) {
+ focusListener_private = AWTEventMulticaster.remove(focusListener_private, l);
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#KEY KEY} events on each
+ * component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeKeyListener
+ */
+ static public void addKeyListener(KeyListener l) {
+ if (keyListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.KEY);
+ }
+ keyListener_private = AWTEventMulticaster.add(keyListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives {@link EventID#KEY KEY}
+ * events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addKeyListener
+ */
+ static public void removeKeyListener(KeyListener l) {
+ keyListener_private = AWTEventMulticaster.remove(keyListener_private, l);
+ if (keyListener_private == null) {
+ awtListener_private.removeListeners(EventID.KEY);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#MOUSE MOUSE} events
+ * on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeMouseListener
+ */
+ static public void addMouseListener(MouseListener l) {
+ if (mouseListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.MOUSE);
+ }
+ mouseListener_private = AWTEventMulticaster.add(mouseListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#MOUSE MOUSE} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addMouseListener
+ */
+ static public void removeMouseListener(MouseListener l) {
+ mouseListener_private = AWTEventMulticaster.remove(mouseListener_private, l);
+ if (mouseListener_private == null) {
+ awtListener_private.removeListeners(EventID.MOUSE);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all mouse {@link EventID#MOTION MOTION}
+ * events on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeMouseMotionListener
+ */
+ static public void addMouseMotionListener(MouseMotionListener l) {
+ if (mouseMotionListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.MOTION);
+ }
+ mouseMotionListener_private = AWTEventMulticaster.add(mouseMotionListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#MOTION MOTION} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addMouseMotionListener
+ */
+ static public void removeMouseMotionListener(MouseMotionListener l) {
+ mouseMotionListener_private = AWTEventMulticaster.remove(mouseMotionListener_private, l);
+ if (mouseMotionListener_private == null) {
+ awtListener_private.removeListeners(EventID.MOTION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#WINDOW WINDOW}
+ * events on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeWindowListener
+ */
+ static public void addWindowListener(WindowListener l) {
+ if (windowListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.WINDOW);
+ }
+ windowListener_private = AWTEventMulticaster.add(windowListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#WINDOW WINDOW} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addWindowListener
+ */
+ static public void removeWindowListener(WindowListener l) {
+ windowListener_private = AWTEventMulticaster.remove(windowListener_private, l);
+ if (windowListener_private == null) {
+ awtListener_private.removeListeners(EventID.WINDOW);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#ACTION ACTION}
+ * events on each component instance in the Java Virtual Machine when they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeActionListener
+ */
+ static public void addActionListener(ActionListener l) {
+ if (actionListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.ACTION);
+ }
+ actionListener_private = AWTEventMulticaster.add(actionListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#ACTION ACTION} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addActionListener
+ */
+ static public void removeActionListener(ActionListener l) {
+ actionListener_private = AWTEventMulticaster.remove(actionListener_private, l);
+ if (actionListener_private == null) {
+ awtListener_private.removeListeners(EventID.ACTION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all
+ * {@link EventID#ADJUSTMENT ADJUSTMENT} events on each component instance
+ * in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeAdjustmentListener
+ */
+ static public void addAdjustmentListener(AdjustmentListener l) {
+ if (adjustmentListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.ADJUSTMENT);
+ }
+ adjustmentListener_private = AWTEventMulticaster.add(adjustmentListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#ADJUSTMENT ADJUSTMENT} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addAdjustmentListener
+ */
+ static public void removeAdjustmentListener(AdjustmentListener l) {
+ adjustmentListener_private = AWTEventMulticaster.remove(adjustmentListener_private, l);
+ if (adjustmentListener_private == null) {
+ awtListener_private.removeListeners(EventID.ADJUSTMENT);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#ITEM ITEM} events
+ * on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeItemListener
+ */
+ static public void addItemListener(ItemListener l) {
+ if (itemListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.ITEM);
+ }
+ itemListener_private = AWTEventMulticaster.add(itemListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives {@link EventID#ITEM ITEM}
+ * events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addItemListener
+ */
+ static public void removeItemListener(ItemListener l) {
+ itemListener_private = AWTEventMulticaster.remove(itemListener_private, l);
+ if (itemListener_private == null) {
+ awtListener_private.removeListeners(EventID.ITEM);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TEXT TEXT} events
+ * on each component instance in the Java Virtual Machine when they occur.
+ *
Note: this listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTextListener
+ */
+ static public void addTextListener(TextListener l) {
+ if (textListener_private == null) {
+ checkInstallPermission();
+ awtListener_private.installListeners(EventID.TEXT);
+ }
+ textListener_private = AWTEventMulticaster.add(textListener_private, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives {@link EventID#TEXT TEXT}
+ * events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addTextListener
+ */
+ static public void removeTextListener(TextListener l) {
+ textListener_private = AWTEventMulticaster.remove(textListener_private, l);
+ if (textListener_private == null) {
+ awtListener_private.removeListeners(EventID.TEXT);
+ }
+ }
+
+
+ /**
+ * AWTEventsListener is the class that does all the work for AWTEventMonitor.
+ * It is not intended for use by any other class except AWTEventMonitor.
+ *
+ */
+
+ static class AWTEventsListener implements TopLevelWindowListener,
+ ActionListener, AdjustmentListener, ComponentListener,
+ ContainerListener, FocusListener, ItemListener, KeyListener,
+ MouseListener, MouseMotionListener, TextListener, WindowListener,
+ ChangeListener {
+
+ /**
+ * internal variables for Action introspection
+ */
+ private java.lang.Class>[] actionListeners;
+ private java.lang.reflect.Method removeActionMethod;
+ private java.lang.reflect.Method addActionMethod;
+ private java.lang.Object[] actionArgs;
+
+ /**
+ * internal variables for Item introspection
+ */
+ private java.lang.Class>[] itemListeners;
+ private java.lang.reflect.Method removeItemMethod;
+ private java.lang.reflect.Method addItemMethod;
+ private java.lang.Object[] itemArgs;
+
+ /**
+ * internal variables for Text introspection
+ */
+ private java.lang.Class>[] textListeners;
+ private java.lang.reflect.Method removeTextMethod;
+ private java.lang.reflect.Method addTextMethod;
+ private java.lang.Object[] textArgs;
+
+ /**
+ * internal variables for Window introspection
+ */
+ private java.lang.Class>[] windowListeners;
+ private java.lang.reflect.Method removeWindowMethod;
+ private java.lang.reflect.Method addWindowMethod;
+ private java.lang.Object[] windowArgs;
+
+ /**
+ * Create a new instance of this class and install it on each component
+ * instance in the virtual machine that supports any of the currently
+ * registered listeners in AWTEventMonitor. Also registers itself
+ * as a TopLevelWindowListener with EventQueueMonitor so it can
+ * automatically add new listeners to new components.
+ *
+ * @see EventQueueMonitor
+ * @see AWTEventMonitor
+ */
+ public AWTEventsListener() {
+ String version = System.getProperty("java.version");
+ if (version != null) {
+ runningOnJDK1_4 = (version.compareTo("1.4") >= 0);
+ }
+ initializeIntrospection();
+ installListeners();
+ if (runningOnJDK1_4) {
+ MenuSelectionManager.defaultManager().addChangeListener(this);
+ }
+ EventQueueMonitor.addTopLevelWindowListener(this);
+ }
+
+ /**
+ * Set up all of the variables needed for introspection
+ */
+ private boolean initializeIntrospection() {
+ actionListeners = new java.lang.Class>[1];
+ actionArgs = new java.lang.Object[1];
+ actionListeners[0] = java.awt.event.ActionListener.class;
+ actionArgs[0] = this;
+
+ itemListeners = new java.lang.Class>[1];
+ itemArgs = new java.lang.Object[1];
+ itemListeners[0] = java.awt.event.ItemListener.class;
+ itemArgs[0] = this;
+
+ textListeners = new java.lang.Class>[1];
+ textArgs = new java.lang.Object[1];
+ textListeners[0] = java.awt.event.TextListener.class;
+ textArgs[0] = this;
+
+ windowListeners = new java.lang.Class>[1];
+ windowArgs = new java.lang.Object[1];
+ windowListeners[0] = java.awt.event.WindowListener.class;
+ windowArgs[0] = this;
+
+ return true;
+ }
+
+ /**
+ * Installs all currently registered listeners on all components based
+ * upon the current topLevelWindows cached by EventQueueMonitor.
+ *
+ * @see EventQueueMonitor
+ * @see AWTEventMonitor
+ */
+ protected void installListeners() {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ installListeners(topLevelWindows[i]);
+ }
+ }
+ }
+
+ /**
+ * Installs listeners for the given event ID on all components based
+ * upon the current topLevelWindows cached by EventQueueMonitor.
+ *
+ * @param eventID the event ID
+ * @see EventID
+ */
+ protected void installListeners(int eventID) {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ installListeners(topLevelWindows[i], eventID);
+ }
+ }
+ }
+
+ /**
+ * Installs all currently registered listeners to just the component.
+ * @param c the component to add listeners to
+ */
+ protected void installListeners(Component c) {
+
+ // Container and focus listeners are always installed for our own use.
+ //
+ installListeners(c,EventID.CONTAINER);
+ installListeners(c,EventID.FOCUS);
+
+ // conditionally install low-level listeners
+ //
+ if (AWTEventMonitor.componentListener_private != null) {
+ installListeners(c,EventID.COMPONENT);
+ }
+ if (AWTEventMonitor.keyListener_private != null) {
+ installListeners(c,EventID.KEY);
+ }
+ if (AWTEventMonitor.mouseListener_private != null) {
+ installListeners(c,EventID.MOUSE);
+ }
+ if (AWTEventMonitor.mouseMotionListener_private != null) {
+ installListeners(c,EventID.MOTION);
+ }
+ if (AWTEventMonitor.windowListener_private != null) {
+ installListeners(c,EventID.WINDOW);
+ }
+
+ // conditionally install Semantic listeners
+ //
+ if (AWTEventMonitor.actionListener_private != null) {
+ installListeners(c,EventID.ACTION);
+ }
+ if (AWTEventMonitor.adjustmentListener_private != null) {
+ installListeners(c,EventID.ADJUSTMENT);
+ }
+ if (AWTEventMonitor.itemListener_private != null) {
+ installListeners(c,EventID.ITEM);
+ }
+ if (AWTEventMonitor.textListener_private != null) {
+ installListeners(c,EventID.TEXT);
+ }
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ processFocusGained();
+ }
+
+ private void processFocusGained() {
+ Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
+ if (focusOwner == null) {
+ return;
+ }
+ MenuSelectionManager.defaultManager().removeChangeListener(this);
+ MenuSelectionManager.defaultManager().addChangeListener(this);
+
+ // Only menus and popup selections are handled by the JRootPane.
+ if (focusOwner instanceof JRootPane) {
+ MenuElement [] path =
+ MenuSelectionManager.defaultManager().getSelectedPath();
+ if (path.length > 1) {
+ Component penult = path[path.length-2].getComponent();
+ Component last = path[path.length-1].getComponent();
+
+ if (last instanceof JPopupMenu ||
+ last instanceof JMenu) {
+ // This is a popup with nothing in the popup
+ // selected. The menu itself is selected.
+ componentWithFocus_private = last;
+ } else if (penult instanceof JPopupMenu) {
+ // This is a popup with an item selected
+ componentWithFocus_private = penult;
+ }
+ }
+ } else {
+ // The focus owner has the selection.
+ componentWithFocus_private = focusOwner;
+ }
+ }
+
+ /**
+ * Installs the given listener on the component and any of its children.
+ * As a precaution, it always attempts to remove itself as a listener
+ * first so it's always guaranteed to have installed itself just once.
+ *
+ * @param c the component to add listeners to
+ * @param eventID the eventID to add listeners for
+ * @see EventID
+ */
+ protected void installListeners(Component c, int eventID) {
+
+ // install the appropriate listener hook into this component
+ //
+ switch (eventID) {
+
+ case EventID.ACTION:
+ try {
+ removeActionMethod = c.getClass().getMethod(
+ "removeActionListener", actionListeners);
+ addActionMethod = c.getClass().getMethod(
+ "addActionListener", actionListeners);
+ try {
+ removeActionMethod.invoke(c, actionArgs);
+ addActionMethod.invoke(c, actionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.ADJUSTMENT:
+ if (c instanceof Adjustable) {
+ ((Adjustable) c).removeAdjustmentListener(this);
+ ((Adjustable) c).addAdjustmentListener(this);
+ }
+ break;
+
+ case EventID.COMPONENT:
+ c.removeComponentListener(this);
+ c.addComponentListener(this);
+ break;
+
+ case EventID.CONTAINER:
+ if (c instanceof Container) {
+ ((Container) c).removeContainerListener(this);
+ ((Container) c).addContainerListener(this);
+ }
+ break;
+
+ case EventID.FOCUS:
+ c.removeFocusListener(this);
+ c.addFocusListener(this);
+
+ if (runningOnJDK1_4) {
+ processFocusGained();
+
+ } else { // not runningOnJDK1_4
+ if ((c != componentWithFocus_private) && c.hasFocus()) {
+ componentWithFocus_private = c;
+ }
+ }
+ break;
+
+ case EventID.ITEM:
+ try {
+ removeItemMethod = c.getClass().getMethod(
+ "removeItemListener", itemListeners);
+ addItemMethod = c.getClass().getMethod(
+ "addItemListener", itemListeners);
+ try {
+ removeItemMethod.invoke(c, itemArgs);
+ addItemMethod.invoke(c, itemArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ // [PK] CheckboxMenuItem isn't a component but it does
+ // implement Interface ItemSelectable!!
+ // if (c instanceof CheckboxMenuItem) {
+ // ((CheckboxMenuItem) c).removeItemListener(this);
+ // ((CheckboxMenuItem) c).addItemListener(this);
+ break;
+
+ case EventID.KEY:
+ c.removeKeyListener(this);
+ c.addKeyListener(this);
+ break;
+
+ case EventID.MOUSE:
+ c.removeMouseListener(this);
+ c.addMouseListener(this);
+ break;
+
+ case EventID.MOTION:
+ c.removeMouseMotionListener(this);
+ c.addMouseMotionListener(this);
+ break;
+
+ case EventID.TEXT:
+ try {
+ removeTextMethod = c.getClass().getMethod(
+ "removeTextListener", textListeners);
+ addTextMethod = c.getClass().getMethod(
+ "addTextListener", textListeners);
+ try {
+ removeTextMethod.invoke(c, textArgs);
+ addTextMethod.invoke(c, textArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.WINDOW:
+ try {
+ removeWindowMethod = c.getClass().getMethod(
+ "removeWindowListener", windowListeners);
+ addWindowMethod = c.getClass().getMethod(
+ "addWindowListener", windowListeners);
+ try {
+ removeWindowMethod.invoke(c, windowArgs);
+ addWindowMethod.invoke(c, windowArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ // Don't bother recursing the children if this isn't going to
+ // accomplish anything.
+ //
+ default:
+ return;
+ }
+
+ // if this component is a container, recurse through children
+ //
+ if (c instanceof Container) {
+ int count = ((Container) c).getComponentCount();
+ for (int i = 0; i < count; i++) {
+ installListeners(((Container) c).getComponent(i), eventID);
+ }
+ }
+ }
+
+ /**
+ * Removes all listeners for the given event ID on all components based
+ * upon the topLevelWindows cached by EventQueueMonitor.
+ *
+ * @param eventID the event ID
+ * @see EventID
+ */
+ protected void removeListeners(int eventID) {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ removeListeners(topLevelWindows[i], eventID);
+ }
+ }
+ }
+
+ /**
+ * Removes all listeners for the given component and all its children.
+ * @param c the component
+ */
+ protected void removeListeners(Component c) {
+
+ // conditionally remove low-level listeners
+ //
+ if (AWTEventMonitor.componentListener_private != null) {
+ removeListeners(c,EventID.COMPONENT);
+ }
+ if (AWTEventMonitor.keyListener_private != null) {
+ removeListeners(c,EventID.KEY);
+ }
+ if (AWTEventMonitor.mouseListener_private != null) {
+ removeListeners(c,EventID.MOUSE);
+ }
+ if (AWTEventMonitor.mouseMotionListener_private != null) {
+ removeListeners(c,EventID.MOTION);
+ }
+ if (AWTEventMonitor.windowListener_private != null) {
+ removeListeners(c,EventID.WINDOW);
+ }
+
+ // Remove semantic listeners
+ //
+ if (AWTEventMonitor.actionListener_private != null) {
+ removeListeners(c,EventID.ACTION);
+ }
+ if (AWTEventMonitor.adjustmentListener_private != null) {
+ removeListeners(c,EventID.ADJUSTMENT);
+ }
+ if (AWTEventMonitor.itemListener_private != null) {
+ removeListeners(c,EventID.ITEM);
+ }
+ if (AWTEventMonitor.textListener_private != null) {
+ removeListeners(c,EventID.TEXT);
+ }
+ }
+
+ /**
+ * Removes all listeners for the event ID from the component and all
+ * of its children.
+ *
+ * @param c the component to remove listeners from
+ * @see EventID
+ */
+ protected void removeListeners(Component c, int eventID) {
+
+ // remove the appropriate listener hook into this component
+ //
+ switch (eventID) {
+
+ case EventID.ACTION:
+ try {
+ removeActionMethod = c.getClass().getMethod(
+ "removeActionListener",
+ actionListeners);
+ try {
+ removeActionMethod.invoke(c, actionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.ADJUSTMENT:
+ if (c instanceof Adjustable) {
+ ((Adjustable) c).removeAdjustmentListener(this);
+ }
+ break;
+
+ case EventID.COMPONENT:
+ c.removeComponentListener(this);
+ break;
+
+ // Never remove these because we're always interested in them
+ // for our own use.
+ //case EventID.CONTAINER:
+ // if (c instanceof Container) {
+ // ((Container) c).removeContainerListener(this);
+ // }
+ // break;
+ //
+ //case EventID.FOCUS:
+ // c.removeFocusListener(this);
+ // break;
+
+ case EventID.ITEM:
+ try {
+ removeItemMethod = c.getClass().getMethod(
+ "removeItemListener", itemListeners);
+ try {
+ removeItemMethod.invoke(c, itemArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ // [PK] CheckboxMenuItem isn't a component but it does
+ // implement Interface ItemSelectable!!
+ // if (c instanceof CheckboxMenuItem) {
+ // ((CheckboxMenuItem) c).removeItemListener(this);
+ break;
+
+ case EventID.KEY:
+ c.removeKeyListener(this);
+ break;
+
+ case EventID.MOUSE:
+ c.removeMouseListener(this);
+ break;
+
+ case EventID.MOTION:
+ c.removeMouseMotionListener(this);
+ break;
+
+ case EventID.TEXT:
+ try {
+ removeTextMethod = c.getClass().getMethod(
+ "removeTextListener", textListeners);
+ try {
+ removeTextMethod.invoke(c, textArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.WINDOW:
+ try {
+ removeWindowMethod = c.getClass().getMethod(
+ "removeWindowListener", windowListeners);
+ try {
+ removeWindowMethod.invoke(c, windowArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (c instanceof Container) {
+ int count = ((Container) c).getComponentCount();
+ for (int i = 0; i < count; i++) {
+ removeListeners(((Container) c).getComponent(i), eventID);
+ }
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Listener Interface Methods */
+ /* */
+ /********************************************************************/
+
+ /* TopLevelWindow Methods ***************************************/
+
+ /**
+ * Called when top level window is created.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ */
+ public void topLevelWindowCreated(Window w) {
+ installListeners(w);
+ }
+
+ /**
+ * Called when top level window is destroyed.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ */
+ public void topLevelWindowDestroyed(Window w) {
+ }
+
+ /* ActionListener Methods ***************************************/
+
+ /**
+ * Called when an action is performed.
+ *
+ * @see AWTEventMonitor#addActionListener
+ */
+ public void actionPerformed(ActionEvent e) {
+ if (AWTEventMonitor.actionListener_private != null) {
+ AWTEventMonitor.actionListener_private.actionPerformed(e);
+ }
+ }
+
+ /* AdjustmentListener Methods ***********************************/
+
+ /**
+ * Called when an adjustment is made.
+ *
+ * @see AWTEventMonitor#addAdjustmentListener
+ */
+ public void adjustmentValueChanged(AdjustmentEvent e) {
+ if (AWTEventMonitor.adjustmentListener_private != null) {
+ AWTEventMonitor.adjustmentListener_private.adjustmentValueChanged(e);
+ }
+ }
+
+ /* ComponentListener Methods ************************************/
+
+ /**
+ * Called when a component is hidden.
+ *
+ * @see AWTEventMonitor#addComponentListener
+ */
+ public void componentHidden(ComponentEvent e) {
+ if (AWTEventMonitor.componentListener_private != null) {
+ AWTEventMonitor.componentListener_private.componentHidden(e);
+ }
+ }
+
+ /**
+ * Called when a component is moved.
+ *
+ * @see AWTEventMonitor#addComponentListener
+ */
+ public void componentMoved(ComponentEvent e) {
+ if (AWTEventMonitor.componentListener_private != null) {
+ AWTEventMonitor.componentListener_private.componentMoved(e);
+ }
+ }
+
+ /**
+ * Called when a component is resized.
+ *
+ * @see AWTEventMonitor#addComponentListener
+ */
+ public void componentResized(ComponentEvent e) {
+ if (AWTEventMonitor.componentListener_private != null) {
+ AWTEventMonitor.componentListener_private.componentResized(e);
+ }
+ }
+
+ /**
+ * Called when a component is shown.
+ *
+ * @see AWTEventMonitor#addComponentListener
+ */
+ public void componentShown(ComponentEvent e) {
+ if (AWTEventMonitor.componentListener_private != null) {
+ AWTEventMonitor.componentListener_private.componentShown(e);
+ }
+ }
+
+ /* ContainerListener Methods ************************************/
+
+ /**
+ * Called when a component is added to a container.
+ *
+ * @see AWTEventMonitor#addContainerListener
+ */
+ public void componentAdded(ContainerEvent e) {
+ installListeners(e.getChild());
+ if (AWTEventMonitor.containerListener_private != null) {
+ AWTEventMonitor.containerListener_private.componentAdded(e);
+ }
+ }
+
+ /**
+ * Called when a component is removed from a container.
+ *
+ * @see AWTEventMonitor#addContainerListener
+ */
+ public void componentRemoved(ContainerEvent e) {
+ removeListeners(e.getChild());
+ if (AWTEventMonitor.containerListener_private != null) {
+ AWTEventMonitor.containerListener_private.componentRemoved(e);
+ }
+ }
+
+ /* FocusListener Methods ****************************************/
+
+ /**
+ * Called when a component gains keyboard focus.
+ *
+ * @see AWTEventMonitor#addFocusListener
+ */
+ public void focusGained(FocusEvent e) {
+ AWTEventMonitor.componentWithFocus_private = (Component) e.getSource();
+ if (AWTEventMonitor.focusListener_private != null) {
+ AWTEventMonitor.focusListener_private.focusGained(e);
+ }
+ }
+
+ /**
+ * Called when a component loses keyboard focus.
+ *
+ * @see AWTEventMonitor#addFocusListener
+ */
+ public void focusLost(FocusEvent e) {
+ AWTEventMonitor.componentWithFocus_private = null;
+ if (AWTEventMonitor.focusListener_private != null) {
+ AWTEventMonitor.focusListener_private.focusLost(e);
+ }
+ }
+
+ /* ItemListener Methods *****************************************/
+
+ /**
+ * Called when an item's state changes.
+ *
+ * @see AWTEventMonitor#addItemListener
+ */
+ public void itemStateChanged(ItemEvent e) {
+ if (AWTEventMonitor.itemListener_private != null) {
+ AWTEventMonitor.itemListener_private.itemStateChanged(e);
+ }
+ }
+
+ /* KeyListener Methods ******************************************/
+
+ /**
+ * Called when a key is pressed.
+ *
+ * @see AWTEventMonitor#addKeyListener
+ */
+ public void keyPressed(KeyEvent e) {
+ if (AWTEventMonitor.keyListener_private != null) {
+ AWTEventMonitor.keyListener_private.keyPressed(e);
+ }
+ }
+
+ /**
+ * Called when a key is typed.
+ *
+ * @see AWTEventMonitor#addKeyListener
+ */
+ public void keyReleased(KeyEvent e) {
+ if (AWTEventMonitor.keyListener_private != null) {
+ AWTEventMonitor.keyListener_private.keyReleased(e);
+ }
+ }
+
+ /**
+ * Called when a key is released.
+ *
+ * @see AWTEventMonitor#addKeyListener
+ */
+ public void keyTyped(KeyEvent e) {
+ if (AWTEventMonitor.keyListener_private != null) {
+ AWTEventMonitor.keyListener_private.keyTyped(e);
+ }
+ }
+
+ /* MouseListener Methods ****************************************/
+
+ /**
+ * Called when the mouse is clicked.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mouseClicked(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mouseClicked(e);
+ }
+ }
+
+ /**
+ * Called when the mouse enters a component.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mouseEntered(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mouseEntered(e);
+ }
+ }
+
+ /**
+ * Called when the mouse leaves a component.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mouseExited(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mouseExited(e);
+ }
+ }
+
+ /**
+ * Called when the mouse is pressed.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mousePressed(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mousePressed(e);
+ }
+ }
+
+ /**
+ * Called when the mouse is released.
+ *
+ * @see AWTEventMonitor#addMouseListener
+ */
+ public void mouseReleased(MouseEvent e) {
+ if (AWTEventMonitor.mouseListener_private != null) {
+ AWTEventMonitor.mouseListener_private.mouseReleased(e);
+ }
+ }
+
+ /* MouseMotionListener Methods **********************************/
+
+ /**
+ * Called when the mouse is dragged.
+ *
+ * @see AWTEventMonitor#addMouseMotionListener
+ */
+ public void mouseDragged(MouseEvent e) {
+ if (AWTEventMonitor.mouseMotionListener_private != null) {
+ AWTEventMonitor.mouseMotionListener_private.mouseDragged(e);
+ }
+ }
+
+ /**
+ * Called when the mouse is moved.
+ *
+ * @see AWTEventMonitor#addMouseMotionListener
+ */
+ public void mouseMoved(MouseEvent e) {
+ if (AWTEventMonitor.mouseMotionListener_private != null) {
+ AWTEventMonitor.mouseMotionListener_private.mouseMoved(e);
+ }
+ }
+
+ /* TextListener Methods *****************************************/
+
+ /**
+ * Called when a component's text value changed.
+ *
+ * @see AWTEventMonitor#addTextListener
+ */
+ public void textValueChanged(TextEvent e) {
+ if (AWTEventMonitor.textListener_private != null) {
+ AWTEventMonitor.textListener_private.textValueChanged(e);
+ }
+ }
+
+ /* WindowListener Methods ***************************************/
+
+ /**
+ * Called when a window is opened.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowOpened(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowOpened(e);
+ }
+ }
+
+ /**
+ * Called when a window is in the process of closing.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowClosing(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowClosing(e);
+ }
+ }
+
+ /**
+ * Called when a window is closed.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowClosed(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowClosed(e);
+ }
+ }
+
+ /**
+ * Called when a window is iconified.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowIconified(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowIconified(e);
+ }
+ }
+
+ /**
+ * Called when a window is deiconified.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowDeiconified(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowDeiconified(e);
+ }
+ }
+
+ /**
+ * Called when a window is activated.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowActivated(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowActivated(e);
+ }
+ }
+
+ /**
+ * Called when a window is deactivated.
+ *
+ * @see AWTEventMonitor#addWindowListener
+ */
+ public void windowDeactivated(WindowEvent e) {
+ if (AWTEventMonitor.windowListener_private != null) {
+ AWTEventMonitor.windowListener_private.windowDeactivated(e);
+ }
+ }
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityEventMonitor.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityEventMonitor.java
new file mode 100644
index 00000000000..4719e7c12de
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityEventMonitor.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.beans.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.accessibility.*;
+
+/**
+ *
{@code AccessibilityEventMonitor} implements a PropertyChange listener
+ * on every UI object that implements interface {@code Accessible} in the Java
+ * Virtual Machine. The events captured by these listeners are made available
+ * through listeners supported by {@code AccessibilityEventMonitor}.
+ * With this, all the individual events on each of the UI object
+ * instances are funneled into one set of PropertyChange listeners.
+ *
This class depends upon {@link EventQueueMonitor}, which provides the base
+ * level support for capturing the top-level containers as they are created.
+ *
+ */
+
+@jdk.Exported
+public class AccessibilityEventMonitor {
+
+ // listeners
+ /**
+ * The current list of registered {@link java.beans.PropertyChangeListener
+ * PropertyChangeListener} classes.
+ *
+ * @see #addPropertyChangeListener
+ * @see #removePropertyChangeListener
+ */
+ static protected final AccessibilityListenerList listenerList =
+ new AccessibilityListenerList();
+
+
+ /**
+ * The actual listener that is installed on the component instances.
+ * This listener calls the other registered listeners when an event
+ * occurs. By doing things this way, the actual number of listeners
+ * installed on a component instance is drastically reduced.
+ */
+ static protected final AccessibilityEventListener accessibilityListener =
+ new AccessibilityEventListener();
+
+ /**
+ * Adds the specified listener to receive all PropertyChange events on
+ * each UI object instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to UI object instances that support this listener type.
+ *
+ * @param l the listener to add
+ *
+ * @see #removePropertyChangeListener
+ */
+ static public void addPropertyChangeListener(PropertyChangeListener l) {
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ accessibilityListener.installListeners();
+ }
+ listenerList.add(PropertyChangeListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives PropertyChange
+ * events when they occur.
+ * @see #addPropertyChangeListener
+ * @param l the listener to remove
+ */
+ static public void removePropertyChangeListener(PropertyChangeListener l) {
+ listenerList.remove(PropertyChangeListener.class, l);
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ accessibilityListener.removeListeners();
+ }
+ }
+
+
+ /**
+ * AccessibilityEventListener is the class that does all the work for
+ * AccessibilityEventMonitor. It is not intended for use by any other
+ * class except AccessibilityEventMonitor.
+ *
+ */
+
+ static class AccessibilityEventListener implements TopLevelWindowListener,
+ PropertyChangeListener {
+
+ /**
+ * Create a new instance of this class and install it on each component
+ * instance in the virtual machine that supports any of the currently
+ * registered listeners in AccessibilityEventMonitor. Also registers
+ * itself as a TopLevelWindowListener with EventQueueMonitor so it can
+ * automatically add new listeners to new components.
+ * @see EventQueueMonitor
+ * @see AccessibilityEventMonitor
+ */
+ public AccessibilityEventListener() {
+ EventQueueMonitor.addTopLevelWindowListener(this);
+ }
+
+ /**
+ * Installs PropertyChange listeners on all Accessible objects based
+ * upon the current topLevelWindows cached by EventQueueMonitor.
+ * @see EventQueueMonitor
+ * @see AWTEventMonitor
+ */
+ protected void installListeners() {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ if (topLevelWindows[i] instanceof Accessible) {
+ installListeners((Accessible) topLevelWindows[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Installs PropertyChange listeners to the Accessible object, and it's
+ * children (so long as the object isn't of TRANSIENT state).
+ * @param a the Accessible object to add listeners to
+ */
+ protected void installListeners(Accessible a) {
+ installListeners(a.getAccessibleContext());
+ }
+
+ /**
+ * Installs PropertyChange listeners to the AccessibleContext object,
+ * and it's * children (so long as the object isn't of TRANSIENT state).
+ * @param a the Accessible object to add listeners to
+ */
+ private void installListeners(AccessibleContext ac) {
+
+ if (ac != null) {
+ AccessibleStateSet states = ac.getAccessibleStateSet();
+ if (!states.contains(AccessibleState.TRANSIENT)) {
+ ac.addPropertyChangeListener(this);
+ /*
+ * Don't add listeners to transient children. Components
+ * with transient children should return an AccessibleStateSet
+ * containing AccessibleState.MANAGES_DESCENDANTS. Components
+ * may not explicitly return the MANAGES_DESCENDANTS state.
+ * In this case, don't add listeners to the children of
+ * lists, tables and trees.
+ */
+ AccessibleStateSet set = ac.getAccessibleStateSet();
+ if (set.contains(_AccessibleState.MANAGES_DESCENDANTS)) {
+ return;
+ }
+ AccessibleRole role = ac.getAccessibleRole();
+ if (role == AccessibleRole.LIST ||
+ role == AccessibleRole.TREE) {
+ return;
+ }
+ if (role == AccessibleRole.TABLE) {
+ // handle Oracle tables containing tables
+ Accessible child = ac.getAccessibleChild(0);
+ if (child != null) {
+ AccessibleContext ac2 = child.getAccessibleContext();
+ if (ac2 != null) {
+ role = ac2.getAccessibleRole();
+ if (role != null && role != AccessibleRole.TABLE) {
+ return;
+ }
+ }
+ }
+ }
+ int count = ac.getAccessibleChildrenCount();
+ for (int i = 0; i < count; i++) {
+ Accessible child = ac.getAccessibleChild(i);
+ if (child != null) {
+ installListeners(child);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes PropertyChange listeners on all Accessible objects based
+ * upon the topLevelWindows cached by EventQueueMonitor.
+ * @param eventID the event ID
+ * @see EventID
+ */
+ protected void removeListeners() {
+ Window topLevelWindows[] = EventQueueMonitor.getTopLevelWindows();
+ if (topLevelWindows != null) {
+ for (int i = 0; i < topLevelWindows.length; i++) {
+ if (topLevelWindows[i] instanceof Accessible) {
+ removeListeners((Accessible) topLevelWindows[i]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes PropertyChange listeners for the given Accessible object,
+ * it's children (so long as the object isn't of TRANSIENT state).
+ * @param a the Accessible object to remove listeners from
+ */
+ protected void removeListeners(Accessible a) {
+ removeListeners(a.getAccessibleContext());
+ }
+
+ /**
+ * Removes PropertyChange listeners for the given AccessibleContext
+ * object, it's children (so long as the object isn't of TRANSIENT
+ * state).
+ * @param a the Accessible object to remove listeners from
+ */
+ private void removeListeners(AccessibleContext ac) {
+
+
+ if (ac != null) {
+ // Listeners are not added to transient components.
+ AccessibleStateSet states = ac.getAccessibleStateSet();
+ if (!states.contains(AccessibleState.TRANSIENT)) {
+ ac.removePropertyChangeListener(this);
+ /*
+ * Listeners are not added to transient children. Components
+ * with transient children should return an AccessibleStateSet
+ * containing AccessibleState.MANAGES_DESCENDANTS. Components
+ * may not explicitly return the MANAGES_DESCENDANTS state.
+ * In this case, don't remove listeners from the children of
+ * lists, tables and trees.
+ */
+ if (states.contains(_AccessibleState.MANAGES_DESCENDANTS)) {
+ return;
+ }
+ AccessibleRole role = ac.getAccessibleRole();
+ if (role == AccessibleRole.LIST ||
+ role == AccessibleRole.TABLE ||
+ role == AccessibleRole.TREE) {
+ return;
+ }
+ int count = ac.getAccessibleChildrenCount();
+ for (int i = 0; i < count; i++) {
+ Accessible child = ac.getAccessibleChild(i);
+ if (child != null) {
+ removeListeners(child);
+ }
+ }
+ }
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Listener Interface Methods */
+ /* */
+ /********************************************************************/
+
+ /* TopLevelWindow Methods ***************************************/
+
+ /**
+ * Called when top level window is created.
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ */
+ public void topLevelWindowCreated(Window w) {
+ if (w instanceof Accessible) {
+ installListeners((Accessible) w);
+ }
+ }
+
+ /**
+ * Called when top level window is destroyed.
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ */
+ public void topLevelWindowDestroyed(Window w) {
+ if (w instanceof Accessible) {
+ removeListeners((Accessible) w);
+ }
+ }
+
+
+ /* PropertyChangeListener Methods **************************************/
+
+ public void propertyChange(PropertyChangeEvent e) {
+ // propogate the event
+ Object[] listeners =
+ AccessibilityEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PropertyChangeListener.class) {
+ ((PropertyChangeListener)listeners[i+1]).propertyChange(e);
+ }
+ }
+
+ // handle childbirth/death
+ String name = e.getPropertyName();
+ if (name.compareTo(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY) == 0) {
+ Object oldValue = e.getOldValue();
+ Object newValue = e.getNewValue();
+
+ if ((oldValue == null) ^ (newValue == null)) { // one null, not both
+ if (oldValue != null) {
+ // this Accessible is a child that's going away
+ if (oldValue instanceof Accessible) {
+ Accessible a = (Accessible) oldValue;
+ removeListeners(a.getAccessibleContext());
+ } else if (oldValue instanceof AccessibleContext) {
+ removeListeners((AccessibleContext) oldValue);
+ }
+ } else if (newValue != null) {
+ // this Accessible is a child was just born
+ if (newValue instanceof Accessible) {
+ Accessible a = (Accessible) newValue;
+ installListeners(a.getAccessibleContext());
+ } else if (newValue instanceof AccessibleContext) {
+ installListeners((AccessibleContext) newValue);
+ }
+ }
+ } else {
+ System.out.println("ERROR in usage of PropertyChangeEvents for: " + e.toString());
+ }
+ }
+ }
+ }
+}
+
+/*
+ * workaround for no public AccessibleState constructor
+ */
+class _AccessibleState extends AccessibleState {
+ /**
+ * Indicates this object is responsible for managing its
+ * subcomponents. This is typically used for trees and tables
+ * that have a large number of subcomponents and where the
+ * objects are created only when needed and otherwise remain virtual.
+ * The application should not manage the subcomponents directly.
+ */
+ public static final _AccessibleState MANAGES_DESCENDANTS
+ = new _AccessibleState ("managesDescendants");
+
+ /**
+ * Creates a new AccessibleState using the given locale independent key.
+ * This should not be a public method. Instead, it is used to create
+ * the constants in this file to make it a strongly typed enumeration.
+ * Subclasses of this class should enforce similar policy.
+ *
+ * The key String should be a locale independent key for the state.
+ * It is not intended to be used as the actual String to display
+ * to the user. To get the localized string, use toDisplayString.
+ *
+ * @param key the locale independent name of the state.
+ * @see AccessibleBundle#toDisplayString
+ */
+ protected _AccessibleState(String key) {
+ super(key);
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityListenerList.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityListenerList.java
new file mode 100644
index 00000000000..76c7147ea09
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AccessibilityListenerList.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.beans.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.accessibility.*;
+
+/**
+ *
The {@code AccessibilityListenerList} is a copy of the Swing
+ * {@link javax.swing.event.EventListenerList EventListerList} class.
+ *
+ */
+
+@jdk.Exported
+public class AccessibilityListenerList {
+ /* A null array to be shared by all empty listener lists */
+ private final static Object[] NULL_ARRAY = new Object[0];
+
+ /**
+ * The list of listener type, listener pairs
+ */
+ protected transient Object[] listenerList = NULL_ARRAY;
+
+ /**
+ * Passes back the event listener list as an array of listener type, listener pairs.
+ * Note that for performance reasons, this implementation passes back the actual
+ * data structure in which the listener data is stored internally. This method
+ * is guaranteed to pass back a non-null array, so that no null-checking
+ * is required in fire methods. A zero-length array of Object is returned if
+ * there are currently no listeners.
+ *
+ * Absolutely no modification of the data contained in this array should be
+ * made. If any such manipulation is necessary, it should be done on a copy
+ * of the array returned rather than the array itself.
+ *
+ * @return an array of listener type, listener pairs.
+ */
+ public Object[] getListenerList() {
+ return listenerList;
+ }
+
+ /**
+ * Returns the total number of listeners for this listener list.
+ *
+ * @return the total number of listeners for this listener list.
+ */
+ public int getListenerCount() {
+ return listenerList.length/2;
+ }
+
+ /**
+ * Return the total number of listeners of the supplied type
+ * for this listener list.
+ *
+ * @param t the type of the listener to be counted
+ * @return the number of listeners found
+ */
+ public int getListenerCount(Class extends EventListener> t) {
+ int count = 0;
+ Object[] lList = listenerList;
+ for (int i = 0; i < lList.length; i+=2) {
+ if (t == (Class)lList[i])
+ count++;
+ }
+ return count;
+ }
+
+ /**
+ * Add the listener as a listener of the specified type.
+ *
+ * @param t the type of the listener to be added
+ * @param l the listener to be added
+ */
+ public synchronized void add(Class extends EventListener> t, EventListener l) {
+ if (!t.isInstance(l)) {
+ throw new IllegalArgumentException("Listener " + l +
+ " is not of type " + t);
+ }
+ if (l ==null) {
+ throw new IllegalArgumentException("Listener " + l +
+ " is null");
+ }
+ if (listenerList == NULL_ARRAY) {
+ // if this is the first listener added,
+ // initialize the lists
+ listenerList = new Object[] { t, l };
+ } else {
+ // Otherwise copy the array and add the new listener
+ int i = listenerList.length;
+ Object[] tmp = new Object[i+2];
+ System.arraycopy(listenerList, 0, tmp, 0, i);
+
+ tmp[i] = t;
+ tmp[i+1] = l;
+
+ listenerList = tmp;
+ }
+ }
+
+ /**
+ * Remove the listener as a listener of the specified type.
+ *
+ * @param t the type of the listener to be removed
+ * @param l the listener to be removed
+ */
+ public synchronized void remove(Class extends EventListener> t, EventListener l) {
+ if (!t.isInstance(l)) {
+ throw new IllegalArgumentException("Listener " + l +
+ " is not of type " + t);
+ }
+ if (l ==null) {
+ throw new IllegalArgumentException("Listener " + l +
+ " is null");
+ }
+
+ // Is l on the list?
+ int index = -1;
+ for (int i = listenerList.length-2; i>=0; i-=2) {
+ if ((listenerList[i]==t) && (listenerList[i+1] == l)) {
+ index = i;
+ break;
+ }
+ }
+
+ // If so, remove it
+ if (index != -1) {
+ Object[] tmp = new Object[listenerList.length-2];
+ // Copy the list up to index
+ System.arraycopy(listenerList, 0, tmp, 0, index);
+ // Copy from two past the index, up to
+ // the end of tmp (which is two elements
+ // shorter than the old list)
+ if (index < tmp.length)
+ System.arraycopy(listenerList, index+2, tmp, index,
+ tmp.length - index);
+ // set the listener array to the new array or null
+ listenerList = (tmp.length == 0) ? NULL_ARRAY : tmp;
+ }
+ }
+
+ /**
+ * Return a string representation of the {@code AccessibilityListenerList}.
+ *
+ * @return a string representation of the {@code AccessibilityListenerList}.
+ */
+ public String toString() {
+ Object[] lList = listenerList;
+ String s = "EventListenerList: ";
+ s += lList.length/2 + " listeners: ";
+ for (int i = 0 ; i <= lList.length-2 ; i+=2) {
+ s += " type " + ((Class)lList[i]).getName();
+ s += " listener " + lList[i+1];
+ }
+ return s;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventID.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventID.java
new file mode 100644
index 00000000000..bbd08f534e9
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventID.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+/**
+ * EventID contains integer constants that map to event support in
+ * AWT and Swing. They are used by primarily by AWTEventMonitor,
+ * AWTEventsListener, SwingEventMonitor, and SwingEventListener, but
+ * can be freely used by any other class.
+ *
+ * @see AWTEventMonitor
+ * @see SwingEventMonitor
+ *
+ */
+@jdk.Exported
+public class EventID {
+
+ /**
+ * Maps to AWT Action support (i.e., ActionListener and ActionEvent)
+ */
+ static public final int ACTION = 0;
+
+ /**
+ * Maps to AWT Adjustment support (i.e., AdjustmentListener
+ * and AdjustmentEvent)
+ */
+ static public final int ADJUSTMENT = 1;
+
+ /**
+ * Maps to AWT Component support (i.e., ComponentListener
+ * and ComponentEvent)
+ */
+ static public final int COMPONENT = 2;
+
+ /**
+ * Maps to AWT Container support (i.e., ContainerListener
+ * and ContainerEvent)
+ */
+ static public final int CONTAINER = 3;
+
+ /**
+ * Maps to AWT Focus support (i.e., FocusListener and FocusEvent)
+ */
+ static public final int FOCUS = 4;
+
+ /**
+ * Maps to AWT Item support (i.e., ItemListener and ItemEvent)
+ */
+ static public final int ITEM = 5;
+
+ /**
+ * Maps to AWT Key support (i.e., KeyListener and KeyEvent)
+ */
+ static public final int KEY = 6;
+
+ /**
+ * Maps to AWT Mouse support (i.e., MouseListener and MouseEvent)
+ */
+ static public final int MOUSE = 7;
+
+ /**
+ * Maps to AWT MouseMotion support (i.e., MouseMotionListener
+ * and MouseMotionEvent)
+ */
+ static public final int MOTION = 8;
+
+ /**
+ * Maps to AWT Text support (i.e., TextListener and TextEvent)
+ */
+ static public final int TEXT = 10;
+
+ /**
+ * Maps to AWT Window support (i.e., WindowListener and WindowEvent)
+ */
+ static public final int WINDOW = 11;
+
+ /**
+ * Maps to Swing Ancestor support (i.e., AncestorListener and
+ * AncestorEvent)
+ */
+ static public final int ANCESTOR = 12;
+
+ /**
+ * Maps to Swing Text Caret support (i.e., CaretListener and
+ * CaretEvent)
+ */
+ static public final int CARET = 13;
+
+ /**
+ * Maps to Swing CellEditor support (i.e., CellEditorListener and
+ * CellEditorEvent)
+ */
+ static public final int CELLEDITOR = 14;
+
+ /**
+ * Maps to Swing Change support (i.e., ChangeListener and
+ * ChangeEvent)
+ */
+ static public final int CHANGE = 15;
+
+ /**
+ * Maps to Swing TableColumnModel support (i.e.,
+ * TableColumnModelListener and TableColumnModelEvent)
+ */
+ static public final int COLUMNMODEL = 16;
+
+ /**
+ * Maps to Swing Document support (i.e., DocumentListener and
+ * DocumentEvent)
+ */
+ static public final int DOCUMENT = 17;
+
+ /**
+ * Maps to Swing ListData support (i.e., ListDataListener and
+ * ListDataEvent)
+ */
+ static public final int LISTDATA = 18;
+
+ /**
+ * Maps to Swing ListSelection support (i.e., ListSelectionListener and
+ * ListSelectionEvent)
+ */
+ static public final int LISTSELECTION = 19;
+
+ /**
+ * Maps to Swing Menu support (i.e., MenuListener and
+ * MenuEvent)
+ */
+ static public final int MENU = 20;
+
+ /**
+ * Maps to Swing PopupMenu support (i.e., PopupMenuListener and
+ * PopupMenuEvent)
+ */
+ static public final int POPUPMENU = 21;
+
+ /**
+ * Maps to Swing TableModel support (i.e., TableModelListener and
+ * TableModelEvent)
+ */
+ static public final int TABLEMODEL = 22;
+
+ /**
+ * Maps to Swing TreeExpansion support (i.e., TreeExpansionListener and
+ * TreeExpansionEvent)
+ */
+ static public final int TREEEXPANSION = 23;
+
+ /**
+ * Maps to Swing TreeModel support (i.e., TreeModelListener and
+ * TreeModelEvent)
+ */
+ static public final int TREEMODEL = 24;
+
+ /**
+ * Maps to Swing TreeSelection support (i.e., TreeSelectionListener and
+ * TreeSelectionEvent)
+ */
+ static public final int TREESELECTION = 25;
+
+ /**
+ * Maps to Swing UndoableEdit support (i.e., UndoableEditListener and
+ * UndoableEditEvent)
+ */
+ static public final int UNDOABLEEDIT = 26;
+
+ /**
+ * Maps to Beans PropertyChange support (i.e., PropertyChangeListener
+ * and PropertyChangeEvent)
+ */
+ static public final int PROPERTYCHANGE = 27;
+
+ /**
+ * Maps to Beans VetoableChange support (i.e., VetoableChangeListener
+ * and VetoableChangeEvent)
+ */
+ static public final int VETOABLECHANGE = 28;
+
+ /**
+ * Maps to Swing InternalFrame support (i.e., InternalFrameListener)
+ */
+ static public final int INTERNALFRAME = 29;
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventQueueMonitor.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventQueueMonitor.java
new file mode 100644
index 00000000000..aa87860bb48
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/EventQueueMonitor.java
@@ -0,0 +1,619 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.accessibility.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * The {@code EventQueueMonitor} class provides key core functionality for Assistive
+ * Technologies (and other system-level technologies that need some of the same
+ * things that Assistive Technology needs).
+ *
+ * @see AWTEventMonitor
+ * @see SwingEventMonitor
+ */
+@jdk.Exported
+public class EventQueueMonitor
+ implements AWTEventListener {
+
+ // NOTE: All of the following properties are static. The reason
+ // for this is that there may be multiple EventQueue instances
+ // in use in the same VM. By making these properties static,
+ // we can guarantee we get the information from all of the
+ // EventQueue instances.
+
+ // The stuff that is cached.
+ //
+ static VectortopLevelWindows = new Vector<>();
+ static Window topLevelWindowWithFocus = null;
+ static Point currentMousePosition = null;
+ static Component currentMouseComponent = null;
+
+ // Low-level listener interfaces
+ //
+ static GUIInitializedListener guiInitializedListener = null;
+ static TopLevelWindowListener topLevelWindowListener = null;
+ static MouseMotionListener mouseMotionListener = null;
+
+ /**
+ * Class variable stating whether the assistive technologies have
+ * been loaded yet or not. The assistive technologies won't be
+ * loaded until the first event is posted to the EventQueue. This
+ * gives the toolkit a chance to do all the necessary initialization
+ * it needs to do.
+ */
+
+ /**
+ * Class variable stating whether the GUI subsystem has been initialized
+ * or not.
+ *
+ * @see #isGUIInitialized
+ */
+ static boolean guiInitialized = false;
+
+ /**
+ * Queue that holds events for later processing.
+ */
+ static EventQueueMonitorItem componentEventQueue = null;
+
+ /**
+ * Class that tells us what the component event dispatch thread is.
+ */
+ static private ComponentEvtDispatchThread cedt = null;
+
+ /**
+ * Handle the synchronization between the thing that populates the
+ * component event dispatch thread ({@link #queueComponentEvent})
+ * and the thing that processes the events ({@link ComponentEvtDispatchThread}).
+ */
+ static Object componentEventQueueLock = new Object();
+
+ /**
+ * Create a new {@code EventQueueMonitor} instance. Normally, this will
+ * be called only by the AWT Toolkit during initialization time.
+ * Assistive technologies should not create instances of
+ * EventQueueMonitor by themselves. Instead, they should either
+ * refer to it directly via the static methods in this class, e.g.,
+ * {@link #getCurrentMousePosition} or obtain the instance by asking the
+ * Toolkit, e.g., {@link java.awt.Toolkit#getSystemEventQueue}.
+ */
+ public EventQueueMonitor() {
+ if (cedt == null) {
+ cedt = new ComponentEvtDispatchThread("EventQueueMonitor-ComponentEvtDispatch");
+
+ cedt.setDaemon(true);
+ cedt.start();
+ }
+ }
+
+ /**
+ * Queue up a {@link java.awt.event.ComponentEvent ComponentEvent} for later
+ * processing by the {@link ComponentEvtDispatch} thread.
+ *
+ * @param e a {@code ComponentEvent}
+ */
+ static void queueComponentEvent(ComponentEvent e) {
+ synchronized(componentEventQueueLock) {
+ EventQueueMonitorItem eqi = new EventQueueMonitorItem(e);
+ if (componentEventQueue == null) {
+ componentEventQueue = eqi;
+ } else {
+ EventQueueMonitorItem q = componentEventQueue;
+ while (true) {
+ if (q.next != null) {
+ q = q.next;
+ } else {
+ break;
+ }
+ }
+ q.next = eqi;
+ }
+ componentEventQueueLock.notifyAll();
+ }
+ }
+
+ /**
+ * Tell the {@code EventQueueMonitor} to start listening for events.
+ */
+ public static void maybeInitialize() {
+ if (cedt == null) {
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Void run() {
+ try {
+ long eventMask = AWTEvent.WINDOW_EVENT_MASK |
+ AWTEvent.FOCUS_EVENT_MASK |
+ AWTEvent.MOUSE_MOTION_EVENT_MASK;
+
+ Toolkit.getDefaultToolkit().addAWTEventListener(new EventQueueMonitor(), eventMask);
+ } catch (Exception e) {
+ }
+ return null;
+ }
+ }
+ );
+ }
+ }
+
+ /**
+ * Handle events as a result of registering a listener
+ * on the {@link java.awt.EventQueue EventQueue} in {@link #maybeInitialize}.
+ */
+ public void eventDispatched(AWTEvent theEvent) {
+ processEvent(theEvent);
+ }
+
+ /**
+ * Assisitive technologies that have
+ * registered a {@link GUIInitializedListener} will be notified.
+ *
+ * @see #addGUIInitializedListener
+ */
+ static void maybeNotifyAssistiveTechnologies() {
+
+ if (!guiInitialized) {
+ guiInitialized = true;
+ if (guiInitializedListener != null) {
+ guiInitializedListener.guiInitialized();
+ }
+ }
+
+ }
+
+ /********************************************************************/
+ /* */
+ /* Package Private Methods */
+ /* */
+ /********************************************************************/
+
+ /**
+ * Add a Container to the list of top-level containers
+ * in the cache. This follows the object's hierarchy up the
+ * tree until it finds the top most parent. If the parent is
+ * not already in the list of Containers, it adds it to the list.
+ *
+ * @param c the Container
+ */
+ static void addTopLevelWindow(Component c) {
+ Container parent;
+
+ if (c == null) {
+ return;
+ }
+
+ if (!(c instanceof Window)) {
+ addTopLevelWindow(c.getParent());
+ return;
+ }
+
+ if ((c instanceof Dialog) || (c instanceof Window)) {
+ parent = (Container) c;
+ } else {
+ parent = c.getParent();
+ if (parent != null) {
+ addTopLevelWindow(parent);
+ return;
+ }
+ }
+
+ if (parent == null) {
+ parent = (Container) c;
+ }
+
+ // Because this method is static, do not make it synchronized because
+ // it can lock the whole class. Instead, just lock what needs to be
+ // locked.
+ //
+ synchronized (topLevelWindows) {
+ if ((parent != null) && !topLevelWindows.contains(parent)) {
+ topLevelWindows.addElement(parent);
+ if (topLevelWindowListener != null) {
+ topLevelWindowListener.topLevelWindowCreated((Window) parent);
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes a container from the list of top level containers in the cache.
+ *
+ * @param c the top level container to remove
+ */
+ static void removeTopLevelWindow(Window w) {
+
+ // Because this method is static, do not make it synchronized because
+ // it can lock the whole class. Instead, just lock what needs to be
+ // locked.
+ //
+ synchronized (topLevelWindows) {
+ if (topLevelWindows.contains(w)) {
+ topLevelWindows.removeElement(w);
+ if (topLevelWindowListener != null) {
+ topLevelWindowListener.topLevelWindowDestroyed(w);
+ }
+ }
+ }
+ }
+
+ /**
+ * Update current mouse position.
+ *
+ * @param mouseEvent the MouseEvent that holds the new mouse position.
+ */
+ static void updateCurrentMousePosition(MouseEvent mouseEvent) {
+ Point oldMousePos = currentMousePosition;
+ // Be careful here. The component in the event might be
+ // hidden by the time we process the event.
+ try {
+ Point eventPoint = mouseEvent.getPoint();
+ currentMouseComponent = (Component) (mouseEvent.getSource());
+ currentMousePosition = currentMouseComponent.getLocationOnScreen();
+ currentMousePosition.translate(eventPoint.x,eventPoint.y);
+ } catch (Exception e) {
+ currentMousePosition = oldMousePos;
+ }
+ }
+
+ /**
+ * Process the event. This maintains the event cache in addition
+ * to calling all the registered listeners. NOTE: The events that
+ * come through here are from peered Components.
+ *
+ * @param theEvent the AWTEvent
+ */
+ static void processEvent(AWTEvent theEvent) {
+ switch (theEvent.getID()) {
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ case FocusEvent.FOCUS_GAINED:
+ case WindowEvent.WINDOW_DEACTIVATED:
+ queueComponentEvent((ComponentEvent) theEvent);
+ break;
+
+ case WindowEvent.WINDOW_ACTIVATED:
+ // Dialogs fire WINDOW_ACTIVATED and FOCUS_GAINED events
+ // before WINDOW_OPENED so we need to add topLevelListeners
+ // for the dialog when it is first activated to get a
+ // focus gained event for the focus component in the dialog.
+ if (theEvent instanceof ComponentEvent) {
+ ComponentEvent ce = (ComponentEvent)theEvent;
+ if (ce.getComponent() instanceof Window) {
+ EventQueueMonitor.addTopLevelWindow(ce.getComponent());
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ } else {
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ EventQueueMonitor.addTopLevelWindow(ce.getComponent());
+ }
+ }
+ queueComponentEvent((ComponentEvent) theEvent);
+ break;
+
+ // handle WINDOW_OPENED and WINDOW_CLOSED events synchronously
+ case WindowEvent.WINDOW_OPENED:
+ if (theEvent instanceof ComponentEvent) {
+ ComponentEvent ce = (ComponentEvent)theEvent;
+ if (ce.getComponent() instanceof Window) {
+ EventQueueMonitor.addTopLevelWindow(ce.getComponent());
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ } else {
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ EventQueueMonitor.addTopLevelWindow(ce.getComponent());
+ }
+ }
+ break;
+ case WindowEvent.WINDOW_CLOSED:
+ if (theEvent instanceof ComponentEvent) {
+ ComponentEvent ce = (ComponentEvent)theEvent;
+ EventQueueMonitor.removeTopLevelWindow((Window) (ce.getComponent()));
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Internal test
+ */
+ static synchronized Component getShowingComponentAt(Container c, int x, int y) {
+ if (!c.contains(x, y)) {
+ return null;
+ }
+ int ncomponents = c.getComponentCount();
+ for (int i = 0 ; i < ncomponents ; i++) {
+ Component comp = c.getComponent(i);
+ if (comp != null && comp.isShowing()) {
+ Point location = comp.getLocation();
+ if (comp.contains(x - location.x, y - location.y)) {
+ return comp;
+ }
+ }
+ }
+ return c;
+ }
+
+ /**
+ * Return the Component at the given Point on the screen in the
+ * given Container.
+ *
+ * @param c the Container to search
+ * @param p the Point in screen coordinates
+ * @return the Component at the given Point on the screen in the
+ * given Container -- can be null if no Component is at that Point
+ */
+ static synchronized Component getComponentAt(Container c, Point p) {
+ if (!c.isShowing()) {
+ return null;
+ }
+
+ Component comp;
+ Point containerLoc = c.getLocationOnScreen();
+ Point containerPoint = new Point(p.x - containerLoc.x,
+ p.y - containerLoc.y);
+
+ comp = getShowingComponentAt(c, containerPoint.x, containerPoint.y);
+
+ if ((comp != c) && (comp instanceof Container)) {
+ return getComponentAt((Container)comp,p);
+ } else {
+ return comp;
+ }
+ }
+
+ /**
+ * Obtain the {@link javax.accessibility.Accessible Accessible} object at the given point on the Screen.
+ * The return value may be null if an {@code Accessible} object cannot be
+ * found at the particular point.
+ *
+ * @param p the point to be accessed
+ * @return the {@code Accessible} at the specified point
+ */
+ static public Accessible getAccessibleAt(Point p) {
+ Window w = getTopLevelWindowWithFocus();
+ Window[] wins = getTopLevelWindows();
+ Component c = null;
+
+ // See if the point we're being asked about is the
+ // currentMousePosition. If so, start with the component
+ // that we know the currentMousePostion is over
+ //
+ if (currentMousePosition == null) {
+ return null;
+ }
+ if (currentMousePosition.equals(p)) {
+ if (currentMouseComponent instanceof Container) {
+ c = getComponentAt((Container) currentMouseComponent, p);
+ }
+ }
+
+ // Try the window with focus next
+ //
+ if (c == null && w != null) {
+ c = getComponentAt(w,p);
+ }
+
+ // Try the other windows next. [[[WDW: Stacking order???]]]
+ if (c == null) {
+ for (int i = 0; i < wins.length; i++) {
+ c = getComponentAt(wins[i],p);
+ if (c != null) {
+ break;
+ }
+ }
+ }
+
+ if (c instanceof Accessible) {
+ AccessibleContext ac = ((Accessible) c).getAccessibleContext();
+ if (ac != null) {
+ AccessibleComponent acmp = ac.getAccessibleComponent();
+ if ((acmp != null) && (ac.getAccessibleChildrenCount() != 0)) {
+ Point location = acmp.getLocationOnScreen();
+ location.move(p.x - location.x, p.y - location.y);
+ return acmp.getAccessibleAt(location);
+ }
+ }
+ return (Accessible) c;
+ } else {
+ return Translator.getAccessible(c);
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Public Methods */
+ /* */
+ /********************************************************************/
+
+ /**
+ * Says whether the GUI subsystem has been initialized or not.
+ * If this returns true, the assistive technology can freely
+ * create GUI component instances. If the return value is false,
+ * the assistive technology should register a {@link GUIInitializedListener}
+ * and wait to create GUI component instances until the listener is
+ * called.
+ *
+ * @return true if the GUI subsystem has been initialized
+ * @see #addGUIInitializedListener
+ */
+ static public boolean isGUIInitialized() {
+ maybeInitialize();
+ return guiInitialized;
+ }
+
+ /**
+ * Adds the specified listener to be notified when the GUI subsystem
+ * is initialized. Assistive technologies should get the results of
+ * {@link #isGUIInitialized} before calling this method.
+ *
+ * @param l the listener to add
+ * @see #isGUIInitialized
+ * @see #removeTopLevelWindowListener
+ */
+ static public void addGUIInitializedListener(GUIInitializedListener l) {
+ maybeInitialize();
+ guiInitializedListener =
+ GUIInitializedMulticaster.add(guiInitializedListener,l);
+ }
+
+ /**
+ * Removes the specified listener to be notified when the GUI subsystem
+ * is initialized.
+ *
+ * @param l the listener to remove
+ * @see #addGUIInitializedListener
+ */
+ static public void removeGUIInitializedListener(GUIInitializedListener l) {
+ guiInitializedListener =
+ GUIInitializedMulticaster.remove(guiInitializedListener,l);
+ }
+
+ /**
+ * Adds the specified listener to be notified when a top level window
+ * is created or destroyed.
+ *
+ * @param l the listener to add
+ * @see #removeTopLevelWindowListener
+ */
+ static public void addTopLevelWindowListener(TopLevelWindowListener l) {
+ topLevelWindowListener =
+ TopLevelWindowMulticaster.add(topLevelWindowListener,l);
+ }
+
+ /**
+ * Removes the specified listener to be notified when a top level window
+ * is created or destroyed.
+ *
+ * @param l the listener to remove
+ * @see #addTopLevelWindowListener
+ */
+ static public void removeTopLevelWindowListener(TopLevelWindowListener l) {
+ topLevelWindowListener =
+ TopLevelWindowMulticaster.remove(topLevelWindowListener,l);
+ }
+
+ /**
+ * Return the last recorded position of the mouse in screen coordinates.
+ *
+ * @return the last recorded position of the mouse in screen coordinates
+ */
+ static public Point getCurrentMousePosition() {
+ return currentMousePosition;
+ }
+
+ /**
+ * Return the list of top level Windows in use in the Java Virtual Machine.
+ *
+ * @return an array of top level {@code Window}s in use in the Java Virtual Machine
+ */
+ static public Window[] getTopLevelWindows() {
+
+ // Because this method is static, do not make it synchronized because
+ // it can lock the whole class. Instead, just lock what needs to be
+ // locked.
+ //
+ synchronized (topLevelWindows) {
+ int count = topLevelWindows.size();
+ if (count > 0) {
+ Window[] w = new Window[count];
+ for (int i = 0; i < count; i++) {
+ w[i] = (Window)topLevelWindows.elementAt(i);
+ }
+ return w;
+ } else {
+ return new Window[0];
+ }
+ }
+ }
+
+ /**
+ * Return the top level {@code Window} that currently has keyboard focus.
+ *
+ * @return the top level {@code Window} that currently has keyboard focus
+ */
+ static public Window getTopLevelWindowWithFocus() {
+ return topLevelWindowWithFocus;
+ }
+}
+
+/**
+ * Handle all Component events in a separate thread. The reason for this is
+ * that WindowEvents tend to be used to do lots of processing on the Window
+ * hierarchy. As a result, it can frequently result in deadlock situations.
+ */
+class ComponentEvtDispatchThread extends Thread {
+ public ComponentEvtDispatchThread(String name) {
+ super(name);
+ }
+ public void run() {
+ ComponentEvent ce = null;
+ while (true) {
+ synchronized(EventQueueMonitor.componentEventQueueLock) {
+ while (EventQueueMonitor.componentEventQueue == null) {
+ try {
+ EventQueueMonitor.componentEventQueueLock.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ ce = (ComponentEvent)EventQueueMonitor.componentEventQueue.event;
+ EventQueueMonitor.componentEventQueue =
+ EventQueueMonitor.componentEventQueue.next;
+ }
+ switch (ce.getID()) {
+ case MouseEvent.MOUSE_MOVED:
+ case MouseEvent.MOUSE_DRAGGED:
+ EventQueueMonitor.updateCurrentMousePosition((MouseEvent) ce);
+ break;
+ case WindowEvent.WINDOW_ACTIVATED:
+ EventQueueMonitor.maybeNotifyAssistiveTechnologies();
+ EventQueueMonitor.topLevelWindowWithFocus = ((WindowEvent) ce).getWindow();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * EventQueueMonitorItem is the basic type that handles the
+ * queue for queueComponentEvent and the ComponentEvtDispatchThread.
+ */
+class EventQueueMonitorItem {
+ AWTEvent event;
+ EventQueueMonitorItem next;
+
+ EventQueueMonitorItem(AWTEvent evt) {
+ event = evt;
+ next = null;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedListener.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedListener.java
new file mode 100644
index 00000000000..9a4474d3e6b
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedListener.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.awt.*;
+import java.util.*;
+import javax.accessibility.*;
+
+/**
+ * The {@code GUIInitializedListener} interface is used by the {@link EventQueueMonitor}
+ * class to notify an interested party when the GUI subsystem has been
+ * initialized. This is necessary because assistive technologies can
+ * be loaded before the GUI subsystem is initialized. As a result,
+ * assistive technologies should check the
+ * {@link EventQueueMonitor#isGUIInitialized isGUIInitialized} method
+ * of {@code EventQueueMonitor} before creating any GUI components. If the
+ * return value is true, assistive technologies can create GUI components
+ * following the same thread restrictions as any other application. If
+ * the return value is false, the assistive technology should register
+ * a {@code GUIInitializedListener} with the {@code EventQueueMonitor} to be notified
+ * when the GUI subsystem is initialized.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#isGUIInitialized
+ * @see EventQueueMonitor#addGUIInitializedListener
+ * @see EventQueueMonitor#removeGUIInitializedListener
+ *
+ */
+@jdk.Exported
+public interface GUIInitializedListener extends EventListener {
+
+ /**
+ * Invoked when the GUI subsystem is initialized and it's OK for
+ * the assisitive technology to create instances of GUI objects.
+ */
+ public void guiInitialized();
+
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedMulticaster.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedMulticaster.java
new file mode 100644
index 00000000000..900b6078f7e
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/GUIInitializedMulticaster.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.awt.*;
+import java.util.EventListener;
+import javax.accessibility.*;
+
+
+/**
+ * The GUIInitializedMulticaster class is used to maintain a list of
+ * GUIInitializedListener classes. It is intended to be used primarily
+ * for internal support in the EventQueueMonitor class, and is not intended
+ * to be used by classes outside the Java Accessibility Utility package.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addGUIInitializedListener
+ * @see EventQueueMonitor#removeGUIInitializedListener
+ *
+ */
+class GUIInitializedMulticaster
+ extends AWTEventMulticaster implements GUIInitializedListener
+{
+ protected GUIInitializedMulticaster(EventListener a, EventListener b) {
+ super(a, b);
+ }
+
+ public void guiInitialized() {
+ ((GUIInitializedListener)a).guiInitialized();
+ ((GUIInitializedListener)b).guiInitialized();
+ }
+
+ public static GUIInitializedListener add(GUIInitializedListener a, GUIInitializedListener b) {
+ return (GUIInitializedListener)addInternal(a, b);
+ }
+
+ public static GUIInitializedListener remove(GUIInitializedListener l, GUIInitializedListener oldl) {
+ return (GUIInitializedListener)removeInternal(l, oldl);
+ }
+
+ protected static EventListener addInternal(EventListener a, EventListener b) {
+ if (a == null) return b;
+ if (b == null) return a;
+ return new GUIInitializedMulticaster(a, b);
+ }
+
+ protected static EventListener removeInternal(EventListener l, EventListener oldl) {
+ if (l == oldl || l == null) {
+ return null;
+ } else if (l instanceof GUIInitializedMulticaster) {
+ return ((GUIInitializedMulticaster)l).remove(oldl);
+ } else {
+ return l; // it's not here
+ }
+ }
+
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/SwingEventMonitor.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/SwingEventMonitor.java
new file mode 100644
index 00000000000..c2150cd78f8
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/SwingEventMonitor.java
@@ -0,0 +1,2530 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.util.*;
+import java.beans.*;
+import java.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.table.*;
+import javax.swing.tree.*;
+import javax.swing.text.*;
+import javax.swing.undo.*;
+import javax.accessibility.*;
+
+
+/**
+ *
{@code SwingEventMonitor} extends {@link AWTEventMonitor} by adding a suite of
+ * listeners conditionally installed on every Swing component instance
+ * in the Java Virtual Machine. The events captured by these listeners
+ * are made available through a unified set of listeners supported by
+ * {@code SwingEventMonitor}. With this, all the individual events on each of the
+ * AWT and Swing component instances are funneled into one set of listeners
+ * broken down by category (see {@link EventID} for the categories).
+ *
This class depends upon {@link EventQueueMonitor}, which provides the base
+ * level support for capturing the top-level containers as they are created.
+ *
Because this class extends {@code AWTEventMonitor}, it is not
+ * necessary to use this class and {@code AWTEventMonitor} at the same time.
+ * If you want to monitor both AWT and Swing components, you should
+ * use just this class.
+ *
+ * @see AWTEventMonitor
+ *
+ */
+@jdk.Exported
+public class SwingEventMonitor extends AWTEventMonitor {
+
+ /**
+ * The master list of all listeners registered by other classes.
+ * This can only be publicly modified by calling the add or
+ * remove listener methods in this class.
+ */
+ static protected final EventListenerList listenerList = new EventListenerList();
+
+ /**
+ * The actual listener that is installed on the component instances.
+ * This listener calls the other registered listeners when an event
+ * occurs. By doing things this way, the actual number of listeners
+ * installed on a component instance is drastically reduced.
+ */
+ static protected final SwingEventListener swingListener = new SwingEventListener();
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#ANCESTOR ANCESTOR}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeAncestorListener
+ */
+ static public void addAncestorListener(AncestorListener l) {
+ if (listenerList.getListenerCount(AncestorListener.class) == 0) {
+ swingListener.installListeners(EventID.ANCESTOR);
+ }
+ listenerList.add(AncestorListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#ANCESTOR ANCESTOR} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addAncestorListener
+ */
+ static public void removeAncestorListener(AncestorListener l) {
+ listenerList.remove(AncestorListener.class, l);
+ if (listenerList.getListenerCount(AncestorListener.class) == 0) {
+ swingListener.removeListeners(EventID.ANCESTOR);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#CARET CARET} events
+ * on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeCaretListener
+ */
+ static public void addCaretListener(CaretListener l) {
+ if (listenerList.getListenerCount(CaretListener.class) == 0) {
+ swingListener.installListeners(EventID.CARET);
+ }
+ listenerList.add(CaretListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#CARET CARET} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addCaretListener
+ */
+ static public void removeCaretListener(CaretListener l) {
+ listenerList.remove(CaretListener.class, l);
+ if (listenerList.getListenerCount(CaretListener.class) == 0) {
+ swingListener.removeListeners(EventID.CARET);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all
+ * {@link EventID#CELLEDITOR CELLEDITOR} events on each
+ * component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeCellEditorListener
+ */
+ static public void addCellEditorListener(CellEditorListener l) {
+ if (listenerList.getListenerCount(CellEditorListener.class) == 0) {
+ swingListener.installListeners(EventID.CELLEDITOR);
+ }
+ listenerList.add(CellEditorListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#CELLEDITOR CELLEDITOR} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addCellEditorListener
+ */
+ static public void removeCellEditorListener(CellEditorListener l) {
+ listenerList.remove(CellEditorListener.class, l);
+ if (listenerList.getListenerCount(CellEditorListener.class) == 0) {
+ swingListener.removeListeners(EventID.CELLEDITOR);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#CHANGE CHANGE}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeChangeListener
+ */
+ static public void addChangeListener(ChangeListener l) {
+ if (listenerList.getListenerCount(ChangeListener.class) == 0) {
+ swingListener.installListeners(EventID.CHANGE);
+ }
+ listenerList.add(ChangeListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#CHANGE CHANGE} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addChangeListener
+ */
+ static public void removeChangeListener(ChangeListener l) {
+ listenerList.remove(ChangeListener.class, l);
+ if (listenerList.getListenerCount(ChangeListener.class) == 0) {
+ swingListener.removeListeners(EventID.CHANGE);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#COLUMNMODEL COLUMNMODEL}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeColumnModelListener
+ */
+ static public void addColumnModelListener(TableColumnModelListener l) {
+ if (listenerList.getListenerCount(TableColumnModelListener.class) == 0) {
+ swingListener.installListeners(EventID.COLUMNMODEL);
+ }
+ listenerList.add(TableColumnModelListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#COLUMNMODEL COLUMNMODEL} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addColumnModelListener
+ */
+ static public void removeColumnModelListener(TableColumnModelListener l) {
+ listenerList.remove(TableColumnModelListener.class, l);
+ if (listenerList.getListenerCount(TableColumnModelListener.class) == 0) {
+ swingListener.removeListeners(EventID.COLUMNMODEL);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#DOCUMENT DOCUMENT}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeDocumentListener
+ */
+ static public void addDocumentListener(DocumentListener l) {
+ if (listenerList.getListenerCount(DocumentListener.class) == 0) {
+ swingListener.installListeners(EventID.DOCUMENT);
+ }
+ listenerList.add(DocumentListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#DOCUMENT DOCUMENT} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addDocumentListener
+ */
+ static public void removeDocumentListener(DocumentListener l) {
+ listenerList.remove(DocumentListener.class, l);
+ if (listenerList.getListenerCount(DocumentListener.class) == 0) {
+ swingListener.removeListeners(EventID.DOCUMENT);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#LISTDATA LISTDATA}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeListDataListener
+ */
+ static public void addListDataListener(ListDataListener l) {
+ if (listenerList.getListenerCount(ListDataListener.class) == 0) {
+ swingListener.installListeners(EventID.LISTDATA);
+ }
+ listenerList.add(ListDataListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#LISTDATA LISTDATA} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addListDataListener
+ */
+ static public void removeListDataListener(ListDataListener l) {
+ listenerList.remove(ListDataListener.class, l);
+ if (listenerList.getListenerCount(ListDataListener.class) == 0) {
+ swingListener.removeListeners(EventID.LISTDATA);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#LISTSELECTION LISTSELECTION}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeListSelectionListener
+ */
+ static public void addListSelectionListener(ListSelectionListener l) {
+ if (listenerList.getListenerCount(ListSelectionListener.class) == 0) {
+ swingListener.installListeners(EventID.LISTSELECTION);
+ }
+ listenerList.add(ListSelectionListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#LISTSELECTION LISTSELECTION} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addListSelectionListener
+ */
+ static public void removeListSelectionListener(ListSelectionListener l) {
+ listenerList.remove(ListSelectionListener.class, l);
+ if (listenerList.getListenerCount(ListSelectionListener.class) == 0) {
+ swingListener.removeListeners(EventID.LISTSELECTION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#MENU MENU} events
+ * on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeMenuListener
+ */
+ static public void addMenuListener(MenuListener l) {
+ if (listenerList.getListenerCount(MenuListener.class) == 0) {
+ swingListener.installListeners(EventID.MENU);
+ }
+ listenerList.add(MenuListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#MENU MENU} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addMenuListener
+ */
+ static public void removeMenuListener(MenuListener l) {
+ listenerList.remove(MenuListener.class, l);
+ if (listenerList.getListenerCount(MenuListener.class) == 0) {
+ swingListener.removeListeners(EventID.MENU);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#POPUPMENU POPUPMENU}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removePopupMenuListener
+ */
+ static public void addPopupMenuListener(PopupMenuListener l) {
+ if (listenerList.getListenerCount(PopupMenuListener.class) == 0) {
+ swingListener.installListeners(EventID.POPUPMENU);
+ }
+ listenerList.add(PopupMenuListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#POPUPMENU POPUPMENU} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addPopupMenuListener
+ */
+ static public void removePopupMenuListener(PopupMenuListener l) {
+ listenerList.remove(PopupMenuListener.class, l);
+ if (listenerList.getListenerCount(PopupMenuListener.class) == 0) {
+ swingListener.removeListeners(EventID.POPUPMENU);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TABLEMODEL TABLEMODEL}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTableModelListener
+ */
+ static public void addTableModelListener(TableModelListener l) {
+ if (listenerList.getListenerCount(TableModelListener.class) == 0) {
+ swingListener.installListeners(EventID.TABLEMODEL);
+ }
+ listenerList.add(TableModelListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#TABLEMODEL TABLEMODEL} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addTableModelListener
+ */
+ static public void removeTableModelListener(TableModelListener l) {
+ listenerList.remove(TableModelListener.class, l);
+ if (listenerList.getListenerCount(TableModelListener.class) == 0) {
+ swingListener.removeListeners(EventID.TABLEMODEL);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TREEEXPANSION TREEEXPANSION}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTreeExpansionListener
+ */
+ static public void addTreeExpansionListener(TreeExpansionListener l) {
+ if (listenerList.getListenerCount(TreeExpansionListener.class) == 0) {
+ swingListener.installListeners(EventID.TREEEXPANSION);
+ }
+ listenerList.add(TreeExpansionListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#TREEEXPANSION TREEEXPANSION} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addTreeExpansionListener
+ */
+ static public void removeTreeExpansionListener(TreeExpansionListener l) {
+ listenerList.remove(TreeExpansionListener.class, l);
+ if (listenerList.getListenerCount(TreeExpansionListener.class) == 0) {
+ swingListener.removeListeners(EventID.TREEEXPANSION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TREEMODEL TREEMODEL}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTreeModelListener
+ */
+ static public void addTreeModelListener(TreeModelListener l) {
+ if (listenerList.getListenerCount(TreeModelListener.class) == 0) {
+ swingListener.installListeners(EventID.TREEMODEL);
+ }
+ listenerList.add(TreeModelListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#TREEMODEL TREEMODEL} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addTreeModelListener
+ */
+ static public void removeTreeModelListener(TreeModelListener l) {
+ listenerList.remove(TreeModelListener.class, l);
+ if (listenerList.getListenerCount(TreeModelListener.class) == 0) {
+ swingListener.removeListeners(EventID.TREEMODEL);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#TREESELECTION TREESELECTION}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeTreeSelectionListener
+ */
+ static public void addTreeSelectionListener(TreeSelectionListener l) {
+ if (listenerList.getListenerCount(TreeSelectionListener.class) == 0) {
+ swingListener.installListeners(EventID.TREESELECTION);
+ }
+ listenerList.add(TreeSelectionListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#TREESELECTION TREESELECTION} events when they occur.
+ * @see #addTreeSelectionListener
+ * @param l the listener to remove
+ */
+ static public void removeTreeSelectionListener(TreeSelectionListener l) {
+ listenerList.remove(TreeSelectionListener.class, l);
+ if (listenerList.getListenerCount(TreeSelectionListener.class) == 0) {
+ swingListener.removeListeners(EventID.TREESELECTION);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#UNDOABLEEDIT UNDOABLEEDIT}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeUndoableEditListener
+ */
+ static public void addUndoableEditListener(UndoableEditListener l) {
+ if (listenerList.getListenerCount(UndoableEditListener.class) == 0) {
+ swingListener.installListeners(EventID.UNDOABLEEDIT);
+ }
+ listenerList.add(UndoableEditListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#UNDOABLEEDIT UNDOABLEEDIT} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addUndoableEditListener
+ */
+ static public void removeUndoableEditListener(UndoableEditListener l) {
+ listenerList.remove(UndoableEditListener.class, l);
+ if (listenerList.getListenerCount(UndoableEditListener.class) == 0) {
+ swingListener.removeListeners(EventID.UNDOABLEEDIT);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#INTERNALFRAME INTERNALFRAME}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeInternalFrameListener
+ */
+ static public void addInternalFrameListener(InternalFrameListener l) {
+ if (listenerList.getListenerCount(InternalFrameListener.class) == 0) {
+ swingListener.installListeners(EventID.INTERNALFRAME);
+ }
+ listenerList.add(InternalFrameListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#INTERNALFRAME INTERNALFRAME} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addInternalFrameListener
+ */
+ static public void removeInternalFrameListener(InternalFrameListener l) {
+ listenerList.remove(InternalFrameListener.class, l);
+ if (listenerList.getListenerCount(InternalFrameListener.class) == 0) {
+ swingListener.removeListeners(EventID.INTERNALFRAME);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#PROPERTYCHANGE PROPERTYCHANGE}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removePropertyChangeListener
+ */
+ static public void addPropertyChangeListener(PropertyChangeListener l) {
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ swingListener.installListeners(EventID.PROPERTYCHANGE);
+ }
+ listenerList.add(PropertyChangeListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#PROPERTYCHANGE PROPERTYCHANGE} events when they occur.
+ * @see #addPropertyChangeListener
+ * @param l the listener to remove
+ */
+ static public void removePropertyChangeListener(PropertyChangeListener l) {
+ listenerList.remove(PropertyChangeListener.class, l);
+ if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+ swingListener.removeListeners(EventID.PROPERTYCHANGE);
+ }
+ }
+
+ /**
+ * Adds the specified listener to receive all {@link EventID#VETOABLECHANGE VETOABLECHANGE}
+ * events on each component instance in the Java Virtual Machine as they occur.
+ *
Note: This listener is automatically added to all component
+ * instances created after this method is called. In addition, it
+ * is only added to component instances that support this listener type.
+ *
+ * @param l the listener to add
+ * @see #removeVetoableChangeListener
+ */
+ static public void addVetoableChangeListener(VetoableChangeListener l) {
+ if (listenerList.getListenerCount(VetoableChangeListener.class) == 0) {
+ swingListener.installListeners(EventID.VETOABLECHANGE);
+ }
+ listenerList.add(VetoableChangeListener.class, l);
+ }
+
+ /**
+ * Removes the specified listener so it no longer receives
+ * {@link EventID#VETOABLECHANGE VETOABLECHANGE} events when they occur.
+ *
+ * @param l the listener to remove
+ * @see #addVetoableChangeListener
+ */
+ static public void removeVetoableChangeListener(VetoableChangeListener l) {
+ listenerList.remove(VetoableChangeListener.class, l);
+ if (listenerList.getListenerCount(VetoableChangeListener.class) == 0) {
+ swingListener.removeListeners(EventID.VETOABLECHANGE);
+ }
+ }
+
+
+ /**
+ * SwingEventListener is the class that does all the work for
+ * SwingEventMonitor. It is not intended for use by any other class
+ * except SwingEventMonitor.
+ *
+ */
+ static class SwingEventListener extends AWTEventsListener
+ implements AncestorListener, CaretListener, CellEditorListener,
+ ChangeListener, DocumentListener, ListDataListener,
+ ListSelectionListener, MenuListener, PopupMenuListener,
+ TableColumnModelListener, TableModelListener, TreeExpansionListener,
+ TreeModelListener, TreeSelectionListener, UndoableEditListener,
+ InternalFrameListener,
+ PropertyChangeListener, VetoableChangeListener {
+
+ /**
+ * internal variables for Caret introspection
+ */
+ private java.lang.Class>[] caretListeners;
+ private java.lang.reflect.Method removeCaretMethod;
+ private java.lang.reflect.Method addCaretMethod;
+ private java.lang.Object[] caretArgs;
+
+ /**
+ * internal variables for CellEditor introspection
+ */
+ private java.lang.Class>[] cellEditorListeners;
+ private java.lang.reflect.Method removeCellEditorMethod;
+ private java.lang.reflect.Method addCellEditorMethod;
+ private java.lang.Object[] cellEditorArgs;
+ private java.lang.reflect.Method getCellEditorMethod;
+
+ /**
+ * internal variables for Change introspection
+ */
+ private java.lang.Class>[] changeListeners;
+ private java.lang.reflect.Method removeChangeMethod;
+ private java.lang.reflect.Method addChangeMethod;
+ private java.lang.Object[] changeArgs;
+
+ /**
+ * internal variable for ColumnModel introspection
+ */
+ private java.lang.reflect.Method getColumnModelMethod;
+
+ /**
+ * internal variables for Document introspection
+ */
+ private java.lang.Class>[] documentListeners;
+ private java.lang.reflect.Method removeDocumentMethod;
+ private java.lang.reflect.Method addDocumentMethod;
+ private java.lang.Object[] documentArgs;
+ private java.lang.reflect.Method getDocumentMethod;
+
+ /**
+ * internal variable for ListData, Table, and Tree introspection
+ */
+ private java.lang.reflect.Method getModelMethod;
+
+ /**
+ * internal variables for ListSelection introspection
+ */
+ private java.lang.Class>[] listSelectionListeners;
+ private java.lang.reflect.Method removeListSelectionMethod;
+ private java.lang.reflect.Method addListSelectionMethod;
+ private java.lang.Object[] listSelectionArgs;
+ private java.lang.reflect.Method getSelectionModelMethod;
+
+ /**
+ * internal variables for Menu introspection
+ */
+ private java.lang.Class>[] menuListeners;
+ private java.lang.reflect.Method removeMenuMethod;
+ private java.lang.reflect.Method addMenuMethod;
+ private java.lang.Object[] menuArgs;
+
+ /**
+ * internal variables for PopupMenu introspection
+ */
+ private java.lang.Class>[] popupMenuListeners;
+ private java.lang.reflect.Method removePopupMenuMethod;
+ private java.lang.reflect.Method addPopupMenuMethod;
+ private java.lang.Object[] popupMenuArgs;
+ private java.lang.reflect.Method getPopupMenuMethod;
+
+ /**
+ * internal variables for TreeExpansion introspection
+ */
+ private java.lang.Class>[] treeExpansionListeners;
+ private java.lang.reflect.Method removeTreeExpansionMethod;
+ private java.lang.reflect.Method addTreeExpansionMethod;
+ private java.lang.Object[] treeExpansionArgs;
+
+ /**
+ * internal variables for TreeSelection introspection
+ */
+ private java.lang.Class>[] treeSelectionListeners;
+ private java.lang.reflect.Method removeTreeSelectionMethod;
+ private java.lang.reflect.Method addTreeSelectionMethod;
+ private java.lang.Object[] treeSelectionArgs;
+
+ /**
+ * internal variables for UndoableEdit introspection
+ */
+ private java.lang.Class>[] undoableEditListeners;
+ private java.lang.reflect.Method removeUndoableEditMethod;
+ private java.lang.reflect.Method addUndoableEditMethod;
+ private java.lang.Object[] undoableEditArgs;
+
+ /**
+ * internal variables for InternalFrame introspection
+ */
+ private java.lang.Class>[] internalFrameListeners;
+ private java.lang.reflect.Method removeInternalFrameMethod;
+ private java.lang.reflect.Method addInternalFrameMethod;
+ private java.lang.Object[] internalFrameArgs;
+
+ /**
+ * internal variables for PropertyChange introspection
+ */
+ private java.lang.Class>[] propertyChangeListeners;
+ private java.lang.reflect.Method removePropertyChangeMethod;
+ private java.lang.reflect.Method addPropertyChangeMethod;
+ private java.lang.Object[] propertyChangeArgs;
+
+ /**
+ * internal variables for a variety of change introspections
+ */
+ private java.lang.Class>[] nullClass;
+ private java.lang.Object[] nullArgs;
+
+ /**
+ * Create a new instance of this class and install it on each component
+ * instance in the virtual machine that supports any of the currently
+ * registered listeners in SwingEventMonitor. Also registers itself
+ * as a TopLevelWindowListener with EventQueueMonitor so it can
+ * automatically add new listeners to new components.
+ * @see EventQueueMonitor
+ * @see SwingEventMonitor
+ */
+ public SwingEventListener() {
+ initializeIntrospection();
+ installListeners();
+ EventQueueMonitor.addTopLevelWindowListener(this);
+ }
+
+ /**
+ * Set up all of the variables needed for introspection
+ */
+ private boolean initializeIntrospection() {
+ caretListeners = new java.lang.Class>[1];
+ caretArgs = new java.lang.Object[1];
+ caretListeners[0] = javax.swing.event.CaretListener.class;
+ caretArgs[0] = this;
+
+ cellEditorListeners = new java.lang.Class>[1];
+ cellEditorArgs = new java.lang.Object[1];
+ cellEditorListeners[0] = javax.swing.event.CellEditorListener.class;
+ cellEditorArgs[0] = this;
+
+ changeListeners = new java.lang.Class>[1];
+ changeArgs = new java.lang.Object[1];
+ changeListeners[0] = javax.swing.event.ChangeListener.class;
+ changeArgs[0] = this;
+
+ documentListeners = new java.lang.Class>[1];
+ documentArgs = new java.lang.Object[1];
+ documentListeners[0] = javax.swing.event.DocumentListener.class;
+ documentArgs[0] = this;
+
+ listSelectionListeners = new java.lang.Class>[1];
+ listSelectionArgs = new java.lang.Object[1];
+ listSelectionListeners[0] = javax.swing.event.ListSelectionListener.class;
+ listSelectionArgs[0] = this;
+
+ menuListeners = new java.lang.Class>[1];
+ menuArgs = new java.lang.Object[1];
+ menuListeners[0] = javax.swing.event.MenuListener.class;
+ menuArgs[0] = this;
+
+ popupMenuListeners = new java.lang.Class>[1];
+ popupMenuArgs = new java.lang.Object[1];
+ popupMenuListeners[0] = javax.swing.event.PopupMenuListener.class;
+ popupMenuArgs[0] = this;
+
+ treeExpansionListeners = new java.lang.Class>[1];
+ treeExpansionArgs = new java.lang.Object[1];
+ treeExpansionListeners[0] = javax.swing.event.TreeExpansionListener.class;
+ treeExpansionArgs[0] = this;
+
+ treeSelectionListeners = new java.lang.Class>[1];
+ treeSelectionArgs = new java.lang.Object[1];
+ treeSelectionListeners[0] = javax.swing.event.TreeSelectionListener.class;
+ treeSelectionArgs[0] = this;
+
+ undoableEditListeners = new java.lang.Class>[1];
+ undoableEditArgs = new java.lang.Object[1];
+ undoableEditListeners[0] = javax.swing.event.UndoableEditListener.class;
+ undoableEditArgs[0] = this;
+
+ internalFrameListeners = new java.lang.Class>[1];
+ internalFrameArgs = new java.lang.Object[1];
+ internalFrameListeners[0] = javax.swing.event.InternalFrameListener.class;
+ internalFrameArgs[0] = this;
+
+ nullClass = new java.lang.Class>[0];
+ nullArgs = new java.lang.Object[0];
+
+ propertyChangeListeners = new java.lang.Class>[1];
+ propertyChangeArgs = new java.lang.Object[1];
+ propertyChangeListeners[0] = java.beans.PropertyChangeListener.class;
+ propertyChangeArgs[0] = this;
+
+ return true;
+ }
+
+ /**
+ * Installs all appropriate Swing listeners to just the component.
+ * Also calls super (AWTEventsListener.installListeners()) to install
+ * the requested AWT listeners.
+ * @param c the component to add listeners to
+ */
+ protected void installListeners(Component c) {
+
+ // This SwingEventListener needs to be notified when a new
+ // Swing component has been added so it can add Swing listeners
+ // to these components. As a result, we always need a Container
+ // listener on every Container.
+ //
+ installListeners(c,EventID.CONTAINER);
+
+ // conditionally install Swing listeners
+ //
+ if (SwingEventMonitor.listenerList.getListenerCount(AncestorListener.class) > 0) {
+ installListeners(c,EventID.ANCESTOR);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(CaretListener.class) > 0) {
+ installListeners(c,EventID.CARET);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(CellEditorListener.class) > 0) {
+ installListeners(c,EventID.CELLEDITOR);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ChangeListener.class) > 0) {
+ installListeners(c,EventID.CHANGE);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TableColumnModelListener.class) > 0) {
+ installListeners(c,EventID.COLUMNMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(DocumentListener.class) > 0) {
+ installListeners(c,EventID.DOCUMENT);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ListDataListener.class) > 0) {
+ installListeners(c,EventID.LISTDATA);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ListSelectionListener.class) > 0) {
+ installListeners(c,EventID.LISTSELECTION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(MenuListener.class) > 0) {
+ installListeners(c,EventID.MENU);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(PopupMenuListener.class) > 0) {
+ installListeners(c,EventID.POPUPMENU);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TableModelListener.class) > 0) {
+ installListeners(c,EventID.TABLEMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeExpansionListener.class) > 0) {
+ installListeners(c,EventID.TREEEXPANSION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeModelListener.class) > 0) {
+ installListeners(c,EventID.TREEMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeSelectionListener.class) > 0) {
+ installListeners(c,EventID.TREESELECTION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(UndoableEditListener.class) > 0) {
+ installListeners(c,EventID.UNDOABLEEDIT);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(InternalFrameListener.class) > 0) {
+ installListeners(c,EventID.INTERNALFRAME);
+ }
+
+ // Conditionally install Beans listeners
+ //
+ if (SwingEventMonitor.listenerList.getListenerCount(PropertyChangeListener.class) > 0) {
+ installListeners(c,EventID.PROPERTYCHANGE);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(VetoableChangeListener.class) > 0) {
+ installListeners(c,EventID.VETOABLECHANGE);
+ }
+
+ // Now install the AWT listeners if needed.
+ //
+ super.installListeners(c);
+ }
+
+ /**
+ * Installs all appropriate Swing listeners to the component and all its
+ * children. As a precaution, it always attempts to remove itself as
+ * a listener first so we're always guaranteed it will installed itself
+ * just once.
+ * @param c the component to add listeners to
+ * @param eventID the eventID to add listeners for
+ */
+ protected void installListeners(Component c, int eventID) {
+
+ // install the appropriate listener hook into this component
+ //
+ switch (eventID) {
+
+ case EventID.CONTAINER:
+ if (c instanceof Container) {
+ ((Container) c).removeContainerListener(this);
+ ((Container) c).addContainerListener(this);
+ }
+ break;
+
+ case EventID.ANCESTOR:
+ if (c instanceof JComponent) {
+ ((JComponent) c).removeAncestorListener(this);
+ ((JComponent) c).addAncestorListener(this);
+ }
+ break;
+
+ case EventID.CARET:
+ try {
+ removeCaretMethod = c.getClass().getMethod(
+ "removeCaretListener", caretListeners);
+ addCaretMethod = c.getClass().getMethod(
+ "addCaretListener", caretListeners);
+ try {
+ removeCaretMethod.invoke(c, caretArgs);
+ addCaretMethod.invoke(c, caretArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.CELLEDITOR:
+ // Look for components which support the getCellEditor method
+ // (e.g. JTable, JTree)
+ //
+ try {
+ getCellEditorMethod = c.getClass().getMethod(
+ "getCellEditorMethod", nullClass);
+ try {
+ Object o = getCellEditorMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof CellEditor) {
+ ((CellEditor) o).removeCellEditorListener(this);
+ ((CellEditor) o).addCellEditorListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support CellEditor listeners
+ // (no current example)
+ //
+ try {
+ removeCellEditorMethod = c.getClass().getMethod(
+ "removeCellEditorListener", cellEditorListeners);
+ addCellEditorMethod = c.getClass().getMethod(
+ "addCellEditorListener", cellEditorListeners);
+ try {
+ removeCellEditorMethod.invoke(c, cellEditorArgs);
+ addCellEditorMethod.invoke(c, cellEditorArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.CHANGE:
+ // [[[FIXME: Need to add support for Style, StyleContext -pk]]]
+
+ // Look for components which support Change listeners
+ // (e.g. AbstractButton, Caret, JProgressBar, JSlider,
+ // JTabbedpane, JTextComponent, JViewport)
+ //
+ try {
+ removeChangeMethod = c.getClass().getMethod(
+ "removeChangeListener", changeListeners);
+ addChangeMethod = c.getClass().getMethod(
+ "addChangeListener", changeListeners);
+ try {
+ removeChangeMethod.invoke(c, changeArgs);
+ addChangeMethod.invoke(c, changeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support the getModel method
+ // whose model supports Change listeners
+ // (e.g. BoundedRangeModel, ButtonModel, SingleSelectionModel)
+ //
+ try {
+ getModelMethod = c.getClass().getMethod(
+ "getModel", nullClass);
+ try {
+ Object o = getModelMethod.invoke(c, nullArgs);
+ if (o != null) {
+ removeChangeMethod = o.getClass().getMethod(
+ "removeChangeListener", changeListeners);
+ addChangeMethod = o.getClass().getMethod(
+ "addChangeListener", changeListeners);
+ removeChangeMethod.invoke(o, changeArgs);
+ addChangeMethod.invoke(o, changeArgs);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ break;
+
+ case EventID.COLUMNMODEL:
+ try {
+ getColumnModelMethod = c.getClass().getMethod(
+ "getTableColumnModel", nullClass);
+ try {
+ Object o = getColumnModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof TableColumnModel) {
+ ((TableColumnModel) o).removeColumnModelListener(this);
+ ((TableColumnModel) o).addColumnModelListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.DOCUMENT:
+ // Look for components which support the getDocument method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getDocumentMethod = c.getClass().getMethod(
+ "getDocument", nullClass);
+ try {
+ Object o = getDocumentMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof Document) {
+ ((Document) o).removeDocumentListener(this);
+ ((Document) o).addDocumentListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support Document listeners
+ // (no current example)
+ //
+ try {
+ removeDocumentMethod = c.getClass().getMethod(
+ "removeDocumentListener", documentListeners);
+ addDocumentMethod = c.getClass().getMethod(
+ "addDocumentListener", documentListeners);
+ try {
+ removeDocumentMethod.invoke(c, documentArgs);
+ addDocumentMethod.invoke(c, documentArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ // Add the monitor as a PropertyChangeListener for document
+ // change events from text components.
+ //
+ if (c instanceof JTextComponent) {
+ try {
+ removePropertyChangeMethod = c.getClass().getMethod(
+ "removePropertyChangeListener",
+ propertyChangeListeners);
+ addPropertyChangeMethod = c.getClass().getMethod(
+ "addPropertyChangeListener",
+ propertyChangeListeners);
+ try {
+ removePropertyChangeMethod.invoke(c,
+ propertyChangeArgs);
+ addPropertyChangeMethod.invoke(c,
+ propertyChangeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ }
+ break;
+
+ case EventID.LISTDATA:
+ case EventID.TABLEMODEL:
+ case EventID.TREEMODEL:
+ try {
+ getModelMethod = c.getClass().getMethod(
+ "getModel", nullClass);
+ try {
+ Object o = getModelMethod.invoke(c, nullArgs);
+ if (o != null) {
+ if (eventID == EventID.LISTDATA &&
+ o instanceof ListModel) {
+ ((ListModel) o).removeListDataListener(this);
+ ((ListModel) o).addListDataListener(this);
+ } else if (eventID == EventID.TABLEMODEL &&
+ o instanceof TableModel) {
+ ((TableModel) o).removeTableModelListener(this);
+ ((TableModel) o).addTableModelListener(this);
+ } else if (
+ o instanceof TreeModel) {
+ ((TreeModel) o).removeTreeModelListener(this);
+ ((TreeModel) o).addTreeModelListener(this);
+ }
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.LISTSELECTION:
+ // Look for components which support ListSelectionListeners
+ // (e.g. JList)
+ //
+ try {
+ removeListSelectionMethod = c.getClass().getMethod(
+ "removeListSelectionListener", listSelectionListeners);
+ addListSelectionMethod = c.getClass().getMethod(
+ "addListSelectionListener", listSelectionListeners);
+ try {
+ removeListSelectionMethod.invoke(c, listSelectionArgs);
+ addListSelectionMethod.invoke(c, listSelectionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for selection models which support ListSelectionListeners
+ // (e.g. JTable's selection model)
+ //
+ try {
+ getSelectionModelMethod = c.getClass().getMethod(
+ "getSelectionModel", nullClass);
+ try {
+ Object o = getSelectionModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof ListSelectionModel) {
+ ((ListSelectionModel) o).removeListSelectionListener(this);
+ ((ListSelectionModel) o).addListSelectionListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.MENU:
+ try {
+ removeMenuMethod = c.getClass().getMethod(
+ "removeMenuListener", menuListeners);
+ addMenuMethod = c.getClass().getMethod(
+ "addMenuListener", menuListeners);
+ try {
+ removeMenuMethod.invoke(c, menuArgs);
+ addMenuMethod.invoke(c, menuArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.POPUPMENU:
+ // Look for components which support PopupMenuListeners
+ // (e.g. JPopupMenu)
+ //
+ try {
+ removePopupMenuMethod = c.getClass().getMethod(
+ "removePopupMenuListener", popupMenuListeners);
+ addPopupMenuMethod = c.getClass().getMethod(
+ "addPopupMenuListener", popupMenuListeners);
+ try {
+ removePopupMenuMethod.invoke(c, popupMenuArgs);
+ addPopupMenuMethod.invoke(c, popupMenuArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support getPopupMenu
+ // (e.g. JMenu)
+ //
+ try {
+ getPopupMenuMethod = c.getClass().getMethod(
+ "getPopupMenu", nullClass);
+ try {
+ Object o = getPopupMenuMethod.invoke(c, nullArgs);
+ if (o != null) {
+ removePopupMenuMethod = o.getClass().getMethod(
+ "removePopupMenuListener", popupMenuListeners);
+ addPopupMenuMethod = o.getClass().getMethod(
+ "addPopupMenuListener", popupMenuListeners);
+ removePopupMenuMethod.invoke(o, popupMenuArgs);
+ addPopupMenuMethod.invoke(o, popupMenuArgs);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.TREEEXPANSION:
+ try {
+ removeTreeExpansionMethod = c.getClass().getMethod(
+ "removeTreeExpansionListener", treeExpansionListeners);
+ addTreeExpansionMethod = c.getClass().getMethod(
+ "addTreeExpansionListener", treeExpansionListeners);
+ try {
+ removeTreeExpansionMethod.invoke(c, treeExpansionArgs);
+ addTreeExpansionMethod.invoke(c, treeExpansionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.TREESELECTION:
+ try {
+ removeTreeSelectionMethod = c.getClass().getMethod(
+ "removeTreeSelectionListener", treeSelectionListeners);
+ addTreeSelectionMethod = c.getClass().getMethod(
+ "addTreeSelectionListener", treeSelectionListeners);
+ try {
+ removeTreeSelectionMethod.invoke(c, treeSelectionArgs);
+ addTreeSelectionMethod.invoke(c, treeSelectionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.UNDOABLEEDIT:
+ // Look for components which support the getDocument method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getDocumentMethod = c.getClass().getMethod(
+ "getDocument", nullClass);
+ try {
+ Object o = getDocumentMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof Document) {
+ ((Document) o).removeUndoableEditListener(this);
+ ((Document) o).addUndoableEditListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support UndoableEdit listeners
+ // (no current example)
+ //
+ try {
+ removeUndoableEditMethod = c.getClass().getMethod(
+ "removeUndoableEditListener", undoableEditListeners);
+ addUndoableEditMethod = c.getClass().getMethod(
+ "addUndoableEditListener", undoableEditListeners);
+ try {
+ removeUndoableEditMethod.invoke(c, undoableEditArgs);
+ addUndoableEditMethod.invoke(c, undoableEditArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.INTERNALFRAME:
+ // Look for components which support InternalFrame listeners
+ // (e.g. JInternalFrame)
+ //
+ try {
+ removeInternalFrameMethod = c.getClass().getMethod(
+ "removeInternalFrameListener", internalFrameListeners);
+ addInternalFrameMethod = c.getClass().getMethod(
+ "addInternalFrameListener", internalFrameListeners);
+ try {
+ removeInternalFrameMethod.invoke(c, internalFrameArgs);
+ addInternalFrameMethod.invoke(c, internalFrameArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.PROPERTYCHANGE:
+ // Look for components which support PropertyChange listeners
+ // (e.g. JComponent)
+ //
+ try {
+ removePropertyChangeMethod = c.getClass().getMethod(
+ "removePropertyChangeListener", propertyChangeListeners);
+ addPropertyChangeMethod = c.getClass().getMethod(
+ "addPropertyChangeListener", propertyChangeListeners);
+ try {
+ removePropertyChangeMethod.invoke(c, propertyChangeArgs);
+ addPropertyChangeMethod.invoke(c, propertyChangeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support the getSelectionModel method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getSelectionModelMethod = c.getClass().getMethod(
+ "getSelectionModel", nullClass);
+ try {
+ Object o = getSelectionModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof TreeSelectionModel) {
+ ((TreeSelectionModel) o).removePropertyChangeListener(this);
+ ((TreeSelectionModel) o).addPropertyChangeListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.VETOABLECHANGE:
+ if (c instanceof JComponent) {
+ ((JComponent) c).removeVetoableChangeListener(this);
+ ((JComponent) c).addVetoableChangeListener(this);
+ }
+ break;
+
+ // Don't bother recursing the children if this isn't going to
+ // accomplish anything.
+ //
+ default:
+ return;
+ }
+
+ if (c instanceof Container) {
+ int count = ((Container) c).getComponentCount();
+ for (int i = 0; i < count; i++) {
+ installListeners(((Container) c).getComponent(i), eventID);
+ }
+ }
+ }
+
+ /**
+ * Removes all listeners for the given component and all its children.
+ * @param c the component
+ */
+ protected void removeListeners(Component c) {
+
+ // conditionaly remove the Swing listeners
+ //
+ if (SwingEventMonitor.listenerList.getListenerCount(AncestorListener.class) > 0) {
+ removeListeners(c,EventID.ANCESTOR);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(CaretListener.class) > 0) {
+ removeListeners(c,EventID.CARET);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(CellEditorListener.class) > 0) {
+ removeListeners(c,EventID.CELLEDITOR);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ChangeListener.class) > 0) {
+ removeListeners(c,EventID.CHANGE);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TableColumnModelListener.class) > 0) {
+ removeListeners(c,EventID.COLUMNMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(DocumentListener.class) > 0) {
+ removeListeners(c,EventID.DOCUMENT);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ListDataListener.class) > 0) {
+ removeListeners(c,EventID.LISTDATA);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(ListSelectionListener.class) > 0) {
+ removeListeners(c,EventID.LISTSELECTION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(MenuListener.class) > 0) {
+ removeListeners(c,EventID.MENU);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(PopupMenuListener.class) > 0) {
+ removeListeners(c,EventID.POPUPMENU);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TableModelListener.class) > 0) {
+ removeListeners(c,EventID.TABLEMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeExpansionListener.class) > 0) {
+ removeListeners(c,EventID.TREEEXPANSION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeModelListener.class) > 0) {
+ removeListeners(c,EventID.TREEMODEL);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(TreeSelectionListener.class) > 0) {
+ removeListeners(c,EventID.TREESELECTION);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(UndoableEditListener.class) > 0) {
+ removeListeners(c,EventID.UNDOABLEEDIT);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(InternalFrameListener.class) > 0) {
+ removeListeners(c,EventID.INTERNALFRAME);
+ }
+
+ // conditionaly remove the beans listeners
+ //
+ if (SwingEventMonitor.listenerList.getListenerCount(PropertyChangeListener.class) > 0) {
+ removeListeners(c,EventID.PROPERTYCHANGE);
+ }
+ if (SwingEventMonitor.listenerList.getListenerCount(VetoableChangeListener.class) > 0) {
+ removeListeners(c,EventID.VETOABLECHANGE);
+ }
+
+ // Now remove the AWT listeners if needed.
+ //
+ super.removeListeners(c);
+ }
+
+ /**
+ * Removes all Swing listeners for the event ID from the component and
+ * all of its children.
+ * @param c the component to remove listeners from
+ */
+ protected void removeListeners(Component c, int eventID) {
+
+ // remove the appropriate listener hook into this component
+ //
+ switch (eventID) {
+
+ case EventID.CONTAINER:
+ //Never remove these because we're always interested in them
+ // for our own use.
+ break;
+
+ case EventID.ANCESTOR:
+ if (c instanceof JComponent) {
+ ((JComponent) c).removeAncestorListener(this);
+ }
+ break;
+
+ case EventID.CARET:
+ try {
+ removeCaretMethod = c.getClass().getMethod(
+ "removeCaretListener", caretListeners);
+ try {
+ removeCaretMethod.invoke(c, caretArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.CELLEDITOR:
+ // Look for components which support the getCellEditor method
+ // (e.g. JTable, JTree)
+ //
+ try {
+ getCellEditorMethod = c.getClass().getMethod(
+ "getCellEditorMethod", nullClass);
+ try {
+ Object o = getCellEditorMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof CellEditor) {
+ ((CellEditor) o).removeCellEditorListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support CellEditor listeners
+ // (no current example)
+ //
+ try {
+ removeCellEditorMethod = c.getClass().getMethod(
+ "removeCellEditorListener", cellEditorListeners);
+ try {
+ removeCellEditorMethod.invoke(c, cellEditorArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.CHANGE:
+ // [[[FIXME: Need to add support for Style, StyleContext -pk ]]]
+
+ // Look for components which support Change listeners
+ // (e.g. AbstractButton, Caret, JProgressBar, JSlider,
+ // JTabbedpane, JTextComponent, JViewport)
+ //
+ try {
+ removeChangeMethod = c.getClass().getMethod(
+ "removeChangeListener", changeListeners);
+ try {
+ removeChangeMethod.invoke(c, changeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support the getModel method
+ // whose model supports Change listeners
+ // (e.g. BoundedRangeModel, ButtonModel, SingleSelectionModel)
+ //
+ try {
+ getModelMethod = c.getClass().getMethod(
+ "getModel", nullClass);
+ try {
+ Object o = getModelMethod.invoke(c, nullArgs);
+ if (o != null) {
+ removeChangeMethod = o.getClass().getMethod(
+ "removeChangeListener", changeListeners);
+ removeChangeMethod.invoke(o, changeArgs);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.COLUMNMODEL:
+ try {
+ getColumnModelMethod = c.getClass().getMethod(
+ "getTableColumnModel", nullClass);
+ try {
+ Object o = getColumnModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof TableColumnModel) {
+ ((TableColumnModel) o).removeColumnModelListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.DOCUMENT:
+ // Look for components which support the getDocument method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getDocumentMethod = c.getClass().getMethod(
+ "getDocument", nullClass);
+ try {
+ Object o = getDocumentMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof Document) {
+ ((Document) o).removeDocumentListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support Document listeners
+ // (no current example)
+ //
+ try {
+ removeDocumentMethod = c.getClass().getMethod(
+ "removeDocumentListener", documentListeners);
+ try {
+ removeDocumentMethod.invoke(c, documentArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.LISTDATA:
+ case EventID.TABLEMODEL:
+ case EventID.TREEMODEL:
+ try {
+ getModelMethod = c.getClass().getMethod(
+ "getModel", nullClass);
+ try {
+ Object o = getModelMethod.invoke(c, nullArgs);
+ if (o != null) {
+ if (eventID == EventID.LISTDATA &&
+ o instanceof ListModel) {
+ ((ListModel) o).removeListDataListener(this);
+ } else if (eventID == EventID.TABLEMODEL &&
+ o instanceof TableModel) {
+ ((TableModel) o).removeTableModelListener(this);
+ } else if (
+ o instanceof TreeModel) {
+ ((TreeModel) o).removeTreeModelListener(this);
+ }
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.LISTSELECTION:
+ // Look for components which support ListSelectionListeners
+ // (e.g. JList)
+ //
+ try {
+ removeListSelectionMethod = c.getClass().getMethod(
+ "removeListSelectionListener", listSelectionListeners);
+ try {
+ removeListSelectionMethod.invoke(c, listSelectionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for selection models which support
+ // ListSelectionListeners (e.g. JTable's selection model)
+ //
+ try {
+ getSelectionModelMethod = c.getClass().getMethod(
+ "getSelectionModel", nullClass);
+ try {
+ Object o = getSelectionModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof ListSelectionModel) {
+ ((ListSelectionModel) o).removeListSelectionListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.MENU:
+ try {
+ removeMenuMethod = c.getClass().getMethod(
+ "removeMenuListener", menuListeners);
+ try {
+ removeMenuMethod.invoke(c, menuArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.POPUPMENU:
+ // Look for components which support PopupMenuListeners
+ // (e.g. JPopupMenu)
+ //
+ try {
+ removePopupMenuMethod = c.getClass().getMethod(
+ "removePopupMenuListener", popupMenuListeners);
+ try {
+ removePopupMenuMethod.invoke(c, popupMenuArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support getPopupMenu
+ // (e.g. JMenu)
+ //
+ try {
+ getPopupMenuMethod = c.getClass().getMethod(
+ "getPopupMenu", nullClass);
+ try {
+ Object o = getPopupMenuMethod.invoke(c, nullArgs);
+ if (o != null) {
+ removePopupMenuMethod = o.getClass().getMethod(
+ "removePopupMenuListener", popupMenuListeners);
+ removePopupMenuMethod.invoke(o, popupMenuArgs);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.TREEEXPANSION:
+ try {
+ removeTreeExpansionMethod = c.getClass().getMethod(
+ "removeTreeExpansionListener", treeExpansionListeners);
+ try {
+ removeTreeExpansionMethod.invoke(c, treeExpansionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.TREESELECTION:
+ try {
+ removeTreeSelectionMethod = c.getClass().getMethod(
+ "removeTreeSelectionListener", treeSelectionListeners);
+ try {
+ removeTreeSelectionMethod.invoke(c, treeSelectionArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.UNDOABLEEDIT:
+ // Look for components which support the getDocument method
+ // (e.g. JTextComponent)
+ //
+ try {
+ getDocumentMethod = c.getClass().getMethod(
+ "getDocument", nullClass);
+ try {
+ Object o = getDocumentMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof Document) {
+ ((Document) o).removeUndoableEditListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support UndoableEdit listeners
+ // (no current example)
+ //
+ try {
+ removeUndoableEditMethod = c.getClass().getMethod(
+ "removeUndoableEditListener", undoableEditListeners);
+ try {
+ removeUndoableEditMethod.invoke(c, undoableEditArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.INTERNALFRAME:
+ try {
+ removeInternalFrameMethod = c.getClass().getMethod(
+ "removeInternalFrameListener", internalFrameListeners);
+ try {
+ removeInternalFrameMethod.invoke(c, internalFrameArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.PROPERTYCHANGE:
+ // Look for components which support PropertyChange listeners
+ // (e.g. JComponent)
+ //
+ try {
+ removePropertyChangeMethod = c.getClass().getMethod(
+ "removePropertyChangeListener", propertyChangeListeners);
+ try {
+ removePropertyChangeMethod.invoke(c, propertyChangeArgs);
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+
+ // Look for components which support the getSelectionModel
+ // method (e.g. JTextComponent)
+ //
+ try {
+ getSelectionModelMethod = c.getClass().getMethod(
+ "getSelectionModel", nullClass);
+ try {
+ Object o = getSelectionModelMethod.invoke(c, nullArgs);
+ if (o != null && o instanceof TreeSelectionModel) {
+ ((TreeSelectionModel) o).removePropertyChangeListener(this);
+ }
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ System.out.println("Exception: " + e.toString());
+ } catch (IllegalAccessException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ } catch (NoSuchMethodException e) {
+ // System.out.println("Exception: " + e.toString());
+ } catch (SecurityException e) {
+ System.out.println("Exception: " + e.toString());
+ }
+ break;
+
+ case EventID.VETOABLECHANGE:
+ if (c instanceof JComponent) {
+ ((JComponent) c).removeVetoableChangeListener(this);
+ }
+ break;
+
+ default:
+ return;
+ }
+
+ if (c instanceof Container) {
+ int count = ((Container) c).getComponentCount();
+ for (int i = 0; i < count; i++) {
+ removeListeners(((Container) c).getComponent(i), eventID);
+ }
+ }
+ }
+
+ /********************************************************************/
+ /* */
+ /* Listener Interface Methods */
+ /* */
+ /********************************************************************/
+
+ /* ContainerListener Methods ************************************/
+
+ public void componentAdded(ContainerEvent e) {
+ installListeners(e.getChild());
+ }
+ public void componentRemoved(ContainerEvent e) {
+ removeListeners(e.getChild());
+ }
+
+ /* AncestorListener Methods ******************************************/
+
+ public void ancestorAdded(AncestorEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==AncestorListener.class) {
+ ((AncestorListener)listeners[i+1]).ancestorAdded(e);
+ }
+ }
+ }
+
+ public void ancestorRemoved(AncestorEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==AncestorListener.class) {
+ ((AncestorListener)listeners[i+1]).ancestorRemoved(e);
+ }
+ }
+ }
+
+ public void ancestorMoved(AncestorEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==AncestorListener.class) {
+ ((AncestorListener)listeners[i+1]).ancestorMoved(e);
+ }
+ }
+ }
+
+ /* CaretListener Methods ******************************************/
+
+ public void caretUpdate(CaretEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==CaretListener.class) {
+ ((CaretListener)listeners[i+1]).caretUpdate(e);
+ }
+ }
+ }
+
+ /* CellEditorListener Methods *****************************************/
+
+ public void editingStopped(ChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==CellEditorListener.class) {
+ ((CellEditorListener)listeners[i+1]).editingStopped(e);
+ }
+ }
+ }
+
+ public void editingCanceled(ChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==CellEditorListener.class) {
+ ((CellEditorListener)listeners[i+1]).editingCanceled(e);
+ }
+ }
+ }
+
+ /* ChangeListener Methods *****************************************/
+
+ public void stateChanged(ChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ChangeListener.class) {
+ ((ChangeListener)listeners[i+1]).stateChanged(e);
+ }
+ }
+ }
+
+ /* TableColumnModelListener Methods *******************************/
+
+ public void columnAdded(TableColumnModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnAdded(e);
+ }
+ }
+ }
+ public void columnMarginChanged(ChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnMarginChanged(e);
+ }
+ }
+ }
+ public void columnMoved(TableColumnModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnMoved(e);
+ }
+ }
+ }
+ public void columnRemoved(TableColumnModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnRemoved(e);
+ }
+ }
+ }
+ public void columnSelectionChanged(ListSelectionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableColumnModelListener.class) {
+ ((TableColumnModelListener)listeners[i+1]).columnSelectionChanged(e);
+ }
+ }
+ }
+
+ /* DocumentListener Methods **************************************/
+
+ public void changedUpdate(DocumentEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==DocumentListener.class) {
+ ((DocumentListener)listeners[i+1]).changedUpdate(e);
+ }
+ }
+ }
+ public void insertUpdate(DocumentEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==DocumentListener.class) {
+ ((DocumentListener)listeners[i+1]).insertUpdate(e);
+ }
+ }
+ }
+ public void removeUpdate(DocumentEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==DocumentListener.class) {
+ ((DocumentListener)listeners[i+1]).removeUpdate(e);
+ }
+ }
+ }
+
+ /* ListDataListener Methods *****************************************/
+
+ public void contentsChanged(ListDataEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ListDataListener.class) {
+ ((ListDataListener)listeners[i+1]).contentsChanged(e);
+ }
+ }
+ }
+ public void intervalAdded(ListDataEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ListDataListener.class) {
+ ((ListDataListener)listeners[i+1]).intervalAdded(e);
+ }
+ }
+ }
+ public void intervalRemoved(ListDataEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ListDataListener.class) {
+ ((ListDataListener)listeners[i+1]).intervalRemoved(e);
+ }
+ }
+ }
+
+ /* ListSelectionListener Methods ***********************************/
+
+ public void valueChanged(ListSelectionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==ListSelectionListener.class) {
+ ((ListSelectionListener)listeners[i+1]).valueChanged(e);
+ }
+ }
+ }
+
+ /* MenuListener Methods *****************************************/
+
+ public void menuCanceled(MenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==MenuListener.class) {
+ ((MenuListener)listeners[i+1]).menuCanceled(e);
+ }
+ }
+ }
+ public void menuDeselected(MenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==MenuListener.class) {
+ ((MenuListener)listeners[i+1]).menuDeselected(e);
+ }
+ }
+ }
+ public void menuSelected(MenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==MenuListener.class) {
+ ((MenuListener)listeners[i+1]).menuSelected(e);
+ }
+ }
+ }
+
+ /* PopupMenuListener Methods **************************************/
+
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PopupMenuListener.class) {
+ ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeVisible(e);
+ }
+ }
+ }
+
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PopupMenuListener.class) {
+ ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeInvisible(e);
+ }
+ }
+ }
+
+ public void popupMenuCanceled(PopupMenuEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PopupMenuListener.class) {
+ ((PopupMenuListener)listeners[i+1]).popupMenuCanceled(e);
+ }
+ }
+ }
+
+ /* TableModelListener Methods **************************************/
+
+ public void tableChanged(TableModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TableModelListener.class) {
+ ((TableModelListener)listeners[i+1]).tableChanged(e);
+ }
+ }
+ }
+
+ /* TreeExpansionListener Methods **********************************/
+
+ public void treeCollapsed(TreeExpansionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeExpansionListener.class) {
+ ((TreeExpansionListener)listeners[i+1]).treeCollapsed(e);
+ }
+ }
+ }
+ public void treeExpanded(TreeExpansionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeExpansionListener.class) {
+ ((TreeExpansionListener)listeners[i+1]).treeExpanded(e);
+ }
+ }
+ }
+
+ /* TreeModelListener Methods **********************************/
+
+ public void treeNodesChanged(TreeModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeModelListener.class) {
+ ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
+ }
+ }
+ }
+ public void treeNodesInserted(TreeModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeModelListener.class) {
+ ((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
+ }
+ }
+ }
+ public void treeNodesRemoved(TreeModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeModelListener.class) {
+ ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
+ }
+ }
+ }
+ public void treeStructureChanged(TreeModelEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeModelListener.class) {
+ ((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
+ }
+ }
+ }
+
+ /* TreeSelectionListener Methods ***********************************/
+
+ public void valueChanged(TreeSelectionEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==TreeSelectionListener.class) {
+ ((TreeSelectionListener)listeners[i+1]).valueChanged(e);
+ }
+ }
+ }
+
+ /* UndoableEditListener Methods **************************************/
+
+ public void undoableEditHappened(UndoableEditEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==UndoableEditListener.class) {
+ ((UndoableEditListener)listeners[i+1]).undoableEditHappened(e);
+ }
+ }
+ }
+
+ /* InternalFrame Methods **********************************/
+
+ public void internalFrameOpened(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameOpened(e);
+ }
+ }
+ }
+
+ public void internalFrameActivated(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameActivated(e);
+ }
+ }
+ }
+
+ public void internalFrameDeactivated(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameDeactivated(e);
+ }
+ }
+ }
+
+ public void internalFrameIconified(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameIconified(e);
+ }
+ }
+ }
+
+ public void internalFrameDeiconified(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameDeiconified(e);
+ }
+ }
+ }
+
+ public void internalFrameClosing(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameClosing(e);
+ }
+ }
+ }
+
+ public void internalFrameClosed(InternalFrameEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==InternalFrameListener.class) {
+ ((InternalFrameListener)listeners[i+1]).internalFrameClosed(e);
+ }
+ }
+ }
+
+ /* PropertyChangeListener Methods **********************************/
+
+ public void propertyChange(PropertyChangeEvent e) {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==PropertyChangeListener.class) {
+ ((PropertyChangeListener)listeners[i+1]).propertyChange(e);
+ }
+ }
+ // Re-add the monitor as a DocumentChangeListener if
+ // the document changed in the text component.
+ if (e.getSource() instanceof JTextComponent) {
+ Document c = ((JTextComponent)e.getSource()).getDocument();
+ if (c == null) {
+ return;
+ }
+ try {
+ removeDocumentMethod = c.getClass().getMethod(
+ "removeDocumentListener", documentListeners);
+ addDocumentMethod = c.getClass().getMethod(
+ "addDocumentListener", documentListeners);
+ try {
+ removeDocumentMethod.invoke(c, documentArgs);
+ addDocumentMethod.invoke(c, documentArgs);
+ } catch (java.lang.reflect.InvocationTargetException e2) {
+ System.out.println("Exception: " + e2.toString());
+ } catch (IllegalAccessException e2) {
+ System.out.println("Exception: " + e2.toString());
+ }
+ } catch (NoSuchMethodException e2) {
+ // System.out.println("Exception: " + e2.toString());
+ } catch (SecurityException e2) {
+ System.out.println("Exception: " + e2.toString());
+ }
+ }
+
+ }
+
+ /* VetoableChangeListener Methods **********************************/
+
+ public void vetoableChange(PropertyChangeEvent e)
+ throws PropertyVetoException {
+ Object[] listeners = SwingEventMonitor.listenerList.getListenerList();
+ for (int i = listeners.length-2; i>=0; i-=2) {
+ if (listeners[i]==VetoableChangeListener.class) {
+ ((VetoableChangeListener)listeners[i+1]).vetoableChange(e);
+ }
+ }
+ }
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowListener.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowListener.java
new file mode 100644
index 00000000000..94d03307a7a
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowListener.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.awt.*;
+import java.util.*;
+import javax.accessibility.*;
+
+/**
+ * The {@code TopLevelWindowListener} interface is used by the {@link EventQueueMonitor}
+ * class to notify an interested party when a top level window is created
+ * or destroyed in the Java Virtual Machine. Classes wishing to express
+ * an interest in top level window events should implement this interface
+ * and register themselves with the {@code EventQueueMonitor} by calling the
+ * {@link EventQueueMonitor#addTopLevelWindowListener EventQueueMonitor.addTopLevelWindowListener}
+ * class method.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ * @see EventQueueMonitor#removeTopLevelWindowListener
+ *
+ */
+@jdk.Exported
+public interface TopLevelWindowListener extends EventListener {
+
+ /**
+ * Invoked when a new top level window has been created.
+ *
+ * @param w the Window that was created
+ */
+ public void topLevelWindowCreated(Window w);
+
+ /**
+ * Invoked when a top level window has been destroyed.
+ *
+ * @param w the Window that was destroyed
+ */
+ public void topLevelWindowDestroyed(Window w);
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowMulticaster.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowMulticaster.java
new file mode 100644
index 00000000000..31ca38020ea
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/TopLevelWindowMulticaster.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util;
+
+import java.awt.*;
+import java.util.EventListener;
+import javax.accessibility.*;
+
+
+/**
+ * The TopLevelWindowMulticaster class is used to maintain a list of
+ * TopLevelWindowListener classes. It is intended to be used primarily
+ * for internal support in the EventQueueMonitor class, and is not intended
+ * to be used by classes outside the Java Accessibility Utility package.
+ *
+ * @see EventQueueMonitor
+ * @see EventQueueMonitor#addTopLevelWindowListener
+ * @see EventQueueMonitor#removeTopLevelWindowListener
+ *
+ */
+class TopLevelWindowMulticaster
+ extends AWTEventMulticaster implements TopLevelWindowListener
+{
+ protected TopLevelWindowMulticaster(EventListener a, EventListener b) {
+ super(a, b);
+ }
+
+ public void topLevelWindowCreated(Window w) {
+ ((TopLevelWindowListener)a).topLevelWindowCreated(w);
+ ((TopLevelWindowListener)b).topLevelWindowCreated(w);
+ }
+
+ public void topLevelWindowDestroyed(Window w) {
+ ((TopLevelWindowListener)a).topLevelWindowDestroyed(w);
+ ((TopLevelWindowListener)b).topLevelWindowDestroyed(w);
+ }
+
+ public static TopLevelWindowListener add(TopLevelWindowListener a, TopLevelWindowListener b) {
+ return (TopLevelWindowListener)addInternal(a, b);
+ }
+
+ public static TopLevelWindowListener remove(TopLevelWindowListener l, TopLevelWindowListener oldl) {
+ return (TopLevelWindowListener)removeInternal(l, oldl);
+ }
+
+ protected static EventListener addInternal(EventListener a, EventListener b) {
+ if (a == null) return b;
+ if (b == null) return a;
+ return new TopLevelWindowMulticaster(a, b);
+ }
+
+ protected static EventListener removeInternal(EventListener l, EventListener oldl) {
+ if (l == oldl || l == null) {
+ return null;
+ } else if (l instanceof TopLevelWindowMulticaster) {
+ return ((TopLevelWindowMulticaster)l).remove(oldl);
+ } else {
+ return l; // it's not here
+ }
+ }
+
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java
new file mode 100644
index 00000000000..2112bd2ea3b
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java
@@ -0,0 +1,744 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package com.sun.java.accessibility.util;
+
+import java.lang.*;
+import java.beans.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+// Do not import Swing classes. This module is intended to work
+// with both Swing and AWT.
+// import javax.swing.*;
+import javax.accessibility.*;
+
+/**
+ *
The {@code Translator} class provides a translation to interface
+ * {@link javax.accessibility.Accessible Accessible}
+ * for objects that do not implement interface {@code Accessible}. Assistive
+ * technologies can use the {@link #getAccessible getAccessible} class method of
+ * {@code Translator} to obtain an object that implements interface {@code Accessible}.
+ * If the object passed in already implements interface {@code Accessible},
+ * {@code getAccessible} merely returns the object.
+ *
+ *
An example of how an assistive technology might use the {@code Translator}
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
Note: This implementation is missing many things and is not a recommended way
+ * to implement accessibility features for a toolkit. Instead of relying upon this
+ * code, a toolkit's components should implement interface {@code Accessible} directly.
+ */
+@jdk.Exported
+public class Translator extends AccessibleContext
+ implements Accessible, AccessibleComponent {
+
+ /** The source object needing translating. */
+ protected Object source;
+
+ /**
+ * Find a translator for this class. If one doesn't exist for this
+ * class explicitly, try its superclass and so on.
+ *
+ * @param c a Class
+ * @return the {@code Translator} Class for the Class passed in
+ */
+ protected static Class> getTranslatorClass(Class> c) {
+ Class> t = null;
+ if (c == null) {
+ return null;
+ }
+ try {
+ t = Class.forName("com.sun.java.accessibility.util."
+ + c.getName()
+ + "Translator");
+ return t;
+ } catch (Exception e) {
+ return getTranslatorClass(c.getSuperclass());
+ }
+ }
+
+ /**
+ * Obtain an object that implements interface {@code Accessible}. If the object
+ * passed in already implements interface {@code Accessible}, {@code getAccessible}
+ * merely returns the object.
+ *
+ * @param o an Object; if a null is passed in a null is returned
+ * @return an {@code Object}, possibly the {@code Object} passed in, that
+ * implements the {@code Accessible} interface for the {@code Object}
+ * which was passed in
+ */
+ public static Accessible getAccessible(Object o) {
+ Accessible a = null;
+
+ if (o == null) {
+ return null;
+ }
+ if (o instanceof Accessible) {
+ a = (Accessible)o;
+ } else {
+ Class> translatorClass = getTranslatorClass(o.getClass());
+ if (translatorClass != null) {
+ try {
+ Translator t = (Translator)translatorClass.newInstance();
+ t.setSource(o);
+ a = t;
+ } catch (Exception e) {
+ }
+ }
+ }
+ if (a == null) {
+ a = new Translator(o);
+ }
+ return a;
+ }
+
+ /**
+ * Create a new {@code Translator}. You must call the {@link #setSource setSource}
+ * method to set the object to be translated after calling this constructor.
+ */
+ public Translator() {
+ }
+
+ /**
+ * Create a new {@code Translator} with the source object o.
+ *
+ * @param o the Component that does not implement interface
+ * {@link javax.accessibility.Accessible Accessible}
+ */
+ public Translator(Object o) {
+ source = o;
+ }
+
+ /**
+ * Get the source {@code Object} of the {@code Translator}.
+ *
+ * @return the source {@code Object} of the {@code Translator}
+ */
+ public Object getSource() {
+ return source;
+ }
+
+ /**
+ * Set the source object of the {@code Translator}.
+ *
+ * @param o the Component that does not implement interface Accessible
+ */
+ public void setSource(Object o) {
+ source = o;
+ }
+
+ /**
+ * Returns true if this object is the same as the one passed in.
+ *
+ * @param o the {@code Object} to check against
+ * @return true if this is the same object
+ */
+ public boolean equals(Object o) {
+ if (o instanceof Translator) {
+ return java.util.Objects.equals(source, o);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Return hashcode.
+ *
+ * @return hashcode
+ */
+ public int hashCode() {
+ return java.util.Objects.hashCode(source);
+ }
+
+
+// Accessible methods
+
+ /**
+ * Returns this object.
+ */
+ public AccessibleContext getAccessibleContext() {
+ return this;
+ }
+
+// AccessibleContext methods
+
+ /**
+ * Get the accessible name of this object.
+ *
+ * @return the localized name of the object; can be null if this object
+ * does not have a name
+ */
+ public String getAccessibleName() {
+ if (source instanceof MenuItem) {
+ return ((MenuItem) source).getLabel();
+ } else if (source instanceof Component) {
+ return ((Component) source).getName();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the name of this object.
+ */
+ public void setAccessibleName(String s) {
+ if (source instanceof MenuItem) {
+ ((MenuItem) source).setLabel(s);
+ } else if (source instanceof Component) {
+ ((Component) source).setName(s);
+ }
+ }
+
+ /**
+ * Get the accessible description of this object.
+ *
+ * @return the description of the object; can be null if this object does
+ * not have a description
+ */
+ public String getAccessibleDescription() {
+ return null;
+ }
+
+ /**
+ * Set the accessible description of this object.
+ *
+ * @param s the new localized description of the object
+ */
+ public void setAccessibleDescription(String s) {
+ }
+
+ /**
+ * Get the role of this object.
+ *
+ * @return an instance of AccessibleRole describing the role of the object
+ */
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.UNKNOWN;
+ }
+
+
+ /**
+ * Get the state of this object, given an already populated state.
+ * This method is intended for use by subclasses so they don't have
+ * to check for everything.
+ *
+ * @return an instance of {@code AccessibleStateSet}
+ * containing the current state of the object
+ */
+ public AccessibleStateSet getAccessibleStateSet() {
+ AccessibleStateSet states = new AccessibleStateSet();
+ if (source instanceof Component) {
+ Component c = (Component) source;
+ for (Container p = c.getParent(); p != null; p = p.getParent()) {
+ if (p instanceof Window) {
+ if (((Window)p).getFocusOwner() == c) {
+ states.add(AccessibleState.FOCUSED);
+ }
+ }
+ }
+ }
+ if (isEnabled()) {
+ states.add(AccessibleState.ENABLED);
+ }
+ if (isFocusTraversable()) {
+ states.add(AccessibleState.FOCUSABLE);
+ }
+ if (source instanceof MenuItem) {
+ states.add(AccessibleState.FOCUSABLE);
+ }
+ return states;
+ }
+
+ /**
+ * Get the accessible parent of this object.
+ *
+ * @return the accessible parent of this object; can be null if this
+ * object does not have an accessible parent
+ */
+ public Accessible getAccessibleParent() {
+ if (accessibleParent != null) {
+ return accessibleParent;
+ } else if (source instanceof Component) {
+ return getAccessible(((Component) source).getParent());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the index of this object in its accessible parent.
+ *
+ * @return -1 of this object does not have an accessible parent; otherwise,
+ * the index of the child in its accessible parent
+ */
+ public int getAccessibleIndexInParent() {
+ if (source instanceof Component) {
+ Container parent = ((Component) source).getParent();
+ if (parent != null) {
+ Component ca[] = parent.getComponents();
+ for (int i = 0; i < ca.length; i++) {
+ if (source.equals(ca[i])) {
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the number of accessible children in the object.
+ *
+ * @return the number of accessible children in the object
+ */
+ public int getAccessibleChildrenCount() {
+ if (source instanceof Container) {
+ Component[] children = ((Container) source).getComponents();
+ int count = 0;
+ for (int i = 0; i < children.length; i++) {
+ Accessible a = getAccessible(children[i]);
+ if (a != null) {
+ count++;
+ }
+ }
+ return count;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Return the nth accessible child of the object.
+ *
+ * @param i zero-based index of child
+ * @return the nth accessible child of the object
+ */
+ public Accessible getAccessibleChild(int i) {
+ if (source instanceof Container) {
+ Component[] children = ((Container) source).getComponents();
+ int count = 0;
+
+ for (int j = 0; j < children.length; j++) {
+ Accessible a = getAccessible(children[j]);
+ if (a != null) {
+ if (count == i) {
+ AccessibleContext ac = a.getAccessibleContext();
+ if (ac != null) {
+ ac.setAccessibleParent(this);
+ }
+ return a;
+ } else {
+ count++;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets the {@code Locale} of the component. If the component does not have a
+ * locale, the locale of its parent is returned.
+ *
+ * @return the {@code Locale} of the object
+ */
+ public Locale getLocale() throws IllegalComponentStateException {
+ if (source instanceof Component) {
+ return ((Component) source).getLocale();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Add a {@code PropertyChangeListener} to the listener list. The listener
+ * is registered for all properties.
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l) {
+ }
+
+ /**
+ * Remove the {@code PropertyChangeListener} from the listener list.
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l) {
+ }
+
+// AccessibleComponent methods
+
+ /**
+ * Get the background {@code Color} of this object.
+ *
+ * @return if supported, the background {@code Color} of the object;
+ * otherwise, null
+ *
+ */
+ public Color getBackground() {
+ if (source instanceof Component) { // MenuComponent doesn't do background
+ return ((Component) source).getBackground();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the background {@code Color} of this object.
+ *
+ * @param c the new {@code Color} for the background
+ */
+ public void setBackground(Color c) {
+ if (source instanceof Component) { // MenuComponent doesn't do background
+ ((Component) source).setBackground(c);
+ }
+ }
+
+ /**
+ * Get the foreground {@code Color} of this object.
+ *
+ * @return if supported, the foreground {@code Color} of the object; otherwise, null
+ */
+ public Color getForeground() {
+ if (source instanceof Component) { // MenuComponent doesn't do foreground
+ return ((Component) source).getForeground();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the foreground {@code Color} of this object.
+ *
+ * @param c the new {@code Color} for the foreground
+ */
+ public void setForeground(Color c) {
+ if (source instanceof Component) { // MenuComponent doesn't do foreground
+ ((Component) source).setForeground(c);
+ }
+ }
+
+ /**
+ * Get the {@code Cursor} of this object.
+ *
+ * @return if supported, the Cursor of the object; otherwise, null
+ */
+ public Cursor getCursor() {
+ if (source instanceof Component) { // MenuComponent doesn't do cursor
+ return ((Component) source).getCursor();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the {@code Cursor} of this object.
+ * @param c the new {@code Cursor} for the object
+ */
+ public void setCursor(Cursor c) {
+ if (source instanceof Component) { // MenuComponent doesn't do cursor
+ ((Component) source).setCursor(c);
+ }
+ }
+
+ /**
+ * Get the {@code Font} of this object.
+ *
+ * @return if supported, the {@code Font} for the object; otherwise, null
+ */
+ public Font getFont() {
+ if (source instanceof Component) {
+ return ((Component) source).getFont();
+ } else if (source instanceof MenuComponent) {
+ return ((MenuComponent) source).getFont();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the {@code Font} of this object.
+ *
+ * @param f the new {@code Font} for the object
+ */
+ public void setFont(Font f) {
+ if (source instanceof Component) {
+ ((Component) source).setFont(f);
+ } else if (source instanceof MenuComponent) {
+ ((MenuComponent) source).setFont(f);
+ }
+ }
+
+ /**
+ * Get the {@code FontMetrics} of this object.
+ *
+ * @param f the {@code Font}
+ * @return if supported, the {@code FontMetrics} the object; otherwise, null
+ * @see #getFont
+ */
+ public FontMetrics getFontMetrics(Font f) {
+ if (source instanceof Component) {
+ return ((Component) source).getFontMetrics(f);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Determine if the object is enabled.
+ *
+ * @return true if object is enabled; otherwise, false
+ */
+ public boolean isEnabled() {
+ if (source instanceof Component) {
+ return ((Component) source).isEnabled();
+ } else if (source instanceof MenuItem) {
+ return ((MenuItem) source).isEnabled();
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Set the enabled state of the object.
+ *
+ * @param b if true, enables this object; otherwise, disables it
+ */
+ public void setEnabled(boolean b) {
+ if (source instanceof Component) {
+ ((Component) source).setEnabled(b);
+ } else if (source instanceof MenuItem) {
+ ((MenuItem) source).setEnabled(b);
+ }
+ }
+
+ /**
+ * Determine if the object is visible.
+ *
+ * @return true if object is visible; otherwise, false
+ */
+ public boolean isVisible() {
+ if (source instanceof Component) {
+ return ((Component) source).isVisible();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Set the visible state of the object.
+ *
+ * @param b if true, shows this object; otherwise, hides it
+ */
+ public void setVisible(boolean b) {
+ if (source instanceof Component) {
+ ((Component) source).setVisible(b);
+ }
+ }
+
+ /**
+ * Determine if the object is showing. This is determined by checking
+ * the visibility of the object and ancestors of the object.
+ *
+ * @return true if object is showing; otherwise, false
+ */
+ public boolean isShowing() {
+ if (source instanceof Component) {
+ return ((Component) source).isShowing();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Checks whether the specified {@code Point} is within this
+ * object's bounds, where the {@code Point} is relative to the coordinate
+ * system of the object.
+ *
+ * @param p the {@code Point} relative to the coordinate system of the object
+ * @return true if object contains {@code Point}; otherwise false
+ */
+ public boolean contains(Point p) {
+ if (source instanceof Component) {
+ return ((Component) source).contains(p);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the location of the object on the screen.
+ *
+ * @return location of object on screen; can be null if this object
+ * is not on the screen
+ */
+ public Point getLocationOnScreen() {
+ if (source instanceof Component) {
+ return ((Component) source).getLocationOnScreen();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the location of the object relative to parent.
+ *
+ * @return location of object relative to parent; can be null if
+ * this object or its parent are not on the screen
+ */
+ public Point getLocation() {
+ if (source instanceof Component) {
+ return ((Component) source).getLocation();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the location of the object relative to parent.
+ */
+ public void setLocation(Point p) {
+ if (source instanceof Component) {
+ ((Component) source).setLocation(p);
+ }
+ }
+
+ /**
+ * Returns the current bounds of this object.
+ *
+ * @return current bounds of object; can be null if this object
+ * is not on the screen
+ */
+ public Rectangle getBounds() {
+ if (source instanceof Component) {
+ return ((Component) source).getBounds();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the current bounds of this object.
+ */
+ public void setBounds(Rectangle r) {
+ if (source instanceof Component) {
+ ((Component) source).setBounds(r);
+ }
+ }
+
+ /**
+ * Returns the current size of this object.
+ *
+ * @return current size of object; can be null if this object is
+ * not on the screen
+ */
+ public Dimension getSize() {
+ if (source instanceof Component) {
+ return ((Component) source).getSize();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the current size of this object.
+ */
+ public void setSize(Dimension d) {
+ if (source instanceof Component) {
+ ((Component) source).setSize(d);
+ }
+ }
+
+ /**
+ * Returns the accessible child contained at the local coordinate
+ * Point, if one exists.
+ *
+ * @return the Accessible at the specified location, if it exists
+ */
+ public Accessible getAccessibleAt(Point p) {
+ if (source instanceof Component) {
+ Component c = ((Component) source).getComponentAt(p);
+ if (c != null) {
+ return (getAccessible(c));
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns whether this object can accept focus or not.
+ *
+ * @return true if object can accept focus; otherwise false
+ */
+ @SuppressWarnings("deprecation")
+ public boolean isFocusTraversable() {
+ if (source instanceof Component) {
+ return ((Component) source).isFocusTraversable();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Requests focus for this object.
+ */
+ public void requestFocus() {
+ if (source instanceof Component) {
+ ((Component) source).requestFocus();
+ }
+ }
+
+ /**
+ * Adds the specified {@code FocusListener} to receive focus events from
+ * this component.
+ *
+ * @param l the focus listener
+ */
+ public synchronized void addFocusListener(FocusListener l) {
+ if (source instanceof Component) {
+ ((Component) source).addFocusListener(l);
+ }
+ }
+
+ /**
+ * Removes the specified focus listener so it no longer receives focus
+ * events from this component.
+ *
+ * @param l the focus listener; this method performs no function, nor does it
+ * throw an exception if the listener specified was not previously added
+ * to this component; if listener is null, no exception is thrown and no
+ * action is performed.
+ */
+ public synchronized void removeFocusListener(FocusListener l) {
+ if (source instanceof Component) {
+ ((Component) source).removeFocusListener(l);
+ }
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ButtonTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ButtonTranslator.java
new file mode 100644
index 00000000000..d775e6e475e
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ButtonTranslator.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the Button class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for Button.
+ *
+ */
+public class ButtonTranslator extends Translator {
+
+ /**
+ * Get the name of this object.
+ * @return the name of the object -- can be null if this object does
+ * not have a name
+ */
+ public String getAccessibleName() {
+ return ((Button) source).getLabel();
+ }
+
+ /**
+ * Set the name of this object.
+ */
+ public void setAccessibleName(String s) {
+ ((Button) source).setLabel(s);
+ }
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.PUSH_BUTTON;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/CheckboxTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/CheckboxTranslator.java
new file mode 100644
index 00000000000..2f131e2c733
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/CheckboxTranslator.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the Checkbox class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for Checkbox.
+ *
+ */
+public class CheckboxTranslator extends Translator {
+
+ /**
+ * Get the state of this object.
+ * @return an instance of AccessibleState containing the current state of the object
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet() {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (((Checkbox) source).getState()) {
+ states.add(AccessibleState.CHECKED);
+ }
+ return states;
+ }
+
+ /**
+ * Get the name of this object.
+ * @return the name of the object -- can be null if this object does
+ * not have a name
+ */
+ public String getAccessibleName() {
+ return ((Checkbox) source).getLabel();
+ }
+
+ /**
+ * Set the name of this object.
+ */
+ public void setAccessibleName(String s) {
+ ((Checkbox) source).setLabel(s);
+ }
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.CHECK_BOX;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/LabelTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/LabelTranslator.java
new file mode 100644
index 00000000000..33a27897c78
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/LabelTranslator.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the Label class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for Label.
+ *
+ */
+public class LabelTranslator extends Translator {
+
+ public String getAccessibleName() {
+ return ((Label) source).getText();
+ }
+
+ /**
+ * Set the name of this object.
+ */
+ public void setAccessibleName(String s) {
+ ((Label) source).setText(s);
+ }
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.LABEL;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ListTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ListTranslator.java
new file mode 100644
index 00000000000..de1c469928e
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/ListTranslator.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the List class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for List.
+ *
+ */
+public class ListTranslator extends Translator {
+
+ /**
+ * Get the state of this object.
+ * @return an instance of AccessibleState containing the current state of the object
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet() {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ if (((java.awt.List) source).isMultipleMode()) {
+ states.add(AccessibleState.MULTISELECTABLE);
+ }
+ if (((java.awt.List) source).getSelectedItems().length > 0) {
+ states.add(AccessibleState.SELECTED);
+ }
+ return states;
+ }
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.LIST;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/TextComponentTranslator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/TextComponentTranslator.java
new file mode 100644
index 00000000000..3ac3fabb708
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/java/awt/TextComponentTranslator.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility.util.java.awt;
+
+import java.lang.*;
+import java.util.*;
+import java.awt.*;
+import java.awt.image.*;
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+
+/**
+ *
The Translator class provides a translation to interface Accessible
+ * for objects that do not implement interface Accessible. Assistive
+ * technologies can use the 'getAccessible' class method of Translator to
+ * obtain an object that implements interface Accessible. If the object
+ * passed in already implements interface Accessible, getAccessible merely
+ * returns the object.
+ *
+ *
An example of how an assistive technology might use the Translator
+ * class is as follows:
+ *
+ *
+ * Accessible accessible = Translator.getAccessible(someObj);
+ * // obtain information from the 'accessible' object.
+ *
+ *
+ *
This class extends the Translator class to provide specific support
+ * for the TextComponent class. Translator.getAccessible() will automatically
+ * load this class when an assistive technology asks for an accessible
+ * translator for TextComponent.
+ *
+ */
+public class TextComponentTranslator extends Translator {
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.TEXT;
+ }
+}
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/package-info.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/package-info.java
new file mode 100644
index 00000000000..f3b0a62dd36
--- /dev/null
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/package-info.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Provides a collection of interfaces and classes that compose the Java Accessibility
+ * Utilities. The classes are used by Assistive Technologies, such as the screen
+ * readers which are used by those who are blind, and help provide access to GUI
+ * toolkits that implement the Java Accessibility API. An overview of the important
+ * classes follows.
+ *
+ *
The class {@code AccessibilityEventMonitor} implements a PropertyChange
+ * listener on every UI object that implements interface {@code Accessible} in the Java
+ * Virtual Machine.
+ *
+ *
The class {@code AWTEventMonitor} implements a suite of listeners that are
+ * conditionally installed on every AWT component instance in the Java Virtual Machine.
+ *
+ *
The class {@code EventQueueMonitor} provides key core functionality for
+ * Assistive Technologies (and other system-level technologies that need some of
+ * the same things that Assistive Technology needs).
+ *
+ *
The class {@code GUIInitializedMulticaster} is used to maintain a list of
+ * {@code GUIInitializedListener} classes which are used by the {@code EventQueueMonitor}
+ * class to notify an interested party when the GUI subsystem has been initialized.
+ * Note that this class is intended to be used primarily for internal support in
+ * the {@code EventQueueMonitor} class, and is not intended to be used by classes
+ * outside the Java Accessibility Utility package.
+ *
+ *
The class {@code SwingEventMonitor} extends {@code AWTEventMonitor} by adding
+ * a suite of listeners conditionally installed on every Swing component instance
+ * in the Java Virtual Machine.
+ *
+ *
The class {@code TopLevelWindowMulticaster} is used to maintain a list of
+ * {@code TopLevelWindowListener} classes which are used by the {@code EventQueueMonitor}
+ * class to notify an interested party when a top level window is created or destroyed
+ * in the Java Virtual Machine Note that this class is intended to be used primarily
+ * for internal support in the {@code EventQueueMonitor} class, and is not intended
+ * to be used by classes outside the Java Accessibility Utility package.
+ *
+ *
The class {@code Translator} provides a translation to interface {@code Accessible}
+ * for objects that do not implement interface {@code Accessible}.
+ *
+ * @since JDK1.7
+ */
+package com.sun.java.accessibility.util;
diff --git a/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/AccessBridge.java b/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/AccessBridge.java
new file mode 100644
index 00000000000..5c47d382324
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/AccessBridge.java
@@ -0,0 +1,7170 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.java.accessibility;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.lang.*;
+import java.lang.reflect.*;
+
+import java.beans.*;
+import javax.swing.*;
+import javax.swing.event.*;
+import javax.swing.text.*;
+import javax.swing.tree.*;
+import javax.swing.table.*;
+import javax.swing.plaf.TreeUI;
+
+import javax.accessibility.*;
+import com.sun.java.accessibility.util.*;
+import sun.awt.AWTAccessor;
+import sun.awt.AppContext;
+import sun.awt.SunToolkit;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+
+/*
+ * Note: This class has to be public. It's loaded from the VM like this:
+ * Class.forName(atName).newInstance();
+ */
+@jdk.Exported(false)
+final public class AccessBridge {
+
+ private static AccessBridge theAccessBridge;
+ private ObjectReferences references;
+ private EventHandler eventHandler;
+
+ // Maps AccessibleRoles strings to AccessibleRoles.
+ private ConcurrentHashMap accessibleRoleMap = new ConcurrentHashMap<>();
+
+ /**
+ If the object's role is in the following array getVirtualAccessibleName
+ will use the extended search algorithm.
+ */
+ private ArrayList extendedVirtualNameSearchRoles = new ArrayList<>();
+ /**
+ If the role of the object's parent is in the following array
+ getVirtualAccessibleName will NOT use the extended search
+ algorithm even if the object's role is in the
+ extendedVirtualNameSearchRoles array.
+ */
+ private ArrayList noExtendedVirtualNameSearchParentRoles = new ArrayList<>();
+
+ private static native boolean isSysWow();
+
+
+ /**
+ * Load DLLs
+ */
+ static {
+ // Load the appropriate DLLs
+ boolean is32on64 = false;
+ if (System.getProperty("os.arch").equals("x86")) {
+ // 32 bit JRE
+ // Load jabsysinfo.dll so can determine Win bitness
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Void run() {
+ System.loadLibrary("jabsysinfo");
+ return null;
+ }
+ }, null, new java.lang.RuntimePermission("loadLibrary.jabsysinfo")
+ );
+ if (isSysWow()) {
+ // 32 bit JRE on 64 bit OS
+ is32on64 = true;
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Void run() {
+ System.loadLibrary("javaaccessbridge-32");
+ return null;
+ }
+ }, null, new java.lang.RuntimePermission("loadLibrary.javaaccessbridge-32")
+ );
+ }
+ }
+ if (!is32on64) {
+ // 32 bit JRE on 32 bit OS or 64 bit JRE on 64 bit OS
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Void run() {
+ System.loadLibrary("javaaccessbridge");
+ return null;
+ }
+ }, null, new java.lang.RuntimePermission("loadLibrary.javaaccessbridge")
+ );
+ }
+ }
+
+ /**
+ * AccessBridge constructor
+ *
+ * Note: This constructor has to be public. It's called from the VM like this:
+ * Class.forName(atName).newInstance();
+ */
+ public AccessBridge() {
+ theAccessBridge = this;
+ references = new ObjectReferences();
+
+ // initialize shutdown hook
+ Runtime runTime = Runtime.getRuntime();
+ shutdownHook hook = new shutdownHook();
+ runTime.addShutdownHook(new Thread(hook));
+
+ // initialize AccessibleRole map
+ initAccessibleRoleMap();
+
+ // determine which version of the JDK is running
+ String version = getJavaVersionProperty();
+ debugString("JDK version = "+version);
+
+ // initialize the methods that map HWNDs and Java top-level
+ // windows
+ initHWNDcalls();
+
+ // is this a JVM we can use?
+ // install JDK 1.2 and later Swing ToolKit listener
+ EventQueueMonitor.isGUIInitialized();
+
+ // start the Java event handler
+ eventHandler = new EventHandler(this);
+
+ // register for menu selection events
+ MenuSelectionManager.defaultManager().addChangeListener(eventHandler);
+
+ // register as a NativeWindowHandler
+ addNativeWindowHandler(new DefaultNativeWindowHandler());
+
+ // start in a new thread
+ Thread abthread = new Thread(new dllRunner());
+ abthread.setDaemon(true);
+ abthread.start();
+ debugString("AccessBridge started");
+ }
+
+ /*
+ * adaptor to run the AccessBridge DLL
+ */
+ private class dllRunner implements Runnable {
+ public void run() {
+ runDLL();
+ }
+ }
+
+ /*
+ * shutdown hook
+ */
+ private class shutdownHook implements Runnable {
+
+ public void run() {
+ debugString("***** shutdownHook: shutting down...");
+ javaShutdown();
+ }
+ }
+
+
+ /*
+ * Initialize the hashtable that maps Strings to AccessibleRoles.
+ */
+ private void initAccessibleRoleMap() {
+ /*
+ * Initialize the AccessibleRoles map. This code uses methods in
+ * java.lang.reflect.* to build the map.
+ */
+ try {
+ Class> clAccessibleRole = Class.forName ("javax.accessibility.AccessibleRole");
+ if (null != clAccessibleRole) {
+ AccessibleRole roleUnknown = AccessibleRole.UNKNOWN;
+ Field [] fields = clAccessibleRole.getFields ();
+ int i = 0;
+ for (i = 0; i < fields.length; i ++) {
+ Field f = fields [i];
+ if (javax.accessibility.AccessibleRole.class == f.getType ()) {
+ AccessibleRole nextRole = (AccessibleRole) (f.get (roleUnknown));
+ String nextRoleString = nextRole.toDisplayString (Locale.US);
+ accessibleRoleMap.put (nextRoleString, nextRole);
+ }
+ }
+ }
+ } catch (Exception e) {}
+
+ /*
+ Build the extendedVirtualNameSearchRoles array list. I chose this method
+ because some of the Accessible Roles that need to be added to it are not
+ available in all versions of the J2SE that we want to support.
+ */
+ extendedVirtualNameSearchRoles.add (AccessibleRole.COMBO_BOX);
+ try {
+ /*
+ Added in J2SE 1.4
+ */
+ extendedVirtualNameSearchRoles.add (AccessibleRole.DATE_EDITOR);
+ } catch (NoSuchFieldError e) {}
+ extendedVirtualNameSearchRoles.add (AccessibleRole.LIST);
+ extendedVirtualNameSearchRoles.add (AccessibleRole.PASSWORD_TEXT);
+ extendedVirtualNameSearchRoles.add (AccessibleRole.SLIDER);
+ try {
+ /*
+ Added in J2SE 1.3
+ */
+ extendedVirtualNameSearchRoles.add (AccessibleRole.SPIN_BOX);
+ } catch (NoSuchFieldError e) {}
+ extendedVirtualNameSearchRoles.add (AccessibleRole.TABLE);
+ extendedVirtualNameSearchRoles.add (AccessibleRole.TEXT);
+ extendedVirtualNameSearchRoles.add (AccessibleRole.UNKNOWN);
+
+ noExtendedVirtualNameSearchParentRoles.add (AccessibleRole.TABLE);
+ noExtendedVirtualNameSearchParentRoles.add (AccessibleRole.TOOL_BAR);
+ }
+
+ /**
+ * start the AccessBridge DLL running in its own thread
+ */
+ private native void runDLL();
+
+ /**
+ * debugging output (goes to OutputDebugStr())
+ */
+ private native void sendDebugString(String debugStr);
+
+ /**
+ * debugging output (goes to OutputDebugStr())
+ */
+ private void debugString(String debugStr) {
+ sendDebugString(debugStr);
+ }
+
+ /* ===== utility methods ===== */
+
+ /**
+ * decrement the reference to the object (called by native code)
+ */
+ private void decrementReference(Object o) {
+ references.decrement(o);
+ }
+
+ /**
+ * get the java.version property from the JVM
+ */
+ private String getJavaVersionProperty() {
+ String s = System.getProperty("java.version");
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ return null;
+ }
+
+ /* ===== HWND/Java window mapping methods ===== */
+
+ // Java toolkit methods for mapping HWNDs to Java components
+ private Method javaGetComponentFromNativeWindowHandleMethod;
+ private Method javaGetNativeWindowHandleFromComponentMethod;
+
+ // native jawt methods for mapping HWNDs to Java components
+ private native int jawtGetNativeWindowHandleFromComponent(Component comp);
+
+ private native Component jawtGetComponentFromNativeWindowHandle(int handle);
+
+ Toolkit toolkit;
+
+ /**
+ * map an HWND to an AWT Component
+ */
+ private void initHWNDcalls() {
+ Class> integerParemter[] = new Class>[1];
+ integerParemter[0] = Integer.TYPE;
+ Class> componentParemter[] = new Class>[1];
+ try {
+ componentParemter[0] = Class.forName("java.awt.Component");
+ } catch (ClassNotFoundException e) {
+ debugString("Exception: " + e.toString());
+ }
+ toolkit = Toolkit.getDefaultToolkit();
+ return;
+ }
+
+ // native window handler interface
+ private interface NativeWindowHandler {
+ public Accessible getAccessibleFromNativeWindowHandle(int nativeHandle);
+ }
+
+ // hash table of native window handle to AccessibleContext mappings
+ static private ConcurrentHashMap windowHandleToContextMap = new ConcurrentHashMap<>();
+
+ // hash table of AccessibleContext to native window handle mappings
+ static private ConcurrentHashMap contextToWindowHandleMap = new ConcurrentHashMap<>();
+
+ /*
+ * adds a virtual window handler to our hash tables
+ */
+ static private void registerVirtualFrame(final Accessible a,
+ Integer nativeWindowHandle ) {
+ if (a != null) {
+ AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, a);
+ windowHandleToContextMap.put(nativeWindowHandle, ac);
+ contextToWindowHandleMap.put(ac, nativeWindowHandle);
+ }
+ }
+
+ /*
+ * removes a virtual window handler to our hash tables
+ */
+ static private void revokeVirtualFrame(final Accessible a,
+ Integer nativeWindowHandle ) {
+ AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, a);
+ windowHandleToContextMap.remove(nativeWindowHandle);
+ contextToWindowHandleMap.remove(ac);
+ }
+
+ // vector of native window handlers
+ private static Vector nativeWindowHandlers = new Vector<>();
+
+ /*
+ * adds a native window handler to our list
+ */
+ private static void addNativeWindowHandler(NativeWindowHandler handler) {
+ if (handler == null) {
+ throw new IllegalArgumentException();
+ }
+ nativeWindowHandlers.addElement(handler);
+ }
+
+ /*
+ * removes a native window handler to our list
+ */
+ private static boolean removeNativeWindowHandler(NativeWindowHandler handler) {
+ if (handler == null) {
+ throw new IllegalArgumentException();
+ }
+ return nativeWindowHandlers.removeElement(handler);
+ }
+
+ /**
+ * verifies that a native window handle is a Java window
+ */
+ private boolean isJavaWindow(int nativeHandle) {
+ AccessibleContext ac = getContextFromNativeWindowHandle(nativeHandle);
+ if (ac != null) {
+ saveContextToWindowHandleMapping(ac, nativeHandle);
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * saves the mapping between an AccessibleContext and a window handle
+ */
+ private void saveContextToWindowHandleMapping(AccessibleContext ac,
+ int nativeHandle) {
+ debugString("saveContextToWindowHandleMapping...");
+ if (ac == null) {
+ return;
+ }
+ if (! contextToWindowHandleMap.containsKey(ac)) {
+ debugString("saveContextToWindowHandleMapping: ac = "+ac+"; handle = "+nativeHandle);
+ contextToWindowHandleMap.put(ac, nativeHandle);
+ }
+ }
+
+ /**
+ * maps a native window handle to an Accessible Context
+ */
+ private AccessibleContext getContextFromNativeWindowHandle(int nativeHandle) {
+ // First, look for the Accessible in our hash table of
+ // virtual window handles.
+ AccessibleContext ac = windowHandleToContextMap.get(nativeHandle);
+ if(ac!=null) {
+ saveContextToWindowHandleMapping(ac, nativeHandle);
+ return ac;
+ }
+
+ // Next, look for the native window handle in our vector
+ // of native window handles.
+ int numHandlers = nativeWindowHandlers.size();
+ for (int i = 0; i < numHandlers; i++) {
+ NativeWindowHandler nextHandler = nativeWindowHandlers.elementAt(i);
+ final Accessible a = nextHandler.getAccessibleFromNativeWindowHandle(nativeHandle);
+ if (a != null) {
+ ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, a);
+ saveContextToWindowHandleMapping(ac, nativeHandle);
+ return ac;
+ }
+ }
+ // Not found.
+ return null;
+ }
+
+ /**
+ * maps an AccessibleContext to a native window handle
+ * returns 0 on error
+ */
+ private int getNativeWindowHandleFromContext(AccessibleContext ac) {
+ debugString("getNativeWindowHandleFromContext: ac = "+ac);
+ try {
+ return contextToWindowHandleMap.get(ac);
+ } catch (Exception ex) {
+ return 0;
+ }
+ }
+
+ private class DefaultNativeWindowHandler implements NativeWindowHandler {
+ /*
+ * returns the Accessible associated with a native window
+ */
+ public Accessible getAccessibleFromNativeWindowHandle(int nativeHandle) {
+ final Component c = jawtGetComponentFromNativeWindowHandle(nativeHandle);
+ if (c instanceof Accessible) {
+ AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return c.getAccessibleContext();
+ }
+ }, c);
+ saveContextToWindowHandleMapping(ac, nativeHandle);
+ return (Accessible)c;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /* ===== AccessibleContext methods =====*/
+
+ /*
+ * returns the inner-most AccessibleContext in parent at Point(x, y)
+ */
+ private AccessibleContext getAccessibleContextAt(int x, int y,
+ AccessibleContext parent) {
+ if (parent == null) {
+ return null;
+ }
+ if (windowHandleToContextMap != null &&
+ windowHandleToContextMap.containsValue(getRootAccessibleContext(parent))) {
+ // Path for applications that register their top-level
+ // windows with the AccessBridge (e.g., StarOffice 6.1)
+ return getAccessibleContextAt_1(x, y, parent);
+ } else {
+ // Path for applications that do not register
+ // their top-level windows with the AccessBridge
+ // (e.g., Swing/AWT applications)
+ return getAccessibleContextAt_2(x, y, parent);
+ }
+ }
+
+ /*
+ * returns the root accessible context
+ */
+ private AccessibleContext getRootAccessibleContext(final AccessibleContext ac) {
+ if (ac == null) {
+ return null;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible parent = ac.getAccessibleParent();
+ if (parent == null) {
+ return ac;
+ }
+ Accessible tmp = parent.getAccessibleContext().getAccessibleParent();
+ while (tmp != null) {
+ parent = tmp;
+ tmp = parent.getAccessibleContext().getAccessibleParent();
+ }
+ return parent.getAccessibleContext();
+ }
+ }, ac);
+ }
+
+ /*
+ * StarOffice version that does not use the EventQueueMonitor
+ */
+ private AccessibleContext getAccessibleContextAt_1(final int x, final int y,
+ final AccessibleContext parent) {
+ debugString(" : getAccessibleContextAt_1 called");
+ debugString(" -> x = " + x + " y = " + y + " parent = " + parent);
+
+ if (parent == null) return null;
+ final AccessibleComponent acmp = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleComponent call() throws Exception {
+ return parent.getAccessibleComponent();
+ }
+ }, parent);
+ if (acmp!=null) {
+ final Point loc = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Point call() throws Exception {
+ return acmp.getLocation();
+ }
+ }, parent);
+ final Accessible a = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return acmp.getAccessibleAt(new Point(x - loc.x, y - loc.y));
+ }
+ }, parent);
+ if (a != null) {
+ AccessibleContext foundAC = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, parent);
+ if (foundAC != null) {
+ if (foundAC != parent) {
+ // recurse down into the child
+ return getAccessibleContextAt_1(x - loc.x, y - loc.y,
+ foundAC);
+ } else
+ return foundAC;
+ }
+ }
+ }
+ return parent;
+ }
+
+ /*
+ * AWT/Swing version
+ */
+ private AccessibleContext getAccessibleContextAt_2(final int x, final int y,
+ AccessibleContext parent) {
+ debugString("getAccessibleContextAt_2 called");
+ debugString(" -> x = " + x + " y = " + y + " parent = " + parent);
+
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = EventQueueMonitor.getAccessibleAt(new Point(x, y));
+ if (a != null) {
+ AccessibleContext childAC = a.getAccessibleContext();
+ if (childAC != null) {
+ debugString(" returning childAC = " + childAC);
+ return childAC;
+ }
+ }
+ return null;
+ }
+ }, parent);
+ }
+
+ /**
+ * returns the Accessible that has focus
+ */
+ private AccessibleContext getAccessibleContextWithFocus() {
+ Component c = AWTEventMonitor.getComponentWithFocus();
+ if (c != null) {
+ final Accessible a = Translator.getAccessible(c);
+ if (a != null) {
+ AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return a.getAccessibleContext();
+ }
+ }, c);
+ if (ac != null) {
+ return ac;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * returns the AccessibleName from an AccessibleContext
+ */
+ private String getAccessibleNameFromContext(final AccessibleContext ac) {
+ debugString("***** ac = "+ac.getClass());
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleName();
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ debugString("Returning AccessibleName from Context: " + s);
+ return s;
+ } else {
+ return null;
+ }
+ } else {
+ debugString("getAccessibleNameFromContext; ac = null!");
+ return null;
+ }
+ }
+
+ /**
+ * Returns an AccessibleName for a component using an algorithm optimized
+ * for the JAWS screen reader. This method is only intended for JAWS. All
+ * other uses are entirely optional.
+ */
+ private String getVirtualAccessibleNameFromContext(final AccessibleContext ac) {
+ if (null != ac) {
+ /*
+ Step 1:
+ =======
+ Determine if we can obtain the Virtual Accessible Name from the
+ Accessible Name or Accessible Description of the object.
+ */
+ String nameString = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleName();
+ }
+ }, ac);
+ if ( ( null != nameString ) && ( 0 != nameString.length () ) ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from AccessibleContext::getAccessibleName.");
+ references.increment (nameString);
+ return nameString;
+ }
+ String descriptionString = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleDescription();
+ }
+ }, ac);
+ if ( ( null != descriptionString ) && ( 0 != descriptionString.length () ) ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from AccessibleContext::getAccessibleDescription.");
+ references.increment (descriptionString);
+ return descriptionString;
+ }
+
+ debugString ("The Virtual Accessible Name was not found using AccessibleContext::getAccessibleDescription. or getAccessibleName");
+ /*
+ Step 2:
+ =======
+ Decide whether the extended name search algorithm should be
+ used for this object.
+ */
+ boolean bExtendedSearch = false;
+ AccessibleRole role = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return ac.getAccessibleRole();
+ }
+ }, ac);
+ AccessibleContext parentContext = null;
+ AccessibleRole parentRole = AccessibleRole.UNKNOWN;
+
+ if ( extendedVirtualNameSearchRoles.contains (role) ) {
+ parentContext = getAccessibleParentFromContext (ac);
+ if ( null != parentContext ) {
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ parentRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return parentContextInnerTemp.getAccessibleRole();
+ }
+ }, ac);
+ if ( AccessibleRole.UNKNOWN != parentRole ) {
+ bExtendedSearch = true;
+ if ( noExtendedVirtualNameSearchParentRoles.contains (parentRole) ) {
+ bExtendedSearch = false;
+ }
+ }
+ }
+ }
+
+ if (false == bExtendedSearch) {
+ debugString ("bk -- getVirtualAccessibleNameFromContext will not use the extended name search algorithm. role = " + role.toDisplayString (Locale.US) );
+ /*
+ Step 3:
+ =======
+ We have determined that we should not use the extended name
+ search algorithm for this object (we must obtain the name of
+ the object from the object itself and not from neighboring
+ objects). However the object name cannot be obtained from
+ the Accessible Name or Accessible Description of the object.
+
+ Handle several special cases here that might yield a value for
+ the Virtual Accessible Name. Return null if the object does
+ not match the criteria for any of these special cases.
+ */
+ if (AccessibleRole.LABEL == role) {
+ /*
+ Does the label support the Accessible Text Interface?
+ */
+ final AccessibleText at = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleText call() throws Exception {
+ return ac.getAccessibleText();
+ }
+ }, ac);
+ if (null != at) {
+ int charCount = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return at.getCharCount();
+ }
+ }, ac);
+ String text = getAccessibleTextRangeFromContext (ac, 0, charCount);
+ if (null != text) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from the Accessible Text of the LABEL object.");
+ references.increment (text);
+ return text;
+ }
+ }
+ /*
+ Does the label support the Accessible Icon Interface?
+ */
+ debugString ("bk -- Attempting to obtain the Virtual Accessible Name from the Accessible Icon information.");
+ final AccessibleIcon [] ai = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleIcon[] call() throws Exception {
+ return ac.getAccessibleIcon();
+ }
+ }, ac);
+ if ( (null != ai) && (ai.length > 0) ) {
+ String iconDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ai[0].getAccessibleIconDescription();
+ }
+ }, ac);
+ if (iconDescription != null){
+ debugString ("bk -- The Virtual Accessible Name was obtained from the description of the first Accessible Icon found in the LABEL object.");
+ references.increment (iconDescription);
+ return iconDescription;
+ }
+ } else {
+ parentContext = getAccessibleParentFromContext (ac);
+ if ( null != parentContext ) {
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ parentRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return parentContextInnerTemp.getAccessibleRole();
+ }
+ }, ac);
+ if ( AccessibleRole.TABLE == parentRole ) {
+ int indexInParent = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac.getAccessibleIndexInParent();
+ }
+ }, ac);
+ final AccessibleContext acTableCell = getAccessibleChildFromContext (parentContext, indexInParent);
+ debugString ("bk -- Making a second attempt to obtain the Virtual Accessible Name from the Accessible Icon information for the Table Cell.");
+ if (acTableCell != null) {
+ final AccessibleIcon [] aiRet =InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleIcon[] call() throws Exception {
+ return acTableCell.getAccessibleIcon();
+ }
+ }, ac);
+ if ( (null != aiRet) && (aiRet.length > 0) ) {
+ String iconDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return aiRet[0].getAccessibleIconDescription();
+ }
+ }, ac);
+ if (iconDescription != null){
+ debugString ("bk -- The Virtual Accessible Name was obtained from the description of the first Accessible Icon found in the Table Cell object.");
+ references.increment (iconDescription);
+ return iconDescription;
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if ( (AccessibleRole.TOGGLE_BUTTON == role) ||
+ (AccessibleRole.PUSH_BUTTON == role) ) {
+ /*
+ Does the button support the Accessible Icon Interface?
+ */
+ debugString ("bk -- Attempting to obtain the Virtual Accessible Name from the Accessible Icon information.");
+ final AccessibleIcon [] ai = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleIcon[] call() throws Exception {
+ return ac.getAccessibleIcon();
+ }
+ }, ac);
+ if ( (null != ai) && (ai.length > 0) ) {
+ String iconDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ai[0].getAccessibleIconDescription();
+ }
+ }, ac);
+ if (iconDescription != null){
+ debugString ("bk -- The Virtual Accessible Name was obtained from the description of the first Accessible Icon found in the TOGGLE_BUTTON or PUSH_BUTTON object.");
+ references.increment (iconDescription);
+ return iconDescription;
+ }
+ }
+ } else if ( AccessibleRole.CHECK_BOX == role ) {
+ /*
+ NOTE: The only case I know of in which a check box does not
+ have a name is when that check box is contained in a table.
+
+ In this case it would be appropriate to use the display string
+ of the check box object as the name (in US English the display
+ string is typically either "true" or "false").
+
+ I am using the AccessibleValue interface to obtain the display
+ string of the check box. If the Accessible Value is 1, I am
+ returning Boolean.TRUE.toString (), If the Accessible Value is
+ 0, I am returning Boolean.FALSE.toString (). If the Accessible
+ Value is some other number, I will return the display string of
+ the current numerical value of the check box.
+ */
+ final AccessibleValue av = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleValue call() throws Exception {
+ return ac.getAccessibleValue();
+ }
+ }, ac);
+ if ( null != av ) {
+ nameString = null;
+ Number value = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Number call() throws Exception {
+ return av.getCurrentAccessibleValue();
+ }
+ }, ac);
+ if ( null != value ) {
+ if ( 1 == value.intValue () ) {
+ nameString = Boolean.TRUE.toString ();
+ } else if ( 0 == value.intValue () ) {
+ nameString = Boolean.FALSE.toString ();
+ } else {
+ nameString = value.toString ();
+ }
+ if ( null != nameString ) {
+ references.increment (nameString);
+ return nameString;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ +
+ Beginning of the extended name search
+ +
+ */
+ final AccessibleContext parentContextOuterTemp = parentContext;
+ String parentName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return parentContextOuterTemp.getAccessibleName();
+ }
+ }, ac);
+ String parentDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return parentContextOuterTemp.getAccessibleDescription();
+ }
+ }, ac);
+
+ /*
+ Step 4:
+ =======
+ Special case for Slider Bar objects.
+ */
+ if ( (AccessibleRole.SLIDER == role) &&
+ (AccessibleRole.PANEL == parentRole) &&
+ (null != parentName) ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from the Accessible Name of the SLIDER object's parent object.");
+ references.increment (parentName);
+ return parentName;
+ }
+
+ boolean bIsEditCombo = false;
+
+ AccessibleContext testContext = ac;
+ /*
+ Step 5:
+ =======
+ Special case for Edit Combo Boxes
+ */
+ if ( (AccessibleRole.TEXT == role) &&
+ (AccessibleRole.COMBO_BOX == parentRole) ) {
+ bIsEditCombo = true;
+ if (null != parentName) {
+ debugString ("bk -- The Virtual Accessible Name for this Edit Combo box was obtained from the Accessible Name of the object's parent object.");
+ references.increment (parentName);
+ return parentName;
+ } else if (null != parentDescription) {
+ debugString ("bk -- The Virtual Accessible Name for this Edit Combo box was obtained from the Accessible Description of the object's parent object.");
+ references.increment (parentDescription);
+ return parentDescription;
+ }
+ testContext = parentContext;
+ parentRole = AccessibleRole.UNKNOWN;
+ parentContext = getAccessibleParentFromContext (testContext);
+ if ( null != parentContext ) {
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ parentRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return parentContextInnerTemp.getAccessibleRole();
+ }
+ }, ac);
+ }
+ }
+
+ /*
+ Step 6:
+ =======
+ Attempt to get the Virtual Accessible Name of the object using the
+ Accessible Relation Set Info (the LABELED_BY Accessible Relation).
+ */
+ {
+ final AccessibleContext parentContextTempInner = parentContext;
+ AccessibleRelationSet ars = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRelationSet call() throws Exception {
+ return parentContextTempInner.getAccessibleRelationSet();
+ }
+ }, ac);
+ if ( ars != null && (ars.size () > 0) && (ars.contains (AccessibleRelation.LABELED_BY)) ) {
+ AccessibleRelation labeledByRelation = ars.get (AccessibleRelation.LABELED_BY);
+ if (labeledByRelation != null) {
+ Object [] targets = labeledByRelation.getTarget ();
+ Object o = targets [0];
+ if (o instanceof Accessible) {
+ AccessibleContext labelContext = ((Accessible)o).getAccessibleContext ();
+ if (labelContext != null) {
+ String labelName = labelContext.getAccessibleName ();
+ String labelDescription = labelContext.getAccessibleDescription ();
+ if (null != labelName) {
+ debugString ("bk -- The Virtual Accessible Name was obtained using the LABELED_BY AccessibleRelation -- Name Case.");
+ references.increment (labelName);
+ return labelName;
+ } else if (null != labelDescription) {
+ debugString ("bk -- The Virtual Accessible Name was obtained using the LABELED_BY AccessibleRelation -- Description Case.");
+ references.increment (labelDescription);
+ return labelDescription;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //Note: add AccessibleContext to use InvocationUtils.invokeAndWait
+ /*
+ Step 7:
+ =======
+ Search for a label object that is positioned either just to the left
+ or just above the object and get the Accessible Name of the Label
+ object.
+ */
+ int testIndexMax = 0;
+ int testX = 0;
+ int testY = 0;
+ int testWidth = 0;
+ int testHeight = 0;
+ int targetX = 0;
+ int targetY = 0;
+ final AccessibleContext tempContext = testContext;
+ int testIndex = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return tempContext.getAccessibleIndexInParent();
+ }
+ }, ac);
+ if ( null != parentContext ) {
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ testIndexMax = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChildrenCount() - 1;
+ }
+ }, ac);
+ }
+ testX = getAccessibleXcoordFromContext (testContext);
+ testY = getAccessibleYcoordFromContext (testContext);
+ testWidth = getAccessibleWidthFromContext (testContext);
+ testHeight = getAccessibleHeightFromContext (testContext);
+ targetX = testX + 2;
+ targetY = testY + 2;
+
+ int childIndex = testIndex - 1;
+ /*Accessible child = null;
+ AccessibleContext childContext = null;
+ AccessibleRole childRole = AccessibleRole.UNKNOWN;*/
+ int childX = 0;
+ int childY = 0;
+ int childWidth = 0;
+ int childHeight = 0;
+ String childName = null;
+ String childDescription = null;
+ while (childIndex >= 0) {
+ final int childIndexTemp = childIndex;
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ final Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChild(childIndexTemp);
+ }
+ }, ac);
+ if ( null != child ) {
+ final AccessibleContext childContext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return child.getAccessibleContext();
+ }
+ }, ac);
+ if ( null != childContext ) {
+ AccessibleRole childRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return childContext.getAccessibleRole();
+ }
+ }, ac);
+ if ( AccessibleRole.LABEL == childRole ) {
+ childX = getAccessibleXcoordFromContext (childContext);
+ childY = getAccessibleYcoordFromContext (childContext);
+ childWidth = getAccessibleWidthFromContext (childContext);
+ childHeight = getAccessibleHeightFromContext (childContext);
+ if ( (childX < testX) &&
+ ((childY <= targetY) && (targetY <= (childY + childHeight))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a LABEL object positioned to the left of the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a LABEL object positioned to the left of the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ } else if ( (childY < targetY) &&
+ ((childX <= targetX) && (targetX <= (childX + childWidth))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a LABEL object positioned above the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a LABEL object positioned above the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ }
+ }
+ }
+ }
+ childIndex --;
+ }
+ childIndex = testIndex + 1;
+ while (childIndex <= testIndexMax) {
+ final int childIndexTemp = childIndex;
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ final Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChild(childIndexTemp);
+ }
+ }, ac);
+ if ( null != child ) {
+ final AccessibleContext childContext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return child.getAccessibleContext();
+ }
+ }, ac);
+ if ( null != childContext ) {
+ AccessibleRole childRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return childContext.getAccessibleRole();
+ }
+ }, ac);
+ if ( AccessibleRole.LABEL == childRole ) {
+ childX = getAccessibleXcoordFromContext (childContext);
+ childY = getAccessibleYcoordFromContext (childContext);
+ childWidth = getAccessibleWidthFromContext (childContext);
+ childHeight = getAccessibleHeightFromContext (childContext);
+ if ( (childX < testX) &&
+ ((childY <= targetY) && (targetY <= (childY + childHeight))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a LABEL object positioned to the left of the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a LABEL object positioned to the left of the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ } else if ( (childY < targetY) &&
+ ((childX <= targetX) && (targetX <= (childX + childWidth))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a LABEL object positioned above the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a LABEL object positioned above the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ }
+ }
+ }
+ }
+ childIndex ++;
+ }
+ /*
+ Step 8:
+ =======
+ Special case for combo boxes and text objects, based on a
+ similar special case I found in some of our internal JAWS code.
+
+ Search for a button object that is positioned either just to the left
+ or just above the object and get the Accessible Name of the button
+ object.
+ */
+ if ( (AccessibleRole.TEXT == role) ||
+ (AccessibleRole.COMBO_BOX == role) ||
+ (bIsEditCombo) ) {
+ childIndex = testIndex - 1;
+ while (childIndex >= 0) {
+ final int childIndexTemp = childIndex;
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ final Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChild(childIndexTemp);
+ }
+ }, ac);
+ if ( null != child ) {
+ final AccessibleContext childContext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return child.getAccessibleContext();
+ }
+ }, ac);
+ if ( null != childContext ) {
+ AccessibleRole childRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return childContext.getAccessibleRole();
+ }
+ }, ac);
+ if ( ( AccessibleRole.PUSH_BUTTON == childRole ) ||
+ ( AccessibleRole.TOGGLE_BUTTON == childRole )) {
+ childX = getAccessibleXcoordFromContext (childContext);
+ childY = getAccessibleYcoordFromContext (childContext);
+ childWidth = getAccessibleWidthFromContext (childContext);
+ childHeight = getAccessibleHeightFromContext (childContext);
+ if ( (childX < testX) &&
+ ((childY <= targetY) && (targetY <= (childY + childHeight))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a PUSH_BUTTON or TOGGLE_BUTTON object positioned to the left of the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a PUSH_BUTTON or TOGGLE_BUTTON object positioned to the left of the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ }
+ }
+ }
+ }
+ childIndex --;
+ }
+ childIndex = testIndex + 1;
+ while (childIndex <= testIndexMax) {
+ final int childIndexTemp = childIndex;
+ final AccessibleContext parentContextInnerTemp = parentContext;
+ final Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return parentContextInnerTemp.getAccessibleChild(childIndexTemp);
+ }
+ }, ac);
+ if ( null != child ) {
+ final AccessibleContext childContext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return child.getAccessibleContext();
+ }
+ }, ac);
+ if ( null != childContext ) {
+ AccessibleRole childRole = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return childContext.getAccessibleRole();
+ }
+ }, ac);
+ if ( ( AccessibleRole.PUSH_BUTTON == childRole ) ||
+ ( AccessibleRole.TOGGLE_BUTTON == childRole ) ) {
+ childX = getAccessibleXcoordFromContext (childContext);
+ childY = getAccessibleYcoordFromContext (childContext);
+ childWidth = getAccessibleWidthFromContext (childContext);
+ childHeight = getAccessibleHeightFromContext (childContext);
+ if ( (childX < testX) &&
+ ((childY <= targetY) && (targetY <= (childY + childHeight))) ) {
+ childName = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleName();
+ }
+ }, ac);
+ if ( null != childName ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Name of a PUSH_BUTTON or TOGGLE_BUTTON object positioned to the left of the object.");
+ references.increment (childName);
+ return childName;
+ }
+ childDescription = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return childContext.getAccessibleDescription();
+ }
+ }, ac);
+ if ( null != childDescription ) {
+ debugString ("bk -- The Virtual Accessible Name was obtained from Accessible Description of a PUSH_BUTTON or TOGGLE_BUTTON object positioned to the left of the object.");
+ references.increment (childDescription);
+ return childDescription;
+ }
+ }
+ }
+ }
+ }
+ childIndex ++;
+ }
+ }
+ return null;
+ } else {
+ debugString ("AccessBridge::getVirtualAccessibleNameFromContext error - ac == null.");
+ return null;
+ }
+ }
+
+ /**
+ * returns the AccessibleDescription from an AccessibleContext
+ */
+ private String getAccessibleDescriptionFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleDescription();
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ debugString("Returning AccessibleDescription from Context: " + s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleDescriptionFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * returns the AccessibleRole from an AccessibleContext
+ */
+ private String getAccessibleRoleStringFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ AccessibleRole role = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRole call() throws Exception {
+ return ac.getAccessibleRole();
+ }
+ }, ac);
+ if (role != null) {
+ String s = role.toDisplayString(Locale.US);
+ if (s != null) {
+ references.increment(s);
+ debugString("Returning AccessibleRole from Context: " + s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getAccessibleRoleStringFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the AccessibleRole from an AccessibleContext in the en_US locale
+ */
+ private String getAccessibleRoleStringFromContext_en_US(final AccessibleContext ac) {
+ return getAccessibleRoleStringFromContext(ac);
+ }
+
+ /**
+ * return the AccessibleStates from an AccessibleContext
+ */
+ private String getAccessibleStatesStringFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ AccessibleStateSet stateSet = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleStateSet call() throws Exception {
+ return ac.getAccessibleStateSet();
+ }
+ }, ac);
+ if (stateSet != null) {
+ String s = stateSet.toString();
+ if (s != null &&
+ s.indexOf(AccessibleState.MANAGES_DESCENDANTS.toDisplayString(Locale.US)) == -1) {
+ // Indicate whether this component manages its own
+ // children
+ AccessibleRole role = ac.getAccessibleRole();
+ if (role == AccessibleRole.LIST ||
+ role == AccessibleRole.TABLE ||
+ role == AccessibleRole.TREE) {
+ s += ",";
+ s += AccessibleState.MANAGES_DESCENDANTS.toDisplayString(Locale.US);
+ }
+ references.increment(s);
+ debugString("Returning AccessibleStateSet from Context: " + s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getAccessibleStatesStringFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * returns the AccessibleStates from an AccessibleContext in the en_US locale
+ */
+ private String getAccessibleStatesStringFromContext_en_US(final AccessibleContext ac) {
+ if (ac != null) {
+ AccessibleStateSet stateSet = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleStateSet call() throws Exception {
+ return ac.getAccessibleStateSet();
+ }
+ }, ac);
+ if (stateSet != null) {
+ String s = "";
+ AccessibleState[] states = stateSet.toArray();
+ if (states != null && states.length > 0) {
+ s = states[0].toDisplayString(Locale.US);
+ for (int i = 1; i < states.length; i++) {
+ s = s + "," + states[i].toDisplayString(Locale.US);
+ }
+ }
+ references.increment(s);
+ debugString("Returning AccessibleStateSet en_US from Context: " + s);
+ return s;
+ }
+ }
+ debugString("getAccessibleStatesStringFromContext; ac = null");
+ return null;
+ }
+
+ /**
+ * returns the AccessibleParent from an AccessibleContext
+ */
+ private AccessibleContext getAccessibleParentFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = ac.getAccessibleParent();
+ if (a != null) {
+ AccessibleContext apc = a.getAccessibleContext();
+ if (apc != null) {
+ return apc;
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleIndexInParent from an AccessibleContext
+ */
+ private int getAccessibleIndexInParentFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac.getAccessibleIndexInParent();
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleChild count from an AccessibleContext
+ */
+ private int getAccessibleChildrenCountFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac.getAccessibleChildrenCount();
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleChild Context from an AccessibleContext
+ */
+ private AccessibleContext getAccessibleChildFromContext(final AccessibleContext ac, final int index) {
+
+ if (ac == null) {
+ return null;
+ }
+
+ final JTable table = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public JTable call() throws Exception {
+ // work-around for AccessibleJTable.getCurrentAccessibleContext returning
+ // wrong renderer component when cell contains more than one component
+ Accessible parent = ac.getAccessibleParent();
+ if (parent != null) {
+ int indexInParent = ac.getAccessibleIndexInParent();
+ Accessible child =
+ parent.getAccessibleContext().getAccessibleChild(indexInParent);
+ if (child instanceof JTable) {
+ return (JTable) child;
+ }
+ }
+ return null;
+ }
+ }, ac);
+
+ if (table == null) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = ac.getAccessibleChild(index);
+ if (a != null) {
+ return a.getAccessibleContext();
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ final AccessibleTable at = getAccessibleTableFromContext(ac);
+
+ final int row = getAccessibleTableRow(at, index);
+ final int column = getAccessibleTableColumn(at, index);
+
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ TableCellRenderer renderer = table.getCellRenderer(row, column);
+ if (renderer == null) {
+ Class> columnClass = table.getColumnClass(column);
+ renderer = table.getDefaultRenderer(columnClass);
+ }
+ Component component =
+ renderer.getTableCellRendererComponent(table, table.getValueAt(row, column),
+ false, false, row, column);
+ if (component instanceof Accessible) {
+ return component.getAccessibleContext();
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleComponent bounds on screen from an AccessibleContext
+ */
+ private Rectangle getAccessibleBoundsOnScreenFromContext(final AccessibleContext ac) {
+ if(ac==null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Rectangle call() throws Exception {
+ AccessibleComponent acmp = ac.getAccessibleComponent();
+ if (acmp != null) {
+ Rectangle r = acmp.getBounds();
+ if (r != null) {
+ try {
+ Point p = acmp.getLocationOnScreen();
+ if (p != null) {
+ r.x = p.x;
+ r.y = p.y;
+ return r;
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleComponent x-coord from an AccessibleContext
+ */
+ private int getAccessibleXcoordFromContext(AccessibleContext ac) {
+ if (ac != null) {
+ Rectangle r = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null) {
+ debugString(" - Returning Accessible x coord from Context: " + r.x);
+ return r.x;
+ }
+ } else {
+ debugString("getAccessibleXcoordFromContext ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * returns the AccessibleComponent y-coord from an AccessibleContext
+ */
+ private int getAccessibleYcoordFromContext(AccessibleContext ac) {
+ debugString("getAccessibleYcoordFromContext() called");
+ if (ac != null) {
+ Rectangle r = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null) {
+ return r.y;
+ }
+ } else {
+ debugString("getAccessibleYcoordFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * returns the AccessibleComponent height from an AccessibleContext
+ */
+ private int getAccessibleHeightFromContext(AccessibleContext ac) {
+ if (ac != null) {
+ Rectangle r = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null) {
+ return r.height;
+ }
+ } else {
+ debugString("getAccessibleHeightFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * returns the AccessibleComponent width from an AccessibleContext
+ */
+ private int getAccessibleWidthFromContext(AccessibleContext ac) {
+ if (ac != null) {
+ Rectangle r = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null) {
+ return r.width;
+ }
+ } else {
+ debugString("getAccessibleWidthFromContext; ac = null");
+ }
+ return -1;
+ }
+
+
+ /**
+ * returns the AccessibleComponent from an AccessibleContext
+ */
+ private AccessibleComponent getAccessibleComponentFromContext(AccessibleContext ac) {
+ if (ac != null) {
+ AccessibleComponent acmp = ac.getAccessibleComponent();
+ if (acmp != null) {
+ debugString("Returning AccessibleComponent Context");
+ return acmp;
+ }
+ } else {
+ debugString("getAccessibleComponentFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * returns the AccessibleAction from an AccessibleContext
+ */
+ private AccessibleAction getAccessibleActionFromContext(final AccessibleContext ac) {
+ debugString("Returning AccessibleAction Context");
+ return ac == null ? null : InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleAction call() throws Exception {
+ return ac.getAccessibleAction();
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the AccessibleSelection from an AccessibleContext
+ */
+ private AccessibleSelection getAccessibleSelectionFromContext(final AccessibleContext ac) {
+ return ac == null ? null : InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleSelection call() throws Exception {
+ return ac.getAccessibleSelection();
+ }
+ }, ac);
+ }
+
+ /**
+ * return the AccessibleText from an AccessibleContext
+ */
+ private AccessibleText getAccessibleTextFromContext(final AccessibleContext ac) {
+ return ac == null ? null : InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleText call() throws Exception {
+ return ac.getAccessibleText();
+ }
+ }, ac);
+ }
+
+ /**
+ * return the AccessibleComponent from an AccessibleContext
+ */
+ private AccessibleValue getAccessibleValueFromContext(final AccessibleContext ac) {
+ return ac == null ? null : InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleValue call() throws Exception {
+ return ac.getAccessibleValue();
+ }
+ }, ac);
+ }
+
+ /* ===== AccessibleText methods ===== */
+
+ /**
+ * returns the bounding rectangle for the text cursor
+ * XXX
+ */
+ private Rectangle getCaretLocation(final AccessibleContext ac) {
+ debugString("getCaretLocation");
+ if (ac==null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Rectangle call() throws Exception {
+ // workaround for JAAPI not returning cursor bounding rectangle
+ Rectangle r = null;
+ Accessible parent = ac.getAccessibleParent();
+ if (parent instanceof Accessible) {
+ int indexInParent = ac.getAccessibleIndexInParent();
+ Accessible child =
+ parent.getAccessibleContext().getAccessibleChild(indexInParent);
+
+ if (child instanceof JTextComponent) {
+ JTextComponent text = (JTextComponent) child;
+ try {
+ r = text.modelToView(text.getCaretPosition());
+ if (r != null) {
+ Point p = text.getLocationOnScreen();
+ r.translate(p.x, p.y);
+ }
+ } catch (BadLocationException ble) {
+ }
+ }
+ }
+ return r;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the x-coordinate for the text cursor rectangle
+ */
+ private int getCaretLocationX(AccessibleContext ac) {
+ Rectangle r = getCaretLocation(ac);
+ if (r != null) {
+ return r.x;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the y-coordinate for the text cursor rectangle
+ */
+ private int getCaretLocationY(AccessibleContext ac) {
+ Rectangle r = getCaretLocation(ac);
+ if (r != null) {
+ return r.y;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the height for the text cursor rectangle
+ */
+ private int getCaretLocationHeight(AccessibleContext ac) {
+ Rectangle r = getCaretLocation(ac);
+ if (r != null) {
+ return r.height;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the width for the text cursor rectangle
+ */
+ private int getCaretLocationWidth(AccessibleContext ac) {
+ Rectangle r = getCaretLocation(ac);
+ if (r != null) {
+ return r.width;
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * returns the character count from an AccessibleContext
+ */
+ private int getAccessibleCharCountFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getCharCount();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * returns the caret position from an AccessibleContext
+ */
+ private int getAccessibleCaretPositionFromContext(final AccessibleContext ac) {
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getCaretPosition();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * Return the index at a specific point from an AccessibleContext
+ * Point(x, y) is in screen coordinates.
+ */
+ private int getAccessibleIndexAtPointFromContext(final AccessibleContext ac,
+ final int x, final int y) {
+ debugString("getAccessibleIndexAtPointFromContext: x = "+x+"; y = "+y);
+ if (ac==null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ AccessibleComponent acomp = ac.getAccessibleComponent();
+ if (at != null && acomp != null) {
+ // Convert x and y from screen coordinates to
+ // local coordinates.
+ try {
+ Point p = acomp.getLocationOnScreen();
+ int x1, y1;
+ if (p != null) {
+ x1 = x - p.x;
+ if (x1 < 0) {
+ x1 = 0;
+ }
+ y1 = y - p.y;
+ if (y1 < 0) {
+ y1 = 0;
+ }
+
+ Point newPoint = new Point(x1, y1);
+ int indexAtPoint = at.getIndexAtPoint(new Point(x1, y1));
+ return indexAtPoint;
+ }
+ } catch (Exception e) {
+ }
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * return the letter at a specific point from an AccessibleContext
+ */
+ private String getAccessibleLetterAtIndexFromContext(final AccessibleContext ac, final int index) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at == null) return null;
+ return at.getAtIndex(AccessibleText.CHARACTER, index);
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleLetterAtIndexFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the word at a specific point from an AccessibleContext
+ */
+ private String getAccessibleWordAtIndexFromContext(final AccessibleContext ac, final int index) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at == null) return null;
+ return at.getAtIndex(AccessibleText.WORD, index);
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleWordAtIndexFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the sentence at a specific point from an AccessibleContext
+ */
+ private String getAccessibleSentenceAtIndexFromContext(final AccessibleContext ac, final int index) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at == null) return null;
+ return at.getAtIndex(AccessibleText.SENTENCE, index);
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleSentenceAtIndexFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the text selection start from an AccessibleContext
+ */
+ private int getAccessibleTextSelectionStartFromContext(final AccessibleContext ac) {
+ if (ac == null) return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getSelectionStart();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * return the text selection end from an AccessibleContext
+ */
+ private int getAccessibleTextSelectionEndFromContext(final AccessibleContext ac) {
+ if (ac == null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getSelectionEnd();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * return the selected text from an AccessibleContext
+ */
+ private String getAccessibleTextSelectedTextFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at == null) return null;
+ return at.getSelectedText();
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getAccessibleTextSelectedTextFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the attribute string at a given index from an AccessibleContext
+ */
+ private String getAccessibleAttributesAtIndexFromContext(final AccessibleContext ac,
+ final int index) {
+ if (ac == null)
+ return null;
+ AttributeSet as = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AttributeSet call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ return at.getCharacterAttribute(index);
+ }
+ return null;
+ }
+ }, ac);
+ String s = expandStyleConstants(as);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ return null;
+ }
+
+ /**
+ * Get line info: left index of line
+ *
+ * algorithm: cast back, doubling each time,
+ * 'till find line boundaries
+ *
+ * return -1 if we can't get the info (e.g. index or at passed in
+ * is bogus; etc.)
+ */
+ private int getAccessibleTextLineLeftBoundsFromContext(final AccessibleContext ac,
+ final int index) {
+ if (ac == null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ int lineStart;
+ int offset;
+ Rectangle charRect;
+ Rectangle indexRect = at.getCharacterBounds(index);
+ int textLen = at.getCharCount();
+ if (indexRect == null) {
+ return -1;
+ }
+ // find the start of the line
+ //
+ offset = 1;
+ lineStart = index - offset < 0 ? 0 : index - offset;
+ charRect = at.getCharacterBounds(lineStart);
+ // slouch behind beginning of line
+ while (charRect != null
+ && charRect.y >= indexRect.y
+ && lineStart > 0) {
+ offset = offset << 1;
+ lineStart = index - offset < 0 ? 0 : index - offset;
+ charRect = at.getCharacterBounds(lineStart);
+ }
+ if (lineStart == 0) { // special case: we're on the first line!
+ // we found it!
+ } else {
+ offset = offset >> 1; // know boundary within last expansion
+ // ground forward to beginning of line
+ while (offset > 0) {
+ charRect = at.getCharacterBounds(lineStart + offset);
+ if (charRect.y < indexRect.y) { // still before line
+ lineStart += offset;
+ } else {
+ // leave lineStart alone, it's close!
+ }
+ offset = offset >> 1;
+ }
+ // subtract one 'cause we're already too far...
+ lineStart += 1;
+ }
+ return lineStart;
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * Get line info: right index of line
+ *
+ * algorithm: cast back, doubling each time,
+ * 'till find line boundaries
+ *
+ * return -1 if we can't get the info (e.g. index or at passed in
+ * is bogus; etc.)
+ */
+ private int getAccessibleTextLineRightBoundsFromContext(final AccessibleContext ac, final int index) {
+ if(ac == null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ int lineEnd;
+ int offset;
+ Rectangle charRect;
+ Rectangle indexRect = at.getCharacterBounds(index);
+ int textLen = at.getCharCount();
+ if (indexRect == null) {
+ return -1;
+ }
+ // find the end of the line
+ //
+ offset = 1;
+ lineEnd = index + offset > textLen - 1
+ ? textLen - 1 : index + offset;
+ charRect = at.getCharacterBounds(lineEnd);
+ // push past end of line
+ while (charRect != null &&
+ charRect.y <= indexRect.y &&
+ lineEnd < textLen - 1) {
+ offset = offset << 1;
+ lineEnd = index + offset > textLen - 1
+ ? textLen - 1 : index + offset;
+ charRect = at.getCharacterBounds(lineEnd);
+ }
+ if (lineEnd == textLen - 1) { // special case: on the last line!
+ // we found it!
+ } else {
+ offset = offset >> 1; // know boundary within last expansion
+ // pull back to end of line
+ while (offset > 0) {
+ charRect = at.getCharacterBounds(lineEnd - offset);
+ if (charRect.y > indexRect.y) { // still beyond line
+ lineEnd -= offset;
+ } else {
+ // leave lineEnd alone, it's close!
+ }
+ offset = offset >> 1;
+ }
+ // subtract one 'cause we're already too far...
+ lineEnd -= 1;
+ }
+ return lineEnd;
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * Get a range of text; null if indicies are bogus
+ */
+ private String getAccessibleTextRangeFromContext(final AccessibleContext ac,
+ final int start, final int end) {
+ String s = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ if (ac != null) {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ // start - end is inclusive
+ if (start > end) {
+ return null;
+ }
+ if (end >= at.getCharCount()) {
+ return null;
+ }
+ StringBuffer buf = new StringBuffer(end - start + 1);
+ for (int i = start; i <= end; i++) {
+ buf.append(at.getAtIndex(AccessibleText.CHARACTER, i));
+ }
+ return buf.toString();
+ }
+ }
+ return null;
+ }
+ }, ac);
+ if (s != null) {
+ references.increment(s);
+ return s;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * return the AttributeSet object at a given index from an AccessibleContext
+ */
+ private AttributeSet getAccessibleAttributeSetAtIndexFromContext(final AccessibleContext ac,
+ final int index) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AttributeSet call() throws Exception {
+ if (ac != null) {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ AttributeSet as = at.getCharacterAttribute(index);
+ if (as != null) {
+ AccessBridge.this.references.increment(as);
+ return as;
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+
+ /**
+ * return the bounding rectangle at index from an AccessibleContext
+ */
+ private Rectangle getAccessibleTextRectAtIndexFromContext(final AccessibleContext ac,
+ final int index) {
+ // want to do this in global coords, so need to combine w/ac global coords
+ Rectangle r = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Rectangle call() throws Exception {
+ // want to do this in global coords, so need to combine w/ac global coords
+ if (ac != null) {
+ AccessibleText at = ac.getAccessibleText();
+ if (at != null) {
+ Rectangle rect = at.getCharacterBounds(index);
+ if (rect != null) {
+ String s = at.getAtIndex(AccessibleText.CHARACTER, index);
+ if (s != null && s.equals("\n")) {
+ rect.width = 0;
+ }
+ return rect;
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ Rectangle acRect = getAccessibleBoundsOnScreenFromContext(ac);
+ if (r != null && acRect != null) {
+ r.translate(acRect.x, acRect.y);
+ return r;
+ }
+ return null;
+ }
+
+ /**
+ * return the AccessibleText character x-coord at index from an AccessibleContext
+ */
+ private int getAccessibleXcoordTextRectAtIndexFromContext(AccessibleContext ac, int index) {
+ if (ac != null) {
+ Rectangle r = getAccessibleTextRectAtIndexFromContext(ac, index);
+ if (r != null) {
+ return r.x;
+ }
+ } else {
+ debugString("getAccessibleXcoordTextRectAtIndexFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the AccessibleText character y-coord at index from an AccessibleContext
+ */
+ private int getAccessibleYcoordTextRectAtIndexFromContext(AccessibleContext ac, int index) {
+ if (ac != null) {
+ Rectangle r = getAccessibleTextRectAtIndexFromContext(ac, index);
+ if (r != null) {
+ return r.y;
+ }
+ } else {
+ debugString("getAccessibleYcoordTextRectAtIndexFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the AccessibleText character height at index from an AccessibleContext
+ */
+ private int getAccessibleHeightTextRectAtIndexFromContext(AccessibleContext ac, int index) {
+ if (ac != null) {
+ Rectangle r = getAccessibleTextRectAtIndexFromContext(ac, index);
+ if (r != null) {
+ return r.height;
+ }
+ } else {
+ debugString("getAccessibleHeightTextRectAtIndexFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the AccessibleText character width at index from an AccessibleContext
+ */
+ private int getAccessibleWidthTextRectAtIndexFromContext(AccessibleContext ac, int index) {
+ if (ac != null) {
+ Rectangle r = getAccessibleTextRectAtIndexFromContext(ac, index);
+ if (r != null) {
+ return r.width;
+ }
+ } else {
+ debugString("getAccessibleWidthTextRectAtIndexFromContext; ac = null");
+ }
+ return -1;
+ }
+
+ /* ===== AttributeSet methods for AccessibleText ===== */
+
+ /**
+ * return the bold setting from an AttributeSet
+ */
+ private boolean getBoldFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isBold(as);
+ } else {
+ debugString("getBoldFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the italic setting from an AttributeSet
+ */
+ private boolean getItalicFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isItalic(as);
+ } else {
+ debugString("getItalicFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the underline setting from an AttributeSet
+ */
+ private boolean getUnderlineFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isUnderline(as);
+ } else {
+ debugString("getUnderlineFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the strikethrough setting from an AttributeSet
+ */
+ private boolean getStrikethroughFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isStrikeThrough(as);
+ } else {
+ debugString("getStrikethroughFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the superscript setting from an AttributeSet
+ */
+ private boolean getSuperscriptFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isSuperscript(as);
+ } else {
+ debugString("getSuperscriptFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the subscript setting from an AttributeSet
+ */
+ private boolean getSubscriptFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.isSubscript(as);
+ } else {
+ debugString("getSubscriptFromAttributeSet; as = null");
+ }
+ return false;
+ }
+
+ /**
+ * return the background color from an AttributeSet
+ */
+ private String getBackgroundColorFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ String s = StyleConstants.getBackground(as).toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getBackgroundColorFromAttributeSet; as = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the foreground color from an AttributeSet
+ */
+ private String getForegroundColorFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ String s = StyleConstants.getForeground(as).toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getForegroundColorFromAttributeSet; as = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the font family from an AttributeSet
+ */
+ private String getFontFamilyFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ String s = StyleConstants.getFontFamily(as).toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ } else {
+ debugString("getFontFamilyFromAttributeSet; as = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the font size from an AttributeSet
+ */
+ private int getFontSizeFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getFontSize(as);
+ } else {
+ debugString("getFontSizeFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the alignment from an AttributeSet
+ */
+ private int getAlignmentFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getAlignment(as);
+ } else {
+ debugString("getAlignmentFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the BiDi level from an AttributeSet
+ */
+ private int getBidiLevelFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getBidiLevel(as);
+ } else {
+ debugString("getBidiLevelFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+
+ /**
+ * return the first line indent from an AttributeSet
+ */
+ private float getFirstLineIndentFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getFirstLineIndent(as);
+ } else {
+ debugString("getFirstLineIndentFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the left indent from an AttributeSet
+ */
+ private float getLeftIndentFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getLeftIndent(as);
+ } else {
+ debugString("getLeftIndentFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the right indent from an AttributeSet
+ */
+ private float getRightIndentFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getRightIndent(as);
+ } else {
+ debugString("getRightIndentFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the line spacing from an AttributeSet
+ */
+ private float getLineSpacingFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getLineSpacing(as);
+ } else {
+ debugString("getLineSpacingFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the space above from an AttributeSet
+ */
+ private float getSpaceAboveFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getSpaceAbove(as);
+ } else {
+ debugString("getSpaceAboveFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * return the space below from an AttributeSet
+ */
+ private float getSpaceBelowFromAttributeSet(AttributeSet as) {
+ if (as != null) {
+ return StyleConstants.getSpaceBelow(as);
+ } else {
+ debugString("getSpaceBelowFromAttributeSet; as = null");
+ }
+ return -1;
+ }
+
+ /**
+ * Enumerate all StyleConstants in the AttributeSet
+ *
+ * We need to check explicitly, 'cause of the HTML package conversion
+ * mechanism (they may not be stored as StyleConstants, just translated
+ * to them when asked).
+ *
+ * (Use convenience methods where they are defined...)
+ *
+ * Not checking the following (which the IBM SNS guidelines says
+ * should be defined):
+ * - ComponentElementName
+ * - IconElementName
+ * - NameAttribute
+ * - ResolveAttribute
+ */
+ private String expandStyleConstants(AttributeSet as) {
+ Color c;
+ Object o;
+ String attrString = "";
+
+ // ---------- check for various Character Constants
+
+ attrString += "BidiLevel = " + StyleConstants.getBidiLevel(as);
+
+ final Component comp = StyleConstants.getComponent(as);
+ if (comp != null) {
+ if (comp instanceof Accessible) {
+ final AccessibleContext ac = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return comp.getAccessibleContext();
+ }
+ }, comp);
+ if (ac != null) {
+ attrString += "; Accessible Component = " + InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleName();
+ }
+ }, ac);
+ } else {
+ attrString += "; Innaccessible Component = " + comp;
+ }
+ } else {
+ attrString += "; Innaccessible Component = " + comp;
+ }
+ }
+
+ Icon i = StyleConstants.getIcon(as);
+ if (i != null) {
+ if (i instanceof ImageIcon) {
+ attrString += "; ImageIcon = " + ((ImageIcon) i).getDescription();
+ } else {
+ attrString += "; Icon = " + i;
+ }
+ }
+
+ attrString += "; FontFamily = " + StyleConstants.getFontFamily(as);
+
+ attrString += "; FontSize = " + StyleConstants.getFontSize(as);
+
+ if (StyleConstants.isBold(as)) {
+ attrString += "; bold";
+ }
+
+ if (StyleConstants.isItalic(as)) {
+ attrString += "; italic";
+ }
+
+ if (StyleConstants.isUnderline(as)) {
+ attrString += "; underline";
+ }
+
+ if (StyleConstants.isStrikeThrough(as)) {
+ attrString += "; strikethrough";
+ }
+
+ if (StyleConstants.isSuperscript(as)) {
+ attrString += "; superscript";
+ }
+
+ if (StyleConstants.isSubscript(as)) {
+ attrString += "; subscript";
+ }
+
+ c = StyleConstants.getForeground(as);
+ if (c != null) {
+ attrString += "; Foreground = " + c;
+ }
+
+ c = StyleConstants.getBackground(as);
+ if (c != null) {
+ attrString += "; Background = " + c;
+ }
+
+ attrString += "; FirstLineIndent = " + StyleConstants.getFirstLineIndent(as);
+
+ attrString += "; RightIndent = " + StyleConstants.getRightIndent(as);
+
+ attrString += "; LeftIndent = " + StyleConstants.getLeftIndent(as);
+
+ attrString += "; LineSpacing = " + StyleConstants.getLineSpacing(as);
+
+ attrString += "; SpaceAbove = " + StyleConstants.getSpaceAbove(as);
+
+ attrString += "; SpaceBelow = " + StyleConstants.getSpaceBelow(as);
+
+ attrString += "; Alignment = " + StyleConstants.getAlignment(as);
+
+ TabSet ts = StyleConstants.getTabSet(as);
+ if (ts != null) {
+ attrString += "; TabSet = " + ts;
+ }
+
+ return attrString;
+ }
+
+
+ /* ===== AccessibleValue methods ===== */
+
+ /**
+ * return the AccessibleValue current value from an AccessibleContext
+ * returned using a String 'cause the value is a java Number
+ *
+ */
+ private String getCurrentAccessibleValueFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ final Number value = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Number call() throws Exception {
+ AccessibleValue av = ac.getAccessibleValue();
+ if (av == null) return null;
+ return av.getCurrentAccessibleValue();
+ }
+ }, ac);
+ if (value != null) {
+ String s = value.toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getCurrentAccessibleValueFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the AccessibleValue maximum value from an AccessibleContext
+ * returned using a String 'cause the value is a java Number
+ *
+ */
+ private String getMaximumAccessibleValueFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ final Number value = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Number call() throws Exception {
+ AccessibleValue av = ac.getAccessibleValue();
+ if (av == null) return null;
+ return av.getMaximumAccessibleValue();
+ }
+ }, ac);
+ if (value != null) {
+ String s = value.toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getMaximumAccessibleValueFromContext; ac = null");
+ }
+ return null;
+ }
+
+ /**
+ * return the AccessibleValue minimum value from an AccessibleContext
+ * returned using a String 'cause the value is a java Number
+ *
+ */
+ private String getMinimumAccessibleValueFromContext(final AccessibleContext ac) {
+ if (ac != null) {
+ final Number value = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Number call() throws Exception {
+ AccessibleValue av = ac.getAccessibleValue();
+ if (av == null) return null;
+ return av.getMinimumAccessibleValue();
+ }
+ }, ac);
+ if (value != null) {
+ String s = value.toString();
+ if (s != null) {
+ references.increment(s);
+ return s;
+ }
+ }
+ } else {
+ debugString("getMinimumAccessibleValueFromContext; ac = null");
+ }
+ return null;
+ }
+
+
+ /* ===== AccessibleSelection methods ===== */
+
+ /**
+ * add to the AccessibleSelection of an AccessibleContext child i
+ *
+ */
+ private void addAccessibleSelectionFromContext(final AccessibleContext ac, final int i) {
+ try {
+ InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Object call() throws Exception {
+ if (ac != null) {
+ AccessibleSelection as = ac.getAccessibleSelection();
+ if (as != null) {
+ as.addAccessibleSelection(i);
+ }
+ }
+ return null;
+ }
+ }, ac);
+ } catch(Exception e){}
+ }
+
+ /**
+ * clear all of the AccessibleSelection of an AccessibleContex
+ *
+ */
+ private void clearAccessibleSelectionFromContext(final AccessibleContext ac) {
+ try {
+ InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Object call() throws Exception {
+ AccessibleSelection as = ac.getAccessibleSelection();
+ if (as != null) {
+ as.clearAccessibleSelection();
+ }
+ return null;
+ }
+ }, ac);
+ } catch(Exception e){}
+
+ }
+
+ /**
+ * get the AccessibleContext of the i-th AccessibleSelection of an AccessibleContext
+ *
+ */
+ private AccessibleContext getAccessibleSelectionFromContext(final AccessibleContext ac, final int i) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ if (ac != null) {
+ AccessibleSelection as = ac.getAccessibleSelection();
+ if (as != null) {
+ Accessible a = as.getAccessibleSelection(i);
+ if (a == null)
+ return null;
+ else
+ return a.getAccessibleContext();
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * get number of things selected in the AccessibleSelection of an AccessibleContext
+ *
+ */
+ private int getAccessibleSelectionCountFromContext(final AccessibleContext ac) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ if (ac != null) {
+ AccessibleSelection as = ac.getAccessibleSelection();
+ if (as != null) {
+ return as.getAccessibleSelectionCount();
+ }
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /**
+ * return true if the i-th child of the AccessibleSelection of an AccessibleContext is selected
+ *
+ */
+ private boolean isAccessibleChildSelectedFromContext(final AccessibleContext ac, final int i) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ if (ac != null) {
+ AccessibleSelection as = ac.getAccessibleSelection();
+ if (as != null) {
+ return as.isAccessibleChildSelected(i);
+ }
+ }
+ return false;
+ }
+ }, ac);
+ }
+
+ /**
+ * remove the i-th child from the AccessibleSelection of an AccessibleContext
+ *
+ */
+ private void removeAccessibleSelectionFromContext(final AccessibleContext ac, final int i) {
+ InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Object call() throws Exception {
+ if (ac != null) {
+ AccessibleSelection as = ac.getAccessibleSelection();
+ if (as != null) {
+ as.removeAccessibleSelection(i);
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * select all (if possible) of the children of the AccessibleSelection of an AccessibleContext
+ *
+ */
+ private void selectAllAccessibleSelectionFromContext(final AccessibleContext ac) {
+ InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Object call() throws Exception {
+ if (ac != null) {
+ AccessibleSelection as = ac.getAccessibleSelection();
+ if (as != null) {
+ as.selectAllAccessibleSelection();
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ // ======== AccessibleTable ========
+
+ ConcurrentHashMap hashtab = new ConcurrentHashMap<>();
+
+ /**
+ * returns the AccessibleTable for an AccessibleContext
+ */
+ private AccessibleTable getAccessibleTableFromContext(final AccessibleContext ac) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleTable call() throws Exception {
+ if (ac != null) {
+ AccessibleTable at = ac.getAccessibleTable();
+ if (at != null) {
+ AccessBridge.this.hashtab.put(at, ac);
+ return at;
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+
+ /*
+ * returns the AccessibleContext that contains an AccessibleTable
+ */
+ private AccessibleContext getContextFromAccessibleTable(AccessibleTable at) {
+ return hashtab.get(at);
+ }
+
+ /*
+ * returns the row count for an AccessibleTable
+ */
+ private int getAccessibleTableRowCount(final AccessibleContext ac) {
+ debugString("##### getAccessibleTableRowCount");
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ if (ac != null) {
+ AccessibleTable at = ac.getAccessibleTable();
+ if (at != null) {
+ return at.getAccessibleRowCount();
+ }
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /*
+ * returns the column count for an AccessibleTable
+ */
+ private int getAccessibleTableColumnCount(final AccessibleContext ac) {
+ debugString("##### getAccessibleTableColumnCount");
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ if (ac != null) {
+ AccessibleTable at = ac.getAccessibleTable();
+ if (at != null) {
+ return at.getAccessibleColumnCount();
+ }
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /*
+ * returns the AccessibleContext for an AccessibleTable cell
+ */
+ private AccessibleContext getAccessibleTableCellAccessibleContext(final AccessibleTable at,
+ final int row, final int column) {
+ debugString("getAccessibleTableCellAccessibleContext: at = "+at.getClass());
+ if (at == null) return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ if (!(at instanceof AccessibleContext)) {
+ Accessible a = at.getAccessibleAt(row, column);
+ if (a != null) {
+ return a.getAccessibleContext();
+ }
+ } else {
+ // work-around for AccessibleJTable.getCurrentAccessibleContext returning
+ // wrong renderer component when cell contains more than one component
+ AccessibleContext ac = (AccessibleContext) at;
+ Accessible parent = ac.getAccessibleParent();
+ if (parent != null) {
+ int indexInParent = ac.getAccessibleIndexInParent();
+ Accessible child =
+ parent.getAccessibleContext().getAccessibleChild(indexInParent);
+ if (child instanceof JTable) {
+ JTable table = (JTable) child;
+
+ TableCellRenderer renderer = table.getCellRenderer(row, column);
+ if (renderer == null) {
+ Class> columnClass = table.getColumnClass(column);
+ renderer = table.getDefaultRenderer(columnClass);
+ }
+ Component component =
+ renderer.getTableCellRendererComponent(table, table.getValueAt(row, column),
+ false, false, row, column);
+ if (component instanceof Accessible) {
+ return component.getAccessibleContext();
+ }
+ }
+ }
+ }
+ return null;
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+
+ /*
+ * returns the index of a cell at a given row and column in an AccessibleTable
+ */
+ private int getAccessibleTableCellIndex(final AccessibleTable at, int row, int column) {
+ debugString("##### getAccessibleTableCellIndex: at="+at);
+ if (at != null) {
+ int cellIndex = row *
+ InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return at.getAccessibleColumnCount();
+ }
+ }, getContextFromAccessibleTable(at)) +
+ column;
+ debugString(" ##### getAccessibleTableCellIndex="+cellIndex);
+ return cellIndex;
+ }
+ debugString(" ##### getAccessibleTableCellIndex FAILED");
+ return -1;
+ }
+
+ /*
+ * returns the row extent of a cell at a given row and column in an AccessibleTable
+ */
+ private int getAccessibleTableCellRowExtent(final AccessibleTable at, final int row, final int column) {
+ debugString("##### getAccessibleTableCellRowExtent");
+ if (at != null) {
+ int rowExtent = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return at.getAccessibleRowExtentAt(row, column);
+ }
+ },
+ getContextFromAccessibleTable(at));
+ debugString(" ##### getAccessibleTableCellRowExtent="+rowExtent);
+ return rowExtent;
+ }
+ debugString(" ##### getAccessibleTableCellRowExtent FAILED");
+ return -1;
+ }
+
+ /*
+ * returns the column extent of a cell at a given row and column in an AccessibleTable
+ */
+ private int getAccessibleTableCellColumnExtent(final AccessibleTable at, final int row, final int column) {
+ debugString("##### getAccessibleTableCellColumnExtent");
+ if (at != null) {
+ int columnExtent = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return at.getAccessibleColumnExtentAt(row, column);
+ }
+ },
+ getContextFromAccessibleTable(at));
+ debugString(" ##### getAccessibleTableCellColumnExtent="+columnExtent);
+ return columnExtent;
+ }
+ debugString(" ##### getAccessibleTableCellColumnExtent FAILED");
+ return -1;
+ }
+
+ /*
+ * returns whether a cell is selected at a given row and column in an AccessibleTable
+ */
+ private boolean isAccessibleTableCellSelected(final AccessibleTable at, final int row,
+ final int column) {
+ debugString("##### isAccessibleTableCellSelected: ["+row+"]["+column+"]");
+ if (at == null)
+ return false;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ boolean isSelected = false;
+ Accessible a = at.getAccessibleAt(row, column);
+ if (a != null) {
+ AccessibleContext ac = a.getAccessibleContext();
+ if (ac == null)
+ return false;
+ AccessibleStateSet as = ac.getAccessibleStateSet();
+ if (as != null) {
+ isSelected = as.contains(AccessibleState.SELECTED);
+ }
+ }
+ return isSelected;
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+
+ /*
+ * returns an AccessibleTable that represents the row header in an
+ * AccessibleTable
+ */
+ private AccessibleTable getAccessibleTableRowHeader(final AccessibleContext ac) {
+ debugString(" ##### getAccessibleTableRowHeader called");
+ AccessibleTable at = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleTable call() throws Exception {
+ if (ac != null) {
+ AccessibleTable at = ac.getAccessibleTable();
+ if (at != null) {
+ return at.getAccessibleRowHeader();
+ }
+ }
+ return null;
+ }
+ }, ac);
+ if (at != null) {
+ hashtab.put(at, ac);
+ }
+ return at;
+ }
+
+ /*
+ * returns an AccessibleTable that represents the column header in an
+ * AccessibleTable
+ */
+ private AccessibleTable getAccessibleTableColumnHeader(final AccessibleContext ac) {
+ debugString("##### getAccessibleTableColumnHeader");
+ if (ac == null)
+ return null;
+ AccessibleTable at = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleTable call() throws Exception {
+ // workaround for getAccessibleColumnHeader NPE
+ // when the table header is null
+ Accessible parent = ac.getAccessibleParent();
+ if (parent != null) {
+ int indexInParent = ac.getAccessibleIndexInParent();
+ Accessible child =
+ parent.getAccessibleContext().getAccessibleChild(indexInParent);
+ if (child instanceof JTable) {
+ JTable table = (JTable) child;
+ if (table.getTableHeader() == null) {
+ return null;
+ }
+ }
+ }
+ AccessibleTable at = ac.getAccessibleTable();
+ if (at != null) {
+ return at.getAccessibleColumnHeader();
+ }
+ return null;
+ }
+ }, ac);
+ if (at != null) {
+ hashtab.put(at, ac);
+ }
+ return at;
+ }
+
+ /*
+ * returns the number of row headers in an AccessibleTable that represents
+ * the row header in an AccessibleTable
+ */
+ private int getAccessibleTableRowHeaderRowCount(AccessibleContext ac) {
+
+ debugString(" ##### getAccessibleTableRowHeaderRowCount called");
+ if (ac != null) {
+ final AccessibleTable atRowHeader = getAccessibleTableRowHeader(ac);
+ if (atRowHeader != null) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ if (atRowHeader != null) {
+ return atRowHeader.getAccessibleRowCount();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+ }
+ return -1;
+ }
+
+ /*
+ * returns the number of column headers in an AccessibleTable that represents
+ * the row header in an AccessibleTable
+ */
+ private int getAccessibleTableRowHeaderColumnCount(AccessibleContext ac) {
+ debugString(" ##### getAccessibleTableRowHeaderColumnCount called");
+ if (ac != null) {
+ final AccessibleTable atRowHeader = getAccessibleTableRowHeader(ac);
+ if (atRowHeader != null) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ if (atRowHeader != null) {
+ return atRowHeader.getAccessibleColumnCount();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+ }
+ debugString(" ##### getAccessibleTableRowHeaderColumnCount FAILED");
+ return -1;
+ }
+
+ /*
+ * returns the number of row headers in an AccessibleTable that represents
+ * the column header in an AccessibleTable
+ */
+ private int getAccessibleTableColumnHeaderRowCount(AccessibleContext ac) {
+
+ debugString("##### getAccessibleTableColumnHeaderRowCount");
+ if (ac != null) {
+ final AccessibleTable atColumnHeader = getAccessibleTableColumnHeader(ac);
+ if (atColumnHeader != null) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ if (atColumnHeader != null) {
+ return atColumnHeader.getAccessibleRowCount();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+ }
+ debugString(" ##### getAccessibleTableColumnHeaderRowCount FAILED");
+ return -1;
+ }
+
+ /*
+ * returns the number of column headers in an AccessibleTable that represents
+ * the column header in an AccessibleTable
+ */
+ private int getAccessibleTableColumnHeaderColumnCount(AccessibleContext ac) {
+
+ debugString("##### getAccessibleTableColumnHeaderColumnCount");
+ if (ac != null) {
+ final AccessibleTable atColumnHeader = getAccessibleTableColumnHeader(ac);
+ if (atColumnHeader != null) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ if (atColumnHeader != null) {
+ return atColumnHeader.getAccessibleColumnCount();
+ }
+ return -1;
+ }
+ }, ac);
+ }
+ }
+ debugString(" ##### getAccessibleTableColumnHeaderColumnCount FAILED");
+ return -1;
+ }
+
+ /*
+ * returns the description of a row header in an AccessibleTable
+ */
+ private AccessibleContext getAccessibleTableRowDescription(final AccessibleTable table,
+ final int row) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ if (table != null) {
+ Accessible a = table.getAccessibleRowDescription(row);
+ if (a != null) {
+ return a.getAccessibleContext();
+ }
+ }
+ return null;
+ }
+ }, getContextFromAccessibleTable(table));
+ }
+
+ /*
+ * returns the description of a column header in an AccessibleTable
+ */
+ private AccessibleContext getAccessibleTableColumnDescription(final AccessibleTable at,
+ final int column) {
+ if (at == null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = at.getAccessibleColumnDescription(column);
+ if (a != null) {
+ return a.getAccessibleContext();
+ }
+ return null;
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+
+ /*
+ * returns the number of rows selected in an AccessibleTable
+ */
+ private int getAccessibleTableRowSelectionCount(final AccessibleTable at) {
+ if (at != null) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ int[] selections = at.getSelectedAccessibleRows();
+ if (selections != null)
+ return selections.length;
+ else
+ return -1;
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+ return -1;
+ }
+
+ /*
+ * returns the row number of the i-th selected row in an AccessibleTable
+ */
+ private int getAccessibleTableRowSelections(final AccessibleTable at, final int i) {
+ if (at != null) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ int[] selections = at.getSelectedAccessibleRows();
+ if (selections.length > i) {
+ return selections[i];
+ }
+ return -1;
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+ return -1;
+ }
+
+ /*
+ * returns whether a row is selected in an AccessibleTable
+ */
+ private boolean isAccessibleTableRowSelected(final AccessibleTable at,
+ final int row) {
+ if (at == null)
+ return false;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ return at.isAccessibleRowSelected(row);
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+
+ /*
+ * returns whether a column is selected in an AccessibleTable
+ */
+ private boolean isAccessibleTableColumnSelected(final AccessibleTable at,
+ final int column) {
+ if (at == null)
+ return false;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ return at.isAccessibleColumnSelected(column);
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+
+ /*
+ * returns the number of columns selected in an AccessibleTable
+ */
+ private int getAccessibleTableColumnSelectionCount(final AccessibleTable at) {
+ if (at == null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ int[] selections = at.getSelectedAccessibleColumns();
+ if (selections != null)
+ return selections.length;
+ else
+ return -1;
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+
+ /*
+ * returns the row number of the i-th selected row in an AccessibleTable
+ */
+ private int getAccessibleTableColumnSelections(final AccessibleTable at, final int i) {
+ if (at == null)
+ return -1;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ int[] selections = at.getSelectedAccessibleColumns();
+ if (selections != null && selections.length > i) {
+ return selections[i];
+ }
+ return -1;
+ }
+ }, getContextFromAccessibleTable(at));
+ }
+
+ /* ===== AccessibleExtendedTable (since 1.4) ===== */
+
+ /*
+ * returns the row number for a cell at a given index in an AccessibleTable
+ */
+ private int getAccessibleTableRow(final AccessibleTable at, int index) {
+ if (at == null)
+ return -1;
+ int colCount=InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return at.getAccessibleColumnCount();
+ }
+ }, getContextFromAccessibleTable(at));
+ return index / colCount;
+ }
+
+ /*
+ * returns the column number for a cell at a given index in an AccessibleTable
+ */
+ private int getAccessibleTableColumn(final AccessibleTable at, int index) {
+ if (at == null)
+ return -1;
+ int colCount=InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return at.getAccessibleColumnCount();
+ }
+ }, getContextFromAccessibleTable(at));
+ return index % colCount;
+ }
+
+ /*
+ * returns the index for a cell at a given row and column in an
+ * AccessibleTable
+ */
+ private int getAccessibleTableIndex(final AccessibleTable at, int row, int column) {
+ if (at == null)
+ return -1;
+ int colCount = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return at.getAccessibleColumnCount();
+ }
+ }, getContextFromAccessibleTable(at));
+ return row * colCount + column;
+ }
+
+ // ===== AccessibleRelationSet =====
+
+ /*
+ * returns the number of relations in the AccessibleContext's
+ * AccessibleRelationSet
+ */
+ private int getAccessibleRelationCount(final AccessibleContext ac) {
+ {
+ if (ac != null) {
+ AccessibleRelationSet ars = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleRelationSet call() throws Exception {
+ return ac.getAccessibleRelationSet();
+ }
+ }, ac);
+ if (ars != null)
+ return ars.size();
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * returns the ith relation key in the AccessibleContext's
+ * AccessibleRelationSet
+ */
+ private String getAccessibleRelationKey(final AccessibleContext ac, final int i) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ if (ac != null) {
+ AccessibleRelationSet ars = ac.getAccessibleRelationSet();
+ if (ars != null) {
+ AccessibleRelation[] relations = ars.toArray();
+ if (relations != null && i >= 0 && i < relations.length) {
+ return relations[i].getKey();
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /*
+ * returns the number of targets in a relation in the AccessibleContext's
+ * AccessibleRelationSet
+ */
+ private int getAccessibleRelationTargetCount(final AccessibleContext ac, final int i) {
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ if (ac != null) {
+ AccessibleRelationSet ars = ac.getAccessibleRelationSet();
+ if (ars != null) {
+ AccessibleRelation[] relations = ars.toArray();
+ if (relations != null && i >= 0 && i < relations.length) {
+ Object[] targets = relations[i].getTarget();
+ return targets.length;
+ }
+ }
+ }
+ return -1;
+ }
+ }, ac);
+ }
+
+ /*
+ * returns the jth target in the ith relation in the AccessibleContext's
+ * AccessibleRelationSet
+ */
+ private AccessibleContext getAccessibleRelationTarget(final AccessibleContext ac,
+ final int i, final int j) {
+ debugString("***** getAccessibleRelationTarget");
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ if (ac != null) {
+ AccessibleRelationSet ars = ac.getAccessibleRelationSet();
+ if (ars != null) {
+ AccessibleRelation[] relations = ars.toArray();
+ if (relations != null && i >= 0 && i < relations.length) {
+ Object[] targets = relations[i].getTarget();
+ if (targets != null && j >= 0 & j < targets.length) {
+ Object o = targets[j];
+ if (o instanceof Accessible) {
+ return ((Accessible) o).getAccessibleContext();
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ // ========= AccessibleHypertext =========
+
+ private Map hyperTextContextMap = new WeakHashMap<>();
+ private Map hyperLinkContextMap = new WeakHashMap<>();
+
+ /*
+ * Returns the AccessibleHypertext
+ */
+ private AccessibleHypertext getAccessibleHypertext(final AccessibleContext ac) {
+ debugString("getAccessibleHyperlink");
+ if (ac==null)
+ return null;
+ AccessibleHypertext hypertext = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleHypertext call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (!(at instanceof AccessibleHypertext)) {
+ return null;
+ }
+ return ((AccessibleHypertext) at);
+ }
+ }, ac);
+ hyperTextContextMap.put(hypertext, ac);
+ return hypertext;
+ }
+
+ /*
+ * Returns the number of AccessibleHyperlinks
+ */
+ private int getAccessibleHyperlinkCount(AccessibleContext ac) {
+ debugString("getAccessibleHyperlinkCount");
+ if (ac == null) {
+ return 0;
+ }
+ final AccessibleHypertext hypertext = getAccessibleHypertext(ac);
+ if (hypertext == null) {
+ return 0;
+ }
+ //return hypertext.getLinkCount();
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return hypertext.getLinkCount();
+ }
+ }, ac);
+ }
+
+ /*
+ * Returns the hyperlink at the specified index
+ */
+ private AccessibleHyperlink getAccessibleHyperlink(final AccessibleHypertext hypertext, final int i) {
+ debugString("getAccessibleHyperlink");
+ if (hypertext == null) {
+ return null;
+ }
+ AccessibleContext ac = hyperTextContextMap.get(hypertext);
+ if ( i < 0 || i >=
+ InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return hypertext.getLinkCount();
+ }
+ }, ac) ) {
+ return null;
+ }
+ AccessibleHyperlink acLink = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleHyperlink call() throws Exception {
+ AccessibleHyperlink link = hypertext.getLink(i);
+ if (link == null || (!link.isValid())) {
+ return null;
+ }
+ return link;
+ }
+ }, ac);
+ hyperLinkContextMap.put(acLink, ac);
+ return acLink;
+ }
+
+ /*
+ * Returns the hyperlink object description
+ */
+ private String getAccessibleHyperlinkText(final AccessibleHyperlink link) {
+ debugString("getAccessibleHyperlinkText");
+ if (link == null) {
+ return null;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ Object o = link.getAccessibleActionDescription(0);
+ if (o != null) {
+ return o.toString();
+ }
+ return null;
+ }
+ }, hyperLinkContextMap.get(link));
+ }
+
+ /*
+ * Returns the hyperlink URL
+ */
+ private String getAccessibleHyperlinkURL(final AccessibleHyperlink link) {
+ debugString("getAccessibleHyperlinkURL");
+ if (link == null) {
+ return null;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ Object o = link.getAccessibleActionObject(0);
+ if (o != null) {
+ return o.toString();
+ } else {
+ return null;
+ }
+ }
+ }, hyperLinkContextMap.get(link));
+ }
+
+ /*
+ * Returns the start index of the hyperlink text
+ */
+ private int getAccessibleHyperlinkStartIndex(final AccessibleHyperlink link) {
+ debugString("getAccessibleHyperlinkStartIndex");
+ if (link == null) {
+ return -1;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return link.getStartIndex();
+ }
+ }, hyperLinkContextMap.get(link));
+ }
+
+ /*
+ * Returns the end index of the hyperlink text
+ */
+ private int getAccessibleHyperlinkEndIndex(final AccessibleHyperlink link) {
+ debugString("getAccessibleHyperlinkEndIndex");
+ if (link == null) {
+ return -1;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return link.getEndIndex();
+ }
+ }, hyperLinkContextMap.get(link));
+ }
+
+ /*
+ * Returns the index into an array of hyperlinks that
+ * is associated with this character index, or -1 if there
+ * is no hyperlink associated with this index.
+ */
+ private int getAccessibleHypertextLinkIndex(final AccessibleHypertext hypertext, final int charIndex) {
+ debugString("getAccessibleHypertextLinkIndex: charIndex = "+charIndex);
+ if (hypertext == null) {
+ return -1;
+ }
+ int linkIndex = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return hypertext.getLinkIndex(charIndex);
+ }
+ }, hyperTextContextMap.get(hypertext));
+ debugString("getAccessibleHypertextLinkIndex returning "+linkIndex);
+ return linkIndex;
+ }
+
+ /*
+ * Actives the hyperlink
+ */
+ private boolean activateAccessibleHyperlink(final AccessibleContext ac,
+ final AccessibleHyperlink link) {
+ //debugString("activateAccessibleHyperlink: link = "+link.getClass());
+ if (link == null) {
+ return false;
+ }
+ boolean retval = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ return link.doAccessibleAction(0);
+ }
+ }, ac);
+ debugString("activateAccessibleHyperlink: returning = "+retval);
+ return retval;
+ }
+
+
+ // ============ AccessibleKeyBinding =============
+
+ /*
+ * returns the component mnemonic
+ */
+ private KeyStroke getMnemonic(final AccessibleContext ac) {
+ if (ac == null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public KeyStroke call() throws Exception {
+ AccessibleComponent comp = ac.getAccessibleComponent();
+ if (!(comp instanceof AccessibleExtendedComponent)) {
+ return null;
+ }
+ AccessibleExtendedComponent aec = (AccessibleExtendedComponent) comp;
+ if (aec != null) {
+ AccessibleKeyBinding akb = aec.getAccessibleKeyBinding();
+ if (akb != null) {
+ Object o = akb.getAccessibleKeyBinding(0);
+ if (o instanceof KeyStroke) {
+ return (KeyStroke) o;
+ }
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /*
+ * returns the JMenuItem accelerator
+ */
+ private KeyStroke getAccelerator(final AccessibleContext ac) {
+ // workaround for getAccessibleKeyBinding not returning the
+ // JMenuItem accelerator
+ if (ac == null)
+ return null;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public KeyStroke call() throws Exception {
+ Accessible parent = ac.getAccessibleParent();
+ if (parent instanceof Accessible) {
+ int indexInParent = ac.getAccessibleIndexInParent();
+ Accessible child =
+ parent.getAccessibleContext().getAccessibleChild(indexInParent);
+ if (child instanceof JMenuItem) {
+ JMenuItem menuItem = (JMenuItem) child;
+ if (menuItem == null)
+ return null;
+ KeyStroke keyStroke = menuItem.getAccelerator();
+ return keyStroke;
+ }
+ }
+ return null;
+ }
+ }, ac);
+ }
+
+ /*
+ * returns 1-24 to indicate which F key is being used for a shortcut or 0 otherwise
+ */
+ private int fKeyNumber(KeyStroke keyStroke) {
+ if (keyStroke == null)
+ return 0;
+ int fKey = 0;
+ String keyText = KeyEvent.getKeyText(keyStroke.getKeyCode());
+ if (keyText != null && (keyText.length() == 2 || keyText.length() == 3)) {
+ String prefix = keyText.substring(0, 1);
+ if (prefix.equals("F")) {
+ try {
+ int suffix = Integer.parseInt(keyText.substring(1));
+ if (suffix >= 1 && suffix <= 24) {
+ fKey = suffix;
+ }
+ } catch (Exception e) { // ignore NumberFormatException
+ }
+ }
+ }
+ return fKey;
+ }
+
+ /*
+ * returns one of several important control characters or 0 otherwise
+ */
+ private int controlCode(KeyStroke keyStroke) {
+ if (keyStroke == null)
+ return 0;
+ int code = keyStroke.getKeyCode();
+ switch (code) {
+ case KeyEvent.VK_BACK_SPACE:
+ case KeyEvent.VK_DELETE:
+ case KeyEvent.VK_DOWN:
+ case KeyEvent.VK_END:
+ case KeyEvent.VK_HOME:
+ case KeyEvent.VK_INSERT:
+ case KeyEvent.VK_KP_DOWN:
+ case KeyEvent.VK_KP_LEFT:
+ case KeyEvent.VK_KP_RIGHT:
+ case KeyEvent.VK_KP_UP:
+ case KeyEvent.VK_LEFT:
+ case KeyEvent.VK_PAGE_DOWN:
+ case KeyEvent.VK_PAGE_UP:
+ case KeyEvent.VK_RIGHT:
+ case KeyEvent.VK_UP:
+ break;
+ default:
+ code = 0;
+ break;
+ }
+ return code;
+ }
+
+ /*
+ * returns the KeyStoke character
+ */
+ private char getKeyChar(KeyStroke keyStroke) {
+ // If the shortcut is an FKey return 1-24
+ if (keyStroke == null)
+ return 0;
+ int fKey = fKeyNumber(keyStroke);
+ if (fKey != 0) {
+ // return 0x00000001 through 0x00000018
+ debugString(" Shortcut is: F" + fKey);
+ return (char)fKey;
+ }
+ // If the accelerator is a control character, return it
+ int keyCode = controlCode(keyStroke);
+ if (keyCode != 0) {
+ debugString(" Shortcut is control character: " + Integer.toHexString(keyCode));
+ return (char)keyCode;
+ }
+ String keyText = KeyEvent.getKeyText(keyStroke.getKeyCode());
+ debugString(" Shortcut is: " + keyText);
+ if (keyText != null || keyText.length() > 0) {
+ CharSequence seq = keyText.subSequence(0, 1);
+ if (seq != null || seq.length() > 0) {
+ return seq.charAt(0);
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * returns the KeyStroke modifiers as an int
+ */
+ private int getModifiers(KeyStroke keyStroke) {
+ if (keyStroke == null)
+ return 0;
+ debugString("In AccessBridge.getModifiers");
+ // modifiers is a bit strip where bits 0-7 indicate a traditional modifier
+ // such as Ctrl/Alt/Shift, bit 8 indicates an F key shortcut, and bit 9 indicates
+ // a control code shortcut such as the delete key.
+
+ int modifiers = 0;
+ // Is the shortcut an FKey?
+ if (fKeyNumber(keyStroke) != 0) {
+ modifiers |= 1 << 8;
+ }
+ // Is the shortcut a control code?
+ if (controlCode(keyStroke) != 0) {
+ modifiers |= 1 << 9;
+ }
+ // The following is needed in order to handle translated modifiers.
+ // getKeyModifiersText doesn't work because for example in German Strg is
+ // returned for Ctrl.
+
+ // There can be more than one modifier, e.g. if the modifier is ctrl + shift + B
+ // the toString text is "shift ctrl pressed B". Need to parse through that.
+ StringTokenizer st = new StringTokenizer(keyStroke.toString());
+ while (st.hasMoreTokens()) {
+ String text = st.nextToken();
+ // Meta+Ctrl+Alt+Shift
+ // 0-3 are shift, ctrl, meta, alt
+ // 4-7 are for Solaris workstations (though not being used)
+ if (text.startsWith("met")) {
+ debugString(" found meta");
+ modifiers |= ActionEvent.META_MASK;
+ }
+ if (text.startsWith("ctr")) {
+ debugString(" found ctrl");
+ modifiers |= ActionEvent.CTRL_MASK;
+ }
+ if (text.startsWith("alt")) {
+ debugString(" found alt");
+ modifiers |= ActionEvent.ALT_MASK;
+ }
+ if (text.startsWith("shi")) {
+ debugString(" found shift");
+ modifiers |= ActionEvent.SHIFT_MASK;
+ }
+ }
+ debugString(" returning modifiers: 0x" + Integer.toHexString(modifiers));
+ return modifiers;
+ }
+
+ /*
+ * returns the number of key bindings associated with this context
+ */
+ private int getAccessibleKeyBindingsCount(AccessibleContext ac) {
+ if (ac == null)
+ return 0;
+ int count = 0;
+
+ if (getMnemonic(ac) != null) {
+ count++;
+ }
+ if (getAccelerator(ac) != null) {
+ count++;
+ }
+ return count;
+ }
+
+ /*
+ * returns the key binding character at the specified index
+ */
+ private char getAccessibleKeyBindingChar(AccessibleContext ac, int index) {
+ if (ac == null)
+ return 0;
+ if((index == 0) && getMnemonic(ac)==null) {// special case when there is no mnemonic
+ KeyStroke keyStroke = getAccelerator(ac);
+ if (keyStroke != null) {
+ return getKeyChar(keyStroke);
+ }
+ }
+ if (index == 0) { // mnemonic
+ KeyStroke keyStroke = getMnemonic(ac);
+ if (keyStroke != null) {
+ return getKeyChar(keyStroke);
+ }
+ } else if (index == 1) { // accelerator
+ KeyStroke keyStroke = getAccelerator(ac);
+ if (keyStroke != null) {
+ return getKeyChar(keyStroke);
+ }
+ }
+ return 0;
+ }
+
+ /*
+ * returns the key binding modifiers at the specified index
+ */
+ private int getAccessibleKeyBindingModifiers(AccessibleContext ac, int index) {
+ if (ac == null)
+ return 0;
+ if((index == 0) && getMnemonic(ac)==null) {// special case when there is no mnemonic
+ KeyStroke keyStroke = getAccelerator(ac);
+ if (keyStroke != null) {
+ return getModifiers(keyStroke);
+ }
+ }
+ if (index == 0) { // mnemonic
+ KeyStroke keyStroke = getMnemonic(ac);
+ if (keyStroke != null) {
+ return getModifiers(keyStroke);
+ }
+ } else if (index == 1) { // accelerator
+ KeyStroke keyStroke = getAccelerator(ac);
+ if (keyStroke != null) {
+ return getModifiers(keyStroke);
+ }
+ }
+ return 0;
+ }
+
+ // ========== AccessibleIcon ============
+
+ /*
+ * return the number of icons associated with this context
+ */
+ private int getAccessibleIconsCount(final AccessibleContext ac) {
+ debugString("getAccessibleIconsCount");
+ if (ac == null) {
+ return 0;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleIcon[] ai = ac.getAccessibleIcon();
+ if (ai == null) {
+ return 0;
+ }
+ return ai.length;
+ }
+ }, ac);
+ }
+
+ /*
+ * return icon description at the specified index
+ */
+ private String getAccessibleIconDescription(final AccessibleContext ac, final int index) {
+ debugString("getAccessibleIconDescription: index = "+index);
+ if (ac == null) {
+ return null;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleIcon[] ai = ac.getAccessibleIcon();
+ if (ai == null || index < 0 || index >= ai.length) {
+ return null;
+ }
+ return ai[index].getAccessibleIconDescription();
+ }
+ }, ac);
+ }
+
+ /*
+ * return icon height at the specified index
+ */
+ private int getAccessibleIconHeight(final AccessibleContext ac, final int index) {
+ debugString("getAccessibleIconHeight: index = "+index);
+ if (ac == null) {
+ return 0;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleIcon[] ai = ac.getAccessibleIcon();
+ if (ai == null || index < 0 || index >= ai.length) {
+ return 0;
+ }
+ return ai[index].getAccessibleIconHeight();
+ }
+ }, ac);
+ }
+
+ /*
+ * return icon width at the specified index
+ */
+ private int getAccessibleIconWidth(final AccessibleContext ac, final int index) {
+ debugString("getAccessibleIconWidth: index = "+index);
+ if (ac == null) {
+ return 0;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleIcon[] ai = ac.getAccessibleIcon();
+ if (ai == null || index < 0 || index >= ai.length) {
+ return 0;
+ }
+ return ai[index].getAccessibleIconWidth();
+ }
+ }, ac);
+ }
+
+ // ========= AccessibleAction ===========
+
+ /*
+ * return the number of icons associated with this context
+ */
+ private int getAccessibleActionsCount(final AccessibleContext ac) {
+ debugString("getAccessibleActionsCount");
+ if (ac == null) {
+ return 0;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ AccessibleAction aa = ac.getAccessibleAction();
+ if (aa == null)
+ return 0;
+ return aa.getAccessibleActionCount();
+ }
+ }, ac);
+ }
+
+ /*
+ * return icon description at the specified index
+ */
+ private String getAccessibleActionName(final AccessibleContext ac, final int index) {
+ debugString("getAccessibleActionName: index = "+index);
+ if (ac == null) {
+ return null;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ AccessibleAction aa = ac.getAccessibleAction();
+ if (aa == null) {
+ return null;
+ }
+ return aa.getAccessibleActionDescription(index);
+ }
+ }, ac);
+ }
+ /*
+ * return icon description at the specified index
+ */
+ private boolean doAccessibleActions(final AccessibleContext ac, final String name) {
+ debugString("doAccessibleActions: action name = "+name);
+ if (ac == null || name == null) {
+ return false;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ AccessibleAction aa = ac.getAccessibleAction();
+ if (aa == null) {
+ return false;
+ }
+ int index = -1;
+ int numActions = aa.getAccessibleActionCount();
+ for (int i = 0; i < numActions; i++) {
+ String actionName = aa.getAccessibleActionDescription(i);
+ if (name.equals(actionName)) {
+ index = i;
+ break;
+ }
+ }
+ if (index == -1) {
+ return false;
+ }
+ boolean retval = aa.doAccessibleAction(index);
+ return retval;
+ }
+ }, ac);
+ }
+
+ /* ===== AT utility methods ===== */
+
+ /**
+ * Sets the contents of an AccessibleContext that
+ * implements AccessibleEditableText with the
+ * specified text string.
+ * Returns whether successful.
+ */
+ private boolean setTextContents(final AccessibleContext ac, final String text) {
+ debugString("setTextContents: ac = "+ac+"; text = "+text);
+
+ if (! (ac instanceof AccessibleEditableText)) {
+ debugString(" ac not instanceof AccessibleEditableText: "+ac);
+ return false;
+ }
+ if (text == null) {
+ debugString(" text is null");
+ return false;
+ }
+
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ // check whether the text field is editable
+ AccessibleStateSet ass = ac.getAccessibleStateSet();
+ if (!ass.contains(AccessibleState.ENABLED)) {
+ return false;
+ }
+ ((AccessibleEditableText) ac).setTextContents(text);
+ return true;
+ }
+ }, ac);
+ }
+
+ /**
+ * Returns the Accessible Context of an Internal Frame object that is
+ * the ancestor of a given object. If the object is an Internal Frame
+ * object or an Internal Frame ancestor object was found, returns the
+ * object's AccessibleContext.
+ * If there is no ancestor object that has an Accessible Role of
+ * Internal Frame, returns (AccessibleContext)0.
+ */
+ private AccessibleContext getInternalFrame (AccessibleContext ac) {
+ return getParentWithRole(ac, AccessibleRole.INTERNAL_FRAME.toString());
+ }
+
+ /**
+ * Returns the Accessible Context for the top level object in
+ * a Java Window. This is same Accessible Context that is obtained
+ * from GetAccessibleContextFromHWND for that window. Returns
+ * (AccessibleContext)0 on error.
+ */
+ private AccessibleContext getTopLevelObject (final AccessibleContext ac) {
+ debugString("getTopLevelObject; ac = "+ac);
+ if (ac == null) {
+ return null;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ if (ac.getAccessibleRole() == AccessibleRole.DIALOG) {
+ // return the dialog, not the parent window
+ return ac;
+ }
+
+ Accessible parent = ac.getAccessibleParent();
+ if (parent == null) {
+ return ac;
+ }
+ Accessible tmp = parent;
+ while (tmp != null && tmp.getAccessibleContext() != null) {
+ AccessibleContext ac2 = tmp.getAccessibleContext();
+ if (ac2 != null && ac2.getAccessibleRole() == AccessibleRole.DIALOG) {
+ // return the dialog, not the parent window
+ return ac2;
+ }
+ parent = tmp;
+ tmp = parent.getAccessibleContext().getAccessibleParent();
+ }
+ return parent.getAccessibleContext();
+ }
+ }, ac);
+ }
+
+ /**
+ * Returns the parent AccessibleContext that has the specified AccessibleRole.
+ * Returns null on error or if the AccessibleContext does not exist.
+ */
+ private AccessibleContext getParentWithRole (final AccessibleContext ac,
+ final String roleName) {
+ debugString("getParentWithRole; ac = "+ac);
+ debugString("role = "+roleName);
+ if (ac == null || roleName == null) {
+ return null;
+ }
+
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ AccessibleRole role = AccessBridge.this.accessibleRoleMap.get(roleName);
+ if (role == null) {
+ return ac;
+ }
+
+ Accessible parent = ac.getAccessibleParent();
+ if (parent == null && ac.getAccessibleRole() == role) {
+ return ac;
+ }
+
+ Accessible tmp = parent;
+ AccessibleContext tmp_ac = null;
+
+ while (tmp != null && (tmp_ac = tmp.getAccessibleContext()) != null) {
+ AccessibleRole ar = tmp_ac.getAccessibleRole();
+ if (ar == role) {
+ // found
+ return tmp_ac;
+ }
+ parent = tmp;
+ tmp = parent.getAccessibleContext().getAccessibleParent();
+ }
+ // not found
+ return null;
+ }
+ }, ac);
+ }
+
+ /**
+ * Returns the parent AccessibleContext that has the specified AccessibleRole.
+ * Otherwise, returns the top level object for the Java Window.
+ * Returns (AccessibleContext)0 on error.
+ */
+ private AccessibleContext getParentWithRoleElseRoot (AccessibleContext ac,
+ String roleName) {
+ AccessibleContext retval = getParentWithRole(ac, roleName);
+ if (retval == null) {
+ retval = getTopLevelObject(ac);
+ }
+ return retval;
+ }
+
+ /**
+ * Returns how deep in the object hierarchy a given object is.
+ * The top most object in the object hierarchy has an object depth of 0.
+ * Returns -1 on error.
+ */
+ private int getObjectDepth(final AccessibleContext ac) {
+ debugString("getObjectDepth: ac = "+ac);
+
+ if (ac == null) {
+ return -1;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ int count = 0;
+ Accessible parent = ac.getAccessibleParent();
+ if (parent == null) {
+ return count;
+ }
+ Accessible tmp = parent;
+ while (tmp != null && tmp.getAccessibleContext() != null) {
+ parent = tmp;
+ tmp = parent.getAccessibleContext().getAccessibleParent();
+ count++;
+ }
+ return count;
+ }
+ }, ac);
+ }
+
+ /**
+ * Returns the Accessible Context of the current ActiveDescendent of an object.
+ * Returns (AccessibleContext)0 on error.
+ */
+ private AccessibleContext getActiveDescendent (final AccessibleContext ac) {
+ debugString("getActiveDescendent: ac = "+ac);
+ if (ac == null) {
+ return null;
+ }
+ // workaround for JTree bug where the only possible active
+ // descendent is the JTree root
+ final Accessible parent = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ return ac.getAccessibleParent();
+ }
+ }, ac);
+
+ if (parent != null) {
+ Accessible child = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Accessible call() throws Exception {
+ int indexInParent = ac.getAccessibleIndexInParent();
+ return parent.getAccessibleContext().getAccessibleChild(indexInParent);
+ }
+ }, ac);
+
+ if (child instanceof JTree) {
+ // return the selected node
+ final JTree tree = (JTree)child;
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ return new AccessibleJTreeNode(tree,
+ tree.getSelectionPath(),
+ null);
+ }
+ }, child);
+ }
+ }
+
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ AccessibleSelection as = ac.getAccessibleSelection();
+ if (as == null) {
+ return null;
+ }
+ // assume single selection
+ if (as.getAccessibleSelectionCount() != 1) {
+ return null;
+ }
+ Accessible a = as.getAccessibleSelection(0);
+ if (a == null) {
+ return null;
+ }
+ return a.getAccessibleContext();
+ }
+ }, ac);
+ }
+
+
+ /**
+ * Additional methods for Teton
+ */
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm.
+ * Returns whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ private String getJAWSAccessibleName(final AccessibleContext ac) {
+ debugString("getJAWSAccessibleName");
+ if (ac == null) {
+ return null;
+ }
+ // placeholder
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return ac.getAccessibleName();
+ }
+ }, ac);
+ }
+
+ /**
+ * Request focus for a component. Returns whether successful;
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ private boolean requestFocus(final AccessibleContext ac) {
+ debugString("requestFocus");
+ if (ac == null) {
+ return false;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ AccessibleComponent acomp = ac.getAccessibleComponent();
+ if (acomp == null) {
+ return false;
+ }
+ acomp.requestFocus();
+ return ac.getAccessibleStateSet().contains(AccessibleState.FOCUSED);
+ }
+ }, ac);
+ }
+
+ /**
+ * Selects text between two indices. Selection includes the
+ * text at the start index and the text at the end index. Returns
+ * whether successful;
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ private boolean selectTextRange(final AccessibleContext ac, final int startIndex, final int endIndex) {
+ debugString("selectTextRange: start = "+startIndex+"; end = "+endIndex);
+ if (ac == null) {
+ return false;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (!(at instanceof AccessibleEditableText)) {
+ return false;
+ }
+ ((AccessibleEditableText) at).selectText(startIndex, endIndex);
+
+ boolean result = at.getSelectionStart() == startIndex &&
+ at.getSelectionEnd() == endIndex;
+ return result;
+ }
+ }, ac);
+ }
+
+ /**
+ * Set the caret to a text position. Returns whether successful;
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ private boolean setCaretPosition(final AccessibleContext ac, final int position) {
+ debugString("setCaretPosition: position = "+position);
+ if (ac == null) {
+ return false;
+ }
+ return InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ AccessibleText at = ac.getAccessibleText();
+ if (!(at instanceof AccessibleEditableText)) {
+ return false;
+ }
+ ((AccessibleEditableText) at).selectText(position, position);
+ return at.getCaretPosition() == position;
+ }
+ }, ac);
+ }
+
+ /**
+ * Gets the number of visible children of an AccessibleContext.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ private int _visibleChildrenCount;
+ private AccessibleContext _visibleChild;
+ private int _currentVisibleIndex;
+ private boolean _foundVisibleChild;
+
+ private int getVisibleChildrenCount(AccessibleContext ac) {
+ debugString("getVisibleChildrenCount");
+ if (ac == null) {
+ return -1;
+ }
+ _visibleChildrenCount = 0;
+ _getVisibleChildrenCount(ac);
+ debugString(" _visibleChildrenCount = "+_visibleChildrenCount);
+ return _visibleChildrenCount;
+ }
+
+ /*
+ * Recursively descends AccessibleContext and gets the number
+ * of visible children
+ */
+ private void _getVisibleChildrenCount(final AccessibleContext ac) {
+ if (ac == null)
+ return;
+ int numChildren = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac.getAccessibleChildrenCount();
+ }
+ }, ac);
+ for (int i = 0; i < numChildren; i++) {
+ final int idx = i;
+ final AccessibleContext ac2 = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = ac.getAccessibleChild(idx);
+ if (a != null)
+ return a.getAccessibleContext();
+ else
+ return null;
+ }
+ }, ac);
+ if ( ac2 == null ||
+ (!InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ return ac2.getAccessibleStateSet().contains(AccessibleState.SHOWING);
+ }
+ }, ac))
+ ) {
+ continue;
+ }
+ _visibleChildrenCount++;
+
+ if (InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac2.getAccessibleChildrenCount();
+ }
+ }, ac) > 0 ) {
+ _getVisibleChildrenCount(ac2);
+ }
+ }
+ }
+
+ /**
+ * Gets the visible child of an AccessibleContext at the
+ * specified index
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ private AccessibleContext getVisibleChild(AccessibleContext ac, int index) {
+ debugString("getVisibleChild: index = "+index);
+ if (ac == null) {
+ return null;
+ }
+ _visibleChild = null;
+ _currentVisibleIndex = 0;
+ _foundVisibleChild = false;
+ _getVisibleChild(ac, index);
+
+ if (_visibleChild != null) {
+ debugString( " getVisibleChild: found child = " +
+ InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public String call() throws Exception {
+ return AccessBridge.this._visibleChild.getAccessibleName();
+ }
+ }, ac) );
+ }
+ return _visibleChild;
+ }
+
+ /*
+ * Recursively searchs AccessibleContext and finds the visible component
+ * at the specified index
+ */
+ private void _getVisibleChild(final AccessibleContext ac, final int index) {
+ if (_visibleChild != null) {
+ return;
+ }
+
+ int numChildren = InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac.getAccessibleChildrenCount();
+ }
+ }, ac);
+ for (int i = 0; i < numChildren; i++) {
+ final int idx=i;
+ final AccessibleContext ac2=InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public AccessibleContext call() throws Exception {
+ Accessible a = ac.getAccessibleChild(idx);
+ if (a == null)
+ return null;
+ else
+ return a.getAccessibleContext();
+ }
+ }, ac);
+ if (ac2 == null ||
+ (!InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ return ac2.getAccessibleStateSet().contains(AccessibleState.SHOWING);
+ }
+ }, ac))) {
+ continue;
+ }
+ if (!_foundVisibleChild && _currentVisibleIndex == index) {
+ _visibleChild = ac2;
+ _foundVisibleChild = true;
+ return;
+ }
+ _currentVisibleIndex++;
+
+ if ( InvocationUtils.invokeAndWait(new Callable() {
+ @Override
+ public Integer call() throws Exception {
+ return ac2.getAccessibleChildrenCount();
+ }
+ }, ac) > 0 ) {
+ _getVisibleChild(ac2, index);
+ }
+ }
+ }
+
+
+ /* ===== Java object memory management code ===== */
+
+ /**
+ * Class to track object references to ensure the
+ * Java VM doesn't garbage collect them
+ */
+ private class ObjectReferences {
+
+ private class Reference {
+ private int value;
+
+ Reference(int i) {
+ value = i;
+ }
+
+ public String toString() {
+ return ("refCount: " + value);
+ }
+ }
+
+ /**
+ * table object references, to keep 'em from being garbage collected
+ */
+ private ConcurrentHashMap refs;
+
+ /**
+ * Constructor
+ */
+ ObjectReferences() {
+ refs = new ConcurrentHashMap<>(4);
+ }
+
+ /**
+ * Debugging: dump the contents of ObjectReferences' refs Hashtable
+ */
+ String dump() {
+ return refs.toString();
+ }
+
+ /**
+ * Increment ref count; set to 1 if we have no references for it
+ */
+ void increment(Object o) {
+ if (o == null){
+ debugString("ObjectReferences::increment - Passed in object is null");
+ return;
+ }
+
+ if (refs.containsKey(o)) {
+ (refs.get(o)).value++;
+ } else {
+ refs.put(o, new Reference(1));
+ }
+ }
+
+ /**
+ * Decrement ref count; remove if count drops to 0
+ */
+ void decrement(Object o) {
+ Reference aRef = refs.get(o);
+ if (aRef != null) {
+ aRef.value--;
+ if (aRef.value == 0) {
+ refs.remove(o);
+ } else if (aRef.value < 0) {
+ debugString("ERROR: decrementing reference count below 0");
+ }
+ } else {
+ debugString("ERROR: object to decrement not in ObjectReferences table");
+ }
+ }
+
+ }
+
+ /* ===== event handling code ===== */
+
+ /**
+ * native method for handling property change events
+ */
+ private native void propertyCaretChange(PropertyChangeEvent e,
+ AccessibleContext src,
+ int oldValue, int newValue);
+ private native void propertyDescriptionChange(PropertyChangeEvent e,
+ AccessibleContext src,
+ String oldValue, String newValue);
+ private native void propertyNameChange(PropertyChangeEvent e,
+ AccessibleContext src,
+ String oldValue, String newValue);
+ private native void propertySelectionChange(PropertyChangeEvent e,
+ AccessibleContext src);
+ private native void propertyStateChange(PropertyChangeEvent e,
+ AccessibleContext src,
+ String oldValue, String newValue);
+ private native void propertyTextChange(PropertyChangeEvent e,
+ AccessibleContext src);
+ private native void propertyValueChange(PropertyChangeEvent e,
+ AccessibleContext src,
+ String oldValue, String newValue);
+ private native void propertyVisibleDataChange(PropertyChangeEvent e,
+ AccessibleContext src);
+ private native void propertyChildChange(PropertyChangeEvent e,
+ AccessibleContext src,
+ AccessibleContext oldValue,
+ AccessibleContext newValue);
+ private native void propertyActiveDescendentChange(PropertyChangeEvent e,
+ AccessibleContext src,
+ AccessibleContext oldValue,
+ AccessibleContext newValue);
+
+ private native void javaShutdown();
+
+ /**
+ * native methods for handling focus events
+ */
+ private native void focusGained(FocusEvent e, AccessibleContext src);
+ private native void focusLost(FocusEvent e, AccessibleContext src);
+
+ /**
+ * native method for handling caret events
+ */
+ private native void caretUpdate(CaretEvent e, AccessibleContext src);
+
+ /**
+ * native methods for handling mouse events
+ */
+ private native void mouseClicked(MouseEvent e, AccessibleContext src);
+ private native void mouseEntered(MouseEvent e, AccessibleContext src);
+ private native void mouseExited(MouseEvent e, AccessibleContext src);
+ private native void mousePressed(MouseEvent e, AccessibleContext src);
+ private native void mouseReleased(MouseEvent e, AccessibleContext src);
+
+ /**
+ * native methods for handling menu & popupMenu events
+ */
+ private native void menuCanceled(MenuEvent e, AccessibleContext src);
+ private native void menuDeselected(MenuEvent e, AccessibleContext src);
+ private native void menuSelected(MenuEvent e, AccessibleContext src);
+ private native void popupMenuCanceled(PopupMenuEvent e, AccessibleContext src);
+ private native void popupMenuWillBecomeInvisible(PopupMenuEvent e,
+ AccessibleContext src);
+ private native void popupMenuWillBecomeVisible(PopupMenuEvent e,
+ AccessibleContext src);
+
+ /* ===== event definitions ===== */
+
+ private static final long PROPERTY_CHANGE_EVENTS = 1;
+ private static final long FOCUS_GAINED_EVENTS = 2;
+ private static final long FOCUS_LOST_EVENTS = 4;
+ private static final long FOCUS_EVENTS = (FOCUS_GAINED_EVENTS | FOCUS_LOST_EVENTS);
+
+ private static final long CARET_UPATE_EVENTS = 8;
+ private static final long CARET_EVENTS = CARET_UPATE_EVENTS;
+
+ private static final long MOUSE_CLICKED_EVENTS = 16;
+ private static final long MOUSE_ENTERED_EVENTS = 32;
+ private static final long MOUSE_EXITED_EVENTS = 64;
+ private static final long MOUSE_PRESSED_EVENTS = 128;
+ private static final long MOUSE_RELEASED_EVENTS = 256;
+ private static final long MOUSE_EVENTS = (MOUSE_CLICKED_EVENTS | MOUSE_ENTERED_EVENTS |
+ MOUSE_EXITED_EVENTS | MOUSE_PRESSED_EVENTS |
+ MOUSE_RELEASED_EVENTS);
+
+ private static final long MENU_CANCELED_EVENTS = 512;
+ private static final long MENU_DESELECTED_EVENTS = 1024;
+ private static final long MENU_SELECTED_EVENTS = 2048;
+ private static final long MENU_EVENTS = (MENU_CANCELED_EVENTS | MENU_DESELECTED_EVENTS |
+ MENU_SELECTED_EVENTS);
+
+ private static final long POPUPMENU_CANCELED_EVENTS = 4096;
+ private static final long POPUPMENU_WILL_BECOME_INVISIBLE_EVENTS = 8192;
+ private static final long POPUPMENU_WILL_BECOME_VISIBLE_EVENTS = 16384;
+ private static final long POPUPMENU_EVENTS = (POPUPMENU_CANCELED_EVENTS |
+ POPUPMENU_WILL_BECOME_INVISIBLE_EVENTS |
+ POPUPMENU_WILL_BECOME_VISIBLE_EVENTS);
+
+ /* These use their own numbering scheme, to ensure sufficient expansion room */
+ private static final long PROPERTY_NAME_CHANGE_EVENTS = 1;
+ private static final long PROPERTY_DESCRIPTION_CHANGE_EVENTS = 2;
+ private static final long PROPERTY_STATE_CHANGE_EVENTS = 4;
+ private static final long PROPERTY_VALUE_CHANGE_EVENTS = 8;
+ private static final long PROPERTY_SELECTION_CHANGE_EVENTS = 16;
+ private static final long PROPERTY_TEXT_CHANGE_EVENTS = 32;
+ private static final long PROPERTY_CARET_CHANGE_EVENTS = 64;
+ private static final long PROPERTY_VISIBLEDATA_CHANGE_EVENTS = 128;
+ private static final long PROPERTY_CHILD_CHANGE_EVENTS = 256;
+ private static final long PROPERTY_ACTIVEDESCENDENT_CHANGE_EVENTS = 512;
+
+
+ private static final long PROPERTY_EVENTS = (PROPERTY_NAME_CHANGE_EVENTS |
+ PROPERTY_DESCRIPTION_CHANGE_EVENTS |
+ PROPERTY_STATE_CHANGE_EVENTS |
+ PROPERTY_VALUE_CHANGE_EVENTS |
+ PROPERTY_SELECTION_CHANGE_EVENTS |
+ PROPERTY_TEXT_CHANGE_EVENTS |
+ PROPERTY_CARET_CHANGE_EVENTS |
+ PROPERTY_VISIBLEDATA_CHANGE_EVENTS |
+ PROPERTY_CHILD_CHANGE_EVENTS |
+ PROPERTY_ACTIVEDESCENDENT_CHANGE_EVENTS);
+
+ /**
+ * The EventHandler class listens for Java events and
+ * forwards them to the AT
+ */
+ private class EventHandler implements PropertyChangeListener,
+ FocusListener, CaretListener,
+ MenuListener, PopupMenuListener,
+ MouseListener, WindowListener,
+ ChangeListener {
+
+ private AccessBridge accessBridge;
+ private long javaEventMask = 0;
+ private long accessibilityEventMask = 0;
+
+ EventHandler(AccessBridge bridge) {
+ accessBridge = bridge;
+
+ // Register to receive WINDOW_OPENED and WINDOW_CLOSED
+ // events. Add the event source as a native window
+ // handler is it implements NativeWindowHandler.
+ // SwingEventMonitor.addWindowListener(this);
+ }
+
+ // --------- Event Notification Registration methods
+
+ /**
+ * Invoked the first time a window is made visible.
+ */
+ public void windowOpened(WindowEvent e) {
+ // If the window is a NativeWindowHandler, add it.
+ Object o = null;
+ if (e != null)
+ o = e.getSource();
+ if (o instanceof NativeWindowHandler) {
+ addNativeWindowHandler((NativeWindowHandler)o);
+ }
+ }
+
+ /**
+ * Invoked when the user attempts to close the window
+ * from the window's system menu. If the program does not
+ * explicitly hide or dispose the window while processing
+ * this event, the window close operation will be canceled.
+ */
+ public void windowClosing(WindowEvent e) {}
+
+ /**
+ * Invoked when a window has been closed as the result
+ * of calling dispose on the window.
+ */
+ public void windowClosed(WindowEvent e) {
+ // If the window is a NativeWindowHandler, remove it.
+ Object o = null;
+ if (e != null)
+ o = e.getSource();
+ if (o instanceof NativeWindowHandler) {
+ removeNativeWindowHandler((NativeWindowHandler)o);
+ }
+ }
+
+ /**
+ * Invoked when a window is changed from a normal to a
+ * minimized state. For many platforms, a minimized window
+ * is displayed as the icon specified in the window's
+ * iconImage property.
+ * @see java.awt.Frame#setIconImage
+ */
+ public void windowIconified(WindowEvent e) {}
+
+ /**
+ * Invoked when a window is changed from a minimized
+ * to a normal state.
+ */
+ public void windowDeiconified(WindowEvent e) {}
+
+ /**
+ * Invoked when the Window is set to be the active Window. Only a Frame or
+ * a Dialog can be the active Window. The native windowing system may
+ * denote the active Window or its children with special decorations, such
+ * as a highlighted title bar. The active Window is always either the
+ * focused Window, or the first Frame or Dialog that is an owner of the
+ * focused Window.
+ */
+ public void windowActivated(WindowEvent e) {}
+
+ /**
+ * Invoked when a Window is no longer the active Window. Only a Frame or a
+ * Dialog can be the active Window. The native windowing system may denote
+ * the active Window or its children with special decorations, such as a
+ * highlighted title bar. The active Window is always either the focused
+ * Window, or the first Frame or Dialog that is an owner of the focused
+ * Window.
+ */
+ public void windowDeactivated(WindowEvent e) {}
+
+ /**
+ * Turn on event monitoring for the event type passed in
+ * If necessary, add the appropriate event listener (if
+ * no other event of that type is being listened for)
+ */
+ void addJavaEventNotification(long type) {
+ long newEventMask = javaEventMask | type;
+ /*
+ if ( ((javaEventMask & PROPERTY_EVENTS) == 0) &&
+ ((newEventMask & PROPERTY_EVENTS) != 0) ) {
+ AccessibilityEventMonitor.addPropertyChangeListener(this);
+ }
+ */
+ if ( ((javaEventMask & FOCUS_EVENTS) == 0) &&
+ ((newEventMask & FOCUS_EVENTS) != 0) ) {
+ SwingEventMonitor.addFocusListener(this);
+ }
+ if ( ((javaEventMask & CARET_EVENTS) == 0) &&
+ ((newEventMask & CARET_EVENTS) != 0) ) {
+ SwingEventMonitor.addCaretListener(this);
+ }
+ if ( ((javaEventMask & MOUSE_EVENTS) == 0) &&
+ ((newEventMask & MOUSE_EVENTS) != 0) ) {
+ SwingEventMonitor.addMouseListener(this);
+ }
+ if ( ((javaEventMask & MENU_EVENTS) == 0) &&
+ ((newEventMask & MENU_EVENTS) != 0) ) {
+ SwingEventMonitor.addMenuListener(this);
+ SwingEventMonitor.addPopupMenuListener(this);
+ }
+ if ( ((javaEventMask & POPUPMENU_EVENTS) == 0) &&
+ ((newEventMask & POPUPMENU_EVENTS) != 0) ) {
+ SwingEventMonitor.addPopupMenuListener(this);
+ }
+
+ javaEventMask = newEventMask;
+ }
+
+ /**
+ * Turn off event monitoring for the event type passed in
+ * If necessary, remove the appropriate event listener (if
+ * no other event of that type is being listened for)
+ */
+ void removeJavaEventNotification(long type) {
+ long newEventMask = javaEventMask & (~type);
+ /*
+ if ( ((javaEventMask & PROPERTY_EVENTS) != 0) &&
+ ((newEventMask & PROPERTY_EVENTS) == 0) ) {
+ AccessibilityEventMonitor.removePropertyChangeListener(this);
+ }
+ */
+ if (((javaEventMask & FOCUS_EVENTS) != 0) &&
+ ((newEventMask & FOCUS_EVENTS) == 0)) {
+ SwingEventMonitor.removeFocusListener(this);
+ }
+ if (((javaEventMask & CARET_EVENTS) != 0) &&
+ ((newEventMask & CARET_EVENTS) == 0)) {
+ SwingEventMonitor.removeCaretListener(this);
+ }
+ if (((javaEventMask & MOUSE_EVENTS) == 0) &&
+ ((newEventMask & MOUSE_EVENTS) != 0)) {
+ SwingEventMonitor.removeMouseListener(this);
+ }
+ if (((javaEventMask & MENU_EVENTS) == 0) &&
+ ((newEventMask & MENU_EVENTS) != 0)) {
+ SwingEventMonitor.removeMenuListener(this);
+ }
+ if (((javaEventMask & POPUPMENU_EVENTS) == 0) &&
+ ((newEventMask & POPUPMENU_EVENTS) != 0)) {
+ SwingEventMonitor.removePopupMenuListener(this);
+ }
+
+ javaEventMask = newEventMask;
+ }
+
+ /**
+ * Turn on event monitoring for the event type passed in
+ * If necessary, add the appropriate event listener (if
+ * no other event of that type is being listened for)
+ */
+ void addAccessibilityEventNotification(long type) {
+ long newEventMask = accessibilityEventMask | type;
+ if ( ((accessibilityEventMask & PROPERTY_EVENTS) == 0) &&
+ ((newEventMask & PROPERTY_EVENTS) != 0) ) {
+ AccessibilityEventMonitor.addPropertyChangeListener(this);
+ }
+ accessibilityEventMask = newEventMask;
+ }
+
+ /**
+ * Turn off event monitoring for the event type passed in
+ * If necessary, remove the appropriate event listener (if
+ * no other event of that type is being listened for)
+ */
+ void removeAccessibilityEventNotification(long type) {
+ long newEventMask = accessibilityEventMask & (~type);
+ if ( ((accessibilityEventMask & PROPERTY_EVENTS) != 0) &&
+ ((newEventMask & PROPERTY_EVENTS) == 0) ) {
+ AccessibilityEventMonitor.removePropertyChangeListener(this);
+ }
+ accessibilityEventMask = newEventMask;
+ }
+
+ /**
+ * ------- property change event glue
+ */
+ // This is invoked on the EDT , as
+ public void propertyChange(PropertyChangeEvent e) {
+
+ accessBridge.debugString("propertyChange(" + e.toString() + ") called");
+
+ if (e != null && (accessibilityEventMask & PROPERTY_EVENTS) != 0) {
+ Object o = e.getSource();
+ AccessibleContext ac;
+
+ if (o instanceof AccessibleContext) {
+ ac = (AccessibleContext) o;
+ } else {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a == null)
+ return;
+ else
+ ac = a.getAccessibleContext();
+ }
+ if (ac != null) {
+ InvocationUtils.registerAccessibleContext(ac, AppContext.getAppContext());
+
+ accessBridge.debugString("AccessibleContext: " + ac);
+ String propertyName = e.getPropertyName();
+
+ if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_CARET_PROPERTY) == 0) {
+ int oldValue = 0;
+ int newValue = 0;
+
+ if (e.getOldValue() instanceof Integer) {
+ oldValue = ((Integer) e.getOldValue()).intValue();
+ }
+ if (e.getNewValue() instanceof Integer) {
+ newValue = ((Integer) e.getNewValue()).intValue();
+ }
+ accessBridge.debugString(" - about to call propertyCaretChange()");
+ accessBridge.debugString(" old value: " + oldValue + "new value: " + newValue);
+ accessBridge.propertyCaretChange(e, ac, oldValue, newValue);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_DESCRIPTION_PROPERTY) == 0) {
+ String oldValue = null;
+ String newValue = null;
+
+ if (e.getOldValue() != null) {
+ oldValue = e.getOldValue().toString();
+ }
+ if (e.getNewValue() != null) {
+ newValue = e.getNewValue().toString();
+ }
+ accessBridge.debugString(" - about to call propertyDescriptionChange()");
+ accessBridge.debugString(" old value: " + oldValue + "new value: " + newValue);
+ accessBridge.propertyDescriptionChange(e, ac, oldValue, newValue);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_NAME_PROPERTY) == 0) {
+ String oldValue = null;
+ String newValue = null;
+
+ if (e.getOldValue() != null) {
+ oldValue = e.getOldValue().toString();
+ }
+ if (e.getNewValue() != null) {
+ newValue = e.getNewValue().toString();
+ }
+ accessBridge.debugString(" - about to call propertyNameChange()");
+ accessBridge.debugString(" old value: " + oldValue + " new value: " + newValue);
+ accessBridge.propertyNameChange(e, ac, oldValue, newValue);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY) == 0) {
+ accessBridge.debugString(" - about to call propertySelectionChange() " + ac + " " + Thread.currentThread() + " " + e.getSource());
+
+ accessBridge.propertySelectionChange(e, ac);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_STATE_PROPERTY) == 0) {
+ String oldValue = null;
+ String newValue = null;
+
+ // Localization fix requested by Oliver for EA-1
+ if (e.getOldValue() != null) {
+ AccessibleState oldState = (AccessibleState) e.getOldValue();
+ oldValue = oldState.toDisplayString(Locale.US);
+ }
+ if (e.getNewValue() != null) {
+ AccessibleState newState = (AccessibleState) e.getNewValue();
+ newValue = newState.toDisplayString(Locale.US);
+ }
+
+ accessBridge.debugString(" - about to call propertyStateChange()");
+ accessBridge.propertyStateChange(e, ac, oldValue, newValue);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_TEXT_PROPERTY) == 0) {
+ accessBridge.debugString(" - about to call propertyTextChange()");
+ accessBridge.propertyTextChange(e, ac);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_VALUE_PROPERTY) == 0) { // strings 'cause of floating point, etc.
+ String oldValue = null;
+ String newValue = null;
+
+ if (e.getOldValue() != null) {
+ oldValue = e.getOldValue().toString();
+ }
+ if (e.getNewValue() != null) {
+ newValue = e.getNewValue().toString();
+ }
+ accessBridge.debugString(" - about to call propertyDescriptionChange()");
+ accessBridge.propertyValueChange(e, ac, oldValue, newValue);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY) == 0) {
+ accessBridge.propertyVisibleDataChange(e, ac);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY) == 0) {
+ AccessibleContext oldAC = null;
+ AccessibleContext newAC = null;
+ Accessible a;
+
+ if (e.getOldValue() instanceof AccessibleContext) {
+ oldAC = (AccessibleContext) e.getOldValue();
+ InvocationUtils.registerAccessibleContext(oldAC, AppContext.getAppContext());
+ }
+ if (e.getNewValue() instanceof AccessibleContext) {
+ newAC = (AccessibleContext) e.getNewValue();
+ InvocationUtils.registerAccessibleContext(newAC, AppContext.getAppContext());
+ }
+ accessBridge.debugString(" - about to call propertyChildChange()");
+ accessBridge.debugString(" old AC: " + oldAC + "new AC: " + newAC);
+ accessBridge.propertyChildChange(e, ac, oldAC, newAC);
+
+ } else if (propertyName.compareTo(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0) {
+ handleActiveDescendentEvent(e, ac);
+ }
+ }
+ }
+ }
+
+ /*
+ * Handle an ActiveDescendent PropertyChangeEvent. This
+ * method works around a JTree bug where ActiveDescendent
+ * PropertyChangeEvents have the wrong parent.
+ */
+ private AccessibleContext prevAC = null; // previous AccessibleContext
+
+ private void handleActiveDescendentEvent(PropertyChangeEvent e,
+ AccessibleContext ac) {
+ if (e == null || ac == null)
+ return;
+ AccessibleContext oldAC = null;
+ AccessibleContext newAC = null;
+ Accessible a;
+
+ // get the old active descendent
+ if (e.getOldValue() instanceof Accessible) {
+ oldAC = ((Accessible) e.getOldValue()).getAccessibleContext();
+ } else if (e.getOldValue() instanceof Component) {
+ a = Translator.getAccessible(e.getOldValue());
+ if (a != null) {
+ oldAC = a.getAccessibleContext();
+ }
+ }
+ if (oldAC != null) {
+ Accessible parent = oldAC.getAccessibleParent();
+ if (parent instanceof JTree) {
+ // use the previous AccessibleJTreeNode
+ oldAC = prevAC;
+ }
+ }
+
+ // get the new active descendent
+ if (e.getNewValue() instanceof Accessible) {
+ newAC = ((Accessible) e.getNewValue()).getAccessibleContext();
+ } else if (e.getNewValue() instanceof Component) {
+ a = Translator.getAccessible(e.getNewValue());
+ if (a != null) {
+ newAC = a.getAccessibleContext();
+ }
+ }
+ if (newAC != null) {
+ Accessible parent = newAC.getAccessibleParent();
+ if (parent instanceof JTree) {
+ // use a new AccessibleJTreeNode with the right parent
+ JTree tree = (JTree)parent;
+ newAC = new AccessibleJTreeNode(tree,
+ tree.getSelectionPath(),
+ null);
+ }
+ }
+ prevAC = newAC;
+
+ accessBridge.debugString(" - about to call propertyActiveDescendentChange()");
+ accessBridge.debugString(" AC: " + ac);
+ accessBridge.debugString(" old AC: " + oldAC + "new AC: " + newAC);
+
+ InvocationUtils.registerAccessibleContext(oldAC, AppContext.getAppContext());
+ InvocationUtils.registerAccessibleContext(newAC, AppContext.getAppContext());
+ accessBridge.propertyActiveDescendentChange(e, ac, oldAC, newAC);
+ }
+
+ /**
+ * ------- focus event glue
+ */
+ private boolean stateChangeListenerAdded = false;
+
+ public void focusGained(FocusEvent e) {
+ processFocusGained();
+ }
+
+ public void stateChanged(ChangeEvent e) {
+ processFocusGained();
+ }
+
+ private void processFocusGained() {
+ Component focusOwner = KeyboardFocusManager.
+ getCurrentKeyboardFocusManager().getFocusOwner();
+ if (focusOwner == null) {
+ return;
+ }
+
+ // Only menus and popup selections are handled by the JRootPane.
+ if (focusOwner instanceof JRootPane) {
+ MenuElement [] path =
+ MenuSelectionManager.defaultManager().getSelectedPath();
+ if (path.length > 1) {
+ Component penult = path[path.length-2].getComponent();
+ Component last = path[path.length-1].getComponent();
+
+ if (last instanceof JPopupMenu) {
+ // This is a popup with nothing in the popup
+ // selected. The menu itself is selected.
+ FocusEvent e = new FocusEvent(penult, FocusEvent.FOCUS_GAINED);
+ AccessibleContext context = penult.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, SunToolkit.targetToAppContext(penult));
+ accessBridge.focusGained(e, context);
+ } else if (penult instanceof JPopupMenu) {
+ // This is a popup with an item selected
+ FocusEvent e =
+ new FocusEvent(last, FocusEvent.FOCUS_GAINED);
+ accessBridge.debugString(" - about to call focusGained()");
+ AccessibleContext focusedAC = last.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(focusedAC, SunToolkit.targetToAppContext(last));
+ accessBridge.debugString(" AC: " + focusedAC);
+ accessBridge.focusGained(e, focusedAC);
+ }
+ }
+ } else {
+ // The focus owner has the selection.
+ if (focusOwner instanceof Accessible) {
+ FocusEvent e = new FocusEvent(focusOwner,
+ FocusEvent.FOCUS_GAINED);
+ accessBridge.debugString(" - about to call focusGained()");
+ AccessibleContext focusedAC = focusOwner.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(focusedAC, SunToolkit.targetToAppContext(focusOwner));
+ accessBridge.debugString(" AC: " + focusedAC);
+ accessBridge.focusGained(e, focusedAC);
+ }
+ }
+ }
+
+ public void focusLost(FocusEvent e) {
+ if (e != null && (javaEventMask & FOCUS_LOST_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ accessBridge.debugString(" - about to call focusLost()");
+ accessBridge.debugString(" AC: " + a.getAccessibleContext());
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.focusLost(e, context);
+ }
+ }
+ }
+
+ /**
+ * ------- caret event glue
+ */
+ public void caretUpdate(CaretEvent e) {
+ if (e != null && (javaEventMask & CARET_UPATE_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.caretUpdate(e, context);
+ }
+ }
+ }
+
+ /**
+ * ------- mouse event glue
+ */
+
+ public void mouseClicked(MouseEvent e) {
+ if (e != null && (javaEventMask & MOUSE_CLICKED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.mouseClicked(e, context);
+ }
+ }
+ }
+
+ public void mouseEntered(MouseEvent e) {
+ if (e != null && (javaEventMask & MOUSE_ENTERED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.mouseEntered(e, context);
+ }
+ }
+ }
+
+ public void mouseExited(MouseEvent e) {
+ if (e != null && (javaEventMask & MOUSE_EXITED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.mouseExited(e, context);
+ }
+ }
+ }
+
+ public void mousePressed(MouseEvent e) {
+ if (e != null && (javaEventMask & MOUSE_PRESSED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.mousePressed(e, context);
+ }
+ }
+ }
+
+ public void mouseReleased(MouseEvent e) {
+ if (e != null && (javaEventMask & MOUSE_RELEASED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.mouseReleased(e, context);
+ }
+ }
+ }
+
+ /**
+ * ------- menu event glue
+ */
+ public void menuCanceled(MenuEvent e) {
+ if (e != null && (javaEventMask & MENU_CANCELED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.menuCanceled(e, context);
+ }
+ }
+ }
+
+ public void menuDeselected(MenuEvent e) {
+ if (e != null && (javaEventMask & MENU_DESELECTED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.menuDeselected(e, context);
+ }
+ }
+ }
+
+ public void menuSelected(MenuEvent e) {
+ if (e != null && (javaEventMask & MENU_SELECTED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.menuSelected(e, context);
+ }
+ }
+ }
+
+ public void popupMenuCanceled(PopupMenuEvent e) {
+ if (e != null && (javaEventMask & POPUPMENU_CANCELED_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.popupMenuCanceled(e, context);
+ }
+ }
+ }
+
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+ if (e != null && (javaEventMask & POPUPMENU_WILL_BECOME_INVISIBLE_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.popupMenuWillBecomeInvisible(e, context);
+ }
+ }
+ }
+
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+ if (e != null && (javaEventMask & POPUPMENU_WILL_BECOME_VISIBLE_EVENTS) != 0) {
+ Accessible a = Translator.getAccessible(e.getSource());
+ if (a != null) {
+ AccessibleContext context = a.getAccessibleContext();
+ InvocationUtils.registerAccessibleContext(context, AppContext.getAppContext());
+ accessBridge.popupMenuWillBecomeVisible(e, context);
+ }
+ }
+ }
+
+ } // End of EventHandler Class
+
+ // --------- Event Notification Registration methods
+
+ /**
+ * Wrapper method around eventHandler.addJavaEventNotification()
+ */
+ private void addJavaEventNotification(final long type) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run(){
+ eventHandler.addJavaEventNotification(type);
+ }
+ });
+ }
+
+ /**
+ * Wrapper method around eventHandler.removeJavaEventNotification()
+ */
+ private void removeJavaEventNotification(final long type) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run(){
+ eventHandler.removeJavaEventNotification(type);
+ }
+ });
+ }
+
+
+ /**
+ * Wrapper method around eventHandler.addAccessibilityEventNotification()
+ */
+ private void addAccessibilityEventNotification(final long type) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run(){
+ eventHandler.addAccessibilityEventNotification(type);
+ }
+ });
+ }
+
+ /**
+ * Wrapper method around eventHandler.removeAccessibilityEventNotification()
+ */
+ private void removeAccessibilityEventNotification(final long type) {
+ EventQueue.invokeLater(new Runnable() {
+ public void run(){
+ eventHandler.removeAccessibilityEventNotification(type);
+ }
+ });
+ }
+
+ /**
+ ******************************************************
+ * All AccessibleRoles
+ *
+ * We shouldn't have to do this since it requires us
+ * to synchronize the allAccessibleRoles array when
+ * the AccessibleRoles class interface changes. However,
+ * there is no Accessibility API method to get all
+ * AccessibleRoles
+ ******************************************************
+ */
+ private AccessibleRole [] allAccessibleRoles = {
+ /**
+ * Object is used to alert the user about something.
+ */
+ AccessibleRole.ALERT,
+
+ /**
+ * The header for a column of data.
+ */
+ AccessibleRole.COLUMN_HEADER,
+
+ /**
+ * Object that can be drawn into and is used to trap
+ * events.
+ * @see #FRAME
+ * @see #GLASS_PANE
+ * @see #LAYERED_PANE
+ */
+ AccessibleRole.CANVAS,
+
+ /**
+ * A list of choices the user can select from. Also optionally
+ * allows the user to enter a choice of their own.
+ */
+ AccessibleRole.COMBO_BOX,
+
+ /**
+ * An iconified internal frame in a DESKTOP_PANE.
+ * @see #DESKTOP_PANE
+ * @see #INTERNAL_FRAME
+ */
+ AccessibleRole.DESKTOP_ICON,
+
+ /**
+ * A frame-like object that is clipped by a desktop pane. The
+ * desktop pane, internal frame, and desktop icon objects are
+ * often used to create multiple document interfaces within an
+ * application.
+ * @see #DESKTOP_ICON
+ * @see #DESKTOP_PANE
+ * @see #FRAME
+ */
+ AccessibleRole.INTERNAL_FRAME,
+
+ /**
+ * A pane that supports internal frames and
+ * iconified versions of those internal frames.
+ * @see #DESKTOP_ICON
+ * @see #INTERNAL_FRAME
+ */
+ AccessibleRole.DESKTOP_PANE,
+
+ /**
+ * A specialized pane whose primary use is inside a DIALOG
+ * @see #DIALOG
+ */
+ AccessibleRole.OPTION_PANE,
+
+ /**
+ * A top level window with no title or border.
+ * @see #FRAME
+ * @see #DIALOG
+ */
+ AccessibleRole.WINDOW,
+
+ /**
+ * A top level window with a title bar, border, menu bar, etc. It is
+ * often used as the primary window for an application.
+ * @see #DIALOG
+ * @see #CANVAS
+ * @see #WINDOW
+ */
+ AccessibleRole.FRAME,
+
+ /**
+ * A top level window with title bar and a border. A dialog is similar
+ * to a frame, but it has fewer properties and is often used as a
+ * secondary window for an application.
+ * @see #FRAME
+ * @see #WINDOW
+ */
+ AccessibleRole.DIALOG,
+
+ /**
+ * A specialized dialog that lets the user choose a color.
+ */
+ AccessibleRole.COLOR_CHOOSER,
+
+
+ /**
+ * A pane that allows the user to navigate through
+ * and select the contents of a directory. May be used
+ * by a file chooser.
+ * @see #FILE_CHOOSER
+ */
+ AccessibleRole.DIRECTORY_PANE,
+
+ /**
+ * A specialized dialog that displays the files in the directory
+ * and lets the user select a file, browse a different directory,
+ * or specify a filename. May use the directory pane to show the
+ * contents of a directory.
+ * @see #DIRECTORY_PANE
+ */
+ AccessibleRole.FILE_CHOOSER,
+
+ /**
+ * An object that fills up space in a user interface. It is often
+ * used in interfaces to tweak the spacing between components,
+ * but serves no other purpose.
+ */
+ AccessibleRole.FILLER,
+
+ /**
+ * A hypertext anchor
+ */
+ // AccessibleRole.HYPERLINK,
+
+ /**
+ * A small fixed size picture, typically used to decorate components.
+ */
+ AccessibleRole.ICON,
+
+ /**
+ * An object used to present an icon or short string in an interface.
+ */
+ AccessibleRole.LABEL,
+
+ /**
+ * A specialized pane that has a glass pane and a layered pane as its
+ * children.
+ * @see #GLASS_PANE
+ * @see #LAYERED_PANE
+ */
+ AccessibleRole.ROOT_PANE,
+
+ /**
+ * A pane that is guaranteed to be painted on top
+ * of all panes beneath it.
+ * @see #ROOT_PANE
+ * @see #CANVAS
+ */
+ AccessibleRole.GLASS_PANE,
+
+ /**
+ * A specialized pane that allows its children to be drawn in layers,
+ * providing a form of stacking order. This is usually the pane that
+ * holds the menu bar as well as the pane that contains most of the
+ * visual components in a window.
+ * @see #GLASS_PANE
+ * @see #ROOT_PANE
+ */
+ AccessibleRole.LAYERED_PANE,
+
+ /**
+ * An object that presents a list of objects to the user and allows the
+ * user to select one or more of them. A list is usually contained
+ * within a scroll pane.
+ * @see #SCROLL_PANE
+ * @see #LIST_ITEM
+ */
+ AccessibleRole.LIST,
+
+ /**
+ * An object that presents an element in a list. A list is usually
+ * contained within a scroll pane.
+ * @see #SCROLL_PANE
+ * @see #LIST
+ */
+ AccessibleRole.LIST_ITEM,
+
+ /**
+ * An object usually drawn at the top of the primary dialog box of
+ * an application that contains a list of menus the user can choose
+ * from. For example, a menu bar might contain menus for "File,"
+ * "Edit," and "Help."
+ * @see #MENU
+ * @see #POPUP_MENU
+ * @see #LAYERED_PANE
+ */
+ AccessibleRole.MENU_BAR,
+
+ /**
+ * A temporary window that is usually used to offer the user a
+ * list of choices, and then hides when the user selects one of
+ * those choices.
+ * @see #MENU
+ * @see #MENU_ITEM
+ */
+ AccessibleRole.POPUP_MENU,
+
+ /**
+ * An object usually found inside a menu bar that contains a list
+ * of actions the user can choose from. A menu can have any object
+ * as its children, but most often they are menu items, other menus,
+ * or rudimentary objects such as radio buttons, check boxes, or
+ * separators. For example, an application may have an "Edit" menu
+ * that contains menu items for "Cut" and "Paste."
+ * @see #MENU_BAR
+ * @see #MENU_ITEM
+ * @see #SEPARATOR
+ * @see #RADIO_BUTTON
+ * @see #CHECK_BOX
+ * @see #POPUP_MENU
+ */
+ AccessibleRole.MENU,
+
+ /**
+ * An object usually contained in a menu that presents an action
+ * the user can choose. For example, the "Cut" menu item in an
+ * "Edit" menu would be an action the user can select to cut the
+ * selected area of text in a document.
+ * @see #MENU_BAR
+ * @see #SEPARATOR
+ * @see #POPUP_MENU
+ */
+ AccessibleRole.MENU_ITEM,
+
+ /**
+ * An object usually contained in a menu to provide a visual
+ * and logical separation of the contents in a menu. For example,
+ * the "File" menu of an application might contain menu items for
+ * "Open," "Close," and "Exit," and will place a separator between
+ * "Close" and "Exit" menu items.
+ * @see #MENU
+ * @see #MENU_ITEM
+ */
+ AccessibleRole.SEPARATOR,
+
+ /**
+ * An object that presents a series of panels (or page tabs), one at a
+ * time, through some mechanism provided by the object. The most common
+ * mechanism is a list of tabs at the top of the panel. The children of
+ * a page tab list are all page tabs.
+ * @see #PAGE_TAB
+ */
+ AccessibleRole.PAGE_TAB_LIST,
+
+ /**
+ * An object that is a child of a page tab list. Its sole child is
+ * the panel that is to be presented to the user when the user
+ * selects the page tab from the list of tabs in the page tab list.
+ * @see #PAGE_TAB_LIST
+ */
+ AccessibleRole.PAGE_TAB,
+
+ /**
+ * A generic container that is often used to group objects.
+ */
+ AccessibleRole.PANEL,
+
+ /**
+ * An object used to indicate how much of a task has been completed.
+ */
+ AccessibleRole.PROGRESS_BAR,
+
+ /**
+ * A text object used for passwords, or other places where the
+ * text contents is not shown visibly to the user
+ */
+ AccessibleRole.PASSWORD_TEXT,
+
+ /**
+ * An object the user can manipulate to tell the application to do
+ * something.
+ * @see #CHECK_BOX
+ * @see #TOGGLE_BUTTON
+ * @see #RADIO_BUTTON
+ */
+ AccessibleRole.PUSH_BUTTON,
+
+ /**
+ * A specialized push button that can be checked or unchecked, but
+ * does not provide a separate indicator for the current state.
+ * @see #PUSH_BUTTON
+ * @see #CHECK_BOX
+ * @see #RADIO_BUTTON
+ */
+ AccessibleRole.TOGGLE_BUTTON,
+
+ /**
+ * A choice that can be checked or unchecked and provides a
+ * separate indicator for the current state.
+ * @see #PUSH_BUTTON
+ * @see #TOGGLE_BUTTON
+ * @see #RADIO_BUTTON
+ */
+ AccessibleRole.CHECK_BOX,
+
+ /**
+ * A specialized check box that will cause other radio buttons in the
+ * same group to become unchecked when this one is checked.
+ * @see #PUSH_BUTTON
+ * @see #TOGGLE_BUTTON
+ * @see #CHECK_BOX
+ */
+ AccessibleRole.RADIO_BUTTON,
+
+ /**
+ * The header for a row of data.
+ */
+ AccessibleRole.ROW_HEADER,
+
+ /**
+ * An object that allows a user to incrementally view a large amount
+ * of information. Its children can include scroll bars and a viewport.
+ * @see #SCROLL_BAR
+ * @see #VIEWPORT
+ */
+ AccessibleRole.SCROLL_PANE,
+
+ /**
+ * An object usually used to allow a user to incrementally view a
+ * large amount of data. Usually used only by a scroll pane.
+ * @see #SCROLL_PANE
+ */
+ AccessibleRole.SCROLL_BAR,
+
+ /**
+ * An object usually used in a scroll pane. It represents the portion
+ * of the entire data that the user can see. As the user manipulates
+ * the scroll bars, the contents of the viewport can change.
+ * @see #SCROLL_PANE
+ */
+ AccessibleRole.VIEWPORT,
+
+ /**
+ * An object that allows the user to select from a bounded range. For
+ * example, a slider might be used to select a number between 0 and 100.
+ */
+ AccessibleRole.SLIDER,
+
+ /**
+ * A specialized panel that presents two other panels at the same time.
+ * Between the two panels is a divider the user can manipulate to make
+ * one panel larger and the other panel smaller.
+ */
+ AccessibleRole.SPLIT_PANE,
+
+ /**
+ * An object used to present information in terms of rows and columns.
+ * An example might include a spreadsheet application.
+ */
+ AccessibleRole.TABLE,
+
+ /**
+ * An object that presents text to the user. The text is usually
+ * editable by the user as opposed to a label.
+ * @see #LABEL
+ */
+ AccessibleRole.TEXT,
+
+ /**
+ * An object used to present hierarchical information to the user.
+ * The individual nodes in the tree can be collapsed and expanded
+ * to provide selective disclosure of the tree's contents.
+ */
+ AccessibleRole.TREE,
+
+ /**
+ * A bar or palette usually composed of push buttons or toggle buttons.
+ * It is often used to provide the most frequently used functions for an
+ * application.
+ */
+ AccessibleRole.TOOL_BAR,
+
+ /**
+ * An object that provides information about another object. The
+ * accessibleDescription property of the tool tip is often displayed
+ * to the user in a small "help bubble" when the user causes the
+ * mouse to hover over the object associated with the tool tip.
+ */
+ AccessibleRole.TOOL_TIP,
+
+ /**
+ * An AWT component, but nothing else is known about it.
+ * @see #SWING_COMPONENT
+ * @see #UNKNOWN
+ */
+ AccessibleRole.AWT_COMPONENT,
+
+ /**
+ * A Swing component, but nothing else is known about it.
+ * @see #AWT_COMPONENT
+ * @see #UNKNOWN
+ */
+ AccessibleRole.SWING_COMPONENT,
+
+ /**
+ * The object contains some Accessible information, but its role is
+ * not known.
+ * @see #AWT_COMPONENT
+ * @see #SWING_COMPONENT
+ */
+ AccessibleRole.UNKNOWN,
+
+ // These roles are only available in JDK 1.4
+
+ /**
+ * A STATUS_BAR is an simple component that can contain
+ * multiple labels of status information to the user.
+ AccessibleRole.STATUS_BAR,
+
+ /**
+ * A DATE_EDITOR is a component that allows users to edit
+ * java.util.Date and java.util.Time objects
+ AccessibleRole.DATE_EDITOR,
+
+ /**
+ * A SPIN_BOX is a simple spinner component and its main use
+ * is for simple numbers.
+ AccessibleRole.SPIN_BOX,
+
+ /**
+ * A FONT_CHOOSER is a component that lets the user pick various
+ * attributes for fonts.
+ AccessibleRole.FONT_CHOOSER,
+
+ /**
+ * A GROUP_BOX is a simple container that contains a border
+ * around it and contains components inside it.
+ AccessibleRole.GROUP_BOX
+
+ /**
+ * Since JDK 1.5
+ *
+ * A text header
+
+ AccessibleRole.HEADER,
+
+ /**
+ * A text footer
+
+ AccessibleRole.FOOTER,
+
+ /**
+ * A text paragraph
+
+ AccessibleRole.PARAGRAPH,
+
+ /**
+ * A ruler is an object used to measure distance
+
+ AccessibleRole.RULER,
+
+ /**
+ * A role indicating the object acts as a formula for
+ * calculating a value. An example is a formula in
+ * a spreadsheet cell.
+ AccessibleRole.EDITBAR
+ */
+ };
+
+ /**
+ * This class implements accessibility support for the
+ * JTree child. It provides an implementation of the
+ * Java Accessibility API appropriate to tree nodes.
+ *
+ * Copied from JTree.java to work around a JTree bug where
+ * ActiveDescendent PropertyChangeEvents contain the wrong
+ * parent.
+ */
+ /**
+ * This class in invoked on the EDT as its part of ActiveDescendant,
+ * hence the calls do not need to be specifically made on the EDT
+ */
+ private class AccessibleJTreeNode extends AccessibleContext
+ implements Accessible, AccessibleComponent, AccessibleSelection,
+ AccessibleAction {
+
+ private JTree tree = null;
+ private TreeModel treeModel = null;
+ private Object obj = null;
+ private TreePath path = null;
+ private Accessible accessibleParent = null;
+ private int index = 0;
+ private boolean isLeaf = false;
+
+ /**
+ * Constructs an AccessibleJTreeNode
+ */
+ AccessibleJTreeNode(JTree t, TreePath p, Accessible ap) {
+ tree = t;
+ path = p;
+ accessibleParent = ap;
+ if (t != null)
+ treeModel = t.getModel();
+ if (p != null) {
+ obj = p.getLastPathComponent();
+ if (treeModel != null && obj != null) {
+ isLeaf = treeModel.isLeaf(obj);
+ }
+ }
+ debugString("AccessibleJTreeNode: name = "+getAccessibleName()+"; TreePath = "+p+"; parent = "+ap);
+ }
+
+ private TreePath getChildTreePath(int i) {
+ // Tree nodes can't be so complex that they have
+ // two sets of children -> we're ignoring that case
+ if (i < 0 || i >= getAccessibleChildrenCount() || path == null || treeModel == null) {
+ return null;
+ } else {
+ Object childObj = treeModel.getChild(obj, i);
+ Object[] objPath = path.getPath();
+ Object[] objChildPath = new Object[objPath.length+1];
+ java.lang.System.arraycopy(objPath, 0, objChildPath, 0, objPath.length);
+ objChildPath[objChildPath.length-1] = childObj;
+ return new TreePath(objChildPath);
+ }
+ }
+
+ /**
+ * Get the AccessibleContext associated with this tree node.
+ * In the implementation of the Java Accessibility API for
+ * this class, return this object, which is its own
+ * AccessibleContext.
+ *
+ * @return this object
+ */
+ public AccessibleContext getAccessibleContext() {
+ return this;
+ }
+
+ private AccessibleContext getCurrentAccessibleContext() {
+ Component c = getCurrentComponent();
+ if (c instanceof Accessible) {
+ return (c.getAccessibleContext());
+ } else {
+ return null;
+ }
+ }
+
+ private Component getCurrentComponent() {
+ debugString("AccessibleJTreeNode: getCurrentComponent");
+ // is the object visible?
+ // if so, get row, selected, focus & leaf state,
+ // and then get the renderer component and return it
+ if (tree != null && tree.isVisible(path)) {
+ TreeCellRenderer r = tree.getCellRenderer();
+ if (r == null) {
+ debugString(" returning null 1");
+ return null;
+ }
+ TreeUI ui = tree.getUI();
+ if (ui != null) {
+ int row = ui.getRowForPath(tree, path);
+ boolean selected = tree.isPathSelected(path);
+ boolean expanded = tree.isExpanded(path);
+ boolean hasFocus = false; // how to tell?? -PK
+ Component retval = r.getTreeCellRendererComponent(tree, obj,
+ selected, expanded,
+ isLeaf, row, hasFocus);
+ debugString(" returning = "+retval.getClass());
+ return retval;
+ }
+ }
+ debugString(" returning null 2");
+ return null;
+ }
+
+ // AccessibleContext methods
+
+ /**
+ * Get the accessible name of this object.
+ *
+ * @return the localized name of the object; null if this
+ * object does not have a name
+ */
+ public String getAccessibleName() {
+ debugString("AccessibleJTreeNode: getAccessibleName");
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ String name = ac.getAccessibleName();
+ if ((name != null) && (!name.isEmpty())) {
+ String retval = ac.getAccessibleName();
+ debugString(" returning "+retval);
+ return retval;
+ } else {
+ return null;
+ }
+ }
+ if ((accessibleName != null) && (accessibleName.isEmpty())) {
+ return accessibleName;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Set the localized accessible name of this object.
+ *
+ * @param s the new localized name of the object.
+ */
+ public void setAccessibleName(String s) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ ac.setAccessibleName(s);
+ } else {
+ super.setAccessibleName(s);
+ }
+ }
+
+ //
+ // *** should check tooltip text for desc. (needs MouseEvent)
+ //
+ /**
+ * Get the accessible description of this object.
+ *
+ * @return the localized description of the object; null if
+ * this object does not have a description
+ */
+ public String getAccessibleDescription() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ return ac.getAccessibleDescription();
+ } else {
+ return super.getAccessibleDescription();
+ }
+ }
+
+ /**
+ * Set the accessible description of this object.
+ *
+ * @param s the new localized description of the object
+ */
+ public void setAccessibleDescription(String s) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ ac.setAccessibleDescription(s);
+ } else {
+ super.setAccessibleDescription(s);
+ }
+ }
+
+ /**
+ * Get the role of this object.
+ *
+ * @return an instance of AccessibleRole describing the role of the object
+ * @see AccessibleRole
+ */
+ public AccessibleRole getAccessibleRole() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ return ac.getAccessibleRole();
+ } else {
+ return AccessibleRole.UNKNOWN;
+ }
+ }
+
+ /**
+ * Get the state set of this object.
+ *
+ * @return an instance of AccessibleStateSet containing the
+ * current state set of the object
+ * @see AccessibleState
+ */
+ public AccessibleStateSet getAccessibleStateSet() {
+ if (tree == null)
+ return null;
+ AccessibleContext ac = getCurrentAccessibleContext();
+ AccessibleStateSet states;
+ int row = tree.getUI().getRowForPath(tree,path);
+ int lsr = tree.getLeadSelectionRow();
+ if (ac != null) {
+ states = ac.getAccessibleStateSet();
+ } else {
+ states = new AccessibleStateSet();
+ }
+ // need to test here, 'cause the underlying component
+ // is a cellRenderer, which is never showing...
+ if (isShowing()) {
+ states.add(AccessibleState.SHOWING);
+ } else if (states.contains(AccessibleState.SHOWING)) {
+ states.remove(AccessibleState.SHOWING);
+ }
+ if (isVisible()) {
+ states.add(AccessibleState.VISIBLE);
+ } else if (states.contains(AccessibleState.VISIBLE)) {
+ states.remove(AccessibleState.VISIBLE);
+ }
+ if (tree.isPathSelected(path)){
+ states.add(AccessibleState.SELECTED);
+ }
+ if (lsr == row) {
+ states.add(AccessibleState.ACTIVE);
+ }
+ if (!isLeaf) {
+ states.add(AccessibleState.EXPANDABLE);
+ }
+ if (tree.isExpanded(path)) {
+ states.add(AccessibleState.EXPANDED);
+ } else {
+ states.add(AccessibleState.COLLAPSED);
+ }
+ if (tree.isEditable()) {
+ states.add(AccessibleState.EDITABLE);
+ }
+ return states;
+ }
+
+ /**
+ * Get the Accessible parent of this object.
+ *
+ * @return the Accessible parent of this object; null if this
+ * object does not have an Accessible parent
+ */
+ public Accessible getAccessibleParent() {
+ // someone wants to know, so we need to create our parent
+ // if we don't have one (hey, we're a talented kid!)
+ if (accessibleParent == null && path != null) {
+ Object[] objPath = path.getPath();
+ if (objPath.length > 1) {
+ Object objParent = objPath[objPath.length-2];
+ if (treeModel != null) {
+ index = treeModel.getIndexOfChild(objParent, obj);
+ }
+ Object[] objParentPath = new Object[objPath.length-1];
+ java.lang.System.arraycopy(objPath, 0, objParentPath,
+ 0, objPath.length-1);
+ TreePath parentPath = new TreePath(objParentPath);
+ accessibleParent = new AccessibleJTreeNode(tree,
+ parentPath,
+ null);
+ this.setAccessibleParent(accessibleParent);
+ } else if (treeModel != null) {
+ accessibleParent = tree; // we're the top!
+ index = 0; // we're an only child!
+ this.setAccessibleParent(accessibleParent);
+ }
+ }
+ return accessibleParent;
+ }
+
+ /**
+ * Get the index of this object in its accessible parent.
+ *
+ * @return the index of this object in its parent; -1 if this
+ * object does not have an accessible parent.
+ * @see #getAccessibleParent
+ */
+ public int getAccessibleIndexInParent() {
+ // index is invalid 'till we have an accessibleParent...
+ if (accessibleParent == null) {
+ getAccessibleParent();
+ }
+ if (path != null) {
+ Object[] objPath = path.getPath();
+ if (objPath.length > 1) {
+ Object objParent = objPath[objPath.length-2];
+ if (treeModel != null) {
+ index = treeModel.getIndexOfChild(objParent, obj);
+ }
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Returns the number of accessible children in the object.
+ *
+ * @return the number of accessible children in the object.
+ */
+ public int getAccessibleChildrenCount() {
+ // Tree nodes can't be so complex that they have
+ // two sets of children -> we're ignoring that case
+ if (obj != null && treeModel != null) {
+ return treeModel.getChildCount(obj);
+ }
+ return 0;
+ }
+
+ /**
+ * Return the specified Accessible child of the object.
+ *
+ * @param i zero-based index of child
+ * @return the Accessible child of the object
+ */
+ public Accessible getAccessibleChild(int i) {
+ // Tree nodes can't be so complex that they have
+ // two sets of children -> we're ignoring that case
+ if (i < 0 || i >= getAccessibleChildrenCount() || path == null || treeModel == null) {
+ return null;
+ } else {
+ Object childObj = treeModel.getChild(obj, i);
+ Object[] objPath = path.getPath();
+ Object[] objChildPath = new Object[objPath.length+1];
+ java.lang.System.arraycopy(objPath, 0, objChildPath, 0, objPath.length);
+ objChildPath[objChildPath.length-1] = childObj;
+ TreePath childPath = new TreePath(objChildPath);
+ return new AccessibleJTreeNode(tree, childPath, this);
+ }
+ }
+
+ /**
+ * Gets the locale of the component. If the component does not have
+ * a locale, then the locale of its parent is returned.
+ *
+ * @return This component's locale. If this component does not have
+ * a locale, the locale of its parent is returned.
+ * @exception IllegalComponentStateException
+ * If the Component does not have its own locale and has not yet
+ * been added to a containment hierarchy such that the locale can be
+ * determined from the containing parent.
+ * @see #setLocale
+ */
+ public Locale getLocale() {
+ if (tree == null)
+ return null;
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ return ac.getLocale();
+ } else {
+ return tree.getLocale();
+ }
+ }
+
+ /**
+ * Add a PropertyChangeListener to the listener list.
+ * The listener is registered for all properties.
+ *
+ * @param l The PropertyChangeListener to be added
+ */
+ public void addPropertyChangeListener(PropertyChangeListener l) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ ac.addPropertyChangeListener(l);
+ } else {
+ super.addPropertyChangeListener(l);
+ }
+ }
+
+ /**
+ * Remove a PropertyChangeListener from the listener list.
+ * This removes a PropertyChangeListener that was registered
+ * for all properties.
+ *
+ * @param l The PropertyChangeListener to be removed
+ */
+ public void removePropertyChangeListener(PropertyChangeListener l) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ ac.removePropertyChangeListener(l);
+ } else {
+ super.removePropertyChangeListener(l);
+ }
+ }
+
+ /**
+ * Get the AccessibleAction associated with this object. In the
+ * implementation of the Java Accessibility API for this class,
+ * return this object, which is responsible for implementing the
+ * AccessibleAction interface on behalf of itself.
+ *
+ * @return this object
+ */
+ public AccessibleAction getAccessibleAction() {
+ return this;
+ }
+
+ /**
+ * Get the AccessibleComponent associated with this object. In the
+ * implementation of the Java Accessibility API for this class,
+ * return this object, which is responsible for implementing the
+ * AccessibleComponent interface on behalf of itself.
+ *
+ * @return this object
+ */
+ public AccessibleComponent getAccessibleComponent() {
+ return this; // to override getBounds()
+ }
+
+ /**
+ * Get the AccessibleSelection associated with this object if one
+ * exists. Otherwise return null.
+ *
+ * @return the AccessibleSelection, or null
+ */
+ public AccessibleSelection getAccessibleSelection() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null && isLeaf) {
+ return getCurrentAccessibleContext().getAccessibleSelection();
+ } else {
+ return this;
+ }
+ }
+
+ /**
+ * Get the AccessibleText associated with this object if one
+ * exists. Otherwise return null.
+ *
+ * @return the AccessibleText, or null
+ */
+ public AccessibleText getAccessibleText() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ return getCurrentAccessibleContext().getAccessibleText();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the AccessibleValue associated with this object if one
+ * exists. Otherwise return null.
+ *
+ * @return the AccessibleValue, or null
+ */
+ public AccessibleValue getAccessibleValue() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ return getCurrentAccessibleContext().getAccessibleValue();
+ } else {
+ return null;
+ }
+ }
+
+
+ // AccessibleComponent methods
+
+ /**
+ * Get the background color of this object.
+ *
+ * @return the background color, if supported, of the object;
+ * otherwise, null
+ */
+ public Color getBackground() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ac).getBackground();
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ return c.getBackground();
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Set the background color of this object.
+ *
+ * @param c the new Color for the background
+ */
+ public void setBackground(Color c) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).setBackground(c);
+ } else {
+ Component cp = getCurrentComponent();
+ if ( cp != null) {
+ cp.setBackground(c);
+ }
+ }
+ }
+
+
+ /**
+ * Get the foreground color of this object.
+ *
+ * @return the foreground color, if supported, of the object;
+ * otherwise, null
+ */
+ public Color getForeground() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ac).getForeground();
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ return c.getForeground();
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public void setForeground(Color c) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).setForeground(c);
+ } else {
+ Component cp = getCurrentComponent();
+ if (cp != null) {
+ cp.setForeground(c);
+ }
+ }
+ }
+
+ public Cursor getCursor() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ac).getCursor();
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ return c.getCursor();
+ } else {
+ Accessible ap = getAccessibleParent();
+ if (ap instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ap).getCursor();
+ } else {
+ return null;
+ }
+ }
+ }
+ }
+
+ public void setCursor(Cursor c) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).setCursor(c);
+ } else {
+ Component cp = getCurrentComponent();
+ if (cp != null) {
+ cp.setCursor(c);
+ }
+ }
+ }
+
+ public Font getFont() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ac).getFont();
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ return c.getFont();
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public void setFont(Font f) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).setFont(f);
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ c.setFont(f);
+ }
+ }
+ }
+
+ public FontMetrics getFontMetrics(Font f) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ac).getFontMetrics(f);
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ return c.getFontMetrics(f);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public boolean isEnabled() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ac).isEnabled();
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ return c.isEnabled();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public void setEnabled(boolean b) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).setEnabled(b);
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ c.setEnabled(b);
+ }
+ }
+ }
+
+ public boolean isVisible() {
+ if (tree == null)
+ return false;
+ Rectangle pathBounds = tree.getPathBounds(path);
+ Rectangle parentBounds = tree.getVisibleRect();
+ if ( pathBounds != null && parentBounds != null &&
+ parentBounds.intersects(pathBounds) ) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public void setVisible(boolean b) {
+ }
+
+ public boolean isShowing() {
+ return (tree.isShowing() && isVisible());
+ }
+
+ public boolean contains(Point p) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ Rectangle r = ((AccessibleComponent) ac).getBounds();
+ return r.contains(p);
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ Rectangle r = c.getBounds();
+ return r.contains(p);
+ } else {
+ return getBounds().contains(p);
+ }
+ }
+ }
+
+ public Point getLocationOnScreen() {
+ if (tree != null) {
+ Point treeLocation = tree.getLocationOnScreen();
+ Rectangle pathBounds = tree.getPathBounds(path);
+ if (treeLocation != null && pathBounds != null) {
+ Point nodeLocation = new Point(pathBounds.x,
+ pathBounds.y);
+ nodeLocation.translate(treeLocation.x, treeLocation.y);
+ return nodeLocation;
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ private Point getLocationInJTree() {
+ Rectangle r = tree.getPathBounds(path);
+ if (r != null) {
+ return r.getLocation();
+ } else {
+ return null;
+ }
+ }
+
+ public Point getLocation() {
+ Rectangle r = getBounds();
+ if (r != null) {
+ return r.getLocation();
+ } else {
+ return null;
+ }
+ }
+
+ public void setLocation(Point p) {
+ }
+
+ public Rectangle getBounds() {
+ if (tree == null)
+ return null;
+ Rectangle r = tree.getPathBounds(path);
+ Accessible parent = getAccessibleParent();
+ if (parent instanceof AccessibleJTreeNode) {
+ Point parentLoc = ((AccessibleJTreeNode) parent).getLocationInJTree();
+ if (parentLoc != null && r != null) {
+ r.translate(-parentLoc.x, -parentLoc.y);
+ } else {
+ return null; // not visible!
+ }
+ }
+ return r;
+ }
+
+ public void setBounds(Rectangle r) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).setBounds(r);
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ c.setBounds(r);
+ }
+ }
+ }
+
+ public Dimension getSize() {
+ return getBounds().getSize();
+ }
+
+ public void setSize (Dimension d) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).setSize(d);
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ c.setSize(d);
+ }
+ }
+ }
+
+ /**
+ * Returns the Accessible child, if one exists,
+ * contained at the local coordinate Point.
+ * Otherwise returns null.
+ *
+ * @param p point in local coordinates of this
+ * Accessible
+ * @return the Accessible, if it exists,
+ * at the specified location; else null
+ */
+ public Accessible getAccessibleAt(Point p) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ac).getAccessibleAt(p);
+ } else {
+ return null;
+ }
+ }
+
+ public boolean isFocusTraversable() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ return ((AccessibleComponent) ac).isFocusTraversable();
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ return c.isFocusable();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ public void requestFocus() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).requestFocus();
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ c.requestFocus();
+ }
+ }
+ }
+
+ public void addFocusListener(FocusListener l) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).addFocusListener(l);
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ c.addFocusListener(l);
+ }
+ }
+ }
+
+ public void removeFocusListener(FocusListener l) {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac instanceof AccessibleComponent) {
+ ((AccessibleComponent) ac).removeFocusListener(l);
+ } else {
+ Component c = getCurrentComponent();
+ if (c != null) {
+ c.removeFocusListener(l);
+ }
+ }
+ }
+
+ // AccessibleSelection methods
+
+ /**
+ * Returns the number of items currently selected.
+ * If no items are selected, the return value will be 0.
+ *
+ * @return the number of items currently selected.
+ */
+ public int getAccessibleSelectionCount() {
+ int count = 0;
+ int childCount = getAccessibleChildrenCount();
+ for (int i = 0; i < childCount; i++) {
+ TreePath childPath = getChildTreePath(i);
+ if (tree.isPathSelected(childPath)) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Returns an Accessible representing the specified selected item
+ * in the object. If there isn't a selection, or there are
+ * fewer items selected than the integer passed in, the return
+ * value will be null.
+ *
+ * @param i the zero-based index of selected items
+ * @return an Accessible containing the selected item
+ */
+ public Accessible getAccessibleSelection(int i) {
+ int childCount = getAccessibleChildrenCount();
+ if (i < 0 || i >= childCount) {
+ return null; // out of range
+ }
+ int count = 0;
+ for (int j = 0; j < childCount && i >= count; j++) {
+ TreePath childPath = getChildTreePath(j);
+ if (tree.isPathSelected(childPath)) {
+ if (count == i) {
+ return new AccessibleJTreeNode(tree, childPath, this);
+ } else {
+ count++;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the current child of this object is selected.
+ *
+ * @param i the zero-based index of the child in this Accessible
+ * object.
+ * @see AccessibleContext#getAccessibleChild
+ */
+ public boolean isAccessibleChildSelected(int i) {
+ int childCount = getAccessibleChildrenCount();
+ if (i < 0 || i >= childCount) {
+ return false; // out of range
+ } else {
+ TreePath childPath = getChildTreePath(i);
+ return tree.isPathSelected(childPath);
+ }
+ }
+
+ /**
+ * Adds the specified selected item in the object to the object's
+ * selection. If the object supports multiple selections,
+ * the specified item is added to any existing selection, otherwise
+ * it replaces any existing selection in the object. If the
+ * specified item is already selected, this method has no effect.
+ *
+ * @param i the zero-based index of selectable items
+ */
+ public void addAccessibleSelection(int i) {
+ if (tree == null)
+ return;
+ TreeModel model = tree.getModel();
+ if (model != null) {
+ if (i >= 0 && i < getAccessibleChildrenCount()) {
+ TreePath path = getChildTreePath(i);
+ tree.addSelectionPath(path);
+ }
+ }
+ }
+
+ /**
+ * Removes the specified selected item in the object from the
+ * object's
+ * selection. If the specified item isn't currently selected, this
+ * method has no effect.
+ *
+ * @param i the zero-based index of selectable items
+ */
+ public void removeAccessibleSelection(int i) {
+ if (tree == null)
+ return;
+ TreeModel model = tree.getModel();
+ if (model != null) {
+ if (i >= 0 && i < getAccessibleChildrenCount()) {
+ TreePath path = getChildTreePath(i);
+ tree.removeSelectionPath(path);
+ }
+ }
+ }
+
+ /**
+ * Clears the selection in the object, so that nothing in the
+ * object is selected.
+ */
+ public void clearAccessibleSelection() {
+ int childCount = getAccessibleChildrenCount();
+ for (int i = 0; i < childCount; i++) {
+ removeAccessibleSelection(i);
+ }
+ }
+
+ /**
+ * Causes every selected item in the object to be selected
+ * if the object supports multiple selections.
+ */
+ public void selectAllAccessibleSelection() {
+ if (tree == null)
+ return;
+ TreeModel model = tree.getModel();
+ if (model != null) {
+ int childCount = getAccessibleChildrenCount();
+ TreePath path;
+ for (int i = 0; i < childCount; i++) {
+ path = getChildTreePath(i);
+ tree.addSelectionPath(path);
+ }
+ }
+ }
+
+ // AccessibleAction methods
+
+ /**
+ * Returns the number of accessible actions available in this
+ * tree node. If this node is not a leaf, there is at least
+ * one action (toggle expand), in addition to any available
+ * on the object behind the TreeCellRenderer.
+ *
+ * @return the number of Actions in this object
+ */
+ public int getAccessibleActionCount() {
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (ac != null) {
+ AccessibleAction aa = ac.getAccessibleAction();
+ if (aa != null) {
+ return (aa.getAccessibleActionCount() + (isLeaf ? 0 : 1));
+ }
+ }
+ return isLeaf ? 0 : 1;
+ }
+
+ /**
+ * Return a description of the specified action of the tree node.
+ * If this node is not a leaf, there is at least one action
+ * description (toggle expand), in addition to any available
+ * on the object behind the TreeCellRenderer.
+ *
+ * @param i zero-based index of the actions
+ * @return a description of the action
+ */
+ public String getAccessibleActionDescription(int i) {
+ if (i < 0 || i >= getAccessibleActionCount()) {
+ return null;
+ }
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (i == 0) {
+ // TIGER - 4766636
+ // return AccessibleAction.TOGGLE_EXPAND;
+ return "toggle expand";
+ } else if (ac != null) {
+ AccessibleAction aa = ac.getAccessibleAction();
+ if (aa != null) {
+ return aa.getAccessibleActionDescription(i - 1);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Perform the specified Action on the tree node. If this node
+ * is not a leaf, there is at least one action which can be
+ * done (toggle expand), in addition to any available on the
+ * object behind the TreeCellRenderer.
+ *
+ * @param i zero-based index of actions
+ * @return true if the the action was performed; else false.
+ */
+ public boolean doAccessibleAction(int i) {
+ if (i < 0 || i >= getAccessibleActionCount()) {
+ return false;
+ }
+ AccessibleContext ac = getCurrentAccessibleContext();
+ if (i == 0) {
+ if (tree.isExpanded(path)) {
+ tree.collapsePath(path);
+ } else {
+ tree.expandPath(path);
+ }
+ return true;
+ } else if (ac != null) {
+ AccessibleAction aa = ac.getAccessibleAction();
+ if (aa != null) {
+ return aa.doAccessibleAction(i - 1);
+ }
+ }
+ return false;
+ }
+
+ } // inner class AccessibleJTreeNode
+
+ /**
+ * A helper class to perform {@code Callable} objects on the event dispatch thread appropriate
+ * for the provided {@code AccessibleContext}.
+ */
+ private static class InvocationUtils {
+
+ /**
+ * Invokes a {@code Callable} in the {@code AppContext} of the given {@code Accessible}
+ * and waits for it to finish blocking the caller thread.
+ *
+ * @param callable the {@code Callable} to invoke
+ * @param accessible the {@code Accessible} which would be used to find the right context
+ * for the task execution
+ * @param type parameter for the result value
+ *
+ * @return the result of the {@code Callable} execution
+ */
+ public static T invokeAndWait(final Callable callable,
+ final Accessible accessible) {
+ if (accessible instanceof Component) {
+ return invokeAndWait(callable, (Component)accessible);
+ }
+ if (accessible instanceof AccessibleContext) {
+ // This case also covers the Translator
+ return invokeAndWait(callable, (AccessibleContext)accessible);
+ }
+ throw new RuntimeException("Unmapped Accessible used to dispatch event: " + accessible);
+ }
+
+ /**
+ * Invokes a {@code Callable} in the {@code AppContext} of the given {@code Component}
+ * and waits for it to finish blocking the caller thread.
+ *
+ * @param callable the {@code Callable} to invoke
+ * @param component the {@code Component} which would be used to find the right context
+ * for the task execution
+ * @param type parameter for the result value
+ *
+ * @return the result of the {@code Callable} execution
+ */
+ public static T invokeAndWait(final Callable callable,
+ final Component component) {
+ return invokeAndWait(callable, SunToolkit.targetToAppContext(component));
+ }
+
+ /**
+ * Invokes a {@code Callable} in the {@code AppContext} mapped to the given {@code AccessibleContext}
+ * and waits for it to finish blocking the caller thread.
+ *
+ * @param callable the {@code Callable} to invoke
+ * @param accessibleContext the {@code AccessibleContext} which would be used to determine the right
+ * context for the task execution.
+ * @param type parameter for the result value
+ *
+ * @return the result of the {@code Callable} execution
+ */
+ public static T invokeAndWait(final Callable callable,
+ final AccessibleContext accessibleContext) {
+ AppContext targetContext = AWTAccessor.getAccessibleContextAccessor()
+ .getAppContext(accessibleContext);
+ if (targetContext != null) {
+ return invokeAndWait(callable, targetContext);
+ } else {
+ // Normally this should not happen, unmapped context provided and
+ // the target AppContext is unknown.
+
+ // Try to recover in case the context is a translator.
+ if (accessibleContext instanceof Translator) {
+ Object source = ((Translator)accessibleContext).getSource();
+ if (source instanceof Component) {
+ return invokeAndWait(callable, (Component)source);
+ }
+ }
+ }
+ throw new RuntimeException("Unmapped AccessibleContext used to dispatch event: " + accessibleContext);
+ }
+
+ private static T invokeAndWait(final Callable callable,
+ final AppContext targetAppContext) {
+ final CallableWrapper wrapper = new CallableWrapper(callable);
+ try {
+ invokeAndWait(wrapper, targetAppContext);
+ T result = wrapper.getResult();
+ updateAppContextMap(result, targetAppContext);
+ return result;
+ } catch (final Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void invokeAndWait(final Runnable runnable,
+ final AppContext appContext)
+ throws InterruptedException, InvocationTargetException {
+
+ EventQueue eq = SunToolkit.getSystemEventQueueImplPP(appContext);
+ Object lock = new Object();
+ Toolkit source = Toolkit.getDefaultToolkit();
+ InvocationEvent event =
+ new InvocationEvent(source, runnable, lock, true);
+ synchronized (lock) {
+ eq.postEvent(event);
+ lock.wait();
+ }
+
+ Throwable eventThrowable = event.getThrowable();
+ if (eventThrowable != null) {
+ throw new InvocationTargetException(eventThrowable);
+ }
+ }
+
+ /**
+ * Maps the {@code AccessibleContext} to the {@code AppContext} which should be used
+ * to dispatch events related to the {@code AccessibleContext}
+ * @param accessibleContext the {@code AccessibleContext} for the mapping
+ * @param targetContext the {@code AppContext} for the mapping
+ */
+ public static void registerAccessibleContext(final AccessibleContext accessibleContext,
+ final AppContext targetContext) {
+ if (accessibleContext != null) {
+ AWTAccessor.getAccessibleContextAccessor().setAppContext(accessibleContext, targetContext);
+ }
+ }
+
+ private static void updateAppContextMap(final T accessibleContext,
+ final AppContext targetContext) {
+ if (accessibleContext instanceof AccessibleContext) {
+ registerAccessibleContext((AccessibleContext)accessibleContext, targetContext);
+ }
+ }
+
+ private static class CallableWrapper implements Runnable {
+ private final Callable callable;
+ private volatile T object;
+ private Exception e;
+
+ CallableWrapper(final Callable callable) {
+ this.callable = callable;
+ }
+
+ public void run() {
+ try {
+ if (callable != null) {
+ object = callable.call();
+ }
+ } catch (final Exception e) {
+ this.e = e;
+ }
+ }
+
+ T getResult() throws Exception {
+ if (e != null)
+ throw e;
+ return object;
+ }
+ }
+ }
+}
diff --git a/jdk/src/jdk.accessibility/windows/conf/accessibility.properties b/jdk/src/jdk.accessibility/windows/conf/accessibility.properties
new file mode 100644
index 00000000000..7217be09feb
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/conf/accessibility.properties
@@ -0,0 +1,6 @@
+#
+# Load the Java Access Bridge class into the JVM
+#
+#assistive_technologies=com.sun.java.accessibility.AccessBridge
+#screen_magnifier_present=true
+
diff --git a/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.cpp b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.cpp
new file mode 100644
index 00000000000..e7325a84ffd
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * A class to manage AccessBridge debugging
+ */
+
+#include "AccessBridgeDebug.h"
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * print a GetLastError message
+ */
+char *printError(char *msg) {
+ LPVOID lpMsgBuf = NULL;
+ static char retbuf[256];
+
+ if (msg != NULL) {
+ strncpy((char *)retbuf, msg, sizeof(retbuf));
+ }
+ if (!FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL ))
+ {
+ PrintDebugString(" %s: FormatMessage failed", msg);
+ } else {
+ PrintDebugString(" %s: %s", msg, (char *)lpMsgBuf);
+ }
+ if (lpMsgBuf != NULL) {
+ strncat((char *)retbuf, ": ", sizeof(retbuf) - strlen(retbuf) - 1);
+ strncat((char *)retbuf, (char *)lpMsgBuf, sizeof(retbuf) - strlen(retbuf) - 1);
+ }
+ return (char *)retbuf;
+}
+
+
+ /**
+ * Send debugging info to the appropriate place
+ */
+ void PrintDebugString(char *msg, ...) {
+#ifdef DEBUGGING_ON
+ char buf[1024];
+ va_list argprt;
+
+ va_start(argprt, msg); // set up argptr
+ vsprintf(buf, msg, argprt);
+#ifdef SEND_TO_OUTPUT_DEBUG_STRING
+ OutputDebugString(buf);
+#endif
+#ifdef SEND_TO_CONSOLE
+ printf(buf);
+ printf("\r\n");
+#endif
+#endif
+ }
+
+ /**
+ * Send Java debugging info to the appropriate place
+ */
+ void PrintJavaDebugString2(char *msg, ...) {
+#ifdef JAVA_DEBUGGING_ON
+ char buf[1024];
+ va_list argprt;
+
+ va_start(argprt, msg); // set up argptr
+ vsprintf(buf, msg, argprt);
+#ifdef SEND_TO_OUTPUT_DEBUG_STRING
+ OutputDebugString(buf);
+#endif
+#ifdef SEND_TO_CONSOLE
+ printf(buf);
+ printf("\r\n");
+#endif
+#endif
+ }
+ /**
+ * Wide version of the method to send debugging info to the appropriate place
+ */
+ void wPrintDebugString(wchar_t *msg, ...) {
+#ifdef DEBUGGING_ON
+ char buf[1024];
+ char charmsg[256];
+ va_list argprt;
+
+ va_start(argprt, msg); // set up argptr
+ sprintf(charmsg, "%ls", msg); // convert format string to multi-byte
+ vsprintf(buf, charmsg, argprt);
+#ifdef SEND_TO_OUTPUT_DEBUG_STRING
+ OutputDebugString(buf);
+#endif
+#ifdef SEND_TO_CONSOLE
+ printf(buf);
+ printf("\r\n");
+#endif
+#endif
+ }
+
+ /**
+ * Wide version of the method to send Java debugging info to the appropriate place
+ */
+ void wPrintJavaDebugString(wchar_t *msg, ...) {
+#ifdef JAVA_DEBUGGING_ON
+ char buf[1024];
+ char charmsg[256];
+ va_list argprt;
+
+ va_start(argprt, msg); // set up argptr
+ sprintf(charmsg, "%ls", msg); // convert format string to multi-byte
+ vsprintf(buf, charmsg, argprt);
+#ifdef SEND_TO_OUTPUT_DEBUG_STRING
+ OutputDebugString(buf);
+#endif
+#ifdef SEND_TO_CONSOLE
+ printf(buf);
+ printf("\r\n");
+#endif
+#endif
+ }
+#ifdef __cplusplus
+}
+#endif
diff --git a/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.h b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.h
new file mode 100644
index 00000000000..1ac7426d6e0
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeDebug.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * A class to manage AccessBridge debugging
+ */
+
+#ifndef __AccessBridgeDebug_H__
+#define __AccessBridgeDebug_H__
+
+#include
+#include
+
+#ifdef DEBUG
+#define DEBUGGING_ON
+#define SEND_TO_OUTPUT_DEBUG_STRING
+//#define JAVA_DEBUGGING_ON
+#endif
+
+#ifdef DEBUGGING_ON
+#define DEBUG_CODE(x) x
+#else
+#define DEBUG_CODE(x) /* */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ char *printError(char *msg);
+ void PrintDebugString(char *msg, ...);
+ void PrintJavaDebugString(char *msg, ...);
+ void wPrintJavaDebugString(wchar_t *msg, ...);
+ void wPrintDebugString(wchar_t *msg, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeMessages.cpp b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeMessages.cpp
new file mode 100644
index 00000000000..e071b9873cb
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeMessages.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Common AccessBridge IPC message definitions
+ */
+
+#include "AccessBridgeMessages.h"
+
+
+// unique broadcast msg. IDs gotten dymanically
+
+// wParam == sourceHwnc; lParam = *vmID
+UINT theFromJavaHelloMsgID;
+// wParam == sourceHwnc; lParam unused
+UINT theFromWindowsHelloMsgID;
+
+
+BOOL initBroadcastMessageIDs() {
+ theFromJavaHelloMsgID = RegisterWindowMessage("AccessBridge-FromJava-Hello");
+ theFromWindowsHelloMsgID = RegisterWindowMessage("AccessBridge-FromWindows-Hello");
+
+ if (theFromJavaHelloMsgID == 0 || theFromWindowsHelloMsgID) {
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeMessages.h b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeMessages.h
new file mode 100644
index 00000000000..08c67f6e5c3
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeMessages.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Common AccessBridge IPC message definitions
+ */
+
+#include
+#include
+
+#ifndef __AccessBridgeMessages_H__
+#define __AccessBridgeMessages_H__
+
+
+// used for messages between AccessBridge dlls to manage IPC
+// In the SendMessage call, the third param (WPARAM) is
+// the source HWND (ourAccessBridgeWindow in this case),
+// and the fourth param (LPARAM) is the size in bytes of
+// the package put into shared memory.
+#define AB_MEMORY_MAPPED_FILE_SETUP (WM_USER+0x1000)
+
+// used for messages between AccessBridge dlls to manage IPC
+// In the SendMessage call, the third param (WPARAM) is
+// the source HWND (ourAccessBridgeWindow in this case),
+// and the fourth param (LPARAM) is the size in bytes of
+// the package put into shared memory.
+#define AB_MESSAGE_WAITING (WM_USER+0x1001)
+
+// used for messages from JavaDLL to itself (or perhaps later also
+// for messages from WindowsDLL to itself). Used with PostMessage,
+// it is called for deferred processing of messages to send across
+// to another DLL (or DLLs)
+#define AB_MESSAGE_QUEUED (WM_USER+0x1002)
+
+// used to let other AccessBridge DLLs know that one of the DLLs
+// they are communicating with is going away (not reversable)
+#define AB_DLL_GOING_AWAY (WM_USER+0x1003)
+
+
+// used as part of the Memory-Mapped file IPC setup. The first
+// constant is the query, the second the response, that are put
+// into the memory mapped file for reading by the opposite DLL
+// to verify that communication is working
+#define AB_MEMORY_MAPPED_FILE_OK_QUERY "OK?"
+#define AB_MEMORY_MAPPED_FILE_OK_ANSWER "OK!"
+
+
+BOOL initBroadcastMessageIDs();
+
+
+#endif
diff --git a/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeStatusWindow.RC b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeStatusWindow.RC
new file mode 100644
index 00000000000..86f62fe5847
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/common/AccessBridgeStatusWindow.RC
@@ -0,0 +1,175 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+#include "accessBridgeResource.h"
+
+#define XSTR(x) STR(x)
+#define STR(x) #x
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#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
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+ACCESSBRIDGESTATUSWINDOW DIALOGEX 160, 78, 209, 163
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_CLIENTEDGE
+CAPTION "Access Bridge status"
+FONT 8, "MS Sans Serif", 0, 0, 0x1
+BEGIN
+ EDITTEXT cVMID,67,23,121,13,ES_READONLY
+ EDITTEXT cStatusText,40,147,162,13,ES_READONLY
+ LTEXT "Java VM ID:",IDC_STATIC,23,25,40,8
+ LTEXT "Status:",IDC_STATIC,11,149,23,8
+ EDITTEXT cWindowsID,67,39,121,13,ES_READONLY
+ LTEXT "Windows ID:",IDC_STATIC,21,41,42,8
+ EDITTEXT cCallInfo,12,65,184,75,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
+ GROUPBOX "Call info",IDC_STATIC,4,55,197,90
+ EDITTEXT cInvokedByText,67,1,121,13,ES_READONLY
+ LTEXT "Invoked by:",IDC_STATIC,25,3,38,8
+END
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Dialog"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,129,7,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ "ACCESSBRIDGESTATUSWINDOW", DIALOG
+ BEGIN
+ LEFTMARGIN, 4
+ RIGHTMARGIN, 202
+ BOTTOMMARGIN, 160
+ END
+
+ "IDD_DIALOG1", DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 179
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 88
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION JDK_FVER
+ PRODUCTVERSION JDK_FVER
+ FILEFLAGSMASK 0x3fL
+#ifdef DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE JDK_FTYPE
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "Java Access Bridge\0"
+ VALUE "CompanyName", XSTR(JDK_COMPANY) "\0"
+ VALUE "FileDescription", XSTR(JDK_COMPONENT) "\0"
+ VALUE "FileVersion", XSTR(JDK_VER) "\0"
+ VALUE "Full Version", XSTR(JDK_BUILD_ID) "\0"
+ VALUE "InternalName", XSTR(JDK_INTERNAL_NAME) "\0"
+ VALUE "LegalCopyright", XSTR(JDK_COPYRIGHT) "\0"
+ VALUE "OriginalFilename", XSTR(JDK_FNAME) "\0"
+ VALUE "ProductName", XSTR(JDK_NAME) "\0"
+ VALUE "ProductVersion", XSTR(JDK_VER) "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/jdk/src/jdk.accessibility/windows/native/common/accessBridgeResource.h b/jdk/src/jdk.accessibility/windows/native/common/accessBridgeResource.h
new file mode 100644
index 00000000000..eeb36751953
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/common/accessBridgeResource.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#define cVMID 1001
+#define cWindowsID 1002
+#define cStatusText 1003
+#define cCallInfo 1004
+#define cInvokedByText 1005
+#define IDC_STATIC -1
+
+#define cInstallAccessBridge 2001
+#define cRemindThereIsNewJVM 2005
+#define cDoNotRemindThereIsNewJVM 2005
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 102
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1032
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/jdk/src/jdk.accessibility/windows/native/common/resource.h b/jdk/src/jdk.accessibility/windows/native/common/resource.h
new file mode 100644
index 00000000000..f419f9be09a
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/common/resource.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by AccessBridgeStatusWindow.RC
+//
+//#define IDB_BITMAP1 102
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1032
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCallbacks.h b/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCallbacks.h
new file mode 100644
index 00000000000..d7c62cf0828
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCallbacks.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * AccessBridgeCallbacks.h 1.17 05/03/21
+ */
+
+/*
+ * Header file defining callback typedefs for Windows routines
+ * which are called from Java (responding to events, etc.).
+ */
+
+#ifndef __AccessBridgeCallbacks_H__
+#define __AccessBridgeCallbacks_H__
+
+#include
+#include "AccessBridgePackages.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*AccessBridge_PropertyChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *property, wchar_t *oldValue, wchar_t *newValue);
+
+typedef void (*AccessBridge_JavaShutdownFP) (long vmID);
+typedef void (*AccessBridge_JavaShutdownFP) (long vmID);
+
+typedef void (*AccessBridge_FocusGainedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_FocusLostFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_CaretUpdateFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_MouseClickedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseEnteredFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseExitedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MousePressedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MouseReleasedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_MenuCanceledFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MenuDeselectedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_MenuSelectedFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuCanceledFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuWillBecomeInvisibleFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PopupMenuWillBecomeVisibleFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+
+typedef void (*AccessBridge_PropertyNameChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldName, wchar_t *newName);
+typedef void (*AccessBridge_PropertyDescriptionChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldDescription, wchar_t *newDescription);
+typedef void (*AccessBridge_PropertyStateChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldState, wchar_t *newState);
+typedef void (*AccessBridge_PropertyValueChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ wchar_t *oldValue, wchar_t *newValue);
+typedef void (*AccessBridge_PropertySelectionChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyTextChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyCaretChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ int oldPosition, int newPosition);
+typedef void (*AccessBridge_PropertyVisibleDataChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source);
+typedef void (*AccessBridge_PropertyChildChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 source,
+ JOBJECT64 oldChild, JOBJECT64 newChild);
+typedef void (*AccessBridge_PropertyActiveDescendentChangeFP) (long vmID, JOBJECT64 event,
+ JOBJECT64 source,
+ JOBJECT64 oldActiveDescendent,
+ JOBJECT64 newActiveDescendent);
+
+typedef void (*AccessBridge_PropertyTableModelChangeFP) (long vmID, JOBJECT64 event, JOBJECT64 src,
+ wchar_t *oldValue, wchar_t *newValue);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCalls.c b/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCalls.c
new file mode 100644
index 00000000000..dc3d1019b51
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCalls.c
@@ -0,0 +1,1131 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @(#)AccessBridgeCalls.c 1.25 05/08/22
+ */
+
+/*
+ * Wrapper functions around calls to the AccessBridge DLL
+ */
+
+
+#include
+#include
+
+
+//#define ACCESSBRIDGE_32
+//#define ACCESSBRIDGE_64
+
+#include "AccessBridgeCalls.h"
+#include "AccessBridgeDebug.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ HINSTANCE theAccessBridgeInstance;
+ AccessBridgeFPs theAccessBridge;
+
+ BOOL theAccessBridgeInitializedFlag = FALSE;
+
+#define LOAD_FP(result, type, name) \
+ PrintDebugString("LOAD_FP loading: %s ...", name); \
+ if ((theAccessBridge.result = \
+ (type) GetProcAddress(theAccessBridgeInstance, name)) == (type) 0) { \
+ PrintDebugString("LOAD_FP failed: %s", name); \
+ return FALSE; \
+ }
+
+ BOOL initializeAccessBridge() {
+
+#ifdef ACCESSBRIDGE_ARCH_32 // For 32bit AT new bridge
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE-32");
+#else
+#ifdef ACCESSBRIDGE_ARCH_64 // For 64bit AT new bridge
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE-64");
+#else // legacy
+ theAccessBridgeInstance = LoadLibrary("WINDOWSACCESSBRIDGE");
+#endif
+#endif
+ if (theAccessBridgeInstance != 0) {
+ LOAD_FP(Windows_run, Windows_runFP, "Windows_run");
+
+ LOAD_FP(SetJavaShutdown, SetJavaShutdownFP, "setJavaShutdownFP");
+ LOAD_FP(SetFocusGained, SetFocusGainedFP, "setFocusGainedFP");
+ LOAD_FP(SetFocusLost, SetFocusLostFP, "setFocusLostFP");
+
+ LOAD_FP(SetCaretUpdate, SetCaretUpdateFP, "setCaretUpdateFP");
+
+ LOAD_FP(SetMouseClicked, SetMouseClickedFP, "setMouseClickedFP");
+ LOAD_FP(SetMouseEntered, SetMouseEnteredFP, "setMouseEnteredFP");
+ LOAD_FP(SetMouseExited, SetMouseExitedFP, "setMouseExitedFP");
+ LOAD_FP(SetMousePressed, SetMousePressedFP, "setMousePressedFP");
+ LOAD_FP(SetMouseReleased, SetMouseReleasedFP, "setMouseReleasedFP");
+
+ LOAD_FP(SetMenuCanceled, SetMenuCanceledFP, "setMenuCanceledFP");
+ LOAD_FP(SetMenuDeselected, SetMenuDeselectedFP, "setMenuDeselectedFP");
+ LOAD_FP(SetMenuSelected, SetMenuSelectedFP, "setMenuSelectedFP");
+ LOAD_FP(SetPopupMenuCanceled, SetPopupMenuCanceledFP, "setPopupMenuCanceledFP");
+ LOAD_FP(SetPopupMenuWillBecomeInvisible, SetPopupMenuWillBecomeInvisibleFP, "setPopupMenuWillBecomeInvisibleFP");
+ LOAD_FP(SetPopupMenuWillBecomeVisible, SetPopupMenuWillBecomeVisibleFP, "setPopupMenuWillBecomeVisibleFP");
+
+ LOAD_FP(SetPropertyNameChange, SetPropertyNameChangeFP, "setPropertyNameChangeFP");
+ LOAD_FP(SetPropertyDescriptionChange, SetPropertyDescriptionChangeFP, "setPropertyDescriptionChangeFP");
+ LOAD_FP(SetPropertyStateChange, SetPropertyStateChangeFP, "setPropertyStateChangeFP");
+ LOAD_FP(SetPropertyValueChange, SetPropertyValueChangeFP, "setPropertyValueChangeFP");
+ LOAD_FP(SetPropertySelectionChange, SetPropertySelectionChangeFP, "setPropertySelectionChangeFP");
+ LOAD_FP(SetPropertyTextChange, SetPropertyTextChangeFP, "setPropertyTextChangeFP");
+ LOAD_FP(SetPropertyCaretChange, SetPropertyCaretChangeFP, "setPropertyCaretChangeFP");
+ LOAD_FP(SetPropertyVisibleDataChange, SetPropertyVisibleDataChangeFP, "setPropertyVisibleDataChangeFP");
+ LOAD_FP(SetPropertyChildChange, SetPropertyChildChangeFP, "setPropertyChildChangeFP");
+ LOAD_FP(SetPropertyActiveDescendentChange, SetPropertyActiveDescendentChangeFP, "setPropertyActiveDescendentChangeFP");
+
+ LOAD_FP(SetPropertyTableModelChange, SetPropertyTableModelChangeFP, "setPropertyTableModelChangeFP");
+
+ LOAD_FP(ReleaseJavaObject, ReleaseJavaObjectFP, "releaseJavaObject");
+ LOAD_FP(GetVersionInfo, GetVersionInfoFP, "getVersionInfo");
+
+ LOAD_FP(IsJavaWindow, IsJavaWindowFP, "isJavaWindow");
+ LOAD_FP(IsSameObject, IsSameObjectFP, "isSameObject");
+ LOAD_FP(GetAccessibleContextFromHWND, GetAccessibleContextFromHWNDFP, "getAccessibleContextFromHWND");
+ LOAD_FP(getHWNDFromAccessibleContext, getHWNDFromAccessibleContextFP, "getHWNDFromAccessibleContext");
+
+ LOAD_FP(GetAccessibleContextAt, GetAccessibleContextAtFP, "getAccessibleContextAt");
+ LOAD_FP(GetAccessibleContextWithFocus, GetAccessibleContextWithFocusFP, "getAccessibleContextWithFocus");
+ LOAD_FP(GetAccessibleContextInfo, GetAccessibleContextInfoFP, "getAccessibleContextInfo");
+ LOAD_FP(GetAccessibleChildFromContext, GetAccessibleChildFromContextFP, "getAccessibleChildFromContext");
+ LOAD_FP(GetAccessibleParentFromContext, GetAccessibleParentFromContextFP, "getAccessibleParentFromContext");
+
+ /* begin AccessibleTable */
+ LOAD_FP(getAccessibleTableInfo, getAccessibleTableInfoFP, "getAccessibleTableInfo");
+ LOAD_FP(getAccessibleTableCellInfo, getAccessibleTableCellInfoFP, "getAccessibleTableCellInfo");
+
+ LOAD_FP(getAccessibleTableRowHeader, getAccessibleTableRowHeaderFP, "getAccessibleTableRowHeader");
+ LOAD_FP(getAccessibleTableColumnHeader, getAccessibleTableColumnHeaderFP, "getAccessibleTableColumnHeader");
+
+ LOAD_FP(getAccessibleTableRowDescription, getAccessibleTableRowDescriptionFP, "getAccessibleTableRowDescription");
+ LOAD_FP(getAccessibleTableColumnDescription, getAccessibleTableColumnDescriptionFP, "getAccessibleTableColumnDescription");
+
+ LOAD_FP(getAccessibleTableRowSelectionCount, getAccessibleTableRowSelectionCountFP,
+ "getAccessibleTableRowSelectionCount");
+ LOAD_FP(isAccessibleTableRowSelected, isAccessibleTableRowSelectedFP,
+ "isAccessibleTableRowSelected");
+ LOAD_FP(getAccessibleTableRowSelections, getAccessibleTableRowSelectionsFP,
+ "getAccessibleTableRowSelections");
+
+ LOAD_FP(getAccessibleTableColumnSelectionCount, getAccessibleTableColumnSelectionCountFP,
+ "getAccessibleTableColumnSelectionCount");
+ LOAD_FP(isAccessibleTableColumnSelected, isAccessibleTableColumnSelectedFP,
+ "isAccessibleTableColumnSelected");
+ LOAD_FP(getAccessibleTableColumnSelections, getAccessibleTableColumnSelectionsFP,
+ "getAccessibleTableColumnSelections");
+
+ LOAD_FP(getAccessibleTableRow, getAccessibleTableRowFP,
+ "getAccessibleTableRow");
+ LOAD_FP(getAccessibleTableColumn, getAccessibleTableColumnFP,
+ "getAccessibleTableColumn");
+ LOAD_FP(getAccessibleTableIndex, getAccessibleTableIndexFP,
+ "getAccessibleTableIndex");
+
+ /* end AccessibleTable */
+
+ /* AccessibleRelationSet */
+ LOAD_FP(getAccessibleRelationSet, getAccessibleRelationSetFP, "getAccessibleRelationSet");
+
+ /* AccessibleHypertext */
+ LOAD_FP(getAccessibleHypertext, getAccessibleHypertextFP, "getAccessibleHypertext");
+ LOAD_FP(activateAccessibleHyperlink, activateAccessibleHyperlinkFP, "activateAccessibleHyperlink");
+ LOAD_FP(getAccessibleHyperlinkCount, getAccessibleHyperlinkCountFP, "getAccessibleHyperlinkCount");
+ LOAD_FP(getAccessibleHypertextExt, getAccessibleHypertextExtFP, "getAccessibleHypertextExt");
+ LOAD_FP(getAccessibleHypertextLinkIndex, getAccessibleHypertextLinkIndexFP, "getAccessibleHypertextLinkIndex");
+ LOAD_FP(getAccessibleHyperlink, getAccessibleHyperlinkFP, "getAccessibleHyperlink");
+
+ /* Accessible KeyBinding, Icon and Action */
+ LOAD_FP(getAccessibleKeyBindings, getAccessibleKeyBindingsFP, "getAccessibleKeyBindings");
+ LOAD_FP(getAccessibleIcons, getAccessibleIconsFP, "getAccessibleIcons");
+ LOAD_FP(getAccessibleActions, getAccessibleActionsFP, "getAccessibleActions");
+ LOAD_FP(doAccessibleActions, doAccessibleActionsFP, "doAccessibleActions");
+
+ /* AccessibleText */
+ LOAD_FP(GetAccessibleTextInfo, GetAccessibleTextInfoFP, "getAccessibleTextInfo");
+ LOAD_FP(GetAccessibleTextItems, GetAccessibleTextItemsFP, "getAccessibleTextItems");
+ LOAD_FP(GetAccessibleTextSelectionInfo, GetAccessibleTextSelectionInfoFP, "getAccessibleTextSelectionInfo");
+ LOAD_FP(GetAccessibleTextAttributes, GetAccessibleTextAttributesFP, "getAccessibleTextAttributes");
+ LOAD_FP(GetAccessibleTextRect, GetAccessibleTextRectFP, "getAccessibleTextRect");
+ LOAD_FP(GetAccessibleTextLineBounds, GetAccessibleTextLineBoundsFP, "getAccessibleTextLineBounds");
+ LOAD_FP(GetAccessibleTextRange, GetAccessibleTextRangeFP, "getAccessibleTextRange");
+
+ LOAD_FP(GetCurrentAccessibleValueFromContext, GetCurrentAccessibleValueFromContextFP, "getCurrentAccessibleValueFromContext");
+ LOAD_FP(GetMaximumAccessibleValueFromContext, GetMaximumAccessibleValueFromContextFP, "getMaximumAccessibleValueFromContext");
+ LOAD_FP(GetMinimumAccessibleValueFromContext, GetMinimumAccessibleValueFromContextFP, "getMinimumAccessibleValueFromContext");
+
+ LOAD_FP(AddAccessibleSelectionFromContext, AddAccessibleSelectionFromContextFP, "addAccessibleSelectionFromContext");
+ LOAD_FP(ClearAccessibleSelectionFromContext, ClearAccessibleSelectionFromContextFP, "clearAccessibleSelectionFromContext");
+ LOAD_FP(GetAccessibleSelectionFromContext, GetAccessibleSelectionFromContextFP, "getAccessibleSelectionFromContext");
+ LOAD_FP(GetAccessibleSelectionCountFromContext, GetAccessibleSelectionCountFromContextFP, "getAccessibleSelectionCountFromContext");
+ LOAD_FP(IsAccessibleChildSelectedFromContext, IsAccessibleChildSelectedFromContextFP, "isAccessibleChildSelectedFromContext");
+ LOAD_FP(RemoveAccessibleSelectionFromContext, RemoveAccessibleSelectionFromContextFP, "removeAccessibleSelectionFromContext");
+ LOAD_FP(SelectAllAccessibleSelectionFromContext, SelectAllAccessibleSelectionFromContextFP, "selectAllAccessibleSelectionFromContext");
+
+ LOAD_FP(setTextContents, setTextContentsFP, "setTextContents");
+ LOAD_FP(getParentWithRole, getParentWithRoleFP, "getParentWithRole");
+ LOAD_FP(getTopLevelObject, getTopLevelObjectFP, "getTopLevelObject");
+ LOAD_FP(getParentWithRoleElseRoot, getParentWithRoleElseRootFP, "getParentWithRoleElseRoot");
+ LOAD_FP(getObjectDepth, getObjectDepthFP, "getObjectDepth");
+ LOAD_FP(getActiveDescendent, getActiveDescendentFP, "getActiveDescendent");
+
+ // additional methods for Teton
+ LOAD_FP(getVirtualAccessibleName, getVirtualAccessibleNameFP, "getVirtualAccessibleName");
+ LOAD_FP(requestFocus, requestFocusFP, "requestFocus");
+ LOAD_FP(selectTextRange, selectTextRangeFP, "selectTextRange");
+ LOAD_FP(getTextAttributesInRange, getTextAttributesInRangeFP, "getTextAttributesInRange");
+ LOAD_FP(getVisibleChildrenCount, getVisibleChildrenCountFP, "getVisibleChildrenCount");
+ LOAD_FP(getVisibleChildren, getVisibleChildrenFP, "getVisibleChildren");
+ LOAD_FP(setCaretPosition, setCaretPositionFP, "setCaretPosition");
+ LOAD_FP(getCaretLocation, getCaretLocationFP, "getCaretLocation");
+
+ LOAD_FP(getEventsWaiting, getEventsWaitingFP, "getEventsWaiting");
+
+ theAccessBridge.Windows_run();
+
+ theAccessBridgeInitializedFlag = TRUE;
+ PrintDebugString("theAccessBridgeInitializedFlag = TRUE");
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ }
+
+
+ BOOL shutdownAccessBridge() {
+ BOOL result;
+ DWORD error;
+ theAccessBridgeInitializedFlag = FALSE;
+ if (theAccessBridgeInstance != (HANDLE) 0) {
+ result = FreeLibrary(theAccessBridgeInstance);
+ if (result != TRUE) {
+ error = GetLastError();
+ }
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+
+ void SetJavaShutdown(AccessBridge_JavaShutdownFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetJavaShutdown(fp);
+ }
+ }
+
+ void SetFocusGained(AccessBridge_FocusGainedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetFocusGained(fp);
+ }
+ }
+
+ void SetFocusLost(AccessBridge_FocusLostFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetFocusLost(fp);
+ }
+ }
+
+
+ void SetCaretUpdate(AccessBridge_CaretUpdateFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetCaretUpdate(fp);
+ }
+ }
+
+
+ void SetMouseClicked(AccessBridge_MouseClickedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseClicked(fp);
+ }
+ }
+
+ void SetMouseEntered(AccessBridge_MouseEnteredFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseEntered(fp);
+ }
+ }
+
+ void SetMouseExited(AccessBridge_MouseExitedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseExited(fp);
+ }
+ }
+
+ void SetMousePressed(AccessBridge_MousePressedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMousePressed(fp);
+ }
+ }
+
+ void SetMouseReleased(AccessBridge_MouseReleasedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMouseReleased(fp);
+ }
+ }
+
+
+ void SetMenuCanceled(AccessBridge_MenuCanceledFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuCanceled(fp);
+ }
+ }
+
+ void SetMenuDeselected(AccessBridge_MenuDeselectedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuDeselected(fp);
+ }
+ }
+
+ void SetMenuSelected(AccessBridge_MenuSelectedFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetMenuSelected(fp);
+ }
+ }
+
+ void SetPopupMenuCanceled(AccessBridge_PopupMenuCanceledFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuCanceled(fp);
+ }
+ }
+
+ void SetPopupMenuWillBecomeInvisible(AccessBridge_PopupMenuWillBecomeInvisibleFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuWillBecomeInvisible(fp);
+ }
+ }
+
+ void SetPopupMenuWillBecomeVisible(AccessBridge_PopupMenuWillBecomeVisibleFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPopupMenuWillBecomeVisible(fp);
+ }
+ }
+
+
+ void SetPropertyNameChange(AccessBridge_PropertyNameChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyNameChange(fp);
+ }
+ }
+
+ void SetPropertyDescriptionChange(AccessBridge_PropertyDescriptionChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyDescriptionChange(fp);
+ }
+ }
+
+ void SetPropertyStateChange(AccessBridge_PropertyStateChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyStateChange(fp);
+ }
+ }
+
+ void SetPropertyValueChange(AccessBridge_PropertyValueChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyValueChange(fp);
+ }
+ }
+
+ void SetPropertySelectionChange(AccessBridge_PropertySelectionChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertySelectionChange(fp);
+ }
+ }
+
+ void SetPropertyTextChange(AccessBridge_PropertyTextChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyTextChange(fp);
+ }
+ }
+
+ void SetPropertyCaretChange(AccessBridge_PropertyCaretChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyCaretChange(fp);
+ }
+ }
+
+ void SetPropertyVisibleDataChange(AccessBridge_PropertyVisibleDataChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyVisibleDataChange(fp);
+ }
+ }
+
+ void SetPropertyChildChange(AccessBridge_PropertyChildChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyChildChange(fp);
+ }
+ }
+
+ void SetPropertyActiveDescendentChange(AccessBridge_PropertyActiveDescendentChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyActiveDescendentChange(fp);
+ }
+ }
+
+ void SetPropertyTableModelChange(AccessBridge_PropertyTableModelChangeFP fp) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SetPropertyTableModelChange(fp);
+ }
+ }
+
+ /**
+ * General routines
+ */
+ void ReleaseJavaObject(long vmID, Java_Object object) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.ReleaseJavaObject(vmID, object);
+ }
+ }
+
+ BOOL GetVersionInfo(long vmID, AccessBridgeVersionInfo *info) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetVersionInfo(vmID, info);
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Window routines
+ */
+ BOOL IsJavaWindow(HWND window) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ BOOL ret ;
+ ret = theAccessBridge.IsJavaWindow(window);
+ return ret ;
+
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Returns the virtual machine ID and AccessibleContext for a top-level window
+ */
+ BOOL GetAccessibleContextFromHWND(HWND target, long *vmID, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextFromHWND(target, vmID, ac);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the HWND from the AccessibleContext of a top-level window. Returns 0
+ * on error or if the AccessibleContext does not refer to a top-level window.
+ */
+ HWND getHWNDFromAccessibleContext(long vmID, JOBJECT64 accesibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getHWNDFromAccessibleContext(vmID, accesibleContext);
+ }
+ return (HWND)0;
+ }
+
+ /**
+ * returns whether two objects are the same
+ */
+ BOOL IsSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.IsSameObject(vmID, obj1, obj2);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Sets editable text contents. The AccessibleContext must implement AccessibleEditableText and
+ * be editable. The maximum text length is MAX_STRING_SIZE - 1.
+ * Returns whether successful
+ */
+ BOOL setTextContents (const long vmID, const AccessibleContext accessibleContext, const wchar_t *text) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.setTextContents(vmID, accessibleContext, text);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h
+ * If there is no ancestor object that has the specified role,
+ * returns (AccessibleContext)0.
+ */
+ AccessibleContext getParentWithRole (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getParentWithRole(vmID, accessibleContext, role);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h. If an object with the specified
+ * role does not exist, returns the top level object for the Java Window.
+ * Returns (AccessibleContext)0 on error.
+ */
+ AccessibleContext getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getParentWithRoleElseRoot(vmID, accessibleContext, role);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns the Accessible Context for the top level object in
+ * a Java Window. This is same Accessible Context that is obtained
+ * from GetAccessibleContextFromHWND for that window. Returns
+ * (AccessibleContext)0 on error.
+ */
+ AccessibleContext getTopLevelObject (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getTopLevelObject(vmID, accessibleContext);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /**
+ * Returns how deep in the object hierarchy a given object is.
+ * The top most object in the object hierarchy has an object depth of 0.
+ * Returns -1 on error.
+ */
+ int getObjectDepth (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getObjectDepth(vmID, accessibleContext);
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the Accessible Context of the current ActiveDescendent of an object.
+ * This method assumes the ActiveDescendent is the component that is currently
+ * selected in a container object.
+ * Returns (AccessibleContext)0 on error or if there is no selection.
+ */
+ AccessibleContext getActiveDescendent (const long vmID, const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getActiveDescendent(vmID, accessibleContext);
+ }
+ return (AccessibleContext)0;
+ }
+
+
+ /**
+ * Accessible Context routines
+ */
+ BOOL GetAccessibleContextAt(long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextAt(vmID, acParent, x, y, ac);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleContextWithFocus(HWND window, long *vmID, AccessibleContext *ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextWithFocus(window, vmID, ac);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleContextInfo(long vmID, AccessibleContext ac, AccessibleContextInfo *info) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleContextInfo(vmID, ac, info);
+ }
+ return FALSE;
+ }
+
+ AccessibleContext GetAccessibleChildFromContext(long vmID, AccessibleContext ac, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleChildFromContext(vmID, ac, index);
+ }
+ return (AccessibleContext) 0;
+ }
+
+ AccessibleContext GetAccessibleParentFromContext(long vmID, AccessibleContext ac) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleParentFromContext(vmID, ac);
+ }
+ return (AccessibleContext) 0;
+ }
+
+ /* begin AccessibleTable routines */
+
+ /*
+ * get information about an AccessibleTable
+ */
+ BOOL getAccessibleTableInfo(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableInfo(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable cell
+ */
+ BOOL getAccessibleTableCellInfo(long vmID, AccessibleTable accessibleTable,
+ jint row, jint column, AccessibleTableCellInfo *tableCellInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableCellInfo(vmID, accessibleTable, row, column, tableCellInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable row header
+ */
+ BOOL getAccessibleTableRowHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowHeader(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get information about an AccessibleTable column header
+ */
+ BOOL getAccessibleTableColumnHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnHeader(vmID, acParent, tableInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return a description of an AccessibleTable row header
+ */
+ AccessibleContext getAccessibleTableRowDescription(long vmID, AccessibleContext acParent, jint row) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowDescription(vmID, acParent, row);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /*
+ * return a description of an AccessibleTable column header
+ */
+ AccessibleContext getAccessibleTableColumnDescription(long vmID, AccessibleContext acParent, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnDescription(vmID, acParent, column);
+ }
+ return (AccessibleContext)0;
+ }
+
+ /*
+ * return the number of rows selected in an AccessibleTable
+ */
+ jint getAccessibleTableRowSelectionCount(long vmID, AccessibleTable table) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowSelectionCount(vmID, table);
+ }
+ return -1;
+ }
+
+ /*
+ * return whether a row is selected in an AccessibleTable
+ */
+ BOOL isAccessibleTableRowSelected(long vmID, AccessibleTable table, jint row) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.isAccessibleTableRowSelected(vmID, table, row);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get an array of selected rows in an AccessibleTable
+ */
+ BOOL getAccessibleTableRowSelections(long vmID, AccessibleTable table, jint count, jint *selections) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRowSelections(vmID, table, count, selections);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return the number of columns selected in an AccessibleTable
+ */
+ jint getAccessibleTableColumnSelectionCount(long vmID, AccessibleTable table) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnSelectionCount(vmID, table);
+ }
+ return -1;
+ }
+
+ /*
+ * return whether a column is selected in an AccessibleTable
+ */
+ BOOL isAccessibleTableColumnSelected(long vmID, AccessibleTable table, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.isAccessibleTableColumnSelected(vmID, table, column);
+ }
+ return FALSE;
+ }
+
+ /*
+ * get an array of columns selected in an AccessibleTable
+ */
+ BOOL getAccessibleTableColumnSelections(long vmID, AccessibleTable table, jint count, jint *selections) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumnSelections(vmID, table, count, selections);
+ }
+ return FALSE;
+ }
+
+ /*
+ * return the row number for a cell at a given index
+ */
+ jint
+ getAccessibleTableRow(long vmID, AccessibleTable table, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableRow(vmID, table, index);
+ }
+ return -1;
+ }
+
+ /*
+ * return the column number for a cell at a given index
+ */
+ jint
+ getAccessibleTableColumn(long vmID, AccessibleTable table, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableColumn(vmID, table, index);
+ }
+ return -1;
+ }
+
+ /*
+ * return the index of a cell at a given row and column
+ */
+ jint
+ getAccessibleTableIndex(long vmID, AccessibleTable table, jint row, jint column) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleTableIndex(vmID, table, row, column);
+ }
+ return -1;
+ }
+
+ /* end AccessibleTable routines */
+
+
+ /**
+ * Accessible Text routines
+ */
+ BOOL GetAccessibleTextInfo(long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextInfo(vmID, at, textInfo, x, y);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextItems(long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextItems(vmID, at, textItems, index);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextSelectionInfo(long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextSelectionInfo(vmID, at, textSelection);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextAttributes(long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextAttributes(vmID, at, index, attributes);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextRect(long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextRect(vmID, at, rectInfo, index);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextLineBounds(long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextLineBounds(vmID, at, index, startIndex, endIndex);
+ }
+ return FALSE;
+ }
+
+ BOOL GetAccessibleTextRange(long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleTextRange(vmID, at, start, end, text, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * AccessibleRelationSet routines
+ */
+ BOOL getAccessibleRelationSet(long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleRelationSet(vmID, accessibleContext, relationSetInfo);
+ }
+ return FALSE;
+ }
+
+ /**
+ * AccessibleHypertext routines
+ */
+
+ // Gets AccessibleHypertext for an AccessibleContext
+ BOOL getAccessibleHypertext(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertext(vmID, accessibleContext, hypertextInfo);
+ }
+ return FALSE;
+ }
+
+ // Activates an AccessibleHyperlink for an AccessibleContext
+ BOOL activateAccessibleHyperlink(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.activateAccessibleHyperlink(vmID, accessibleContext, accessibleHyperlink);
+ }
+ return FALSE;
+ }
+
+ /*
+ * Returns the number of hyperlinks in a component
+ * Maps to AccessibleHypertext.getLinkCount.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHyperlinkCount(const long vmID,
+ const AccessibleContext accessibleContext) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHyperlinkCount(vmID, accessibleContext);
+ }
+ return -1;
+ }
+
+ /*
+ * This method is used to iterate through the hyperlinks in a component. It
+ * returns hypertext information for a component starting at hyperlink index
+ * nStartIndex. No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will
+ * be returned for each call to this method.
+ * returns FALSE on error.
+ */
+ BOOL getAccessibleHypertextExt(const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ /* OUT */ AccessibleHypertextInfo *hypertextInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertextExt(vmID,
+ accessibleContext,
+ nStartIndex,
+ hypertextInfo);
+ }
+ return FALSE;
+ }
+
+ /*
+ * Returns the index into an array of hyperlinks that is associated with
+ * a character index in document;
+ * Maps to AccessibleHypertext.getLinkIndex.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHypertextLinkIndex(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHypertextLinkIndex(vmID,
+ hypertext,
+ nIndex);
+ }
+ return -1;
+ }
+
+ /*
+ * Returns the nth hyperlink in a document.
+ * Maps to AccessibleHypertext.getLink.
+ * Returns -1 on error
+ */
+ BOOL getAccessibleHyperlink(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo) {
+
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleHyperlink(vmID,
+ hypertext,
+ nIndex,
+ hyperlinkInfo);
+ }
+ return FALSE;
+ }
+
+
+ /* Accessible KeyBindings, Icons and Actions */
+ BOOL getAccessibleKeyBindings(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleKeyBindings(vmID, accessibleContext, keyBindings);
+ }
+ return FALSE;
+ }
+
+ BOOL getAccessibleIcons(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleIcons(vmID, accessibleContext, icons);
+ }
+ return FALSE;
+ }
+
+ BOOL getAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getAccessibleActions(vmID, accessibleContext, actions);
+ }
+ return FALSE;
+ }
+
+ BOOL doAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.doAccessibleActions(vmID, accessibleContext, actionsToDo, failure);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Accessible Value routines
+ */
+ BOOL GetCurrentAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetCurrentAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+ BOOL GetMaximumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetMaximumAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+ BOOL GetMinimumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetMinimumAccessibleValueFromContext(vmID, av, value, len);
+ }
+ return FALSE;
+ }
+
+
+ /**
+ * Accessible Selection routines
+ */
+ void addAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.AddAccessibleSelectionFromContext(vmID, as, i);
+ }
+ }
+
+ void clearAccessibleSelectionFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.ClearAccessibleSelectionFromContext(vmID, as);
+ }
+ }
+
+ JOBJECT64 GetAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleSelectionFromContext(vmID, as, i);
+ }
+ return (JOBJECT64) 0;
+ }
+
+ int GetAccessibleSelectionCountFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.GetAccessibleSelectionCountFromContext(vmID, as);
+ }
+ return -1;
+ }
+
+ BOOL IsAccessibleChildSelectedFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.IsAccessibleChildSelectedFromContext(vmID, as, i);
+ }
+ return FALSE;
+ }
+
+ void RemoveAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.RemoveAccessibleSelectionFromContext(vmID, as, i);
+ }
+ }
+
+ void SelectAllAccessibleSelectionFromContext(long vmID, AccessibleSelection as) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ theAccessBridge.SelectAllAccessibleSelectionFromContext(vmID, as);
+ }
+ }
+
+ /**
+ * Additional methods for Teton
+ */
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
+ * whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ BOOL getVirtualAccessibleName(const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVirtualAccessibleName(vmID, accessibleContext, name, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Request focus for a component. Returns whether successful;
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ BOOL requestFocus(const long vmID, const AccessibleContext accessibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.requestFocus(vmID, accessibleContext);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Selects text between two indices. Selection includes the text at the start index
+ * and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ BOOL selectTextRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.selectTextRange(vmID, accessibleContext, startIndex, endIndex);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Get text attributes between two indices. The attribute list includes the text at the
+ * start index and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944761 - getTextAttributes between two indices method needed
+ */
+ BOOL getTextAttributesInRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getTextAttributesInRange(vmID, accessibleContext, startIndex,
+ endIndex, attributes, len);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Returns the number of visible children of a component. Returns -1 on error.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ int getVisibleChildrenCount(const long vmID, const AccessibleContext accessibleContext) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVisibleChildrenCount(vmID, accessibleContext);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the visible children of an AccessibleContext. Returns whether successful;
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ BOOL getVisibleChildren(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, VisibleChildrenInfo *visibleChildrenInfo) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getVisibleChildren(vmID, accessibleContext, startIndex,
+ visibleChildrenInfo);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Set the caret to a text position. Returns whether successful;
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ BOOL setCaretPosition(const long vmID, const AccessibleContext accessibleContext,
+ const int position) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.setCaretPosition(vmID, accessibleContext, position);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the text caret location
+ */
+ BOOL getCaretLocation(long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, jint index) {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getCaretLocation(vmID, ac, rectInfo, index);
+ }
+ return FALSE;
+ }
+
+ /**
+ * Gets the number of events waiting to fire
+ */
+ int getEventsWaiting() {
+ if (theAccessBridgeInitializedFlag == TRUE) {
+ return theAccessBridge.getEventsWaiting();
+ }
+ return FALSE;
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCalls.h b/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCalls.h
new file mode 100644
index 00000000000..51fa08c794a
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgeCalls.h
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Wrapper functions around calls to the AccessBridge DLL
+ */
+
+#include
+#include
+#include "AccessBridgeCallbacks.h"
+#include "AccessBridgePackages.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define null NULL
+
+ typedef JOBJECT64 AccessibleContext;
+ typedef JOBJECT64 AccessibleText;
+ typedef JOBJECT64 AccessibleValue;
+ typedef JOBJECT64 AccessibleSelection;
+ typedef JOBJECT64 Java_Object;
+ typedef JOBJECT64 PropertyChangeEvent;
+ typedef JOBJECT64 FocusEvent;
+ typedef JOBJECT64 CaretEvent;
+ typedef JOBJECT64 MouseEvent;
+ typedef JOBJECT64 MenuEvent;
+ typedef JOBJECT64 AccessibleTable;
+ typedef JOBJECT64 AccessibleHyperlink;
+ typedef JOBJECT64 AccessibleHypertext;
+
+
+ typedef void (*Windows_runFP) ();
+
+ typedef void (*SetPropertyChangeFP) (AccessBridge_PropertyChangeFP fp);
+
+ typedef void (*SetJavaShutdownFP) (AccessBridge_JavaShutdownFP fp);
+ typedef void (*SetFocusGainedFP) (AccessBridge_FocusGainedFP fp);
+ typedef void (*SetFocusLostFP) (AccessBridge_FocusLostFP fp);
+
+ typedef void (*SetCaretUpdateFP) (AccessBridge_CaretUpdateFP fp);
+
+ typedef void (*SetMouseClickedFP) (AccessBridge_MouseClickedFP fp);
+ typedef void (*SetMouseEnteredFP) (AccessBridge_MouseEnteredFP fp);
+ typedef void (*SetMouseExitedFP) (AccessBridge_MouseExitedFP fp);
+ typedef void (*SetMousePressedFP) (AccessBridge_MousePressedFP fp);
+ typedef void (*SetMouseReleasedFP) (AccessBridge_MouseReleasedFP fp);
+
+ typedef void (*SetMenuCanceledFP) (AccessBridge_MenuCanceledFP fp);
+ typedef void (*SetMenuDeselectedFP) (AccessBridge_MenuDeselectedFP fp);
+ typedef void (*SetMenuSelectedFP) (AccessBridge_MenuSelectedFP fp);
+ typedef void (*SetPopupMenuCanceledFP) (AccessBridge_PopupMenuCanceledFP fp);
+ typedef void (*SetPopupMenuWillBecomeInvisibleFP) (AccessBridge_PopupMenuWillBecomeInvisibleFP fp);
+ typedef void (*SetPopupMenuWillBecomeVisibleFP) (AccessBridge_PopupMenuWillBecomeVisibleFP fp);
+
+ typedef void (*SetPropertyNameChangeFP) (AccessBridge_PropertyNameChangeFP fp);
+ typedef void (*SetPropertyDescriptionChangeFP) (AccessBridge_PropertyDescriptionChangeFP fp);
+ typedef void (*SetPropertyStateChangeFP) (AccessBridge_PropertyStateChangeFP fp);
+ typedef void (*SetPropertyValueChangeFP) (AccessBridge_PropertyValueChangeFP fp);
+ typedef void (*SetPropertySelectionChangeFP) (AccessBridge_PropertySelectionChangeFP fp);
+ typedef void (*SetPropertyTextChangeFP) (AccessBridge_PropertyTextChangeFP fp);
+ typedef void (*SetPropertyCaretChangeFP) (AccessBridge_PropertyCaretChangeFP fp);
+ typedef void (*SetPropertyVisibleDataChangeFP) (AccessBridge_PropertyVisibleDataChangeFP fp);
+ typedef void (*SetPropertyChildChangeFP) (AccessBridge_PropertyChildChangeFP fp);
+ typedef void (*SetPropertyActiveDescendentChangeFP) (AccessBridge_PropertyActiveDescendentChangeFP fp);
+
+ typedef void (*SetPropertyTableModelChangeFP) (AccessBridge_PropertyTableModelChangeFP fp);
+
+ typedef void (*ReleaseJavaObjectFP) (long vmID, Java_Object object);
+
+ typedef BOOL (*GetVersionInfoFP) (long vmID, AccessBridgeVersionInfo *info);
+
+ typedef BOOL (*IsJavaWindowFP) (HWND window);
+ typedef BOOL (*IsSameObjectFP) (long vmID, JOBJECT64 obj1, JOBJECT64 obj2);
+ typedef BOOL (*GetAccessibleContextFromHWNDFP) (HWND window, long *vmID, AccessibleContext *ac);
+ typedef HWND (*getHWNDFromAccessibleContextFP) (long vmID, AccessibleContext ac);
+
+ typedef BOOL (*GetAccessibleContextAtFP) (long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac);
+ typedef BOOL (*GetAccessibleContextWithFocusFP) (HWND window, long *vmID, AccessibleContext *ac);
+ typedef BOOL (*GetAccessibleContextInfoFP) (long vmID, AccessibleContext ac, AccessibleContextInfo *info);
+ typedef AccessibleContext (*GetAccessibleChildFromContextFP) (long vmID, AccessibleContext ac, jint i);
+ typedef AccessibleContext (*GetAccessibleParentFromContextFP) (long vmID, AccessibleContext ac);
+
+ /* begin AccessibleTable */
+ typedef BOOL (*getAccessibleTableInfoFP) (long vmID, AccessibleContext ac, AccessibleTableInfo *tableInfo);
+ typedef BOOL (*getAccessibleTableCellInfoFP) (long vmID, AccessibleTable accessibleTable,
+ jint row, jint column, AccessibleTableCellInfo *tableCellInfo);
+
+ typedef BOOL (*getAccessibleTableRowHeaderFP) (long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+ typedef BOOL (*getAccessibleTableColumnHeaderFP) (long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ typedef AccessibleContext (*getAccessibleTableRowDescriptionFP) (long vmID, AccessibleContext acParent, jint row);
+ typedef AccessibleContext (*getAccessibleTableColumnDescriptionFP) (long vmID, AccessibleContext acParent, jint column);
+
+ typedef jint (*getAccessibleTableRowSelectionCountFP) (long vmID, AccessibleTable table);
+ typedef BOOL (*isAccessibleTableRowSelectedFP) (long vmID, AccessibleTable table, jint row);
+ typedef BOOL (*getAccessibleTableRowSelectionsFP) (long vmID, AccessibleTable table, jint count,
+ jint *selections);
+
+ typedef jint (*getAccessibleTableColumnSelectionCountFP) (long vmID, AccessibleTable table);
+ typedef BOOL (*isAccessibleTableColumnSelectedFP) (long vmID, AccessibleTable table, jint column);
+ typedef BOOL (*getAccessibleTableColumnSelectionsFP) (long vmID, AccessibleTable table, jint count,
+ jint *selections);
+
+ typedef jint (*getAccessibleTableRowFP) (long vmID, AccessibleTable table, jint index);
+ typedef jint (*getAccessibleTableColumnFP) (long vmID, AccessibleTable table, jint index);
+ typedef jint (*getAccessibleTableIndexFP) (long vmID, AccessibleTable table, jint row, jint column);
+ /* end AccessibleTable */
+
+ /* AccessibleRelationSet */
+ typedef BOOL (*getAccessibleRelationSetFP) (long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo);
+
+ /* AccessibleHypertext */
+ typedef BOOL (*getAccessibleHypertextFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ typedef BOOL (*activateAccessibleHyperlinkFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink);
+
+ typedef jint (*getAccessibleHyperlinkCountFP)(const long vmID,
+ const AccessibleContext accessibleContext);
+
+ typedef BOOL (*getAccessibleHypertextExtFP) (const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ typedef jint (*getAccessibleHypertextLinkIndexFP)(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex);
+
+ typedef BOOL (*getAccessibleHyperlinkFP)(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ AccessibleHyperlinkInfo *hyperlinkInfo);
+
+
+ /* Accessible KeyBindings, Icons and Actions */
+ typedef BOOL (*getAccessibleKeyBindingsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings);
+
+ typedef BOOL (*getAccessibleIconsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons);
+
+ typedef BOOL (*getAccessibleActionsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions);
+
+ typedef BOOL (*doAccessibleActionsFP)(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure);
+
+
+ /* AccessibleText */
+
+ typedef BOOL (*GetAccessibleTextInfoFP) (long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y);
+ typedef BOOL (*GetAccessibleTextItemsFP) (long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index);
+ typedef BOOL (*GetAccessibleTextSelectionInfoFP) (long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection);
+ typedef BOOL (*GetAccessibleTextAttributesFP) (long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes);
+ typedef BOOL (*GetAccessibleTextRectFP) (long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index);
+ typedef BOOL (*GetAccessibleTextLineBoundsFP) (long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex);
+ typedef BOOL (*GetAccessibleTextRangeFP) (long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len);
+
+ typedef BOOL (*GetCurrentAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+ typedef BOOL (*GetMaximumAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+ typedef BOOL (*GetMinimumAccessibleValueFromContextFP) (long vmID, AccessibleValue av, wchar_t *value, short len);
+
+ typedef void (*AddAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*ClearAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as);
+ typedef JOBJECT64 (*GetAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef int (*GetAccessibleSelectionCountFromContextFP) (long vmID, AccessibleSelection as);
+ typedef BOOL (*IsAccessibleChildSelectedFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*RemoveAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as, int i);
+ typedef void (*SelectAllAccessibleSelectionFromContextFP) (long vmID, AccessibleSelection as);
+
+ /* Utility methods */
+
+ typedef BOOL (*setTextContentsFP) (const long vmID, const AccessibleContext ac, const wchar_t *text);
+ typedef AccessibleContext (*getParentWithRoleFP) (const long vmID, const AccessibleContext ac, const wchar_t *role);
+ typedef AccessibleContext (*getParentWithRoleElseRootFP) (const long vmID, const AccessibleContext ac, const wchar_t *role);
+ typedef AccessibleContext (*getTopLevelObjectFP) (const long vmID, const AccessibleContext ac);
+ typedef int (*getObjectDepthFP) (const long vmID, const AccessibleContext ac);
+ typedef AccessibleContext (*getActiveDescendentFP) (const long vmID, const AccessibleContext ac);
+
+
+ typedef BOOL (*getVirtualAccessibleNameFP) (const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len);
+
+ typedef BOOL (*requestFocusFP) (const long vmID, const AccessibleContext accessibleContext);
+
+ typedef BOOL (*selectTextRangeFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex);
+
+ typedef BOOL (*getTextAttributesInRangeFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len);
+
+ typedef int (*getVisibleChildrenCountFP) (const long vmID, const AccessibleContext accessibleContext);
+
+ typedef BOOL (*getVisibleChildrenFP) (const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, VisibleChildrenInfo *children);
+
+ typedef BOOL (*setCaretPositionFP) (const long vmID, const AccessibleContext accessibleContext, const int position);
+
+ typedef BOOL (*getCaretLocationFP) (long vmID, AccessibleContext ac, AccessibleTextRectInfo *rectInfo, jint index);
+
+ typedef int (*getEventsWaitingFP) ();
+
+ typedef struct AccessBridgeFPsTag {
+ Windows_runFP Windows_run;
+
+ SetPropertyChangeFP SetPropertyChange;
+
+ SetJavaShutdownFP SetJavaShutdown;
+ SetFocusGainedFP SetFocusGained;
+ SetFocusLostFP SetFocusLost;
+
+ SetCaretUpdateFP SetCaretUpdate;
+
+ SetMouseClickedFP SetMouseClicked;
+ SetMouseEnteredFP SetMouseEntered;
+ SetMouseExitedFP SetMouseExited;
+ SetMousePressedFP SetMousePressed;
+ SetMouseReleasedFP SetMouseReleased;
+
+ SetMenuCanceledFP SetMenuCanceled;
+ SetMenuDeselectedFP SetMenuDeselected;
+ SetMenuSelectedFP SetMenuSelected;
+ SetPopupMenuCanceledFP SetPopupMenuCanceled;
+ SetPopupMenuWillBecomeInvisibleFP SetPopupMenuWillBecomeInvisible;
+ SetPopupMenuWillBecomeVisibleFP SetPopupMenuWillBecomeVisible;
+
+ SetPropertyNameChangeFP SetPropertyNameChange;
+ SetPropertyDescriptionChangeFP SetPropertyDescriptionChange;
+ SetPropertyStateChangeFP SetPropertyStateChange;
+ SetPropertyValueChangeFP SetPropertyValueChange;
+ SetPropertySelectionChangeFP SetPropertySelectionChange;
+ SetPropertyTextChangeFP SetPropertyTextChange;
+ SetPropertyCaretChangeFP SetPropertyCaretChange;
+ SetPropertyVisibleDataChangeFP SetPropertyVisibleDataChange;
+ SetPropertyChildChangeFP SetPropertyChildChange;
+ SetPropertyActiveDescendentChangeFP SetPropertyActiveDescendentChange;
+
+ SetPropertyTableModelChangeFP SetPropertyTableModelChange;
+
+ ReleaseJavaObjectFP ReleaseJavaObject;
+ GetVersionInfoFP GetVersionInfo;
+
+ IsJavaWindowFP IsJavaWindow;
+ IsSameObjectFP IsSameObject;
+ GetAccessibleContextFromHWNDFP GetAccessibleContextFromHWND;
+ getHWNDFromAccessibleContextFP getHWNDFromAccessibleContext;
+
+ GetAccessibleContextAtFP GetAccessibleContextAt;
+ GetAccessibleContextWithFocusFP GetAccessibleContextWithFocus;
+ GetAccessibleContextInfoFP GetAccessibleContextInfo;
+ GetAccessibleChildFromContextFP GetAccessibleChildFromContext;
+ GetAccessibleParentFromContextFP GetAccessibleParentFromContext;
+
+ getAccessibleTableInfoFP getAccessibleTableInfo;
+ getAccessibleTableCellInfoFP getAccessibleTableCellInfo;
+
+ getAccessibleTableRowHeaderFP getAccessibleTableRowHeader;
+ getAccessibleTableColumnHeaderFP getAccessibleTableColumnHeader;
+
+ getAccessibleTableRowDescriptionFP getAccessibleTableRowDescription;
+ getAccessibleTableColumnDescriptionFP getAccessibleTableColumnDescription;
+
+ getAccessibleTableRowSelectionCountFP getAccessibleTableRowSelectionCount;
+ isAccessibleTableRowSelectedFP isAccessibleTableRowSelected;
+ getAccessibleTableRowSelectionsFP getAccessibleTableRowSelections;
+
+ getAccessibleTableColumnSelectionCountFP getAccessibleTableColumnSelectionCount;
+ isAccessibleTableColumnSelectedFP isAccessibleTableColumnSelected;
+ getAccessibleTableColumnSelectionsFP getAccessibleTableColumnSelections;
+
+ getAccessibleTableRowFP getAccessibleTableRow;
+ getAccessibleTableColumnFP getAccessibleTableColumn;
+ getAccessibleTableIndexFP getAccessibleTableIndex;
+
+ getAccessibleRelationSetFP getAccessibleRelationSet;
+
+ getAccessibleHypertextFP getAccessibleHypertext;
+ activateAccessibleHyperlinkFP activateAccessibleHyperlink;
+ getAccessibleHyperlinkCountFP getAccessibleHyperlinkCount;
+ getAccessibleHypertextExtFP getAccessibleHypertextExt;
+ getAccessibleHypertextLinkIndexFP getAccessibleHypertextLinkIndex;
+ getAccessibleHyperlinkFP getAccessibleHyperlink;
+
+ getAccessibleKeyBindingsFP getAccessibleKeyBindings;
+ getAccessibleIconsFP getAccessibleIcons;
+ getAccessibleActionsFP getAccessibleActions;
+ doAccessibleActionsFP doAccessibleActions;
+
+ GetAccessibleTextInfoFP GetAccessibleTextInfo;
+ GetAccessibleTextItemsFP GetAccessibleTextItems;
+ GetAccessibleTextSelectionInfoFP GetAccessibleTextSelectionInfo;
+ GetAccessibleTextAttributesFP GetAccessibleTextAttributes;
+ GetAccessibleTextRectFP GetAccessibleTextRect;
+ GetAccessibleTextLineBoundsFP GetAccessibleTextLineBounds;
+ GetAccessibleTextRangeFP GetAccessibleTextRange;
+
+ GetCurrentAccessibleValueFromContextFP GetCurrentAccessibleValueFromContext;
+ GetMaximumAccessibleValueFromContextFP GetMaximumAccessibleValueFromContext;
+ GetMinimumAccessibleValueFromContextFP GetMinimumAccessibleValueFromContext;
+
+ AddAccessibleSelectionFromContextFP AddAccessibleSelectionFromContext;
+ ClearAccessibleSelectionFromContextFP ClearAccessibleSelectionFromContext;
+ GetAccessibleSelectionFromContextFP GetAccessibleSelectionFromContext;
+ GetAccessibleSelectionCountFromContextFP GetAccessibleSelectionCountFromContext;
+ IsAccessibleChildSelectedFromContextFP IsAccessibleChildSelectedFromContext;
+ RemoveAccessibleSelectionFromContextFP RemoveAccessibleSelectionFromContext;
+ SelectAllAccessibleSelectionFromContextFP SelectAllAccessibleSelectionFromContext;
+
+ setTextContentsFP setTextContents;
+ getParentWithRoleFP getParentWithRole;
+ getTopLevelObjectFP getTopLevelObject;
+ getParentWithRoleElseRootFP getParentWithRoleElseRoot;
+ getObjectDepthFP getObjectDepth;
+ getActiveDescendentFP getActiveDescendent;
+
+ getVirtualAccessibleNameFP getVirtualAccessibleName;
+ requestFocusFP requestFocus;
+ selectTextRangeFP selectTextRange;
+ getTextAttributesInRangeFP getTextAttributesInRange;
+ getVisibleChildrenCountFP getVisibleChildrenCount;
+ getVisibleChildrenFP getVisibleChildren;
+ setCaretPositionFP setCaretPosition;
+ getCaretLocationFP getCaretLocation;
+
+ getEventsWaitingFP getEventsWaiting;
+
+ } AccessBridgeFPs;
+
+
+ /**
+ * Initialize the world
+ */
+ BOOL initializeAccessBridge();
+ BOOL shutdownAccessBridge();
+
+ /**
+ * Window routines
+ */
+ BOOL IsJavaWindow(HWND window);
+
+ // Returns the virtual machine ID and AccessibleContext for a top-level window
+ BOOL GetAccessibleContextFromHWND(HWND target, long *vmID, AccessibleContext *ac);
+
+ // Returns the HWND from the AccessibleContext of a top-level window
+ HWND getHWNDFromAccessibleContext(long vmID, AccessibleContext ac);
+
+
+ /**
+ * Event handling routines
+ */
+ void SetJavaShutdown(AccessBridge_JavaShutdownFP fp);
+ void SetFocusGained(AccessBridge_FocusGainedFP fp);
+ void SetFocusLost(AccessBridge_FocusLostFP fp);
+
+ void SetCaretUpdate(AccessBridge_CaretUpdateFP fp);
+
+ void SetMouseClicked(AccessBridge_MouseClickedFP fp);
+ void SetMouseEntered(AccessBridge_MouseEnteredFP fp);
+ void SetMouseExited(AccessBridge_MouseExitedFP fp);
+ void SetMousePressed(AccessBridge_MousePressedFP fp);
+ void SetMouseReleased(AccessBridge_MouseReleasedFP fp);
+
+ void SetMenuCanceled(AccessBridge_MenuCanceledFP fp);
+ void SetMenuDeselected(AccessBridge_MenuDeselectedFP fp);
+ void SetMenuSelected(AccessBridge_MenuSelectedFP fp);
+ void SetPopupMenuCanceled(AccessBridge_PopupMenuCanceledFP fp);
+ void SetPopupMenuWillBecomeInvisible(AccessBridge_PopupMenuWillBecomeInvisibleFP fp);
+ void SetPopupMenuWillBecomeVisible(AccessBridge_PopupMenuWillBecomeVisibleFP fp);
+
+ void SetPropertyNameChange(AccessBridge_PropertyNameChangeFP fp);
+ void SetPropertyDescriptionChange(AccessBridge_PropertyDescriptionChangeFP fp);
+ void SetPropertyStateChange(AccessBridge_PropertyStateChangeFP fp);
+ void SetPropertyValueChange(AccessBridge_PropertyValueChangeFP fp);
+ void SetPropertySelectionChange(AccessBridge_PropertySelectionChangeFP fp);
+ void SetPropertyTextChange(AccessBridge_PropertyTextChangeFP fp);
+ void SetPropertyCaretChange(AccessBridge_PropertyCaretChangeFP fp);
+ void SetPropertyVisibleDataChange(AccessBridge_PropertyVisibleDataChangeFP fp);
+ void SetPropertyChildChange(AccessBridge_PropertyChildChangeFP fp);
+ void SetPropertyActiveDescendentChange(AccessBridge_PropertyActiveDescendentChangeFP fp);
+
+ void SetPropertyTableModelChange(AccessBridge_PropertyTableModelChangeFP fp);
+
+
+ /**
+ * General routines
+ */
+ void ReleaseJavaObject(long vmID, Java_Object object);
+ BOOL GetVersionInfo(long vmID, AccessBridgeVersionInfo *info);
+ HWND GetHWNDFromAccessibleContext(long vmID, JOBJECT64 accesibleContext);
+
+ /**
+ * Accessible Context routines
+ */
+ BOOL GetAccessibleContextAt(long vmID, AccessibleContext acParent,
+ jint x, jint y, AccessibleContext *ac);
+ BOOL GetAccessibleContextWithFocus(HWND window, long *vmID, AccessibleContext *ac);
+ BOOL GetAccessibleContextInfo(long vmID, AccessibleContext ac, AccessibleContextInfo *info);
+ AccessibleContext GetAccessibleChildFromContext(long vmID, AccessibleContext ac, jint index);
+ AccessibleContext GetAccessibleParentFromContext(long vmID, AccessibleContext ac);
+
+ /**
+ * Accessible Text routines
+ */
+ BOOL GetAccessibleTextInfo(long vmID, AccessibleText at, AccessibleTextInfo *textInfo, jint x, jint y);
+ BOOL GetAccessibleTextItems(long vmID, AccessibleText at, AccessibleTextItemsInfo *textItems, jint index);
+ BOOL GetAccessibleTextSelectionInfo(long vmID, AccessibleText at, AccessibleTextSelectionInfo *textSelection);
+ BOOL GetAccessibleTextAttributes(long vmID, AccessibleText at, jint index, AccessibleTextAttributesInfo *attributes);
+ BOOL GetAccessibleTextRect(long vmID, AccessibleText at, AccessibleTextRectInfo *rectInfo, jint index);
+ BOOL GetAccessibleTextLineBounds(long vmID, AccessibleText at, jint index, jint *startIndex, jint *endIndex);
+ BOOL GetAccessibleTextRange(long vmID, AccessibleText at, jint start, jint end, wchar_t *text, short len);
+
+ /* begin AccessibleTable routines */
+ BOOL getAccessibleTableInfo(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ BOOL getAccessibleTableCellInfo(long vmID, AccessibleTable accessibleTable, jint row, jint column,
+ AccessibleTableCellInfo *tableCellInfo);
+
+ BOOL getAccessibleTableRowHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+ BOOL getAccessibleTableColumnHeader(long vmID, AccessibleContext acParent, AccessibleTableInfo *tableInfo);
+
+ AccessibleContext getAccessibleTableRowDescription(long vmID, AccessibleContext acParent, jint row);
+ AccessibleContext getAccessibleTableColumnDescription(long vmID, AccessibleContext acParent, jint column);
+
+ jint getAccessibleTableRowSelectionCount(long vmID, AccessibleTable table);
+ BOOL isAccessibleTableRowSelected(long vmID, AccessibleTable table, jint row);
+ BOOL getAccessibleTableRowSelections(long vmID, AccessibleTable table, jint count, jint *selections);
+
+ jint getAccessibleTableColumnSelectionCount(long vmID, AccessibleTable table);
+ BOOL isAccessibleTableColumnSelected(long vmID, AccessibleTable table, jint column);
+ BOOL getAccessibleTableColumnSelections(long vmID, AccessibleTable table, jint count, jint *selections);
+
+ jint getAccessibleTableRow(long vmID, AccessibleTable table, jint index);
+ jint getAccessibleTableColumn(long vmID, AccessibleTable table, jint index);
+ jint getAccessibleTableIndex(long vmID, AccessibleTable table, jint row, jint column);
+ /* end AccessibleTable */
+
+ /* ----- AccessibleRelationSet routines */
+ BOOL getAccessibleRelationSet(long vmID, AccessibleContext accessibleContext,
+ AccessibleRelationSetInfo *relationSetInfo);
+
+ /* ----- AccessibleHypertext routines */
+
+ /*
+ * Returns hypertext information associated with a component.
+ */
+ BOOL getAccessibleHypertext(long vmID, AccessibleContext accessibleContext,
+ AccessibleHypertextInfo *hypertextInfo);
+
+ /*
+ * Requests that a hyperlink be activated.
+ */
+ BOOL activateAccessibleHyperlink(long vmID, AccessibleContext accessibleContext,
+ AccessibleHyperlink accessibleHyperlink);
+
+ /*
+ * Returns the number of hyperlinks in a component
+ * Maps to AccessibleHypertext.getLinkCount.
+ * Returns -1 on error.
+ */
+ jint getAccessibleHyperlinkCount(const long vmID,
+ const AccessibleHypertext hypertext);
+
+ /*
+ * This method is used to iterate through the hyperlinks in a component. It
+ * returns hypertext information for a component starting at hyperlink index
+ * nStartIndex. No more than MAX_HYPERLINKS AccessibleHypertextInfo objects will
+ * be returned for each call to this method.
+ * Returns FALSE on error.
+ */
+ BOOL getAccessibleHypertextExt(const long vmID,
+ const AccessibleContext accessibleContext,
+ const jint nStartIndex,
+ /* OUT */ AccessibleHypertextInfo *hypertextInfo);
+
+ /*
+ * Returns the index into an array of hyperlinks that is associated with
+ * a character index in document; maps to AccessibleHypertext.getLinkIndex
+ * Returns -1 on error.
+ */
+ jint getAccessibleHypertextLinkIndex(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex);
+
+ /*
+ * Returns the nth hyperlink in a document
+ * Maps to AccessibleHypertext.getLink.
+ * Returns FALSE on error
+ */
+ BOOL getAccessibleHyperlink(const long vmID,
+ const AccessibleHypertext hypertext,
+ const jint nIndex,
+ /* OUT */ AccessibleHyperlinkInfo *hyperlinkInfo);
+
+ /* Accessible KeyBindings, Icons and Actions */
+
+ /*
+ * Returns a list of key bindings associated with a component.
+ */
+ BOOL getAccessibleKeyBindings(long vmID, AccessibleContext accessibleContext,
+ AccessibleKeyBindings *keyBindings);
+
+ /*
+ * Returns a list of icons associate with a component.
+ */
+ BOOL getAccessibleIcons(long vmID, AccessibleContext accessibleContext,
+ AccessibleIcons *icons);
+
+ /*
+ * Returns a list of actions that a component can perform.
+ */
+ BOOL getAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActions *actions);
+
+ /*
+ * Request that a list of AccessibleActions be performed by a component.
+ * Returns TRUE if all actions are performed. Returns FALSE
+ * when the first requested action fails in which case "failure"
+ * contains the index of the action that failed.
+ */
+ BOOL doAccessibleActions(long vmID, AccessibleContext accessibleContext,
+ AccessibleActionsToDo *actionsToDo, jint *failure);
+
+
+
+ /* Additional utility methods */
+
+ /*
+ * Returns whether two object references refer to the same object.
+ */
+ BOOL IsSameObject(long vmID, JOBJECT64 obj1, JOBJECT64 obj2);
+
+ /**
+ * Sets editable text contents. The AccessibleContext must implement AccessibleEditableText and
+ * be editable. The maximum text length that can be set is MAX_STRING_SIZE - 1.
+ * Returns whether successful
+ */
+ BOOL setTextContents (const long vmID, const AccessibleContext accessibleContext, const wchar_t *text);
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h
+ * If there is no ancestor object that has the specified role,
+ * returns (AccessibleContext)0.
+ */
+ AccessibleContext getParentWithRole (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role);
+
+ /**
+ * Returns the Accessible Context with the specified role that is the
+ * ancestor of a given object. The role is one of the role strings
+ * defined in AccessBridgePackages.h. If an object with the specified
+ * role does not exist, returns the top level object for the Java Window.
+ * Returns (AccessibleContext)0 on error.
+ */
+ AccessibleContext getParentWithRoleElseRoot (const long vmID, const AccessibleContext accessibleContext,
+ const wchar_t *role);
+
+ /**
+ * Returns the Accessible Context for the top level object in
+ * a Java Window. This is same Accessible Context that is obtained
+ * from GetAccessibleContextFromHWND for that window. Returns
+ * (AccessibleContext)0 on error.
+ */
+ AccessibleContext getTopLevelObject (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Returns how deep in the object hierarchy a given object is.
+ * The top most object in the object hierarchy has an object depth of 0.
+ * Returns -1 on error.
+ */
+ int getObjectDepth (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Returns the Accessible Context of the current ActiveDescendent of an object.
+ * This method assumes the ActiveDescendent is the component that is currently
+ * selected in a container object.
+ * Returns (AccessibleContext)0 on error or if there is no selection.
+ */
+ AccessibleContext getActiveDescendent (const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ /**
+ * Accessible Value routines
+ */
+ BOOL GetCurrentAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+ BOOL GetMaximumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+ BOOL GetMinimumAccessibleValueFromContext(long vmID, AccessibleValue av, wchar_t *value, short len);
+
+ /**
+ * Accessible Selection routines
+ */
+ void AddAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ void ClearAccessibleSelectionFromContext(long vmID, AccessibleSelection as);
+ JOBJECT64 GetAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ int GetAccessibleSelectionCountFromContext(long vmID, AccessibleSelection as);
+ BOOL IsAccessibleChildSelectedFromContext(long vmID, AccessibleSelection as, int i);
+ void RemoveAccessibleSelectionFromContext(long vmID, AccessibleSelection as, int i);
+ void SelectAllAccessibleSelectionFromContext(long vmID, AccessibleSelection as);
+
+ /**
+ * Additional methods for Teton
+ */
+
+ /**
+ * Gets the AccessibleName for a component based upon the JAWS algorithm. Returns
+ * whether successful.
+ *
+ * Bug ID 4916682 - Implement JAWS AccessibleName policy
+ */
+ BOOL getVirtualAccessibleName(const long vmID, const AccessibleContext accessibleContext,
+ wchar_t *name, int len);
+
+ /**
+ * Request focus for a component. Returns whether successful.
+ *
+ * Bug ID 4944757 - requestFocus method needed
+ */
+ BOOL requestFocus(const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Selects text between two indices. Selection includes the text at the start index
+ * and the text at the end index. Returns whether successful.
+ *
+ * Bug ID 4944758 - selectTextRange method needed
+ */
+ BOOL selectTextRange(const long vmID, const AccessibleContext accessibleContext, const int startIndex,
+ const int endIndex);
+
+ /**
+ * Get text attributes between two indices. The attribute list includes the text at the
+ * start index and the text at the end index. Returns whether successful;
+ *
+ * Bug ID 4944761 - getTextAttributes between two indices method needed
+ */
+ BOOL getTextAttributesInRange(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex, const int endIndex,
+ AccessibleTextAttributesInfo *attributes, short *len);
+
+ /**
+ * Returns the number of visible children of a component. Returns -1 on error.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ int getVisibleChildrenCount(const long vmID, const AccessibleContext accessibleContext);
+
+ /**
+ * Gets the visible children of an AccessibleContext. Returns whether successful.
+ *
+ * Bug ID 4944762- getVisibleChildren for list-like components needed
+ */
+ BOOL getVisibleChildren(const long vmID, const AccessibleContext accessibleContext,
+ const int startIndex,
+ VisibleChildrenInfo *visibleChildrenInfo);
+
+ /**
+ * Set the caret to a text position. Returns whether successful.
+ *
+ * Bug ID 4944770 - setCaretPosition method needed
+ */
+ BOOL setCaretPosition(const long vmID, const AccessibleContext accessibleContext,
+ const int position);
+
+ /**
+ * Gets the text caret location
+ */
+ BOOL getCaretLocation(long vmID, AccessibleContext ac,
+ AccessibleTextRectInfo *rectInfo, jint index);
+
+ /**
+ * Gets the number of events waiting to fire
+ */
+ int getEventsWaiting();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h b/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h
new file mode 100644
index 00000000000..27c31be09a8
--- /dev/null
+++ b/jdk/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h
@@ -0,0 +1,2215 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Header file for packages of paramaters passed between Java Accessibility
+ * and native Assistive Technologies
+ */
+
+#ifndef __AccessBridgePackages_H__
+#define __AccessBridgePackages_H__
+
+#include