Merge jdk7-b112
authorlana
Fri, 24 Sep 2010 16:41:32 -0700
changeset 2792b53f226b1d91
parent 2724 c2cdc8c94b65
parent 2791 61f1bbd49a5e
child 2793 61d3b9fbb26b
child 2795 ad17cf689258
child 2802 a601a6711ef8
child 2820 b57ca6031a35
child 2847 4b0fdb9f7cfe
Merge
src/share/classes/com/sun/media/sound/MidiDeviceReceiver.java
src/share/native/sun/java2d/cmm/lcms/cmscam97.c
src/share/native/sun/java2d/cmm/lcms/cmsmatsh.c
src/share/native/sun/java2d/cmm/lcms/icc34.h
src/share/native/sun/java2d/cmm/lcms/lcms.h
src/solaris/classes/sun/net/spi/SdpProvider.java
src/solaris/native/sun/net/spi/SdpProvider.c
test/java/util/Locale/data/deflocale.exe
test/java/util/Locale/data/deflocale.jds3
test/java/util/Locale/data/deflocale.rhel4
test/java/util/Locale/data/deflocale.winvista
test/java/util/Locale/data/deflocale.winxp
test/tools/launcher/VerifyExceptions.java
     1.1 --- a/make/com/Makefile	Thu Sep 23 17:33:40 2010 -0700
     1.2 +++ b/make/com/Makefile	Fri Sep 24 16:41:32 2010 -0700
     1.3 @@ -31,7 +31,7 @@
     1.4  PRODUCT = com
     1.5  include $(BUILDDIR)/common/Defs.gmk
     1.6  
     1.7 -SUBDIRS = sun
     1.8 +SUBDIRS = sun oracle
     1.9  include $(BUILDDIR)/common/Subdirs.gmk
    1.10  
    1.11  all build clean clobber::
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/make/com/oracle/Makefile	Fri Sep 24 16:41:32 2010 -0700
     2.3 @@ -0,0 +1,34 @@
     2.4 +#
     2.5 +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
     2.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 +#
     2.8 +# This code is free software; you can redistribute it and/or modify it
     2.9 +# under the terms of the GNU General Public License version 2 only, as
    2.10 +# published by the Free Software Foundation.  Oracle designates this
    2.11 +# particular file as subject to the "Classpath" exception as provided
    2.12 +# by Oracle in the LICENSE file that accompanied this code.
    2.13 +#
    2.14 +# This code is distributed in the hope that it will be useful, but WITHOUT
    2.15 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.16 +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.17 +# version 2 for more details (a copy is included in the LICENSE file that
    2.18 +# accompanied this code).
    2.19 +#
    2.20 +# You should have received a copy of the GNU General Public License version
    2.21 +# 2 along with this work; if not, write to the Free Software Foundation,
    2.22 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.23 +#
    2.24 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.25 +# or visit www.oracle.com if you need additional information or have any
    2.26 +# questions.
    2.27 +#
    2.28 +
    2.29 +BUILDDIR = ../..
    2.30 +PRODUCT = oracle
    2.31 +include $(BUILDDIR)/common/Defs.gmk
    2.32 +
    2.33 +SUBDIRS = net
    2.34 +include $(BUILDDIR)/common/Subdirs.gmk
    2.35 +
    2.36 +all build clean clobber::
    2.37 +	$(SUBDIRS-loop)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/make/com/oracle/net/Makefile	Fri Sep 24 16:41:32 2010 -0700
     3.3 @@ -0,0 +1,39 @@
     3.4 +#
     3.5 +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
     3.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 +#
     3.8 +# This code is free software; you can redistribute it and/or modify it
     3.9 +# under the terms of the GNU General Public License version 2 only, as
    3.10 +# published by the Free Software Foundation.  Oracle designates this
    3.11 +# particular file as subject to the "Classpath" exception as provided
    3.12 +# by Oracle in the LICENSE file that accompanied this code.
    3.13 +#
    3.14 +# This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 +# version 2 for more details (a copy is included in the LICENSE file that
    3.18 +# accompanied this code).
    3.19 +#
    3.20 +# You should have received a copy of the GNU General Public License version
    3.21 +# 2 along with this work; if not, write to the Free Software Foundation,
    3.22 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 +#
    3.24 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 +# or visit www.oracle.com if you need additional information or have any
    3.26 +# questions.
    3.27 +#
    3.28 +
    3.29 +BUILDDIR = ../../..
    3.30 +PRODUCT = oracle
    3.31 +include $(BUILDDIR)/common/Defs.gmk
    3.32 +
    3.33 +#
    3.34 +# Files to compile
    3.35 +#
    3.36 +AUTO_FILES_JAVA_DIRS = com/oracle/net
    3.37 +
    3.38 +#
    3.39 +# Rules
    3.40 +#
    3.41 +include $(BUILDDIR)/common/Classes.gmk
    3.42 +
     4.1 --- a/make/common/Release.gmk	Thu Sep 23 17:33:40 2010 -0700
     4.2 +++ b/make/common/Release.gmk	Fri Sep 24 16:41:32 2010 -0700
     4.3 @@ -573,13 +573,13 @@
     4.4  	$(ECHO) "sun/jvmstat/" >> $@
     4.5  	$(ECHO) "sun/nio/cs/ext/" >> $@
     4.6  	$(ECHO) "sun/awt/HKSCS.class" >> $@
     4.7 -	$(ECHO) "sun/awt/motif/X11GB2312$Decoder.class" >> $@
     4.8 -	$(ECHO) "sun/awt/motif/X11GB2312$Encoder.class" >> $@
     4.9 +	$(ECHO) "sun/awt/motif/X11GB2312\$$Decoder.class" >> $@
    4.10 +	$(ECHO) "sun/awt/motif/X11GB2312\$$Encoder.class" >> $@
    4.11  	$(ECHO) "sun/awt/motif/X11GB2312.class" >> $@
    4.12 -	$(ECHO) "sun/awt/motif/X11GBK$Encoder.class" >> $@
    4.13 +	$(ECHO) "sun/awt/motif/X11GBK\$$Encoder.class" >> $@
    4.14  	$(ECHO) "sun/awt/motif/X11GBK.class" >> $@
    4.15 -	$(ECHO) "sun/awt/motif/X11KSC5601$Decoder.class" >> $@
    4.16 -	$(ECHO) "sun/awt/motif/X11KSC5601$Encoder.class" >> $@
    4.17 +	$(ECHO) "sun/awt/motif/X11KSC5601\$$Decoder.class" >> $@
    4.18 +	$(ECHO) "sun/awt/motif/X11KSC5601\$$Encoder.class" >> $@
    4.19  	$(ECHO) "sun/awt/motif/X11KSC5601.class" >> $@
    4.20  	$(ECHO) "sun/rmi/rmic/" >> $@
    4.21  	$(ECHO) "sun/tools/asm/" >> $@
     5.1 --- a/make/docs/NON_CORE_PKGS.gmk	Thu Sep 23 17:33:40 2010 -0700
     5.2 +++ b/make/docs/NON_CORE_PKGS.gmk	Fri Sep 24 16:41:32 2010 -0700
     5.3 @@ -91,6 +91,8 @@
     5.4  TRACING_PKGS     = com.sun.tracing         \
     5.5                     com.sun.tracing.dtrace
     5.6  
     5.7 +ORACLENET_PKGS   = com.oracle.net
     5.8 +
     5.9  # non-core packages in rt.jar
    5.10  NON_CORE_PKGS    = $(DOMAPI_PKGS) \
    5.11                     $(MGMT_PKGS) \
    5.12 @@ -101,5 +103,6 @@
    5.13                     $(HTTPSERVER_PKGS) \
    5.14                     $(SMARTCARDIO_PKGS) \
    5.15                     $(TRACING_PKGS) \
    5.16 -                   $(SCTPAPI_PKGS)
    5.17 +                   $(SCTPAPI_PKGS) \
    5.18 +                   $(ORACLENET_PKGS)
    5.19  
     6.1 --- a/make/java/java/FILES_java.gmk	Thu Sep 23 17:33:40 2010 -0700
     6.2 +++ b/make/java/java/FILES_java.gmk	Fri Sep 24 16:41:32 2010 -0700
     6.3 @@ -183,10 +183,22 @@
     6.4          java/util/MissingFormatWidthException.java \
     6.5          java/util/UnknownFormatConversionException.java \
     6.6          java/util/UnknownFormatFlagsException.java \
     6.7 +    java/util/IllformedLocaleException.java \
     6.8      java/util/FormatterClosedException.java \
     6.9      java/util/ListResourceBundle.java \
    6.10          sun/util/EmptyListResourceBundle.java \
    6.11      java/util/Locale.java \
    6.12 +        sun/util/locale/AsciiUtil.java \
    6.13 +        sun/util/locale/BaseLocale.java \
    6.14 +        sun/util/locale/Extension.java \
    6.15 +        sun/util/locale/InternalLocaleBuilder.java \
    6.16 +        sun/util/locale/LanguageTag.java \
    6.17 +        sun/util/locale/LocaleExtensions.java \
    6.18 +        sun/util/locale/LocaleObjectCache.java \
    6.19 +        sun/util/locale/LocaleSyntaxException.java \
    6.20 +        sun/util/locale/ParseStatus.java \
    6.21 +        sun/util/locale/StringTokenIterator.java \
    6.22 +        sun/util/locale/UnicodeLocaleExtension.java \
    6.23      java/util/LocaleISOData.java \
    6.24          sun/util/LocaleServiceProviderPool.java \
    6.25  	sun/util/LocaleDataMetaInfo.java \
     7.1 --- a/make/java/net/FILES_c.gmk	Thu Sep 23 17:33:40 2010 -0700
     7.2 +++ b/make/java/net/FILES_c.gmk	Fri Sep 24 16:41:32 2010 -0700
     7.3 @@ -39,10 +39,6 @@
     7.4  	ResolverConfigurationImpl.c \
     7.5  	DefaultProxySelector.c
     7.6  
     7.7 -ifeq ($(PLATFORM), solaris)
     7.8 -    FILES_c += SdpProvider.c
     7.9 -endif
    7.10 -
    7.11  ifeq ($(PLATFORM), linux)
    7.12      FILES_c += linux_close.c
    7.13  endif
     8.1 --- a/make/java/net/Makefile	Thu Sep 23 17:33:40 2010 -0700
     8.2 +++ b/make/java/net/Makefile	Fri Sep 24 16:41:32 2010 -0700
     8.3 @@ -44,6 +44,8 @@
     8.4      endif
     8.5      FILES_c += NTLMAuthSequence.c
     8.6      FILES_c += NetworkInterface_winXP.c
     8.7 +else
     8.8 +    FILES_c += SdpSupport.c
     8.9  endif
    8.10  
    8.11  FILES_export = \
    8.12 @@ -84,7 +86,8 @@
    8.13  #
    8.14  # Find platform specific native code
    8.15  #
    8.16 -vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm $(PLATFORM_SRC)/native/sun/net/spi
    8.17 +vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm \
    8.18 +    $(PLATFORM_SRC)/native/sun/net/sdp $(PLATFORM_SRC)/native/sun/net/spi
    8.19  
    8.20  #
    8.21  # Include rules
     9.1 --- a/make/java/net/mapfile-vers	Thu Sep 23 17:33:40 2010 -0700
     9.2 +++ b/make/java/net/mapfile-vers	Fri Sep 24 16:41:32 2010 -0700
     9.3 @@ -88,9 +88,10 @@
     9.4  		Java_java_net_PlainDatagramSocketImpl_setTimeToLive;
     9.5  		Java_sun_net_dns_ResolverConfigurationImpl_localDomain0;
     9.6  		Java_sun_net_dns_ResolverConfigurationImpl_fallbackDomain0;
     9.7 +		Java_sun_net_sdp_SdpSupport_convert0;
     9.8 +		Java_sun_net_sdp_SdpSupport_create0;
     9.9  		Java_sun_net_spi_DefaultProxySelector_init;
    9.10  		Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
    9.11 -		Java_sun_net_spi_SdpProvider_convert;
    9.12  		NET_AllocSockaddr;
    9.13  		NET_SockaddrToInetAddress;
    9.14                  NET_SockaddrEqualsInetAddress;
    10.1 --- a/make/java/nio/FILES_java.gmk	Thu Sep 23 17:33:40 2010 -0700
    10.2 +++ b/make/java/nio/FILES_java.gmk	Fri Sep 24 16:41:32 2010 -0700
    10.3 @@ -83,6 +83,7 @@
    10.4  	java/nio/file/ClosedFileSystemException.java \
    10.5  	java/nio/file/ClosedWatchServiceException.java \
    10.6  	java/nio/file/CopyOption.java \
    10.7 +	java/nio/file/DirectoryIteratorException.java \
    10.8  	java/nio/file/DirectoryNotEmptyException.java \
    10.9  	java/nio/file/DirectoryStream.java \
   10.10  	java/nio/file/FileAlreadyExistsException.java \
   10.11 @@ -199,6 +200,7 @@
   10.12  	sun/nio/ch/PipeImpl.java \
   10.13  	sun/nio/ch/PollArrayWrapper.java \
   10.14  	sun/nio/ch/Reflect.java \
   10.15 +	sun/nio/ch/Secrets.java \
   10.16  	sun/nio/ch/SelectionKeyImpl.java \
   10.17  	sun/nio/ch/SelectorImpl.java \
   10.18  	sun/nio/ch/SelectorProviderImpl.java \
    11.1 --- a/make/java/nio/mapfile-linux	Thu Sep 23 17:33:40 2010 -0700
    11.2 +++ b/make/java/nio/mapfile-linux	Fri Sep 24 16:41:32 2010 -0700
    11.3 @@ -89,7 +89,7 @@
    11.4                  Java_sun_nio_ch_IOUtil_drain;
    11.5                  Java_sun_nio_ch_IOUtil_fdVal;
    11.6                  Java_sun_nio_ch_IOUtil_initIDs;
    11.7 -                Java_sun_nio_ch_IOUtil_initPipe;
    11.8 +                Java_sun_nio_ch_IOUtil_makePipe;
    11.9                  Java_sun_nio_ch_IOUtil_randomBytes;
   11.10                  Java_sun_nio_ch_IOUtil_setfdVal;
   11.11  		Java_sun_nio_ch_NativeThread_current;
    12.1 --- a/make/java/nio/mapfile-solaris	Thu Sep 23 17:33:40 2010 -0700
    12.2 +++ b/make/java/nio/mapfile-solaris	Fri Sep 24 16:41:32 2010 -0700
    12.3 @@ -76,7 +76,7 @@
    12.4                  Java_sun_nio_ch_IOUtil_drain;
    12.5                  Java_sun_nio_ch_IOUtil_fdVal;
    12.6                  Java_sun_nio_ch_IOUtil_initIDs;
    12.7 -                Java_sun_nio_ch_IOUtil_initPipe;
    12.8 +                Java_sun_nio_ch_IOUtil_makePipe;
    12.9                  Java_sun_nio_ch_IOUtil_randomBytes;
   12.10                  Java_sun_nio_ch_IOUtil_setfdVal;
   12.11  		Java_sun_nio_ch_NativeThread_current;
    13.1 --- a/make/java/text/base/FILES_java.gmk	Thu Sep 23 17:33:40 2010 -0700
    13.2 +++ b/make/java/text/base/FILES_java.gmk	Fri Sep 24 16:41:32 2010 -0700
    13.3 @@ -1,5 +1,5 @@
    13.4  #
    13.5 -# Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
    13.6 +# Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    13.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    13.8  #
    13.9  # This code is free software; you can redistribute it and/or modify it
   13.10 @@ -29,6 +29,7 @@
   13.11      java/text/AttributedString.java \
   13.12      java/text/BreakDictionary.java \
   13.13      java/text/BreakIterator.java \
   13.14 +    java/text/CalendarBuilder.java \
   13.15      java/text/CharacterIterator.java \
   13.16      java/text/CharacterIteratorFieldDelegate.java \
   13.17      java/text/ChoiceFormat.java \
    14.1 --- a/make/sun/cmm/lcms/FILES_c_unix.gmk	Thu Sep 23 17:33:40 2010 -0700
    14.2 +++ b/make/sun/cmm/lcms/FILES_c_unix.gmk	Fri Sep 24 16:41:32 2010 -0700
    14.3 @@ -25,7 +25,6 @@
    14.4  
    14.5  FILES_c = \
    14.6      cmscam02.c \
    14.7 -    cmscam97.c \
    14.8      cmscgats.c \
    14.9      cmscnvrt.c \
   14.10      cmserr.c \
   14.11 @@ -35,13 +34,17 @@
   14.12      cmsio0.c \
   14.13      cmsio1.c \
   14.14      cmslut.c \
   14.15 -    cmsmatsh.c \
   14.16 +    cmsmd5.c \
   14.17      cmsmtrx.c \
   14.18      cmsnamed.c \
   14.19 +    cmsopt.c \
   14.20      cmspack.c \
   14.21      cmspcs.c \
   14.22 +    cmsplugin.c \
   14.23      cmsps2.c \
   14.24      cmssamp.c \
   14.25 +    cmssm.c \
   14.26 +    cmstypes.c \
   14.27      cmsvirt.c \
   14.28      cmswtpnt.c \
   14.29      cmsxform.c \
    15.1 --- a/make/sun/cmm/lcms/FILES_c_windows.gmk	Thu Sep 23 17:33:40 2010 -0700
    15.2 +++ b/make/sun/cmm/lcms/FILES_c_windows.gmk	Fri Sep 24 16:41:32 2010 -0700
    15.3 @@ -25,7 +25,6 @@
    15.4  
    15.5  FILES_c = \
    15.6      cmscam02.c \
    15.7 -    cmscam97.c \
    15.8      cmscgats.c \
    15.9      cmscnvrt.c \
   15.10      cmserr.c \
   15.11 @@ -35,13 +34,17 @@
   15.12      cmsio0.c \
   15.13      cmsio1.c \
   15.14      cmslut.c \
   15.15 -    cmsmatsh.c \
   15.16 +    cmsmd5.c \
   15.17      cmsmtrx.c \
   15.18      cmsnamed.c \
   15.19 +    cmsopt.c \
   15.20      cmspack.c \
   15.21      cmspcs.c \
   15.22 +    cmsplugin.c \
   15.23      cmsps2.c \
   15.24      cmssamp.c \
   15.25 +    cmssm.c \
   15.26 +    cmstypes.c \
   15.27      cmsvirt.c \
   15.28      cmswtpnt.c \
   15.29      cmsxform.c \
    16.1 --- a/make/sun/cmm/lcms/Makefile	Thu Sep 23 17:33:40 2010 -0700
    16.2 +++ b/make/sun/cmm/lcms/Makefile	Fri Sep 24 16:41:32 2010 -0700
    16.3 @@ -80,8 +80,8 @@
    16.4  vpath %.c   $(SHARE_SRC)/native/sun/java2d
    16.5  
    16.6  ifeq ($(PLATFORM), windows)
    16.7 -
    16.8 -OTHER_LDLIBS = user32.lib version.lib $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
    16.9 +OTHER_CFLAGS += -DCMS_IS_WINDOWS_ -Dsqrtf=sqrt
   16.10 +OTHER_LDLIBS = $(OBJDIR)/../../../sun.awt/awt/$(OBJDIRNAME)/awt.lib
   16.11  OTHER_INCLUDES += -I$(SHARE_SRC)/native/sun/java2d \
   16.12                    -I$(SHARE_SRC)/native/sun/awt/debug
   16.13  
    17.1 --- a/make/sun/net/FILES_java.gmk	Thu Sep 23 17:33:40 2010 -0700
    17.2 +++ b/make/sun/net/FILES_java.gmk	Fri Sep 24 16:41:32 2010 -0700
    17.3 @@ -53,6 +53,7 @@
    17.4  	sun/net/ftp/FtpProtocolException.java \
    17.5  	sun/net/ftp/impl/FtpClient.java \
    17.6  	sun/net/ftp/impl/DefaultFtpClientProvider.java \
    17.7 +	sun/net/sdp/SdpSupport.java \
    17.8  	sun/net/spi/DefaultProxySelector.java \
    17.9  	sun/net/spi/nameservice/NameServiceDescriptor.java \
   17.10  	sun/net/spi/nameservice/NameService.java \
   17.11 @@ -136,8 +137,6 @@
   17.12  
   17.13  ifeq ($(PLATFORM), windows)
   17.14      FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java 
   17.15 +else
   17.16 +    FILES_java += sun/net/sdp/SdpProvider.java
   17.17  endif
   17.18 -
   17.19 -ifeq ($(PLATFORM), solaris)
   17.20 -    FILES_java += sun/net/spi/SdpProvider.java
   17.21 -endif
    18.1 --- a/src/share/bin/java.c	Thu Sep 23 17:33:40 2010 -0700
    18.2 +++ b/src/share/bin/java.c	Fri Sep 24 16:41:32 2010 -0700
    18.3 @@ -712,19 +712,19 @@
    18.4      struct stat statbuf;
    18.5  
    18.6      /* return if jre/lib/rt.jar exists */
    18.7 -    sprintf(pathname, "%s%slib%srt.jar", jrepath, separator, separator);
    18.8 +    JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%srt.jar", jrepath, separator, separator);
    18.9      if (stat(pathname, &statbuf) == 0) {
   18.10          return;
   18.11      }
   18.12  
   18.13      /* return if jre/classes exists */
   18.14 -    sprintf(pathname, "%s%sclasses", jrepath, separator);
   18.15 +    JLI_Snprintf(pathname, sizeof(pathname), "%s%sclasses", jrepath, separator);
   18.16      if (stat(pathname, &statbuf) == 0) {
   18.17          return;
   18.18      }
   18.19  
   18.20      /* modularized jre */
   18.21 -    sprintf(pathname, "%s%slib%s*", jrepath, separator, separator);
   18.22 +    JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%s*", jrepath, separator, separator);
   18.23      s = (char *) JLI_WildcardExpandClasspath(pathname);
   18.24      def = JLI_MemAlloc(sizeof(format)
   18.25                         - 2 /* strlen("%s") */
   18.26 @@ -1624,11 +1624,8 @@
   18.27      if (JLI_IsTraceLauncher()) {
   18.28          start = CounterGet();
   18.29      }
   18.30 -
   18.31 -    JLI_StrCpy(jvmCfgName, jrepath);
   18.32 -    JLI_StrCat(jvmCfgName, FILESEP "lib" FILESEP);
   18.33 -    JLI_StrCat(jvmCfgName, arch);
   18.34 -    JLI_StrCat(jvmCfgName, FILESEP "jvm.cfg");
   18.35 +    JLI_Snprintf(jvmCfgName, sizeof(jvmCfgName), "%s%slib%s%s%sjvm.cfg",
   18.36 +        jrepath, FILESEP, FILESEP, arch, FILESEP);
   18.37  
   18.38      jvmCfg = fopen(jvmCfgName, "r");
   18.39      if (jvmCfg == NULL) {
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/src/share/classes/com/oracle/net/Sdp.java	Fri Sep 24 16:41:32 2010 -0700
    19.3 @@ -0,0 +1,201 @@
    19.4 +/*
    19.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    19.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.7 + *
    19.8 + * This code is free software; you can redistribute it and/or modify it
    19.9 + * under the terms of the GNU General Public License version 2 only, as
   19.10 + * published by the Free Software Foundation.  Oracle designates this
   19.11 + * particular file as subject to the "Classpath" exception as provided
   19.12 + * by Oracle in the LICENSE file that accompanied this code.
   19.13 + *
   19.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   19.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   19.17 + * version 2 for more details (a copy is included in the LICENSE file that
   19.18 + * accompanied this code).
   19.19 + *
   19.20 + * You should have received a copy of the GNU General Public License version
   19.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   19.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   19.23 + *
   19.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   19.25 + * or visit www.oracle.com if you need additional information or have any
   19.26 + * questions.
   19.27 + */
   19.28 +
   19.29 +package com.oracle.net;
   19.30 +
   19.31 +import java.net.Socket;
   19.32 +import java.net.ServerSocket;
   19.33 +import java.net.SocketImpl;
   19.34 +import java.net.SocketImplFactory;
   19.35 +import java.net.SocketException;
   19.36 +import java.nio.channels.SocketChannel;
   19.37 +import java.nio.channels.ServerSocketChannel;
   19.38 +import java.io.IOException;
   19.39 +import java.io.FileDescriptor;
   19.40 +import java.security.AccessController;
   19.41 +import java.security.PrivilegedAction;
   19.42 +import java.lang.reflect.Constructor;
   19.43 +import java.lang.reflect.AccessibleObject;
   19.44 +import java.lang.reflect.InvocationTargetException;
   19.45 +
   19.46 +import sun.net.sdp.SdpSupport;
   19.47 +
   19.48 +/**
   19.49 + * This class consists exclusively of static methods that Sockets or Channels to
   19.50 + * sockets that support the InfiniBand Sockets Direct Protocol (SDP).
   19.51 + */
   19.52 +
   19.53 +public final class Sdp {
   19.54 +    private Sdp() { }
   19.55 +
   19.56 +    /**
   19.57 +     * The package-privage ServerSocket(SocketImpl) constructor
   19.58 +     */
   19.59 +    private static final Constructor<ServerSocket> serverSocketCtor;
   19.60 +    static {
   19.61 +        try {
   19.62 +            serverSocketCtor = (Constructor<ServerSocket>)
   19.63 +                ServerSocket.class.getDeclaredConstructor(SocketImpl.class);
   19.64 +            setAccessible(serverSocketCtor);
   19.65 +        } catch (NoSuchMethodException e) {
   19.66 +            throw new AssertionError(e);
   19.67 +        }
   19.68 +    }
   19.69 +
   19.70 +    /**
   19.71 +     * The package-private SdpSocketImpl() constructor
   19.72 +     */
   19.73 +    private static final Constructor<SocketImpl> socketImplCtor;
   19.74 +    static {
   19.75 +        try {
   19.76 +            Class<?> cl = Class.forName("java.net.SdpSocketImpl", true, null);
   19.77 +            socketImplCtor = (Constructor<SocketImpl>)cl.getDeclaredConstructor();
   19.78 +            setAccessible(socketImplCtor);
   19.79 +        } catch (ClassNotFoundException e) {
   19.80 +            throw new AssertionError(e);
   19.81 +        } catch (NoSuchMethodException e) {
   19.82 +            throw new AssertionError(e);
   19.83 +        }
   19.84 +    }
   19.85 +
   19.86 +    private static void setAccessible(final AccessibleObject o) {
   19.87 +        AccessController.doPrivileged(new PrivilegedAction<Void>() {
   19.88 +            public Void run() {
   19.89 +                o.setAccessible(true);
   19.90 +                return null;
   19.91 +            }
   19.92 +        });
   19.93 +    }
   19.94 +
   19.95 +    /**
   19.96 +     * SDP enabled Socket.
   19.97 +     */
   19.98 +    private static class SdpSocket extends Socket {
   19.99 +        SdpSocket(SocketImpl impl) throws SocketException {
  19.100 +            super(impl);
  19.101 +        }
  19.102 +    }
  19.103 +
  19.104 +    /**
  19.105 +     * Creates a SDP enabled SocketImpl
  19.106 +     */
  19.107 +    private static SocketImpl createSocketImpl() {
  19.108 +        try {
  19.109 +            return socketImplCtor.newInstance();
  19.110 +        } catch (InstantiationException x) {
  19.111 +            throw new AssertionError(x);
  19.112 +        } catch (IllegalAccessException x) {
  19.113 +            throw new AssertionError(x);
  19.114 +        } catch (InvocationTargetException x) {
  19.115 +            throw new AssertionError(x);
  19.116 +        }
  19.117 +    }
  19.118 +
  19.119 +    /**
  19.120 +     * Creates an unconnected and unbound SDP socket. The {@code Socket} is
  19.121 +     * associated with a {@link java.net.SocketImpl} of the system-default type.
  19.122 +     *
  19.123 +     * @return  a new Socket
  19.124 +     *
  19.125 +     * @throws  UnsupportedOperationException
  19.126 +     *          If SDP is not supported
  19.127 +     * @throws  IOException
  19.128 +     *          If an I/O error occurs
  19.129 +     */
  19.130 +    public static Socket openSocket() throws IOException {
  19.131 +        SocketImpl impl = createSocketImpl();
  19.132 +        return new SdpSocket(impl);
  19.133 +    }
  19.134 +
  19.135 +    /**
  19.136 +     * Creates an unbound SDP server socket. The {@code ServerSocket} is
  19.137 +     * associated with a {@link java.net.SocketImpl} of the system-default type.
  19.138 +     *
  19.139 +     * @return  a new ServerSocket
  19.140 +     *
  19.141 +     * @throws  UnsupportedOperationException
  19.142 +     *          If SDP is not supported
  19.143 +     * @throws  IOException
  19.144 +     *          If an I/O error occurs
  19.145 +     */
  19.146 +    public static ServerSocket openServerSocket() throws IOException {
  19.147 +        // create ServerSocket via package-private constructor
  19.148 +        SocketImpl impl = createSocketImpl();
  19.149 +        try {
  19.150 +            return serverSocketCtor.newInstance(impl);
  19.151 +        } catch (IllegalAccessException x) {
  19.152 +            throw new AssertionError(x);
  19.153 +        } catch (InstantiationException x) {
  19.154 +            throw new AssertionError(x);
  19.155 +        } catch (InvocationTargetException x) {
  19.156 +            Throwable cause = x.getCause();
  19.157 +            if (cause instanceof IOException)
  19.158 +                throw (IOException)cause;
  19.159 +            if (cause instanceof RuntimeException)
  19.160 +                throw (RuntimeException)cause;
  19.161 +            throw new RuntimeException(x);
  19.162 +        }
  19.163 +    }
  19.164 +
  19.165 +    /**
  19.166 +     * Opens a socket channel to a SDP socket.
  19.167 +     *
  19.168 +     * <p> The channel will be associated with the system-wide default
  19.169 +     * {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
  19.170 +     *
  19.171 +     * @return  a new SocketChannel
  19.172 +     *
  19.173 +     * @throws  UnsupportedOperationException
  19.174 +     *          If SDP is not supported or not supported by the default selector
  19.175 +     *          provider
  19.176 +     * @throws  IOException
  19.177 +     *          If an I/O error occurs.
  19.178 +     */
  19.179 +    public static SocketChannel openSocketChannel() throws IOException {
  19.180 +        FileDescriptor fd = SdpSupport.createSocket();
  19.181 +        return sun.nio.ch.Secrets.newSocketChannel(fd);
  19.182 +    }
  19.183 +
  19.184 +    /**
  19.185 +     * Opens a socket channel to a SDP socket.
  19.186 +     *
  19.187 +     * <p> The channel will be associated with the system-wide default
  19.188 +     * {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
  19.189 +     *
  19.190 +     * @return  a new ServerSocketChannel
  19.191 +     *
  19.192 +     * @throws  UnsupportedOperationException
  19.193 +     *          If SDP is not supported or not supported by the default selector
  19.194 +     *          provider
  19.195 +     * @throws  IOException
  19.196 +     *          If an I/O error occurs
  19.197 +     */
  19.198 +    public static ServerSocketChannel openServerSocketChannel()
  19.199 +        throws IOException
  19.200 +    {
  19.201 +        FileDescriptor fd = SdpSupport.createSocket();
  19.202 +        return sun.nio.ch.Secrets.newServerSocketChannel(fd);
  19.203 +    }
  19.204 +}
    20.1 --- a/src/share/classes/com/sun/java/swing/SwingUtilities3.java	Thu Sep 23 17:33:40 2010 -0700
    20.2 +++ b/src/share/classes/com/sun/java/swing/SwingUtilities3.java	Fri Sep 24 16:41:32 2010 -0700
    20.3 @@ -1,5 +1,5 @@
    20.4  /*
    20.5 - * Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
    20.6 + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
    20.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.8   *
    20.9   * This code is free software; you can redistribute it and/or modify it
   20.10 @@ -31,13 +31,14 @@
   20.11  import java.util.Map;
   20.12  import java.util.WeakHashMap;
   20.13  import java.util.concurrent.Callable;
   20.14 +import java.applet.Applet;
   20.15  import java.awt.AWTEvent;
   20.16  import java.awt.EventQueue;
   20.17  import java.awt.Component;
   20.18  import java.awt.Container;
   20.19 +import java.awt.Window;
   20.20  import javax.swing.JComponent;
   20.21  import javax.swing.RepaintManager;
   20.22 -import javax.swing.SwingUtilities;
   20.23  
   20.24  /**
   20.25   * A collection of utility methods for Swing.
   20.26 @@ -91,7 +92,7 @@
   20.27       */
   20.28      public static void setVsyncRequested(Container rootContainer,
   20.29                                           boolean isRequested) {
   20.30 -        assert SwingUtilities.getRoot(rootContainer) == rootContainer;
   20.31 +        assert (rootContainer instanceof Applet) || (rootContainer instanceof Window);
   20.32          if (isRequested) {
   20.33              vsyncedMap.put(rootContainer, Boolean.TRUE);
   20.34          } else {
   20.35 @@ -106,7 +107,7 @@
   20.36       * @return {@code true} if vsync painting is requested for {@code rootContainer}
   20.37       */
   20.38      public static boolean isVsyncRequested(Container rootContainer) {
   20.39 -        assert SwingUtilities.getRoot(rootContainer) == rootContainer;
   20.40 +        assert (rootContainer instanceof Applet) || (rootContainer instanceof Window);
   20.41          return Boolean.TRUE == vsyncedMap.get(rootContainer);
   20.42      }
   20.43  
    21.1 --- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java	Thu Sep 23 17:33:40 2010 -0700
    21.2 +++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java	Fri Sep 24 16:41:32 2010 -0700
    21.3 @@ -1,5 +1,5 @@
    21.4  /*
    21.5 - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
    21.6 + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
    21.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.8   *
    21.9   * This code is free software; you can redistribute it and/or modify it
   21.10 @@ -399,7 +399,7 @@
   21.11          }
   21.12  
   21.13          String detail = "arrow";
   21.14 -        if (name == "ScrollBar.button") {
   21.15 +        if ((name == "ScrollBar.button") || (name == "TabbedPane.button")) {
   21.16              if (arrowType == ArrowType.UP || arrowType == ArrowType.DOWN) {
   21.17                  detail = "vscrollbar";
   21.18              } else {
   21.19 @@ -409,7 +409,7 @@
   21.20                     name == "Spinner.previousButton") {
   21.21              detail = "spinbutton";
   21.22          } else if (name != "ComboBox.arrowButton") {
   21.23 -            assert false;
   21.24 +            assert false : "unexpected name: " + name;
   21.25          }
   21.26  
   21.27          int gtkState = GTKLookAndFeel.synthStateToGTKState(
   21.28 @@ -436,7 +436,7 @@
   21.29          String name = button.getName();
   21.30          String detail = "button";
   21.31          int direction = SwingConstants.CENTER;
   21.32 -        if (name == "ScrollBar.button") {
   21.33 +        if ((name == "ScrollBar.button") || (name == "TabbedPane.button")) {
   21.34              Integer prop = (Integer)
   21.35                  button.getClientProperty("__arrow_direction__");
   21.36              direction = (prop != null) ?
   21.37 @@ -457,7 +457,7 @@
   21.38          } else if (name == "Spinner.nextButton") {
   21.39              detail = "spinbutton_up";
   21.40          } else if (name != "ComboBox.arrowButton") {
   21.41 -            assert false;
   21.42 +            assert false : "unexpected name: " + name;
   21.43          }
   21.44  
   21.45          int state = context.getComponentState();
    22.1 --- a/src/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java	Thu Sep 23 17:33:40 2010 -0700
    22.2 +++ b/src/share/classes/com/sun/java/swing/plaf/gtk/PangoFonts.java	Fri Sep 24 16:41:32 2010 -0700
    22.3 @@ -150,11 +150,6 @@
    22.4           * case for it to be a problem the values would have to be different.
    22.5           * It also seems unlikely to arise except when a user explicitly
    22.6           * deletes the X resource database entry.
    22.7 -         * 3) Because of rounding errors sizes may differ very slightly
    22.8 -         * between JDK and GTK. To fix that would at the very least require
    22.9 -         * Swing to specify floating pt font sizes.
   22.10 -         * Eg "10 pts" for GTK at 96 dpi to get the same size at Java 2D's
   22.11 -         * 72 dpi you'd need to specify exactly 13.33.
   22.12           * There also some other issues to be aware of for the future:
   22.13           * GTK specifies the Xft.dpi value as server-wide which when used
   22.14           * on systems with 2 distinct X screens with different physical DPI
   22.15 @@ -197,11 +192,16 @@
   22.16          String fcFamilyLC = family.toLowerCase();
   22.17          if (FontUtilities.mapFcName(fcFamilyLC) != null) {
   22.18              /* family is a Fc/Pango logical font which we need to expand. */
   22.19 -           return FontUtilities.getFontConfigFUIR(fcFamilyLC, style, size);
   22.20 +            Font font =  FontUtilities.getFontConfigFUIR(fcFamilyLC, style, size);
   22.21 +            font = font.deriveFont(style, (float)dsize);
   22.22 +            return new FontUIResource(font);
   22.23          } else {
   22.24              /* It's a physical font which we will create with a fallback */
   22.25 -            Font font = new FontUIResource(family, style, size);
   22.26 -            return FontUtilities.getCompositeFontUIResource(font);
   22.27 +            Font font = new Font(family, style, size);
   22.28 +            /* a roundabout way to set the font size in floating points */
   22.29 +            font = font.deriveFont(style, (float)dsize);
   22.30 +            FontUIResource fuir = new FontUIResource(font);
   22.31 +            return FontUtilities.getCompositeFontUIResource(fuir);
   22.32          }
   22.33      }
   22.34  
    23.1 --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java	Thu Sep 23 17:33:40 2010 -0700
    23.2 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifBorders.java	Fri Sep 24 16:41:32 2010 -0700
    23.3 @@ -1,5 +1,5 @@
    23.4  /*
    23.5 - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved.
    23.6 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
    23.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    23.8   *
    23.9   * This code is free software; you can redistribute it and/or modify it
   23.10 @@ -40,8 +40,6 @@
   23.11  import java.awt.Point;
   23.12  import java.awt.Rectangle;
   23.13  
   23.14 -import java.io.Serializable;
   23.15 -
   23.16  /**
   23.17   * Factory object that can vend Icons appropriate for the basic L & F.
   23.18   * <p>
   23.19 @@ -99,7 +97,7 @@
   23.20          }
   23.21  
   23.22          public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
   23.23 -            if (((JComponent)c).hasFocus()) {
   23.24 +            if (c.hasFocus()) {
   23.25                  g.setColor(focus);
   23.26                  g.drawRect(x, y, w-1, h-1);
   23.27              } else {
   23.28 @@ -233,6 +231,9 @@
   23.29          }
   23.30  
   23.31          public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
   23.32 +            if (!(c instanceof JMenuBar)) {
   23.33 +                return;
   23.34 +            }
   23.35              JMenuBar menuBar = (JMenuBar)c;
   23.36              if (menuBar.isBorderPainted() == true) {
   23.37                  // this draws the MenuBar border
   23.38 @@ -658,6 +659,9 @@
   23.39           * @param height the height of the painted border
   23.40           */
   23.41          public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
   23.42 +            if (!(c instanceof JPopupMenu)) {
   23.43 +                return;
   23.44 +            }
   23.45  
   23.46              Font origFont = g.getFont();
   23.47              Color origColor = g.getColor();
   23.48 @@ -701,6 +705,9 @@
   23.49           * @param insets the object to be reinitialized
   23.50           */
   23.51          public Insets getBorderInsets(Component c, Insets insets) {
   23.52 +            if (!(c instanceof JPopupMenu)) {
   23.53 +                return insets;
   23.54 +            }
   23.55              FontMetrics fm;
   23.56              int         descent = 0;
   23.57              int         ascent = 16;
    24.1 --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java	Thu Sep 23 17:33:40 2010 -0700
    24.2 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsBorders.java	Fri Sep 24 16:41:32 2010 -0700
    24.3 @@ -1,5 +1,5 @@
    24.4  /*
    24.5 - * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
    24.6 + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
    24.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.8   *
    24.9   * This code is free software; you can redistribute it and/or modify it
   24.10 @@ -32,12 +32,8 @@
   24.11  
   24.12  import java.awt.Component;
   24.13  import java.awt.Insets;
   24.14 -import java.awt.Dimension;
   24.15 -import java.awt.Image;
   24.16 -import java.awt.Rectangle;
   24.17  import java.awt.Color;
   24.18  import java.awt.Graphics;
   24.19 -import java.io.Serializable;
   24.20  
   24.21  import static com.sun.java.swing.plaf.windows.TMSchema.*;
   24.22  import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
   24.23 @@ -159,6 +155,9 @@
   24.24  
   24.25          public void paintBorder(Component c, Graphics g, int x, int y,
   24.26                                  int width, int height) {
   24.27 +            if (!(c instanceof JToolBar)) {
   24.28 +                return;
   24.29 +            }
   24.30              g.translate(x, y);
   24.31  
   24.32              XPStyle xp = XPStyle.getXP();
   24.33 @@ -190,33 +189,33 @@
   24.34  
   24.35                  } else {
   24.36  
   24.37 -                if (!vertical) {
   24.38 -                    if (c.getComponentOrientation().isLeftToRight()) {
   24.39 +                    if (!vertical) {
   24.40 +                        if (c.getComponentOrientation().isLeftToRight()) {
   24.41 +                            g.setColor(shadow);
   24.42 +                            g.drawLine(4, 3, 4, height - 4);
   24.43 +                            g.drawLine(4, height - 4, 2, height - 4);
   24.44 +
   24.45 +                            g.setColor(highlight);
   24.46 +                            g.drawLine(2, 3, 3, 3);
   24.47 +                            g.drawLine(2, 3, 2, height - 5);
   24.48 +                        } else {
   24.49 +                            g.setColor(shadow);
   24.50 +                            g.drawLine(width - 3, 3, width - 3, height - 4);
   24.51 +                            g.drawLine(width - 4, height - 4, width - 4, height - 4);
   24.52 +
   24.53 +                            g.setColor(highlight);
   24.54 +                            g.drawLine(width - 5, 3, width - 4, 3);
   24.55 +                            g.drawLine(width - 5, 3, width - 5, height - 5);
   24.56 +                        }
   24.57 +                    } else { // Vertical
   24.58                          g.setColor(shadow);
   24.59 -                        g.drawLine(4, 3, 4, height - 4);
   24.60 -                        g.drawLine(4, height - 4, 2, height - 4);
   24.61 +                        g.drawLine(3, 4, width - 4, 4);
   24.62 +                        g.drawLine(width - 4, 2, width - 4, 4);
   24.63  
   24.64                          g.setColor(highlight);
   24.65 -                        g.drawLine(2, 3, 3, 3);
   24.66 -                        g.drawLine(2, 3, 2, height - 5);
   24.67 -                    } else {
   24.68 -                        g.setColor(shadow);
   24.69 -                        g.drawLine(width - 3, 3, width - 3, height - 4);
   24.70 -                        g.drawLine(width - 4, height - 4, width - 4, height - 4);
   24.71 -
   24.72 -                        g.setColor(highlight);
   24.73 -                        g.drawLine(width - 5, 3, width - 4, 3);
   24.74 -                        g.drawLine(width - 5, 3, width - 5, height - 5);
   24.75 +                        g.drawLine(3, 2, width - 4, 2);
   24.76 +                        g.drawLine(3, 2, 3, 3);
   24.77                      }
   24.78 -                } else { // Vertical
   24.79 -                    g.setColor(shadow);
   24.80 -                    g.drawLine(3, 4, width - 4, 4);
   24.81 -                    g.drawLine(width - 4, 2, width - 4, 4);
   24.82 -
   24.83 -                    g.setColor(highlight);
   24.84 -                    g.drawLine(3, 2, width - 4, 2);
   24.85 -                    g.drawLine(3, 2, 3, 3);
   24.86 -                }
   24.87                  }
   24.88              }
   24.89  
   24.90 @@ -225,6 +224,9 @@
   24.91  
   24.92          public Insets getBorderInsets(Component c, Insets insets) {
   24.93              insets.set(1,1,1,1);
   24.94 +            if (!(c instanceof JToolBar)) {
   24.95 +                return insets;
   24.96 +            }
   24.97              if (((JToolBar)c).isFloatable()) {
   24.98                  int gripInset = (XPStyle.getXP() != null) ? 12 : 9;
   24.99                  if (((JToolBar)c).getOrientation() == HORIZONTAL) {
    25.1 --- a/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java	Thu Sep 23 17:33:40 2010 -0700
    25.2 +++ b/src/share/classes/com/sun/media/sound/AbstractMidiDevice.java	Fri Sep 24 16:41:32 2010 -0700
    25.3 @@ -474,7 +474,7 @@
    25.4          This is necessary for Receivers retrieved via MidiSystem.getReceiver()
    25.5          (which opens the device implicitely).
    25.6       */
    25.7 -    protected abstract class AbstractReceiver implements Receiver {
    25.8 +    protected abstract class AbstractReceiver implements MidiDeviceReceiver {
    25.9          private boolean open = true;
   25.10  
   25.11  
   25.12 @@ -508,6 +508,10 @@
   25.13              AbstractMidiDevice.this.closeInternal(this);
   25.14          }
   25.15  
   25.16 +        public MidiDevice getMidiDevice() {
   25.17 +            return AbstractMidiDevice.this;
   25.18 +        }
   25.19 +
   25.20          protected boolean isOpen() {
   25.21              return open;
   25.22          }
   25.23 @@ -529,7 +533,7 @@
   25.24       * Also, it has some optimizations regarding sending to the Receivers,
   25.25       * for known Receivers, and managing itself in the TransmitterList.
   25.26       */
   25.27 -    protected class BasicTransmitter implements Transmitter {
   25.28 +    protected class BasicTransmitter implements MidiDeviceTransmitter {
   25.29  
   25.30          private Receiver receiver = null;
   25.31          TransmitterList tlist = null;
   25.32 @@ -568,6 +572,9 @@
   25.33              }
   25.34          }
   25.35  
   25.36 +        public MidiDevice getMidiDevice() {
   25.37 +            return AbstractMidiDevice.this;
   25.38 +        }
   25.39  
   25.40      } // class BasicTransmitter
   25.41  
    26.1 --- a/src/share/classes/com/sun/media/sound/AudioFloatConverter.java	Thu Sep 23 17:33:40 2010 -0700
    26.2 +++ b/src/share/classes/com/sun/media/sound/AudioFloatConverter.java	Fri Sep 24 16:41:32 2010 -0700
    26.3 @@ -1,5 +1,5 @@
    26.4  /*
    26.5 - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
    26.6 + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
    26.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    26.8   *
    26.9   * This code is free software; you can redistribute it and/or modify it
   26.10 @@ -40,8 +40,6 @@
   26.11   */
   26.12  public abstract class AudioFloatConverter {
   26.13  
   26.14 -    public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
   26.15 -
   26.16      /***************************************************************************
   26.17       *
   26.18       * LSB Filter, used filter least significant byte in samples arrays.
   26.19 @@ -982,7 +980,7 @@
   26.20                              format.getSampleSizeInBits() + 7) / 8) - 4);
   26.21                  }
   26.22              }
   26.23 -        } else if (format.getEncoding().equals(PCM_FLOAT)) {
   26.24 +        } else if (format.getEncoding().equals(Encoding.PCM_FLOAT)) {
   26.25              if (format.getSampleSizeInBits() == 32) {
   26.26                  if (format.isBigEndian())
   26.27                      conv = new AudioFloatConversion32B();
    27.1 --- a/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java	Thu Sep 23 17:33:40 2010 -0700
    27.2 +++ b/src/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java	Fri Sep 24 16:41:32 2010 -0700
    27.3 @@ -1,5 +1,5 @@
    27.4  /*
    27.5 - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
    27.6 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
    27.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    27.8   *
    27.9   * This code is free software; you can redistribute it and/or modify it
   27.10 @@ -175,7 +175,6 @@
   27.11                  for (int c = 0; c < targetChannels; c++) {
   27.12                      for (int i = 0, ix = off + c; i < len2; i++, ix += cs) {
   27.13                          b[ix] = conversion_buffer[i];
   27.14 -                        ;
   27.15                      }
   27.16                  }
   27.17              } else if (targetChannels == 1) {
   27.18 @@ -186,7 +185,6 @@
   27.19                  for (int c = 1; c < sourceChannels; c++) {
   27.20                      for (int i = c, ix = off; i < len2; i += cs, ix++) {
   27.21                          b[ix] += conversion_buffer[i];
   27.22 -                        ;
   27.23                      }
   27.24                  }
   27.25                  float vol = 1f / ((float) sourceChannels);
   27.26 @@ -390,6 +388,7 @@
   27.27                  return -1;
   27.28              if (len < 0)
   27.29                  return 0;
   27.30 +            int offlen = off + len;
   27.31              int remain = len / nrofchannels;
   27.32              int destPos = 0;
   27.33              int in_end = ibuffer_len;
   27.34 @@ -423,7 +422,7 @@
   27.35              for (int c = 0; c < nrofchannels; c++) {
   27.36                  int ix = 0;
   27.37                  float[] buff = cbuffer[c];
   27.38 -                for (int i = c; i < b.length; i += nrofchannels) {
   27.39 +                for (int i = c + off; i < offlen; i += nrofchannels) {
   27.40                      b[i] = buff[ix++];
   27.41                  }
   27.42              }
   27.43 @@ -447,7 +446,7 @@
   27.44          }
   27.45  
   27.46          public long skip(long len) throws IOException {
   27.47 -            if (len > 0)
   27.48 +            if (len < 0)
   27.49                  return 0;
   27.50              if (skipbuffer == null)
   27.51                  skipbuffer = new float[1024 * targetFormat.getFrameSize()];
   27.52 @@ -470,7 +469,7 @@
   27.53      }
   27.54  
   27.55      private Encoding[] formats = { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   27.56 -            AudioFloatConverter.PCM_FLOAT };
   27.57 +            Encoding.PCM_FLOAT };
   27.58  
   27.59      public AudioInputStream getAudioInputStream(Encoding targetEncoding,
   27.60              AudioInputStream sourceStream) {
   27.61 @@ -482,7 +481,7 @@
   27.62          float samplerate = format.getSampleRate();
   27.63          int bits = format.getSampleSizeInBits();
   27.64          boolean bigendian = format.isBigEndian();
   27.65 -        if (targetEncoding.equals(AudioFloatConverter.PCM_FLOAT))
   27.66 +        if (targetEncoding.equals(Encoding.PCM_FLOAT))
   27.67              bits = 32;
   27.68          AudioFormat targetFormat = new AudioFormat(encoding, samplerate, bits,
   27.69                  channels, channels * bits / 8, samplerate, bigendian);
   27.70 @@ -521,19 +520,19 @@
   27.71  
   27.72      public Encoding[] getSourceEncodings() {
   27.73          return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   27.74 -                AudioFloatConverter.PCM_FLOAT };
   27.75 +                Encoding.PCM_FLOAT };
   27.76      }
   27.77  
   27.78      public Encoding[] getTargetEncodings() {
   27.79          return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   27.80 -                AudioFloatConverter.PCM_FLOAT };
   27.81 +                Encoding.PCM_FLOAT };
   27.82      }
   27.83  
   27.84      public Encoding[] getTargetEncodings(AudioFormat sourceFormat) {
   27.85          if (AudioFloatConverter.getConverter(sourceFormat) == null)
   27.86              return new Encoding[0];
   27.87          return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
   27.88 -                AudioFloatConverter.PCM_FLOAT };
   27.89 +                Encoding.PCM_FLOAT };
   27.90      }
   27.91  
   27.92      public AudioFormat[] getTargetFormats(Encoding targetEncoding,
   27.93 @@ -572,17 +571,17 @@
   27.94              }
   27.95          }
   27.96  
   27.97 -        if (targetEncoding.equals(AudioFloatConverter.PCM_FLOAT)) {
   27.98 -            formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
   27.99 +        if (targetEncoding.equals(Encoding.PCM_FLOAT)) {
  27.100 +            formats.add(new AudioFormat(Encoding.PCM_FLOAT,
  27.101                      AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
  27.102                      AudioSystem.NOT_SPECIFIED, false));
  27.103 -            formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
  27.104 +            formats.add(new AudioFormat(Encoding.PCM_FLOAT,
  27.105                      AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
  27.106                      AudioSystem.NOT_SPECIFIED, true));
  27.107 -            formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
  27.108 +            formats.add(new AudioFormat(Encoding.PCM_FLOAT,
  27.109                      AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
  27.110                      AudioSystem.NOT_SPECIFIED, false));
  27.111 -            formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
  27.112 +            formats.add(new AudioFormat(Encoding.PCM_FLOAT,
  27.113                      AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
  27.114                      AudioSystem.NOT_SPECIFIED, true));
  27.115          }
    28.1 --- a/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java	Thu Sep 23 17:33:40 2010 -0700
    28.2 +++ b/src/share/classes/com/sun/media/sound/AudioSynthesizerPropertyInfo.java	Fri Sep 24 16:41:32 2010 -0700
    28.3 @@ -42,11 +42,14 @@
    28.4       */
    28.5      public AudioSynthesizerPropertyInfo(String name, Object value) {
    28.6          this.name = name;
    28.7 -        this.value = value;
    28.8          if (value instanceof Class)
    28.9              valueClass = (Class)value;
   28.10 -        else if (value != null)
   28.11 -            valueClass = value.getClass();
   28.12 +        else
   28.13 +        {
   28.14 +            this.value = value;
   28.15 +            if (value != null)
   28.16 +                valueClass = value.getClass();
   28.17 +        }
   28.18      }
   28.19      /**
   28.20       * The name of the property.
    29.1 --- a/src/share/classes/com/sun/media/sound/DLSSoundbank.java	Thu Sep 23 17:33:40 2010 -0700
    29.2 +++ b/src/share/classes/com/sun/media/sound/DLSSoundbank.java	Fri Sep 24 16:41:32 2010 -0700
    29.3 @@ -1,5 +1,5 @@
    29.4  /*
    29.5 - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
    29.6 + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
    29.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.8   *
    29.9   * This code is free software; you can redistribute it and/or modify it
   29.10 @@ -781,7 +781,7 @@
   29.11                      }
   29.12                      if (sampleformat == 3) {
   29.13                          audioformat = new AudioFormat(
   29.14 -                                AudioFloatConverter.PCM_FLOAT, samplerate, bits,
   29.15 +                                Encoding.PCM_FLOAT, samplerate, bits,
   29.16                                  channels, framesize, samplerate, false);
   29.17                      }
   29.18  
   29.19 @@ -965,7 +965,7 @@
   29.20              sampleformat = 1;
   29.21          else if (audioformat.getEncoding().equals(Encoding.PCM_SIGNED))
   29.22              sampleformat = 1;
   29.23 -        else if (audioformat.getEncoding().equals(AudioFloatConverter.PCM_FLOAT))
   29.24 +        else if (audioformat.getEncoding().equals(Encoding.PCM_FLOAT))
   29.25              sampleformat = 3;
   29.26  
   29.27          fmt_chunk.writeUnsignedShort(sampleformat);
    30.1 --- a/src/share/classes/com/sun/media/sound/MidiDeviceReceiver.java	Thu Sep 23 17:33:40 2010 -0700
    30.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3 @@ -1,41 +0,0 @@
    30.4 -/*
    30.5 - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
    30.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    30.7 - *
    30.8 - * This code is free software; you can redistribute it and/or modify it
    30.9 - * under the terms of the GNU General Public License version 2 only, as
   30.10 - * published by the Free Software Foundation.  Oracle designates this
   30.11 - * particular file as subject to the "Classpath" exception as provided
   30.12 - * by Oracle in the LICENSE file that accompanied this code.
   30.13 - *
   30.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
   30.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   30.17 - * version 2 for more details (a copy is included in the LICENSE file that
   30.18 - * accompanied this code).
   30.19 - *
   30.20 - * You should have received a copy of the GNU General Public License version
   30.21 - * 2 along with this work; if not, write to the Free Software Foundation,
   30.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   30.23 - *
   30.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   30.25 - * or visit www.oracle.com if you need additional information or have any
   30.26 - * questions.
   30.27 - */
   30.28 -package com.sun.media.sound;
   30.29 -
   30.30 -import javax.sound.midi.MidiDevice;
   30.31 -import javax.sound.midi.Receiver;
   30.32 -
   30.33 -/**
   30.34 - * A Receiver with reference to it's MidiDevice object.
   30.35 - *
   30.36 - * @author Karl Helgason
   30.37 - */
   30.38 -public interface MidiDeviceReceiver extends Receiver {
   30.39 -
   30.40 -    /** Obtains the MidiDevice object associated with this Receiver.
   30.41 -     */
   30.42 -    public MidiDevice getMidiDevice();
   30.43 -
   30.44 -}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/src/share/classes/com/sun/media/sound/MidiDeviceReceiverEnvelope.java	Fri Sep 24 16:41:32 2010 -0700
    31.3 @@ -0,0 +1,80 @@
    31.4 +/*
    31.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    31.7 + *
    31.8 + * This code is free software; you can redistribute it and/or modify it
    31.9 + * under the terms of the GNU General Public License version 2 only, as
   31.10 + * published by the Free Software Foundation.  Oracle designates this
   31.11 + * particular file as subject to the "Classpath" exception as provided
   31.12 + * by Oracle in the LICENSE file that accompanied this code.
   31.13 + *
   31.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   31.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   31.17 + * version 2 for more details (a copy is included in the LICENSE file that
   31.18 + * accompanied this code).
   31.19 + *
   31.20 + * You should have received a copy of the GNU General Public License version
   31.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   31.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   31.23 + *
   31.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   31.25 + * or visit www.oracle.com if you need additional information or have any
   31.26 + * questions.
   31.27 + */
   31.28 +package com.sun.media.sound;
   31.29 +
   31.30 +import javax.sound.midi.*;
   31.31 +
   31.32 +
   31.33 +/**
   31.34 + * Helper class which allows to convert {@code Receiver}
   31.35 + * to {@code MidiDeviceReceiver}.
   31.36 + *
   31.37 + * @author Alex Menkov
   31.38 + */
   31.39 +public class MidiDeviceReceiverEnvelope implements MidiDeviceReceiver {
   31.40 +
   31.41 +    private final MidiDevice device;
   31.42 +    private final Receiver receiver;
   31.43 +
   31.44 +    /**
   31.45 +     * Creates a new {@code MidiDeviceReceiverEnvelope} object which
   31.46 +     * envelops the specified {@code Receiver}
   31.47 +     * and is owned by the specified {@code MidiDevice}.
   31.48 +     *
   31.49 +     * @param device the owner {@code MidiDevice}
   31.50 +     * @param receiver the {@code Receiver} to be enveloped
   31.51 +     */
   31.52 +    public MidiDeviceReceiverEnvelope(MidiDevice device, Receiver receiver) {
   31.53 +        if (device == null || receiver == null) {
   31.54 +            throw new NullPointerException();
   31.55 +        }
   31.56 +        this.device = device;
   31.57 +        this.receiver = receiver;
   31.58 +    }
   31.59 +
   31.60 +    // Receiver implementation
   31.61 +    public void close() {
   31.62 +        receiver.close();
   31.63 +    }
   31.64 +
   31.65 +    public void send(MidiMessage message, long timeStamp) {
   31.66 +        receiver.send(message, timeStamp);
   31.67 +    }
   31.68 +
   31.69 +    // MidiDeviceReceiver implementation
   31.70 +    public MidiDevice getMidiDevice() {
   31.71 +        return device;
   31.72 +    }
   31.73 +
   31.74 +    /**
   31.75 +     * Obtains the receiver enveloped
   31.76 +     * by this {@code MidiDeviceReceiverEnvelope} object.
   31.77 +     *
   31.78 +     * @return the enveloped receiver
   31.79 +     */
   31.80 +    public Receiver getReceiver() {
   31.81 +        return receiver;
   31.82 +    }
   31.83 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/src/share/classes/com/sun/media/sound/MidiDeviceTransmitterEnvelope.java	Fri Sep 24 16:41:32 2010 -0700
    32.3 @@ -0,0 +1,85 @@
    32.4 +/*
    32.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.7 + *
    32.8 + * This code is free software; you can redistribute it and/or modify it
    32.9 + * under the terms of the GNU General Public License version 2 only, as
   32.10 + * published by the Free Software Foundation.  Oracle designates this
   32.11 + * particular file as subject to the "Classpath" exception as provided
   32.12 + * by Oracle in the LICENSE file that accompanied this code.
   32.13 + *
   32.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   32.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   32.17 + * version 2 for more details (a copy is included in the LICENSE file that
   32.18 + * accompanied this code).
   32.19 + *
   32.20 + * You should have received a copy of the GNU General Public License version
   32.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   32.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   32.23 + *
   32.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   32.25 + * or visit www.oracle.com if you need additional information or have any
   32.26 + * questions.
   32.27 + */
   32.28 +package com.sun.media.sound;
   32.29 +
   32.30 +import javax.sound.midi.*;
   32.31 +
   32.32 +
   32.33 +/**
   32.34 + * Helper class which allows to convert {@code Transmitter}
   32.35 + * to {@code MidiDeviceTransmitter}.
   32.36 + *
   32.37 + * @author Alex Menkov
   32.38 + */
   32.39 +public class MidiDeviceTransmitterEnvelope implements MidiDeviceTransmitter {
   32.40 +
   32.41 +    private final MidiDevice device;
   32.42 +    private final Transmitter transmitter;
   32.43 +
   32.44 +    /**
   32.45 +     * Creates a new {@code MidiDeviceTransmitterEnvelope} object which
   32.46 +     * envelops the specified {@code Transmitter}
   32.47 +     * and is owned by the specified {@code MidiDevice}.
   32.48 +     *
   32.49 +     * @param device the owner {@code MidiDevice}
   32.50 +     * @param transmitter the {@code Transmitter} to be enveloped
   32.51 +     */
   32.52 +    public MidiDeviceTransmitterEnvelope(MidiDevice device, Transmitter transmitter) {
   32.53 +        if (device == null || transmitter == null) {
   32.54 +            throw new NullPointerException();
   32.55 +        }
   32.56 +        this.device = device;
   32.57 +        this.transmitter = transmitter;
   32.58 +    }
   32.59 +
   32.60 +    // Transmitter implementation
   32.61 +    public void setReceiver(Receiver receiver) {
   32.62 +        transmitter.setReceiver(receiver);
   32.63 +    }
   32.64 +
   32.65 +    public Receiver getReceiver() {
   32.66 +        return transmitter.getReceiver();
   32.67 +    }
   32.68 +
   32.69 +    public void close() {
   32.70 +        transmitter.close();
   32.71 +    }
   32.72 +
   32.73 +
   32.74 +    // MidiDeviceReceiver implementation
   32.75 +    public MidiDevice getMidiDevice() {
   32.76 +        return device;
   32.77 +    }
   32.78 +
   32.79 +    /**
   32.80 +     * Obtains the transmitter enveloped
   32.81 +     * by this {@code MidiDeviceTransmitterEnvelope} object.
   32.82 +     *
   32.83 +     * @return the enveloped transmitter
   32.84 +     */
   32.85 +    public Transmitter getTransmitter() {
   32.86 +        return transmitter;
   32.87 +    }
   32.88 +}
    33.1 --- a/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java	Thu Sep 23 17:33:40 2010 -0700
    33.2 +++ b/src/share/classes/com/sun/media/sound/ModelByteBufferWavetable.java	Fri Sep 24 16:41:32 2010 -0700
    33.3 @@ -205,7 +205,8 @@
    33.4          }
    33.5          if (buffer.array() == null) {
    33.6              return AudioFloatInputStream.getInputStream(new AudioInputStream(
    33.7 -                    buffer.getInputStream(), format, buffer.capacity()));
    33.8 +                    buffer.getInputStream(), format,
    33.9 +                    buffer.capacity() / format.getFrameSize()));
   33.10          }
   33.11          if (buffer8 != null) {
   33.12              if (format.getEncoding().equals(Encoding.PCM_SIGNED)
    34.1 --- a/src/share/classes/com/sun/media/sound/ModelInstrument.java	Thu Sep 23 17:33:40 2010 -0700
    34.2 +++ b/src/share/classes/com/sun/media/sound/ModelInstrument.java	Fri Sep 24 16:41:32 2010 -0700
    34.3 @@ -56,7 +56,7 @@
    34.4  
    34.5      public ModelDirector getDirector(ModelPerformer[] performers,
    34.6              MidiChannel channel, ModelDirectedPlayer player) {
    34.7 -        return new ModelStandardDirector(performers, player);
    34.8 +        return new ModelStandardIndexedDirector(performers, player);
    34.9      }
   34.10  
   34.11      public ModelPerformer[] getPerformers() {
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/src/share/classes/com/sun/media/sound/ModelStandardIndexedDirector.java	Fri Sep 24 16:41:32 2010 -0700
    35.3 @@ -0,0 +1,186 @@
    35.4 +/*
    35.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    35.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    35.7 + *
    35.8 + * This code is free software; you can redistribute it and/or modify it
    35.9 + * under the terms of the GNU General Public License version 2 only, as
   35.10 + * published by the Free Software Foundation.  Oracle designates this
   35.11 + * particular file as subject to the "Classpath" exception as provided
   35.12 + * by Oracle in the LICENSE file that accompanied this code.
   35.13 + *
   35.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   35.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   35.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   35.17 + * version 2 for more details (a copy is included in the LICENSE file that
   35.18 + * accompanied this code).
   35.19 + *
   35.20 + * You should have received a copy of the GNU General Public License version
   35.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   35.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   35.23 + *
   35.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   35.25 + * or visit www.oracle.com if you need additional information or have any
   35.26 + * questions.
   35.27 + */
   35.28 +package com.sun.media.sound;
   35.29 +
   35.30 +/**
   35.31 + * A standard indexed director who chooses performers
   35.32 + * by there keyfrom,keyto,velfrom,velto properties.
   35.33 + *
   35.34 + * @author Karl Helgason
   35.35 + */
   35.36 +public class ModelStandardIndexedDirector implements ModelDirector {
   35.37 +
   35.38 +    ModelPerformer[] performers;
   35.39 +    ModelDirectedPlayer player;
   35.40 +    boolean noteOnUsed = false;
   35.41 +    boolean noteOffUsed = false;
   35.42 +
   35.43 +    // Variables needed for index
   35.44 +    byte[][] trantables;
   35.45 +    int[] counters;
   35.46 +    int[][] mat;
   35.47 +
   35.48 +    public ModelStandardIndexedDirector(ModelPerformer[] performers,
   35.49 +            ModelDirectedPlayer player) {
   35.50 +        this.performers = performers;
   35.51 +        this.player = player;
   35.52 +        for (int i = 0; i < performers.length; i++) {
   35.53 +            ModelPerformer p = performers[i];
   35.54 +            if (p.isReleaseTriggered()) {
   35.55 +                noteOffUsed = true;
   35.56 +            } else {
   35.57 +                noteOnUsed = true;
   35.58 +            }
   35.59 +        }
   35.60 +        buildindex();
   35.61 +    }
   35.62 +
   35.63 +    private int[] lookupIndex(int x, int y) {
   35.64 +        if ((x >= 0) && (x < 128) && (y >= 0) && (y < 128)) {
   35.65 +            int xt = trantables[0][x];
   35.66 +            int yt = trantables[1][y];
   35.67 +            if (xt != -1 && yt != -1) {
   35.68 +                return mat[xt + yt * counters[0]];
   35.69 +            }
   35.70 +        }
   35.71 +        return null;
   35.72 +    }
   35.73 +
   35.74 +    private int restrict(int value) {
   35.75 +        if(value < 0) return 0;
   35.76 +        if(value > 127) return 127;
   35.77 +        return value;
   35.78 +    }
   35.79 +
   35.80 +    private void buildindex() {
   35.81 +        trantables = new byte[2][129];
   35.82 +        counters = new int[trantables.length];
   35.83 +        for (ModelPerformer performer : performers) {
   35.84 +            int keyFrom = performer.getKeyFrom();
   35.85 +            int keyTo = performer.getKeyTo();
   35.86 +            int velFrom = performer.getVelFrom();
   35.87 +            int velTo = performer.getVelTo();
   35.88 +            if (keyFrom > keyTo) continue;
   35.89 +            if (velFrom > velTo) continue;
   35.90 +            keyFrom = restrict(keyFrom);
   35.91 +            keyTo = restrict(keyTo);
   35.92 +            velFrom = restrict(velFrom);
   35.93 +            velTo = restrict(velTo);
   35.94 +            trantables[0][keyFrom] = 1;
   35.95 +            trantables[0][keyTo + 1] = 1;
   35.96 +            trantables[1][velFrom] = 1;
   35.97 +            trantables[1][velTo + 1] = 1;
   35.98 +        }
   35.99 +        for (int d = 0; d < trantables.length; d++) {
  35.100 +            byte[] trantable = trantables[d];
  35.101 +            int transize = trantable.length;
  35.102 +            for (int i = transize - 1; i >= 0; i--) {
  35.103 +                if (trantable[i] == 1) {
  35.104 +                    trantable[i] = -1;
  35.105 +                    break;
  35.106 +                }
  35.107 +                trantable[i] = -1;
  35.108 +            }
  35.109 +            int counter = -1;
  35.110 +            for (int i = 0; i < transize; i++) {
  35.111 +                if (trantable[i] != 0) {
  35.112 +                    counter++;
  35.113 +                    if (trantable[i] == -1)
  35.114 +                        break;
  35.115 +                }
  35.116 +                trantable[i] = (byte) counter;
  35.117 +            }
  35.118 +            counters[d] = counter;
  35.119 +        }
  35.120 +        mat = new int[counters[0] * counters[1]][];
  35.121 +        int ix = 0;
  35.122 +        for (ModelPerformer performer : performers) {
  35.123 +            int keyFrom = performer.getKeyFrom();
  35.124 +            int keyTo = performer.getKeyTo();
  35.125 +            int velFrom = performer.getVelFrom();
  35.126 +            int velTo = performer.getVelTo();
  35.127 +            if (keyFrom > keyTo) continue;
  35.128 +            if (velFrom > velTo) continue;
  35.129 +            keyFrom = restrict(keyFrom);
  35.130 +            keyTo = restrict(keyTo);
  35.131 +            velFrom = restrict(velFrom);
  35.132 +            velTo = restrict(velTo);
  35.133 +            int x_from = trantables[0][keyFrom];
  35.134 +            int x_to = trantables[0][keyTo + 1];
  35.135 +            int y_from = trantables[1][velFrom];
  35.136 +            int y_to = trantables[1][velTo + 1];
  35.137 +            if (x_to == -1)
  35.138 +                x_to = counters[0];
  35.139 +            if (y_to == -1)
  35.140 +                y_to = counters[1];
  35.141 +            for (int y = y_from; y < y_to; y++) {
  35.142 +                int i = x_from + y * counters[0];
  35.143 +                for (int x = x_from; x < x_to; x++) {
  35.144 +                    int[] mprev = mat[i];
  35.145 +                    if (mprev == null) {
  35.146 +                        mat[i] = new int[] { ix };
  35.147 +                    } else {
  35.148 +                        int[] mnew = new int[mprev.length + 1];
  35.149 +                        mnew[mnew.length - 1] = ix;
  35.150 +                        for (int k = 0; k < mprev.length; k++)
  35.151 +                            mnew[k] = mprev[k];
  35.152 +                        mat[i] = mnew;
  35.153 +                    }
  35.154 +                    i++;
  35.155 +                }
  35.156 +            }
  35.157 +            ix++;
  35.158 +        }
  35.159 +    }
  35.160 +
  35.161 +    public void close() {
  35.162 +    }
  35.163 +
  35.164 +    public void noteOff(int noteNumber, int velocity) {
  35.165 +        if (!noteOffUsed)
  35.166 +            return;
  35.167 +        int[] plist = lookupIndex(noteNumber, velocity);
  35.168 +        if(plist == null) return;
  35.169 +        for (int i : plist) {
  35.170 +            ModelPerformer p = performers[i];
  35.171 +            if (p.isReleaseTriggered()) {
  35.172 +                player.play(i, null);
  35.173 +            }
  35.174 +        }
  35.175 +    }
  35.176 +
  35.177 +    public void noteOn(int noteNumber, int velocity) {
  35.178 +        if (!noteOnUsed)
  35.179 +            return;
  35.180 +        int[] plist = lookupIndex(noteNumber, velocity);
  35.181 +        if(plist == null) return;
  35.182 +        for (int i : plist) {
  35.183 +            ModelPerformer p = performers[i];
  35.184 +            if (!p.isReleaseTriggered()) {
  35.185 +                player.play(i, null);
  35.186 +            }
  35.187 +        }
  35.188 +    }
  35.189 +}
    36.1 --- a/src/share/classes/com/sun/media/sound/SoftChannel.java	Thu Sep 23 17:33:40 2010 -0700
    36.2 +++ b/src/share/classes/com/sun/media/sound/SoftChannel.java	Fri Sep 24 16:41:32 2010 -0700
    36.3 @@ -1,5 +1,5 @@
    36.4  /*
    36.5 - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
    36.6 + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
    36.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    36.8   *
    36.9   * This code is free software; you can redistribute it and/or modify it
   36.10 @@ -116,7 +116,7 @@
   36.11      protected int tuning_program = 0;
   36.12      protected SoftInstrument current_instrument = null;
   36.13      protected ModelChannelMixer current_mixer = null;
   36.14 -    private ModelDirector current_director = null;
   36.15 +    protected ModelDirector current_director = null;
   36.16  
   36.17      // Controller Destination Settings
   36.18      protected int cds_control_number = -1;
   36.19 @@ -1264,13 +1264,16 @@
   36.20      }
   36.21  
   36.22      public void programChange(int bank, int program) {
   36.23 -        bank = restrict7Bit(bank);
   36.24 +        bank = restrict14Bit(bank);
   36.25          program = restrict7Bit(program);
   36.26          synchronized (control_mutex) {
   36.27              mainmixer.activity();
   36.28 -            this.bank = bank;
   36.29 -            this.program = program;
   36.30 -            current_instrument = null;
   36.31 +            if(this.bank != bank || this.program != program)
   36.32 +            {
   36.33 +                this.bank = bank;
   36.34 +                this.program = program;
   36.35 +                current_instrument = null;
   36.36 +            }
   36.37          }
   36.38      }
   36.39  
    37.1 --- a/src/share/classes/com/sun/media/sound/SoftMixingMixer.java	Thu Sep 23 17:33:40 2010 -0700
    37.2 +++ b/src/share/classes/com/sun/media/sound/SoftMixingMixer.java	Fri Sep 24 16:41:32 2010 -0700
    37.3 @@ -1,5 +1,5 @@
    37.4  /*
    37.5 - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
    37.6 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
    37.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    37.8   *
    37.9   * This code is free software; you can redistribute it and/or modify it
   37.10 @@ -118,16 +118,16 @@
   37.11                          AudioSystem.NOT_SPECIFIED, bits, channels, channels
   37.12                                  * bits / 8, AudioSystem.NOT_SPECIFIED, true));
   37.13              }
   37.14 -            formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
   37.15 +            formats.add(new AudioFormat(Encoding.PCM_FLOAT,
   37.16                      AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
   37.17                      AudioSystem.NOT_SPECIFIED, false));
   37.18 -            formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
   37.19 +            formats.add(new AudioFormat(Encoding.PCM_FLOAT,
   37.20                      AudioSystem.NOT_SPECIFIED, 32, channels, channels * 4,
   37.21                      AudioSystem.NOT_SPECIFIED, true));
   37.22 -            formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
   37.23 +            formats.add(new AudioFormat(Encoding.PCM_FLOAT,
   37.24                      AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
   37.25                      AudioSystem.NOT_SPECIFIED, false));
   37.26 -            formats.add(new AudioFormat(AudioFloatConverter.PCM_FLOAT,
   37.27 +            formats.add(new AudioFormat(Encoding.PCM_FLOAT,
   37.28                      AudioSystem.NOT_SPECIFIED, 64, channels, channels * 8,
   37.29                      AudioSystem.NOT_SPECIFIED, true));
   37.30          }
    38.1 --- a/src/share/classes/com/sun/media/sound/SoftReceiver.java	Thu Sep 23 17:33:40 2010 -0700
    38.2 +++ b/src/share/classes/com/sun/media/sound/SoftReceiver.java	Fri Sep 24 16:41:32 2010 -0700
    38.3 @@ -27,6 +27,7 @@
    38.4  import java.util.TreeMap;
    38.5  
    38.6  import javax.sound.midi.MidiDevice;
    38.7 +import javax.sound.midi.MidiDeviceReceiver;
    38.8  import javax.sound.midi.MidiMessage;
    38.9  import javax.sound.midi.ShortMessage;
   38.10  
    39.1 --- a/src/share/classes/com/sun/media/sound/SoftSynthesizer.java	Thu Sep 23 17:33:40 2010 -0700
    39.2 +++ b/src/share/classes/com/sun/media/sound/SoftSynthesizer.java	Fri Sep 24 16:41:32 2010 -0700
    39.3 @@ -1,5 +1,5 @@
    39.4  /*
    39.5 - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
    39.6 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
    39.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    39.8   *
    39.9   * This code is free software; you can redistribute it and/or modify it
   39.10 @@ -25,16 +25,25 @@
   39.11  
   39.12  package com.sun.media.sound;
   39.13  
   39.14 +import java.io.BufferedInputStream;
   39.15  import java.io.File;
   39.16 +import java.io.FileInputStream;
   39.17 +import java.io.FileOutputStream;
   39.18  import java.io.IOException;
   39.19  import java.io.InputStream;
   39.20 +import java.io.OutputStream;
   39.21  import java.lang.ref.WeakReference;
   39.22 -import java.security.AccessControlException;
   39.23 +import java.security.AccessController;
   39.24 +import java.security.PrivilegedAction;
   39.25  import java.util.ArrayList;
   39.26  import java.util.Arrays;
   39.27  import java.util.HashMap;
   39.28  import java.util.List;
   39.29  import java.util.Map;
   39.30 +import java.util.Properties;
   39.31 +import java.util.StringTokenizer;
   39.32 +import java.util.prefs.BackingStoreException;
   39.33 +import java.util.prefs.Preferences;
   39.34  
   39.35  import javax.sound.midi.Instrument;
   39.36  import javax.sound.midi.MidiChannel;
   39.37 @@ -182,6 +191,7 @@
   39.38      // 1: DLS Voice Allocation
   39.39      protected int voice_allocation_mode = 0;
   39.40  
   39.41 +    protected boolean load_default_soundbank = false;
   39.42      protected boolean reverb_light = true;
   39.43      protected boolean reverb_on = true;
   39.44      protected boolean chorus_on = true;
   39.45 @@ -226,8 +236,6 @@
   39.46              = new HashMap<String, SoftTuning>();
   39.47      private Map<String, SoftInstrument> inslist
   39.48              = new HashMap<String, SoftInstrument>();
   39.49 -    private Map<String, ModelInstrument> availlist
   39.50 -            = new HashMap<String, ModelInstrument>();
   39.51      private Map<String, ModelInstrument> loadedlist
   39.52              = new HashMap<String, ModelInstrument>();
   39.53  
   39.54 @@ -275,10 +283,12 @@
   39.55          synchronized (control_mutex) {
   39.56              if (channels != null)
   39.57                  for (SoftChannel c : channels)
   39.58 +                {
   39.59                      c.current_instrument = null;
   39.60 +                    c.current_director = null;
   39.61 +                }
   39.62              for (Instrument instrument : instruments) {
   39.63                  String pat = patchToString(instrument.getPatch());
   39.64 -                availlist.remove(pat);
   39.65                  SoftInstrument softins
   39.66                          = new SoftInstrument((ModelInstrument) instrument);
   39.67                  inslist.put(pat, softins);
   39.68 @@ -341,6 +351,7 @@
   39.69          number_of_midi_channels = (Integer)items[10].value;
   39.70          jitter_correction = (Boolean)items[11].value;
   39.71          reverb_light = (Boolean)items[12].value;
   39.72 +        load_default_soundbank = (Boolean)items[13].value;
   39.73      }
   39.74  
   39.75      private String patchToString(Patch patch) {
   39.76 @@ -578,7 +589,9 @@
   39.77                  c.current_instrument = null;
   39.78              inslist.remove(pat);
   39.79              loadedlist.remove(pat);
   39.80 -            availlist.remove(pat);
   39.81 +            for (int i = 0; i < channels.length; i++) {
   39.82 +                channels[i].allSoundOff();
   39.83 +            }
   39.84          }
   39.85      }
   39.86  
   39.87 @@ -600,7 +613,7 @@
   39.88              return false;
   39.89  
   39.90          synchronized (control_mutex) {
   39.91 -            if (!loadedlist.containsValue(to) && !availlist.containsValue(to))
   39.92 +            if (!loadedlist.containsValue(to))
   39.93                  throw new IllegalArgumentException("Instrument to is not loaded.");
   39.94              unloadInstrument(from);
   39.95              ModelMappedInstrument mfrom = new ModelMappedInstrument(
   39.96 @@ -609,118 +622,155 @@
   39.97          }
   39.98      }
   39.99  
  39.100 -    public synchronized Soundbank getDefaultSoundbank() {
  39.101 -        if (defaultSoundBank == null) {
  39.102 -            try {
  39.103 -                File javahome = new File(System.getProperties().getProperty(
  39.104 -                        "java.home"));
  39.105 -                File libaudio = new File(new File(javahome, "lib"), "audio");
  39.106 +    public Soundbank getDefaultSoundbank() {
  39.107 +        synchronized (SoftSynthesizer.class) {
  39.108 +            if (defaultSoundBank != null)
  39.109 +                return defaultSoundBank;
  39.110  
  39.111 -                if (libaudio.exists()) {
  39.112 -                    File foundfile = null;
  39.113 -                    File[] files = libaudio.listFiles();
  39.114 -                    if (files != null) {
  39.115 -                        for (int i = 0; i < files.length; i++) {
  39.116 -                            File file = files[i];
  39.117 -                            if (file.isFile()) {
  39.118 -                                String lname = file.getName().toLowerCase();
  39.119 -                                if (lname.endsWith(".sf2") ||
  39.120 -                                        lname.endsWith(".dls")) {
  39.121 -                                    if (foundfile == null || (file.length() >
  39.122 -                                            foundfile.length())) {
  39.123 -                                        foundfile = file;
  39.124 +            List<PrivilegedAction<InputStream>> actions =
  39.125 +                new ArrayList<PrivilegedAction<InputStream>>();
  39.126 +
  39.127 +            actions.add(new PrivilegedAction<InputStream>() {
  39.128 +                public InputStream run() {
  39.129 +                    File javahome = new File(System.getProperties()
  39.130 +                            .getProperty("java.home"));
  39.131 +                    File libaudio = new File(new File(javahome, "lib"), "audio");
  39.132 +                    if (libaudio.exists()) {
  39.133 +                        File foundfile = null;
  39.134 +                        File[] files = libaudio.listFiles();
  39.135 +                        if (files != null) {
  39.136 +                            for (int i = 0; i < files.length; i++) {
  39.137 +                                File file = files[i];
  39.138 +                                if (file.isFile()) {
  39.139 +                                    String lname = file.getName().toLowerCase();
  39.140 +                                    if (lname.endsWith(".sf2")
  39.141 +                                            || lname.endsWith(".dls")) {
  39.142 +                                        if (foundfile == null
  39.143 +                                                || (file.length() > foundfile
  39.144 +                                                        .length())) {
  39.145 +                                            foundfile = file;
  39.146 +                                        }
  39.147                                      }
  39.148                                  }
  39.149                              }
  39.150                          }
  39.151 -                    }
  39.152 -                    if (foundfile != null) {
  39.153 -                        try {
  39.154 -                            Soundbank sbk = MidiSystem.getSoundbank(foundfile);
  39.155 -                            defaultSoundBank = sbk;
  39.156 -                            return defaultSoundBank;
  39.157 -                        } catch (Exception e) {
  39.158 -                            //e.printStackTrace();
  39.159 +                        if (foundfile != null) {
  39.160 +                            try {
  39.161 +                                return new FileInputStream(foundfile);
  39.162 +                            } catch (IOException e) {
  39.163 +                            }
  39.164                          }
  39.165                      }
  39.166 +                    return null;
  39.167                  }
  39.168 +            });
  39.169  
  39.170 -                if (System.getProperties().getProperty("os.name")
  39.171 -                        .startsWith("Windows")) {
  39.172 -                    File gm_dls = new File(System.getenv("SystemRoot")
  39.173 -                            + "\\system32\\drivers\\gm.dls");
  39.174 -                    if (gm_dls.exists()) {
  39.175 -                        try {
  39.176 -                            Soundbank sbk = MidiSystem.getSoundbank(gm_dls);
  39.177 -                            defaultSoundBank = sbk;
  39.178 -                            return defaultSoundBank;
  39.179 -                        } catch (Exception e) {
  39.180 -                            //e.printStackTrace();
  39.181 +            actions.add(new PrivilegedAction<InputStream>() {
  39.182 +                public InputStream run() {
  39.183 +                    if (System.getProperties().getProperty("os.name")
  39.184 +                            .startsWith("Windows")) {
  39.185 +                        File gm_dls = new File(System.getenv("SystemRoot")
  39.186 +                                + "\\system32\\drivers\\gm.dls");
  39.187 +                        if (gm_dls.exists()) {
  39.188 +                            try {
  39.189 +                                return new FileInputStream(gm_dls);
  39.190 +                            } catch (IOException e) {
  39.191 +                            }
  39.192                          }
  39.193                      }
  39.194 +                    return null;
  39.195                  }
  39.196 -            } catch (AccessControlException e) {
  39.197 -            } catch (Exception e) {
  39.198 -                //e.printStackTrace();
  39.199 -            }
  39.200 +            });
  39.201  
  39.202 -            File userhome = null;
  39.203 -            File emg_soundbank_file = null;
  39.204 +            actions.add(new PrivilegedAction<InputStream>() {
  39.205 +                public InputStream run() {
  39.206 +                    /*
  39.207 +                     * Try to load saved generated soundbank
  39.208 +                     */
  39.209 +                    File userhome = new File(System.getProperty("user.home"),
  39.210 +                            ".gervill");
  39.211 +                    File emg_soundbank_file = new File(userhome,
  39.212 +                            "soundbank-emg.sf2");
  39.213 +                    if (emg_soundbank_file.exists()) {
  39.214 +                        try {
  39.215 +                            return new FileInputStream(emg_soundbank_file);
  39.216 +                        } catch (IOException e) {
  39.217 +                        }
  39.218 +                    }
  39.219 +                    return null;
  39.220 +                }
  39.221 +            });
  39.222  
  39.223 -            /*
  39.224 -             *  Try to load saved generated soundbank
  39.225 -             */
  39.226 -            try {
  39.227 -                userhome = new File(System.getProperty("user.home"),
  39.228 -                     ".gervill");
  39.229 -                emg_soundbank_file = new File(userhome, "soundbank-emg.sf2");
  39.230 -                Soundbank sbk = MidiSystem.getSoundbank(emg_soundbank_file);
  39.231 -                defaultSoundBank = sbk;
  39.232 -                return defaultSoundBank;
  39.233 -            } catch (AccessControlException e) {
  39.234 -            } catch (Exception e) {
  39.235 -                //e.printStackTrace();
  39.236 +            for (PrivilegedAction<InputStream> action : actions) {
  39.237 +                try {
  39.238 +                    InputStream is = AccessController.doPrivileged(action);
  39.239 +                    if(is == null) continue;
  39.240 +                    Soundbank sbk;
  39.241 +                    try {
  39.242 +                        sbk = MidiSystem.getSoundbank(new BufferedInputStream(is));
  39.243 +                    } finally {
  39.244 +                        is.close();
  39.245 +                    }
  39.246 +                    if (sbk != null) {
  39.247 +                        defaultSoundBank = sbk;
  39.248 +                        return defaultSoundBank;
  39.249 +                    }
  39.250 +                } catch (Exception e) {
  39.251 +                }
  39.252              }
  39.253  
  39.254              try {
  39.255 -
  39.256                  /*
  39.257 -                 *  Generate emergency soundbank
  39.258 +                 * Generate emergency soundbank
  39.259                   */
  39.260                  defaultSoundBank = EmergencySoundbank.createSoundbank();
  39.261 -
  39.262 -                /*
  39.263 -                 *  Save generated soundbank to disk for faster future use.
  39.264 -                 */
  39.265 -                if(defaultSoundBank != null)
  39.266 -                {
  39.267 -                    if(!userhome.exists()) userhome.mkdirs();
  39.268 -                    if(!emg_soundbank_file.exists())
  39.269 -                        ((SF2Soundbank)defaultSoundBank).save(emg_soundbank_file);
  39.270 -                }
  39.271              } catch (Exception e) {
  39.272 -                //e.printStackTrace();
  39.273              }
  39.274  
  39.275 +            if (defaultSoundBank != null) {
  39.276 +                /*
  39.277 +                 * Save generated soundbank to disk for faster future use.
  39.278 +                 */
  39.279 +                OutputStream out = AccessController
  39.280 +                        .doPrivileged(new PrivilegedAction<OutputStream>() {
  39.281 +                            public OutputStream run() {
  39.282 +                                try {
  39.283 +                                    File userhome = new File(System
  39.284 +                                            .getProperty("user.home"),
  39.285 +                                            ".gervill");
  39.286 +                                    if (!userhome.exists())
  39.287 +                                        userhome.mkdirs();
  39.288 +                                    File emg_soundbank_file = new File(
  39.289 +                                            userhome, "soundbank-emg.sf2");
  39.290 +                                    if (emg_soundbank_file.exists())
  39.291 +                                        return null;
  39.292 +                                    return new FileOutputStream(
  39.293 +                                            emg_soundbank_file);
  39.294 +                                } catch (IOException e) {
  39.295 +                                } catch (SecurityException e) {
  39.296 +                                }
  39.297 +                                return null;
  39.298 +                            }
  39.299 +                        });
  39.300 +                if (out != null) {
  39.301 +                    try {
  39.302 +                        ((SF2Soundbank) defaultSoundBank).save(out);
  39.303 +                        out.close();
  39.304 +                    } catch (IOException e) {
  39.305 +                    }
  39.306 +                }
  39.307 +            }
  39.308          }
  39.309          return defaultSoundBank;
  39.310      }
  39.311  
  39.312      public Instrument[] getAvailableInstruments() {
  39.313 -        if (!isOpen()) {
  39.314 -            Soundbank defsbk = getDefaultSoundbank();
  39.315 -            if (defsbk == null)
  39.316 -                return new Instrument[0];
  39.317 -            return defsbk.getInstruments();
  39.318 -        }
  39.319 -
  39.320 -        synchronized (control_mutex) {
  39.321 -            ModelInstrument[] inslist_array =
  39.322 -                    new ModelInstrument[availlist.values().size()];
  39.323 -            availlist.values().toArray(inslist_array);
  39.324 -            Arrays.sort(inslist_array, new ModelInstrumentComparator());
  39.325 -            return inslist_array;
  39.326 -        }
  39.327 +        Soundbank defsbk = getDefaultSoundbank();
  39.328 +        if (defsbk == null)
  39.329 +            return new Instrument[0];
  39.330 +        Instrument[] inslist_array = defsbk.getInstruments();
  39.331 +        Arrays.sort(inslist_array, new ModelInstrumentComparator());
  39.332 +        return inslist_array;
  39.333      }
  39.334  
  39.335      public Instrument[] getLoadedInstruments() {
  39.336 @@ -794,6 +844,31 @@
  39.337          return info;
  39.338      }
  39.339  
  39.340 +    private Properties getStoredProperties() {
  39.341 +        return AccessController
  39.342 +                .doPrivileged(new PrivilegedAction<Properties>() {
  39.343 +                    public Properties run() {
  39.344 +                        Properties p = new Properties();
  39.345 +                        String notePath = "/com/sun/media/sound/softsynthesizer";
  39.346 +                        try {
  39.347 +                            Preferences prefroot = Preferences.userRoot();
  39.348 +                            if (prefroot.nodeExists(notePath)) {
  39.349 +                                Preferences prefs = prefroot.node(notePath);
  39.350 +                                String[] prefs_keys = prefs.keys();
  39.351 +                                for (String prefs_key : prefs_keys) {
  39.352 +                                    String val = prefs.get(prefs_key, null);
  39.353 +                                    if (val != null)
  39.354 +                                        p.setProperty(prefs_key, val);
  39.355 +                                }
  39.356 +                            }
  39.357 +                        } catch (BackingStoreException e) {
  39.358 +                        } catch (SecurityException e) {
  39.359 +                        }
  39.360 +                        return p;
  39.361 +                    }
  39.362 +                });
  39.363 +    }
  39.364 +
  39.365      public AudioSynthesizerPropertyInfo[] getPropertyInfo(Map<String, Object> info) {
  39.366          List<AudioSynthesizerPropertyInfo> list =
  39.367                  new ArrayList<AudioSynthesizerPropertyInfo>();
  39.368 @@ -861,17 +936,92 @@
  39.369          item.description = "Turn light reverb mode on or off";
  39.370          list.add(item);
  39.371  
  39.372 +        item = new AudioSynthesizerPropertyInfo("load default soundbank", o?load_default_soundbank:true);
  39.373 +        item.description = "Enabled/disable loading default soundbank";
  39.374 +        list.add(item);
  39.375 +
  39.376          AudioSynthesizerPropertyInfo[] items;
  39.377          items = list.toArray(new AudioSynthesizerPropertyInfo[list.size()]);
  39.378  
  39.379 -        if (info != null)
  39.380 -            for (AudioSynthesizerPropertyInfo item2: items) {
  39.381 -                Object v = info.get(item2.name);
  39.382 +        Properties storedProperties = getStoredProperties();
  39.383 +
  39.384 +        for (AudioSynthesizerPropertyInfo item2 : items) {
  39.385 +            Object v = (info == null) ? null : info.get(item2.name);
  39.386 +            v = (v != null) ? v : storedProperties.getProperty(item2.name);
  39.387 +            if (v != null) {
  39.388                  Class c = (item2.valueClass);
  39.389 -                if (v != null)
  39.390 -                    if (c.isInstance(v))
  39.391 -                        item2.value = v;
  39.392 +                if (c.isInstance(v))
  39.393 +                    item2.value = v;
  39.394 +                else if (v instanceof String) {
  39.395 +                    String s = (String) v;
  39.396 +                    if (c == Boolean.class) {
  39.397 +                        if (s.equalsIgnoreCase("true"))
  39.398 +                            item2.value = Boolean.TRUE;
  39.399 +                        if (s.equalsIgnoreCase("false"))
  39.400 +                            item2.value = Boolean.FALSE;
  39.401 +                    } else if (c == AudioFormat.class) {
  39.402 +                        int channels = 2;
  39.403 +                        boolean signed = true;
  39.404 +                        boolean bigendian = false;
  39.405 +                        int bits = 16;
  39.406 +                        float sampleRate = 44100f;
  39.407 +                        try {
  39.408 +                            StringTokenizer st = new StringTokenizer(s, ", ");
  39.409 +                            String prevToken = "";
  39.410 +                            while (st.hasMoreTokens()) {
  39.411 +                                String token = st.nextToken().toLowerCase();
  39.412 +                                if (token.equals("mono"))
  39.413 +                                    channels = 1;
  39.414 +                                if (token.startsWith("channel"))
  39.415 +                                    channels = Integer.parseInt(prevToken);
  39.416 +                                if (token.contains("unsigned"))
  39.417 +                                    signed = false;
  39.418 +                                if (token.equals("big-endian"))
  39.419 +                                    bigendian = true;
  39.420 +                                if (token.equals("bit"))
  39.421 +                                    bits = Integer.parseInt(prevToken);
  39.422 +                                if (token.equals("hz"))
  39.423 +                                    sampleRate = Float.parseFloat(prevToken);
  39.424 +                                prevToken = token;
  39.425 +                            }
  39.426 +                            item2.value = new AudioFormat(sampleRate, bits,
  39.427 +                                    channels, signed, bigendian);
  39.428 +                        } catch (NumberFormatException e) {
  39.429 +                        }
  39.430 +
  39.431 +                    } else
  39.432 +                        try {
  39.433 +                            if (c == Byte.class)
  39.434 +                                item2.value = Byte.valueOf(s);
  39.435 +                            else if (c == Short.class)
  39.436 +                                item2.value = Short.valueOf(s);
  39.437 +                            else if (c == Integer.class)
  39.438 +                                item2.value = Integer.valueOf(s);
  39.439 +                            else if (c == Long.class)
  39.440 +                                item2.value = Long.valueOf(s);
  39.441 +                            else if (c == Float.class)
  39.442 +                                item2.value = Float.valueOf(s);
  39.443 +                            else if (c == Double.class)
  39.444 +                                item2.value = Double.valueOf(s);
  39.445 +                        } catch (NumberFormatException e) {
  39.446 +                        }
  39.447 +                } else if (v instanceof Number) {
  39.448 +                    Number n = (Number) v;
  39.449 +                    if (c == Byte.class)
  39.450 +                        item2.value = Byte.valueOf(n.byteValue());
  39.451 +                    if (c == Short.class)
  39.452 +                        item2.value = Short.valueOf(n.shortValue());
  39.453 +                    if (c == Integer.class)
  39.454 +                        item2.value = Integer.valueOf(n.intValue());
  39.455 +                    if (c == Long.class)
  39.456 +                        item2.value = Long.valueOf(n.longValue());
  39.457 +                    if (c == Float.class)
  39.458 +                        item2.value = Float.valueOf(n.floatValue());
  39.459 +                    if (c == Double.class)
  39.460 +                        item2.value = Double.valueOf(n.doubleValue());
  39.461 +                }
  39.462              }
  39.463 +        }
  39.464  
  39.465          return items;
  39.466      }
  39.467 @@ -1007,11 +1157,12 @@
  39.468              if (targetFormat != null)
  39.469                  setFormat(targetFormat);
  39.470  
  39.471 -            Soundbank defbank = getDefaultSoundbank();
  39.472 -            if (defbank != null) {
  39.473 -                loadAllInstruments(defbank);
  39.474 -                availlist.putAll(loadedlist);
  39.475 -                loadedlist.clear();
  39.476 +            if (load_default_soundbank)
  39.477 +            {
  39.478 +                Soundbank defbank = getDefaultSoundbank();
  39.479 +                if (defbank != null) {
  39.480 +                    loadAllInstruments(defbank);
  39.481 +                }
  39.482              }
  39.483  
  39.484              voices = new SoftVoice[maxpoly];
  39.485 @@ -1117,7 +1268,6 @@
  39.486              }
  39.487  
  39.488              inslist.clear();
  39.489 -            availlist.clear();
  39.490              loadedlist.clear();
  39.491              tunings.clear();
  39.492  
    40.1 --- a/src/share/classes/com/sun/media/sound/SoftVoice.java	Thu Sep 23 17:33:40 2010 -0700
    40.2 +++ b/src/share/classes/com/sun/media/sound/SoftVoice.java	Fri Sep 24 16:41:32 2010 -0700
    40.3 @@ -279,9 +279,12 @@
    40.4      }
    40.5  
    40.6      protected void updateTuning(SoftTuning newtuning) {
    40.7 +        tuning = newtuning;
    40.8          tunedKey = tuning.getTuning(note) / 100.0;
    40.9          if (!portamento) {
   40.10              co_noteon_keynumber[0] = tunedKey * (1.0 / 128.0);
   40.11 +            if(performer == null)
   40.12 +                return;
   40.13              int[] c = performer.midi_connections[4];
   40.14              if (c == null)
   40.15                  return;
   40.16 @@ -433,6 +436,8 @@
   40.17      }
   40.18  
   40.19      protected void setPolyPressure(int pressure) {
   40.20 +        if(performer == null)
   40.21 +            return;
   40.22          int[] c = performer.midi_connections[2];
   40.23          if (c == null)
   40.24              return;
   40.25 @@ -441,6 +446,8 @@
   40.26      }
   40.27  
   40.28      protected void setChannelPressure(int pressure) {
   40.29 +        if(performer == null)
   40.30 +            return;
   40.31          int[] c = performer.midi_connections[1];
   40.32          if (c == null)
   40.33              return;
   40.34 @@ -449,6 +456,8 @@
   40.35      }
   40.36  
   40.37      protected void controlChange(int controller, int value) {
   40.38 +        if(performer == null)
   40.39 +            return;
   40.40          int[] c = performer.midi_ctrl_connections[controller];
   40.41          if (c == null)
   40.42              return;
   40.43 @@ -457,6 +466,8 @@
   40.44      }
   40.45  
   40.46      protected void nrpnChange(int controller, int value) {
   40.47 +        if(performer == null)
   40.48 +            return;
   40.49          int[] c = performer.midi_nrpn_connections.get(controller);
   40.50          if (c == null)
   40.51              return;
   40.52 @@ -465,6 +476,8 @@
   40.53      }
   40.54  
   40.55      protected void rpnChange(int controller, int value) {
   40.56 +        if(performer == null)
   40.57 +            return;
   40.58          int[] c = performer.midi_rpn_connections.get(controller);
   40.59          if (c == null)
   40.60              return;
   40.61 @@ -473,6 +486,8 @@
   40.62      }
   40.63  
   40.64      protected void setPitchBend(int bend) {
   40.65 +        if(performer == null)
   40.66 +            return;
   40.67          int[] c = performer.midi_connections[0];
   40.68          if (c == null)
   40.69              return;
   40.70 @@ -499,6 +514,8 @@
   40.71  
   40.72          co_noteon_on[0] = -1;
   40.73  
   40.74 +        if(performer == null)
   40.75 +            return;
   40.76          int[] c = performer.midi_connections[3];
   40.77          if (c == null)
   40.78              return;
   40.79 @@ -527,6 +544,8 @@
   40.80  
   40.81          co_noteon_on[0] = 0;
   40.82  
   40.83 +        if(performer == null)
   40.84 +            return;
   40.85          int[] c = performer.midi_connections[3];
   40.86          if (c == null)
   40.87              return;
   40.88 @@ -543,6 +562,8 @@
   40.89          sustain = true;
   40.90          co_noteon_on[0] = 1;
   40.91  
   40.92 +        if(performer == null)
   40.93 +            return;
   40.94          int[] c = performer.midi_connections[3];
   40.95          if (c == null)
   40.96              return;
   40.97 @@ -555,6 +576,11 @@
   40.98              active = false;
   40.99              stopping = false;
  40.100              audiostarted = false;
  40.101 +            instrument = null;
  40.102 +            performer = null;
  40.103 +            connections = null;
  40.104 +            extendedConnectionBlocks = null;
  40.105 +            channelmixer = null;
  40.106              if (osc_stream != null)
  40.107                  try {
  40.108                      osc_stream.close();
    41.1 --- a/src/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java	Thu Sep 23 17:33:40 2010 -0700
    41.2 +++ b/src/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java	Fri Sep 24 16:41:32 2010 -0700
    41.3 @@ -1,5 +1,5 @@
    41.4  /*
    41.5 - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
    41.6 + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
    41.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    41.8   *
    41.9   * This code is free software; you can redistribute it and/or modify it
   41.10 @@ -271,7 +271,7 @@
   41.11                          bits, channels, framesize, samplerate, false, p);
   41.12              }
   41.13          } else if (subFormat.equals(SUBTYPE_IEEE_FLOAT)) {
   41.14 -            audioformat = new AudioFormat(AudioFloatConverter.PCM_FLOAT,
   41.15 +            audioformat = new AudioFormat(Encoding.PCM_FLOAT,
   41.16                      samplerate, bits, channels, framesize, samplerate, false, p);
   41.17          } else
   41.18              throw new UnsupportedAudioFileException();
    42.1 --- a/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java	Thu Sep 23 17:33:40 2010 -0700
    42.2 +++ b/src/share/classes/com/sun/media/sound/WaveFloatFileReader.java	Fri Sep 24 16:41:32 2010 -0700
    42.3 @@ -1,5 +1,5 @@
    42.4  /*
    42.5 - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
    42.6 + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
    42.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    42.8   *
    42.9   * This code is free software; you can redistribute it and/or modify it
   42.10 @@ -33,6 +33,7 @@
   42.11  
   42.12  import javax.sound.sampled.AudioFileFormat;
   42.13  import javax.sound.sampled.AudioFormat;
   42.14 +import javax.sound.sampled.AudioFormat.Encoding;
   42.15  import javax.sound.sampled.AudioInputStream;
   42.16  import javax.sound.sampled.AudioSystem;
   42.17  import javax.sound.sampled.UnsupportedAudioFileException;
   42.18 @@ -102,7 +103,7 @@
   42.19              throw new UnsupportedAudioFileException();
   42.20  
   42.21          AudioFormat audioformat = new AudioFormat(
   42.22 -                AudioFloatConverter.PCM_FLOAT, samplerate, bits, channels,
   42.23 +                Encoding.PCM_FLOAT, samplerate, bits, channels,
   42.24                  framesize, samplerate, false);
   42.25          AudioFileFormat fileformat = new AudioFileFormat(
   42.26                  AudioFileFormat.Type.WAVE, audioformat,
    43.1 --- a/src/share/classes/com/sun/media/sound/WaveFloatFileWriter.java	Thu Sep 23 17:33:40 2010 -0700
    43.2 +++ b/src/share/classes/com/sun/media/sound/WaveFloatFileWriter.java	Fri Sep 24 16:41:32 2010 -0700
    43.3 @@ -1,5 +1,5 @@
    43.4  /*
    43.5 - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
    43.6 + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
    43.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    43.8   *
    43.9   * This code is free software; you can redistribute it and/or modify it
   43.10 @@ -30,6 +30,7 @@
   43.11  
   43.12  import javax.sound.sampled.AudioFileFormat;
   43.13  import javax.sound.sampled.AudioFormat;
   43.14 +import javax.sound.sampled.AudioFormat.Encoding;
   43.15  import javax.sound.sampled.AudioInputStream;
   43.16  import javax.sound.sampled.AudioSystem;
   43.17  import javax.sound.sampled.AudioFileFormat.Type;
   43.18 @@ -48,8 +49,7 @@
   43.19  
   43.20      public Type[] getAudioFileTypes(AudioInputStream stream) {
   43.21  
   43.22 -        if (!stream.getFormat().getEncoding().equals(
   43.23 -                AudioFloatConverter.PCM_FLOAT))
   43.24 +        if (!stream.getFormat().getEncoding().equals(Encoding.PCM_FLOAT))
   43.25              return new Type[0];
   43.26          return new Type[] { Type.WAVE };
   43.27      }
   43.28 @@ -58,8 +58,7 @@
   43.29          if (!Type.WAVE.equals(type))
   43.30              throw new IllegalArgumentException("File type " + type
   43.31                      + " not supported.");
   43.32 -        if (!stream.getFormat().getEncoding().equals(
   43.33 -                AudioFloatConverter.PCM_FLOAT))
   43.34 +        if (!stream.getFormat().getEncoding().equals(Encoding.PCM_FLOAT))
   43.35              throw new IllegalArgumentException("File format "
   43.36                      + stream.getFormat() + " not supported.");
   43.37      }
    44.1 --- a/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Thu Sep 23 17:33:40 2010 -0700
    44.2 +++ b/src/share/classes/com/sun/rowset/CachedRowSetImpl.java	Fri Sep 24 16:41:32 2010 -0700
    44.3 @@ -1,5 +1,5 @@
    44.4  /*
    44.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    44.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    44.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    44.8   *
    44.9   * This code is free software; you can redistribute it and/or modify it
   44.10 @@ -518,7 +518,7 @@
   44.11              setReadOnly(true);
   44.12          setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
   44.13          setEscapeProcessing(true);
   44.14 -        setTypeMap(null);
   44.15 +        //setTypeMap(null);
   44.16          checkTransactionalWriter();
   44.17  
   44.18          //Instantiating the vector for MatchColumns
   44.19 @@ -679,7 +679,10 @@
   44.20                  } else if (obj instanceof Clob) {
   44.21                      obj = new SerialClob((Clob)obj);
   44.22                  } else if (obj instanceof java.sql.Array) {
   44.23 -                    obj = new SerialArray((java.sql.Array)obj, map);
   44.24 +                    if(map != null)
   44.25 +                        obj = new SerialArray((java.sql.Array)obj, map);
   44.26 +                    else
   44.27 +                        obj = new SerialArray((java.sql.Array)obj);
   44.28                  }
   44.29  
   44.30                  ((Row)currentRow).initColumnObject(i, obj);
   44.31 @@ -762,7 +765,7 @@
   44.32          if( conn != null){
   44.33             // JDBC 4.0 mandates as does the Java EE spec that all DataBaseMetaData methods
   44.34             // must be implemented, therefore, the previous fix for 5055528 is being backed out
   44.35 -           dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
   44.36 +            dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
   44.37          }
   44.38      }
   44.39  
   44.40 @@ -6322,6 +6325,7 @@
   44.41          crs.RowSetMD = RowSetMD;
   44.42          crs.numRows = 1;
   44.43          crs.cursorPos = 0;
   44.44 +        crs.setTypeMap(this.getTypeMap());
   44.45  
   44.46          // make sure we don't get someone playing with these
   44.47          // %%% is this now necessary ???
   44.48 @@ -10114,7 +10118,7 @@
   44.49       * during the deserialization process
   44.50       *
   44.51       */
   44.52 -    protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   44.53 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   44.54          // Default state initialization happens here
   44.55          ois.defaultReadObject();
   44.56          // Initialization of transient Res Bundle happens here .
   44.57 @@ -10125,5 +10129,15 @@
   44.58          }
   44.59  
   44.60      }
   44.61 -        static final long serialVersionUID =1884577171200622428L;
   44.62 +
   44.63 +    //------------------------- JDBC 4.1 -----------------------------------
   44.64 +    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
   44.65 +        throw new SQLFeatureNotSupportedException("Not supported yet.");
   44.66 +    }
   44.67 +
   44.68 +    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
   44.69 +        throw new SQLFeatureNotSupportedException("Not supported yet.");
   44.70 +    }
   44.71 +
   44.72 +    static final long serialVersionUID =1884577171200622428L;
   44.73  }
    45.1 --- a/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java	Thu Sep 23 17:33:40 2010 -0700
    45.2 +++ b/src/share/classes/com/sun/rowset/FilteredRowSetImpl.java	Fri Sep 24 16:41:32 2010 -0700
    45.3 @@ -1,5 +1,5 @@
    45.4  /*
    45.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    45.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    45.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    45.8   *
    45.9   * This code is free software; you can redistribute it and/or modify it
   45.10 @@ -1746,5 +1746,23 @@
   45.11        onInsertRow = false;
   45.12        super.insertRow();
   45.13     }
   45.14 -  static final long serialVersionUID = 6178454588413509360L;
   45.15 +
   45.16 +   /**
   45.17 +    * This method re populates the resBundle
   45.18 +    * during the deserialization process
   45.19 +    *
   45.20 +    */
   45.21 +   private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   45.22 +       // Default state initialization happens here
   45.23 +       ois.defaultReadObject();
   45.24 +       // Initialization of transient Res Bundle happens here .
   45.25 +       try {
   45.26 +          resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   45.27 +       } catch(IOException ioe) {
   45.28 +           throw new RuntimeException(ioe);
   45.29 +       }
   45.30 +
   45.31 +   }
   45.32 +
   45.33 +   static final long serialVersionUID = 6178454588413509360L;
   45.34  } // end FilteredRowSetImpl class
    46.1 --- a/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Thu Sep 23 17:33:40 2010 -0700
    46.2 +++ b/src/share/classes/com/sun/rowset/JdbcRowSetImpl.java	Fri Sep 24 16:41:32 2010 -0700
    46.3 @@ -1,5 +1,5 @@
    46.4  /*
    46.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    46.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    46.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    46.8   *
    46.9   * This code is free software; you can redistribute it and/or modify it
   46.10 @@ -101,7 +101,7 @@
   46.11      private Vector strMatchColumns;
   46.12  
   46.13  
   46.14 -    protected transient JdbcRowSetResourceBundle jdbcResBundle;
   46.15 +    protected transient JdbcRowSetResourceBundle resBundle;
   46.16  
   46.17      /**
   46.18       * Constructs a default <code>JdbcRowSet</code> object.
   46.19 @@ -140,7 +140,7 @@
   46.20          rs   = null;
   46.21  
   46.22          try {
   46.23 -           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   46.24 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   46.25          } catch(IOException ioe) {
   46.26              throw new RuntimeException(ioe);
   46.27          }
   46.28 @@ -154,42 +154,42 @@
   46.29          try {
   46.30              setShowDeleted(false);
   46.31          } catch(SQLException sqle) {
   46.32 -             System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setshowdeleted").toString() +
   46.33 +             System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setshowdeleted").toString() +
   46.34                                  sqle.getLocalizedMessage());
   46.35          }
   46.36  
   46.37          try {
   46.38              setQueryTimeout(0);
   46.39          } catch(SQLException sqle) {
   46.40 -            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() +
   46.41 +            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() +
   46.42                                  sqle.getLocalizedMessage());
   46.43          }
   46.44  
   46.45          try {
   46.46              setMaxRows(0);
   46.47          } catch(SQLException sqle) {
   46.48 -            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() +
   46.49 +            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() +
   46.50                                  sqle.getLocalizedMessage());
   46.51          }
   46.52  
   46.53          try {
   46.54              setMaxFieldSize(0);
   46.55          } catch(SQLException sqle) {
   46.56 -             System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() +
   46.57 +             System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() +
   46.58                                  sqle.getLocalizedMessage());
   46.59          }
   46.60  
   46.61          try {
   46.62              setEscapeProcessing(true);
   46.63          } catch(SQLException sqle) {
   46.64 -             System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() +
   46.65 +             System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() +
   46.66                                  sqle.getLocalizedMessage());
   46.67          }
   46.68  
   46.69          try {
   46.70              setConcurrency(ResultSet.CONCUR_UPDATABLE);
   46.71          } catch (SQLException sqle) {
   46.72 -            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setconcurrency").toString() +
   46.73 +            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setconcurrency").toString() +
   46.74                                  sqle.getLocalizedMessage());
   46.75          }
   46.76  
   46.77 @@ -198,7 +198,7 @@
   46.78          try {
   46.79              setType(ResultSet.TYPE_SCROLL_INSENSITIVE);
   46.80          } catch(SQLException sqle){
   46.81 -          System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.settype").toString() +
   46.82 +          System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.settype").toString() +
   46.83                                  sqle.getLocalizedMessage());
   46.84          }
   46.85  
   46.86 @@ -207,7 +207,7 @@
   46.87          try {
   46.88              setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
   46.89          } catch(SQLException sqle){
   46.90 -            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.settransactionisolation").toString() +
   46.91 +            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.settransactionisolation").toString() +
   46.92                                  sqle.getLocalizedMessage());
   46.93          }
   46.94  
   46.95 @@ -263,7 +263,7 @@
   46.96          rs = null;
   46.97  
   46.98          try {
   46.99 -           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
  46.100 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
  46.101          } catch(IOException ioe) {
  46.102              throw new RuntimeException(ioe);
  46.103          }
  46.104 @@ -338,7 +338,7 @@
  46.105          rs = null;
  46.106  
  46.107          try {
  46.108 -           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
  46.109 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
  46.110          } catch(IOException ioe) {
  46.111              throw new RuntimeException(ioe);
  46.112          }
  46.113 @@ -430,7 +430,7 @@
  46.114          rs = res;
  46.115  
  46.116          try {
  46.117 -           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
  46.118 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
  46.119          } catch(IOException ioe) {
  46.120              throw new RuntimeException(ioe);
  46.121          }
  46.122 @@ -517,7 +517,7 @@
  46.123          // to the db, implies undesirable state so throw exception
  46.124  
  46.125          if (conn == null && ps == null && rs == null ) {
  46.126 -            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.invalstate").toString());
  46.127 +            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.invalstate").toString());
  46.128          }
  46.129      }
  46.130  
  46.131 @@ -593,28 +593,28 @@
  46.132          try {
  46.133              ps.setEscapeProcessing(getEscapeProcessing());
  46.134          } catch (SQLException ex) {
  46.135 -            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() +
  46.136 +            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setescapeprocessing").toString() +
  46.137                                  ex.getLocalizedMessage());
  46.138          }
  46.139  
  46.140          try {
  46.141              ps.setMaxFieldSize(getMaxFieldSize());
  46.142          } catch (SQLException ex) {
  46.143 -            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() +
  46.144 +            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setmaxfieldsize").toString() +
  46.145                                  ex.getLocalizedMessage());
  46.146          }
  46.147  
  46.148          try {
  46.149              ps.setMaxRows(getMaxRows());
  46.150          } catch (SQLException ex) {
  46.151 -           System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() +
  46.152 +           System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setmaxrows").toString() +
  46.153                                  ex.getLocalizedMessage());
  46.154          }
  46.155  
  46.156          try {
  46.157              ps.setQueryTimeout(getQueryTimeout());
  46.158          } catch (SQLException ex) {
  46.159 -           System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() +
  46.160 +           System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.setquerytimeout").toString() +
  46.161                                  ex.getLocalizedMessage());
  46.162          }
  46.163  
  46.164 @@ -651,7 +651,7 @@
  46.165                  }
  46.166              }
  46.167              catch (javax.naming.NamingException ex) {
  46.168 -                throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.connect").toString());
  46.169 +                throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.connect").toString());
  46.170              }
  46.171  
  46.172          } else if (getUrl() != null) {
  46.173 @@ -681,7 +681,7 @@
  46.174              }
  46.175              ps = conn.prepareStatement(getCommand(),ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
  46.176          } catch (SQLException ex) {
  46.177 -            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.prepare").toString() +
  46.178 +            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.prepare").toString() +
  46.179                                  ex.getLocalizedMessage());
  46.180  
  46.181              if (ps != null)
  46.182 @@ -721,15 +721,15 @@
  46.183                      if (param[0] instanceof java.sql.Date ||
  46.184                          param[0] instanceof java.sql.Time ||
  46.185                          param[0] instanceof java.sql.Timestamp) {
  46.186 -                        System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.detecteddate"));
  46.187 +                        System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.detecteddate"));
  46.188                          if (param[1] instanceof java.util.Calendar) {
  46.189 -                            System.err.println(jdbcResBundle.handleGetObject("jdbcrowsetimpl.detectedcalendar"));
  46.190 +                            System.err.println(resBundle.handleGetObject("jdbcrowsetimpl.detectedcalendar"));
  46.191                              ps.setDate(i + 1, (java.sql.Date)param[0],
  46.192                                         (java.util.Calendar)param[1]);
  46.193                              continue;
  46.194                          }
  46.195                          else {
  46.196 -                            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
  46.197 +                            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
  46.198                          }
  46.199                      }
  46.200  
  46.201 @@ -770,7 +770,7 @@
  46.202                                                (java.io.InputStream)param[0],
  46.203                                                ((Integer)param[1]).intValue());
  46.204                          default:
  46.205 -                            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
  46.206 +                            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
  46.207                          }
  46.208                      }
  46.209  
  46.210 @@ -784,7 +784,7 @@
  46.211                          continue;
  46.212                      }
  46.213  
  46.214 -                    throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
  46.215 +                    throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.paramtype").toString());
  46.216  
  46.217                  } else {
  46.218                      // common case - this catches all SQL92 types
  46.219 @@ -3749,7 +3749,7 @@
  46.220           for( int j= 0 ;j < columnIdxes.length; j++) {
  46.221              i_val = (Integer.parseInt(iMatchColumns.get(j).toString()));
  46.222              if(columnIdxes[j] != i_val) {
  46.223 -               throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols").toString());
  46.224 +               throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols").toString());
  46.225              }
  46.226           }
  46.227  
  46.228 @@ -3776,7 +3776,7 @@
  46.229  
  46.230          for(int j = 0 ;j < columnIdxes.length; j++) {
  46.231             if( !columnIdxes[j].equals(strMatchColumns.get(j)) ){
  46.232 -              throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols").toString());
  46.233 +              throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols").toString());
  46.234             }
  46.235          }
  46.236  
  46.237 @@ -3800,7 +3800,7 @@
  46.238          String []str_temp = new String[strMatchColumns.size()];
  46.239  
  46.240          if( strMatchColumns.get(0) == null) {
  46.241 -           throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmatchcols").toString());
  46.242 +           throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.setmatchcols").toString());
  46.243          }
  46.244  
  46.245          strMatchColumns.copyInto(str_temp);
  46.246 @@ -3825,7 +3825,7 @@
  46.247          i_val = ((Integer)iMatchColumns.get(0)).intValue();
  46.248  
  46.249          if( i_val == -1 ) {
  46.250 -           throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.setmatchcols").toString());
  46.251 +           throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.setmatchcols").toString());
  46.252          }
  46.253  
  46.254  
  46.255 @@ -3859,7 +3859,7 @@
  46.256  
  46.257          for(int j = 0 ; j < columnIdxes.length; j++) {
  46.258             if( columnIdxes[j] < 0 ) {
  46.259 -              throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
  46.260 +              throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
  46.261             }
  46.262          }
  46.263          for(int i = 0 ;i < columnIdxes.length; i++) {
  46.264 @@ -3886,7 +3886,7 @@
  46.265  
  46.266          for(int j = 0; j < columnNames.length; j++) {
  46.267             if( columnNames[j] == null || columnNames[j].equals("")) {
  46.268 -              throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
  46.269 +              throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
  46.270             }
  46.271          }
  46.272          for( int i = 0; i < columnNames.length; i++) {
  46.273 @@ -3915,7 +3915,7 @@
  46.274      public void setMatchColumn(int columnIdx) throws SQLException {
  46.275          // validate, if col is ok to be set
  46.276          if(columnIdx < 0) {
  46.277 -            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
  46.278 +            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols1").toString());
  46.279          } else {
  46.280              // set iMatchColumn
  46.281              iMatchColumns.set(0, new Integer(columnIdx));
  46.282 @@ -3941,7 +3941,7 @@
  46.283      public void setMatchColumn(String columnName) throws SQLException {
  46.284          // validate, if col is ok to be set
  46.285          if(columnName.equals(null) || ((columnName = columnName.trim()) == "" )) {
  46.286 -            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
  46.287 +            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.matchcols2").toString());
  46.288          } else {
  46.289              // set strMatchColumn
  46.290              strMatchColumns.set(0, columnName);
  46.291 @@ -3966,9 +3966,9 @@
  46.292      public void unsetMatchColumn(int columnIdx) throws SQLException {
  46.293          // check if we are unsetting the SAME column
  46.294          if(! iMatchColumns.get(0).equals(new Integer(columnIdx) )  ) {
  46.295 -            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
  46.296 +            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
  46.297          } else if(strMatchColumns.get(0) != null) {
  46.298 -            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.usecolname").toString());
  46.299 +            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.usecolname").toString());
  46.300          } else {
  46.301                  // that is, we are unsetting it.
  46.302                 iMatchColumns.set(0, new Integer(-1));
  46.303 @@ -3995,9 +3995,9 @@
  46.304          columnName = columnName.trim();
  46.305  
  46.306          if(!((strMatchColumns.get(0)).equals(columnName))) {
  46.307 -            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
  46.308 +            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.unsetmatch").toString());
  46.309          } else if( ((Integer)(iMatchColumns.get(0))).intValue() > 0) {
  46.310 -            throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.usecolid").toString());
  46.311 +            throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.usecolid").toString());
  46.312          } else {
  46.313              strMatchColumns.set(0, null);   // that is, we are unsetting it.
  46.314          }
  46.315 @@ -4152,7 +4152,7 @@
  46.316      private void checkTypeConcurrency() throws SQLException {
  46.317          if(rs.getType() == TYPE_FORWARD_ONLY ||
  46.318             rs.getConcurrency() == CONCUR_READ_ONLY) {
  46.319 -              throw new SQLException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.resnotupd").toString());
  46.320 +              throw new SQLException(resBundle.handleGetObject("jdbcrowsetimpl.resnotupd").toString());
  46.321           }
  46.322      }
  46.323  
  46.324 @@ -4642,7 +4642,7 @@
  46.325       * @since 6.0
  46.326       */
  46.327      public SQLXML getSQLXML(int columnIndex) throws SQLException {
  46.328 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.329 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.330      }
  46.331  
  46.332      /**
  46.333 @@ -4653,7 +4653,7 @@
  46.334       * @throws SQLException if a database access error occurs
  46.335       */
  46.336      public SQLXML getSQLXML(String colName) throws SQLException {
  46.337 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.338 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.339      }
  46.340  
  46.341      /**
  46.342 @@ -4668,7 +4668,7 @@
  46.343       * @since 6.0
  46.344       */
  46.345      public RowId getRowId(int columnIndex) throws SQLException {
  46.346 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.347 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.348      }
  46.349  
  46.350      /**
  46.351 @@ -4683,7 +4683,7 @@
  46.352       * @since 6.0
  46.353       */
  46.354      public RowId getRowId(String columnName) throws SQLException {
  46.355 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.356 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.357      }
  46.358  
  46.359      /**
  46.360 @@ -4699,7 +4699,7 @@
  46.361       * @since 6.0
  46.362       */
  46.363      public void updateRowId(int columnIndex, RowId x) throws SQLException {
  46.364 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.365 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.366      }
  46.367  
  46.368      /**
  46.369 @@ -4715,7 +4715,7 @@
  46.370       * @since 6.0
  46.371       */
  46.372      public void updateRowId(String columnName, RowId x) throws SQLException {
  46.373 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.374 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.375      }
  46.376  
  46.377      /**
  46.378 @@ -4725,7 +4725,7 @@
  46.379       * @since 6.0
  46.380       */
  46.381      public int getHoldability() throws SQLException {
  46.382 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.383 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.384      }
  46.385  
  46.386      /**
  46.387 @@ -4736,7 +4736,7 @@
  46.388       * @since 6.0
  46.389       */
  46.390      public boolean isClosed() throws SQLException {
  46.391 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.392 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.393      }
  46.394  
  46.395      /**
  46.396 @@ -4748,7 +4748,7 @@
  46.397       * @since 6.0
  46.398       */
  46.399      public void updateNString(int columnIndex, String nString) throws SQLException {
  46.400 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.401 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.402      }
  46.403  
  46.404      /**
  46.405 @@ -4760,7 +4760,7 @@
  46.406       * @since 6.0
  46.407       */
  46.408      public void updateNString(String columnName, String nString) throws SQLException {
  46.409 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.410 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.411      }
  46.412  
  46.413  
  46.414 @@ -4773,7 +4773,7 @@
  46.415       * @since 6.0
  46.416       */
  46.417      public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
  46.418 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.419 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.420      }
  46.421  
  46.422      /**
  46.423 @@ -4785,7 +4785,7 @@
  46.424       * @since 6.0
  46.425       */
  46.426      public void updateNClob(String columnName, NClob nClob) throws SQLException {
  46.427 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.428 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.429      }
  46.430  
  46.431      /**
  46.432 @@ -4800,7 +4800,7 @@
  46.433       * @since 6.0
  46.434       */
  46.435      public NClob getNClob(int i) throws SQLException {
  46.436 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.437 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.438      }
  46.439  
  46.440  
  46.441 @@ -4816,7 +4816,7 @@
  46.442       * @since 6.0
  46.443       */
  46.444      public NClob getNClob(String colName) throws SQLException {
  46.445 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.446 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.447      }
  46.448  
  46.449      public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException{
  46.450 @@ -4836,7 +4836,7 @@
  46.451        * @since 1.6
  46.452        */
  46.453       public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
  46.454 -         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.455 +         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.456       }
  46.457  
  46.458      /**
  46.459 @@ -4848,7 +4848,7 @@
  46.460       * @since 1.6
  46.461       */
  46.462      public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
  46.463 -         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.464 +         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.465       }
  46.466  
  46.467      /**
  46.468 @@ -4863,7 +4863,7 @@
  46.469       * @since 1.6
  46.470       */
  46.471      public void setRowId(int parameterIndex, RowId x) throws SQLException {
  46.472 -         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.473 +         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.474       }
  46.475  
  46.476      /**
  46.477 @@ -4877,7 +4877,7 @@
  46.478      * @since 1.6
  46.479      */
  46.480     public void setRowId(String parameterName, RowId x) throws SQLException {
  46.481 -         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.482 +         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.483       }
  46.484  
  46.485  
  46.486 @@ -4897,7 +4897,7 @@
  46.487       * @since 1.6
  46.488       */
  46.489       public void setNString(int parameterIndex, String value) throws SQLException {
  46.490 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.491 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.492       }
  46.493  
  46.494  
  46.495 @@ -4925,7 +4925,7 @@
  46.496      * @since 1.6
  46.497      */
  46.498      public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
  46.499 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.500 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.501      }
  46.502  
  46.503    /**
  46.504 @@ -4940,7 +4940,7 @@
  46.505      * @since 1.6
  46.506      */
  46.507      public void setNClob(String parameterName, NClob value) throws SQLException {
  46.508 -         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.509 +         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.510       }
  46.511  
  46.512  
  46.513 @@ -4960,7 +4960,7 @@
  46.514       * @since 1.6
  46.515       */
  46.516      public java.io.Reader getNCharacterStream(int columnIndex) throws SQLException {
  46.517 -       throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.518 +       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.519       }
  46.520  
  46.521  
  46.522 @@ -4980,7 +4980,7 @@
  46.523       * @since 1.6
  46.524       */
  46.525      public java.io.Reader getNCharacterStream(String columnName) throws SQLException {
  46.526 -       throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.527 +       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.528       }
  46.529  
  46.530      /**
  46.531 @@ -4996,7 +4996,7 @@
  46.532       * @since 1.6
  46.533       */
  46.534      public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
  46.535 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.536 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.537      }
  46.538  
  46.539      /**
  46.540 @@ -5013,7 +5013,7 @@
  46.541       * @since 1.6
  46.542       */
  46.543      public void updateSQLXML(String columnName, SQLXML xmlObject) throws SQLException {
  46.544 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.545 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.546      }
  46.547  
  46.548       /**
  46.549 @@ -5031,7 +5031,7 @@
  46.550       * @since 1.6
  46.551       */
  46.552      public String getNString(int columnIndex) throws SQLException {
  46.553 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.554 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.555      }
  46.556  
  46.557      /**
  46.558 @@ -5049,7 +5049,7 @@
  46.559       * @since 1.6
  46.560       */
  46.561      public String getNString(String columnName) throws SQLException {
  46.562 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.563 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.564      }
  46.565  
  46.566       /**
  46.567 @@ -5071,7 +5071,7 @@
  46.568                              java.io.Reader x,
  46.569                              long length)
  46.570                              throws SQLException {
  46.571 -          throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.572 +          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.573         }
  46.574  
  46.575       /**
  46.576 @@ -5093,7 +5093,7 @@
  46.577                              java.io.Reader x,
  46.578                              long length)
  46.579                              throws SQLException {
  46.580 -          throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.581 +          throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.582         }
  46.583  
  46.584      /**
  46.585 @@ -5123,7 +5123,7 @@
  46.586       */
  46.587      public void updateNCharacterStream(int columnIndex,
  46.588                               java.io.Reader x) throws SQLException {
  46.589 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.590 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.591      }
  46.592  
  46.593      /**
  46.594 @@ -5155,7 +5155,7 @@
  46.595       */
  46.596      public void updateNCharacterStream(String columnLabel,
  46.597                               java.io.Reader reader) throws SQLException {
  46.598 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.599 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.600      }
  46.601  
  46.602      /**
  46.603 @@ -5188,7 +5188,7 @@
  46.604       * @since 1.6
  46.605       */
  46.606      public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException{
  46.607 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.608 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.609      }
  46.610  
  46.611      /**
  46.612 @@ -5221,7 +5221,7 @@
  46.613       * @since 1.6
  46.614       */
  46.615      public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
  46.616 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.617 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.618      }
  46.619  
  46.620      /**
  46.621 @@ -5256,7 +5256,7 @@
  46.622       * @since 1.6
  46.623       */
  46.624      public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
  46.625 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.626 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.627      }
  46.628  
  46.629      /**
  46.630 @@ -5291,7 +5291,7 @@
  46.631       * @since 1.6
  46.632       */
  46.633      public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
  46.634 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.635 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.636      }
  46.637  
  46.638      /**
  46.639 @@ -5323,7 +5323,7 @@
  46.640       * @since 1.6
  46.641       */
  46.642      public void updateClob(int columnIndex,  Reader reader, long length) throws SQLException {
  46.643 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.644 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.645      }
  46.646  
  46.647      /**
  46.648 @@ -5355,7 +5355,7 @@
  46.649       * @since 1.6
  46.650       */
  46.651      public void updateClob(String columnLabel,  Reader reader, long length) throws SQLException {
  46.652 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.653 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.654      }
  46.655  
  46.656      /**
  46.657 @@ -5389,7 +5389,7 @@
  46.658       * @since 1.6
  46.659       */
  46.660      public void updateClob(int columnIndex,  Reader reader) throws SQLException {
  46.661 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.662 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.663      }
  46.664  
  46.665      /**
  46.666 @@ -5424,7 +5424,7 @@
  46.667       * @since 1.6
  46.668       */
  46.669      public void updateClob(String columnLabel,  Reader reader) throws SQLException {
  46.670 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.671 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.672      }
  46.673  
  46.674     /**
  46.675 @@ -5458,7 +5458,7 @@
  46.676       * @since 1.6
  46.677       */
  46.678      public void updateNClob(int columnIndex,  Reader reader, long length) throws SQLException {
  46.679 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.680 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.681      }
  46.682  
  46.683      /**
  46.684 @@ -5492,7 +5492,7 @@
  46.685       * @since 1.6
  46.686       */
  46.687      public void updateNClob(String columnLabel,  Reader reader, long length) throws SQLException {
  46.688 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.689 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.690      }
  46.691  
  46.692      /**
  46.693 @@ -5528,7 +5528,7 @@
  46.694       * @since 1.6
  46.695       */
  46.696      public void updateNClob(int columnIndex,  Reader reader) throws SQLException {
  46.697 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.698 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.699      }
  46.700  
  46.701      /**
  46.702 @@ -5565,7 +5565,7 @@
  46.703       * @since 1.6
  46.704       */
  46.705      public void updateNClob(String columnLabel,  Reader reader) throws SQLException {
  46.706 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.707 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.708      }
  46.709  
  46.710  
  46.711 @@ -5590,7 +5590,7 @@
  46.712      public void updateAsciiStream(int columnIndex,
  46.713                             java.io.InputStream x,
  46.714                             long length) throws SQLException {
  46.715 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.716 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.717      }
  46.718  
  46.719      /**
  46.720 @@ -5614,7 +5614,7 @@
  46.721      public void updateBinaryStream(int columnIndex,
  46.722                              java.io.InputStream x,
  46.723                              long length) throws SQLException {
  46.724 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.725 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.726      }
  46.727  
  46.728      /**
  46.729 @@ -5638,7 +5638,7 @@
  46.730      public void updateCharacterStream(int columnIndex,
  46.731                               java.io.Reader x,
  46.732                               long length) throws SQLException {
  46.733 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.734 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.735      }
  46.736  
  46.737       /**
  46.738 @@ -5662,7 +5662,7 @@
  46.739      public void updateAsciiStream(String columnLabel,
  46.740                             java.io.InputStream x,
  46.741                             long length) throws SQLException {
  46.742 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.743 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.744      }
  46.745  
  46.746      /**
  46.747 @@ -5687,7 +5687,7 @@
  46.748       */
  46.749      public void updateAsciiStream(int columnIndex,
  46.750                             java.io.InputStream x) throws SQLException {
  46.751 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.752 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.753      }
  46.754  
  46.755      /**
  46.756 @@ -5713,7 +5713,7 @@
  46.757       */
  46.758      public void updateAsciiStream(String columnLabel,
  46.759                             java.io.InputStream x) throws SQLException {
  46.760 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.761 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.762      }
  46.763  
  46.764  
  46.765 @@ -5738,7 +5738,7 @@
  46.766      public void updateBinaryStream(String columnLabel,
  46.767                              java.io.InputStream x,
  46.768                              long length) throws SQLException {
  46.769 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.770 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.771      }
  46.772  
  46.773      /**
  46.774 @@ -5763,7 +5763,7 @@
  46.775       */
  46.776      public void updateBinaryStream(int columnIndex,
  46.777                              java.io.InputStream x) throws SQLException {
  46.778 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.779 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.780      }
  46.781  
  46.782  
  46.783 @@ -5790,7 +5790,7 @@
  46.784       */
  46.785      public void updateBinaryStream(String columnLabel,
  46.786                              java.io.InputStream x) throws SQLException {
  46.787 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.788 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.789      }
  46.790  
  46.791  
  46.792 @@ -5816,7 +5816,7 @@
  46.793      public void updateCharacterStream(String columnLabel,
  46.794                               java.io.Reader reader,
  46.795                               long length) throws SQLException {
  46.796 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.797 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.798      }
  46.799  
  46.800      /**
  46.801 @@ -5841,7 +5841,7 @@
  46.802       */
  46.803      public void updateCharacterStream(int columnIndex,
  46.804                               java.io.Reader x) throws SQLException {
  46.805 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.806 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.807      }
  46.808  
  46.809      /**
  46.810 @@ -5868,7 +5868,7 @@
  46.811       */
  46.812      public void updateCharacterStream(String columnLabel,
  46.813                               java.io.Reader reader) throws SQLException {
  46.814 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.815 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.816      }
  46.817  
  46.818  
  46.819 @@ -5885,7 +5885,7 @@
  46.820    * @since 1.4
  46.821    */
  46.822    public void setURL(int parameterIndex, java.net.URL x) throws SQLException{
  46.823 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.824 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.825     }
  46.826  
  46.827  
  46.828 @@ -5914,7 +5914,7 @@
  46.829    */
  46.830    public void setNClob(int parameterIndex, Reader reader)
  46.831      throws SQLException{
  46.832 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.833 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.834     }
  46.835  
  46.836     /**
  46.837 @@ -5942,7 +5942,7 @@
  46.838              */
  46.839              public void setNClob(String parameterName, Reader reader, long length)
  46.840      throws SQLException{
  46.841 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.842 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.843     }
  46.844  
  46.845  
  46.846 @@ -5969,7 +5969,7 @@
  46.847    */
  46.848    public void setNClob(String parameterName, Reader reader)
  46.849      throws SQLException{
  46.850 -             throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.851 +             throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.852     }
  46.853  
  46.854  
  46.855 @@ -5996,7 +5996,7 @@
  46.856       */
  46.857       public void setNClob(int parameterIndex, Reader reader, long length)
  46.858         throws SQLException{
  46.859 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.860 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.861     }
  46.862  
  46.863  
  46.864 @@ -6012,7 +6012,7 @@
  46.865       * @since 1.6
  46.866       */
  46.867       public void setNClob(int parameterIndex, NClob value) throws SQLException{
  46.868 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.869 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.870     }
  46.871  
  46.872  
  46.873 @@ -6029,7 +6029,7 @@
  46.874    */
  46.875   public void setNString(String parameterName, String value)
  46.876           throws SQLException{
  46.877 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.878 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.879     }
  46.880  
  46.881   /**
  46.882 @@ -6046,7 +6046,7 @@
  46.883    * @since 1.6
  46.884    */
  46.885    public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException{
  46.886 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.887 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.888     }
  46.889  
  46.890  
  46.891 @@ -6066,7 +6066,7 @@
  46.892    */
  46.893   public void setNCharacterStream(String parameterName, Reader value, long length)
  46.894           throws SQLException{
  46.895 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.896 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.897     }
  46.898  
  46.899    /**
  46.900 @@ -6092,7 +6092,7 @@
  46.901    * @since 1.6
  46.902    */
  46.903    public void setNCharacterStream(String parameterName, Reader value) throws SQLException{
  46.904 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.905 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.906     }
  46.907  
  46.908    /**
  46.909 @@ -6118,7 +6118,7 @@
  46.910      */
  46.911      public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
  46.912         throws SQLException{
  46.913 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.914 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.915     }
  46.916  
  46.917      /**
  46.918 @@ -6144,7 +6144,7 @@
  46.919                */
  46.920        public  void setClob(String parameterName, Reader reader, long length)
  46.921        throws SQLException{
  46.922 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.923 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.924     }
  46.925  
  46.926  
  46.927 @@ -6163,7 +6163,7 @@
  46.928      * @since 1.6
  46.929      */
  46.930      public void setClob (String parameterName, Clob x) throws SQLException{
  46.931 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.932 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.933     }
  46.934  
  46.935   /**
  46.936 @@ -6188,7 +6188,7 @@
  46.937      */
  46.938      public void setClob(String parameterName, Reader reader)
  46.939        throws SQLException{
  46.940 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.941 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.942     }
  46.943  
  46.944  
  46.945 @@ -6210,7 +6210,7 @@
  46.946      */
  46.947      public void setDate(String parameterName, java.sql.Date x)
  46.948         throws SQLException{
  46.949 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.950 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.951     }
  46.952  
  46.953     /**
  46.954 @@ -6236,7 +6236,7 @@
  46.955      */
  46.956     public void setDate(String parameterName, java.sql.Date x, Calendar cal)
  46.957         throws SQLException{
  46.958 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.959 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.960     }
  46.961  
  46.962  
  46.963 @@ -6256,7 +6256,7 @@
  46.964      */
  46.965     public void setTime(String parameterName, java.sql.Time x)
  46.966         throws SQLException{
  46.967 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.968 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.969     }
  46.970  
  46.971   /**
  46.972 @@ -6282,7 +6282,7 @@
  46.973      */
  46.974     public void setTime(String parameterName, java.sql.Time x, Calendar cal)
  46.975         throws SQLException{
  46.976 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.977 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.978     }
  46.979  
  46.980     /**
  46.981 @@ -6308,7 +6308,7 @@
  46.982     */
  46.983     public void setClob(int parameterIndex, Reader reader)
  46.984       throws SQLException{
  46.985 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.986 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.987     }
  46.988  
  46.989  
  46.990 @@ -6333,7 +6333,7 @@
  46.991     */
  46.992     public void setClob(int parameterIndex, Reader reader, long length)
  46.993       throws SQLException{
  46.994 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.995 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
  46.996     }
  46.997  
  46.998  
  46.999 @@ -6363,7 +6363,7 @@
 46.1000      */
 46.1001      public void setBlob(int parameterIndex, InputStream inputStream, long length)
 46.1002         throws SQLException{
 46.1003 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1004 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1005     }
 46.1006  
 46.1007   /**
 46.1008 @@ -6395,7 +6395,7 @@
 46.1009      */
 46.1010      public void setBlob(int parameterIndex, InputStream inputStream)
 46.1011         throws SQLException{
 46.1012 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1013 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1014     }
 46.1015  
 46.1016   /**
 46.1017 @@ -6426,7 +6426,7 @@
 46.1018        */
 46.1019        public void setBlob(String parameterName, InputStream inputStream, long length)
 46.1020           throws SQLException{
 46.1021 -         throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1022 +         throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1023      }
 46.1024  
 46.1025  
 46.1026 @@ -6444,7 +6444,7 @@
 46.1027      * @since 1.6
 46.1028      */
 46.1029     public void setBlob (String parameterName, Blob x) throws SQLException{
 46.1030 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1031 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1032     }
 46.1033  
 46.1034   /**
 46.1035 @@ -6470,7 +6470,7 @@
 46.1036      */
 46.1037      public void setBlob(String parameterName, InputStream inputStream)
 46.1038         throws SQLException{
 46.1039 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1040 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1041     }
 46.1042  
 46.1043    /**
 46.1044 @@ -6516,7 +6516,7 @@
 46.1045    */
 46.1046    public void setObject(String parameterName, Object x, int targetSqlType, int scale)
 46.1047       throws SQLException{
 46.1048 -      throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1049 +      throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1050   }
 46.1051  
 46.1052    /**
 46.1053 @@ -6542,7 +6542,7 @@
 46.1054      */
 46.1055      public void setObject(String parameterName, Object x, int targetSqlType)
 46.1056         throws SQLException{
 46.1057 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1058 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1059     }
 46.1060  
 46.1061   /**
 46.1062 @@ -6582,7 +6582,7 @@
 46.1063     * @since 1.4
 46.1064     */
 46.1065     public void setObject(String parameterName, Object x) throws SQLException{
 46.1066 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1067 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1068     }
 46.1069  
 46.1070    /**
 46.1071 @@ -6609,7 +6609,7 @@
 46.1072    */
 46.1073   public void setAsciiStream(String parameterName, java.io.InputStream x, int length)
 46.1074       throws SQLException{
 46.1075 -      throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1076 +      throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1077   }
 46.1078  
 46.1079  
 46.1080 @@ -6636,7 +6636,7 @@
 46.1081    */
 46.1082   public void setBinaryStream(String parameterName, java.io.InputStream x,
 46.1083                        int length) throws SQLException{
 46.1084 -      throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1085 +      throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1086   }
 46.1087  
 46.1088   /**
 46.1089 @@ -6665,7 +6665,7 @@
 46.1090    public void setCharacterStream(String parameterName,
 46.1091                            java.io.Reader reader,
 46.1092                            int length) throws SQLException{
 46.1093 -       throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1094 +       throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1095    }
 46.1096  
 46.1097    /**
 46.1098 @@ -6692,7 +6692,7 @@
 46.1099    */
 46.1100    public void setAsciiStream(String parameterName, java.io.InputStream x)
 46.1101            throws SQLException{
 46.1102 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1103 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1104     }
 46.1105  
 46.1106  
 46.1107 @@ -6719,7 +6719,7 @@
 46.1108      */
 46.1109     public void setBinaryStream(String parameterName, java.io.InputStream x)
 46.1110     throws SQLException{
 46.1111 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1112 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1113     }
 46.1114  
 46.1115   /**
 46.1116 @@ -6748,7 +6748,7 @@
 46.1117      */
 46.1118     public void setCharacterStream(String parameterName,
 46.1119                           java.io.Reader reader) throws SQLException{
 46.1120 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1121 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1122     }
 46.1123  
 46.1124     /**
 46.1125 @@ -6767,7 +6767,7 @@
 46.1126      * @since 1.4
 46.1127      */
 46.1128     public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
 46.1129 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1130 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1131     }
 46.1132  
 46.1133   /**
 46.1134 @@ -6788,7 +6788,7 @@
 46.1135      * @since 1.4
 46.1136      */
 46.1137     public void setString(String parameterName, String x) throws SQLException{
 46.1138 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1139 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1140     }
 46.1141  
 46.1142  
 46.1143 @@ -6810,7 +6810,7 @@
 46.1144      * @since 1.4
 46.1145      */
 46.1146     public void setBytes(String parameterName, byte x[]) throws SQLException{
 46.1147 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1148 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1149     }
 46.1150  
 46.1151   /**
 46.1152 @@ -6830,7 +6830,7 @@
 46.1153      */
 46.1154     public void setTimestamp(String parameterName, java.sql.Timestamp x)
 46.1155         throws SQLException{
 46.1156 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1157 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1158     }
 46.1159  
 46.1160      /**
 46.1161 @@ -6847,7 +6847,7 @@
 46.1162      * @since 1.4
 46.1163      */
 46.1164     public void setNull(String parameterName, int sqlType) throws SQLException {
 46.1165 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1166 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1167     }
 46.1168  
 46.1169   /**
 46.1170 @@ -6884,7 +6884,7 @@
 46.1171      */
 46.1172     public void setNull (String parameterName, int sqlType, String typeName)
 46.1173         throws SQLException{
 46.1174 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1175 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1176     }
 46.1177  
 46.1178   /**
 46.1179 @@ -6902,7 +6902,7 @@
 46.1180      * @since 1.4
 46.1181      */
 46.1182     public void setBoolean(String parameterName, boolean x) throws SQLException{
 46.1183 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1184 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1185     }
 46.1186  
 46.1187  
 46.1188 @@ -6922,7 +6922,7 @@
 46.1189      * @since 1.4
 46.1190      */
 46.1191     public void setByte(String parameterName, byte x) throws SQLException{
 46.1192 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1193 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1194     }
 46.1195  
 46.1196  
 46.1197 @@ -6941,7 +6941,7 @@
 46.1198      * @since 1.4
 46.1199      */
 46.1200     public void setShort(String parameterName, short x) throws SQLException{
 46.1201 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1202 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1203     }
 46.1204  
 46.1205  
 46.1206 @@ -6960,7 +6960,7 @@
 46.1207      * @since 1.4
 46.1208      */
 46.1209     public void setInt(String parameterName, int x) throws SQLException{
 46.1210 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1211 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1212     }
 46.1213  
 46.1214   /**
 46.1215 @@ -6978,7 +6978,7 @@
 46.1216      * @since 1.4
 46.1217      */
 46.1218     public void setLong(String parameterName, long x) throws SQLException{
 46.1219 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1220 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1221     }
 46.1222  
 46.1223  
 46.1224 @@ -6997,7 +6997,7 @@
 46.1225      * @since 1.4
 46.1226      */
 46.1227     public void setFloat(String parameterName, float x) throws SQLException{
 46.1228 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1229 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1230     }
 46.1231  
 46.1232   /**
 46.1233 @@ -7015,7 +7015,7 @@
 46.1234      * @since 1.4
 46.1235      */
 46.1236     public void setDouble(String parameterName, double x) throws SQLException{
 46.1237 -        throw new SQLFeatureNotSupportedException(jdbcResBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1238 +        throw new SQLFeatureNotSupportedException(resBundle.handleGetObject("jdbcrowsetimpl.featnotsupp").toString());
 46.1239     }
 46.1240  
 46.1241      /**
 46.1242 @@ -7023,15 +7023,25 @@
 46.1243       * during the deserialization process
 46.1244       *
 46.1245       */
 46.1246 -    protected void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
 46.1247 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
 46.1248          // Default state initialization happens here
 46.1249          ois.defaultReadObject();
 46.1250          // Initialization of transient Res Bundle happens here .
 46.1251          try {
 46.1252 -           jdbcResBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 46.1253 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
 46.1254          } catch(IOException ioe) {}
 46.1255  
 46.1256      }
 46.1257  
 46.1258     static final long serialVersionUID = -3591946023893483003L;
 46.1259 +
 46.1260 + //------------------------- JDBC 4.1 -----------------------------------
 46.1261 +
 46.1262 +    public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
 46.1263 +        throw new SQLFeatureNotSupportedException("Not supported yet.");
 46.1264 +    }
 46.1265 +
 46.1266 +    public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
 46.1267 +        throw new SQLFeatureNotSupportedException("Not supported yet.");
 46.1268 +    }
 46.1269  }
    47.1 --- a/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java	Thu Sep 23 17:33:40 2010 -0700
    47.2 +++ b/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java	Fri Sep 24 16:41:32 2010 -0700
    47.3 @@ -1,5 +1,5 @@
    47.4  /*
    47.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    47.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    47.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    47.8   *
    47.9   * This code is free software; you can redistribute it and/or modify it
   47.10 @@ -153,4 +153,5 @@
   47.11         return propResBundle.handleGetObject(key);
   47.12      }
   47.13  
   47.14 +    static final long serialVersionUID = 436199386225359954L;
   47.15  }
    48.1 --- a/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Thu Sep 23 17:33:40 2010 -0700
    48.2 +++ b/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Fri Sep 24 16:41:32 2010 -0700
    48.3 @@ -1,5 +1,5 @@
    48.4  /*
    48.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    48.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    48.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    48.8   *
    48.9   * This code is free software; you can redistribute it and/or modify it
   48.10 @@ -127,6 +127,11 @@
   48.11          strMatchKey = null;
   48.12          supportedJOINs =
   48.13                new boolean[] {false, true, false, false, false};
   48.14 +       try {
   48.15 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   48.16 +        } catch(IOException ioe) {
   48.17 +            throw new RuntimeException(ioe);
   48.18 +        }
   48.19  
   48.20      }
   48.21  
   48.22 @@ -4306,5 +4311,22 @@
   48.23           return crsInternal.createCopySchema();
   48.24       }
   48.25  
   48.26 -        static final long serialVersionUID = -5590501621560008453L;
   48.27 +    /**
   48.28 +     * This method re populates the resBundle
   48.29 +     * during the deserialization process
   48.30 +     *
   48.31 +     */
   48.32 +     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   48.33 +        // Default state initialization happens here
   48.34 +        ois.defaultReadObject();
   48.35 +        // Initialization of transient Res Bundle happens here .
   48.36 +        try {
   48.37 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   48.38 +        } catch(IOException ioe) {
   48.39 +            throw new RuntimeException(ioe);
   48.40 +        }
   48.41 +
   48.42 +     }
   48.43 +
   48.44 +     static final long serialVersionUID = -5590501621560008453L;
   48.45  }
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/src/share/classes/com/sun/rowset/RowSetFactoryImpl.java	Fri Sep 24 16:41:32 2010 -0700
    49.3 @@ -0,0 +1,69 @@
    49.4 +/*
    49.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    49.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    49.7 + *
    49.8 + * This code is free software; you can redistribute it and/or modify it
    49.9 + * under the terms of the GNU General Public License version 2 only, as
   49.10 + * published by the Free Software Foundation.  Oracle designates this
   49.11 + * particular file as subject to the "Classpath" exception as provided
   49.12 + * by Oracle in the LICENSE file that accompanied this code.
   49.13 + *
   49.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   49.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   49.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   49.17 + * version 2 for more details (a copy is included in the LICENSE file that
   49.18 + * accompanied this code).
   49.19 + *
   49.20 + * You should have received a copy of the GNU General Public License version
   49.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   49.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   49.23 + *
   49.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   49.25 + * or visit www.oracle.com if you need additional information or have any
   49.26 + * questions.
   49.27 + */
   49.28 +
   49.29 +package com.sun.rowset;
   49.30 +
   49.31 +import java.sql.SQLException;
   49.32 +import javax.sql.rowset.CachedRowSet;
   49.33 +import javax.sql.rowset.FilteredRowSet;
   49.34 +import javax.sql.rowset.JdbcRowSet;
   49.35 +import javax.sql.rowset.JoinRowSet;
   49.36 +import javax.sql.rowset.WebRowSet;
   49.37 +import javax.sql.rowset.RowSetFactory;
   49.38 +
   49.39 +/**
   49.40 + * This is the implementation specific class for the
   49.41 + * <code>javax.sql.rowset.spi.RowSetFactory</code>. This is the platform
   49.42 + * default implementation for the Java SE platform.
   49.43 + *
   49.44 + * @author Lance Andersen
   49.45 + *
   49.46 + *
   49.47 + * @version 1.7
   49.48 + */
   49.49 +public  final class RowSetFactoryImpl implements RowSetFactory {
   49.50 +
   49.51 +    public CachedRowSet createCachedRowSet() throws SQLException {
   49.52 +        return new com.sun.rowset.CachedRowSetImpl();
   49.53 +    }
   49.54 +
   49.55 +    public FilteredRowSet createFilteredRowSet() throws SQLException {
   49.56 +        return new com.sun.rowset.FilteredRowSetImpl();
   49.57 +    }
   49.58 +
   49.59 +
   49.60 +    public JdbcRowSet createJdbcRowSet() throws SQLException {
   49.61 +        return new com.sun.rowset.JdbcRowSetImpl();
   49.62 +    }
   49.63 +
   49.64 +    public JoinRowSet createJoinRowSet() throws SQLException {
   49.65 +        return new com.sun.rowset.JoinRowSetImpl();
   49.66 +    }
   49.67 +
   49.68 +    public WebRowSet createWebRowSet() throws SQLException {
   49.69 +        return new com.sun.rowset.WebRowSetImpl();
   49.70 +    }
   49.71 +
   49.72 +}
    50.1 --- a/src/share/classes/com/sun/rowset/WebRowSetImpl.java	Thu Sep 23 17:33:40 2010 -0700
    50.2 +++ b/src/share/classes/com/sun/rowset/WebRowSetImpl.java	Fri Sep 24 16:41:32 2010 -0700
    50.3 @@ -1,5 +1,5 @@
    50.4  /*
    50.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    50.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    50.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    50.8   *
    50.9   * This code is free software; you can redistribute it and/or modify it
   50.10 @@ -103,6 +103,12 @@
   50.11       */
   50.12      public WebRowSetImpl(Hashtable env) throws SQLException {
   50.13  
   50.14 +        try {
   50.15 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   50.16 +        } catch(IOException ioe) {
   50.17 +            throw new RuntimeException(ioe);
   50.18 +        }
   50.19 +
   50.20          if ( env == null) {
   50.21              throw new SQLException(resBundle.handleGetObject("webrowsetimpl.nullhash").toString());
   50.22          }
   50.23 @@ -263,5 +269,23 @@
   50.24  
   50.25              this.writeXml(oStream);
   50.26      }
   50.27 -static final long serialVersionUID = -8771775154092422943L;
   50.28 +
   50.29 +    /**
   50.30 +     * This method re populates the resBundle
   50.31 +     * during the deserialization process
   50.32 +     *
   50.33 +     */
   50.34 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   50.35 +        // Default state initialization happens here
   50.36 +        ois.defaultReadObject();
   50.37 +        // Initialization of transient Res Bundle happens here .
   50.38 +        try {
   50.39 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   50.40 +        } catch(IOException ioe) {
   50.41 +            throw new RuntimeException(ioe);
   50.42 +        }
   50.43 +
   50.44 +    }
   50.45 +
   50.46 +    static final long serialVersionUID = -8771775154092422943L;
   50.47  }
    51.1 --- a/src/share/classes/com/sun/rowset/internal/CachedRowSetReader.java	Thu Sep 23 17:33:40 2010 -0700
    51.2 +++ b/src/share/classes/com/sun/rowset/internal/CachedRowSetReader.java	Fri Sep 24 16:41:32 2010 -0700
    51.3 @@ -1,5 +1,5 @@
    51.4  /*
    51.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    51.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    51.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    51.8   *
    51.9   * This code is free software; you can redistribute it and/or modify it
   51.10 @@ -490,4 +490,17 @@
   51.11          startPosition = pos;
   51.12      }
   51.13  
   51.14 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   51.15 +        // Default state initialization happens here
   51.16 +        ois.defaultReadObject();
   51.17 +        // Initialization of  Res Bundle happens here .
   51.18 +        try {
   51.19 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   51.20 +        } catch(IOException ioe) {
   51.21 +            throw new RuntimeException(ioe);
   51.22 +        }
   51.23 +
   51.24 +    }
   51.25 +
   51.26 +    static final long serialVersionUID =5049738185801363801L;
   51.27  }
    52.1 --- a/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java	Thu Sep 23 17:33:40 2010 -0700
    52.2 +++ b/src/share/classes/com/sun/rowset/internal/CachedRowSetWriter.java	Fri Sep 24 16:41:32 2010 -0700
    52.3 @@ -1,5 +1,5 @@
    52.4  /*
    52.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    52.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    52.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    52.8   *
    52.9   * This code is free software; you can redistribute it and/or modify it
   52.10 @@ -31,7 +31,13 @@
   52.11  import java.io.*;
   52.12  
   52.13  import com.sun.rowset.*;
   52.14 +import java.text.MessageFormat;
   52.15  import javax.sql.rowset.*;
   52.16 +import javax.sql.rowset.serial.SQLInputImpl;
   52.17 +import javax.sql.rowset.serial.SerialArray;
   52.18 +import javax.sql.rowset.serial.SerialBlob;
   52.19 +import javax.sql.rowset.serial.SerialClob;
   52.20 +import javax.sql.rowset.serial.SerialStruct;
   52.21  import javax.sql.rowset.spi.*;
   52.22  
   52.23  
   52.24 @@ -53,6 +59,7 @@
   52.25   * Standard JDBC RowSet implementations provide an object instance of this
   52.26   * writer by invoking the <code>SyncProvider.getRowSetWriter()</code> method.
   52.27   *
   52.28 + * @version 0.2
   52.29   * @author Jonathan Bruce
   52.30   * @see javax.sql.rowset.spi.SyncProvider
   52.31   * @see javax.sql.rowset.spi.SyncFactory
   52.32 @@ -508,10 +515,11 @@
   52.33  
   52.34              ResultSet rs = null;
   52.35              rs = pstmt.executeQuery();
   52.36 -            if (rs.next() == true) {
   52.37 +            ResultSetMetaData rsmd = rs.getMetaData();
   52.38  
   52.39 +            if (rs.next()) {
   52.40                  if (rs.next()) {
   52.41 -                  /**  More than one row conflict.
   52.42 +                   /** More than one row conflict.
   52.43                      *  If rs has only one row we are able to
   52.44                      *  uniquely identify the row where update
   52.45                      *  have to happen else if more than one
   52.46 @@ -528,7 +536,7 @@
   52.47                  // we require the record in rs to be used.
   52.48                  // rs.close();
   52.49                  // pstmt.close();
   52.50 -                        rs.first();
   52.51 +                rs.first();
   52.52  
   52.53                  // how many fields need to be updated
   52.54                  int colsNotChanged = 0;
   52.55 @@ -552,6 +560,49 @@
   52.56                  orig = origVals.getObject(i);
   52.57                  curr = crs.getObject(i);
   52.58                  rsval = rs.getObject(i);
   52.59 +                /*
   52.60 +                 * the following block creates equivalent objects
   52.61 +                 * that would have been created if this rs is populated
   52.62 +                 * into a CachedRowSet so that comparison of the column values
   52.63 +                 * from the ResultSet and CachedRowSet are possible
   52.64 +                 */
   52.65 +                Map map = (crs.getTypeMap() == null)?con.getTypeMap():crs.getTypeMap();
   52.66 +                if (rsval instanceof Struct) {
   52.67 +
   52.68 +                    Struct s = (Struct)rsval;
   52.69 +
   52.70 +                    // look up the class in the map
   52.71 +                    Class c = null;
   52.72 +                    c = (Class)map.get(s.getSQLTypeName());
   52.73 +                    if (c != null) {
   52.74 +                        // create new instance of the class
   52.75 +                        SQLData obj = null;
   52.76 +                        try {
   52.77 +                            obj = (SQLData)c.newInstance();
   52.78 +                        } catch (java.lang.InstantiationException ex) {
   52.79 +                            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
   52.80 +                            ex.getMessage()));
   52.81 +                        } catch (java.lang.IllegalAccessException ex) {
   52.82 +                            throw new SQLException(MessageFormat.format(resBundle.handleGetObject("cachedrowsetimpl.unableins").toString(),
   52.83 +                            ex.getMessage()));
   52.84 +                        }
   52.85 +                        // get the attributes from the struct
   52.86 +                        Object attribs[] = s.getAttributes(map);
   52.87 +                        // create the SQLInput "stream"
   52.88 +                        SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);
   52.89 +                        // read the values...
   52.90 +                        obj.readSQL(sqlInput, s.getSQLTypeName());
   52.91 +                        rsval = obj;
   52.92 +                    }
   52.93 +                } else if (rsval instanceof SQLData) {
   52.94 +                    rsval = new SerialStruct((SQLData)rsval, map);
   52.95 +                } else if (rsval instanceof Blob) {
   52.96 +                    rsval = new SerialBlob((Blob)rsval);
   52.97 +                } else if (rsval instanceof Clob) {
   52.98 +                    rsval = new SerialClob((Clob)rsval);
   52.99 +                } else if (rsval instanceof java.sql.Array) {
  52.100 +                    rsval = new SerialArray((java.sql.Array)rsval, map);
  52.101 +                }
  52.102  
  52.103                  // reset boolNull if it had been set
  52.104                  boolNull = true;
  52.105 @@ -669,6 +720,9 @@
  52.106                                   }
  52.107                  } //end for
  52.108  
  52.109 +                rs.close();
  52.110 +                pstmt.close();
  52.111 +
  52.112                 this.crsResolve.insertRow();
  52.113                     this.crsResolve.moveToCurrentRow();
  52.114  
  52.115 @@ -1179,11 +1233,22 @@
  52.116      private void buildKeyDesc(CachedRowSet crs) throws SQLException {
  52.117  
  52.118          keyCols = crs.getKeyColumns();
  52.119 +        ResultSetMetaData resultsetmd = crs.getMetaData();
  52.120          if (keyCols == null || keyCols.length == 0) {
  52.121 -            keyCols = new int[callerColumnCount];
  52.122 -            for (int i = 0; i < keyCols.length; ) {
  52.123 -                keyCols[i] = ++i;
  52.124 +            ArrayList<Integer> listKeys = new ArrayList<Integer>();
  52.125 +
  52.126 +            for (int i = 0; i < callerColumnCount; i++ ) {
  52.127 +                if(resultsetmd.getColumnType(i+1) != java.sql.Types.CLOB &&
  52.128 +                        resultsetmd.getColumnType(i+1) != java.sql.Types.STRUCT &&
  52.129 +                        resultsetmd.getColumnType(i+1) != java.sql.Types.SQLXML &&
  52.130 +                        resultsetmd.getColumnType(i+1) != java.sql.Types.BLOB &&
  52.131 +                        resultsetmd.getColumnType(i+1) != java.sql.Types.ARRAY &&
  52.132 +                        resultsetmd.getColumnType(i+1) != java.sql.Types.OTHER )
  52.133 +                    listKeys.add(i+1);
  52.134              }
  52.135 +            keyCols = new int[listKeys.size()];
  52.136 +            for (int i = 0; i < listKeys.size(); i++ )
  52.137 +                keyCols[i] = listKeys.get(i);
  52.138          }
  52.139          params = new Object[keyCols.length];
  52.140      }
  52.141 @@ -1359,4 +1424,17 @@
  52.142          }
  52.143      }
  52.144  
  52.145 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
  52.146 +        // Default state initialization happens here
  52.147 +        ois.defaultReadObject();
  52.148 +        // Initialization of  Res Bundle happens here .
  52.149 +        try {
  52.150 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
  52.151 +        } catch(IOException ioe) {
  52.152 +            throw new RuntimeException(ioe);
  52.153 +        }
  52.154 +
  52.155 +    }
  52.156 +
  52.157 +    static final long serialVersionUID =-8506030970299413976L;
  52.158  }
    53.1 --- a/src/share/classes/com/sun/rowset/internal/InsertRow.java	Thu Sep 23 17:33:40 2010 -0700
    53.2 +++ b/src/share/classes/com/sun/rowset/internal/InsertRow.java	Fri Sep 24 16:41:32 2010 -0700
    53.3 @@ -1,5 +1,5 @@
    53.4  /*
    53.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    53.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    53.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    53.8   *
    53.9   * This code is free software; you can redistribute it and/or modify it
   53.10 @@ -157,4 +157,23 @@
   53.11          origVals[idx - 1] = val;
   53.12          markColInserted(idx - 1);
   53.13      }
   53.14 +
   53.15 +    /**
   53.16 +     * This method re populates the resBundle
   53.17 +     * during the deserialization process
   53.18 +     *
   53.19 +     */
   53.20 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   53.21 +        // Default state initialization happens here
   53.22 +        ois.defaultReadObject();
   53.23 +        // Initialization of transient Res Bundle happens here .
   53.24 +        try {
   53.25 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   53.26 +        } catch(IOException ioe) {
   53.27 +            throw new RuntimeException(ioe);
   53.28 +        }
   53.29 +
   53.30 +    }
   53.31 +
   53.32 +    static final long serialVersionUID = 1066099658102869344L;
   53.33  }
    54.1 --- a/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java	Thu Sep 23 17:33:40 2010 -0700
    54.2 +++ b/src/share/classes/com/sun/rowset/internal/SyncResolverImpl.java	Fri Sep 24 16:41:32 2010 -0700
    54.3 @@ -1,5 +1,5 @@
    54.4  /*
    54.5 - * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
    54.6 + * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
    54.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    54.8   *
    54.9   * This code is free software; you can redistribute it and/or modify it
   54.10 @@ -35,6 +35,7 @@
   54.11  
   54.12  import com.sun.rowset.*;
   54.13  import java.io.IOException;
   54.14 +import java.io.ObjectInputStream;
   54.15  
   54.16  /**
   54.17   * There will be two sets of data which will be maintained by the rowset at the
   54.18 @@ -4837,4 +4838,23 @@
   54.19                              throws SQLException {
   54.20            throw new UnsupportedOperationException("Operation not yet supported");
   54.21         }
   54.22 +
   54.23 +      /**
   54.24 +       * This method re populates the resBundle
   54.25 +       * during the deserialization process
   54.26 +       *
   54.27 +       */
   54.28 +       private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   54.29 +         // Default state initialization happens here
   54.30 +         ois.defaultReadObject();
   54.31 +         // Initialization of transient Res Bundle happens here .
   54.32 +         try {
   54.33 +            resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   54.34 +         } catch(IOException ioe) {
   54.35 +             throw new RuntimeException(ioe);
   54.36 +         }
   54.37 +
   54.38 +       }
   54.39 +
   54.40 +       static final long serialVersionUID = -3345004441725080251L;
   54.41  } //end class
    55.1 --- a/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java	Thu Sep 23 17:33:40 2010 -0700
    55.2 +++ b/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java	Fri Sep 24 16:41:32 2010 -0700
    55.3 @@ -1,5 +1,5 @@
    55.4  /*
    55.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    55.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    55.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    55.8   *
    55.9   * This code is free software; you can redistribute it and/or modify it
   55.10 @@ -216,4 +216,22 @@
   55.11      public void readData(RowSetInternal caller) {
   55.12      }
   55.13  
   55.14 +    /**
   55.15 +     * This method re populates the resBundle
   55.16 +     * during the deserialization process
   55.17 +     *
   55.18 +     */
   55.19 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   55.20 +        // Default state initialization happens here
   55.21 +        ois.defaultReadObject();
   55.22 +        // Initialization of transient Res Bundle happens here .
   55.23 +        try {
   55.24 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   55.25 +        } catch(IOException ioe) {
   55.26 +            throw new RuntimeException(ioe);
   55.27 +        }
   55.28 +
   55.29 +    }
   55.30 +
   55.31 +    static final long serialVersionUID = -9127058392819008014L;
   55.32  }
    56.1 --- a/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java	Thu Sep 23 17:33:40 2010 -0700
    56.2 +++ b/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java	Fri Sep 24 16:41:32 2010 -0700
    56.3 @@ -1,5 +1,5 @@
    56.4  /*
    56.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    56.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    56.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    56.8   *
    56.9   * This code is free software; you can redistribute it and/or modify it
   56.10 @@ -663,4 +663,23 @@
   56.11          return s;
   56.12      }
   56.13  
   56.14 +
   56.15 +    /**
   56.16 +     * This method re populates the resBundle
   56.17 +     * during the deserialization process
   56.18 +     *
   56.19 +     */
   56.20 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   56.21 +        // Default state initialization happens here
   56.22 +        ois.defaultReadObject();
   56.23 +        // Initialization of transient Res Bundle happens here .
   56.24 +        try {
   56.25 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   56.26 +        } catch(IOException ioe) {
   56.27 +            throw new RuntimeException(ioe);
   56.28 +        }
   56.29 +
   56.30 +    }
   56.31 +
   56.32 +    static final long serialVersionUID = 7163134986189677641L;
   56.33  }
    57.1 --- a/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java	Thu Sep 23 17:33:40 2010 -0700
    57.2 +++ b/src/share/classes/com/sun/rowset/providers/RIOptimisticProvider.java	Fri Sep 24 16:41:32 2010 -0700
    57.3 @@ -1,5 +1,5 @@
    57.4  /*
    57.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    57.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    57.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    57.8   *
    57.9   * This code is free software; you can redistribute it and/or modify it
   57.10 @@ -245,4 +245,18 @@
   57.11      public String getVendor() {
   57.12          return this.vendorName;
   57.13      }
   57.14 +
   57.15 +    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   57.16 +        // Default state initialization happens here
   57.17 +        ois.defaultReadObject();
   57.18 +        // Initialization of transient Res Bundle happens here .
   57.19 +        try {
   57.20 +           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
   57.21 +        } catch(IOException ioe) {
   57.22 +            throw new RuntimeException(ioe);
   57.23 +        }
   57.24 +
   57.25 +    }
   57.26 +    static final long serialVersionUID =-3143367176751761936L;
   57.27 +
   57.28  }
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/src/share/classes/com/sun/security/ntlm/Client.java	Fri Sep 24 16:41:32 2010 -0700
    58.3 @@ -0,0 +1,212 @@
    58.4 +/*
    58.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    58.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    58.7 + *
    58.8 + * This code is free software; you can redistribute it and/or modify it
    58.9 + * under the terms of the GNU General Public License version 2 only, as
   58.10 + * published by the Free Software Foundation.  Oracle designates this
   58.11 + * particular file as subject to the "Classpath" exception as provided
   58.12 + * by Oracle in the LICENSE file that accompanied this code.
   58.13 + *
   58.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   58.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   58.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   58.17 + * version 2 for more details (a copy is included in the LICENSE file that
   58.18 + * accompanied this code).
   58.19 + *
   58.20 + * You should have received a copy of the GNU General Public License version
   58.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   58.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   58.23 + *
   58.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   58.25 + * or visit www.oracle.com if you need additional information or have any
   58.26 + * questions.
   58.27 + */
   58.28 +
   58.29 +package com.sun.security.ntlm;
   58.30 +
   58.31 +import java.math.BigInteger;
   58.32 +import java.util.Arrays;
   58.33 +import java.util.Date;
   58.34 +import java.util.Locale;
   58.35 +
   58.36 +/**
   58.37 + * The NTLM client. Not multi-thread enabled.<p>
   58.38 + * Example:
   58.39 + * <pre>
   58.40 + * Client client = new Client(null, "host", "dummy",
   58.41 + *       "REALM", "t0pSeCr3t".toCharArray());
   58.42 + * byte[] type1 = client.type1();
   58.43 + * // Send type1 to server and receive response as type2
   58.44 + * byte[] type3 = client.type3(type2, nonce);
   58.45 + * // Send type3 to server
   58.46 + * </pre>
   58.47 + */
   58.48 +public final class Client extends NTLM {
   58.49 +    final private String hostname;
   58.50 +    final private String username;
   58.51 +
   58.52 +    private String domain;    // might be updated by Type 2 msg
   58.53 +    private byte[] pw1, pw2;
   58.54 +
   58.55 +    /**
   58.56 +     * Creates an NTLM Client instance.
   58.57 +     * @param version the NTLM version to use, which can be:
   58.58 +     * <ul>
   58.59 +     * <li>LM/NTLM: Original NTLM v1
   58.60 +     * <li>LM: Original NTLM v1, LM only
   58.61 +     * <li>NTLM: Original NTLM v1, NTLM only
   58.62 +     * <li>NTLM2: NTLM v1 with Client Challenge
   58.63 +     * <li>LMv2/NTLMv2: NTLM v2
   58.64 +     * <li>LMv2: NTLM v2, LM only
   58.65 +     * <li>NTLMv2: NTLM v2, NTLM only
   58.66 +     * </ul>
   58.67 +     * If null, "LMv2/NTLMv2" will be used.
   58.68 +     * @param hostname hostname of the client, can be null
   58.69 +     * @param username username to be authenticated, must not be null
   58.70 +     * @param domain domain of {@code username}, can be null
   58.71 +     * @param password password for {@code username}, must not be not null.
   58.72 +     * This method does not make any modification to this parameter, it neither
   58.73 +     * needs to access the content of this parameter after this method call,
   58.74 +     * so you are free to modify or nullify this parameter after this call.
   58.75 +     * @throws NullPointerException if {@code username} or {@code password} is null.
   58.76 +     * @throws NTLMException if {@code version} is illegal
   58.77 +     */
   58.78 +    public Client(String version, String hostname, String username,
   58.79 +            String domain, char[] password) throws NTLMException {
   58.80 +        super(version);
   58.81 +        if ((username == null || password == null)) {
   58.82 +            throw new NullPointerException("username/password cannot be null");
   58.83 +        }
   58.84 +        this.hostname = hostname;
   58.85 +        this.username = username;
   58.86 +        this.domain = domain;
   58.87 +        this.pw1 = getP1(password);
   58.88 +        this.pw2 = getP2(password);
   58.89 +        debug("NTLM Client: (h,u,t,version(v)) = (%s,%s,%s,%s(%s))\n",
   58.90 +                    hostname, username, domain, version, v.toString());
   58.91 +    }
   58.92 +
   58.93 +    /**
   58.94 +     * Generates the Type 1 message
   58.95 +     * @return the message generated
   58.96 +     */
   58.97 +    public byte[] type1() {
   58.98 +        Writer p = new Writer(1, 32);
   58.99 +        int flags = 0x8203;
  58.100 +        if (hostname != null) {
  58.101 +            flags |= 0x2000;
  58.102 +        }
  58.103 +        if (domain != null) {
  58.104 +            flags |= 0x1000;
  58.105 +        }
  58.106 +        if (v != Version.NTLM) {
  58.107 +            flags |= 0x80000;
  58.108 +        }
  58.109 +        p.writeInt(12, flags);
  58.110 +        p.writeSecurityBuffer(24, hostname, false);
  58.111 +        p.writeSecurityBuffer(16, domain, false);
  58.112 +        debug("NTLM Client: Type 1 created\n");
  58.113 +        debug(p.getBytes());
  58.114 +        return p.getBytes();
  58.115 +    }
  58.116 +
  58.117 +    /**
  58.118 +     * Generates the Type 3 message
  58.119 +     * @param type2 the responding Type 2 message from server, must not be null
  58.120 +     * @param nonce random 8-byte array to be used in message generation,
  58.121 +     * must not be null except for original NTLM v1
  58.122 +     * @return the message generated
  58.123 +     * @throws NullPointerException if {@code type2} or {@code nonce} is null
  58.124 +     * for NTLM v1.
  58.125 +     * @throws NTLMException if the incoming message is invalid
  58.126 +     */
  58.127 +    public byte[] type3(byte[] type2, byte[] nonce) throws NTLMException {
  58.128 +        if (type2 == null || (v != Version.NTLM && nonce == null)) {
  58.129 +            throw new NullPointerException("type2 and nonce cannot be null");
  58.130 +        }
  58.131 +        debug("NTLM Client: Type 2 received\n");
  58.132 +        debug(type2);
  58.133 +        Reader r = new Reader(type2);
  58.134 +        byte[] challenge = r.readBytes(24, 8);
  58.135 +        int inputFlags = r.readInt(20);
  58.136 +        boolean unicode = (inputFlags & 1) == 1;
  58.137 +        String domainFromServer = r.readSecurityBuffer(12, unicode);
  58.138 +        if (domainFromServer != null) {
  58.139 +            domain = domainFromServer;
  58.140 +        }
  58.141 +        if (domain == null) {
  58.142 +            throw new NTLMException(NTLMException.NO_DOMAIN_INFO,
  58.143 +                    "No domain info");
  58.144 +        }
  58.145 +
  58.146 +        int flags = 0x88200 | (inputFlags & 3);
  58.147 +        Writer p = new Writer(3, 64);
  58.148 +        byte[] lm = null, ntlm = null;
  58.149 +
  58.150 +        p.writeSecurityBuffer(28, domain, unicode);
  58.151 +        p.writeSecurityBuffer(36, username, unicode);
  58.152 +        p.writeSecurityBuffer(44, hostname, unicode);
  58.153 +
  58.154 +        if (v == Version.NTLM) {
  58.155 +            byte[] lmhash = calcLMHash(pw1);
  58.156 +            byte[] nthash = calcNTHash(pw2);
  58.157 +            if (writeLM) lm = calcResponse (lmhash, challenge);
  58.158 +            if (writeNTLM) ntlm = calcResponse (nthash, challenge);
  58.159 +        } else if (v == Version.NTLM2) {
  58.160 +            byte[] nthash = calcNTHash(pw2);
  58.161 +            lm = ntlm2LM(nonce);
  58.162 +            ntlm = ntlm2NTLM(nthash, nonce, challenge);
  58.163 +        } else {
  58.164 +            byte[] nthash = calcNTHash(pw2);
  58.165 +            if (writeLM) lm = calcV2(nthash,
  58.166 +                    username.toUpperCase(Locale.US)+domain, nonce, challenge);
  58.167 +            if (writeNTLM) {
  58.168 +                byte[] alist = type2.length > 48 ?
  58.169 +                    r.readSecurityBuffer(40) : new byte[0];
  58.170 +                byte[] blob = new byte[32+alist.length];
  58.171 +                System.arraycopy(new byte[]{1,1,0,0,0,0,0,0}, 0, blob, 0, 8);
  58.172 +                // TS
  58.173 +                byte[] time = BigInteger.valueOf(new Date().getTime())
  58.174 +                        .add(new BigInteger("11644473600000"))
  58.175 +                        .multiply(BigInteger.valueOf(10000))
  58.176 +                        .toByteArray();
  58.177 +                for (int i=0; i<time.length; i++) {
  58.178 +                    blob[8+time.length-i-1] = time[i];
  58.179 +                }
  58.180 +                System.arraycopy(nonce, 0, blob, 16, 8);
  58.181 +                System.arraycopy(new byte[]{0,0,0,0}, 0, blob, 24, 4);
  58.182 +                System.arraycopy(alist, 0, blob, 28, alist.length);
  58.183 +                System.arraycopy(new byte[]{0,0,0,0}, 0,
  58.184 +                        blob, 28+alist.length, 4);
  58.185 +                ntlm = calcV2(nthash, username.toUpperCase(Locale.US)+domain,
  58.186 +                        blob, challenge);
  58.187 +            }
  58.188 +        }
  58.189 +        p.writeSecurityBuffer(12, lm);
  58.190 +        p.writeSecurityBuffer(20, ntlm);
  58.191 +        p.writeSecurityBuffer(52, new byte[0]);
  58.192 +
  58.193 +        p.writeInt(60, flags);
  58.194 +        debug("NTLM Client: Type 3 created\n");
  58.195 +        debug(p.getBytes());
  58.196 +        return p.getBytes();
  58.197 +    }
  58.198 +
  58.199 +    /**
  58.200 +     * Returns the domain value provided by server after the authentication
  58.201 +     * is complete, or the domain value provided by the client before it.
  58.202 +     * @return the domain
  58.203 +     */
  58.204 +    public String getDomain() {
  58.205 +        return domain;
  58.206 +    }
  58.207 +
  58.208 +    /**
  58.209 +     * Disposes any password-derived information.
  58.210 +     */
  58.211 +    public void dispose() {
  58.212 +        Arrays.fill(pw1, (byte)0);
  58.213 +        Arrays.fill(pw2, (byte)0);
  58.214 +    }
  58.215 +}
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/src/share/classes/com/sun/security/ntlm/NTLM.java	Fri Sep 24 16:41:32 2010 -0700
    59.3 @@ -0,0 +1,426 @@
    59.4 +/*
    59.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    59.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    59.7 + *
    59.8 + * This code is free software; you can redistribute it and/or modify it
    59.9 + * under the terms of the GNU General Public License version 2 only, as
   59.10 + * published by the Free Software Foundation.  Oracle designates this
   59.11 + * particular file as subject to the "Classpath" exception as provided
   59.12 + * by Oracle in the LICENSE file that accompanied this code.
   59.13 + *
   59.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   59.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   59.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   59.17 + * version 2 for more details (a copy is included in the LICENSE file that
   59.18 + * accompanied this code).
   59.19 + *
   59.20 + * You should have received a copy of the GNU General Public License version
   59.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   59.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   59.23 + *
   59.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   59.25 + * or visit www.oracle.com if you need additional information or have any
   59.26 + * questions.
   59.27 + */
   59.28 +
   59.29 +package com.sun.security.ntlm;
   59.30 +
   59.31 +import static com.sun.security.ntlm.Version.*;
   59.32 +import java.io.IOException;
   59.33 +import java.io.UnsupportedEncodingException;
   59.34 +import java.security.InvalidKeyException;
   59.35 +import java.security.MessageDigest;
   59.36 +import java.security.NoSuchAlgorithmException;
   59.37 +import java.security.spec.InvalidKeySpecException;
   59.38 +import java.util.Arrays;
   59.39 +import javax.crypto.BadPaddingException;
   59.40 +import javax.crypto.Cipher;
   59.41 +import javax.crypto.IllegalBlockSizeException;
   59.42 +import javax.crypto.Mac;
   59.43 +import javax.crypto.NoSuchPaddingException;
   59.44 +import javax.crypto.SecretKey;
   59.45 +import javax.crypto.SecretKeyFactory;
   59.46 +import javax.crypto.spec.DESKeySpec;
   59.47 +import javax.crypto.spec.SecretKeySpec;
   59.48 +
   59.49 +/**
   59.50 + * NTLM authentication implemented according to MS-NLMP, version 12.1
   59.51 + * @since 1.7
   59.52 + */
   59.53 +class NTLM {
   59.54 +
   59.55 +    private final SecretKeyFactory fac;
   59.56 +    private final Cipher cipher;
   59.57 +    private final MessageDigest md4;
   59.58 +    private final Mac hmac;
   59.59 +    private final MessageDigest md5;
   59.60 +    private static final boolean DEBUG =
   59.61 +            System.getProperty("ntlm.debug") != null;
   59.62 +
   59.63 +    final Version v;
   59.64 +
   59.65 +    final boolean writeLM;
   59.66 +    final boolean writeNTLM;
   59.67 +
   59.68 +    protected NTLM(String version) throws NTLMException {
   59.69 +        if (version == null) version = "LMv2/NTLMv2";
   59.70 +        switch (version) {
   59.71 +            case "LM": v = NTLM; writeLM = true; writeNTLM = false; break;
   59.72 +            case "NTLM": v = NTLM; writeLM = false; writeNTLM = true; break;
   59.73 +            case "LM/NTLM": v = NTLM; writeLM = writeNTLM = true; break;
   59.74 +            case "NTLM2": v = NTLM2; writeLM = writeNTLM = true; break;
   59.75 +            case "LMv2": v = NTLMv2; writeLM = true; writeNTLM = false; break;
   59.76 +            case "NTLMv2": v = NTLMv2; writeLM = false; writeNTLM = true; break;
   59.77 +            case "LMv2/NTLMv2": v = NTLMv2; writeLM = writeNTLM = true; break;
   59.78 +            default: throw new NTLMException(NTLMException.BAD_VERSION,
   59.79 +                    "Unknown version " + version);
   59.80 +        }
   59.81 +        try {
   59.82 +            fac = SecretKeyFactory.getInstance ("DES");
   59.83 +            cipher = Cipher.getInstance ("DES/ECB/NoPadding");
   59.84 +            md4 = sun.security.provider.MD4.getInstance();
   59.85 +            hmac = Mac.getInstance("HmacMD5");
   59.86 +            md5 = MessageDigest.getInstance("MD5");
   59.87 +        } catch (NoSuchPaddingException e) {
   59.88 +            throw new AssertionError();
   59.89 +        } catch (NoSuchAlgorithmException e) {
   59.90 +            throw new AssertionError();
   59.91 +        }
   59.92 +    }
   59.93 +
   59.94 +    /**
   59.95 +     * Prints out a formatted string, called in various places inside then NTLM
   59.96 +     * implementation for debugging/logging purposes. When the system property
   59.97 +     * "ntlm.debug" is set, <code>System.out.printf(format, args)</code> is
   59.98 +     * called. This method is designed to be overridden by child classes to
   59.99 +     * match their own debugging/logging mechanisms.
  59.100 +     * @param format a format string
  59.101 +     * @param args the arguments referenced by <code>format</code>
  59.102 +     * @see java.io.PrintStream#printf(java.lang.String, java.lang.Object[])
  59.103 +     */
  59.104 +    public void debug(String format, Object... args) {
  59.105 +        if (DEBUG) {
  59.106 +            System.out.printf(format, args);
  59.107 +        }
  59.108 +    }
  59.109 +
  59.110 +    /**
  59.111 +     * Prints out the content of a byte array, called in various places inside
  59.112 +     * the NTLM implementation for debugging/logging purposes. When the system
  59.113 +     * property "ntlm.debug" is set, the hexdump of the array is printed into
  59.114 +     * System.out. This method is designed to be overridden by child classes to
  59.115 +     * match their own debugging/logging mechanisms.
  59.116 +     * @param bytes the byte array to print out
  59.117 +     */
  59.118 +    public void debug(byte[] bytes) {
  59.119 +        if (DEBUG) {
  59.120 +            try {
  59.121 +                new sun.misc.HexDumpEncoder().encodeBuffer(bytes, System.out);
  59.122 +            } catch (IOException ioe) {
  59.123 +                // Impossible
  59.124 +            }
  59.125 +        }
  59.126 +    }
  59.127 +
  59.128 +    /**
  59.129 +     * Reading an NTLM packet
  59.130 +     */
  59.131 +    static class Reader {
  59.132 +
  59.133 +        private final byte[] internal;
  59.134 +
  59.135 +        Reader(byte[] data) {
  59.136 +            internal = data;
  59.137 +        }
  59.138 +
  59.139 +        int readInt(int offset) throws NTLMException {
  59.140 +            try {
  59.141 +                return internal[offset] & 0xff +
  59.142 +                        (internal[offset+1] & 0xff << 8) +
  59.143 +                        (internal[offset+2] & 0xff << 16) +
  59.144 +                        (internal[offset+3] & 0xff << 24);
  59.145 +            } catch (ArrayIndexOutOfBoundsException ex) {
  59.146 +                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
  59.147 +                        "Input message incorrect size");
  59.148 +            }
  59.149 +        }
  59.150 +
  59.151 +        int readShort(int offset) throws NTLMException {
  59.152 +            try {
  59.153 +                return internal[offset] & 0xff +
  59.154 +                        (internal[offset+1] & 0xff << 8);
  59.155 +            } catch (ArrayIndexOutOfBoundsException ex) {
  59.156 +                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
  59.157 +                        "Input message incorrect size");
  59.158 +            }
  59.159 +        }
  59.160 +
  59.161 +        byte[] readBytes(int offset, int len) throws NTLMException {
  59.162 +            try {
  59.163 +                return Arrays.copyOfRange(internal, offset, offset + len);
  59.164 +            } catch (ArrayIndexOutOfBoundsException ex) {
  59.165 +                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
  59.166 +                        "Input message incorrect size");
  59.167 +            }
  59.168 +        }
  59.169 +
  59.170 +        byte[] readSecurityBuffer(int offset) throws NTLMException {
  59.171 +            int pos = readInt(offset+4);
  59.172 +            if (pos == 0) return null;
  59.173 +            try {
  59.174 +                return Arrays.copyOfRange(
  59.175 +                        internal, pos, pos + readShort(offset));
  59.176 +            } catch (ArrayIndexOutOfBoundsException ex) {
  59.177 +                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
  59.178 +                        "Input message incorrect size");
  59.179 +            }
  59.180 +        }
  59.181 +
  59.182 +        String readSecurityBuffer(int offset, boolean unicode)
  59.183 +                throws NTLMException {
  59.184 +            byte[] raw = readSecurityBuffer(offset);
  59.185 +            try {
  59.186 +                return raw == null ? null : new String(
  59.187 +                        raw, unicode ? "UnicodeLittleUnmarked" : "ISO8859_1");
  59.188 +            } catch (UnsupportedEncodingException ex) {
  59.189 +                throw new NTLMException(NTLMException.PACKET_READ_ERROR,
  59.190 +                        "Invalid input encoding");
  59.191 +            }
  59.192 +        }
  59.193 +    }
  59.194 +
  59.195 +    /**
  59.196 +     * Writing an NTLM packet
  59.197 +     */
  59.198 +    static class Writer {
  59.199 +
  59.200 +        private byte[] internal;    // buffer
  59.201 +        private int current;        // current written content interface buffer
  59.202 +
  59.203 +        /**
  59.204 +         * Starts writing a NTLM packet
  59.205 +         * @param type NEGOTIATE || CHALLENGE || AUTHENTICATE
  59.206 +         * @param len the base length, without security buffers
  59.207 +         */
  59.208 +        Writer(int type, int len) {
  59.209 +            assert len < 256;
  59.210 +            internal = new byte[256];
  59.211 +            current = len;
  59.212 +            System.arraycopy (
  59.213 +                    new byte[] {'N','T','L','M','S','S','P',0,(byte)type},
  59.214 +                    0, internal, 0, 9);
  59.215 +        }
  59.216 +
  59.217 +        void writeShort(int offset, int number) {
  59.218 +            internal[offset] = (byte)(number);
  59.219 +            internal[offset+1] = (byte)(number >> 8);
  59.220 +        }
  59.221 +
  59.222 +        void writeInt(int offset, int number) {
  59.223 +            internal[offset] = (byte)(number);
  59.224 +            internal[offset+1] = (byte)(number >> 8);
  59.225 +            internal[offset+2] = (byte)(number >> 16);
  59.226 +            internal[offset+3] = (byte)(number >> 24);
  59.227 +        }
  59.228 +
  59.229 +        void writeBytes(int offset, byte[] data) {
  59.230 +            System.arraycopy(data, 0, internal, offset, data.length);
  59.231 +        }
  59.232 +
  59.233 +        void writeSecurityBuffer(int offset, byte[] data) {
  59.234 +            if (data == null) {
  59.235 +                writeShort(offset+4, current);
  59.236 +            } else {
  59.237 +                int len = data.length;
  59.238 +                if (current + len > internal.length) {
  59.239 +                    internal = Arrays.copyOf(internal, current + len + 256);
  59.240 +                }
  59.241 +                writeShort(offset, len);
  59.242 +                writeShort(offset+2, len);
  59.243 +                writeShort(offset+4, current);
  59.244 +                System.arraycopy(data, 0, internal, current, len);
  59.245 +                current += len;
  59.246 +            }
  59.247 +        }
  59.248 +
  59.249 +        void writeSecurityBuffer(int offset, String str, boolean unicode) {
  59.250 +            try {
  59.251 +                writeSecurityBuffer(offset, str == null ? null : str.getBytes(
  59.252 +                        unicode ? "UnicodeLittleUnmarked" : "ISO8859_1"));
  59.253 +            } catch (UnsupportedEncodingException ex) {
  59.254 +                assert false;
  59.255 +            }
  59.256 +        }
  59.257 +
  59.258 +        byte[] getBytes() {
  59.259 +            return Arrays.copyOf(internal, current);
  59.260 +        }
  59.261 +    }
  59.262 +
  59.263 +    // LM/NTLM
  59.264 +
  59.265 +    /* Convert a 7 byte array to an 8 byte array (for a des key with parity)
  59.266 +     * input starts at offset off
  59.267 +     */
  59.268 +    byte[] makeDesKey (byte[] input, int off) {
  59.269 +        int[] in = new int [input.length];
  59.270 +        for (int i=0; i<in.length; i++ ) {
  59.271 +            in[i] = input[i]<0 ? input[i]+256: input[i];
  59.272 +        }
  59.273 +        byte[] out = new byte[8];
  59.274 +        out[0] = (byte)in[off+0];
  59.275 +        out[1] = (byte)(((in[off+0] << 7) & 0xFF) | (in[off+1] >> 1));
  59.276 +        out[2] = (byte)(((in[off+1] << 6) & 0xFF) | (in[off+2] >> 2));
  59.277 +        out[3] = (byte)(((in[off+2] << 5) & 0xFF) | (in[off+3] >> 3));
  59.278 +        out[4] = (byte)(((in[off+3] << 4) & 0xFF) | (in[off+4] >> 4));
  59.279 +        out[5] = (byte)(((in[off+4] << 3) & 0xFF) | (in[off+5] >> 5));
  59.280 +        out[6] = (byte)(((in[off+5] << 2) & 0xFF) | (in[off+6] >> 6));
  59.281 +        out[7] = (byte)((in[off+6] << 1) & 0xFF);
  59.282 +        return out;
  59.283 +    }
  59.284 +
  59.285 +    byte[] calcLMHash (byte[] pwb) {
  59.286 +        byte[] magic = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
  59.287 +        byte[] pwb1 = new byte [14];
  59.288 +        int len = pwb.length;
  59.289 +        if (len > 14)
  59.290 +            len = 14;
  59.291 +        System.arraycopy (pwb, 0, pwb1, 0, len); /* Zero padded */
  59.292 +
  59.293 +        try {
  59.294 +            DESKeySpec dks1 = new DESKeySpec (makeDesKey (pwb1, 0));
  59.295 +            DESKeySpec dks2 = new DESKeySpec (makeDesKey (pwb1, 7));
  59.296 +
  59.297 +            SecretKey key1 = fac.generateSecret (dks1);
  59.298 +            SecretKey key2 = fac.generateSecret (dks2);
  59.299 +            cipher.init (Cipher.ENCRYPT_MODE, key1);
  59.300 +            byte[] out1 = cipher.doFinal (magic, 0, 8);
  59.301 +            cipher.init (Cipher.ENCRYPT_MODE, key2);
  59.302 +            byte[] out2 = cipher.doFinal (magic, 0, 8);
  59.303 +            byte[] result = new byte [21];
  59.304 +            System.arraycopy (out1, 0, result, 0, 8);
  59.305 +            System.arraycopy (out2, 0, result, 8, 8);
  59.306 +            return result;
  59.307 +        } catch (InvalidKeyException ive) {
  59.308 +            // Will not happen, all key material are 8 bytes
  59.309 +            assert false;
  59.310 +        } catch (InvalidKeySpecException ikse) {
  59.311 +            // Will not happen, we only feed DESKeySpec to DES factory
  59.312 +            assert false;
  59.313 +        } catch (IllegalBlockSizeException ibse) {
  59.314 +            // Will not happen, we encrypt 8 bytes
  59.315 +            assert false;
  59.316 +        } catch (BadPaddingException bpe) {
  59.317 +            // Will not happen, this is encryption
  59.318 +            assert false;
  59.319 +        }
  59.320 +        return null;    // will not happen, we returned already
  59.321 +    }
  59.322 +
  59.323 +    byte[] calcNTHash (byte[] pw) {
  59.324 +        byte[] out = md4.digest (pw);
  59.325 +        byte[] result = new byte [21];
  59.326 +        System.arraycopy (out, 0, result, 0, 16);
  59.327 +        return result;
  59.328 +    }
  59.329 +
  59.330 +    /* key is a 21 byte array. Split it into 3 7 byte chunks,
  59.331 +     * Convert each to 8 byte DES keys, encrypt the text arg with
  59.332 +     * each key and return the three results in a sequential []
  59.333 +     */
  59.334 +    byte[] calcResponse (byte[] key, byte[] text) {
  59.335 +        try {
  59.336 +            assert key.length == 21;
  59.337 +            DESKeySpec dks1 = new DESKeySpec(makeDesKey(key, 0));
  59.338 +            DESKeySpec dks2 = new DESKeySpec(makeDesKey(key, 7));
  59.339 +            DESKeySpec dks3 = new DESKeySpec(makeDesKey(key, 14));
  59.340 +            SecretKey key1 = fac.generateSecret(dks1);
  59.341 +            SecretKey key2 = fac.generateSecret(dks2);
  59.342 +            SecretKey key3 = fac.generateSecret(dks3);
  59.343 +            cipher.init(Cipher.ENCRYPT_MODE, key1);
  59.344 +            byte[] out1 = cipher.doFinal(text, 0, 8);
  59.345 +            cipher.init(Cipher.ENCRYPT_MODE, key2);
  59.346 +            byte[] out2 = cipher.doFinal(text, 0, 8);
  59.347 +            cipher.init(Cipher.ENCRYPT_MODE, key3);
  59.348 +            byte[] out3 = cipher.doFinal(text, 0, 8);
  59.349 +            byte[] result = new byte[24];
  59.350 +            System.arraycopy(out1, 0, result, 0, 8);
  59.351 +            System.arraycopy(out2, 0, result, 8, 8);
  59.352 +            System.arraycopy(out3, 0, result, 16, 8);
  59.353 +            return result;
  59.354 +        } catch (IllegalBlockSizeException ex) {    // None will happen
  59.355 +            assert false;
  59.356 +        } catch (BadPaddingException ex) {
  59.357 +            assert false;
  59.358 +        } catch (InvalidKeySpecException ex) {
  59.359 +            assert false;
  59.360 +        } catch (InvalidKeyException ex) {
  59.361 +            assert false;
  59.362 +        }
  59.363 +        return null;
  59.364 +    }
  59.365 +
  59.366 +    // LMv2/NTLMv2
  59.367 +
  59.368 +    byte[] hmacMD5(byte[] key, byte[] text) {
  59.369 +        try {
  59.370 +            SecretKeySpec skey =
  59.371 +                    new SecretKeySpec(Arrays.copyOf(key, 16), "HmacMD5");
  59.372 +            hmac.init(skey);
  59.373 +            return hmac.doFinal(text);
  59.374 +        } catch (InvalidKeyException ex) {
  59.375 +            assert false;
  59.376 +        } catch (RuntimeException e) {
  59.377 +            assert false;
  59.378 +        }
  59.379 +        return null;
  59.380 +    }
  59.381 +
  59.382 +    byte[] calcV2(byte[] nthash, String text, byte[] blob, byte[] challenge) {
  59.383 +        try {
  59.384 +            byte[] ntlmv2hash = hmacMD5(nthash,
  59.385 +                    text.getBytes("UnicodeLittleUnmarked"));
  59.386 +            byte[] cn = new byte[blob.length+8];
  59.387 +            System.arraycopy(challenge, 0, cn, 0, 8);
  59.388 +            System.arraycopy(blob, 0, cn, 8, blob.length);
  59.389 +            byte[] result = new byte[16+blob.length];
  59.390 +            System.arraycopy(hmacMD5(ntlmv2hash, cn), 0, result, 0, 16);
  59.391 +            System.arraycopy(blob, 0, result, 16, blob.length);
  59.392 +            return result;
  59.393 +        } catch (UnsupportedEncodingException ex) {
  59.394 +            assert false;
  59.395 +        }
  59.396 +        return null;
  59.397 +    }
  59.398 +
  59.399 +    // NTLM2 LM/NTLM
  59.400 +
  59.401 +    static byte[] ntlm2LM(byte[] nonce) {
  59.402 +        return Arrays.copyOf(nonce, 24);
  59.403 +    }
  59.404 +
  59.405 +    byte[] ntlm2NTLM(byte[] ntlmHash, byte[] nonce, byte[] challenge) {
  59.406 +        byte[] b = Arrays.copyOf(challenge, 16);
  59.407 +        System.arraycopy(nonce, 0, b, 8, 8);
  59.408 +        byte[] sesshash = Arrays.copyOf(md5.digest(b), 8);
  59.409 +        return calcResponse(ntlmHash, sesshash);
  59.410 +    }
  59.411 +
  59.412 +    // Password in ASCII and UNICODE
  59.413 +
  59.414 +    static byte[] getP1(char[] password) {
  59.415 +        try {
  59.416 +            return new String(password).toUpperCase().getBytes("ISO8859_1");
  59.417 +        } catch (UnsupportedEncodingException ex) {
  59.418 +            return null;
  59.419 +        }
  59.420 +    }
  59.421 +
  59.422 +    static byte[] getP2(char[] password) {
  59.423 +        try {
  59.424 +            return new String(password).getBytes("UnicodeLittleUnmarked");
  59.425 +        } catch (UnsupportedEncodingException ex) {
  59.426 +            return null;
  59.427 +        }
  59.428 +    }
  59.429 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/src/share/classes/com/sun/security/ntlm/NTLMException.java	Fri Sep 24 16:41:32 2010 -0700
    60.3 @@ -0,0 +1,88 @@
    60.4 +/*
    60.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    60.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    60.7 + *
    60.8 + * This code is free software; you can redistribute it and/or modify it
    60.9 + * under the terms of the GNU General Public License version 2 only, as
   60.10 + * published by the Free Software Foundation.  Oracle designates this
   60.11 + * particular file as subject to the "Classpath" exception as provided
   60.12 + * by Oracle in the LICENSE file that accompanied this code.
   60.13 + *
   60.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   60.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   60.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   60.17 + * version 2 for more details (a copy is included in the LICENSE file that
   60.18 + * accompanied this code).
   60.19 + *
   60.20 + * You should have received a copy of the GNU General Public License version
   60.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   60.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   60.23 + *
   60.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   60.25 + * or visit www.oracle.com if you need additional information or have any
   60.26 + * questions.
   60.27 + */
   60.28 +
   60.29 +package com.sun.security.ntlm;
   60.30 +
   60.31 +import java.security.GeneralSecurityException;
   60.32 +
   60.33 +/**
   60.34 + * An NTLM-related Exception
   60.35 + */
   60.36 +public final class NTLMException extends GeneralSecurityException {
   60.37 +
   60.38 +    /**
   60.39 +     * If the incoming packet is invalid.
   60.40 +     */
   60.41 +    public final static int PACKET_READ_ERROR = 1;
   60.42 +
   60.43 +    /**
   60.44 +     * If the client cannot get a domain value from the server and the
   60.45 +     * caller has not provided one.
   60.46 +     */
   60.47 +    public final static int NO_DOMAIN_INFO = 2;
   60.48 +
   60.49 +    /**
   60.50 +     * If the domain provided by the client does not match the one received
   60.51 +     * from server.
   60.52 +     */
   60.53 +    //public final static int DOMAIN_UNMATCH = 3;
   60.54 +
   60.55 +    /**
   60.56 +     * If the client name is not found on server's user database.
   60.57 +     */
   60.58 +    public final static int USER_UNKNOWN = 3;
   60.59 +
   60.60 +    /**
   60.61 +     * If authentication fails.
   60.62 +     */
   60.63 +    public final static int AUTH_FAILED = 4;
   60.64 +
   60.65 +    /**
   60.66 +     * If an illegal version string is provided.
   60.67 +     */
   60.68 +    public final static int BAD_VERSION = 5;
   60.69 +
   60.70 +    private int errorCode;
   60.71 +
   60.72 +    /**
   60.73 +     * Constructs an NTLMException object.
   60.74 +     * @param errorCode the error code, which can be retrieved by
   60.75 +     * the {@link #errorCode() } method.
   60.76 +     * @param msg the string message, which can be retrived by
   60.77 +     * the {@link Exception#getMessage() } method.
   60.78 +     */
   60.79 +    public NTLMException(int errorCode, String msg) {
   60.80 +        super(msg);
   60.81 +        this.errorCode = errorCode;
   60.82 +    }
   60.83 +
   60.84 +    /**
   60.85 +     * Returns the error code associated with this NTLMException.
   60.86 +     * @return the error code
   60.87 +     */
   60.88 +    public int errorCode() {
   60.89 +        return errorCode;
   60.90 +    }
   60.91 +}
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/src/share/classes/com/sun/security/ntlm/Server.java	Fri Sep 24 16:41:32 2010 -0700
    61.3 @@ -0,0 +1,205 @@
    61.4 +/*
    61.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    61.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    61.7 + *
    61.8 + * This code is free software; you can redistribute it and/or modify it
    61.9 + * under the terms of the GNU General Public License version 2 only, as
   61.10 + * published by the Free Software Foundation.  Oracle designates this
   61.11 + * particular file as subject to the "Classpath" exception as provided
   61.12 + * by Oracle in the LICENSE file that accompanied this code.
   61.13 + *
   61.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   61.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   61.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   61.17 + * version 2 for more details (a copy is included in the LICENSE file that
   61.18 + * accompanied this code).
   61.19 + *
   61.20 + * You should have received a copy of the GNU General Public License version
   61.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   61.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   61.23 + *
   61.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   61.25 + * or visit www.oracle.com if you need additional information or have any
   61.26 + * questions.
   61.27 + */
   61.28 +
   61.29 +package com.sun.security.ntlm;
   61.30 +
   61.31 +import java.util.Arrays;
   61.32 +import java.util.Locale;
   61.33 +
   61.34 +/**
   61.35 + * The NTLM server, not multi-thread enabled.<p>
   61.36 + * Example:
   61.37 + * <pre>
   61.38 + * Server server = new Server(null, "REALM") {
   61.39 + *     public char[] getPassword(String ntdomain, String username) {
   61.40 + *         switch (username) {
   61.41 + *             case "dummy": return "t0pSeCr3t".toCharArray();
   61.42 + *             case "guest": return "".toCharArray();
   61.43 + *             default: return null;
   61.44 + *         }
   61.45 + *     }
   61.46 + * };
   61.47 + * // Receive client request as type1
   61.48 + * byte[] type2 = server.type2(type1, nonce);
   61.49 + * // Send type2 to client and receive type3
   61.50 + * verify(type3, nonce);
   61.51 + * </pre>
   61.52 + */
   61.53 +public abstract class Server extends NTLM {
   61.54 +    final private String domain;
   61.55 +    final private boolean allVersion;
   61.56 +    /**
   61.57 +     * Creates a Server instance.
   61.58 +     * @param version the NTLM version to use, which can be:
   61.59 +     * <ul>
   61.60 +     * <li>NTLM: Original NTLM v1
   61.61 +     * <li>NTLM2: NTLM v1 with Client Challenge
   61.62 +     * <li>NTLMv2: NTLM v2
   61.63 +     * </ul>
   61.64 +     * If null, all versions will be supported. Please note that unless NTLM2
   61.65 +     * is selected, authentication succeeds if one of LM (or LMv2) or
   61.66 +     * NTLM (or NTLMv2) is verified.
   61.67 +     * @param domain the domain, must not be null
   61.68 +     * @throws NullPointerException if {@code domain} is null.
   61.69 +     */
   61.70 +    public Server(String version, String domain) throws NTLMException {
   61.71 +        super(version);
   61.72 +        if (domain == null) {
   61.73 +            throw new NullPointerException("domain cannot be null");
   61.74 +        }
   61.75 +        this.allVersion = (version == null);
   61.76 +        this.domain = domain;
   61.77 +        debug("NTLM Server: (t,version) = (%s,%s)\n", domain, version);
   61.78 +    }
   61.79 +
   61.80 +    /**
   61.81 +     * Generates the Type 2 message
   61.82 +     * @param type1 the Type1 message received, must not be null
   61.83 +     * @param nonce the random 8-byte array to be used in message generation,
   61.84 +     * must not be null
   61.85 +     * @return the message generated
   61.86 +     * @throws NullPointerException if type1 or nonce is null
   61.87 +     * @throws NTLMException if the incoming message is invalid
   61.88 +     */
   61.89 +    public byte[] type2(byte[] type1, byte[] nonce) {
   61.90 +        if (nonce == null) {
   61.91 +            throw new NullPointerException("nonce cannot be null");
   61.92 +        }
   61.93 +        debug("NTLM Server: Type 1 received\n");
   61.94 +        if (type1 != null) debug(type1);
   61.95 +        Writer p = new Writer(2, 32);
   61.96 +        int flags = 0x80205;
   61.97 +        p.writeSecurityBuffer(12, domain, true);
   61.98 +        p.writeInt(20, flags);
   61.99 +        p.writeBytes(24, nonce);
  61.100 +        debug("NTLM Server: Type 2 created\n");
  61.101 +        debug(p.getBytes());
  61.102 +        return p.getBytes();
  61.103 +    }
  61.104 +
  61.105 +    /**
  61.106 +     * Verifies the Type3 message received from client and returns
  61.107 +     * various negotiated information.
  61.108 +     * @param type3 the incoming Type3 message from client, must not be null
  61.109 +     * @param nonce the same nonce provided in {@link #type2}, must not be null
  61.110 +     * @return username and hostname of the client in a byte array
  61.111 +     * @throws NullPointerException if {@code type3} or {@code nonce} is null
  61.112 +     * @throws NTLMException if the incoming message is invalid
  61.113 +     */
  61.114 +    public String[] verify(byte[] type3, byte[] nonce)
  61.115 +            throws NTLMException {
  61.116 +        if (type3 == null || nonce == null) {
  61.117 +            throw new NullPointerException("type1 or nonce cannot be null");
  61.118 +        }
  61.119 +        debug("NTLM Server: Type 3 received\n");
  61.120 +        if (type3 != null) debug(type3);
  61.121 +        Reader r = new Reader(type3);
  61.122 +        String username = r.readSecurityBuffer(36, true);
  61.123 +        String hostname = r.readSecurityBuffer(44, true);
  61.124 +        String incomingDomain = r.readSecurityBuffer(28, true);
  61.125 +        /*if (incomingDomain != null && !incomingDomain.equals(domain)) {
  61.126 +            throw new NTLMException(NTLMException.DOMAIN_UNMATCH,
  61.127 +                    "Wrong domain: " + incomingDomain +
  61.128 +                    " vs " + domain); // Needed?
  61.129 +        }*/
  61.130 +        boolean verified = false;
  61.131 +        char[] password = getPassword(domain, username);
  61.132 +        if (password == null) {
  61.133 +            throw new NTLMException(NTLMException.USER_UNKNOWN,
  61.134 +                    "Unknown user");
  61.135 +        }
  61.136 +        byte[] incomingLM = r.readSecurityBuffer(12);
  61.137 +        byte[] incomingNTLM = r.readSecurityBuffer(20);
  61.138 +
  61.139 +        if (!verified && (allVersion || v == Version.NTLM)) {
  61.140 +            if (incomingLM.length > 0) {
  61.141 +                byte[] pw1 = getP1(password);
  61.142 +                byte[] lmhash = calcLMHash(pw1);
  61.143 +                byte[] lmresponse = calcResponse (lmhash, nonce);
  61.144 +                if (Arrays.equals(lmresponse, incomingLM)) {
  61.145 +                    verified = true;
  61.146 +                }
  61.147 +            }
  61.148 +            if (incomingNTLM.length > 0) {
  61.149 +                byte[] pw2 = getP2(password);
  61.150 +                byte[] nthash = calcNTHash(pw2);
  61.151 +                byte[] ntresponse = calcResponse (nthash, nonce);
  61.152 +                if (Arrays.equals(ntresponse, incomingNTLM)) {
  61.153 +                    verified = true;
  61.154 +                }
  61.155 +            }
  61.156 +            debug("NTLM Server: verify using NTLM: " + verified  + "\n");
  61.157 +        }
  61.158 +        if (!verified && (allVersion || v == Version.NTLM2)) {
  61.159 +            byte[] pw2 = getP2(password);
  61.160 +            byte[] nthash = calcNTHash(pw2);
  61.161 +            byte[] clientNonce = Arrays.copyOf(incomingLM, 8);
  61.162 +            byte[] ntlmresponse = ntlm2NTLM(nthash, clientNonce, nonce);
  61.163 +            if (Arrays.equals(incomingNTLM, ntlmresponse)) {
  61.164 +                verified = true;
  61.165 +            }
  61.166 +            debug("NTLM Server: verify using NTLM2: " + verified + "\n");
  61.167 +        }
  61.168 +        if (!verified && (allVersion || v == Version.NTLMv2)) {
  61.169 +            byte[] pw2 = getP2(password);
  61.170 +            byte[] nthash = calcNTHash(pw2);
  61.171 +            if (incomingLM.length > 0) {
  61.172 +                byte[] clientNonce = Arrays.copyOfRange(
  61.173 +                        incomingLM, 16, incomingLM.length);
  61.174 +                byte[] lmresponse = calcV2(nthash,
  61.175 +                        username.toUpperCase(Locale.US)+incomingDomain,
  61.176 +                        clientNonce, nonce);
  61.177 +                if (Arrays.equals(lmresponse, incomingLM)) {
  61.178 +                    verified = true;
  61.179 +                }
  61.180 +            }
  61.181 +            if (incomingNTLM.length > 0) {
  61.182 +                byte[] clientBlob = Arrays.copyOfRange(
  61.183 +                        incomingNTLM, 16, incomingNTLM.length);
  61.184 +                byte[] ntlmresponse = calcV2(nthash,
  61.185 +                        username.toUpperCase(Locale.US)+incomingDomain,
  61.186 +                        clientBlob, nonce);
  61.187 +                if (Arrays.equals(ntlmresponse, incomingNTLM)) {
  61.188 +                    verified = true;
  61.189 +                }
  61.190 +            }
  61.191 +            debug("NTLM Server: verify using NTLMv2: " + verified + "\n");
  61.192 +        }
  61.193 +        if (!verified) {
  61.194 +            throw new NTLMException(NTLMException.AUTH_FAILED,
  61.195 +                    "None of LM and NTLM verified");
  61.196 +        }
  61.197 +        return new String[] {username, hostname};
  61.198 +    }
  61.199 +
  61.200 +    /**
  61.201 +     * Retrieves the password for a given user. This method should be
  61.202 +     * overridden in a concrete class.
  61.203 +     * @param domain can be null
  61.204 +     * @param username must not be null
  61.205 +     * @return the password for the user, or null if unknown
  61.206 +     */
  61.207 +    public abstract char[] getPassword(String domain, String username);
  61.208 +}
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/src/share/classes/com/sun/security/ntlm/Version.java	Fri Sep 24 16:41:32 2010 -0700
    62.3 @@ -0,0 +1,30 @@
    62.4 +/*
    62.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    62.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    62.7 + *
    62.8 + * This code is free software; you can redistribute it and/or modify it
    62.9 + * under the terms of the GNU General Public License version 2 only, as
   62.10 + * published by the Free Software Foundation.  Oracle designates this
   62.11 + * particular file as subject to the "Classpath" exception as provided
   62.12 + * by Oracle in the LICENSE file that accompanied this code.
   62.13 + *
   62.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   62.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   62.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   62.17 + * version 2 for more details (a copy is included in the LICENSE file that
   62.18 + * accompanied this code).
   62.19 + *
   62.20 + * You should have received a copy of the GNU General Public License version
   62.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   62.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   62.23 + *
   62.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   62.25 + * or visit www.oracle.com if you need additional information or have any
   62.26 + * questions.
   62.27 + */
   62.28 +
   62.29 +package com.sun.security.ntlm;
   62.30 +
   62.31 +enum Version {
   62.32 +    NTLM, NTLM2, NTLMv2
   62.33 +}
    63.1 --- a/src/share/classes/com/sun/security/sasl/Provider.java	Thu Sep 23 17:33:40 2010 -0700
    63.2 +++ b/src/share/classes/com/sun/security/sasl/Provider.java	Fri Sep 24 16:41:32 2010 -0700
    63.3 @@ -1,5 +1,5 @@
    63.4  /*
    63.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    63.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    63.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    63.8   *
    63.9   * This code is free software; you can redistribute it and/or modify it
   63.10 @@ -35,10 +35,12 @@
   63.11   * - CRAM-MD5
   63.12   * - DIGEST-MD5
   63.13   * - GSSAPI/Kerberos v5
   63.14 + * - NTLM
   63.15   * And server support for
   63.16   * - CRAM-MD5
   63.17   * - DIGEST-MD5
   63.18   * - GSSAPI/Kerberos v5
   63.19 + * - NTLM
   63.20   */
   63.21  
   63.22  public final class Provider extends java.security.Provider {
   63.23 @@ -47,8 +49,8 @@
   63.24  
   63.25      private static final String info = "Sun SASL provider" +
   63.26          "(implements client mechanisms for: " +
   63.27 -        "DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5;" +
   63.28 -        " server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)";
   63.29 +        "DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5, NTLM;" +
   63.30 +        " server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5, NTLM)";
   63.31  
   63.32      public Provider() {
   63.33          super("SunSASL", 1.7d, info);
   63.34 @@ -58,6 +60,8 @@
   63.35                  // Client mechanisms
   63.36                  put("SaslClientFactory.DIGEST-MD5",
   63.37                      "com.sun.security.sasl.digest.FactoryImpl");
   63.38 +                put("SaslClientFactory.NTLM",
   63.39 +                    "com.sun.security.sasl.ntlm.FactoryImpl");
   63.40                  put("SaslClientFactory.GSSAPI",
   63.41                      "com.sun.security.sasl.gsskerb.FactoryImpl");
   63.42  
   63.43 @@ -75,6 +79,8 @@
   63.44                      "com.sun.security.sasl.gsskerb.FactoryImpl");
   63.45                  put("SaslServerFactory.DIGEST-MD5",
   63.46                      "com.sun.security.sasl.digest.FactoryImpl");
   63.47 +                put("SaslServerFactory.NTLM",
   63.48 +                    "com.sun.security.sasl.ntlm.FactoryImpl");
   63.49                  return null;
   63.50              }
   63.51          });
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/src/share/classes/com/sun/security/sasl/ntlm/FactoryImpl.java	Fri Sep 24 16:41:32 2010 -0700
    64.3 @@ -0,0 +1,119 @@
    64.4 +/*
    64.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    64.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    64.7 + *
    64.8 + * This code is free software; you can redistribute it and/or modify it
    64.9 + * under the terms of the GNU General Public License version 2 only, as
   64.10 + * published by the Free Software Foundation.  Oracle designates this
   64.11 + * particular file as subject to the "Classpath" exception as provided
   64.12 + * by Oracle in the LICENSE file that accompanied this code.
   64.13 + *
   64.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   64.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   64.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   64.17 + * version 2 for more details (a copy is included in the LICENSE file that
   64.18 + * accompanied this code).
   64.19 + *
   64.20 + * You should have received a copy of the GNU General Public License version
   64.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   64.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   64.23 + *
   64.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   64.25 + * or visit www.oracle.com if you need additional information or have any
   64.26 + * questions.
   64.27 + */
   64.28 +
   64.29 +package com.sun.security.sasl.ntlm;
   64.30 +
   64.31 +import java.util.Map;
   64.32 +
   64.33 +import javax.security.sasl.*;
   64.34 +import javax.security.auth.callback.CallbackHandler;
   64.35 +
   64.36 +import com.sun.security.sasl.util.PolicyUtils;
   64.37 +
   64.38 +
   64.39 +/**
   64.40 +  * Client and server factory for NTLM SASL client/server mechanisms.
   64.41 +  * See NTLMClient and NTLMServer for input requirements.
   64.42 +  *
   64.43 +  * @since 1.7
   64.44 +  */
   64.45 +
   64.46 +public final class FactoryImpl implements SaslClientFactory,
   64.47 +SaslServerFactory{
   64.48 +
   64.49 +    private static final String myMechs[] = { "NTLM" };
   64.50 +    private static final int mechPolicies[] = {
   64.51 +            PolicyUtils.NOPLAINTEXT|PolicyUtils.NOANONYMOUS
   64.52 +    };
   64.53 +
   64.54 +    /**
   64.55 +      * Empty constructor.
   64.56 +      */
   64.57 +    public FactoryImpl() {
   64.58 +    }
   64.59 +
   64.60 +    /**
   64.61 +     * Returns a new instance of the NTLM SASL client mechanism.
   64.62 +     * Argument checks are performed in SaslClient's constructor.
   64.63 +     * @returns a new SaslClient ; otherwise null if unsuccessful.
   64.64 +     * @throws SaslException If there is an error creating the NTLM
   64.65 +     * SASL client.
   64.66 +     */
   64.67 +    public SaslClient createSaslClient(String[] mechs,
   64.68 +         String authorizationId, String protocol, String serverName,
   64.69 +         Map<String,?> props, CallbackHandler cbh)
   64.70 +         throws SaslException {
   64.71 +
   64.72 +         for (int i=0; i<mechs.length; i++) {
   64.73 +            if (mechs[i].equals("NTLM") &&
   64.74 +                    PolicyUtils.checkPolicy(mechPolicies[0], props)) {
   64.75 +
   64.76 +                return new NTLMClient(mechs[i], authorizationId,
   64.77 +                    protocol, serverName, props, cbh);
   64.78 +            }
   64.79 +        }
   64.80 +        return null;
   64.81 +    }
   64.82 +
   64.83 +    /**
   64.84 +     * Returns a new instance of the NTLM SASL server mechanism.
   64.85 +     * Argument checks are performed in SaslServer's constructor.
   64.86 +     * @returns a new SaslServer ; otherwise null if unsuccessful.
   64.87 +     * @throws SaslException If there is an error creating the NTLM
   64.88 +     * SASL server.
   64.89 +     */
   64.90 +    public SaslServer createSaslServer(String mech,
   64.91 +         String protocol, String serverName, Map<String,?> props, CallbackHandler cbh)
   64.92 +         throws SaslException {
   64.93 +
   64.94 +         if (mech.equals("NTLM") &&
   64.95 +                 PolicyUtils.checkPolicy(mechPolicies[0], props)) {
   64.96 +             if (props != null) {
   64.97 +                 String qop = (String)props.get(Sasl.QOP);
   64.98 +                 if (qop != null && !qop.equals("auth")) {
   64.99 +                     throw new SaslException("NTLM only support auth");
  64.100 +                 }
  64.101 +             }
  64.102 +             if (cbh == null) {
  64.103 +                 throw new SaslException(
  64.104 +                        "Callback handler with support for AuthorizeCallback, "+
  64.105 +                        "RealmCallback, NameCallback, and PasswordCallback " +
  64.106 +                        "required");
  64.107 +             }
  64.108 +             return new NTLMServer(mech, protocol, serverName, props, cbh);
  64.109 +         }
  64.110 +         return null;
  64.111 +    }
  64.112 +
  64.113 +    /**
  64.114 +      * Returns the authentication mechanisms that this factory can produce.
  64.115 +      *
  64.116 +      * @returns String[] {"NTLM"} if policies in env match those of this
  64.117 +      * factory.
  64.118 +      */
  64.119 +    public String[] getMechanismNames(Map<String,?> env) {
  64.120 +        return PolicyUtils.filterMechs(myMechs, mechPolicies, env);
  64.121 +    }
  64.122 +}
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/src/share/classes/com/sun/security/sasl/ntlm/NTLMClient.java	Fri Sep 24 16:41:32 2010 -0700
    65.3 @@ -0,0 +1,231 @@
    65.4 +/*
    65.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    65.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    65.7 + *
    65.8 + * This code is free software; you can redistribute it and/or modify it
    65.9 + * under the terms of the GNU General Public License version 2 only, as
   65.10 + * published by the Free Software Foundation.  Oracle designates this
   65.11 + * particular file as subject to the "Classpath" exception as provided
   65.12 + * by Oracle in the LICENSE file that accompanied this code.
   65.13 + *
   65.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   65.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   65.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   65.17 + * version 2 for more details (a copy is included in the LICENSE file that
   65.18 + * accompanied this code).
   65.19 + *
   65.20 + * You should have received a copy of the GNU General Public License version
   65.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   65.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   65.23 + *
   65.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   65.25 + * or visit www.oracle.com if you need additional information or have any
   65.26 + * questions.
   65.27 + */
   65.28 +
   65.29 +package com.sun.security.sasl.ntlm;
   65.30 +
   65.31 +import com.sun.security.ntlm.Client;
   65.32 +import com.sun.security.ntlm.NTLMException;
   65.33 +import java.io.IOException;
   65.34 +import java.net.InetAddress;
   65.35 +import java.net.UnknownHostException;
   65.36 +import java.util.Map;
   65.37 +import java.util.Random;
   65.38 +import javax.security.auth.callback.Callback;
   65.39 +
   65.40 +
   65.41 +import javax.security.sasl.*;
   65.42 +import javax.security.auth.callback.CallbackHandler;
   65.43 +import javax.security.auth.callback.NameCallback;
   65.44 +import javax.security.auth.callback.PasswordCallback;
   65.45 +import javax.security.auth.callback.UnsupportedCallbackException;
   65.46 +
   65.47 +/**
   65.48 +  * Required callbacks:
   65.49 +  * - RealmCallback
   65.50 +  *    handle can provide domain info for authentication, optional
   65.51 +  * - NameCallback
   65.52 +  *    handler must enter username to use for authentication
   65.53 +  * - PasswordCallback
   65.54 +  *    handler must enter password for username to use for authentication
   65.55 +  *
   65.56 +  * Environment properties that affect behavior of implementation:
   65.57 +  *
   65.58 +  * javax.security.sasl.qop
   65.59 +  *    String, quality of protection; only "auth" is accepted, default "auth"
   65.60 +  *
   65.61 +  * com.sun.security.sasl.ntlm.version
   65.62 +  *    String, name a specific version to use; can be:
   65.63 +  *      LM/NTLM: Original NTLM v1
   65.64 +  *      LM: Original NTLM v1, LM only
   65.65 +  *      NTLM: Original NTLM v1, NTLM only
   65.66 +  *      NTLM2: NTLM v1 with Client Challenge
   65.67 +  *      LMv2/NTLMv2: NTLM v2
   65.68 +  *      LMv2: NTLM v2, LM only
   65.69 +  *      NTLMv2: NTLM v2, NTLM only
   65.70 +  *    If not specified, use system property "ntlm.version". If
   65.71 +  *    still not specified, use default value "LMv2/NTLMv2".
   65.72 +  *
   65.73 +  * com.sun.security.sasl.ntlm.random
   65.74 +  *    java.util.Random, the nonce source to be used in NTLM v2 or NTLM v1 with
   65.75 +  *    Client Challenge. Default null, an internal java.util.Random object
   65.76 +  *    will be used
   65.77 +  *
   65.78 +  * Negotiated Properties:
   65.79 +  *
   65.80 +  * javax.security.sasl.qop
   65.81 +  *    Always "auth"
   65.82 +  *
   65.83 +  * com.sun.security.sasl.html.domain
   65.84 +  *    The domain for the user, provided by the server
   65.85 +  *
   65.86 +  * @see <a href="http://www.ietf.org/rfc/rfc2222.txt">RFC 2222</a>
   65.87 +  * - Simple Authentication and Security Layer (SASL)
   65.88 +  *
   65.89 +  */
   65.90 +final class NTLMClient implements SaslClient {
   65.91 +
   65.92 +    private static final String NTLM_VERSION =
   65.93 +            "com.sun.security.sasl.ntlm.version";
   65.94 +    private static final String NTLM_RANDOM =
   65.95 +            "com.sun.security.sasl.ntlm.random";
   65.96 +    private final static String NTLM_DOMAIN =
   65.97 +            "com.sun.security.sasl.ntlm.domain";
   65.98 +    private final static String NTLM_HOSTNAME =
   65.99 +            "com.sun.security.sasl.ntlm.hostname";
  65.100 +
  65.101 +    private final Client client;
  65.102 +    private final String mech;
  65.103 +    private final Random random;
  65.104 +
  65.105 +    private int step = 0;   // 0-start,1-nego,2-auth,3-done
  65.106 +
  65.107 +    /**
  65.108 +     * @param mech non-null
  65.109 +     * @param authorizationId can be null or empty and ignored
  65.110 +     * @param protocol non-null for Sasl, useless for NTLM
  65.111 +     * @param serverName non-null for Sasl, but can be null for NTLM
  65.112 +     * @param props can be null
  65.113 +     * @param cbh can be null for Sasl, but will throw NPE for NTLM
  65.114 +     * @throws SaslException
  65.115 +     */
  65.116 +    NTLMClient(String mech, String authzid, String protocol, String serverName,
  65.117 +            Map props, CallbackHandler cbh) throws SaslException {
  65.118 +
  65.119 +        this.mech = mech;
  65.120 +        String version = null;
  65.121 +        Random rtmp = null;
  65.122 +        String hostname = null;
  65.123 +
  65.124 +        if (props != null) {
  65.125 +            String qop = (String)props.get(Sasl.QOP);
  65.126 +            if (qop != null && !qop.equals("auth")) {
  65.127 +                throw new SaslException("NTLM only support auth");
  65.128 +            }
  65.129 +            version = (String)props.get(NTLM_VERSION);
  65.130 +            rtmp = (Random)props.get(NTLM_RANDOM);
  65.131 +            hostname = (String)props.get(NTLM_HOSTNAME);
  65.132 +        }
  65.133 +        this.random = rtmp != null ? rtmp : new Random();
  65.134 +
  65.135 +        if (version == null) {
  65.136 +            version = System.getProperty("ntlm.version");
  65.137 +        }
  65.138 +
  65.139 +        RealmCallback dcb = (serverName != null && !serverName.isEmpty())?
  65.140 +            new RealmCallback("Realm: ", serverName) :
  65.141 +            new RealmCallback("Realm: ");
  65.142 +        NameCallback ncb = (authzid != null && !authzid.isEmpty()) ?
  65.143 +            new NameCallback("User name: ", authzid) :
  65.144 +            new NameCallback("User name: ");
  65.145 +        PasswordCallback pcb =
  65.146 +            new PasswordCallback("Password: ", false);
  65.147 +
  65.148 +        try {
  65.149 +            cbh.handle(new Callback[] {dcb, ncb, pcb});
  65.150 +        } catch (UnsupportedCallbackException e) {
  65.151 +            throw new SaslException("NTLM: Cannot perform callback to " +
  65.152 +                "acquire realm, username or password", e);
  65.153 +        } catch (IOException e) {
  65.154 +            throw new SaslException(
  65.155 +                "NTLM: Error acquiring realm, username or password", e);
  65.156 +        }
  65.157 +
  65.158 +        if (hostname == null) {
  65.159 +            try {
  65.160 +                hostname = InetAddress.getLocalHost().getCanonicalHostName();
  65.161 +            } catch (UnknownHostException e) {
  65.162 +                hostname = "localhost";
  65.163 +            }
  65.164 +        }
  65.165 +        try {
  65.166 +            client = new Client(version, hostname,
  65.167 +                    ncb.getName(),
  65.168 +                    dcb.getText(),
  65.169 +                    pcb.getPassword());
  65.170 +        } catch (NTLMException ne) {
  65.171 +            throw new SaslException(
  65.172 +                    "NTLM: Invalid version string: " + version, ne);
  65.173 +        }
  65.174 +    }
  65.175 +
  65.176 +    @Override
  65.177 +    public String getMechanismName() {
  65.178 +        return mech;
  65.179 +    }
  65.180 +
  65.181 +    @Override
  65.182 +    public boolean isComplete() {
  65.183 +        return step >= 2;
  65.184 +    }
  65.185 +
  65.186 +    @Override
  65.187 +    public byte[] unwrap(byte[] incoming, int offset, int len)
  65.188 +            throws SaslException {
  65.189 +        throw new UnsupportedOperationException("Not supported.");
  65.190 +    }
  65.191 +
  65.192 +    @Override
  65.193 +    public byte[] wrap(byte[] outgoing, int offset, int len)
  65.194 +            throws SaslException {
  65.195 +        throw new UnsupportedOperationException("Not supported.");
  65.196 +    }
  65.197 +
  65.198 +    @Override
  65.199 +    public Object getNegotiatedProperty(String propName) {
  65.200 +        if (propName.equals(Sasl.QOP)) {
  65.201 +            return "auth";
  65.202 +        } else if (propName.equals(NTLM_DOMAIN)) {
  65.203 +            return client.getDomain();
  65.204 +        } else {
  65.205 +            return null;
  65.206 +        }
  65.207 +    }
  65.208 +
  65.209 +    @Override
  65.210 +    public void dispose() throws SaslException {
  65.211 +        client.dispose();
  65.212 +    }
  65.213 +
  65.214 +    @Override
  65.215 +    public boolean hasInitialResponse() {
  65.216 +        return true;
  65.217 +    }
  65.218 +
  65.219 +    @Override
  65.220 +    public byte[] evaluateChallenge(byte[] challenge) throws SaslException {
  65.221 +        step++;
  65.222 +        if (step == 1) {
  65.223 +            return client.type1();
  65.224 +        } else {
  65.225 +            try {
  65.226 +                byte[] nonce = new byte[8];
  65.227 +                random.nextBytes(nonce);
  65.228 +                return client.type3(challenge, nonce);
  65.229 +            } catch (NTLMException ex) {
  65.230 +                throw new SaslException("Type3 creation failed", ex);
  65.231 +            }
  65.232 +        }
  65.233 +    }
  65.234 +}
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/src/share/classes/com/sun/security/sasl/ntlm/NTLMServer.java	Fri Sep 24 16:41:32 2010 -0700
    66.3 @@ -0,0 +1,226 @@
    66.4 +/*
    66.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    66.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    66.7 + *
    66.8 + * This code is free software; you can redistribute it and/or modify it
    66.9 + * under the terms of the GNU General Public License version 2 only, as
   66.10 + * published by the Free Software Foundation.  Oracle designates this
   66.11 + * particular file as subject to the "Classpath" exception as provided
   66.12 + * by Oracle in the LICENSE file that accompanied this code.
   66.13 + *
   66.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   66.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   66.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   66.17 + * version 2 for more details (a copy is included in the LICENSE file that
   66.18 + * accompanied this code).
   66.19 + *
   66.20 + * You should have received a copy of the GNU General Public License version
   66.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   66.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   66.23 + *
   66.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   66.25 + * or visit www.oracle.com if you need additional information or have any
   66.26 + * questions.
   66.27 + */
   66.28 +
   66.29 +package com.sun.security.sasl.ntlm;
   66.30 +
   66.31 +import com.sun.security.ntlm.NTLMException;
   66.32 +import com.sun.security.ntlm.Server;
   66.33 +import java.io.IOException;
   66.34 +import java.security.GeneralSecurityException;
   66.35 +import java.util.Map;
   66.36 +import java.util.Random;
   66.37 +import javax.security.auth.callback.Callback;
   66.38 +import javax.security.auth.callback.CallbackHandler;
   66.39 +import javax.security.auth.callback.NameCallback;
   66.40 +import javax.security.auth.callback.PasswordCallback;
   66.41 +import javax.security.auth.callback.UnsupportedCallbackException;
   66.42 +import javax.security.sasl.*;
   66.43 +
   66.44 +/**
   66.45 +  * Required callbacks:
   66.46 +  * - RealmCallback
   66.47 +  *      used as key by handler to fetch password, optional
   66.48 +  * - NameCallback
   66.49 +  *      used as key by handler to fetch password
   66.50 +  * - PasswordCallback
   66.51 +  *      handler must enter password for username/realm supplied
   66.52 +  *
   66.53 +  * Environment properties that affect the implementation:
   66.54 +  *
   66.55 +  * javax.security.sasl.qop
   66.56 +  *    String, quality of protection; only "auth" is accepted, default "auth"
   66.57 +  *
   66.58 +  * com.sun.security.sasl.ntlm.version
   66.59 +  *    String, name a specific version to accept:
   66.60 +  *      LM/NTLM: Original NTLM v1
   66.61 +  *      LM: Original NTLM v1, LM only
   66.62 +  *      NTLM: Original NTLM v1, NTLM only
   66.63 +  *      NTLM2: NTLM v1 with Client Challenge
   66.64 +  *      LMv2/NTLMv2: NTLM v2
   66.65 +  *      LMv2: NTLM v2, LM only
   66.66 +  *      NTLMv2: NTLM v2, NTLM only
   66.67 +  *    If not specified, use system property "ntlm.version". If also
   66.68 +  *    not specfied, all versions are accepted.
   66.69 +  *
   66.70 +  * com.sun.security.sasl.ntlm.domain
   66.71 +  *    String, the domain of the server, default is server name (fqdn parameter)
   66.72 +  *
   66.73 +  * com.sun.security.sasl.ntlm.random
   66.74 +  *    java.util.Random, the nonce source. Default null, an internal
   66.75 +  *    java.util.Random object will be used
   66.76 +  *
   66.77 +  * Negotiated Properties:
   66.78 +  *
   66.79 +  * javax.security.sasl.qop
   66.80 +  *    Always "auth"
   66.81 +  *
   66.82 +  * com.sun.security.sasl.ntlm.hostname
   66.83 +  *    The hostname for the user, provided by the client
   66.84 +  *
   66.85 +  */
   66.86 +
   66.87 +final class NTLMServer implements SaslServer {
   66.88 +
   66.89 +    private final static String NTLM_VERSION =
   66.90 +            "com.sun.security.sasl.ntlm.version";
   66.91 +    private final static String NTLM_DOMAIN =
   66.92 +            "com.sun.security.sasl.ntlm.domain";
   66.93 +    private final static String NTLM_HOSTNAME =
   66.94 +            "com.sun.security.sasl.ntlm.hostname";
   66.95 +    private static final String NTLM_RANDOM =
   66.96 +            "com.sun.security.sasl.ntlm.random";
   66.97 +
   66.98 +    private final Random random;
   66.99 +    private final Server server;
  66.100 +    private byte[] nonce;
  66.101 +    private int step = 0;
  66.102 +    private String authzId;
  66.103 +    private final String mech;
  66.104 +    private String hostname;
  66.105 +
  66.106 +    /**
  66.107 +     * @param mech not null
  66.108 +     * @param protocol not null for Sasl, ignored in NTLM
  66.109 +     * @param serverName not null for Sasl, can be null in NTLM. If non-null,
  66.110 +     * might be used as domain if not provided in props
  66.111 +     * @param props can be null
  66.112 +     * @param cbh can be null for Sasl, but will throw NPE in auth for NTLM
  66.113 +     * @throws SaslException
  66.114 +     */
  66.115 +    NTLMServer(String mech, String protocol, String serverName,
  66.116 +            Map props, final CallbackHandler cbh) throws SaslException {
  66.117 +
  66.118 +        this.mech = mech;
  66.119 +        String version = null;
  66.120 +        String domain = null;
  66.121 +        Random rtmp = null;
  66.122 +
  66.123 +        if (props != null) {
  66.124 +            domain = (String) props.get(NTLM_DOMAIN);
  66.125 +            version = (String)props.get(NTLM_VERSION);
  66.126 +            rtmp = (Random)props.get(NTLM_RANDOM);
  66.127 +        }
  66.128 +        random = rtmp != null ? rtmp : new Random();
  66.129 +
  66.130 +        if (version == null) {
  66.131 +            version = System.getProperty("ntlm.version");
  66.132 +        }
  66.133 +        if (domain == null) {
  66.134 +            domain = serverName;
  66.135 +        }
  66.136 +        if (domain == null) {
  66.137 +            throw new NullPointerException("Domain must be provided as"
  66.138 +                    + " the serverName argument or in props");
  66.139 +        }
  66.140 +
  66.141 +        try {
  66.142 +            server = new Server(version, domain) {
  66.143 +                public char[] getPassword(String ntdomain, String username) {
  66.144 +                    try {
  66.145 +                        RealmCallback rcb = new RealmCallback(
  66.146 +                                "Domain: ", ntdomain);
  66.147 +                        NameCallback ncb = new NameCallback(
  66.148 +                                "Name: ", username);
  66.149 +                        PasswordCallback pcb = new PasswordCallback(
  66.150 +                                "Password: ", false);
  66.151 +                        cbh.handle(new Callback[] { rcb, ncb, pcb });
  66.152 +                        char[] passwd = pcb.getPassword();
  66.153 +                        pcb.clearPassword();
  66.154 +                        return passwd;
  66.155 +                    } catch (IOException ioe) {
  66.156 +                        return null;
  66.157 +                    } catch (UnsupportedCallbackException uce) {
  66.158 +                        return null;
  66.159 +                    }
  66.160 +                }
  66.161 +            };
  66.162 +        } catch (NTLMException ne) {
  66.163 +            throw new SaslException(
  66.164 +                    "NTLM: Invalid version string: " + version, ne);
  66.165 +        }
  66.166 +        nonce = new byte[8];
  66.167 +    }
  66.168 +
  66.169 +    @Override
  66.170 +    public String getMechanismName() {
  66.171 +        return mech;
  66.172 +    }
  66.173 +
  66.174 +    @Override
  66.175 +    public byte[] evaluateResponse(byte[] response) throws SaslException {
  66.176 +        try {
  66.177 +            step++;
  66.178 +            if (step == 1) {
  66.179 +                random.nextBytes(nonce);
  66.180 +                return server.type2(response, nonce);
  66.181 +            } else {
  66.182 +                String[] out = server.verify(response, nonce);
  66.183 +                authzId = out[0];
  66.184 +                hostname = out[1];
  66.185 +                return null;
  66.186 +            }
  66.187 +        } catch (GeneralSecurityException ex) {
  66.188 +            throw new SaslException("", ex);
  66.189 +        }
  66.190 +    }
  66.191 +
  66.192 +    @Override
  66.193 +    public boolean isComplete() {
  66.194 +        return step >= 2;
  66.195 +    }
  66.196 +
  66.197 +    @Override
  66.198 +    public String getAuthorizationID() {
  66.199 +        return authzId;
  66.200 +    }
  66.201 +
  66.202 +    @Override
  66.203 +    public byte[] unwrap(byte[] incoming, int offset, int len)
  66.204 +            throws SaslException {
  66.205 +        throw new UnsupportedOperationException("Not supported yet.");
  66.206 +    }
  66.207 +
  66.208 +    @Override
  66.209 +    public byte[] wrap(byte[] outgoing, int offset, int len)
  66.210 +            throws SaslException {
  66.211 +        throw new UnsupportedOperationException("Not supported yet.");
  66.212 +    }
  66.213 +
  66.214 +    @Override
  66.215 +    public Object getNegotiatedProperty(String propName) {
  66.216 +        if (propName.equals(Sasl.QOP)) {
  66.217 +            return "auth";
  66.218 +        } else if (propName.equals(NTLM_HOSTNAME)) {
  66.219 +            return hostname;
  66.220 +        } else {
  66.221 +            return null;
  66.222 +        }
  66.223 +    }
  66.224 +
  66.225 +    @Override
  66.226 +    public void dispose() throws SaslException {
  66.227 +        return;
  66.228 +    }
  66.229 +}
    67.1 --- a/src/share/classes/java/awt/Dialog.java	Thu Sep 23 17:33:40 2010 -0700
    67.2 +++ b/src/share/classes/java/awt/Dialog.java	Fri Sep 24 16:41:32 2010 -0700
    67.3 @@ -277,10 +277,8 @@
    67.4       */
    67.5      String title;
    67.6  
    67.7 -    private transient volatile boolean keepBlockingEDT = false;
    67.8 -    private transient volatile boolean keepBlockingCT = false;
    67.9 -
   67.10      private transient ModalEventFilter modalFilter;
   67.11 +    private transient volatile SecondaryLoop secondaryLoop;
   67.12  
   67.13      /*
   67.14       * Indicates that this dialog is being hidden. This flag is set to true at
   67.15 @@ -1005,12 +1003,6 @@
   67.16          super.setVisible(b);
   67.17      }
   67.18  
   67.19 -    /**
   67.20 -    * Stores the app context on which event dispatch thread the dialog
   67.21 -    * is being shown. Initialized in show(), used in hideAndDisposeHandler()
   67.22 -    */
   67.23 -    transient private AppContext showAppContext;
   67.24 -
   67.25     /**
   67.26       * Makes the {@code Dialog} visible. If the dialog and/or its owner
   67.27       * are not yet displayable, both are made displayable.  The
   67.28 @@ -1037,39 +1029,18 @@
   67.29          if (!isModal()) {
   67.30              conditionalShow(null, null);
   67.31          } else {
   67.32 -            // Set this variable before calling conditionalShow(). That
   67.33 -            // way, if the Dialog is hidden right after being shown, we
   67.34 -            // won't mistakenly block this thread.
   67.35 -            keepBlockingEDT = true;
   67.36 -            keepBlockingCT = true;
   67.37 -
   67.38 -            // Store the app context on which this dialog is being shown.
   67.39 -            // Event dispatch thread of this app context will be sleeping until
   67.40 -            // we wake it by any event from hideAndDisposeHandler().
   67.41 -            showAppContext = AppContext.getAppContext();
   67.42 +            AppContext showAppContext = AppContext.getAppContext();
   67.43  
   67.44              AtomicLong time = new AtomicLong();
   67.45              Component predictedFocusOwner = null;
   67.46              try {
   67.47                  predictedFocusOwner = getMostRecentFocusOwner();
   67.48                  if (conditionalShow(predictedFocusOwner, time)) {
   67.49 -                    // We have two mechanisms for blocking: 1. If we're on the
   67.50 -                    // EventDispatchThread, start a new event pump. 2. If we're
   67.51 -                    // on any other thread, call wait() on the treelock.
   67.52 -
   67.53                      modalFilter = ModalEventFilter.createFilterForDialog(this);
   67.54 -
   67.55 -                    final Runnable pumpEventsForFilter = new Runnable() {
   67.56 -                        public void run() {
   67.57 -                            EventDispatchThread dispatchThread =
   67.58 -                                (EventDispatchThread)Thread.currentThread();
   67.59 -                            dispatchThread.pumpEventsForFilter(new Conditional() {
   67.60 -                                public boolean evaluate() {
   67.61 -                                    synchronized (getTreeLock()) {
   67.62 -                                        return keepBlockingEDT && windowClosingException == null;
   67.63 -                                    }
   67.64 -                                }
   67.65 -                            }, modalFilter);
   67.66 +                    Conditional cond = new Conditional() {
   67.67 +                        @Override
   67.68 +                        public boolean evaluate() {
   67.69 +                            return windowClosingException == null;
   67.70                          }
   67.71                      };
   67.72  
   67.73 @@ -1096,44 +1067,10 @@
   67.74  
   67.75                      modalityPushed();
   67.76                      try {
   67.77 -                        if (EventQueue.isDispatchThread()) {
   67.78 -                            /*
   67.79 -                             * dispose SequencedEvent we are dispatching on current
   67.80 -                             * AppContext, to prevent us from hang.
   67.81 -                             *
   67.82 -                             */
   67.83 -                            // BugId 4531693 (son@sparc.spb.su)
   67.84 -                            SequencedEvent currentSequencedEvent = KeyboardFocusManager.
   67.85 -                                getCurrentKeyboardFocusManager().getCurrentSequencedEvent();
   67.86 -                            if (currentSequencedEvent != null) {
   67.87 -                                currentSequencedEvent.dispose();
   67.88 -                            }
   67.89 -
   67.90 -                            /*
   67.91 -                             * Event processing is done inside doPrivileged block so that
   67.92 -                             * it wouldn't matter even if user code is on the stack
   67.93 -                             * Fix for BugId 6300270
   67.94 -                             */
   67.95 -
   67.96 -                             AccessController.doPrivileged(new PrivilegedAction() {
   67.97 -                                     public Object run() {
   67.98 -                                        pumpEventsForFilter.run();
   67.99 -                                        return null;
  67.100 -                                     }
  67.101 -                             });
  67.102 -                        } else {
  67.103 -                            synchronized (getTreeLock()) {
  67.104 -                                Toolkit.getEventQueue().postEvent(new PeerEvent(this,
  67.105 -                                                                                pumpEventsForFilter,
  67.106 -                                                                                PeerEvent.PRIORITY_EVENT));
  67.107 -                                while (keepBlockingCT && windowClosingException == null) {
  67.108 -                                    try {
  67.109 -                                        getTreeLock().wait();
  67.110 -                                    } catch (InterruptedException e) {
  67.111 -                                        break;
  67.112 -                                    }
  67.113 -                                }
  67.114 -                            }
  67.115 +                        EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
  67.116 +                        secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 5000);
  67.117 +                        if (!secondaryLoop.enter()) {
  67.118 +                            secondaryLoop = null;
  67.119                          }
  67.120                      } finally {
  67.121                          modalityPopped();
  67.122 @@ -1194,18 +1131,11 @@
  67.123              windowClosingException = null;
  67.124          }
  67.125      }
  67.126 -    final class WakingRunnable implements Runnable {
  67.127 -        public void run() {
  67.128 -            synchronized (getTreeLock()) {
  67.129 -                keepBlockingCT = false;
  67.130 -                getTreeLock().notifyAll();
  67.131 -            }
  67.132 -        }
  67.133 -    }
  67.134 +
  67.135      private void hideAndDisposePreHandler() {
  67.136          isInHide = true;
  67.137          synchronized (getTreeLock()) {
  67.138 -            if (keepBlockingEDT) {
  67.139 +            if (secondaryLoop != null) {
  67.140                  modalHide();
  67.141                  // dialog can be shown and then disposed before its
  67.142                  // modal filter is created
  67.143 @@ -1217,20 +1147,9 @@
  67.144          }
  67.145      }
  67.146      private void hideAndDisposeHandler() {
  67.147 -        synchronized (getTreeLock()) {
  67.148 -            if (keepBlockingEDT) {
  67.149 -                keepBlockingEDT = false;
  67.150 -                PeerEvent wakingEvent = new PeerEvent(getToolkit(), new WakingRunnable(), PeerEvent.PRIORITY_EVENT);
  67.151 -                AppContext curAppContext = AppContext.getAppContext();
  67.152 -                if (showAppContext != curAppContext) {
  67.153 -                    // Wake up event dispatch thread on which the dialog was
  67.154 -                    // initially shown
  67.155 -                    SunToolkit.postEvent(showAppContext, wakingEvent);
  67.156 -                    showAppContext = null;
  67.157 -                } else {
  67.158 -                    Toolkit.getEventQueue().postEvent(wakingEvent);
  67.159 -                }
  67.160 -            }
  67.161 +        if (secondaryLoop != null) {
  67.162 +            secondaryLoop.exit();
  67.163 +            secondaryLoop = null;
  67.164          }
  67.165          isInHide = false;
  67.166      }
    68.1 --- a/src/share/classes/java/awt/EventDispatchThread.java	Thu Sep 23 17:33:40 2010 -0700
    68.2 +++ b/src/share/classes/java/awt/EventDispatchThread.java	Fri Sep 24 16:41:32 2010 -0700
    68.3 @@ -113,8 +113,7 @@
    68.4          pumpEventsForHierarchy(id, cond, null);
    68.5      }
    68.6  
    68.7 -    void pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent)
    68.8 -    {
    68.9 +    void pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent) {
   68.10          pumpEventsForFilter(id, cond, new HierarchyEventFilter(modalComponent));
   68.11      }
   68.12  
   68.13 @@ -124,6 +123,7 @@
   68.14  
   68.15      void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
   68.16          addEventFilter(filter);
   68.17 +        doDispatch = true;
   68.18          while (doDispatch && cond.evaluate()) {
   68.19              if (isInterrupted() || !pumpOneEventForFilters(id)) {
   68.20                  doDispatch = false;
   68.21 @@ -133,6 +133,7 @@
   68.22      }
   68.23  
   68.24      void addEventFilter(EventFilter filter) {
   68.25 +        eventLog.finest("adding the event filter: " + filter);
   68.26          synchronized (eventFilters) {
   68.27              if (!eventFilters.contains(filter)) {
   68.28                  if (filter instanceof ModalEventFilter) {
   68.29 @@ -156,6 +157,7 @@
   68.30      }
   68.31  
   68.32      void removeEventFilter(EventFilter filter) {
   68.33 +        eventLog.finest("removing the event filter: " + filter);
   68.34          synchronized (eventFilters) {
   68.35              eventFilters.remove(filter);
   68.36          }
    69.1 --- a/src/share/classes/java/awt/EventQueue.java	Thu Sep 23 17:33:40 2010 -0700
    69.2 +++ b/src/share/classes/java/awt/EventQueue.java	Fri Sep 24 16:41:32 2010 -0700
    69.3 @@ -884,6 +884,41 @@
    69.4      }
    69.5  
    69.6      /**
    69.7 +     * Creates a new {@code secondary loop} associated with this
    69.8 +     * event queue. Use the {@link SecondaryLoop#enter} and
    69.9 +     * {@link SecondaryLoop#exit} methods to start and stop the
   69.10 +     * event loop and dispatch the events from this queue.
   69.11 +     *
   69.12 +     * @return secondaryLoop A new secondary loop object, which can
   69.13 +     *                       be used to launch a new nested event
   69.14 +     *                       loop and dispatch events from this queue
   69.15 +     *
   69.16 +     * @see SecondaryLoop#enter
   69.17 +     * @see SecondaryLoop#exit
   69.18 +     *
   69.19 +     * @since 1.7
   69.20 +     */
   69.21 +    public SecondaryLoop createSecondaryLoop() {
   69.22 +        return createSecondaryLoop(null, null, 0);
   69.23 +    }
   69.24 +
   69.25 +    SecondaryLoop createSecondaryLoop(Conditional cond, EventFilter filter, long interval) {
   69.26 +        pushPopLock.lock();
   69.27 +        try {
   69.28 +            if (nextQueue != null) {
   69.29 +                // Forward the request to the top of EventQueue stack
   69.30 +                return nextQueue.createSecondaryLoop(cond, filter, interval);
   69.31 +            }
   69.32 +            if (dispatchThread == null) {
   69.33 +                initDispatchThread();
   69.34 +            }
   69.35 +            return new WaitDispatchSupport(dispatchThread, cond, filter, interval);
   69.36 +        } finally {
   69.37 +            pushPopLock.unlock();
   69.38 +        }
   69.39 +    }
   69.40 +
   69.41 +    /**
   69.42       * Returns true if the calling thread is
   69.43       * {@link Toolkit#getSystemEventQueue the current AWT EventQueue}'s
   69.44       * dispatch thread. Use this method to ensure that a particular
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/src/share/classes/java/awt/SecondaryLoop.java	Fri Sep 24 16:41:32 2010 -0700
    70.3 @@ -0,0 +1,147 @@
    70.4 +/*
    70.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    70.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    70.7 + *
    70.8 + * This code is free software; you can redistribute it and/or modify it
    70.9 + * under the terms of the GNU General Public License version 2 only, as
   70.10 + * published by the Free Software Foundation.  Oracle designates this
   70.11 + * particular file as subject to the "Classpath" exception as provided
   70.12 + * by Oracle in the LICENSE file that accompanied this code.
   70.13 + *
   70.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   70.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   70.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   70.17 + * version 2 for more details (a copy is included in the LICENSE file that
   70.18 + * accompanied this code).
   70.19 + *
   70.20 + * You should have received a copy of the GNU General Public License version
   70.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   70.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   70.23 + *
   70.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   70.25 + * or visit www.oracle.com if you need additional information or have any
   70.26 + * questions.
   70.27 + */
   70.28 +
   70.29 +package java.awt;
   70.30 +
   70.31 +/**
   70.32 + * A helper interface to run the nested event loop.
   70.33 + * <p>
   70.34 + * Objects that implement this interface are created with the
   70.35 + * {@link EventQueue#createSecondaryLoop} method. The interface
   70.36 + * provides two methods, {@link enter} and {@link exit},
   70.37 + * which can be used to start and stop the event loop.
   70.38 + * <p>
   70.39 + * When the {@link enter} method is called, the current
   70.40 + * thread is blocked until the loop is terminated by the
   70.41 + * {@link exit} method. Also, a new event loop is started
   70.42 + * on the event dispatch thread, which may or may not be
   70.43 + * the current thread. The loop can be terminated on any
   70.44 + * thread by calling its {@link exit} method. After the
   70.45 + * loop is terminated, the {@code SecondaryLoop} object can
   70.46 + * be reused to run a new nested event loop.
   70.47 + * <p>
   70.48 + * A typical use case of applying this interface is AWT
   70.49 + * and Swing modal dialogs. When a modal dialog is shown on
   70.50 + * the event dispatch thread, it enters a new secondary loop.
   70.51 + * Later, when the dialog is hidden or disposed, it exits
   70.52 + * the loop, and the thread continues its execution.
   70.53 + * <p>
   70.54 + * The following example illustrates a simple use case of
   70.55 + * secondary loops:
   70.56 + *
   70.57 + * <pre>
   70.58 + *   SecondaryLoop loop;
   70.59 + *
   70.60 + *   JButton jButton = new JButton("Button");
   70.61 + *   jButton.addActionListener(new ActionListener() {
   70.62 + *       {@code @Override}
   70.63 + *       public void actionPerformed(ActionEvent e) {
   70.64 + *           Toolkit tk = Toolkit.getDefaultToolkit();
   70.65 + *           EventQueue eq = tk.getSystemEventQueue();
   70.66 + *           loop = eq.createSecondaryLoop();
   70.67 + *
   70.68 + *           // Spawn a new thread to do the work
   70.69 + *           Thread worker = new WorkerThread();
   70.70 + *           worker.start();
   70.71 + *
   70.72 + *           // Enter the loop to block the current event
   70.73 + *           // handler, but leave UI responsive
   70.74 + *           if (!loop.enter()) {
   70.75 + *               // Report an error
   70.76 + *           }
   70.77 + *       }
   70.78 + *   });
   70.79 + *
   70.80 + *   class WorkerThread extends Thread {
   70.81 + *       {@code @Override}
   70.82 + *       public void run() {
   70.83 + *           // Perform calculations
   70.84 + *           doSomethingUseful();
   70.85 + *
   70.86 + *           // Exit the loop
   70.87 + *           loop.exit();
   70.88 + *       }
   70.89 + *   }
   70.90 + * </pre>
   70.91 + *
   70.92 + * @see Dialog#show
   70.93 + * @see EventQueue#createSecondaryLoop
   70.94 + * @see Toolkit#getSystemEventQueue
   70.95 + *
   70.96 + * @author Anton Tarasov, Artem Ananiev
   70.97 + *
   70.98 + * @since 1.7
   70.99 + */
  70.100 +public interface SecondaryLoop {
  70.101 +
  70.102 +    /**
  70.103 +     * Blocks the execution of the current thread and enters a new
  70.104 +     * secondary event loop on the event dispatch thread.
  70.105 +     * <p>
  70.106 +     * This method can be called by any thread including the event
  70.107 +     * dispatch thread. This thread will be blocked until the {@link
  70.108 +     * exit} method is called or the loop is terminated. A new
  70.109 +     * secondary loop will be created on the event dispatch thread
  70.110 +     * for dispatching events in either case.
  70.111 +     * <p>
  70.112 +     * This method can only start one new event loop at a time per
  70.113 +     * object. If a secondary event loop has already been started
  70.114 +     * by this object and is currently still running, this method
  70.115 +     * returns {@code false} to indicate that it was not successful
  70.116 +     * in starting a new event loop. Otherwise, this method blocks
  70.117 +     * the calling thread and later returns {@code true} when the
  70.118 +     * new event loop is terminated. At such time, this object can
  70.119 +     * again be used to start another new event loop.
  70.120 +     *
  70.121 +     * @return {@code true} after termination of the secondary loop,
  70.122 +     *         if the secondary loop was started by this call,
  70.123 +     *         {@code false} otherwise
  70.124 +     */
  70.125 +    public boolean enter();
  70.126 +
  70.127 +    /**
  70.128 +     * Unblocks the execution of the thread blocked by the {@link
  70.129 +     * enter} method and exits the secondary loop.
  70.130 +     * <p>
  70.131 +     * This method resumes the thread that called the {@link enter}
  70.132 +     * method and exits the secondary loop that was created when
  70.133 +     * the {@link enter} method was invoked.
  70.134 +     * <p>
  70.135 +     * Note that if any other secondary loop is started while this
  70.136 +     * loop is running, the blocked thread will not resume execution
  70.137 +     * until the nested loop is terminated.
  70.138 +     * <p>
  70.139 +     * If this secondary loop has not been started with the {@link
  70.140 +     * enter} method, or this secondary loop has already finished
  70.141 +     * with the {@link exit} method, this method returns {@code
  70.142 +     * false}, otherwise {@code true} is returned.
  70.143 +     *
  70.144 +     * @return {@code true} if this loop was previously started and
  70.145 +     *         has not yet been finished with the {@link exit} method,
  70.146 +     *         {@code false} otherwise
  70.147 +     */
  70.148 +    public boolean exit();
  70.149 +
  70.150 +}
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/src/share/classes/java/awt/WaitDispatchSupport.java	Fri Sep 24 16:41:32 2010 -0700
    71.3 @@ -0,0 +1,302 @@
    71.4 +/*
    71.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    71.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    71.7 + *
    71.8 + * This code is free software; you can redistribute it and/or modify it
    71.9 + * under the terms of the GNU General Public License version 2 only, as
   71.10 + * published by the Free Software Foundation.  Oracle designates this
   71.11 + * particular file as subject to the "Classpath" exception as provided
   71.12 + * by Oracle in the LICENSE file that accompanied this code.
   71.13 + *
   71.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   71.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   71.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   71.17 + * version 2 for more details (a copy is included in the LICENSE file that
   71.18 + * accompanied this code).
   71.19 + *
   71.20 + * You should have received a copy of the GNU General Public License version
   71.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   71.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   71.23 + *
   71.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   71.25 + * or visit www.oracle.com if you need additional information or have any
   71.26 + * questions.
   71.27 + */
   71.28 +
   71.29 +package java.awt;
   71.30 +
   71.31 +import java.util.Timer;
   71.32 +import java.util.TimerTask;
   71.33 +import java.util.concurrent.atomic.AtomicBoolean;
   71.34 +
   71.35 +import java.security.PrivilegedAction;
   71.36 +import java.security.AccessController;
   71.37 +
   71.38 +import sun.awt.PeerEvent;
   71.39 +
   71.40 +import sun.util.logging.PlatformLogger;
   71.41 +
   71.42 +/**
   71.43 + * This utility class is used to suspend execution on a thread
   71.44 + * while still allowing {@code EventDispatchThread} to dispatch events.
   71.45 + * The API methods of the class are thread-safe.
   71.46 + *
   71.47 + * @author Anton Tarasov, Artem Ananiev
   71.48 + *
   71.49 + * @since 1.7
   71.50 + */
   71.51 +class WaitDispatchSupport implements SecondaryLoop {
   71.52 +
   71.53 +    private final static PlatformLogger log =
   71.54 +        PlatformLogger.getLogger("java.awt.event.WaitDispatchSupport");
   71.55 +
   71.56 +    private EventDispatchThread dispatchThread;
   71.57 +    private EventFilter filter;
   71.58 +
   71.59 +    private volatile Conditional extCondition;
   71.60 +    private volatile Conditional condition;
   71.61 +
   71.62 +    private long interval;
   71.63 +    // Use a shared daemon timer to serve all the WaitDispatchSupports
   71.64 +    private static Timer timer;
   71.65 +    // When this WDS expires, we cancel the timer task leaving the
   71.66 +    // shared timer up and running
   71.67 +    private TimerTask timerTask;
   71.68 +
   71.69 +    private AtomicBoolean keepBlockingEDT = new AtomicBoolean(false);
   71.70 +    private AtomicBoolean keepBlockingCT = new AtomicBoolean(false);
   71.71 +
   71.72 +    private static synchronized void initializeTimer() {
   71.73 +        if (timer == null) {
   71.74 +            timer = new Timer("AWT-WaitDispatchSupport-Timer", true);
   71.75 +        }
   71.76 +    }
   71.77 +
   71.78 +    /**
   71.79 +     * Creates a {@code WaitDispatchSupport} instance to
   71.80 +     * serve the given event dispatch thread.
   71.81 +     *
   71.82 +     * @param dispatchThread An event dispatch thread that
   71.83 +     *        should not stop dispatching events while waiting
   71.84 +     *
   71.85 +     * @since 1.7
   71.86 +     */
   71.87 +    public WaitDispatchSupport(EventDispatchThread dispatchThread) {
   71.88 +        this(dispatchThread, null);
   71.89 +    }
   71.90 +
   71.91 +    /**
   71.92 +     * Creates a {@code WaitDispatchSupport} instance to
   71.93 +     * serve the given event dispatch thread.
   71.94 +     *
   71.95 +     * @param dispatchThread An event dispatch thread that
   71.96 +     *        should not stop dispatching events while waiting
   71.97 +     * @param extCondition A conditional object used to determine
   71.98 +     *        if the loop should be terminated
   71.99 +     *
  71.100 +     * @since 1.7
  71.101 +     */
  71.102 +    public WaitDispatchSupport(EventDispatchThread dispatchThread,
  71.103 +                               Conditional extCond)
  71.104 +    {
  71.105 +        if (dispatchThread == null) {
  71.106 +            throw new IllegalArgumentException("The dispatchThread can not be null");
  71.107 +        }
  71.108 +
  71.109 +        this.dispatchThread = dispatchThread;
  71.110 +        this.extCondition = extCond;
  71.111 +        this.condition = new Conditional() {
  71.112 +            @Override
  71.113 +            public boolean evaluate() {
  71.114 +                if (log.isLoggable(PlatformLogger.FINEST)) {
  71.115 +                    log.finest("evaluate(): blockingEDT=" + keepBlockingEDT.get() +
  71.116 +                               ", blockingCT=" + keepBlockingCT.get());
  71.117 +                }
  71.118 +                boolean extEvaluate =
  71.119 +                    (extCondition != null) ? extCondition.evaluate() : true;
  71.120 +                if (!keepBlockingEDT.get() || !extEvaluate) {
  71.121 +                    if (timerTask != null) {
  71.122 +                        timerTask.cancel();
  71.123 +                        timerTask = null;
  71.124 +                    }
  71.125 +                    return false;
  71.126 +                }
  71.127 +                return true;
  71.128 +            }
  71.129 +        };
  71.130 +    }
  71.131 +
  71.132 +    /**
  71.133 +     * Creates a {@code WaitDispatchSupport} instance to
  71.134 +     * serve the given event dispatch thread.
  71.135 +     * <p>
  71.136 +     * The {@link EventFilter} is set on the {@code dispatchThread}
  71.137 +     * while waiting. The filter is removed on completion of the
  71.138 +     * waiting process.
  71.139 +     * <p>
  71.140 +     *
  71.141 +     *
  71.142 +     * @param dispatchThread An event dispatch thread that
  71.143 +     *        should not stop dispatching events while waiting
  71.144 +     * @param filter {@code EventFilter} to be set
  71.145 +     * @param interval A time interval to wait for. Note that
  71.146 +     *        when the waiting process takes place on EDT
  71.147 +     *        there is no guarantee to stop it in the given time
  71.148 +     *
  71.149 +     * @since 1.7
  71.150 +     */
  71.151 +    public WaitDispatchSupport(EventDispatchThread dispatchThread,
  71.152 +                               Conditional extCondition,
  71.153 +                               EventFilter filter, long interval)
  71.154 +    {
  71.155 +        this(dispatchThread, extCondition);
  71.156 +        this.filter = filter;
  71.157 +        if (interval < 0) {
  71.158 +            throw new IllegalArgumentException("The interval value must be >= 0");
  71.159 +        }
  71.160 +        this.interval = interval;
  71.161 +        if (interval != 0) {
  71.162 +            initializeTimer();
  71.163 +        }
  71.164 +    }
  71.165 +
  71.166 +    /**
  71.167 +     * @inheritDoc
  71.168 +     */
  71.169 +    @Override
  71.170 +    public boolean enter() {
  71.171 +        log.fine("enter(): blockingEDT=" + keepBlockingEDT.get() +
  71.172 +                 ", blockingCT=" + keepBlockingCT.get());
  71.173 +
  71.174 +        if (!keepBlockingEDT.compareAndSet(false, true)) {
  71.175 +            log.fine("The secondary loop is already running, aborting");
  71.176 +            return false;
  71.177 +        }
  71.178 +
  71.179 +        final Runnable run = new Runnable() {
  71.180 +            public void run() {
  71.181 +                log.fine("Starting a new event pump");
  71.182 +                if (filter == null) {
  71.183 +                    dispatchThread.pumpEvents(condition);
  71.184 +                } else {
  71.185 +                    dispatchThread.pumpEventsForFilter(condition, filter);
  71.186 +                }
  71.187 +            }
  71.188 +        };
  71.189 +
  71.190 +        // We have two mechanisms for blocking: if we're on the
  71.191 +        // dispatch thread, start a new event pump; if we're
  71.192 +        // on any other thread, call wait() on the treelock
  71.193 +
  71.194 +        Thread currentThread = Thread.currentThread();
  71.195 +        if (currentThread == dispatchThread) {
  71.196 +            log.finest("On dispatch thread: " + dispatchThread);
  71.197 +            if (interval != 0) {
  71.198 +                log.finest("scheduling the timer for " + interval + " ms");
  71.199 +                timer.schedule(timerTask = new TimerTask() {
  71.200 +                    @Override
  71.201 +                    public void run() {
  71.202 +                        if (keepBlockingEDT.compareAndSet(true, false)) {
  71.203 +                            wakeupEDT();
  71.204 +                        }
  71.205 +                    }
  71.206 +                }, interval);
  71.207 +            }
  71.208 +            // Dispose SequencedEvent we are dispatching on the the current
  71.209 +            // AppContext, to prevent us from hang - see 4531693 for details
  71.210 +            SequencedEvent currentSE = KeyboardFocusManager.
  71.211 +                getCurrentKeyboardFocusManager().getCurrentSequencedEvent();
  71.212 +            if (currentSE != null) {
  71.213 +                log.fine("Dispose current SequencedEvent: " + currentSE);
  71.214 +                currentSE.dispose();
  71.215 +            }
  71.216 +            // In case the exit() method is called before starting
  71.217 +            // new event pump it will post the waking event to EDT.
  71.218 +            // The event will be handled after the the new event pump
  71.219 +            // starts. Thus, the enter() method will not hang.
  71.220 +            //
  71.221 +            // Event pump should be privileged. See 6300270.
  71.222 +            AccessController.doPrivileged(new PrivilegedAction() {
  71.223 +                public Object run() {
  71.224 +                    run.run();
  71.225 +                    return null;
  71.226 +                }
  71.227 +            });
  71.228 +        } else {
  71.229 +            log.finest("On non-dispatch thread: " + currentThread);
  71.230 +            synchronized (getTreeLock()) {
  71.231 +                if (filter != null) {
  71.232 +                    dispatchThread.addEventFilter(filter);
  71.233 +                }
  71.234 +                try {
  71.235 +                    EventQueue eq = dispatchThread.getEventQueue();
  71.236 +                    eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT));
  71.237 +                    keepBlockingCT.set(true);
  71.238 +                    if (interval > 0) {
  71.239 +                        long currTime = System.currentTimeMillis();
  71.240 +                        while (keepBlockingCT.get() &&
  71.241 +                               ((extCondition != null) ? extCondition.evaluate() : true) &&
  71.242 +                               (currTime + interval > System.currentTimeMillis()))
  71.243 +                        {
  71.244 +                            getTreeLock().wait(interval);
  71.245 +                        }
  71.246 +                    } else {
  71.247 +                        while (keepBlockingCT.get() &&
  71.248 +                               ((extCondition != null) ? extCondition.evaluate() : true))
  71.249 +                        {
  71.250 +                            getTreeLock().wait();
  71.251 +                        }
  71.252 +                    }
  71.253 +                    log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get());
  71.254 +                } catch (InterruptedException e) {
  71.255 +                    log.fine("Exception caught while waiting: " + e);
  71.256 +                } finally {
  71.257 +                    if (filter != null) {
  71.258 +                        dispatchThread.removeEventFilter(filter);
  71.259 +                    }
  71.260 +                }
  71.261 +                // If the waiting process has been stopped because of the
  71.262 +                // time interval passed or an exception occurred, the state
  71.263 +                // should be changed
  71.264 +                keepBlockingEDT.set(false);
  71.265 +                keepBlockingCT.set(false);
  71.266 +            }
  71.267 +        }
  71.268 +
  71.269 +        return true;
  71.270 +    }
  71.271 +
  71.272 +    /**
  71.273 +     * @inheritDoc
  71.274 +     */
  71.275 +    public boolean exit() {
  71.276 +        log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() +
  71.277 +                 ", blockingCT=" + keepBlockingCT.get());
  71.278 +        if (keepBlockingEDT.compareAndSet(true, false)) {
  71.279 +            wakeupEDT();
  71.280 +            return true;
  71.281 +        }
  71.282 +        return false;
  71.283 +    }
  71.284 +
  71.285 +    private final static Object getTreeLock() {
  71.286 +        return Component.LOCK;
  71.287 +    }
  71.288 +
  71.289 +    private final Runnable wakingRunnable = new Runnable() {
  71.290 +        public void run() {
  71.291 +            log.fine("Wake up EDT");
  71.292 +            synchronized (getTreeLock()) {
  71.293 +                keepBlockingCT.set(false);
  71.294 +                getTreeLock().notifyAll();
  71.295 +            }
  71.296 +            log.fine("Wake up EDT done");
  71.297 +        }
  71.298 +    };
  71.299 +
  71.300 +    private void wakeupEDT() {
  71.301 +        log.finest("wakeupEDT(): EDT == " + dispatchThread);
  71.302 +        EventQueue eq = dispatchThread.getEventQueue();
  71.303 +        eq.postEvent(new PeerEvent(this, wakingRunnable, PeerEvent.PRIORITY_EVENT));
  71.304 +    }
  71.305 +}
    72.1 --- a/src/share/classes/java/lang/AutoCloseable.java	Thu Sep 23 17:33:40 2010 -0700
    72.2 +++ b/src/share/classes/java/lang/AutoCloseable.java	Fri Sep 24 16:41:32 2010 -0700
    72.3 @@ -34,8 +34,8 @@
    72.4  public interface AutoCloseable {
    72.5      /**
    72.6       * Close this resource, relinquishing any underlying resources.
    72.7 -     * This method is invoked automatically by the automatic resource
    72.8 -     * management block construct.
    72.9 +     * This method is invoked automatically by the {@code
   72.10 +     * try}-with-resources statement.
   72.11       *
   72.12       * <p>Classes implementing this method are strongly encouraged to
   72.13       * be declared to throw more specific exceptions (or no exception
    73.1 --- a/src/share/classes/java/lang/Character.java	Thu Sep 23 17:33:40 2010 -0700
    73.2 +++ b/src/share/classes/java/lang/Character.java	Fri Sep 24 16:41:32 2010 -0700
    73.3 @@ -595,7 +595,6 @@
    73.4          /**
    73.5           * Constructs a new <code>Subset</code> instance.
    73.6           *
    73.7 -         * @exception NullPointerException if name is <code>null</code>
    73.8           * @param  name  The name of this subset
    73.9           * @exception NullPointerException if name is <code>null</code>
   73.10           */
    74.1 --- a/src/share/classes/java/lang/ClassLoader.java	Thu Sep 23 17:33:40 2010 -0700
    74.2 +++ b/src/share/classes/java/lang/ClassLoader.java	Fri Sep 24 16:41:32 2010 -0700
    74.3 @@ -823,7 +823,7 @@
    74.4       * </tt></blockquote>
    74.5       *
    74.6       * @param  name
    74.7 -     *         The expected <a href="#name">binary name</a. of the class, or
    74.8 +     *         The expected <a href="#name">binary name</a>. of the class, or
    74.9       *         <tt>null</tt> if not known
   74.10       *
   74.11       * @param  b
    75.1 --- a/src/share/classes/java/lang/Object.java	Thu Sep 23 17:33:40 2010 -0700
    75.2 +++ b/src/share/classes/java/lang/Object.java	Fri Sep 24 16:41:32 2010 -0700
    75.3 @@ -189,7 +189,9 @@
    75.4       * specific cloning operation. First, if the class of this object does
    75.5       * not implement the interface {@code Cloneable}, then a
    75.6       * {@code CloneNotSupportedException} is thrown. Note that all arrays
    75.7 -     * are considered to implement the interface {@code Cloneable}.
    75.8 +     * are considered to implement the interface {@code Cloneable} and that
    75.9 +     * the return type of the {@code clone} method of an array type {@code T[]}
   75.10 +     * is {@code T[]} where T is any reference or primitive type.
   75.11       * Otherwise, this method creates a new instance of the class of this
   75.12       * object and initializes all its fields with exactly the contents of
   75.13       * the corresponding fields of this object, as if by assignment; the
    76.1 --- a/src/share/classes/java/lang/Throwable.java	Thu Sep 23 17:33:40 2010 -0700
    76.2 +++ b/src/share/classes/java/lang/Throwable.java	Fri Sep 24 16:41:32 2010 -0700
    76.3 @@ -498,8 +498,8 @@
    76.4       * }
    76.5       * </pre>
    76.6       * As of release 7, the platform supports the notion of
    76.7 -     * <i>suppressed exceptions</i> (in conjunction with automatic
    76.8 -     * resource management blocks). Any exceptions that were
    76.9 +     * <i>suppressed exceptions</i> (in conjunction with the {@code
   76.10 +     * try}-with-resources statement). Any exceptions that were
   76.11       * suppressed in order to deliver an exception are printed out
   76.12       * beneath the stack trace.  The format of this information
   76.13       * depends on the implementation, but the following example may be
   76.14 @@ -805,7 +805,7 @@
   76.15  
   76.16      /**
   76.17       * Adds the specified exception to the list of exceptions that
   76.18 -     * were suppressed, typically by the automatic resource management
   76.19 +     * were suppressed, typically by the {@code try}-with-resources
   76.20       * statement, in order to deliver this exception.
   76.21       *
   76.22       * <p>Note that when one exception {@linkplain
   76.23 @@ -839,7 +839,7 @@
   76.24  
   76.25      /**
   76.26       * Returns an array containing all of the exceptions that were
   76.27 -     * suppressed, typically by the automatic resource management
   76.28 +     * suppressed, typically by the {@code try}-with-resources
   76.29       * statement, in order to deliver this exception.
   76.30       *
   76.31       * @return an array containing all of the exceptions that were
    77.1 --- a/src/share/classes/java/lang/reflect/Constructor.java	Thu Sep 23 17:33:40 2010 -0700
    77.2 +++ b/src/share/classes/java/lang/reflect/Constructor.java	Fri Sep 24 16:41:32 2010 -0700
    77.3 @@ -166,8 +166,7 @@
    77.4  
    77.5      /**
    77.6       * Returns the name of this constructor, as a string.  This is
    77.7 -     * always the same as the simple name of the constructor's declaring
    77.8 -     * class.
    77.9 +     * the binary name of the constructor's declaring class.
   77.10       */
   77.11      public String getName() {
   77.12          return getDeclaringClass().getName();
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/src/share/classes/java/net/SdpSocketImpl.java	Fri Sep 24 16:41:32 2010 -0700
    78.3 @@ -0,0 +1,49 @@
    78.4 +/*
    78.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    78.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    78.7 + *
    78.8 + * This code is free software; you can redistribute it and/or modify it
    78.9 + * under the terms of the GNU General Public License version 2 only, as
   78.10 + * published by the Free Software Foundation.  Oracle designates this
   78.11 + * particular file as subject to the "Classpath" exception as provided
   78.12 + * by Oracle in the LICENSE file that accompanied this code.
   78.13 + *
   78.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   78.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   78.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   78.17 + * version 2 for more details (a copy is included in the LICENSE file that
   78.18 + * accompanied this code).
   78.19 + *
   78.20 + * You should have received a copy of the GNU General Public License version
   78.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   78.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   78.23 + *
   78.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   78.25 + * or visit www.oracle.com if you need additional information or have any
   78.26 + * questions.
   78.27 + */
   78.28 +
   78.29 +package java.net;
   78.30 +
   78.31 +import java.io.IOException;
   78.32 +import java.io.FileDescriptor;
   78.33 +
   78.34 +import sun.net.sdp.SdpSupport;
   78.35 +
   78.36 +/**
   78.37 + * SocketImpl that supports the SDP protocol
   78.38 + */
   78.39 +class SdpSocketImpl extends PlainSocketImpl {
   78.40 +    SdpSocketImpl() { }
   78.41 +
   78.42 +    @Override
   78.43 +    protected void create(boolean stream) throws IOException {
   78.44 +        if (!stream)
   78.45 +            throw new UnsupportedOperationException("Must be a stream socket");
   78.46 +        fd = SdpSupport.createSocket();
   78.47 +        if (socket != null)
   78.48 +            socket.setCreated();
   78.49 +        if (serverSocket != null)
   78.50 +            serverSocket.setCreated();
   78.51 +    }
   78.52 +}
    79.1 --- a/src/share/classes/java/net/ServerSocket.java	Thu Sep 23 17:33:40 2010 -0700
    79.2 +++ b/src/share/classes/java/net/ServerSocket.java	Fri Sep 24 16:41:32 2010 -0700
    79.3 @@ -69,6 +69,15 @@
    79.4      private boolean oldImpl = false;
    79.5  
    79.6      /**
    79.7 +     * Package-private constructor to create a ServerSocket associated with
    79.8 +     * the given SocketImpl.
    79.9 +     */
   79.10 +    ServerSocket(SocketImpl impl) {
   79.11 +        this.impl = impl;
   79.12 +        impl.setServerSocket(this);
   79.13 +    }
   79.14 +
   79.15 +    /**
   79.16       * Creates an unbound server socket.
   79.17       *
   79.18       * @exception IOException IO error when opening the socket.
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/src/share/classes/java/nio/file/DirectoryIteratorException.java	Fri Sep 24 16:41:32 2010 -0700
    80.3 @@ -0,0 +1,87 @@
    80.4 +/*
    80.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    80.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    80.7 + *
    80.8 + * This code is free software; you can redistribute it and/or modify it
    80.9 + * under the terms of the GNU General Public License version 2 only, as
   80.10 + * published by the Free Software Foundation.  Oracle designates this
   80.11 + * particular file as subject to the "Classpath" exception as provided
   80.12 + * by Oracle in the LICENSE file that accompanied this code.
   80.13 + *
   80.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   80.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   80.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   80.17 + * version 2 for more details (a copy is included in the LICENSE file that
   80.18 + * accompanied this code).
   80.19 + *
   80.20 + * You should have received a copy of the GNU General Public License version
   80.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   80.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   80.23 + *
   80.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   80.25 + * or visit www.oracle.com if you need additional information or have any
   80.26 + * questions.
   80.27 + */
   80.28 +
   80.29 +package java.nio.file;
   80.30 +
   80.31 +import java.util.ConcurrentModificationException;
   80.32 +import java.util.Objects;
   80.33 +import java.io.IOException;
   80.34 +import java.io.ObjectInputStream;
   80.35 +import java.io.InvalidObjectException;
   80.36 +
   80.37 +/**
   80.38 + * Runtime exception thrown if an I/O error is encountered when iterating over
   80.39 + * the entries in a directory. The I/O error is retrieved as an {@link
   80.40 + * IOException} using the {@link #getCause() getCause()} method.
   80.41 + *
   80.42 + * @since 1.7
   80.43 + * @see DirectoryStream
   80.44 + */
   80.45 +
   80.46 +public final class DirectoryIteratorException
   80.47 +    extends ConcurrentModificationException
   80.48 +{
   80.49 +    private static final long serialVersionUID = -6012699886086212874L;
   80.50 +
   80.51 +    /**
   80.52 +     * Constructs an instance of this class.
   80.53 +     *
   80.54 +     * @param   cause
   80.55 +     *          the {@code IOException} that caused the directory iteration
   80.56 +     *          to fail
   80.57 +     *
   80.58 +     * @throws  NullPointerException
   80.59 +     *          if the cause is {@code null}
   80.60 +     */
   80.61 +    public DirectoryIteratorException(IOException cause) {
   80.62 +        super(Objects.nonNull(cause));
   80.63 +    }
   80.64 +
   80.65 +    /**
   80.66 +     * Returns the cause of this exception.
   80.67 +     *
   80.68 +     * @return  the cause
   80.69 +     */
   80.70 +    @Override
   80.71 +    public IOException getCause() {
   80.72 +        return (IOException)super.getCause();
   80.73 +    }
   80.74 +
   80.75 +    /**
   80.76 +     * Called to read the object from a stream.
   80.77 +     *
   80.78 +     * @throws  InvalidObjectException
   80.79 +     *          if the object is invalid or has a cause that is not
   80.80 +     *          an {@code IOException}
   80.81 +     */
   80.82 +    private void readObject(ObjectInputStream s)
   80.83 +        throws IOException, ClassNotFoundException
   80.84 +    {
   80.85 +        s.defaultReadObject();
   80.86 +        Throwable cause = super.getCause();
   80.87 +        if (!(cause instanceof IOException))
   80.88 +            throw new InvalidObjectException("Cause must be an IOException");
   80.89 +    }
   80.90 +}
    81.1 --- a/src/share/classes/java/nio/file/DirectoryStream.java	Thu Sep 23 17:33:40 2010 -0700
    81.2 +++ b/src/share/classes/java/nio/file/DirectoryStream.java	Fri Sep 24 16:41:32 2010 -0700
    81.3 @@ -31,60 +31,84 @@
    81.4  
    81.5  /**
    81.6   * An object to iterate over the entries in a directory. A directory stream
    81.7 - * allows for convenient use of the for-each construct:
    81.8 + * allows for the convenient use of the for-each construct to iterate over a
    81.9 + * directory.
   81.10 + *
   81.11 + * <p> <b> While {@code DirectoryStream} extends {@code Iterable}, it is not a
   81.12 + * general-purpose {@code Iterable} as it supports only a single {@code
   81.13 + * Iterator}; invoking the {@link #iterator iterator} method to obtain a second
   81.14 + * or subsequent iterator throws {@code IllegalStateException}. </b>
   81.15 + *
   81.16 + * <p> An important property of the directory stream's {@code Iterator} is that
   81.17 + * its {@link Iterator#hasNext() hasNext} method is guaranteed to read-ahead by
   81.18 + * at least one element. If {@code hasNext} method returns {@code true}, and is
   81.19 + * followed by a call to the {@code next} method, it is guaranteed that the
   81.20 + * {@code next} method will not throw an exception due to an I/O error, or
   81.21 + * because the stream has been {@link #close closed}. The {@code Iterator} does
   81.22 + * not support the {@link Iterator#remove remove} operation.
   81.23 + *
   81.24 + * <p> A {@code DirectoryStream} is opened upon creation and is closed by
   81.25 + * invoking the {@code close} method. Closing a directory stream releases any
   81.26 + * resources associated with the stream. Failure to close the stream may result
   81.27 + * in a resource leak. The try-with-resources statement provides a useful
   81.28 + * construct to ensure that the stream is closed:
   81.29   * <pre>
   81.30   *   Path dir = ...
   81.31 - *   DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream();
   81.32 - *   try {
   81.33 + *   try (DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream()) {
   81.34   *       for (Path entry: stream) {
   81.35 - *         ..
   81.36 + *           ...
   81.37   *       }
   81.38 - *   } finally {
   81.39 - *       stream.close();
   81.40   *   }
   81.41   * </pre>
   81.42   *
   81.43 - * <p><b> A {@code DirectoryStream} is not a general-purpose {@code Iterable}.
   81.44 - * While this interface extends {@code Iterable}, the {@code iterator} method
   81.45 - * may only be invoked once to obtain the iterator; a second, or subsequent,
   81.46 - * call to the {@code iterator} method throws {@code IllegalStateException}. </b>
   81.47 - *
   81.48 - * <p> A {@code DirectoryStream} is opened upon creation and is closed by
   81.49 - * invoking the {@link #close close} method. Closing the directory stream
   81.50 - * releases any resources associated with the stream. Once a directory stream
   81.51 - * is closed, all further method invocations on the iterator throw {@link
   81.52 - * java.util.ConcurrentModificationException} with cause {@link
   81.53 - * ClosedDirectoryStreamException}.
   81.54 + * <p> Once a directory stream is closed, then further access to the directory,
   81.55 + * using the {@code Iterator}, behaves as if the end of stream has been reached.
   81.56 + * Due to read-ahead, the {@code Iterator} may return one or more elements
   81.57 + * after the directory stream has been closed. Once these buffered elements
   81.58 + * have been read, then subsequent calls to the {@code hasNext} method returns
   81.59 + * {@code false}, and subsequent calls to the {@code next} method will throw
   81.60 + * {@code NoSuchElementException}.
   81.61   *
   81.62   * <p> A directory stream is not required to be <i>asynchronously closeable</i>.
   81.63   * If a thread is blocked on the directory stream's iterator reading from the
   81.64   * directory, and another thread invokes the {@code close} method, then the
   81.65   * second thread may block until the read operation is complete.
   81.66   *
   81.67 - * <p> The {@link Iterator#hasNext() hasNext} and {@link Iterator#next() next}
   81.68 - * methods can encounter an I/O error when iterating over the directory in which
   81.69 - * case {@code ConcurrentModificationException} is thrown with cause
   81.70 - * {@link java.io.IOException}. The {@code hasNext} method is guaranteed to
   81.71 - * read-ahead by at least one element. This means that if the {@code hasNext}
   81.72 - * method returns {@code true} and is followed by a call to the {@code next}
   81.73 - * method then it is guaranteed not to fail with a {@code
   81.74 - * ConcurrentModificationException}.
   81.75 + * <p> If an I/O error is encountered when accessing the directory then it
   81.76 + * causes the {@code Iterator}'s {@code hasNext} or {@code next} methods to
   81.77 + * throw {@link DirectoryIteratorException} with the {@link IOException} as the
   81.78 + * cause. As stated above, the {@code hasNext} method is guaranteed to
   81.79 + * read-ahead by at least one element. This means that if {@code hasNext} method
   81.80 + * returns {@code true}, and is followed by a call to the {@code next} method,
   81.81 + * then it is guaranteed that the {@code next} method will not fail with a
   81.82 + * {@code DirectoryIteratorException}.
   81.83   *
   81.84   * <p> The elements returned by the iterator are in no specific order. Some file
   81.85   * systems maintain special links to the directory itself and the directory's
   81.86   * parent directory. Entries representing these links are not returned by the
   81.87   * iterator.
   81.88   *
   81.89 - * <p> The iterator's {@link Iterator#remove() remove} method removes the
   81.90 - * directory entry for the last element returned by the iterator, as if by
   81.91 - * invoking the {@link Path#delete delete} method. If an I/O error or
   81.92 - * security exception occurs then {@code ConcurrentModificationException} is
   81.93 - * thrown with the cause.
   81.94 - *
   81.95   * <p> The iterator is <i>weakly consistent</i>. It is thread safe but does not
   81.96   * freeze the directory while iterating, so it may (or may not) reflect updates
   81.97   * to the directory that occur after the {@code DirectoryStream} is created.
   81.98   *
   81.99 + * <p> <b>Usage Examples:</b>
  81.100 + * Suppose we want a list of the source files in a directory. This example uses
  81.101 + * both the for-each and try-with-resources constructs.
  81.102 + * <pre>
  81.103 + *   List&lt;Path&gt; listSourceFiles(Path dir) throws IOException {
  81.104 + *       List&lt;Path&gt; result = new ArrayList&lt;Path&gt;();
  81.105 + *       try (DirectoryStream&lt;Path&gt; stream = dir.newDirectoryStream("*.{c,h,cpp,hpp,java}")) {
  81.106 + *           for (Path entry: stream) {
  81.107 + *               result.add(entry);
  81.108 + *           }
  81.109 + *       } catch (DirectoryIteratorException ex) {
  81.110 + *           // I/O error encounted during the iteration, the cause is an IOException
  81.111 + *           throw ex.getCause();
  81.112 + *       }
  81.113 + *       return result;
  81.114 + *   }
  81.115 + * </pre>
  81.116   * @param   <T>     The type of element returned by the iterator
  81.117   *
  81.118   * @since 1.7
    82.1 --- a/src/share/classes/java/nio/file/Path.java	Thu Sep 23 17:33:40 2010 -0700
    82.2 +++ b/src/share/classes/java/nio/file/Path.java	Fri Sep 24 16:41:32 2010 -0700
    82.3 @@ -984,11 +984,11 @@
    82.4       * directory.
    82.5       *
    82.6       * <p> Where the filter terminates due to an uncaught error or runtime
    82.7 -     * exception then it is propogated to the iterator's {@link Iterator#hasNext()
    82.8 +     * exception then it is propagated to the {@link Iterator#hasNext()
    82.9       * hasNext} or {@link Iterator#next() next} method. Where an {@code
   82.10 -     * IOException} is thrown, it is propogated as a {@link
   82.11 -     * java.util.ConcurrentModificationException} with the {@code
   82.12 -     * IOException} as the cause.
   82.13 +     * IOException} is thrown, it results in the {@code hasNext} or {@code
   82.14 +     * next} method throwing a {@link DirectoryIteratorException} with the
   82.15 +     * {@code IOException} as the cause.
   82.16       *
   82.17       * <p> When an implementation supports operations on entries in the
   82.18       * directory that execute in a race-free manner then the returned directory
    83.1 --- a/src/share/classes/java/nio/file/SecureDirectoryStream.java	Thu Sep 23 17:33:40 2010 -0700
    83.2 +++ b/src/share/classes/java/nio/file/SecureDirectoryStream.java	Fri Sep 24 16:41:32 2010 -0700
    83.3 @@ -47,15 +47,6 @@
    83.4   * newDirectoryStream} method will be a {@code SecureDirectoryStream} and must
    83.5   * be cast to that type in order to invoke the methods defined by this interface.
    83.6   *
    83.7 - * <p> As specified by {@code DirectoryStream}, the iterator's {@link
    83.8 - * java.util.Iterator#remove() remove} method removes the directory entry for
    83.9 - * the last element returned by the iterator. In the case of a {@code
   83.10 - * SecureDirectoryStream} the {@code remove} method behaves as if by invoking
   83.11 - * the {@link #deleteFile deleteFile} or {@link #deleteDirectory deleteDirectory}
   83.12 - * methods defined by this interface. The {@code remove} may require to examine
   83.13 - * the file to determine if the file is a directory, and consequently, it may
   83.14 - * not be atomic with respect to other file system operations.
   83.15 - *
   83.16   * <p> In the case of the default {@link java.nio.file.spi.FileSystemProvider
   83.17   * provider}, and a security manager is set, then the permission checks are
   83.18   * performed using the path obtained by resolving the given relative path
    84.1 --- a/src/share/classes/java/sql/CallableStatement.java	Thu Sep 23 17:33:40 2010 -0700
    84.2 +++ b/src/share/classes/java/sql/CallableStatement.java	Fri Sep 24 16:41:32 2010 -0700
    84.3 @@ -1,5 +1,5 @@
    84.4  /*
    84.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    84.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    84.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    84.8   *
    84.9   * This code is free software; you can redistribute it and/or modify it
   84.10 @@ -2436,4 +2436,64 @@
   84.11       */
   84.12       void setNClob(String parameterName, Reader reader)
   84.13         throws SQLException;
   84.14 +
   84.15 +    //------------------------- JDBC 4.1 -----------------------------------
   84.16 +
   84.17 +
   84.18 +    /**
   84.19 +     *<p>Returns an object representing the value of OUT parameter
   84.20 +     * {@code parameterIndex} and will convert from the
   84.21 +     * SQL type of the parameter to the requested Java data type, if the
   84.22 +     * conversion is supported. If the conversion is not
   84.23 +     * supported or null is specified for the type, a
   84.24 +     * <code>SQLException</code> is thrown.
   84.25 +     *<p>
   84.26 +     * At a minimum, an implementation must support the conversions defined in
   84.27 +     * Appendix B, Table B-3 and conversion of appropriate user defined SQL
   84.28 +     * types to a Java type which implements {@code SQLData}, or {@code Struct}.
   84.29 +     * Additional conversions may be supported and are vendor defined.
   84.30 +     *
   84.31 +     * @param parameterIndex the first parameter is 1, the second is 2, and so on
   84.32 +     * @param type Class representing the Java data type to convert the
   84.33 +     * designated parameter to.
   84.34 +     * @return an instance of {@code type} holding the OUT parameter value
   84.35 +     * @throws SQLException if conversion is not supported, type is null or
   84.36 +     *         another error occurs. The getCause() method of the
   84.37 +     * exception may provide a more detailed exception, for example, if
   84.38 +     * a conversion error occurs
   84.39 +     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
   84.40 +     * this method
   84.41 +     * @since 1.7
   84.42 +     */
   84.43 +     public <T> T getObject(int parameterIndex, Class<T> type) throws SQLException;
   84.44 +
   84.45 +
   84.46 +    /**
   84.47 +     *<p>Returns an object representing the value of OUT parameter
   84.48 +     * {@code parameterName} and will convert from the
   84.49 +     * SQL type of the parameter to the requested Java data type, if the
   84.50 +     * conversion is supported. If the conversion is not
   84.51 +     * supported  or null is specified for the type, a
   84.52 +     * <code>SQLException</code> is thrown.
   84.53 +     *<p>
   84.54 +     * At a minimum, an implementation must support the conversions defined in
   84.55 +     * Appendix B, Table B-3 and conversion of appropriate user defined SQL
   84.56 +     * types to a Java type which implements {@code SQLData}, or {@code Struct}.
   84.57 +     * Additional conversions may be supported and are vendor defined.
   84.58 +     *
   84.59 +     * @param parameterName the name of the parameter
   84.60 +     * @param type Class representing the Java data type to convert
   84.61 +     * the designated parameter to.
   84.62 +     * @return an instance of {@code type} holding the OUT parameter
   84.63 +     * value
   84.64 +     * @throws SQLException if conversion is not supported, type is null or
   84.65 +     *         another error occurs. The getCause() method of the
   84.66 +     * exception may provide a more detailed exception, for example, if
   84.67 +     * a conversion error occurs
   84.68 +     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
   84.69 +     * this method
   84.70 +     * @since 1.7
   84.71 +     */
   84.72 +     public <T> T getObject(String parameterName, Class<T> type) throws SQLException;
   84.73 +
   84.74  }
    85.1 --- a/src/share/classes/java/sql/Connection.java	Thu Sep 23 17:33:40 2010 -0700
    85.2 +++ b/src/share/classes/java/sql/Connection.java	Fri Sep 24 16:41:32 2010 -0700
    85.3 @@ -1,5 +1,5 @@
    85.4  /*
    85.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    85.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    85.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    85.8   *
    85.9   * This code is free software; you can redistribute it and/or modify it
   85.10 @@ -26,6 +26,7 @@
   85.11  package java.sql;
   85.12  
   85.13  import java.util.Properties;
   85.14 +import java.util.concurrent.Executor;
   85.15  
   85.16  /**
   85.17   * <P>A connection (session) with a specific
   85.18 @@ -38,7 +39,7 @@
   85.19   * information is obtained with the <code>getMetaData</code> method.
   85.20   *
   85.21   * <P><B>Note:</B> When configuring a <code>Connection</code>, JDBC applications
   85.22 - *  should use the appropritate <code>Connection</code> method such as
   85.23 + *  should use the appropriate <code>Connection</code> method such as
   85.24   *  <code>setAutoCommit</code> or <code>setTransactionIsolation</code>.
   85.25   *  Applications should not invoke SQL commands directly to change the connection's
   85.26   *   configuration when there is a JDBC method available.  By default a <code>Connection</code> object is in
   85.27 @@ -80,7 +81,7 @@
   85.28   * @see ResultSet
   85.29   * @see DatabaseMetaData
   85.30   */
   85.31 -public interface Connection  extends Wrapper {
   85.32 +public interface Connection  extends Wrapper, AutoCloseable {
   85.33  
   85.34      /**
   85.35       * Creates a <code>Statement</code> object for sending
   85.36 @@ -347,6 +348,13 @@
   85.37       * <P>
   85.38       * If the driver does not support catalogs, it will
   85.39       * silently ignore this request.
   85.40 +     * <p>
   85.41 +     * Calling {@code setCatalog} has no effect on previously created or prepared
   85.42 +     * {@code Statement} objects. It is implementation defined whether a DBMS
   85.43 +     * prepare operation takes place immediately when the {@code Connection}
   85.44 +     * method {@code prepareStatement} or {@code prepareCall} is invoked.
   85.45 +     * For maximum portability, {@code setCatalog} should be called before a
   85.46 +     * {@code Statement} is created or prepared.
   85.47       *
   85.48       * @param catalog the name of a catalog (subspace in this
   85.49       *        <code>Connection</code> object's database) in which to work
   85.50 @@ -598,7 +606,17 @@
   85.51       * <code>Connection</code> object.
   85.52       * Unless the application has added an entry, the type map returned
   85.53       * will be empty.
   85.54 -     *
   85.55 +     * <p>
   85.56 +     * You must invoke <code>setTypeMap</code> after making changes to the
   85.57 +     * <code>Map</code> object returned from
   85.58 +     *  <code>getTypeMap</code> as a JDBC driver may create an internal
   85.59 +     * copy of the <code>Map</code> object passed to <code>setTypeMap</code>:
   85.60 +     * <p>
   85.61 +     * <pre>
   85.62 +     *      Map&lt;String,Class&lt;?&gt;&gt; myMap = con.getTypeMap();
   85.63 +     *      myMap.put("mySchemaName.ATHLETES", Athletes.class);
   85.64 +     *      con.setTypeMap(myMap);
   85.65 +     * </pre>
   85.66       * @return the <code>java.util.Map</code> object associated
   85.67       *         with this <code>Connection</code> object
   85.68       * @exception SQLException if a database access error occurs
   85.69 @@ -614,7 +632,16 @@
   85.70       * Installs the given <code>TypeMap</code> object as the type map for
   85.71       * this <code>Connection</code> object.  The type map will be used for the
   85.72       * custom mapping of SQL structured types and distinct types.
   85.73 -     *
   85.74 +     *<p>
   85.75 +     * You must set the the values for the <code>TypeMap</code> prior to
   85.76 +     * callng <code>setMap</code> as a JDBC driver may create an internal copy
   85.77 +     * of the <code>TypeMap</code>:
   85.78 +     * <p>
   85.79 +     * <pre>
   85.80 +     *      Map myMap&lt;String,Class&lt;?&gt;&gt; = new HashMap&lt;String,Class&lt;?&gt;&gt;();
   85.81 +     *      myMap.put("mySchemaName.ATHLETES", Athletes.class);
   85.82 +     *      con.setTypeMap(myMap);
   85.83 +     * </pre>
   85.84       * @param map the <code>java.util.Map</code> object to install
   85.85       *        as the replacement for this <code>Connection</code>
   85.86       *        object's default type map
   85.87 @@ -1274,4 +1301,186 @@
   85.88    */
   85.89   Struct createStruct(String typeName, Object[] attributes)
   85.90  throws SQLException;
   85.91 +
   85.92 +   //--------------------------JDBC 4.1 -----------------------------
   85.93 +
   85.94 +   /**
   85.95 +    * Sets the given schema name to access.
   85.96 +    * <P>
   85.97 +    * If the driver does not support schemas, it will
   85.98 +    * silently ignore this request.
   85.99 +    * <p>
  85.100 +    * Calling {@code setSchema} has no effect on previously created or prepared
  85.101 +    * {@code Statement} objects. It is implementation defined whether a DBMS
  85.102 +    * prepare operation takes place immediately when the {@code Connection}
  85.103 +    * method {@code prepareStatement} or {@code prepareCall} is invoked.
  85.104 +    * For maximum portability, {@code setSchema} should be called before a
  85.105 +    * {@code Statement} is created or prepared.
  85.106 +    *
  85.107 +    * @param schema the name of a schema  in which to work
  85.108 +    * @exception SQLException if a database access error occurs
  85.109 +    * or this method is called on a closed connection
  85.110 +    * @see #getSchema
  85.111 +    * @since 1.7
  85.112 +    */
  85.113 +    void setSchema(String schema) throws SQLException;
  85.114 +
  85.115 +    /**
  85.116 +     * Retrieves this <code>Connection</code> object's current schema name.
  85.117 +     *
  85.118 +     * @return the current schema name or <code>null</code> if there is none
  85.119 +     * @exception SQLException if a database access error occurs
  85.120 +     * or this method is called on a closed connection
  85.121 +     * @see #setSchema
  85.122 +     * @since 1.7
  85.123 +     */
  85.124 +    String getSchema() throws SQLException;
  85.125 +
  85.126 +    /**
  85.127 +     * Terminates an open connection.  Calling <code>abort</code> results in:
  85.128 +     * <ul>
  85.129 +     * <li>The connection marked as closed
  85.130 +     * <li>Closes any physical connection to the database
  85.131 +     * <li>Releases resources used by the connection
  85.132 +     * <li>Insures that any thread that is currently accessing the connection
  85.133 +     * will either progress to completion or throw an <code>SQLException</code>.
  85.134 +     * </ul>
  85.135 +     * <p>
  85.136 +     * Calling <code>abort</code> marks the connection closed and releases any
  85.137 +     * resources. Calling <code>abort</code> on a closed connection is a
  85.138 +     * no-op.
  85.139 +     * <p>
  85.140 +     * It is possible that the aborting and releasing of the resources that are
  85.141 +     * held by the connection can take an extended period of time.  When the
  85.142 +     * <code>abort</code> method returns, the connection will have been marked as
  85.143 +     * closed and the <code>Executor</code> that was passed as a parameter to abort
  85.144 +     * may still be executing tasks to release resources.
  85.145 +     * <p>
  85.146 +     * This method checks to see that there is an <code>SQLPermission</code>
  85.147 +     * object before allowing the method to proceed.  If a
  85.148 +     * <code>SecurityManager</code> exists and its
  85.149 +     * <code>checkPermission</code> method denies calling <code>abort</code>,
  85.150 +     * this method throws a
  85.151 +     * <code>java.lang.SecurityException</code>.
  85.152 +     * @param executor  The <code>Executor</code>  implementation which will
  85.153 +     * be used by <code>abort</code>.
  85.154 +     * @throws java.sql.SQLException if a database access error occurs or
  85.155 +     * the {@code executor} is {@code null},
  85.156 +     * @throws java.lang.SecurityException if a security manager exists and its
  85.157 +     *    <code>checkPermission</code> method denies calling <code>abort</code>
  85.158 +     * @see SecurityManager#checkPermission
  85.159 +     * @see Executor
  85.160 +     * @since 1.7
  85.161 +     */
  85.162 +    void abort(Executor executor) throws SQLException;
  85.163 +
  85.164 +    /**
  85.165 +     *
  85.166 +     * Sets the maximum period a <code>Connection</code> or
  85.167 +     * objects created from the <code>Connection</code>
  85.168 +     * will wait for the database to reply to any one request. If any
  85.169 +     *  request remains unanswered, the waiting method will
  85.170 +     * return with a <code>SQLException</code>, and the <code>Connection</code>
  85.171 +     * or objects created from the <code>Connection</code>  will be marked as
  85.172 +     * closed. Any subsequent use of
  85.173 +     * the objects, with the exception of the <code>close</code>,
  85.174 +     * <code>isClosed</code> or <code>Connection.isValid</code>
  85.175 +     * methods, will result in  a <code>SQLException</code>.
  85.176 +     * <p>
  85.177 +     * <b>Note</b>: This method is intended to address a rare but serious
  85.178 +     * condition where network partitions can cause threads issuing JDBC calls
  85.179 +     * to hang uninterruptedly in socket reads, until the OS TCP-TIMEOUT
  85.180 +     * (typically 10 minutes). This method is related to the
  85.181 +     * {@link #abort abort() } method which provides an administrator
  85.182 +     * thread a means to free any such threads in cases where the
  85.183 +     * JDBC connection is accessible to the administrator thread.
  85.184 +     * The <code>setNetworkTimeout</code> method will cover cases where
  85.185 +     * there is no administrator thread, or it has no access to the
  85.186 +     * connection. This method is severe in it's effects, and should be
  85.187 +     * given a high enough value so it is never triggered before any more
  85.188 +     * normal timeouts, such as transaction timeouts.
  85.189 +     * <p>
  85.190 +     * JDBC driver implementations  may also choose to support the
  85.191 +     * {@code setNetworkTimeout} method to impose a limit on database
  85.192 +     * response time, in environments where no network is present.
  85.193 +     * <p>
  85.194 +     * Drivers may internally implement some or all of their API calls with
  85.195 +     * multiple internal driver-database transmissions, and it is left to the
  85.196 +     * driver implementation to determine whether the limit will be
  85.197 +     * applied always to the response to the API call, or to any
  85.198 +     * single  request made during the API call.
  85.199 +     * <p>
  85.200 +     *
  85.201 +     * This method can be invoked more than once, such as to set a limit for an
  85.202 +     * area of JDBC code, and to reset to the default on exit from this area.
  85.203 +     * Invocation of this method has no impact on already outstanding
  85.204 +     * requests.
  85.205 +     * <p>
  85.206 +     * The {@code Statement.setQueryTimeout()} timeout value is independent of the
  85.207 +     * timeout value specified in {@code setNetworkTimeout}. If the query timeout
  85.208 +     * expires  before the network timeout then the
  85.209 +     * statement execution will be canceled. If the network is still
  85.210 +     * active the result will be that both the statement and connection
  85.211 +     * are still usable. However if the network timeout expires before
  85.212 +     * the query timeout or if the statement timeout fails due to network
  85.213 +     * problems, the connection will be marked as closed, any resources held by
  85.214 +     * the connection will be released and both the connection and
  85.215 +     * statement will be unusable.
  85.216 +     *<p>
  85.217 +     * When the driver determines that the {@code setNetworkTimeout} timeout
  85.218 +     * value has expired, the JDBC driver marks the connection
  85.219 +     * closed and releases any resources held by the connection.
  85.220 +     * <p>
  85.221 +     *
  85.222 +     * This method checks to see that there is an <code>SQLPermission</code>
  85.223 +     * object before allowing the method to proceed.  If a
  85.224 +     * <code>SecurityManager</code> exists and its
  85.225 +     * <code>checkPermission</code> method denies calling
  85.226 +     * <code>setNetworkTimeout</code>, this method throws a
  85.227 +     * <code>java.lang.SecurityException</code>.
  85.228 +     *
  85.229 +     * @param executor  The <code>Executor</code>  implementation which will
  85.230 +     * be used by <code>setNetworkTimeout</code>.
  85.231 +     * @param milliseconds The time in milliseconds to wait for the database
  85.232 +     * operation
  85.233 +     *  to complete.  If the JDBC driver does not support milliseconds, the
  85.234 +     * JDBC driver will round the value up to the nearest second.  If the
  85.235 +     * timeout period expires before the operation
  85.236 +     * completes, a SQLException will be thrown.
  85.237 +     * A value of 0 indicates that there is not timeout for database operations.
  85.238 +     * @throws java.sql.SQLException if a database access error occurs, this
  85.239 +     * method is called on a closed connection,
  85.240 +     * the {@code executor} is {@code null},
  85.241 +     * or the value specified for <code>seconds</code> is less than 0.
  85.242 +     * @throws java.lang.SecurityException if a security manager exists and its
  85.243 +     *    <code>checkPermission</code> method denies calling
  85.244 +     * <code>setNetworkTimeout</code>.
  85.245 +     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
  85.246 +     * this method
  85.247 +     * @see SecurityManager#checkPermission
  85.248 +     * @see Statement#setQueryTimeout
  85.249 +     * @see #getNetworkTimeout
  85.250 +     * @see #abort
  85.251 +     * @see Executor
  85.252 +     * @since 1.7
  85.253 +     */
  85.254 +    void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException;
  85.255 +
  85.256 +
  85.257 +    /**
  85.258 +     * Retrieves the number of milliseconds the driver will
  85.259 +     * wait for a database request to complete.
  85.260 +     * If the limit is exceeded, a
  85.261 +     * <code>SQLException</code> is thrown.
  85.262 +     *
  85.263 +     * @return the current timeout limit in milliseconds; zero means there is
  85.264 +     *         no limit
  85.265 +     * @throws SQLException if a database access error occurs or
  85.266 +     * this method is called on a closed <code>Connection</code>
  85.267 +     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
  85.268 +     * this method
  85.269 +     * @see #setNetworkTimeout
  85.270 +     * @since 1.7
  85.271 +     */
  85.272 +    int getNetworkTimeout() throws SQLException;
  85.273  }
    86.1 --- a/src/share/classes/java/sql/DatabaseMetaData.java	Thu Sep 23 17:33:40 2010 -0700
    86.2 +++ b/src/share/classes/java/sql/DatabaseMetaData.java	Fri Sep 24 16:41:32 2010 -0700
    86.3 @@ -1,5 +1,5 @@
    86.4  /*
    86.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    86.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    86.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    86.8   *
    86.9   * This code is free software; you can redistribute it and/or modify it
   86.10 @@ -1342,10 +1342,10 @@
   86.11       * defined.
   86.12       *  <LI><B>IS_NULLABLE</B> String  => ISO rules are used to determine the nullability for a column.
   86.13       *       <UL>
   86.14 -     *       <LI> YES           --- if the parameter can include NULLs
   86.15 -     *       <LI> NO            --- if the parameter cannot include NULLs
   86.16 +     *       <LI> YES           --- if the column can include NULLs
   86.17 +     *       <LI> NO            --- if the column cannot include NULLs
   86.18       *       <LI> empty string  --- if the nullability for the
   86.19 -     * parameter is unknown
   86.20 +     * column is unknown
   86.21       *       </UL>
   86.22       *  <LI><B>SPECIFIC_NAME</B> String  => the name which uniquely identifies this procedure within its schema.
   86.23       *  </OL>
   86.24 @@ -1610,17 +1610,17 @@
   86.25       *      (starting at 1)
   86.26       *  <LI><B>IS_NULLABLE</B> String  => ISO rules are used to determine the nullability for a column.
   86.27       *       <UL>
   86.28 -     *       <LI> YES           --- if the parameter can include NULLs
   86.29 -     *       <LI> NO            --- if the parameter cannot include NULLs
   86.30 +     *       <LI> YES           --- if the column can include NULLs
   86.31 +     *       <LI> NO            --- if the column cannot include NULLs
   86.32       *       <LI> empty string  --- if the nullability for the
   86.33 -     * parameter is unknown
   86.34 +     * column is unknown
   86.35       *       </UL>
   86.36 -     *  <LI><B>SCOPE_CATLOG</B> String => catalog of table that is the scope
   86.37 +     *  <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the scope
   86.38       *      of a reference attribute (<code>null</code> if DATA_TYPE isn't REF)
   86.39       *  <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the scope
   86.40       *      of a reference attribute (<code>null</code> if the DATA_TYPE isn't REF)
   86.41       *  <LI><B>SCOPE_TABLE</B> String => table name that this the scope
   86.42 -     *      of a reference attribure (<code>null</code> if the DATA_TYPE isn't REF)
   86.43 +     *      of a reference attribute (<code>null</code> if the DATA_TYPE isn't REF)
   86.44       *  <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated
   86.45       *      Ref type, SQL type from java.sql.Types (<code>null</code> if DATA_TYPE
   86.46       *      isn't DISTINCT or user-generated REF)
   86.47 @@ -1629,11 +1629,16 @@
   86.48       *       <LI> YES           --- if the column is auto incremented
   86.49       *       <LI> NO            --- if the column is not auto incremented
   86.50       *       <LI> empty string  --- if it cannot be determined whether the column is auto incremented
   86.51 -     * parameter is unknown
   86.52 +     *       </UL>
   86.53 +     *   <LI><B>IS_GENERATEDCOLUMN</B> String  => Indicates whether this is a generated column
   86.54 +     *       <UL>
   86.55 +     *       <LI> YES           --- if this a generated column
   86.56 +     *       <LI> NO            --- if this not a generated column
   86.57 +     *       <LI> empty string  --- if it cannot be determined whether this is a generated column
   86.58       *       </UL>
   86.59       *  </OL>
   86.60       *
   86.61 -     * <p>The COLUMN_SIZE column the specified column size for the given column.
   86.62 +     * <p>The COLUMN_SIZE column specifies the column size for the given column.
   86.63       * For numeric data, this is the maximum precision.  For character data, this is the length in characters.
   86.64       * For datetime datatypes, this is the length in characters of the String representation (assuming the
   86.65       * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes.  For the ROWID datatype,
   86.66 @@ -3186,7 +3191,7 @@
   86.67       * Retrieves whether this database supports statement pooling.
   86.68       *
   86.69       * @return <code>true</code> if so; <code>false</code> otherwise
   86.70 -     * @throws SQLExcpetion if a database access error occurs
   86.71 +     * @throws SQLException if a database access error occurs
   86.72       * @since 1.4
   86.73       */
   86.74      boolean supportsStatementPooling() throws SQLException;
   86.75 @@ -3568,4 +3573,83 @@
   86.76       */
   86.77      int functionReturnsTable    = 2;
   86.78  
   86.79 +    //--------------------------JDBC 4.1 -----------------------------
   86.80 +
   86.81 +    /**
   86.82 +     * Retrieves a description of the pseudo or hidden columns available
   86.83 +     * in a given table within the specified catalog and schema.
   86.84 +     * Pseudo or hidden columns may not always be stored within
   86.85 +     * a table and are not visible in a ResultSet unless they are
   86.86 +     * specified in the query's outermost SELECT list. Pseudo or hidden
   86.87 +     * columns may not necessarily be able to be modified. If there are
   86.88 +     * no pseudo or hidden columns, an empty ResultSet is returned.
   86.89 +     *
   86.90 +     * <P>Only column descriptions matching the catalog, schema, table
   86.91 +     * and column name criteria are returned.  They are ordered by
   86.92 +     * <code>TABLE_CAT</code>,<code>TABLE_SCHEM</code>, <code>TABLE_NAME</code>
   86.93 +     * and <code>COLUMN_NAME</code>.
   86.94 +     *
   86.95 +     * <P>Each column description has the following columns:
   86.96 +     *  <OL>
   86.97 +     *  <LI><B>TABLE_CAT</B> String => table catalog (may be <code>null</code>)
   86.98 +     *  <LI><B>TABLE_SCHEM</B> String => table schema (may be <code>null</code>)
   86.99 +     *  <LI><B>TABLE_NAME</B> String => table name
  86.100 +     *  <LI><B>COLUMN_NAME</B> String => column name
  86.101 +     *  <LI><B>DATA_TYPE</B> int => SQL type from java.sql.Types
  86.102 +     *  <LI><B>COLUMN_SIZE</B> int => column size.
  86.103 +     *  <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits. Null is returned for data types where
  86.104 +     * DECIMAL_DIGITS is not applicable.
  86.105 +     *  <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
  86.106 +     *  <LI><B>COLUMN_USAGE</B> String => The allowed usage for the column.  The
  86.107 +     *  value returned will correspond to the enum name returned by {@link PseudoColumnUsage#name PseudoColumnUsage.name()}
  86.108 +     *  <LI><B>REMARKS</B> String => comment describing column (may be <code>null</code>)
  86.109 +     *  <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
  86.110 +     *       maximum number of bytes in the column
  86.111 +     *  <LI><B>IS_NULLABLE</B> String  => ISO rules are used to determine the nullability for a column.
  86.112 +     *       <UL>
  86.113 +     *       <LI> YES           --- if the column can include NULLs
  86.114 +     *       <LI> NO            --- if the column cannot include NULLs
  86.115 +     *       <LI> empty string  --- if the nullability for the column is unknown
  86.116 +     *       </UL>
  86.117 +     *  </OL>
  86.118 +     *
  86.119 +     * <p>The COLUMN_SIZE column specifies the column size for the given column.
  86.120 +     * For numeric data, this is the maximum precision.  For character data, this is the length in characters.
  86.121 +     * For datetime datatypes, this is the length in characters of the String representation (assuming the
  86.122 +     * maximum allowed precision of the fractional seconds component). For binary data, this is the length in bytes.  For the ROWID datatype,
  86.123 +     * this is the length in bytes. Null is returned for data types where the
  86.124 +     * column size is not applicable.
  86.125 +     *
  86.126 +     * @param catalog a catalog name; must match the catalog name as it
  86.127 +     *        is stored in the database; "" retrieves those without a catalog;
  86.128 +     *        <code>null</code> means that the catalog name should not be used to narrow
  86.129 +     *        the search
  86.130 +     * @param schemaPattern a schema name pattern; must match the schema name
  86.131 +     *        as it is stored in the database; "" retrieves those without a schema;
  86.132 +     *        <code>null</code> means that the schema name should not be used to narrow
  86.133 +     *        the search
  86.134 +     * @param tableNamePattern a table name pattern; must match the
  86.135 +     *        table name as it is stored in the database
  86.136 +     * @param columnNamePattern a column name pattern; must match the column
  86.137 +     *        name as it is stored in the database
  86.138 +     * @return <code>ResultSet</code> - each row is a column description
  86.139 +     * @exception SQLException if a database access error occurs
  86.140 +     * @see PseudoColumnUsage
  86.141 +     * @since 1.7
  86.142 +     */
  86.143 +    ResultSet getPseudoColumns(String catalog, String schemaPattern,
  86.144 +                         String tableNamePattern, String columnNamePattern)
  86.145 +        throws SQLException;
  86.146 +
  86.147 +    /**
  86.148 +     * Retrieves whether a generated key will always be returned if the column
  86.149 +     * name(s) or indexe(s) specified for the auto generated key column(s)
  86.150 +     * are valid and the statement succeeds.  The key that is returned may or
  86.151 +     * may not be based on the column(s) for the auto generated key.
  86.152 +     * Consult your JDBC driver documentation for additional details.
  86.153 +     * @return <code>true</code> if so; <code>false</code> otherwise
  86.154 +     * @exception SQLException if a database access error occurs
  86.155 +     * @since 1.7
  86.156 +     */
  86.157 +    boolean  generatedKeyAlwaysReturned() throws SQLException;
  86.158  }
    87.1 --- a/src/share/classes/java/sql/Date.java	Thu Sep 23 17:33:40 2010 -0700
    87.2 +++ b/src/share/classes/java/sql/Date.java	Fri Sep 24 16:41:32 2010 -0700
    87.3 @@ -1,5 +1,5 @@
    87.4  /*
    87.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    87.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    87.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    87.8   *
    87.9   * This code is free software; you can redistribute it and/or modify it
   87.10 @@ -96,11 +96,12 @@
   87.11       * a <code>Date</code> value.
   87.12       *
   87.13       * @param s a <code>String</code> object representing a date in
   87.14 -     *        in the format "yyyy-mm-dd"
   87.15 +     *        in the format "yyyy-[m]m-[d]d". The leading zero for <code>mm</code>
   87.16 +     * and <code>dd</code> may also be omitted.
   87.17       * @return a <code>java.sql.Date</code> object representing the
   87.18       *         given date
   87.19       * @throws IllegalArgumentException if the date given is not in the
   87.20 -     *         JDBC date escape format (yyyy-mm-dd)
   87.21 +     *         JDBC date escape format (yyyy-[m]m-[d]d)
   87.22       */
   87.23      public static Date valueOf(String s) {
   87.24          final int YEAR_LENGTH = 4;
   87.25 @@ -123,8 +124,9 @@
   87.26              String yyyy = s.substring(0, firstDash);
   87.27              String mm = s.substring(firstDash + 1, secondDash);
   87.28              String dd = s.substring(secondDash + 1);
   87.29 -            if (yyyy.length() == YEAR_LENGTH && mm.length() == MONTH_LENGTH &&
   87.30 -                    dd.length() == DAY_LENGTH) {
   87.31 +            if (yyyy.length() == YEAR_LENGTH &&
   87.32 +                    (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
   87.33 +                    (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
   87.34                  int year = Integer.parseInt(yyyy);
   87.35                  int month = Integer.parseInt(mm);
   87.36                  int day = Integer.parseInt(dd);
    88.1 --- a/src/share/classes/java/sql/Driver.java	Thu Sep 23 17:33:40 2010 -0700
    88.2 +++ b/src/share/classes/java/sql/Driver.java	Fri Sep 24 16:41:32 2010 -0700
    88.3 @@ -1,5 +1,5 @@
    88.4  /*
    88.5 - * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
    88.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    88.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    88.8   *
    88.9   * This code is free software; you can redistribute it and/or modify it
   88.10 @@ -25,6 +25,8 @@
   88.11  
   88.12  package java.sql;
   88.13  
   88.14 +import java.util.logging.Logger;
   88.15 +
   88.16  /**
   88.17   * The interface that every driver class must implement.
   88.18   * <P>The Java SQL framework allows for multiple database drivers.
   88.19 @@ -150,4 +152,19 @@
   88.20       *         otherwise
   88.21       */
   88.22      boolean jdbcCompliant();
   88.23 +
   88.24 +    //------------------------- JDBC 4.1 -----------------------------------
   88.25 +
   88.26 +    /**
   88.27 +     * Return the parent Logger of all the Loggers used by this driver. This
   88.28 +     * should be the Logger farthest from the root Logger that is
   88.29 +     * still an ancestor of all of the Loggers used by this driver. Configuring
   88.30 +     * this Logger will affect all of the log messages generated by the driver.
   88.31 +     * In the worst case, this may be the root Logger.
   88.32 +     *
   88.33 +     * @return the parent Logger for this driver
   88.34 +     * @throws SQLFeatureNotSupportedException if the driver does not use <code>java.util.logging<code>.
   88.35 +     * @since 1.7
   88.36 +     */
   88.37 +    public Logger getParentLogger() throws SQLFeatureNotSupportedException;
   88.38  }
    89.1 --- a/src/share/classes/java/sql/PreparedStatement.java	Thu Sep 23 17:33:40 2010 -0700
    89.2 +++ b/src/share/classes/java/sql/PreparedStatement.java	Fri Sep 24 16:41:32 2010 -0700
    89.3 @@ -1,5 +1,5 @@
    89.4  /*
    89.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    89.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    89.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    89.8   *
    89.9   * This code is free software; you can redistribute it and/or modify it
   89.10 @@ -69,6 +69,10 @@
   89.11       * @exception SQLException if a database access error occurs;
   89.12       * this method is called on a closed  <code>PreparedStatement</code> or the SQL
   89.13       *            statement does not return a <code>ResultSet</code> object
   89.14 +     * @throws SQLTimeoutException when the driver has determined that the
   89.15 +     * timeout value that was specified by the {@code setQueryTimeout}
   89.16 +     * method has been exceeded and has at least attempted to cancel
   89.17 +     * the currently running {@code Statement}
   89.18       */
   89.19      ResultSet executeQuery() throws SQLException;
   89.20  
   89.21 @@ -82,8 +86,11 @@
   89.22       *         or (2) 0 for SQL statements that return nothing
   89.23       * @exception SQLException if a database access error occurs;
   89.24       * this method is called on a closed  <code>PreparedStatement</code>
   89.25 -     * or the SQL
   89.26 -     *            statement returns a <code>ResultSet</code> object
   89.27 +     * or the SQL statement returns a <code>ResultSet</code> object
   89.28 +     * @throws SQLTimeoutException when the driver has determined that the
   89.29 +     * timeout value that was specified by the {@code setQueryTimeout}
   89.30 +     * method has been exceeded and has at least attempted to cancel
   89.31 +     * the currently running {@code Statement}
   89.32       */
   89.33      int executeUpdate() throws SQLException;
   89.34  
   89.35 @@ -463,6 +470,10 @@
   89.36       * @exception SQLException if a database access error occurs;
   89.37       * this method is called on a closed <code>PreparedStatement</code>
   89.38       * or an argument is supplied to this method
   89.39 +     * @throws SQLTimeoutException when the driver has determined that the
   89.40 +     * timeout value that was specified by the {@code setQueryTimeout}
   89.41 +     * method has been exceeded and has at least attempted to cancel
   89.42 +     * the currently running {@code Statement}
   89.43       * @see Statement#execute
   89.44       * @see Statement#getResultSet
   89.45       * @see Statement#getUpdateCount
   89.46 @@ -1208,4 +1219,5 @@
   89.47       void setNClob(int parameterIndex, Reader reader)
   89.48         throws SQLException;
   89.49  
   89.50 +
   89.51  }
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/src/share/classes/java/sql/PseudoColumnUsage.java	Fri Sep 24 16:41:32 2010 -0700
    90.3 @@ -0,0 +1,57 @@
    90.4 +/*
    90.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    90.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    90.7 + *
    90.8 + * This code is free software; you can redistribute it and/or modify it
    90.9 + * under the terms of the GNU General Public License version 2 only, as
   90.10 + * published by the Free Software Foundation.  Oracle designates this
   90.11 + * particular file as subject to the "Classpath" exception as provided
   90.12 + * by Oracle in the LICENSE file that accompanied this code.
   90.13 + *
   90.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   90.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   90.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   90.17 + * version 2 for more details (a copy is included in the LICENSE file that
   90.18 + * accompanied this code).
   90.19 + *
   90.20 + * You should have received a copy of the GNU General Public License version
   90.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   90.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   90.23 + *
   90.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   90.25 + * or visit www.oracle.com if you need additional information or have any
   90.26 + * questions.
   90.27 + */
   90.28 +
   90.29 +package java.sql;
   90.30 +
   90.31 +
   90.32 +/**
   90.33 + * Enumeration for pseudo/hidden column usage.
   90.34 + *
   90.35 + * @since 1.7
   90.36 + * @see DatabaseMetaData#getPseudoColumns
   90.37 + */
   90.38 +public enum PseudoColumnUsage {
   90.39 +
   90.40 +    /**
   90.41 +     * The pseudo/hidden column may only be used in a SELECT list.
   90.42 +     */
   90.43 +    SELECT_LIST_ONLY,
   90.44 +
   90.45 +    /**
   90.46 +     * The pseudo/hidden column may only be used in a WHERE clause.
   90.47 +     */
   90.48 +    WHERE_CLAUSE_ONLY,
   90.49 +
   90.50 +    /**
   90.51 +     * There are no restrictions on the usage of the pseudo/hidden columns.
   90.52 +     */
   90.53 +    NO_USAGE_RESTRICTIONS,
   90.54 +
   90.55 +    /**
   90.56 +     * The usage of the pseudo/hidden column cannot be determined.
   90.57 +     */
   90.58 +    USAGE_UNKNOWN
   90.59 +
   90.60 +}
    91.1 --- a/src/share/classes/java/sql/ResultSet.java	Thu Sep 23 17:33:40 2010 -0700
    91.2 +++ b/src/share/classes/java/sql/ResultSet.java	Fri Sep 24 16:41:32 2010 -0700
    91.3 @@ -1,5 +1,5 @@
    91.4  /*
    91.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    91.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
    91.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    91.8   *
    91.9   * This code is free software; you can redistribute it and/or modify it
   91.10 @@ -145,7 +145,7 @@
   91.11   * @see ResultSetMetaData
   91.12   */
   91.13  
   91.14 -public interface ResultSet extends Wrapper {
   91.15 +public interface ResultSet extends Wrapper, AutoCloseable {
   91.16  
   91.17      /**
   91.18       * Moves the cursor froward one row from its current position.
   91.19 @@ -1187,6 +1187,9 @@
   91.20       * cursor on the last row; calling the method <code>absolute(-2)</code>
   91.21       * moves the cursor to the next-to-last row, and so on.
   91.22       *
   91.23 +     * <p>If the row number specified is zero, the cursor is moved to
   91.24 +     * before the first row.
   91.25 +     *
   91.26       * <p>An attempt to position the cursor beyond the first/last row in
   91.27       * the result set leaves the cursor before the first row or after
   91.28       * the last row.
   91.29 @@ -1196,9 +1199,10 @@
   91.30       * is the same as calling <code>last()</code>.
   91.31       *
   91.32       * @param row the number of the row to which the cursor should move.
   91.33 -     *        A positive number indicates the row number counting from the
   91.34 -     *        beginning of the result set; a negative number indicates the
   91.35 -     *        row number counting from the end of the result set
   91.36 +     *        A value of zero indicates that the cursor will be positioned
   91.37 +     *        before the first row; a positive number indicates the row number
   91.38 +     *        counting from the beginning of the result set; a negative number
   91.39 +     *        indicates the row number counting from the end of the result set
   91.40       * @return <code>true</code> if the cursor is moved to a position in this
   91.41       * <code>ResultSet</code> object;
   91.42       * <code>false</code> if the cursor is before the first row or after the
   91.43 @@ -2529,7 +2533,7 @@
   91.44       * @exception SQLException if the columnLabel is not valid;
   91.45       * if a database access error occurs
   91.46       * or this method is called on a closed result set
   91.47 -      * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
   91.48 +     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
   91.49       * this method
   91.50       * @since 1.2
   91.51       */
   91.52 @@ -4072,4 +4076,64 @@
   91.53       */
   91.54      void updateNClob(String columnLabel,  Reader reader) throws SQLException;
   91.55  
   91.56 +    //------------------------- JDBC 4.1 -----------------------------------
   91.57 +
   91.58 +
   91.59 +    /**
   91.60 +     *<p>Retrieves the value of the designated column in the current row
   91.61 +     * of this <code>ResultSet</code> object and will convert from the
   91.62 +     * SQL type of the column to the requested Java data type, if the
   91.63 +     * conversion is supported. If the conversion is not
   91.64 +     * supported  or null is specified for the type, a
   91.65 +     * <code>SQLException</code> is thrown.
   91.66 +     *<p>
   91.67 +     * At a minimum, an implementation must support the conversions defined in
   91.68 +     * Appendix B, Table B-3 and conversion of appropriate user defined SQL
   91.69 +     * types to a Java type which implements {@code SQLData}, or {@code Struct}.
   91.70 +     * Additional conversions may be supported and are vendor defined.
   91.71 +     *
   91.72 +     * @param columnIndex the first column is 1, the second is 2, ...
   91.73 +     * @param type Class representing the Java data type to convert the designated
   91.74 +     * column to.
   91.75 +     * @return an instance of {@code type} holding the column value
   91.76 +     * @throws SQLException if conversion is not supported, type is null or
   91.77 +     *         another error occurs. The getCause() method of the
   91.78 +     * exception may provide a more detailed exception, for example, if
   91.79 +     * a conversion error occurs
   91.80 +     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
   91.81 +     * this method
   91.82 +     * @since 1.7
   91.83 +     */
   91.84 +     public <T> T getObject(int columnIndex, Class<T> type) throws SQLException;
   91.85 +
   91.86 +
   91.87 +    /**
   91.88 +     *<p>Retrieves the value of the designated column in the current row
   91.89 +     * of this <code>ResultSet</code> object and will convert from the
   91.90 +     * SQL type of the column to the requested Java data type, if the
   91.91 +     * conversion is supported. If the conversion is not
   91.92 +     * supported  or null is specified for the type, a
   91.93 +     * <code>SQLException</code> is thrown.
   91.94 +     *<p>
   91.95 +     * At a minimum, an implementation must support the conversions defined in
   91.96 +     * Appendix B, Table B-3 and conversion of appropriate user defined SQL
   91.97 +     * types to a Java type which implements {@code SQLData}, or {@code Struct}.
   91.98 +     * Additional conversions may be supported and are vendor defined.
   91.99 +     *
  91.100 +     * @param columnLabel the label for the column specified with the SQL AS clause.
  91.101 +     * If the SQL AS clause was not specified, then the label is the name
  91.102 +     * of the column
  91.103 +     * @param type Class representing the Java data type to convert the designated
  91.104 +     * column to.
  91.105 +     * @return an instance of {@code type} holding the column value
  91.106 +     * @throws SQLException if conversion is not supported, type is null or
  91.107 +     *         another error occurs. The getCause() method of the
  91.108 +     * exception may provide a more detailed exception, for example, if
  91.109 +     * a conversion error occurs
  91.110 +     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
  91.111 +     * this method
  91.112 +     * @since 1.7
  91.113 +     */
  91.114 +     public <T> T getObject(String columnLabel, Class<T> type) throws SQLException;
  91.115 +
  91.116  }
    92.1 --- a/src/share/classes/java/sql/SQLDataException.java	Thu Sep 23 17:33:40 2010 -0700
    92.2 +++ b/src/share/classes/java/sql/SQLDataException.java	Fri Sep 24 16:41:32 2010 -0700
    92.3 @@ -1,5 +1,5 @@
    92.4  /*
    92.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    92.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    92.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    92.8   *
    92.9   * This code is free software; you can redistribute it and/or modify it
   92.10 @@ -26,10 +26,13 @@
   92.11  package java.sql;
   92.12  
   92.13  /**
   92.14 - * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>22</i>'. This indicates
   92.15 - * various data errors, including but not limited to not-allowed conversion, division by 0
   92.16 - * and invalid arguments to functions.
   92.17 - *
   92.18 + * The subclass of {@link SQLException} thrown when the SQLState class value
   92.19 + * is '<i>22</i>', or under vendor-specified conditions.  This indicates
   92.20 + * various data errors, including but not limited to data conversion errors,
   92.21 + * division by 0, and invalid arguments to functions.
   92.22 + * <p>
   92.23 + * Please consult your driver vendor documentation for the vendor-specified
   92.24 + * conditions for which this <code>Exception</code> may be thrown.
   92.25   * @since 1.6
   92.26   */
   92.27  public class SQLDataException extends SQLNonTransientException {
    93.1 --- a/src/share/classes/java/sql/SQLIntegrityConstraintViolationException.java	Thu Sep 23 17:33:40 2010 -0700
    93.2 +++ b/src/share/classes/java/sql/SQLIntegrityConstraintViolationException.java	Fri Sep 24 16:41:32 2010 -0700
    93.3 @@ -1,5 +1,5 @@
    93.4  /*
    93.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    93.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    93.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    93.8   *
    93.9   * This code is free software; you can redistribute it and/or modify it
   93.10 @@ -26,9 +26,13 @@
   93.11  package java.sql;
   93.12  
   93.13  /**
   93.14 - * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>23</i>'. This indicates that an integrity
   93.15 + * The subclass of {@link SQLException} thrown when the SQLState class value
   93.16 + * is '<i>23</i>', or under vendor-specified conditions.
   93.17 + * This indicates that an integrity
   93.18   * constraint (foreign key, primary key or unique key) has been violated.
   93.19 - *
   93.20 + * <p>
   93.21 + * Please consult your driver vendor documentation for the vendor-specified
   93.22 + * conditions for which this <code>Exception</code> may be thrown.
   93.23   * @since 1.6
   93.24   */
   93.25  public class SQLIntegrityConstraintViolationException extends SQLNonTransientException {
    94.1 --- a/src/share/classes/java/sql/SQLInvalidAuthorizationSpecException.java	Thu Sep 23 17:33:40 2010 -0700
    94.2 +++ b/src/share/classes/java/sql/SQLInvalidAuthorizationSpecException.java	Fri Sep 24 16:41:32 2010 -0700
    94.3 @@ -1,5 +1,5 @@
    94.4  /*
    94.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    94.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    94.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    94.8   *
    94.9   * This code is free software; you can redistribute it and/or modify it
   94.10 @@ -26,9 +26,13 @@
   94.11  package java.sql;
   94.12  
   94.13  /**
   94.14 - * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>28</i>'. This indicated that the
   94.15 - * authorization credentials presented during connection establishment are not valid.
   94.16 - *
   94.17 + * The subclass of {@link SQLException} thrown when the SQLState class value
   94.18 + * is '<i>28</i>', or under vendor-specified conditions. This indicates that
   94.19 + * the authorization credentials presented during connection establishment
   94.20 + * are not valid.
   94.21 + * <p>
   94.22 + * Please consult your driver vendor documentation for the vendor-specified
   94.23 + * conditions for which this <code>Exception</code> may be thrown.
   94.24   * @since 1.6
   94.25   */
   94.26  public class SQLInvalidAuthorizationSpecException extends SQLNonTransientException {
    95.1 --- a/src/share/classes/java/sql/SQLNonTransientConnectionException.java	Thu Sep 23 17:33:40 2010 -0700
    95.2 +++ b/src/share/classes/java/sql/SQLNonTransientConnectionException.java	Fri Sep 24 16:41:32 2010 -0700
    95.3 @@ -1,5 +1,5 @@
    95.4  /*
    95.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    95.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    95.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    95.8   *
    95.9   * This code is free software; you can redistribute it and/or modify it
   95.10 @@ -26,11 +26,13 @@
   95.11  package java.sql;
   95.12  
   95.13  /**
   95.14 - * <P> The subclass of {@link SQLException} thrown for the SQLState
   95.15 - * class value '<i>08</i>', representing
   95.16 - * that the connection operation that failed will not succeed when
   95.17 + * The subclass of {@link SQLException} thrown for the SQLState
   95.18 + * class value '<i>08</i>', or under vendor-specified conditions.  This
   95.19 + * indicates that the connection operation that failed will not succeed if
   95.20   * the operation is retried without the cause of the failure being corrected.
   95.21   * <p>
   95.22 + * Please consult your driver vendor documentation for the vendor-specified
   95.23 + * conditions for which this <code>Exception</code> may be thrown.
   95.24   * @since 1.6
   95.25   */
   95.26  public class SQLNonTransientConnectionException extends java.sql.SQLNonTransientException {
    96.1 --- a/src/share/classes/java/sql/SQLPermission.java	Thu Sep 23 17:33:40 2010 -0700
    96.2 +++ b/src/share/classes/java/sql/SQLPermission.java	Fri Sep 24 16:41:32 2010 -0700
    96.3 @@ -1,5 +1,5 @@
    96.4  /*
    96.5 - * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved.
    96.6 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
    96.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    96.8   *
    96.9   * This code is free software; you can redistribute it and/or modify it
   96.10 @@ -30,9 +30,14 @@
   96.11  
   96.12  /**
   96.13   * The permission for which the <code>SecurityManager</code> will check
   96.14 - * when code that is running in an applet calls the
   96.15 - * <code>DriverManager.setLogWriter</code> method or the
   96.16 - * <code>DriverManager.setLogStream</code> (deprecated) method.
   96.17 + * when code that is running in an applet, or an application with a
   96.18 + * <code>SecurityManager</code> enabled, calls the
   96.19 + * <code>DriverManager.setLogWriter</code> method,
   96.20 + * <code>DriverManager.setLogStream</code> (deprecated) method,
   96.21 + * {@code SyncFactory.setJNDIContext} method,
   96.22 + * {@code SyncFactory.setLogger} method,
   96.23 + * {@code Connection.setNetworktimeout} method,
   96.24 + * or the <code>Connection.abort</code> method.
   96.25   * If there is no <code>SQLPermission</code> object, these methods
   96.26   * throw a <code>java.lang.SecurityException</code> as a runtime exception.
   96.27   * <P>
   96.28 @@ -48,7 +53,6 @@
   96.29   * but <code>*loadLibrary</code> or <code>a*b</code> is not valid.
   96.30   * <P>
   96.31   * The following table lists all the possible <code>SQLPermission</code> target names.
   96.32 - * Currently, the only name allowed is <code>setLog</code>.
   96.33   * The table gives a description of what the permission allows
   96.34   * and a discussion of the risks of granting code the permission.
   96.35   * <P>
   96.36 @@ -67,9 +71,33 @@
   96.37   * The contents of the log may contain usernames and passwords,
   96.38   * SQL statements, and SQL data.</td>
   96.39   * </tr>
   96.40 + * <tr>
   96.41 + * <td>callAbort</td>
   96.42 + *   <td>Allows the invocation of the {@code Connection} method
   96.43 + *   {@code abort}</td>
   96.44 + *   <td>Permits an application to terminate a physical connection to a
   96.45 + *  database.</td>
   96.46 + * </tr>
   96.47 + * <tr>
   96.48 + * <td>setSyncFactory</td>
   96.49 + *   <td>Allows the invocation of the {@code SyncFactory} methods
   96.50 + *   {@code setJNDIContext} and {@code setLogger}</td>
   96.51 + *   <td>Permits an application to specify the JNDI context from which the
   96.52 + *   {@code SyncProvider} implementations can be retrieved from and the logging
   96.53 + *   object to be used by the{@codeSyncProvider} implementation.</td>
   96.54 + * </tr>
   96.55   *
   96.56 + * <tr>
   96.57 + * <td>setNetworkTimeout</td>
   96.58 + *   <td>Allows the invocation of the {@code Connection} method
   96.59 + *   {@code setNetworkTimeout}</td>
   96.60 + *   <td>Permits an application to specify the maximum period a
   96.61 + * <code>Connection</code> or
   96.62 + * objects created from the <code>Connection</code>
   96.63 + * will wait for the database to reply to any one request.</td>
   96.64 + * </tr>
   96.65   * </table>
   96.66 - *
   96.67 + *<p>
   96.68   * The person running an applet decides what permissions to allow
   96.69   * and will run the <code>Policy Tool</code> to create an
   96.70   * <code>SQLPermission</code> in a policy file.  A programmer does
    97.1 --- a/src/share/classes/java/sql/SQLSyntaxErrorException.java	Thu Sep 23 17:33:40 2010 -0700
    97.2 +++ b/src/share/classes/java/sql/SQLSyntaxErrorException.java	Fri Sep 24 16:41:32 2010 -0700
    97.3 @@ -1,5 +1,5 @@
    97.4  /*
    97.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    97.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    97.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    97.8   *
    97.9   * This code is free software; you can redistribute it and/or modify it
   97.10 @@ -26,9 +26,12 @@
   97.11  package java.sql;
   97.12  
   97.13  /**
   97.14 - * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>42</i>'. This indicates that the
   97.15 + * The subclass of {@link SQLException} thrown when the SQLState class value
   97.16 + * is '<i>42</i>', or under vendor-specified conditions. This indicates that the
   97.17   * in-progress query has violated SQL syntax rules.
   97.18 - *
   97.19 + * <p>
   97.20 + * Please consult your driver vendor documentation for the vendor-specified
   97.21 + * conditions for which this <code>Exception</code> may be thrown.
   97.22   * @since 1.6
   97.23   */
   97.24  public class SQLSyntaxErrorException extends SQLNonTransientException {
    98.1 --- a/src/share/classes/java/sql/SQLTransactionRollbackException.java	Thu Sep 23 17:33:40 2010 -0700
    98.2 +++ b/src/share/classes/java/sql/SQLTransactionRollbackException.java	Fri Sep 24 16:41:32 2010 -0700
    98.3 @@ -1,5 +1,5 @@
    98.4  /*
    98.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    98.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    98.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    98.8   *
    98.9   * This code is free software; you can redistribute it and/or modify it
   98.10 @@ -26,10 +26,13 @@
   98.11  package java.sql;
   98.12  
   98.13  /**
   98.14 - * The subclass of {@link SQLException} thrown when the SQLState class value is '<i>40</i>'. This indicates that the
   98.15 - * current statement was automatically rolled back by the database becuase of deadlock or other
   98.16 - * transaction serialization failures.
   98.17 - *
   98.18 + * The subclass of {@link SQLException} thrown when the SQLState class value
   98.19 + * is '<i>40</i>', or under vendor-specified conditions. This indicates that the
   98.20 + * current statement was automatically rolled back by the database because
   98.21 + * of deadlock or other transaction serialization failures.
   98.22 + * <p>
   98.23 + * Please consult your driver vendor documentation for the vendor-specified
   98.24 + * conditions for which this <code>Exception</code> may be thrown.
   98.25   * @since 1.6
   98.26   */
   98.27  public class SQLTransactionRollbackException extends SQLTransientException {
    99.1 --- a/src/share/classes/java/sql/SQLTransientConnectionException.java	Thu Sep 23 17:33:40 2010 -0700
    99.2 +++ b/src/share/classes/java/sql/SQLTransientConnectionException.java	Fri Sep 24 16:41:32 2010 -0700
    99.3 @@ -1,5 +1,5 @@
    99.4  /*
    99.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
    99.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
    99.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    99.8   *
    99.9   * This code is free software; you can redistribute it and/or modify it
   99.10 @@ -27,11 +27,12 @@
   99.11  
   99.12  /**
   99.13   * The subclass of {@link SQLException} for the SQLState class
   99.14 - * value '<i>08</i>', representing
   99.15 - * that the connection operation that failed might be able to succeed when
   99.16 + * value '<i>08</i>', or under vendor-specified conditions.  This indicates
   99.17 + * that the connection operation that failed might be able to succeed if
   99.18   * the operation is retried without any application-level changes.
   99.19 - *<p>
   99.20 - *
   99.21 + * <p>
   99.22 + * Please consult your driver vendor documentation for the vendor-specified
   99.23 + * conditions for which this <code>Exception</code> may be thrown.
   99.24   * @since 1.6
   99.25   */
   99.26  public class SQLTransientConnectionException extends java.sql.SQLTransientException {
   100.1 --- a/src/share/classes/java/sql/Statement.java	Thu Sep 23 17:33:40 2010 -0700
   100.2 +++ b/src/share/classes/java/sql/Statement.java	Fri Sep 24 16:41:32 2010 -0700
   100.3 @@ -1,5 +1,5 @@
   100.4  /*
   100.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   100.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   100.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   100.8   *
   100.9   * This code is free software; you can redistribute it and/or modify it
  100.10 @@ -40,20 +40,27 @@
  100.11   * @see Connection#createStatement
  100.12   * @see ResultSet
  100.13   */
  100.14 -public interface Statement extends Wrapper {
  100.15 +public interface Statement extends Wrapper, AutoCloseable {
  100.16  
  100.17      /**
  100.18       * Executes the given SQL statement, which returns a single
  100.19       * <code>ResultSet</code> object.
  100.20 -     *
  100.21 +     *<p>
  100.22 +     * <strong>Note:</strong>This method cannot be called on a
  100.23 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
  100.24       * @param sql an SQL statement to be sent to the database, typically a
  100.25       *        static SQL <code>SELECT</code> statement
  100.26       * @return a <code>ResultSet</code> object that contains the data produced
  100.27       *         by the given query; never <code>null</code>
  100.28       * @exception SQLException if a database access error occurs,
  100.29 -     * this method is called on a closed <code>Statement</code> or the given
  100.30 +     * this method is called on a closed <code>Statement</code>, the given
  100.31       *            SQL statement produces anything other than a single
  100.32 -     *            <code>ResultSet</code> object
  100.33 +     *            <code>ResultSet</code> object, the method is called on a
  100.34 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
  100.35 +     * @throws SQLTimeoutException when the driver has determined that the
  100.36 +     * timeout value that was specified by the {@code setQueryTimeout}
  100.37 +     * method has been exceeded and has at least attempted to cancel
  100.38 +     * the currently running {@code Statement}
  100.39       */
  100.40      ResultSet executeQuery(String sql) throws SQLException;
  100.41  
  100.42 @@ -61,7 +68,9 @@
  100.43       * Executes the given SQL statement, which may be an <code>INSERT</code>,
  100.44       * <code>UPDATE</code>, or <code>DELETE</code> statement or an
  100.45       * SQL statement that returns nothing, such as an SQL DDL statement.
  100.46 -     *
  100.47 +     *<p>
  100.48 +     * <strong>Note:</strong>This method cannot be called on a
  100.49 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
  100.50       * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
  100.51       * <code>DELETE</code>; or an SQL statement that returns nothing,
  100.52       * such as a DDL statement.
  100.53 @@ -70,8 +79,13 @@
  100.54       *         or (2) 0 for SQL statements that return nothing
  100.55       *
  100.56       * @exception SQLException if a database access error occurs,
  100.57 -     * this method is called on a closed <code>Statement</code> or the given
  100.58 -     *            SQL statement produces a <code>ResultSet</code> object
  100.59 +     * this method is called on a closed <code>Statement</code>, the given
  100.60 +     * SQL statement produces a <code>ResultSet</code> object, the method is called on a
  100.61 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
  100.62 +     * @throws SQLTimeoutException when the driver has determined that the
  100.63 +     * timeout value that was specified by the {@code setQueryTimeout}
  100.64 +     * method has been exceeded and has at least attempted to cancel
  100.65 +     * the currently running {@code Statement}
  100.66       */
  100.67      int executeUpdate(String sql) throws SQLException;
  100.68  
  100.69 @@ -198,11 +212,21 @@
  100.70      /**
  100.71       * Sets the number of seconds the driver will wait for a
  100.72       * <code>Statement</code> object to execute to the given number of seconds.
  100.73 -     * If the limit is exceeded, an <code>SQLException</code> is thrown. A JDBC
  100.74 -     * driver must apply this limit to the <code>execute</code>,
  100.75 -     * <code>executeQuery</code> and <code>executeUpdate</code> methods. JDBC driver
  100.76 -     * implementations may also apply this limit to <code>ResultSet</code> methods
  100.77 +     *By default there is no limit on the amount of time allowed for a running
  100.78 +     * statement to complete. If the limit is exceeded, an
  100.79 +     * <code>SQLTimeoutException</code> is thrown.
  100.80 +     * A JDBC driver must apply this limit to the <code>execute</code>,
  100.81 +     * <code>executeQuery</code> and <code>executeUpdate</code> methods.
  100.82 +     * <p>
  100.83 +     * <strong>Note:</strong> JDBC driver implementations may also apply this
  100.84 +     * limit to {@code ResultSet} methods
  100.85       * (consult your driver vendor documentation for details).
  100.86 +     * <p>
  100.87 +     * <strong>Note:</strong> In the case of {@code Statement} batching, it is
  100.88 +     * implementation defined as to whether the time-out is applied to
  100.89 +     * individual SQL commands added via the {@code addBatch} method or to
  100.90 +     * the entire batch of SQL commands invoked by the {@code executeBatch}
  100.91 +     * method (consult your driver vendor documentation for details).
  100.92       *
  100.93       * @param seconds the new query timeout limit in seconds; zero means
  100.94       *        there is no limit
  100.95 @@ -300,13 +324,21 @@
  100.96       * <code>getResultSet</code> or <code>getUpdateCount</code>
  100.97       * to retrieve the result, and <code>getMoreResults</code> to
  100.98       * move to any subsequent result(s).
  100.99 -     *
 100.100 +     * <p>
 100.101 +     *<strong>Note:</strong>This method cannot be called on a
 100.102 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
 100.103       * @param sql any SQL statement
 100.104       * @return <code>true</code> if the first result is a <code>ResultSet</code>
 100.105       *         object; <code>false</code> if it is an update count or there are
 100.106       *         no results
 100.107 -     * @exception SQLException if a database access error occurs or
 100.108 -     * this method is called on a closed <code>Statement</code>
 100.109 +     * @exception SQLException if a database access error occurs,
 100.110 +     * this method is called on a closed <code>Statement</code>,
 100.111 +     * the method is called on a
 100.112 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
 100.113 +     * @throws SQLTimeoutException when the driver has determined that the
 100.114 +     * timeout value that was specified by the {@code setQueryTimeout}
 100.115 +     * method has been exceeded and has at least attempted to cancel
 100.116 +     * the currently running {@code Statement}
 100.117       * @see #getResultSet
 100.118       * @see #getUpdateCount
 100.119       * @see #getMoreResults
 100.120 @@ -465,12 +497,14 @@
 100.121       * <code>Statement</code> object. The commands in this list can be
 100.122       * executed as a batch by calling the method <code>executeBatch</code>.
 100.123       * <P>
 100.124 -     *
 100.125 +     *<strong>Note:</strong>This method cannot be called on a
 100.126 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
 100.127       * @param sql typically this is a SQL <code>INSERT</code> or
 100.128       * <code>UPDATE</code> statement
 100.129       * @exception SQLException if a database access error occurs,
 100.130 -     * this method is called on a closed <code>Statement</code> or the
 100.131 -     * driver does not support batch updates
 100.132 +     * this method is called on a closed <code>Statement</code>, the
 100.133 +     * driver does not support batch updates, the method is called on a
 100.134 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
 100.135       * @see #executeBatch
 100.136       * @see DatabaseMetaData#supportsBatchUpdates
 100.137       * @since 1.2
 100.138 @@ -536,7 +570,10 @@
 100.139       * driver does not support batch statements. Throws {@link BatchUpdateException}
 100.140       * (a subclass of <code>SQLException</code>) if one of the commands sent to the
 100.141       * database fails to execute properly or attempts to return a result set.
 100.142 -     *
 100.143 +     * @throws SQLTimeoutException when the driver has determined that the
 100.144 +     * timeout value that was specified by the {@code setQueryTimeout}
 100.145 +     * method has been exceeded and has at least attempted to cancel
 100.146 +     * the currently running {@code Statement}
 100.147       *
 100.148       * @see #addBatch
 100.149       * @see DatabaseMetaData#supportsBatchUpdates
 100.150 @@ -678,7 +715,9 @@
 100.151       * flag if the SQL statement
 100.152       * is not an <code>INSERT</code> statement, or an SQL statement able to return
 100.153       * auto-generated keys (the list of such statements is vendor-specific).
 100.154 -     *
 100.155 +     *<p>
 100.156 +     * <strong>Note:</strong>This method cannot be called on a
 100.157 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
 100.158       * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
 100.159       * <code>DELETE</code>; or an SQL statement that returns nothing,
 100.160       * such as a DDL statement.
 100.161 @@ -693,10 +732,15 @@
 100.162       *
 100.163       * @exception SQLException if a database access error occurs,
 100.164       *  this method is called on a closed <code>Statement</code>, the given
 100.165 -     *            SQL statement returns a <code>ResultSet</code> object, or
 100.166 -     *            the given constant is not one of those allowed
 100.167 +     *            SQL statement returns a <code>ResultSet</code> object,
 100.168 +     *            the given constant is not one of those allowed, the method is called on a
 100.169 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
 100.170       * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
 100.171       * this method with a constant of Statement.RETURN_GENERATED_KEYS
 100.172 +     * @throws SQLTimeoutException when the driver has determined that the
 100.173 +     * timeout value that was specified by the {@code setQueryTimeout}
 100.174 +     * method has been exceeded and has at least attempted to cancel
 100.175 +     * the currently running {@code Statement}
 100.176       * @since 1.4
 100.177       */
 100.178      int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException;
 100.179 @@ -709,7 +753,9 @@
 100.180       * available. The driver will ignore the array if the SQL statement
 100.181       * is not an <code>INSERT</code> statement, or an SQL statement able to return
 100.182       * auto-generated keys (the list of such statements is vendor-specific).
 100.183 -     *
 100.184 +     *<p>
 100.185 +     * <strong>Note:</strong>This method cannot be called on a
 100.186 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
 100.187       * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
 100.188       * <code>DELETE</code>; or an SQL statement that returns nothing,
 100.189       * such as a DDL statement.
 100.190 @@ -721,10 +767,15 @@
 100.191       *
 100.192       * @exception SQLException if a database access error occurs,
 100.193       * this method is called on a closed <code>Statement</code>, the SQL
 100.194 -     *            statement returns a <code>ResultSet</code> object, or the
 100.195 -     *            second argument supplied to this method is not an <code>int</code> array
 100.196 -     *            whose elements are valid column indexes
 100.197 +     * statement returns a <code>ResultSet</code> object,the second argument
 100.198 +     * supplied to this method is not an
 100.199 +     * <code>int</code> array whose elements are valid column indexes, the method is called on a
 100.200 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
 100.201       * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
 100.202 +     * @throws SQLTimeoutException when the driver has determined that the
 100.203 +     * timeout value that was specified by the {@code setQueryTimeout}
 100.204 +     * method has been exceeded and has at least attempted to cancel
 100.205 +     * the currently running {@code Statement}
 100.206       * @since 1.4
 100.207       */
 100.208      int executeUpdate(String sql, int columnIndexes[]) throws SQLException;
 100.209 @@ -737,7 +788,9 @@
 100.210       * available. The driver will ignore the array if the SQL statement
 100.211       * is not an <code>INSERT</code> statement, or an SQL statement able to return
 100.212       * auto-generated keys (the list of such statements is vendor-specific).
 100.213 -     *
 100.214 +     *<p>
 100.215 +     * <strong>Note:</strong>This method cannot be called on a
 100.216 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
 100.217       * @param sql an SQL Data Manipulation Language (DML) statement, such as <code>INSERT</code>, <code>UPDATE</code> or
 100.218       * <code>DELETE</code>; or an SQL statement that returns nothing,
 100.219       * such as a DDL statement.
 100.220 @@ -748,11 +801,15 @@
 100.221       *         that return nothing
 100.222       * @exception SQLException if a database access error occurs,
 100.223       *  this method is called on a closed <code>Statement</code>, the SQL
 100.224 -     *            statement returns a <code>ResultSet</code> object, or the
 100.225 +     *            statement returns a <code>ResultSet</code> object, the
 100.226       *            second argument supplied to this method is not a <code>String</code> array
 100.227 -     *            whose elements are valid column names
 100.228 -     *
 100.229 +     *            whose elements are valid column names, the method is called on a
 100.230 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
 100.231       * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
 100.232 +     * @throws SQLTimeoutException when the driver has determined that the
 100.233 +     * timeout value that was specified by the {@code setQueryTimeout}
 100.234 +     * method has been exceeded and has at least attempted to cancel
 100.235 +     * the currently running {@code Statement}
 100.236       * @since 1.4
 100.237       */
 100.238      int executeUpdate(String sql, String columnNames[]) throws SQLException;
 100.239 @@ -776,7 +833,9 @@
 100.240       * <code>getResultSet</code> or <code>getUpdateCount</code>
 100.241       * to retrieve the result, and <code>getMoreResults</code> to
 100.242       * move to any subsequent result(s).
 100.243 -     *
 100.244 +     *<p>
 100.245 +     *<strong>Note:</strong>This method cannot be called on a
 100.246 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
 100.247       * @param sql any SQL statement
 100.248       * @param autoGeneratedKeys a constant indicating whether auto-generated
 100.249       *        keys should be made available for retrieval using the method
 100.250 @@ -787,12 +846,18 @@
 100.251       *         object; <code>false</code> if it is an update count or there are
 100.252       *         no results
 100.253       * @exception SQLException if a database access error occurs,
 100.254 -     * this method is called on a closed <code>Statement</code> or the second
 100.255 +     * this method is called on a closed <code>Statement</code>, the second
 100.256       *         parameter supplied to this method is not
 100.257       *         <code>Statement.RETURN_GENERATED_KEYS</code> or
 100.258 -     *         <code>Statement.NO_GENERATED_KEYS</code>.
 100.259 +     *         <code>Statement.NO_GENERATED_KEYS</code>,
 100.260 +     * the method is called on a
 100.261 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
 100.262       * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
 100.263       * this method with a constant of Statement.RETURN_GENERATED_KEYS
 100.264 +     * @throws SQLTimeoutException when the driver has determined that the
 100.265 +     * timeout value that was specified by the {@code setQueryTimeout}
 100.266 +     * method has been exceeded and has at least attempted to cancel
 100.267 +     * the currently running {@code Statement}
 100.268       * @see #getResultSet
 100.269       * @see #getUpdateCount
 100.270       * @see #getMoreResults
 100.271 @@ -823,7 +888,9 @@
 100.272       * <code>getResultSet</code> or <code>getUpdateCount</code>
 100.273       * to retrieve the result, and <code>getMoreResults</code> to
 100.274       * move to any subsequent result(s).
 100.275 -     *
 100.276 +     *<p>
 100.277 +     * <strong>Note:</strong>This method cannot be called on a
 100.278 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
 100.279       * @param sql any SQL statement
 100.280       * @param columnIndexes an array of the indexes of the columns in the
 100.281       *        inserted row that should be  made available for retrieval by a
 100.282 @@ -832,10 +899,15 @@
 100.283       *         object; <code>false</code> if it is an update count or there
 100.284       *         are no results
 100.285       * @exception SQLException if a database access error occurs,
 100.286 -     * this method is called on a closed <code>Statement</code> or the
 100.287 +     * this method is called on a closed <code>Statement</code>, the
 100.288       *            elements in the <code>int</code> array passed to this method
 100.289 -     *            are not valid column indexes
 100.290 +     *            are not valid column indexes, the method is called on a
 100.291 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
 100.292       * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
 100.293 +     * @throws SQLTimeoutException when the driver has determined that the
 100.294 +     * timeout value that was specified by the {@code setQueryTimeout}
 100.295 +     * method has been exceeded and has at least attempted to cancel
 100.296 +     * the currently running {@code Statement}
 100.297       * @see #getResultSet
 100.298       * @see #getUpdateCount
 100.299       * @see #getMoreResults
 100.300 @@ -865,7 +937,9 @@
 100.301       * <code>getResultSet</code> or <code>getUpdateCount</code>
 100.302       * to retrieve the result, and <code>getMoreResults</code> to
 100.303       * move to any subsequent result(s).
 100.304 -     *
 100.305 +     *<p>
 100.306 +     * <strong>Note:</strong>This method cannot be called on a
 100.307 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>.
 100.308       * @param sql any SQL statement
 100.309       * @param columnNames an array of the names of the columns in the inserted
 100.310       *        row that should be made available for retrieval by a call to the
 100.311 @@ -874,10 +948,15 @@
 100.312       *         object; <code>false</code> if it is an update count or there
 100.313       *         are no more results
 100.314       * @exception SQLException if a database access error occurs,
 100.315 -     * this method is called on a closed <code>Statement</code> or the
 100.316 +     * this method is called on a closed <code>Statement</code>,the
 100.317       *          elements of the <code>String</code> array passed to this
 100.318 -     *          method are not valid column names
 100.319 +     *          method are not valid column names, the method is called on a
 100.320 +     * <code>PreparedStatement</code> or <code>CallableStatement</code>
 100.321       * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
 100.322 +     * @throws SQLTimeoutException when the driver has determined that the
 100.323 +     * timeout value that was specified by the {@code setQueryTimeout}
 100.324 +     * method has been exceeded and has at least attempted to cancel
 100.325 +     * the currently running {@code Statement}
 100.326       * @see #getResultSet
 100.327       * @see #getUpdateCount
 100.328       * @see #getMoreResults
 100.329 @@ -951,4 +1030,34 @@
 100.330          boolean isPoolable()
 100.331                  throws SQLException;
 100.332  
 100.333 +    //--------------------------JDBC 4.1 -----------------------------
 100.334 +
 100.335 +    /**
 100.336 +     * Specifies that this {@code Statement} will be closed when all its
 100.337 +     * dependent result sets are closed. If execution of the {@code Statement}
 100.338 +     * does not produce any result sets, this method has no effect.
 100.339 +     * <p>
 100.340 +     * <strong>Note:</strong> Multiple calls to {@code closeOnCompletion} do
 100.341 +     * not toggle the effect on this {@code Statement}. However, a call to
 100.342 +     * {@code closeOnCompletion} does effect both the subsequent execution of
 100.343 +     * statements, and statements that currently have open, dependent,
 100.344 +     * result sets.
 100.345 +     *
 100.346 +     * @throws SQLException if this method is called on a closed
 100.347 +     * {@code Statement}
 100.348 +     * @since 1.7
 100.349 +     */
 100.350 +    public void closeOnCompletion() throws SQLException;
 100.351 +
 100.352 +    /**
 100.353 +     * Returns a value indicating whether this {@code Statement} will be
 100.354 +     * closed when all dependent objects such as resultsets are closed.
 100.355 +     * @return {@code true} if the {@code Statement} will be closed when all
 100.356 +     * of its dependent objects are closed; {@code false} otherwise
 100.357 +     * @throws SQLException if this method is called on a closed
 100.358 +     * {@code Statement}
 100.359 +     * @since 1.7
 100.360 +     */
 100.361 +    public boolean isCloseOnCompletion() throws SQLException;
 100.362 +
 100.363  }
   101.1 --- a/src/share/classes/java/sql/Timestamp.java	Thu Sep 23 17:33:40 2010 -0700
   101.2 +++ b/src/share/classes/java/sql/Timestamp.java	Fri Sep 24 16:41:32 2010 -0700
   101.3 @@ -1,5 +1,5 @@
   101.4  /*
   101.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   101.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   101.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   101.8   *
   101.9   * This code is free software; you can redistribute it and/or modify it
  101.10 @@ -155,19 +155,26 @@
  101.11       * Converts a <code>String</code> object in JDBC timestamp escape format to a
  101.12       * <code>Timestamp</code> value.
  101.13       *
  101.14 -     * @param s timestamp in format <code>yyyy-mm-dd hh:mm:ss[.f...]</code>.  The
  101.15 -     * fractional seconds may be omitted.
  101.16 +     * @param s timestamp in format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>.  The
  101.17 +     * fractional seconds may be omitted. The leading zero for <code>mm</code>
  101.18 +     * and <code>dd</code> may also be omitted.
  101.19 +     *
  101.20       * @return corresponding <code>Timestamp</code> value
  101.21       * @exception java.lang.IllegalArgumentException if the given argument
  101.22 -     * does not have the format <code>yyyy-mm-dd hh:mm:ss[.f...]</code>
  101.23 +     * does not have the format <code>yyyy-[m]m-[d]d hh:mm:ss[.f...]</code>
  101.24       */
  101.25      public static Timestamp valueOf(String s) {
  101.26 +        final int YEAR_LENGTH = 4;
  101.27 +        final int MONTH_LENGTH = 2;
  101.28 +        final int DAY_LENGTH = 2;
  101.29 +        final int MAX_MONTH = 12;
  101.30 +        final int MAX_DAY = 31;
  101.31          String date_s;
  101.32          String time_s;
  101.33          String nanos_s;
  101.34 -        int year;
  101.35 -        int month;
  101.36 -        int day;
  101.37 +        int year = 0;
  101.38 +        int month = 0;
  101.39 +        int day = 0;
  101.40          int hour;
  101.41          int minute;
  101.42          int second;
  101.43 @@ -182,17 +189,9 @@
  101.44          String zeros = "000000000";
  101.45          String delimiterDate = "-";
  101.46          String delimiterTime = ":";
  101.47 -        StringTokenizer stringTokeninzerDate;
  101.48 -        StringTokenizer stringTokeninzerTime;
  101.49  
  101.50          if (s == null) throw new java.lang.IllegalArgumentException("null string");
  101.51  
  101.52 -        int counterD = 0;
  101.53 -        int intDate[] = {4,2,2};
  101.54 -
  101.55 -        int counterT = 0;
  101.56 -        int intTime[] = {2,2,12};
  101.57 -
  101.58          // Split the string into date and time components
  101.59          s = s.trim();
  101.60          dividingSpace = s.indexOf(' ');
  101.61 @@ -203,30 +202,6 @@
  101.62              throw new java.lang.IllegalArgumentException(formatError);
  101.63          }
  101.64  
  101.65 -        stringTokeninzerTime = new StringTokenizer(time_s, delimiterTime);
  101.66 -        stringTokeninzerDate = new StringTokenizer(date_s, delimiterDate);
  101.67 -
  101.68 -        while(stringTokeninzerDate.hasMoreTokens()) {
  101.69 -             String tokenDate = stringTokeninzerDate.nextToken();
  101.70 -             if(tokenDate.length() != intDate[counterD] ) {
  101.71 -                throw new java.lang.IllegalArgumentException(formatError);
  101.72 -             }
  101.73 -             counterD++;
  101.74 -        }
  101.75 -
  101.76 -        /*
  101.77 -         //Commenting this portion out for checking of time
  101.78 -
  101.79 -        while(stringTokeninzerTime.hasMoreTokens()) {
  101.80 -             String tokenTime = stringTokeninzerTime.nextToken();
  101.81 -
  101.82 -             if (counterT < 2 && tokenTime.length() != intTime[counterT]  ) {
  101.83 -                throw new java.lang.IllegalArgumentException(formatError);
  101.84 -             }
  101.85 -             counterT++;
  101.86 -        }
  101.87 -        */
  101.88 -
  101.89          // Parse the date
  101.90          firstDash = date_s.indexOf('-');
  101.91          secondDash = date_s.indexOf('-', firstDash+1);
  101.92 @@ -239,14 +214,24 @@
  101.93          period = time_s.indexOf('.', secondColon+1);
  101.94  
  101.95          // Convert the date
  101.96 -        if ((firstDash > 0) && (secondDash > 0) &&
  101.97 -            (secondDash < date_s.length()-1)) {
  101.98 -            year = Integer.parseInt(date_s.substring(0, firstDash)) - 1900;
  101.99 -            month =
 101.100 -                Integer.parseInt(date_s.substring
 101.101 -                                 (firstDash+1, secondDash)) - 1;
 101.102 -            day = Integer.parseInt(date_s.substring(secondDash+1));
 101.103 -        } else {
 101.104 +        boolean parsedDate = false;
 101.105 +        if ((firstDash > 0) && (secondDash > 0) && (secondDash < date_s.length() - 1)) {
 101.106 +            String yyyy = date_s.substring(0, firstDash);
 101.107 +            String mm = date_s.substring(firstDash + 1, secondDash);
 101.108 +            String dd = date_s.substring(secondDash + 1);
 101.109 +            if (yyyy.length() == YEAR_LENGTH &&
 101.110 +                    (mm.length() >= 1 && mm.length() <= MONTH_LENGTH) &&
 101.111 +                    (dd.length() >= 1 && dd.length() <= DAY_LENGTH)) {
 101.112 +                 year = Integer.parseInt(yyyy);
 101.113 +                 month = Integer.parseInt(mm);
 101.114 +                 day = Integer.parseInt(dd);
 101.115 +
 101.116 +                if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
 101.117 +                    parsedDate = true;
 101.118 +                }
 101.119 +            }
 101.120 +        }
 101.121 +        if (! parsedDate) {
 101.122              throw new java.lang.IllegalArgumentException(formatError);
 101.123          }
 101.124  
 101.125 @@ -272,10 +257,10 @@
 101.126                  second = Integer.parseInt(time_s.substring(secondColon+1));
 101.127              }
 101.128          } else {
 101.129 -            throw new java.lang.IllegalArgumentException();
 101.130 +            throw new java.lang.IllegalArgumentException(formatError);
 101.131          }
 101.132  
 101.133 -        return new Timestamp(year, month, day, hour, minute, second, a_nanos);
 101.134 +        return new Timestamp(year - 1900, month - 1, day, hour, minute, second, a_nanos);
 101.135      }
 101.136  
 101.137      /**
 101.138 @@ -502,14 +487,10 @@
 101.139  
 101.140      /**
 101.141       * Compares this <code>Timestamp</code> object to the given
 101.142 -     * <code>Date</code>, which must be a <code>Timestamp</code>
 101.143 -     * object. If the argument is not a <code>Timestamp</code> object,
 101.144 -     * this method throws a <code>ClassCastException</code> object.
 101.145 -     * (<code>Timestamp</code> objects are
 101.146 -     * comparable only to other <code>Timestamp</code> objects.)
 101.147 +     * <code>Date</code> object.
 101.148       *
 101.149 -     * @param o the <code>Date</code> to be compared, which must be a
 101.150 -     *        <code>Timestamp</code> object
 101.151 +     * @param o the <code>Date</code> to be compared to
 101.152 +     *          this <code>Timestamp</code> object
 101.153       * @return  the value <code>0</code> if this <code>Timestamp</code> object
 101.154       *          and the given object are equal; a value less than <code>0</code>
 101.155       *          if this  <code>Timestamp</code> object is before the given argument;
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/src/share/classes/java/text/CalendarBuilder.java	Fri Sep 24 16:41:32 2010 -0700
   102.3 @@ -0,0 +1,170 @@
   102.4 +/*
   102.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   102.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   102.7 + *
   102.8 + * This code is free software; you can redistribute it and/or modify it
   102.9 + * under the terms of the GNU General Public License version 2 only, as
  102.10 + * published by the Free Software Foundation.  Oracle designates this
  102.11 + * particular file as subject to the "Classpath" exception as provided
  102.12 + * by Oracle in the LICENSE file that accompanied this code.
  102.13 + *
  102.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  102.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  102.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  102.17 + * version 2 for more details (a copy is included in the LICENSE file that
  102.18 + * accompanied this code).
  102.19 + *
  102.20 + * You should have received a copy of the GNU General Public License version
  102.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  102.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  102.23 + *
  102.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  102.25 + * or visit www.oracle.com if you need additional information or have any
  102.26 + * questions.
  102.27 + */
  102.28 +
  102.29 +package java.text;
  102.30 +
  102.31 +import java.util.Calendar;
  102.32 +import static java.util.GregorianCalendar.*;
  102.33 +
  102.34 +/**
  102.35 + * {@code CalendarBuilder} keeps field-value pairs for setting
  102.36 + * the calendar fields of the given {@code Calendar}. It has the
  102.37 + * {@link Calendar#FIELD_COUNT FIELD_COUNT}-th field for the week year
  102.38 + * support. Also {@code ISO_DAY_OF_WEEK} is used to specify
  102.39 + * {@code DAY_OF_WEEK} in the ISO day of week numbering.
  102.40 + *
  102.41 + * <p>{@code CalendarBuilder} retains the semantic of the pseudo
  102.42 + * timestamp for fields. {@code CalendarBuilder} uses a single
  102.43 + * int array combining fields[] and stamp[] of {@code Calendar}.
  102.44 + *
  102.45 + * @author Masayoshi Okutsu
  102.46 + */
  102.47 +class CalendarBuilder {
  102.48 +    /*
  102.49 +     * Pseudo time stamp constants used in java.util.Calendar
  102.50 +     */
  102.51 +    private static final int UNSET = 0;
  102.52 +    private static final int COMPUTED = 1;
  102.53 +    private static final int MINIMUM_USER_STAMP = 2;
  102.54 +
  102.55 +    private static final int MAX_FIELD = FIELD_COUNT + 1;
  102.56 +
  102.57 +    public static final int WEEK_YEAR = FIELD_COUNT;
  102.58 +    public static final int ISO_DAY_OF_WEEK = 1000; // pseudo field index
  102.59 +
  102.60 +    // stamp[] (lower half) and field[] (upper half) combined
  102.61 +    private final int[] field;
  102.62 +    private int nextStamp;
  102.63 +    private int maxFieldIndex;
  102.64 +
  102.65 +    CalendarBuilder() {
  102.66 +        field = new int[MAX_FIELD * 2];
  102.67 +        nextStamp = MINIMUM_USER_STAMP;
  102.68 +        maxFieldIndex = -1;
  102.69 +    }
  102.70 +
  102.71 +    CalendarBuilder set(int index, int value) {
  102.72 +        if (index == ISO_DAY_OF_WEEK) {
  102.73 +            index = DAY_OF_WEEK;
  102.74 +            value = toCalendarDayOfWeek(value);
  102.75 +        }
  102.76 +        field[index] = nextStamp++;
  102.77 +        field[MAX_FIELD + index] = value;
  102.78 +        if (index > maxFieldIndex && index < FIELD_COUNT) {
  102.79 +            maxFieldIndex = index;
  102.80 +        }
  102.81 +        return this;
  102.82 +    }
  102.83 +
  102.84 +    CalendarBuilder addYear(int value) {
  102.85 +        field[MAX_FIELD + YEAR] += value;
  102.86 +        field[MAX_FIELD + WEEK_YEAR] += value;
  102.87 +        return this;
  102.88 +    }
  102.89 +
  102.90 +    boolean isSet(int index) {
  102.91 +        if (index == ISO_DAY_OF_WEEK) {
  102.92 +            index = DAY_OF_WEEK;
  102.93 +        }
  102.94 +        return field[index] > UNSET;
  102.95 +    }
  102.96 +
  102.97 +    Calendar establish(Calendar cal) {
  102.98 +        boolean weekDate = isSet(WEEK_YEAR)
  102.99 +                            && field[WEEK_YEAR] > field[YEAR];
 102.100 +        if (weekDate && !cal.isWeekDateSupported()) {
 102.101 +            // Use YEAR instead
 102.102 +            if (!isSet(YEAR)) {
 102.103 +                set(YEAR, field[MAX_FIELD + WEEK_YEAR]);
 102.104 +            }
 102.105 +            weekDate = false;
 102.106 +        }
 102.107 +
 102.108 +        cal.clear();
 102.109 +        // Set the fields from the min stamp to the max stamp so that
 102.110 +        // the field resolution works in the Calendar.
 102.111 +        for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) {
 102.112 +            for (int index = 0; index <= maxFieldIndex; index++) {
 102.113 +                if (field[index] == stamp) {
 102.114 +                    cal.set(index, field[MAX_FIELD + index]);
 102.115 +                    break;
 102.116 +                }
 102.117 +            }
 102.118 +        }
 102.119 +
 102.120 +        if (weekDate) {
 102.121 +            int weekOfYear = isSet(WEEK_OF_YEAR) ? field[MAX_FIELD + WEEK_OF_YEAR] : 1;
 102.122 +            int dayOfWeek = isSet(DAY_OF_WEEK) ?
 102.123 +                                field[MAX_FIELD + DAY_OF_WEEK] : cal.getFirstDayOfWeek();
 102.124 +            if (!isValidDayOfWeek(dayOfWeek) && cal.isLenient()) {
 102.125 +                if (dayOfWeek >= 8) {
 102.126 +                    dayOfWeek--;
 102.127 +                    weekOfYear += dayOfWeek / 7;
 102.128 +                    dayOfWeek = (dayOfWeek % 7) + 1;
 102.129 +                } else {
 102.130 +                    while (dayOfWeek <= 0) {
 102.131 +                        dayOfWeek += 7;
 102.132 +                        weekOfYear--;
 102.133 +                    }
 102.134 +                }
 102.135 +                dayOfWeek = toCalendarDayOfWeek(dayOfWeek);
 102.136 +            }
 102.137 +            cal.setWeekDate(field[MAX_FIELD + WEEK_YEAR], weekOfYear, dayOfWeek);
 102.138 +        }
 102.139 +        return cal;
 102.140 +    }
 102.141 +
 102.142 +    public String toString() {
 102.143 +        StringBuilder sb = new StringBuilder();
 102.144 +        sb.append("CalendarBuilder:[");
 102.145 +        for (int i = 0; i < field.length; i++) {
 102.146 +            if (isSet(i)) {
 102.147 +                sb.append(i).append('=').append(field[MAX_FIELD + i]).append(',');
 102.148 +            }
 102.149 +        }
 102.150 +        int lastIndex = sb.length() - 1;
 102.151 +        if (sb.charAt(lastIndex) == ',') {
 102.152 +            sb.setLength(lastIndex);
 102.153 +        }
 102.154 +        sb.append(']');
 102.155 +        return sb.toString();
 102.156 +    }
 102.157 +
 102.158 +    static int toISODayOfWeek(int calendarDayOfWeek) {
 102.159 +        return calendarDayOfWeek == SUNDAY ? 7 : calendarDayOfWeek - 1;
 102.160 +    }
 102.161 +
 102.162 +    static int toCalendarDayOfWeek(int isoDayOfWeek) {
 102.163 +        if (!isValidDayOfWeek(isoDayOfWeek)) {
 102.164 +            // adjust later for lenient mode
 102.165 +            return isoDayOfWeek;
 102.166 +        }
 102.167 +        return isoDayOfWeek == 7 ? SUNDAY : isoDayOfWeek + 1;
 102.168 +    }
 102.169 +
 102.170 +    static boolean isValidDayOfWeek(int dayOfWeek) {
 102.171 +        return dayOfWeek > 0 && dayOfWeek <= 7;
 102.172 +    }
 102.173 +}
   103.1 --- a/src/share/classes/java/text/DateFormat.java	Thu Sep 23 17:33:40 2010 -0700
   103.2 +++ b/src/share/classes/java/text/DateFormat.java	Fri Sep 24 16:41:32 2010 -0700
   103.3 @@ -443,7 +443,7 @@
   103.4       */
   103.5      public final static DateFormat getTimeInstance()
   103.6      {
   103.7 -        return get(DEFAULT, 0, 1, Locale.getDefault());
   103.8 +        return get(DEFAULT, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
   103.9      }
  103.10  
  103.11      /**
  103.12 @@ -455,7 +455,7 @@
  103.13       */
  103.14      public final static DateFormat getTimeInstance(int style)
  103.15      {
  103.16 -        return get(style, 0, 1, Locale.getDefault());
  103.17 +        return get(style, 0, 1, Locale.getDefault(Locale.Category.FORMAT));
  103.18      }
  103.19  
  103.20      /**
  103.21 @@ -479,7 +479,7 @@
  103.22       */
  103.23      public final static DateFormat getDateInstance()
  103.24      {
  103.25 -        return get(0, DEFAULT, 2, Locale.getDefault());
  103.26 +        return get(0, DEFAULT, 2, Locale.getDefault(Locale.Category.FORMAT));
  103.27      }
  103.28  
  103.29      /**
  103.30 @@ -491,7 +491,7 @@
  103.31       */
  103.32      public final static DateFormat getDateInstance(int style)
  103.33      {
  103.34 -        return get(0, style, 2, Locale.getDefault());
  103.35 +        return get(0, style, 2, Locale.getDefault(Locale.Category.FORMAT));
  103.36      }
  103.37  
  103.38      /**
  103.39 @@ -515,7 +515,7 @@
  103.40       */
  103.41      public final static DateFormat getDateTimeInstance()
  103.42      {
  103.43 -        return get(DEFAULT, DEFAULT, 3, Locale.getDefault());
  103.44 +        return get(DEFAULT, DEFAULT, 3, Locale.getDefault(Locale.Category.FORMAT));
  103.45      }
  103.46  
  103.47      /**
  103.48 @@ -530,7 +530,7 @@
  103.49      public final static DateFormat getDateTimeInstance(int dateStyle,
  103.50                                                         int timeStyle)
  103.51      {
  103.52 -        return get(timeStyle, dateStyle, 3, Locale.getDefault());
  103.53 +        return get(timeStyle, dateStyle, 3, Locale.getDefault(Locale.Category.FORMAT));
  103.54      }
  103.55  
  103.56      /**
   104.1 --- a/src/share/classes/java/text/DateFormatSymbols.java	Thu Sep 23 17:33:40 2010 -0700
   104.2 +++ b/src/share/classes/java/text/DateFormatSymbols.java	Fri Sep 24 16:41:32 2010 -0700
   104.3 @@ -1,5 +1,5 @@
   104.4  /*
   104.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   104.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   104.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   104.8   *
   104.9   * This code is free software; you can redistribute it and/or modify it
  104.10 @@ -118,7 +118,7 @@
  104.11       */
  104.12      public DateFormatSymbols()
  104.13      {
  104.14 -        initializeData(Locale.getDefault());
  104.15 +        initializeData(Locale.getDefault(Locale.Category.FORMAT));
  104.16      }
  104.17  
  104.18      /**
  104.19 @@ -226,7 +226,30 @@
  104.20       * Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
  104.21       * All locales use the same these unlocalized pattern characters.
  104.22       */
  104.23 -    static final String  patternChars = "GyMdkHmsSEDFwWahKzZ";
  104.24 +    static final String  patternChars = "GyMdkHmsSEDFwWahKzZYuX";
  104.25 +
  104.26 +    static final int PATTERN_ERA                  =  0; // G
  104.27 +    static final int PATTERN_YEAR                 =  1; // y
  104.28 +    static final int PATTERN_MONTH                =  2; // M
  104.29 +    static final int PATTERN_DAY_OF_MONTH         =  3; // d
  104.30 +    static final int PATTERN_HOUR_OF_DAY1         =  4; // k
  104.31 +    static final int PATTERN_HOUR_OF_DAY0         =  5; // H
  104.32 +    static final int PATTERN_MINUTE               =  6; // m
  104.33 +    static final int PATTERN_SECOND               =  7; // s
  104.34 +    static final int PATTERN_MILLISECOND          =  8; // S
  104.35 +    static final int PATTERN_DAY_OF_WEEK          =  9; // E
  104.36 +    static final int PATTERN_DAY_OF_YEAR          = 10; // D
  104.37 +    static final int PATTERN_DAY_OF_WEEK_IN_MONTH = 11; // F
  104.38 +    static final int PATTERN_WEEK_OF_YEAR         = 12; // w
  104.39 +    static final int PATTERN_WEEK_OF_MONTH        = 13; // W
  104.40 +    static final int PATTERN_AM_PM                = 14; // a
  104.41 +    static final int PATTERN_HOUR1                = 15; // h
  104.42 +    static final int PATTERN_HOUR0                = 16; // K
  104.43 +    static final int PATTERN_ZONE_NAME            = 17; // z
  104.44 +    static final int PATTERN_ZONE_VALUE           = 18; // Z
  104.45 +    static final int PATTERN_WEEK_YEAR            = 19; // Y
  104.46 +    static final int PATTERN_ISO_DAY_OF_WEEK      = 20; // u
  104.47 +    static final int PATTERN_ISO_ZONE             = 21; // X
  104.48  
  104.49      /**
  104.50       * Localized date-time pattern characters. For example, a locale may
  104.51 @@ -282,7 +305,7 @@
  104.52       * @since 1.6
  104.53       */
  104.54      public static final DateFormatSymbols getInstance() {
  104.55 -        return getInstance(Locale.getDefault());
  104.56 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT));
  104.57      }
  104.58  
  104.59      /**
  104.60 @@ -505,7 +528,7 @@
  104.61       * @return the localized date-time pattern characters.
  104.62       */
  104.63      public String getLocalPatternChars() {
  104.64 -        return new String(localPatternChars);
  104.65 +        return localPatternChars;
  104.66      }
  104.67  
  104.68      /**
  104.69 @@ -514,7 +537,8 @@
  104.70       * pattern characters.
  104.71       */
  104.72      public void setLocalPatternChars(String newLocalPatternChars) {
  104.73 -        localPatternChars = new String(newLocalPatternChars);
  104.74 +        // Call toString() to throw an NPE in case the argument is null
  104.75 +        localPatternChars = newLocalPatternChars.toString();
  104.76      }
  104.77  
  104.78      /**
  104.79 @@ -699,7 +723,7 @@
  104.80          } else {
  104.81              dst.zoneStrings = null;
  104.82          }
  104.83 -        dst.localPatternChars = new String (src.localPatternChars);
  104.84 +        dst.localPatternChars = src.localPatternChars;
  104.85      }
  104.86  
  104.87      /**
   105.1 --- a/src/share/classes/java/text/DecimalFormat.java	Thu Sep 23 17:33:40 2010 -0700
   105.2 +++ b/src/share/classes/java/text/DecimalFormat.java	Fri Sep 24 16:41:32 2010 -0700
   105.3 @@ -392,7 +392,7 @@
   105.4       * @see java.text.NumberFormat#getPercentInstance
   105.5       */
   105.6      public DecimalFormat() {
   105.7 -        Locale def = Locale.getDefault();
   105.8 +        Locale def = Locale.getDefault(Locale.Category.FORMAT);
   105.9          // try to get the pattern from the cache
  105.10          String pattern = (String) cachedLocaleData.get(def);
  105.11          if (pattern == null) {  /* cache miss */
  105.12 @@ -430,7 +430,7 @@
  105.13       */
  105.14      public DecimalFormat(String pattern) {
  105.15          // Always applyPattern after the symbols are set
  105.16 -        this.symbols = new DecimalFormatSymbols(Locale.getDefault());
  105.17 +        this.symbols = new DecimalFormatSymbols(Locale.getDefault(Locale.Category.FORMAT));
  105.18          applyPattern(pattern, false);
  105.19      }
  105.20  
   106.1 --- a/src/share/classes/java/text/DecimalFormatSymbols.java	Thu Sep 23 17:33:40 2010 -0700
   106.2 +++ b/src/share/classes/java/text/DecimalFormatSymbols.java	Fri Sep 24 16:41:32 2010 -0700
   106.3 @@ -1,5 +1,5 @@
   106.4  /*
   106.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   106.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   106.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   106.8   *
   106.9   * This code is free software; you can redistribute it and/or modify it
  106.10 @@ -43,10 +43,10 @@
  106.11  import java.io.Serializable;
  106.12  import java.text.spi.DecimalFormatSymbolsProvider;
  106.13  import java.util.Currency;
  106.14 -import java.util.Hashtable;
  106.15  import java.util.Locale;
  106.16  import java.util.ResourceBundle;
  106.17 -import java.util.spi.LocaleServiceProvider;
  106.18 +import java.util.concurrent.ConcurrentHashMap;
  106.19 +
  106.20  import sun.util.LocaleServiceProviderPool;
  106.21  import sun.util.resources.LocaleData;
  106.22  
  106.23 @@ -76,7 +76,7 @@
  106.24       * {@link #getInstance(Locale) getInstance} method.
  106.25       */
  106.26      public DecimalFormatSymbols() {
  106.27 -        initialize( Locale.getDefault() );
  106.28 +        initialize( Locale.getDefault(Locale.Category.FORMAT) );
  106.29      }
  106.30  
  106.31      /**
  106.32 @@ -125,7 +125,7 @@
  106.33       * @since 1.6
  106.34       */
  106.35      public static final DecimalFormatSymbols getInstance() {
  106.36 -        return getInstance(Locale.getDefault());
  106.37 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT));
  106.38      }
  106.39  
  106.40      /**
  106.41 @@ -527,10 +527,17 @@
  106.42  
  106.43          // get resource bundle data - try the cache first
  106.44          boolean needCacheUpdate = false;
  106.45 -        Object[] data = (Object[]) cachedLocaleData.get(locale);
  106.46 +        Object[] data = cachedLocaleData.get(locale);
  106.47          if (data == null) {  /* cache miss */
  106.48 +            // When numbering system is thai (Locale's extension contains u-nu-thai),
  106.49 +            // we read the data from th_TH_TH.
  106.50 +            Locale lookupLocale = locale;
  106.51 +            String numberType = locale.getUnicodeLocaleType("nu");
  106.52 +            if (numberType != null && numberType.equals("thai")) {
  106.53 +                lookupLocale = new Locale("th", "TH", "TH");
  106.54 +            }
  106.55              data = new Object[3];
  106.56 -            ResourceBundle rb = LocaleData.getNumberFormatData(locale);
  106.57 +            ResourceBundle rb = LocaleData.getNumberFormatData(lookupLocale);
  106.58              data[0] = rb.getStringArray("NumberElements");
  106.59              needCacheUpdate = true;
  106.60          }
  106.61 @@ -586,7 +593,7 @@
  106.62          monetarySeparator = decimalSeparator;
  106.63  
  106.64          if (needCacheUpdate) {
  106.65 -            cachedLocaleData.put(locale, data);
  106.66 +            cachedLocaleData.putIfAbsent(locale, data);
  106.67          }
  106.68      }
  106.69  
  106.70 @@ -806,7 +813,7 @@
  106.71       * cache to hold the NumberElements and the Currency
  106.72       * of a Locale.
  106.73       */
  106.74 -    private static final Hashtable cachedLocaleData = new Hashtable(3);
  106.75 +    private static final ConcurrentHashMap<Locale, Object[]> cachedLocaleData = new ConcurrentHashMap<Locale, Object[]>(3);
  106.76  
  106.77      /**
  106.78       * Obtains a DecimalFormatSymbols instance from a DecimalFormatSymbolsProvider
   107.1 --- a/src/share/classes/java/text/MessageFormat.java	Thu Sep 23 17:33:40 2010 -0700
   107.2 +++ b/src/share/classes/java/text/MessageFormat.java	Fri Sep 24 16:41:32 2010 -0700
   107.3 @@ -363,7 +363,7 @@
   107.4       * @exception IllegalArgumentException if the pattern is invalid
   107.5       */
   107.6      public MessageFormat(String pattern) {
   107.7 -        this.locale = Locale.getDefault();
   107.8 +        this.locale = Locale.getDefault(Locale.Category.FORMAT);
   107.9          applyPattern(pattern);
  107.10      }
  107.11  
   108.1 --- a/src/share/classes/java/text/NumberFormat.java	Thu Sep 23 17:33:40 2010 -0700
   108.2 +++ b/src/share/classes/java/text/NumberFormat.java	Fri Sep 24 16:41:32 2010 -0700
   108.3 @@ -381,7 +381,7 @@
   108.4       * {@link #getNumberInstance() getNumberInstance()}.
   108.5       */
   108.6      public final static NumberFormat getInstance() {
   108.7 -        return getInstance(Locale.getDefault(), NUMBERSTYLE);
   108.8 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
   108.9      }
  108.10  
  108.11      /**
  108.12 @@ -397,7 +397,7 @@
  108.13       * Returns a general-purpose number format for the current default locale.
  108.14       */
  108.15      public final static NumberFormat getNumberInstance() {
  108.16 -        return getInstance(Locale.getDefault(), NUMBERSTYLE);
  108.17 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
  108.18      }
  108.19  
  108.20      /**
  108.21 @@ -420,7 +420,7 @@
  108.22       * @since 1.4
  108.23       */
  108.24      public final static NumberFormat getIntegerInstance() {
  108.25 -        return getInstance(Locale.getDefault(), INTEGERSTYLE);
  108.26 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), INTEGERSTYLE);
  108.27      }
  108.28  
  108.29      /**
  108.30 @@ -443,7 +443,7 @@
  108.31       * Returns a currency format for the current default locale.
  108.32       */
  108.33      public final static NumberFormat getCurrencyInstance() {
  108.34 -        return getInstance(Locale.getDefault(), CURRENCYSTYLE);
  108.35 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), CURRENCYSTYLE);
  108.36      }
  108.37  
  108.38      /**
  108.39 @@ -457,7 +457,7 @@
  108.40       * Returns a percentage format for the current default locale.
  108.41       */
  108.42      public final static NumberFormat getPercentInstance() {
  108.43 -        return getInstance(Locale.getDefault(), PERCENTSTYLE);
  108.44 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), PERCENTSTYLE);
  108.45      }
  108.46  
  108.47      /**
  108.48 @@ -471,7 +471,7 @@
  108.49       * Returns a scientific format for the current default locale.
  108.50       */
  108.51      /*public*/ final static NumberFormat getScientificInstance() {
  108.52 -        return getInstance(Locale.getDefault(), SCIENTIFICSTYLE);
  108.53 +        return getInstance(Locale.getDefault(Locale.Category.FORMAT), SCIENTIFICSTYLE);
  108.54      }
  108.55  
  108.56      /**
   109.1 --- a/src/share/classes/java/text/SimpleDateFormat.java	Thu Sep 23 17:33:40 2010 -0700
   109.2 +++ b/src/share/classes/java/text/SimpleDateFormat.java	Fri Sep 24 16:41:32 2010 -0700
   109.3 @@ -1,5 +1,5 @@
   109.4  /*
   109.5 - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
   109.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   109.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   109.8   *
   109.9   * This code is free software; you can redistribute it and/or modify it
  109.10 @@ -55,6 +55,8 @@
  109.11  import sun.util.calendar.ZoneInfoFile;
  109.12  import sun.util.resources.LocaleData;
  109.13  
  109.14 +import static java.text.DateFormatSymbols.*;
  109.15 +
  109.16  /**
  109.17   * <code>SimpleDateFormat</code> is a concrete class for formatting and
  109.18   * parsing dates in a locale-sensitive manner. It allows for formatting
  109.19 @@ -108,40 +110,50 @@
  109.20   *         <td><a href="#year">Year</a>
  109.21   *         <td><code>1996</code>; <code>96</code>
  109.22   *     <tr>
  109.23 + *         <td><code>Y</code>
  109.24 + *         <td>Week year
  109.25 + *         <td><a href="#year">Year</a>
  109.26 + *         <td><code>2009</code>; <code>09</code>
  109.27 + *     <tr bgcolor="#eeeeff">
  109.28   *         <td><code>M</code>
  109.29   *         <td>Month in year
  109.30   *         <td><a href="#month">Month</a>
  109.31   *         <td><code>July</code>; <code>Jul</code>; <code>07</code>
  109.32 - *     <tr bgcolor="#eeeeff">
  109.33 + *     <tr>
  109.34   *         <td><code>w</code>
  109.35   *         <td>Week in year
  109.36   *         <td><a href="#number">Number</a>
  109.37   *         <td><code>27</code>
  109.38 - *     <tr>
  109.39 + *     <tr bgcolor="#eeeeff">
  109.40   *         <td><code>W</code>
  109.41   *         <td>Week in month
  109.42   *         <td><a href="#number">Number</a>
  109.43   *         <td><code>2</code>
  109.44 - *     <tr bgcolor="#eeeeff">
  109.45 + *     <tr>
  109.46   *         <td><code>D</code>
  109.47   *         <td>Day in year
  109.48   *         <td><a href="#number">Number</a>
  109.49   *         <td><code>189</code>
  109.50 - *     <tr>
  109.51 + *     <tr bgcolor="#eeeeff">
  109.52   *         <td><code>d</code>
  109.53   *         <td>Day in month
  109.54   *         <td><a href="#number">Number</a>
  109.55   *         <td><code>10</code>
  109.56 - *     <tr bgcolor="#eeeeff">
  109.57 + *     <tr>
  109.58   *         <td><code>F</code>
  109.59   *         <td>Day of week in month
  109.60   *         <td><a href="#number">Number</a>
  109.61   *         <td><code>2</code>
  109.62 - *     <tr>
  109.63 + *     <tr bgcolor="#eeeeff">
  109.64   *         <td><code>E</code>
  109.65 - *         <td>Day in week
  109.66 + *         <td>Day name in week
  109.67   *         <td><a href="#text">Text</a>
  109.68   *         <td><code>Tuesday</code>; <code>Tue</code>
  109.69 + *     <tr>
  109.70 + *         <td><code>u</code>
  109.71 + *         <td>Day number of week (1 = Monday, ..., 7 = Sunday)
  109.72 + *         <td><a href="#number">Number</a>
  109.73 + *         <td><code>1</code>
  109.74   *     <tr bgcolor="#eeeeff">
  109.75   *         <td><code>a</code>
  109.76   *         <td>Am/pm marker
  109.77 @@ -192,6 +204,11 @@
  109.78   *         <td>Time zone
  109.79   *         <td><a href="#rfc822timezone">RFC 822 time zone</a>
  109.80   *         <td><code>-0800</code>
  109.81 + *     <tr bgcolor="#eeeeff">
  109.82 + *         <td><code>X</code>
  109.83 + *         <td>Time zone
  109.84 + *         <td><a href="#iso8601timezone">ISO 8601 time zone</a>
  109.85 + *         <td><code>-08</code>; <code>-0800</code>;  <code>-08:00</code>
  109.86   * </table>
  109.87   * </blockquote>
  109.88   * Pattern letters are usually repeated, as their number determines the
  109.89 @@ -202,12 +219,12 @@
  109.90   *     the full form is used; otherwise a short or abbreviated form
  109.91   *     is used if available.
  109.92   *     For parsing, both forms are accepted, independent of the number
  109.93 - *     of pattern letters.
  109.94 + *     of pattern letters.<br><br></li>
  109.95   * <li><strong><a name="number">Number:</a></strong>
  109.96   *     For formatting, the number of pattern letters is the minimum
  109.97   *     number of digits, and shorter numbers are zero-padded to this amount.
  109.98   *     For parsing, the number of pattern letters is ignored unless
  109.99 - *     it's needed to separate two adjacent fields.
 109.100 + *     it's needed to separate two adjacent fields.<br><br></li>
 109.101   * <li><strong><a name="year">Year:</a></strong>
 109.102   *     If the formatter's {@link #getCalendar() Calendar} is the Gregorian
 109.103   *     calendar, the following rules are applied.<br>
 109.104 @@ -239,11 +256,20 @@
 109.105   *     letters is 4 or more, a calendar specific {@linkplain
 109.106   *     Calendar#LONG long form} is used. Otherwise, a calendar
 109.107   *     specific {@linkplain Calendar#SHORT short or abbreviated form}
 109.108 - *     is used.
 109.109 + *     is used.<br>
 109.110 + *     <br>
 109.111 + *     If week year {@code 'Y'} is specified and the {@linkplain
 109.112 + *     #getCalendar() calendar} doesn't support any <a
 109.113 + *     href="../util/GregorianCalendar.html#week_year"> week
 109.114 + *     years</a>, the calendar year ({@code 'y'}) is used instead. The
 109.115 + *     support of week years can be tested with a call to {@link
 109.116 + *     DateFormat#getCalendar() getCalendar()}.{@link
 109.117 + *     java.util.Calendar#isWeekDateSupported()
 109.118 + *     isWeekDateSupported()}.<br><br></li>
 109.119   * <li><strong><a name="month">Month:</a></strong>
 109.120   *     If the number of pattern letters is 3 or more, the month is
 109.121   *     interpreted as <a href="#text">text</a>; otherwise,
 109.122 - *     it is interpreted as a <a href="#number">number</a>.
 109.123 + *     it is interpreted as a <a href="#number">number</a>.<br><br></li>
 109.124   * <li><strong><a name="timezone">General time zone:</a></strong>
 109.125   *     Time zones are interpreted as <a href="#text">text</a> if they have
 109.126   *     names. For time zones representing a GMT offset value, the
 109.127 @@ -264,9 +290,10 @@
 109.128   *     00 and 59. The format is locale independent and digits must be taken
 109.129   *     from the Basic Latin block of the Unicode standard.
 109.130   *     <p>For parsing, <a href="#rfc822timezone">RFC 822 time zones</a> are also
 109.131 - *     accepted.
 109.132 + *     accepted.<br><br></li>
 109.133   * <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong>
 109.134   *     For formatting, the RFC 822 4-digit time zone format is used:
 109.135 + *
 109.136   *     <pre>
 109.137   *     <i>RFC822TimeZone:</i>
 109.138   *             <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
 109.139 @@ -274,8 +301,41 @@
 109.140   *             <i>Digit Digit</i></pre>
 109.141   *     <i>TwoDigitHours</i> must be between 00 and 23. Other definitions
 109.142   *     are as for <a href="#timezone">general time zones</a>.
 109.143 + *
 109.144   *     <p>For parsing, <a href="#timezone">general time zones</a> are also
 109.145   *     accepted.
 109.146 + * <li><strong><a name="iso8601timezone">ISO 8601 Time zone:</a></strong>
 109.147 + *     The number of pattern letters designates the format for both formatting
 109.148 + *     and parsing as follows:
 109.149 + *     <pre>
 109.150 + *     <i>ISO8601TimeZone:</i>
 109.151 + *             <i>OneLetterISO8601TimeZone</i>
 109.152 + *             <i>TwoLetterISO8601TimeZone</i>
 109.153 + *             <i>ThreeLetterISO8601TimeZone</i>
 109.154 + *     <i>OneLetterISO8601TimeZone:</i>
 109.155 + *             <i>Sign</i> <i>TwoDigitHours</i>
 109.156 + *             {@code Z}
 109.157 + *     <i>TwoLetterISO8601TimeZone:</i>
 109.158 + *             <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
 109.159 + *             {@code Z}
 109.160 + *     <i>ThreeLetterISO8601TimeZone:</i>
 109.161 + *             <i>Sign</i> <i>TwoDigitHours</i> {@code :} <i>Minutes</i>
 109.162 + *             {@code Z}</pre>
 109.163 + *     Other definitions are as for <a href="#timezone">general time zones</a> or
 109.164 + *     <a href="#rfc822timezone">RFC 822 time zones</a>.
 109.165 + *
 109.166 + *     <p>For formatting, if the offset value from GMT is 0, {@code "Z"} is
 109.167 + *     produced. If the number of pattern letters is 1, any fraction of an hour
 109.168 + *     is ignored. For example, if the pattern is {@code "X"} and the time zone is
 109.169 + *     {@code "GMT+05:30"}, {@code "+05"} is produced.
 109.170 + *
 109.171 + *     <p>For parsing, {@code "Z"} is parsed as the UTC time zone designator.
 109.172 + *     <a href="#timezone">General time zones</a> are <em>not</em> accepted.
 109.173 + *
 109.174 + *     <p>If the number of pattern letters is 4 or more, {@link
 109.175 + *     IllegalArgumentException} is thrown when constructing a {@code
 109.176 + *     SimpleDateFormat} or {@linkplain #applyPattern(String) applying a
 109.177 + *     pattern}.
 109.178   * </ul>
 109.179   * <code>SimpleDateFormat</code> also supports <em>localized date and time
 109.180   * pattern</em> strings. In these strings, the pattern letters described above
 109.181 @@ -321,6 +381,12 @@
 109.182   *     <tr>
 109.183   *         <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
 109.184   *         <td><code>2001-07-04T12:08:56.235-0700</code>
 109.185 + *     <tr bgcolor="#eeeeff">
 109.186 + *         <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
 109.187 + *         <td><code>2001-07-04T12:08:56.235-07:00</code>
 109.188 + *     <tr>
 109.189 + *         <td><code>"YYYY-'W'ww-u"</code>
 109.190 + *         <td><code>2001-W27-3</code>
 109.191   * </table>
 109.192   * </blockquote>
 109.193   *
 109.194 @@ -474,7 +540,7 @@
 109.195       * class.
 109.196       */
 109.197      public SimpleDateFormat() {
 109.198 -        this(SHORT, SHORT, Locale.getDefault());
 109.199 +        this(SHORT, SHORT, Locale.getDefault(Locale.Category.FORMAT));
 109.200      }
 109.201  
 109.202      /**
 109.203 @@ -490,7 +556,7 @@
 109.204       */
 109.205      public SimpleDateFormat(String pattern)
 109.206      {
 109.207 -        this(pattern, Locale.getDefault());
 109.208 +        this(pattern, Locale.getDefault(Locale.Category.FORMAT));
 109.209      }
 109.210  
 109.211      /**
 109.212 @@ -535,7 +601,7 @@
 109.213  
 109.214          this.pattern = pattern;
 109.215          this.formatData = (DateFormatSymbols) formatSymbols.clone();
 109.216 -        this.locale = Locale.getDefault();
 109.217 +        this.locale = Locale.getDefault(Locale.Category.FORMAT);
 109.218          initializeCalendar(this.locale);
 109.219          initialize(this.locale);
 109.220          useDateFormatSymbols = true;
 109.221 @@ -815,6 +881,9 @@
 109.222       * Encodes the given tag and length and puts encoded char(s) into buffer.
 109.223       */
 109.224      private static final void encode(int tag, int length, StringBuilder buffer) {
 109.225 +        if (tag == PATTERN_ISO_ZONE && length >= 4) {
 109.226 +            throw new IllegalArgumentException("invalid ISO 8601 format: length=" + length);
 109.227 +        }
 109.228          if (length < 255) {
 109.229              buffer.append((char)(tag << 8 | length));
 109.230          } else {
 109.231 @@ -877,7 +946,7 @@
 109.232       * @param pos the formatting position. On input: an alignment field,
 109.233       * if desired. On output: the offsets of the alignment field.
 109.234       * @return the formatted date-time string.
 109.235 -     * @exception NullPointerException if the given date is null
 109.236 +     * @exception NullPointerException if the given {@code date} is {@code null}.
 109.237       */
 109.238      public StringBuffer format(Date date, StringBuffer toAppendTo,
 109.239                                 FieldPosition pos)
 109.240 @@ -968,6 +1037,10 @@
 109.241          Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK_IN_MONTH,
 109.242          Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH,
 109.243          Calendar.AM_PM, Calendar.HOUR, Calendar.HOUR, Calendar.ZONE_OFFSET,
 109.244 +        Calendar.ZONE_OFFSET,
 109.245 +        // Pseudo Calendar fields
 109.246 +        CalendarBuilder.WEEK_YEAR,
 109.247 +        CalendarBuilder.ISO_DAY_OF_WEEK,
 109.248          Calendar.ZONE_OFFSET
 109.249      };
 109.250  
 109.251 @@ -982,6 +1055,8 @@
 109.252          DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.AM_PM_FIELD,
 109.253          DateFormat.HOUR1_FIELD, DateFormat.HOUR0_FIELD,
 109.254          DateFormat.TIMEZONE_FIELD, DateFormat.TIMEZONE_FIELD,
 109.255 +        DateFormat.YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD,
 109.256 +        DateFormat.TIMEZONE_FIELD
 109.257      };
 109.258  
 109.259      // Maps from DecimalFormatSymbols index to Field constant
 109.260 @@ -993,6 +1068,8 @@
 109.261          Field.WEEK_OF_YEAR, Field.WEEK_OF_MONTH,
 109.262          Field.AM_PM, Field.HOUR1, Field.HOUR0, Field.TIME_ZONE,
 109.263          Field.TIME_ZONE,
 109.264 +        Field.YEAR, Field.DAY_OF_WEEK,
 109.265 +        Field.TIME_ZONE
 109.266      };
 109.267  
 109.268      /**
 109.269 @@ -1007,9 +1084,24 @@
 109.270          int     beginOffset = buffer.length();
 109.271  
 109.272          int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
 109.273 -        int value = calendar.get(field);
 109.274 +        int value;
 109.275 +        if (field == CalendarBuilder.WEEK_YEAR) {
 109.276 +            if (calendar.isWeekDateSupported()) {
 109.277 +                value = calendar.getWeekYear();
 109.278 +            } else {
 109.279 +                // use calendar year 'y' instead
 109.280 +                patternCharIndex = PATTERN_YEAR;
 109.281 +                field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
 109.282 +                value = calendar.get(field);
 109.283 +            }
 109.284 +        } else if (field == CalendarBuilder.ISO_DAY_OF_WEEK) {
 109.285 +            value = CalendarBuilder.toISODayOfWeek(calendar.get(Calendar.DAY_OF_WEEK));
 109.286 +        } else {
 109.287 +            value = calendar.get(field);
 109.288 +        }
 109.289 +
 109.290          int style = (count >= 4) ? Calendar.LONG : Calendar.SHORT;
 109.291 -        if (!useDateFormatSymbols) {
 109.292 +        if (!useDateFormatSymbols && field != CalendarBuilder.ISO_DAY_OF_WEEK) {
 109.293              current = calendar.getDisplayName(field, style, locale);
 109.294          }
 109.295  
 109.296 @@ -1018,7 +1110,7 @@
 109.297          // zeroPaddingNumber() must be fixed.
 109.298  
 109.299          switch (patternCharIndex) {
 109.300 -        case 0: // 'G' - ERA
 109.301 +        case PATTERN_ERA: // 'G'
 109.302              if (useDateFormatSymbols) {
 109.303                  String[] eras = formatData.getEras();
 109.304                  if (value < eras.length)
 109.305 @@ -1028,7 +1120,8 @@
 109.306                  current = "";
 109.307              break;
 109.308  
 109.309 -        case 1: // 'y' - YEAR
 109.310 +        case PATTERN_WEEK_YEAR: // 'Y'
 109.311 +        case PATTERN_YEAR:      // 'y'
 109.312              if (calendar instanceof GregorianCalendar) {
 109.313                  if (count != 2)
 109.314                      zeroPaddingNumber(value, count, maxIntCount, buffer);
 109.315 @@ -1042,7 +1135,7 @@
 109.316              }
 109.317              break;
 109.318  
 109.319 -        case 2: // 'M' - MONTH
 109.320 +        case PATTERN_MONTH: // 'M'
 109.321              if (useDateFormatSymbols) {
 109.322                  String[] months;
 109.323                  if (count >= 4) {
 109.324 @@ -1062,7 +1155,7 @@
 109.325              }
 109.326              break;
 109.327  
 109.328 -        case 4: // 'k' - HOUR_OF_DAY: 1-based.  eg, 23:59 + 1 hour =>> 24:59
 109.329 +        case PATTERN_HOUR_OF_DAY1: // 'k' 1-based.  eg, 23:59 + 1 hour =>> 24:59
 109.330              if (current == null) {
 109.331                  if (value == 0)
 109.332                      zeroPaddingNumber(calendar.getMaximum(Calendar.HOUR_OF_DAY)+1,
 109.333 @@ -1072,7 +1165,7 @@
 109.334              }
 109.335              break;
 109.336  
 109.337 -        case 9: // 'E' - DAY_OF_WEEK
 109.338 +        case PATTERN_DAY_OF_WEEK: // 'E'
 109.339              if (useDateFormatSymbols) {
 109.340                  String[] weekdays;
 109.341                  if (count >= 4) {
 109.342 @@ -1085,14 +1178,14 @@
 109.343              }
 109.344              break;
 109.345  
 109.346 -        case 14:    // 'a' - AM_PM
 109.347 +        case PATTERN_AM_PM:    // 'a'
 109.348              if (useDateFormatSymbols) {
 109.349                  String[] ampm = formatData.getAmPmStrings();
 109.350                  current = ampm[value];
 109.351              }
 109.352              break;
 109.353  
 109.354 -        case 15: // 'h' - HOUR:1-based.  eg, 11PM + 1 hour =>> 12 AM
 109.355 +        case PATTERN_HOUR1:    // 'h' 1-based.  eg, 11PM + 1 hour =>> 12 AM
 109.356              if (current == null) {
 109.357                  if (value == 0)
 109.358                      zeroPaddingNumber(calendar.getLeastMaximum(Calendar.HOUR)+1,
 109.359 @@ -1102,7 +1195,7 @@
 109.360              }
 109.361              break;
 109.362  
 109.363 -        case 17: // 'z' - ZONE_OFFSET
 109.364 +        case PATTERN_ZONE_NAME: // 'z'
 109.365              if (current == null) {
 109.366                  if (formatData.locale == null || formatData.isZoneStringsSet) {
 109.367                      int zoneIndex =
 109.368 @@ -1129,7 +1222,7 @@
 109.369              }
 109.370              break;
 109.371  
 109.372 -        case 18: // 'Z' - ZONE_OFFSET ("-/+hhmm" form)
 109.373 +        case PATTERN_ZONE_VALUE: // 'Z' ("-/+hhmm" form)
 109.374              value = (calendar.get(Calendar.ZONE_OFFSET) +
 109.375                       calendar.get(Calendar.DST_OFFSET)) / 60000;
 109.376  
 109.377 @@ -1144,17 +1237,46 @@
 109.378              CalendarUtils.sprintf0d(buffer, num, width);
 109.379              break;
 109.380  
 109.381 +        case PATTERN_ISO_ZONE:   // 'X'
 109.382 +            value = calendar.get(Calendar.ZONE_OFFSET)
 109.383 +                    + calendar.get(Calendar.DST_OFFSET);
 109.384 +
 109.385 +            if (value == 0) {
 109.386 +                buffer.append('Z');
 109.387 +                break;
 109.388 +            }
 109.389 +
 109.390 +            value /=  60000;
 109.391 +            if (value >= 0) {
 109.392 +                buffer.append('+');
 109.393 +            } else {
 109.394 +                buffer.append('-');
 109.395 +                value = -value;
 109.396 +            }
 109.397 +
 109.398 +            CalendarUtils.sprintf0d(buffer, value / 60, 2);
 109.399 +            if (count == 1) {
 109.400 +                break;
 109.401 +            }
 109.402 +
 109.403 +            if (count == 3) {
 109.404 +                buffer.append(':');
 109.405 +            }
 109.406 +            CalendarUtils.sprintf0d(buffer, value % 60, 2);
 109.407 +            break;
 109.408 +
 109.409          default:
 109.410 -            // case 3: // 'd' - DATE
 109.411 -            // case 5: // 'H' - HOUR_OF_DAY:0-based.  eg, 23:59 + 1 hour =>> 00:59
 109.412 -            // case 6: // 'm' - MINUTE
 109.413 -            // case 7: // 's' - SECOND
 109.414 -            // case 8: // 'S' - MILLISECOND
 109.415 -            // case 10: // 'D' - DAY_OF_YEAR
 109.416 -            // case 11: // 'F' - DAY_OF_WEEK_IN_MONTH
 109.417 -            // case 12: // 'w' - WEEK_OF_YEAR
 109.418 -            // case 13: // 'W' - WEEK_OF_MONTH
 109.419 -            // case 16: // 'K' - HOUR: 0-based.  eg, 11PM + 1 hour =>> 0 AM
 109.420 +     // case PATTERN_DAY_OF_MONTH:         // 'd'
 109.421 +     // case PATTERN_HOUR_OF_DAY0:         // 'H' 0-based.  eg, 23:59 + 1 hour =>> 00:59
 109.422 +     // case PATTERN_MINUTE:               // 'm'
 109.423 +     // case PATTERN_SECOND:               // 's'
 109.424 +     // case PATTERN_MILLISECOND:          // 'S'
 109.425 +     // case PATTERN_DAY_OF_YEAR:          // 'D'
 109.426 +     // case PATTERN_DAY_OF_WEEK_IN_MONTH: // 'F'
 109.427 +     // case PATTERN_WEEK_OF_YEAR:         // 'w'
 109.428 +     // case PATTERN_WEEK_OF_MONTH:        // 'W'
 109.429 +     // case PATTERN_HOUR0:                // 'K' eg, 11PM + 1 hour =>> 0 AM
 109.430 +     // case PATTERN_ISO_DAY_OF_WEEK:      // 'u' pseudo field, Monday = 1, ..., Sunday = 7
 109.431              if (current == null) {
 109.432                  zeroPaddingNumber(value, count, maxIntCount, buffer);
 109.433              }
 109.434 @@ -1264,10 +1386,9 @@
 109.435          int oldStart = start;
 109.436          int textLength = text.length();
 109.437  
 109.438 -        calendar.clear(); // Clears all the time fields
 109.439 -
 109.440          boolean[] ambiguousYear = {false};
 109.441  
 109.442 +        CalendarBuilder calb = new CalendarBuilder();
 109.443  
 109.444          for (int i = 0; i < compiledPattern.length; ) {
 109.445              int tag = compiledPattern[i] >>> 8;
 109.446 @@ -1340,7 +1461,7 @@
 109.447                  }
 109.448                  start = subParse(text, start, tag, count, obeyCount,
 109.449                                   ambiguousYear, pos,
 109.450 -                                 useFollowingMinusSignAsDelimiter);
 109.451 +                                 useFollowingMinusSignAsDelimiter, calb);
 109.452                  if (start < 0) {
 109.453                      pos.index = oldStart;
 109.454                      return null;
 109.455 @@ -1354,46 +1475,16 @@
 109.456  
 109.457          pos.index = start;
 109.458  
 109.459 -        // This part is a problem:  When we call parsedDate.after, we compute the time.
 109.460 -        // Take the date April 3 2004 at 2:30 am.  When this is first set up, the year
 109.461 -        // will be wrong if we're parsing a 2-digit year pattern.  It will be 1904.
 109.462 -        // April 3 1904 is a Sunday (unlike 2004) so it is the DST onset day.  2:30 am
 109.463 -        // is therefore an "impossible" time, since the time goes from 1:59 to 3:00 am
 109.464 -        // on that day.  It is therefore parsed out to fields as 3:30 am.  Then we
 109.465 -        // add 100 years, and get April 3 2004 at 3:30 am.  Note that April 3 2004 is
 109.466 -        // a Saturday, so it can have a 2:30 am -- and it should. [LIU]
 109.467 -        /*
 109.468 -        Date parsedDate = calendar.getTime();
 109.469 -        if( ambiguousYear[0] && !parsedDate.after(defaultCenturyStart) ) {
 109.470 -            calendar.add(Calendar.YEAR, 100);
 109.471 -            parsedDate = calendar.getTime();
 109.472 -        }
 109.473 -        */
 109.474 -        // Because of the above condition, save off the fields in case we need to readjust.
 109.475 -        // The procedure we use here is not particularly efficient, but there is no other
 109.476 -        // way to do this given the API restrictions present in Calendar.  We minimize
 109.477 -        // inefficiency by only performing this computation when it might apply, that is,
 109.478 -        // when the two-digit year is equal to the start year, and thus might fall at the
 109.479 -        // front or the back of the default century.  This only works because we adjust
 109.480 -        // the year correctly to start with in other cases -- see subParse().
 109.481          Date parsedDate;
 109.482          try {
 109.483 -            if (ambiguousYear[0]) // If this is true then the two-digit year == the default start year
 109.484 -            {
 109.485 -                // We need a copy of the fields, and we need to avoid triggering a call to
 109.486 -                // complete(), which will recalculate the fields.  Since we can't access
 109.487 -                // the fields[] array in Calendar, we clone the entire object.  This will
 109.488 -                // stop working if Calendar.clone() is ever rewritten to call complete().
 109.489 -                Calendar savedCalendar = (Calendar)calendar.clone();
 109.490 -                parsedDate = calendar.getTime();
 109.491 -                if (parsedDate.before(defaultCenturyStart))
 109.492 -                {
 109.493 -                    // We can't use add here because that does a complete() first.
 109.494 -                    savedCalendar.set(Calendar.YEAR, defaultCenturyStartYear + 100);
 109.495 -                    parsedDate = savedCalendar.getTime();
 109.496 +            parsedDate = calb.establish(calendar).getTime();
 109.497 +            // If the year value is ambiguous,
 109.498 +            // then the two-digit year == the default start year
 109.499 +            if (ambiguousYear[0]) {
 109.500 +                if (parsedDate.before(defaultCenturyStart)) {
 109.501 +                    parsedDate = calb.addYear(100).establish(calendar).getTime();
 109.502                  }
 109.503              }
 109.504 -            else parsedDate = calendar.getTime();
 109.505          }
 109.506          // An IllegalArgumentException will be thrown by Calendar.getTime()
 109.507          // if any fields are out of range, e.g., MONTH == 17.
 109.508 @@ -1415,7 +1506,7 @@
 109.509       * @return the new start position if matching succeeded; a negative number
 109.510       * indicating matching failure, otherwise.
 109.511       */
 109.512 -    private int matchString(String text, int start, int field, String[] data)
 109.513 +    private int matchString(String text, int start, int field, String[] data, CalendarBuilder calb)
 109.514      {
 109.515          int i = 0;
 109.516          int count = data.length;
 109.517 @@ -1441,7 +1532,7 @@
 109.518          }
 109.519          if (bestMatch >= 0)
 109.520          {
 109.521 -            calendar.set(field, bestMatch);
 109.522 +            calb.set(field, bestMatch);
 109.523              return start + bestMatchLength;
 109.524          }
 109.525          return -start;
 109.526 @@ -1452,7 +1543,8 @@
 109.527       * String[]). This method takes a Map<String, Integer> instead of
 109.528       * String[].
 109.529       */
 109.530 -    private int matchString(String text, int start, int field, Map<String,Integer> data) {
 109.531 +    private int matchString(String text, int start, int field,
 109.532 +                            Map<String,Integer> data, CalendarBuilder calb) {
 109.533          if (data != null) {
 109.534              String bestMatch = null;
 109.535  
 109.536 @@ -1466,7 +1558,7 @@
 109.537              }
 109.538  
 109.539              if (bestMatch != null) {
 109.540 -                calendar.set(field, data.get(bestMatch));
 109.541 +                calb.set(field, data.get(bestMatch));
 109.542                  return start + bestMatch.length();
 109.543              }
 109.544          }
 109.545 @@ -1486,11 +1578,22 @@
 109.546          return -1;
 109.547      }
 109.548  
 109.549 +    private boolean matchDSTString(String text, int start, int zoneIndex, int standardIndex,
 109.550 +                                   String[][] zoneStrings) {
 109.551 +        int index = standardIndex + 2;
 109.552 +        String zoneName  = zoneStrings[zoneIndex][index];
 109.553 +        if (text.regionMatches(true, start,
 109.554 +                               zoneName, 0, zoneName.length())) {
 109.555 +            return true;
 109.556 +        }
 109.557 +        return false;
 109.558 +    }
 109.559 +
 109.560      /**
 109.561       * find time zone 'text' matched zoneStrings and set to internal
 109.562       * calendar.
 109.563       */
 109.564 -    private int subParseZoneString(String text, int start) {
 109.565 +    private int subParseZoneString(String text, int start, CalendarBuilder calb) {
 109.566          boolean useSameName = false; // true if standard and daylight time use the same abbreviation.
 109.567          TimeZone currentTimeZone = getTimeZone();
 109.568  
 109.569 @@ -1524,6 +1627,7 @@
 109.570                  }
 109.571              }
 109.572          }
 109.573 +
 109.574          if (tz == null) {
 109.575              int len = zoneStrings.length;
 109.576              for (int i = 0; i < len; i++) {
 109.577 @@ -1549,8 +1653,8 @@
 109.578              // determine the local time. (6645292)
 109.579              int dstAmount = (nameIndex >= 3) ? tz.getDSTSavings() : 0;
 109.580              if (!(useSameName || (nameIndex >= 3 && dstAmount == 0))) {
 109.581 -                calendar.set(Calendar.ZONE_OFFSET, tz.getRawOffset());
 109.582 -                calendar.set(Calendar.DST_OFFSET, dstAmount);
 109.583 +                calb.set(Calendar.ZONE_OFFSET, tz.getRawOffset())
 109.584 +                    .set(Calendar.DST_OFFSET, dstAmount);
 109.585              }
 109.586              return (start + zoneNames[nameIndex].length());
 109.587          }
 109.588 @@ -1577,11 +1681,15 @@
 109.589      private int subParse(String text, int start, int patternCharIndex, int count,
 109.590                           boolean obeyCount, boolean[] ambiguousYear,
 109.591                           ParsePosition origPos,
 109.592 -                         boolean useFollowingMinusSignAsDelimiter) {
 109.593 +                         boolean useFollowingMinusSignAsDelimiter, CalendarBuilder calb) {
 109.594          Number number = null;
 109.595          int value = 0;
 109.596          ParsePosition pos = new ParsePosition(0);
 109.597          pos.index = start;
 109.598 +        if (patternCharIndex == PATTERN_WEEK_YEAR && !calendar.isWeekDateSupported()) {
 109.599 +            // use calendar year 'y' instead
 109.600 +            patternCharIndex = PATTERN_YEAR;
 109.601 +        }
 109.602          int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
 109.603  
 109.604          // If there are any spaces here, skip over them.  If we hit the end
 109.605 @@ -1602,10 +1710,11 @@
 109.606              // a number value.  We handle further, more generic cases below.  We need
 109.607              // to handle some of them here because some fields require extra processing on
 109.608              // the parsed value.
 109.609 -            if (patternCharIndex == 4 /* HOUR_OF_DAY1_FIELD */ ||
 109.610 -                patternCharIndex == 15 /* HOUR1_FIELD */ ||
 109.611 -                (patternCharIndex == 2 /* MONTH_FIELD */ && count <= 2) ||
 109.612 -                patternCharIndex == 1 /* YEAR_FIELD */) {
 109.613 +            if (patternCharIndex == PATTERN_HOUR_OF_DAY1 ||
 109.614 +                patternCharIndex == PATTERN_HOUR1 ||
 109.615 +                (patternCharIndex == PATTERN_MONTH && count <= 2) ||
 109.616 +                patternCharIndex == PATTERN_YEAR ||
 109.617 +                patternCharIndex == PATTERN_WEEK_YEAR) {
 109.618                  // It would be good to unify this with the obeyCount logic below,
 109.619                  // but that's going to be difficult.
 109.620                  if (obeyCount) {
 109.621 @@ -1617,7 +1726,7 @@
 109.622                      number = numberFormat.parse(text, pos);
 109.623                  }
 109.624                  if (number == null) {
 109.625 -                    if (patternCharIndex != 1 || calendar instanceof GregorianCalendar) {
 109.626 +                    if (patternCharIndex != PATTERN_YEAR || calendar instanceof GregorianCalendar) {
 109.627                          break parsing;
 109.628                      }
 109.629                  } else {
 109.630 @@ -1638,33 +1747,34 @@
 109.631  
 109.632              int index;
 109.633              switch (patternCharIndex) {
 109.634 -            case 0: // 'G' - ERA
 109.635 +            case PATTERN_ERA: // 'G'
 109.636                  if (useDateFormatSymbols) {
 109.637 -                    if ((index = matchString(text, start, Calendar.ERA, formatData.getEras())) > 0) {
 109.638 +                    if ((index = matchString(text, start, Calendar.ERA, formatData.getEras(), calb)) > 0) {
 109.639                          return index;
 109.640                      }
 109.641                  } else {
 109.642                      Map<String, Integer> map = calendar.getDisplayNames(field,
 109.643                                                                          Calendar.ALL_STYLES,
 109.644                                                                          locale);
 109.645 -                    if ((index = matchString(text, start, field, map)) > 0) {
 109.646 +                    if ((index = matchString(text, start, field, map, calb)) > 0) {
 109.647                          return index;
 109.648                      }
 109.649                  }
 109.650                  break parsing;
 109.651  
 109.652 -            case 1: // 'y' - YEAR
 109.653 +            case PATTERN_WEEK_YEAR: // 'Y'
 109.654 +            case PATTERN_YEAR:      // 'y'
 109.655                  if (!(calendar instanceof GregorianCalendar)) {
 109.656                      // calendar might have text representations for year values,
 109.657                      // such as "\u5143" in JapaneseImperialCalendar.
 109.658                      int style = (count >= 4) ? Calendar.LONG : Calendar.SHORT;
 109.659                      Map<String, Integer> map = calendar.getDisplayNames(field, style, locale);
 109.660                      if (map != null) {
 109.661 -                        if ((index = matchString(text, start, field, map)) > 0) {
 109.662 +                        if ((index = matchString(text, start, field, map, calb)) > 0) {
 109.663                              return index;
 109.664                          }
 109.665                      }
 109.666 -                    calendar.set(field, value);
 109.667 +                    calb.set(field, value);
 109.668                      return pos.index;
 109.669                  }
 109.670  
 109.671 @@ -1676,8 +1786,7 @@
 109.672                  // is treated literally:  "2250", "-1", "1", "002".
 109.673                  if (count <= 2 && (pos.index - start) == 2
 109.674                      && Character.isDigit(text.charAt(start))
 109.675 -                    && Character.isDigit(text.charAt(start+1)))
 109.676 -                {
 109.677 +                    && Character.isDigit(text.charAt(start+1))) {
 109.678                      // Assume for example that the defaultCenturyStart is 6/18/1903.
 109.679                      // This means that two-digit years will be forced into the range
 109.680                      // 6/18/1903 to 6/17/2003.  As a result, years 00, 01, and 02
 109.681 @@ -1691,16 +1800,16 @@
 109.682                      value += (defaultCenturyStartYear/100)*100 +
 109.683                          (value < ambiguousTwoDigitYear ? 100 : 0);
 109.684                  }
 109.685 -                calendar.set(Calendar.YEAR, value);
 109.686 +                calb.set(field, value);
 109.687                  return pos.index;
 109.688  
 109.689 -            case 2: // 'M' - MONTH
 109.690 +            case PATTERN_MONTH: // 'M'
 109.691                  if (count <= 2) // i.e., M or MM.
 109.692                  {
 109.693                      // Don't want to parse the month if it is a string
 109.694                      // while pattern uses numeric style: M or MM.
 109.695                      // [We computed 'value' above.]
 109.696 -                    calendar.set(Calendar.MONTH, value - 1);
 109.697 +                    calb.set(Calendar.MONTH, value - 1);
 109.698                      return pos.index;
 109.699                  }
 109.700  
 109.701 @@ -1710,50 +1819,50 @@
 109.702                      // Try count == 4 first:
 109.703                      int newStart = 0;
 109.704                      if ((newStart = matchString(text, start, Calendar.MONTH,
 109.705 -                                                formatData.getMonths())) > 0) {
 109.706 +                                                formatData.getMonths(), calb)) > 0) {
 109.707                          return newStart;
 109.708                      }
 109.709                      // count == 4 failed, now try count == 3
 109.710                      if ((index = matchString(text, start, Calendar.MONTH,
 109.711 -                                             formatData.getShortMonths())) > 0) {
 109.712 +                                             formatData.getShortMonths(), calb)) > 0) {
 109.713                          return index;
 109.714                      }
 109.715                  } else {
 109.716                      Map<String, Integer> map = calendar.getDisplayNames(field,
 109.717                                                                          Calendar.ALL_STYLES,
 109.718                                                                          locale);
 109.719 -                    if ((index = matchString(text, start, field, map)) > 0) {
 109.720 +                    if ((index = matchString(text, start, field, map, calb)) > 0) {
 109.721                          return index;
 109.722                      }
 109.723                  }
 109.724                  break parsing;
 109.725  
 109.726 -            case 4: // 'k' - HOUR_OF_DAY: 1-based.  eg, 23:59 + 1 hour =>> 24:59
 109.727 +            case PATTERN_HOUR_OF_DAY1: // 'k' 1-based.  eg, 23:59 + 1 hour =>> 24:59
 109.728                  // [We computed 'value' above.]
 109.729                  if (value == calendar.getMaximum(Calendar.HOUR_OF_DAY)+1) value = 0;
 109.730 -                calendar.set(Calendar.HOUR_OF_DAY, value);
 109.731 +                calb.set(Calendar.HOUR_OF_DAY, value);
 109.732                  return pos.index;
 109.733  
 109.734 -            case 9:
 109.735 -                { // 'E' - DAY_OF_WEEK
 109.736 +            case PATTERN_DAY_OF_WEEK:  // 'E'
 109.737 +                {
 109.738                      if (useDateFormatSymbols) {
 109.739                          // Want to be able to parse both short and long forms.
 109.740                          // Try count == 4 (DDDD) first:
 109.741                          int newStart = 0;
 109.742                          if ((newStart=matchString(text, start, Calendar.DAY_OF_WEEK,
 109.743 -                                                  formatData.getWeekdays())) > 0) {
 109.744 +                                                  formatData.getWeekdays(), calb)) > 0) {
 109.745                              return newStart;
 109.746                          }
 109.747                          // DDDD failed, now try DDD
 109.748                          if ((index = matchString(text, start, Calendar.DAY_OF_WEEK,
 109.749 -                                                 formatData.getShortWeekdays())) > 0) {
 109.750 +                                                 formatData.getShortWeekdays(), calb)) > 0) {
 109.751                              return index;
 109.752                          }
 109.753                      } else {
 109.754                          int[] styles = { Calendar.LONG, Calendar.SHORT };
 109.755                          for (int style : styles) {
 109.756                              Map<String,Integer> map = calendar.getDisplayNames(field, style, locale);
 109.757 -                            if ((index = matchString(text, start, field, map)) > 0) {
 109.758 +                            if ((index = matchString(text, start, field, map, calb)) > 0) {
 109.759                                  return index;
 109.760                              }
 109.761                          }
 109.762 @@ -1761,27 +1870,28 @@
 109.763                  }
 109.764                  break parsing;
 109.765  
 109.766 -            case 14:    // 'a' - AM_PM
 109.767 +            case PATTERN_AM_PM:    // 'a'
 109.768                  if (useDateFormatSymbols) {
 109.769 -                    if ((index = matchString(text, start, Calendar.AM_PM, formatData.getAmPmStrings())) > 0) {
 109.770 +                    if ((index = matchString(text, start, Calendar.AM_PM,
 109.771 +                                             formatData.getAmPmStrings(), calb)) > 0) {
 109.772                          return index;
 109.773                      }
 109.774                  } else {
 109.775                      Map<String,Integer> map = calendar.getDisplayNames(field, Calendar.ALL_STYLES, locale);
 109.776 -                    if ((index = matchString(text, start, field, map)) > 0) {
 109.777 +                    if ((index = matchString(text, start, field, map, calb)) > 0) {
 109.778                          return index;
 109.779                      }
 109.780                  }
 109.781                  break parsing;
 109.782  
 109.783 -            case 15: // 'h' - HOUR:1-based.  eg, 11PM + 1 hour =>> 12 AM
 109.784 +            case PATTERN_HOUR1: // 'h' 1-based.  eg, 11PM + 1 hour =>> 12 AM
 109.785                  // [We computed 'value' above.]
 109.786                  if (value == calendar.getLeastMaximum(Calendar.HOUR)+1) value = 0;
 109.787 -                calendar.set(Calendar.HOUR, value);
 109.788 +                calb.set(Calendar.HOUR, value);
 109.789                  return pos.index;
 109.790  
 109.791 -            case 17: // 'z' - ZONE_OFFSET
 109.792 -            case 18: // 'Z' - ZONE_OFFSET
 109.793 +            case PATTERN_ZONE_NAME:  // 'z'
 109.794 +            case PATTERN_ZONE_VALUE: // 'Z'
 109.795                  // First try to parse generic forms such as GMT-07:00. Do this first
 109.796                  // in case localized TimeZoneNames contains the string "GMT"
 109.797                  // for a zone; in that case, we don't want to match the first three
 109.798 @@ -1797,7 +1907,7 @@
 109.799                      if ((text.length() - start) >= GMT.length() &&
 109.800                          text.regionMatches(true, start, GMT, 0, GMT.length())) {
 109.801                          int num;
 109.802 -                        calendar.set(Calendar.DST_OFFSET, 0);
 109.803 +                        calb.set(Calendar.DST_OFFSET, 0);
 109.804                          pos.index = start + GMT.length();
 109.805  
 109.806                          try { // try-catch for "GMT" only time zone string
 109.807 @@ -1810,8 +1920,8 @@
 109.808                          }
 109.809                          catch(StringIndexOutOfBoundsException e) {}
 109.810  
 109.811 -                        if (sign == 0) {        /* "GMT" without offset */
 109.812 -                            calendar.set(Calendar.ZONE_OFFSET, 0);
 109.813 +                        if (sign == 0) {    /* "GMT" without offset */
 109.814 +                            calb.set(Calendar.ZONE_OFFSET, 0);
 109.815                              return pos.index;
 109.816                          }
 109.817  
 109.818 @@ -1875,7 +1985,7 @@
 109.819                                  sign = -1;
 109.820                              } else {
 109.821                                  // Try parsing the text as a time zone name (abbr).
 109.822 -                                int i = subParseZoneString(text, pos.index);
 109.823 +                                int i = subParseZoneString(text, pos.index, calb);
 109.824                                  if (i != 0) {
 109.825                                      return i;
 109.826                                  }
 109.827 @@ -1933,24 +2043,112 @@
 109.828                      // arrive here if the form GMT+/-... or an RFC 822 form was seen.
 109.829                      if (sign != 0) {
 109.830                          offset *= MILLIS_PER_MINUTE * sign;
 109.831 -                        calendar.set(Calendar.ZONE_OFFSET, offset);
 109.832 -                        calendar.set(Calendar.DST_OFFSET, 0);
 109.833 +                        calb.set(Calendar.ZONE_OFFSET, offset).set(Calendar.DST_OFFSET, 0);
 109.834 +                        return ++pos.index;
 109.835 +                    }
 109.836 +                }
 109.837 +                break parsing;
 109.838 +
 109.839 +            case PATTERN_ISO_ZONE:   // 'X'
 109.840 +                {
 109.841 +                    int sign = 0;
 109.842 +                    int offset = 0;
 109.843 +
 109.844 +                    iso8601: {
 109.845 +                        try {
 109.846 +                            char c = text.charAt(pos.index);
 109.847 +                            if (c == 'Z') {
 109.848 +                                calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0);
 109.849 +                                return ++pos.index;
 109.850 +                            }
 109.851 +
 109.852 +                            // parse text as "+/-hh[[:]mm]" based on count
 109.853 +                            if (c == '+') {
 109.854 +                                sign = 1;
 109.855 +                            } else if (c == '-') {
 109.856 +                                sign = -1;
 109.857 +                            }
 109.858 +                            // Look for hh.
 109.859 +                            int hours = 0;
 109.860 +                            c = text.charAt(++pos.index);
 109.861 +                            if (c < '0' || c > '9') { /* must be from '0' to '9'. */
 109.862 +                                break parsing;
 109.863 +                            }
 109.864 +                            hours = c - '0';
 109.865 +                            c = text.charAt(++pos.index);
 109.866 +                            if (c < '0' || c > '9') { /* must be from '0' to '9'. */
 109.867 +                                break parsing;
 109.868 +                            }
 109.869 +                            hours *= 10;
 109.870 +                            hours += c - '0';
 109.871 +                            if (hours > 23) {
 109.872 +                                break parsing;
 109.873 +                            }
 109.874 +
 109.875 +                            if (count == 1) { // "X"
 109.876 +                                offset = hours * 60;
 109.877 +                                break iso8601;
 109.878 +                            }
 109.879 +
 109.880 +                            c = text.charAt(++pos.index);
 109.881 +                            // Skip ':' if "XXX"
 109.882 +                            if (c == ':') {
 109.883 +                                if (count == 2) {
 109.884 +                                    break parsing;
 109.885 +                                }
 109.886 +                                c = text.charAt(++pos.index);
 109.887 +                            } else {
 109.888 +                                if (count == 3) {
 109.889 +                                    // missing ':'
 109.890 +                                    break parsing;
 109.891 +                                }
 109.892 +                            }
 109.893 +
 109.894 +                            // Look for mm.
 109.895 +                            int minutes = 0;
 109.896 +                            if (c < '0' || c > '9') { /* must be from '0' to '9'. */
 109.897 +                                break parsing;
 109.898 +                            }
 109.899 +                            minutes = c - '0';
 109.900 +                            c = text.charAt(++pos.index);
 109.901 +                            if (c < '0' || c > '9') { /* must be from '0' to '9'. */
 109.902 +                                break parsing;
 109.903 +                            }
 109.904 +                            minutes *= 10;
 109.905 +                            minutes += c - '0';
 109.906 +
 109.907 +                            if (minutes > 59) {
 109.908 +                                break parsing;
 109.909 +                            }
 109.910 +
 109.911 +                            offset = hours * 60 + minutes;
 109.912 +                        } catch (StringIndexOutOfBoundsException e) {
 109.913 +                            break parsing;
 109.914 +                        }
 109.915 +                    }
 109.916 +
 109.917 +                    // Do the final processing for both of the above cases.  We only
 109.918 +                    // arrive here if the form GMT+/-... or an RFC 822 form was seen.
 109.919 +                    if (sign != 0) {
 109.920 +                        offset *= MILLIS_PER_MINUTE * sign;
 109.921 +                        calb.set(Calendar.ZONE_OFFSET, offset).set(Calendar.DST_OFFSET, 0);
 109.922                          return ++pos.index;
 109.923                      }
 109.924                  }
 109.925                  break parsing;
 109.926  
 109.927              default:
 109.928 -                // case 3: // 'd' - DATE
 109.929 -                // case 5: // 'H' - HOUR_OF_DAY:0-based.  eg, 23:59 + 1 hour =>> 00:59
 109.930 -                // case 6: // 'm' - MINUTE
 109.931 -                // case 7: // 's' - SECOND
 109.932 -                // case 8: // 'S' - MILLISECOND
 109.933 -                // case 10: // 'D' - DAY_OF_YEAR
 109.934 -                // case 11: // 'F' - DAY_OF_WEEK_IN_MONTH
 109.935 -                // case 12: // 'w' - WEEK_OF_YEAR
 109.936 -                // case 13: // 'W' - WEEK_OF_MONTH
 109.937 -                // case 16: // 'K' - HOUR: 0-based.  eg, 11PM + 1 hour =>> 0 AM
 109.938 +         // case PATTERN_DAY_OF_MONTH:         // 'd'
 109.939 +         // case PATTERN_HOUR_OF_DAY0:         // 'H' 0-based.  eg, 23:59 + 1 hour =>> 00:59
 109.940 +         // case PATTERN_MINUTE:               // 'm'
 109.941 +         // case PATTERN_SECOND:               // 's'
 109.942 +         // case PATTERN_MILLISECOND:          // 'S'
 109.943 +         // case PATTERN_DAY_OF_YEAR:          // 'D'
 109.944 +         // case PATTERN_DAY_OF_WEEK_IN_MONTH: // 'F'
 109.945 +         // case PATTERN_WEEK_OF_YEAR:         // 'w'
 109.946 +         // case PATTERN_WEEK_OF_MONTH:        // 'W'
 109.947 +         // case PATTERN_HOUR0:                // 'K' 0-based.  eg, 11PM + 1 hour =>> 0 AM
 109.948 +         // case PATTERN_ISO_DAY_OF_WEEK:      // 'u' (pseudo field);
 109.949  
 109.950                  // Handle "generic" fields
 109.951                  if (obeyCount) {
 109.952 @@ -1973,7 +2171,7 @@
 109.953                          pos.index--;
 109.954                      }
 109.955  
 109.956 -                    calendar.set(field, value);
 109.957 +                    calb.set(field, value);
 109.958                      return pos.index;
 109.959                  }
 109.960                  break parsing;
 109.961 @@ -2020,11 +2218,18 @@
 109.962                      inQuote = true;
 109.963                  else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
 109.964                      int ci = from.indexOf(c);
 109.965 -                    if (ci == -1)
 109.966 +                    if (ci >= 0) {
 109.967 +                        // patternChars is longer than localPatternChars due
 109.968 +                        // to serialization compatibility. The pattern letters
 109.969 +                        // unsupported by localPatternChars pass through.
 109.970 +                        if (ci < to.length()) {
 109.971 +                            c = to.charAt(ci);
 109.972 +                        }
 109.973 +                    } else {
 109.974                          throw new IllegalArgumentException("Illegal pattern " +
 109.975                                                             " character '" +
 109.976                                                             c + "'");
 109.977 -                    c = to.charAt(ci);
 109.978 +                    }
 109.979                  }
 109.980              }
 109.981              result.append(c);
 109.982 @@ -2061,7 +2266,7 @@
 109.983       * @exception NullPointerException if the given pattern is null
 109.984       * @exception IllegalArgumentException if the given pattern is invalid
 109.985       */
 109.986 -    public void applyPattern (String pattern)
 109.987 +    public void applyPattern(String pattern)
 109.988      {
 109.989          compiledPattern = compile(pattern);
 109.990          this.pattern = pattern;
   110.1 --- a/src/share/classes/java/util/Calendar.java	Thu Sep 23 17:33:40 2010 -0700
   110.2 +++ b/src/share/classes/java/util/Calendar.java	Fri Sep 24 16:41:32 2010 -0700
   110.3 @@ -1,5 +1,5 @@
   110.4  /*
   110.5 - * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
   110.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   110.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   110.8   *
   110.9   * This code is free software; you can redistribute it and/or modify it
  110.10 @@ -119,7 +119,7 @@
  110.11   * calculating its time or calendar field values if any out-of-range field
  110.12   * value has been set.
  110.13   *
  110.14 - * <h4>First Week</h4>
  110.15 + * <h4><a name="first_week">First Week</a></h4>
  110.16   *
  110.17   * <code>Calendar</code> defines a locale-specific seven day week using two
  110.18   * parameters: the first day of the week and the minimal days in first week
  110.19 @@ -933,7 +933,7 @@
  110.20       */
  110.21      protected Calendar()
  110.22      {
  110.23 -        this(TimeZone.getDefaultRef(), Locale.getDefault());
  110.24 +        this(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
  110.25          sharedZone = true;
  110.26      }
  110.27  
  110.28 @@ -962,7 +962,7 @@
  110.29       */
  110.30      public static Calendar getInstance()
  110.31      {
  110.32 -        Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault());
  110.33 +        Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
  110.34          cal.sharedZone = true;
  110.35          return cal;
  110.36      }
  110.37 @@ -977,7 +977,7 @@
  110.38       */
  110.39      public static Calendar getInstance(TimeZone zone)
  110.40      {
  110.41 -        return createCalendar(zone, Locale.getDefault());
  110.42 +        return createCalendar(zone, Locale.getDefault(Locale.Category.FORMAT));
  110.43      }
  110.44  
  110.45      /**
  110.46 @@ -1013,19 +1013,30 @@
  110.47      private static Calendar createCalendar(TimeZone zone,
  110.48                                             Locale aLocale)
  110.49      {
  110.50 -        // If the specified locale is a Thai locale, returns a BuddhistCalendar
  110.51 -        // instance.
  110.52 -        if ("th".equals(aLocale.getLanguage())
  110.53 -            && ("TH".equals(aLocale.getCountry()))) {
  110.54 -            return new sun.util.BuddhistCalendar(zone, aLocale);
  110.55 -        } else if ("JP".equals(aLocale.getVariant())
  110.56 -                   && "JP".equals(aLocale.getCountry())
  110.57 -                   && "ja".equals(aLocale.getLanguage())) {
  110.58 -            return new JapaneseImperialCalendar(zone, aLocale);
  110.59 +        Calendar cal = null;
  110.60 +
  110.61 +        String caltype = aLocale.getUnicodeLocaleType("ca");
  110.62 +        if (caltype == null) {
  110.63 +            // Calendar type is not specified.
  110.64 +            // If the specified locale is a Thai locale,
  110.65 +            // returns a BuddhistCalendar instance.
  110.66 +            if ("th".equals(aLocale.getLanguage())
  110.67 +                    && ("TH".equals(aLocale.getCountry()))) {
  110.68 +                    cal = new BuddhistCalendar(zone, aLocale);
  110.69 +            } else {
  110.70 +                cal = new GregorianCalendar(zone, aLocale);
  110.71 +            }
  110.72 +        } else if (caltype.equals("japanese")) {
  110.73 +            cal = new JapaneseImperialCalendar(zone, aLocale);
  110.74 +        } else if (caltype.equals("buddhist")) {
  110.75 +            cal = new BuddhistCalendar(zone, aLocale);
  110.76 +        } else {
  110.77 +            // Unsupported calendar type.
  110.78 +            // Use Gregorian calendar as a fallback.
  110.79 +            cal = new GregorianCalendar(zone, aLocale);
  110.80          }
  110.81  
  110.82 -        // else create the default calendar
  110.83 -        return new GregorianCalendar(zone, aLocale);
  110.84 +        return cal;
  110.85      }
  110.86  
  110.87      /**
  110.88 @@ -2196,6 +2207,101 @@
  110.89      }
  110.90  
  110.91      /**
  110.92 +     * Returns whether this {@code Calendar} supports week dates.
  110.93 +     *
  110.94 +     * <p>The default implementation of this method returns {@code false}.
  110.95 +     *
  110.96 +     * @return {@code true} if this {@code Calendar} supports week dates;
  110.97 +     *         {@code false} otherwise.
  110.98 +     * @see #getWeekYear()
  110.99 +     * @see #setWeekDate(int,int,int)
 110.100 +     * @see #getWeeksInWeekYear()
 110.101 +     * @since 1.7
 110.102 +     */
 110.103 +    public boolean isWeekDateSupported() {
 110.104 +        return false;
 110.105 +    }
 110.106 +
 110.107 +    /**
 110.108 +     * Returns the week year represented by this {@code Calendar}. The
 110.109 +     * week year is in sync with the week cycle. The {@linkplain
 110.110 +     * #getFirstDayOfWeek() first day of the first week} is the first
 110.111 +     * day of the week year.
 110.112 +     *
 110.113 +     * <p>The default implementation of this method throws an
 110.114 +     * {@link UnsupportedOperationException}.
 110.115 +     *
 110.116 +     * @return the week year of this {@code Calendar}
 110.117 +     * @exception UnsupportedOperationException
 110.118 +     *            if any week year numbering isn't supported
 110.119 +     *            in this {@code Calendar}.
 110.120 +     * @see #isWeekDateSupported()
 110.121 +     * @see #getFirstDayOfWeek()
 110.122 +     * @see #getMinimalDaysInFirstWeek()
 110.123 +     * @since 1.7
 110.124 +     */
 110.125 +    public int getWeekYear() {
 110.126 +        throw new UnsupportedOperationException();
 110.127 +    }
 110.128 +
 110.129 +    /**
 110.130 +     * Sets the date of this {@code Calendar} with the the given date
 110.131 +     * specifiers - week year, week of year, and day of week.
 110.132 +     *
 110.133 +     * <p>Unlike the {@code set} method, all of the calendar fields
 110.134 +     * and {@code time} values are calculated upon return.
 110.135 +     *
 110.136 +     * <p>If {@code weekOfYear} is out of the valid week-of-year range
 110.137 +     * in {@code weekYear}, the {@code weekYear} and {@code
 110.138 +     * weekOfYear} values are adjusted in lenient mode, or an {@code
 110.139 +     * IllegalArgumentException} is thrown in non-lenient mode.
 110.140 +     *
 110.141 +     * <p>The default implementation of this method throws an
 110.142 +     * {@code UnsupportedOperationException}.
 110.143 +     *
 110.144 +     * @param weekYear   the week year
 110.145 +     * @param weekOfYear the week number based on {@code weekYear}
 110.146 +     * @param dayOfWeek  the day of week value: one of the constants
 110.147 +     *                   for the {@link #DAY_OF_WEEK} field: {@link
 110.148 +     *                   #SUNDAY}, ..., {@link #SATURDAY}.
 110.149 +     * @exception IllegalArgumentException
 110.150 +     *            if any of the given date specifiers is invalid
 110.151 +     *            or any of the calendar fields are inconsistent
 110.152 +     *            with the given date specifiers in non-lenient mode
 110.153 +     * @exception UnsupportedOperationException
 110.154 +     *            if any week year numbering isn't supported in this
 110.155 +     *            {@code Calendar}.
 110.156 +     * @see #isWeekDateSupported()
 110.157 +     * @see #getFirstDayOfWeek()
 110.158 +     * @see #getMinimalDaysInFirstWeek()
 110.159 +     * @since 1.7
 110.160 +     */
 110.161 +    public void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {
 110.162 +        throw new UnsupportedOperationException();
 110.163 +    }
 110.164 +
 110.165 +    /**
 110.166 +     * Returns the number of weeks in the week year represented by this
 110.167 +     * {@code Calendar}.
 110.168 +     *
 110.169 +     * <p>The default implementation of this method throws an
 110.170 +     * {@code UnsupportedOperationException}.
 110.171 +     *
 110.172 +     * @return the number of weeks in the week year.
 110.173 +     * @exception UnsupportedOperationException
 110.174 +     *            if any week year numbering isn't supported in this
 110.175 +     *            {@code Calendar}.
 110.176 +     * @see #WEEK_OF_YEAR
 110.177 +     * @see #isWeekDateSupported()
 110.178 +     * @see #getWeekYear()
 110.179 +     * @see #getActualMaximum(int)
 110.180 +     * @since 1.7
 110.181 +     */
 110.182 +    public int getWeeksInWeekYear() {
 110.183 +        throw new UnsupportedOperationException();
 110.184 +    }
 110.185 +
 110.186 +    /**
 110.187       * Returns the minimum value for the given calendar field of this
 110.188       * <code>Calendar</code> instance. The minimum value is defined as
 110.189       * the smallest value returned by the {@link #get(int) get} method
   111.1 --- a/src/share/classes/java/util/ConcurrentModificationException.java	Thu Sep 23 17:33:40 2010 -0700
   111.2 +++ b/src/share/classes/java/util/ConcurrentModificationException.java	Fri Sep 24 16:41:32 2010 -0700
   111.3 @@ -49,9 +49,9 @@
   111.4   * <p>Note that fail-fast behavior cannot be guaranteed as it is, generally
   111.5   * speaking, impossible to make any hard guarantees in the presence of
   111.6   * unsynchronized concurrent modification.  Fail-fast operations
   111.7 - * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
   111.8 + * throw {@code ConcurrentModificationException} on a best-effort basis.
   111.9   * Therefore, it would be wrong to write a program that depended on this
  111.10 - * exception for its correctness: <i><tt>ConcurrentModificationException</tt>
  111.11 + * exception for its correctness: <i>{@code ConcurrentModificationException}
  111.12   * should be used only to detect bugs.</i>
  111.13   *
  111.14   * @author  Josh Bloch
  111.15 @@ -77,7 +77,7 @@
  111.16      }
  111.17  
  111.18      /**
  111.19 -     * Constructs a <tt>ConcurrentModificationException</tt> with the
  111.20 +     * Constructs a {@code ConcurrentModificationException} with the
  111.21       * specified detail message.
  111.22       *
  111.23       * @param message the detail message pertaining to this exception.
  111.24 @@ -85,4 +85,39 @@
  111.25      public ConcurrentModificationException(String message) {
  111.26          super(message);
  111.27      }
  111.28 +
  111.29 +    /**
  111.30 +     * Constructs a new exception with the specified cause and a detail
  111.31 +     * message of {@code (cause==null ? null : cause.toString())} (which
  111.32 +     * typically contains the class and detail message of {@code cause}.
  111.33 +     *
  111.34 +     * @param  cause the cause (which is saved for later retrieval by the
  111.35 +     *         {@link Throwable#getCause()} method).  (A {@code null} value is
  111.36 +     *         permitted, and indicates that the cause is nonexistent or
  111.37 +     *         unknown.)
  111.38 +     * @since  1.7
  111.39 +     */
  111.40 +    public ConcurrentModificationException(Throwable cause) {
  111.41 +        super(cause);
  111.42 +    }
  111.43 +
  111.44 +    /**
  111.45 +     * Constructs a new exception with the specified detail message and
  111.46 +     * cause.
  111.47 +     *
  111.48 +     * <p>Note that the detail message associated with <code>cause</code> is
  111.49 +     * <i>not</i> automatically incorporated in this exception's detail
  111.50 +     * message.
  111.51 +     *
  111.52 +     * @param  message the detail message (which is saved for later retrieval
  111.53 +     *         by the {@link Throwable#getMessage()} method).
  111.54 +     * @param  cause the cause (which is saved for later retrieval by the
  111.55 +     *         {@link Throwable#getCause()} method).  (A {@code null} value
  111.56 +     *         is permitted, and indicates that the cause is nonexistent or
  111.57 +     *         unknown.)
  111.58 +     * @since 1.7
  111.59 +     */
  111.60 +    public ConcurrentModificationException(String message, Throwable cause) {
  111.61 +        super(message, cause);
  111.62 +    }
  111.63  }
   112.1 --- a/src/share/classes/java/util/Currency.java	Thu Sep 23 17:33:40 2010 -0700
   112.2 +++ b/src/share/classes/java/util/Currency.java	Fri Sep 24 16:41:32 2010 -0700
   112.3 @@ -452,7 +452,7 @@
   112.4       * @return the symbol of this currency for the default locale
   112.5       */
   112.6      public String getSymbol() {
   112.7 -        return getSymbol(Locale.getDefault());
   112.8 +        return getSymbol(Locale.getDefault(Locale.Category.DISPLAY));
   112.9      }
  112.10  
  112.11      /**
  112.12 @@ -528,7 +528,7 @@
  112.13       * @since 1.7
  112.14       */
  112.15      public String getDisplayName() {
  112.16 -        return getDisplayName(Locale.getDefault());
  112.17 +        return getDisplayName(Locale.getDefault(Locale.Category.DISPLAY));
  112.18      }
  112.19  
  112.20      /**
   113.1 --- a/src/share/classes/java/util/Formatter.java	Thu Sep 23 17:33:40 2010 -0700
   113.2 +++ b/src/share/classes/java/util/Formatter.java	Fri Sep 24 16:41:32 2010 -0700
   113.3 @@ -1866,7 +1866,7 @@
   113.4       * virtual machine.
   113.5       */
   113.6      public Formatter() {
   113.7 -        init(new StringBuilder(), Locale.getDefault());
   113.8 +        init(new StringBuilder(), Locale.getDefault(Locale.Category.FORMAT));
   113.9      }
  113.10  
  113.11      /**
  113.12 @@ -1882,7 +1882,7 @@
  113.13      public Formatter(Appendable a) {
  113.14          if (a == null)
  113.15              a = new StringBuilder();
  113.16 -        init(a, Locale.getDefault());
  113.17 +        init(a, Locale.getDefault(Locale.Category.FORMAT));
  113.18      }
  113.19  
  113.20      /**
  113.21 @@ -1949,7 +1949,7 @@
  113.22       */
  113.23      public Formatter(String fileName) throws FileNotFoundException {
  113.24          init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
  113.25 -             Locale.getDefault());
  113.26 +             Locale.getDefault(Locale.Category.FORMAT));
  113.27      }
  113.28  
  113.29      /**
  113.30 @@ -1985,7 +1985,7 @@
  113.31      public Formatter(String fileName, String csn)
  113.32          throws FileNotFoundException, UnsupportedEncodingException
  113.33      {
  113.34 -        this(fileName, csn, Locale.getDefault());
  113.35 +        this(fileName, csn, Locale.getDefault(Locale.Category.FORMAT));
  113.36      }
  113.37  
  113.38      /**
  113.39 @@ -2057,7 +2057,7 @@
  113.40       */
  113.41      public Formatter(File file) throws FileNotFoundException {
  113.42          init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
  113.43 -             Locale.getDefault());
  113.44 +             Locale.getDefault(Locale.Category.FORMAT));
  113.45      }
  113.46  
  113.47      /**
  113.48 @@ -2093,7 +2093,7 @@
  113.49      public Formatter(File file, String csn)
  113.50          throws FileNotFoundException, UnsupportedEncodingException
  113.51      {
  113.52 -        this(file, csn, Locale.getDefault());
  113.53 +        this(file, csn, Locale.getDefault(Locale.Category.FORMAT));
  113.54      }
  113.55  
  113.56      /**
  113.57 @@ -2152,7 +2152,7 @@
  113.58      public Formatter(PrintStream ps) {
  113.59          if (ps == null)
  113.60              throw new NullPointerException();
  113.61 -        init((Appendable)ps, Locale.getDefault());
  113.62 +        init((Appendable)ps, Locale.getDefault(Locale.Category.FORMAT));
  113.63      }
  113.64  
  113.65      /**
  113.66 @@ -2171,7 +2171,7 @@
  113.67       */
  113.68      public Formatter(OutputStream os) {
  113.69          init(new BufferedWriter(new OutputStreamWriter(os)),
  113.70 -             Locale.getDefault());
  113.71 +             Locale.getDefault(Locale.Category.FORMAT));
  113.72      }
  113.73  
  113.74      /**
  113.75 @@ -2195,7 +2195,7 @@
  113.76      public Formatter(OutputStream os, String csn)
  113.77          throws UnsupportedEncodingException
  113.78      {
  113.79 -        this(os, csn, Locale.getDefault());
  113.80 +        this(os, csn, Locale.getDefault(Locale.Category.FORMAT));
  113.81      }
  113.82  
  113.83      /**
   114.1 --- a/src/share/classes/java/util/GregorianCalendar.java	Thu Sep 23 17:33:40 2010 -0700
   114.2 +++ b/src/share/classes/java/util/GregorianCalendar.java	Fri Sep 24 16:41:32 2010 -0700
   114.3 @@ -1,5 +1,5 @@
   114.4  /*
   114.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   114.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   114.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   114.8   *
   114.9   * This code is free software; you can redistribute it and/or modify it
  114.10 @@ -88,23 +88,49 @@
  114.11   * adjustment may be made if desired for dates that are prior to the Gregorian
  114.12   * changeover and which fall between January 1 and March 24.
  114.13   *
  114.14 - * <p>Values calculated for the <code>WEEK_OF_YEAR</code> field range from 1 to
  114.15 - * 53.  Week 1 for a year is the earliest seven day period starting on
  114.16 - * <code>getFirstDayOfWeek()</code> that contains at least
  114.17 - * <code>getMinimalDaysInFirstWeek()</code> days from that year.  It thus
  114.18 - * depends on the values of <code>getMinimalDaysInFirstWeek()</code>,
  114.19 - * <code>getFirstDayOfWeek()</code>, and the day of the week of January 1.
  114.20 - * Weeks between week 1 of one year and week 1 of the following year are
  114.21 - * numbered sequentially from 2 to 52 or 53 (as needed).
  114.22 -
  114.23 - * <p>For example, January 1, 1998 was a Thursday.  If
  114.24 - * <code>getFirstDayOfWeek()</code> is <code>MONDAY</code> and
  114.25 - * <code>getMinimalDaysInFirstWeek()</code> is 4 (these are the values
  114.26 - * reflecting ISO 8601 and many national standards), then week 1 of 1998 starts
  114.27 - * on December 29, 1997, and ends on January 4, 1998.  If, however,
  114.28 - * <code>getFirstDayOfWeek()</code> is <code>SUNDAY</code>, then week 1 of 1998
  114.29 - * starts on January 4, 1998, and ends on January 10, 1998; the first three days
  114.30 - * of 1998 then are part of week 53 of 1997.
  114.31 + * <h4><a name="week_and_year">Week Of Year and Week Year</a></h4>
  114.32 + *
  114.33 + * <p>Values calculated for the {@link Calendar#WEEK_OF_YEAR
  114.34 + * WEEK_OF_YEAR} field range from 1 to 53. The first week of a
  114.35 + * calendar year is the earliest seven day period starting on {@link
  114.36 + * Calendar#getFirstDayOfWeek() getFirstDayOfWeek()} that contains at
  114.37 + * least {@link Calendar#getMinimalDaysInFirstWeek()
  114.38 + * getMinimalDaysInFirstWeek()} days from that year. It thus depends
  114.39 + * on the values of {@code getMinimalDaysInFirstWeek()}, {@code
  114.40 + * getFirstDayOfWeek()}, and the day of the week of January 1. Weeks
  114.41 + * between week 1 of one year and week 1 of the following year
  114.42 + * (exclusive) are numbered sequentially from 2 to 52 or 53 (except
  114.43 + * for year(s) involved in the Julian-Gregorian transition).
  114.44 + *
  114.45 + * <p>The {@code getFirstDayOfWeek()} and {@code
  114.46 + * getMinimalDaysInFirstWeek()} values are initialized using
  114.47 + * locale-dependent resources when constructing a {@code
  114.48 + * GregorianCalendar}. <a name="iso8601_compatible_setting">The week
  114.49 + * determination is compatible</a> with the ISO 8601 standard when {@code
  114.50 + * getFirstDayOfWeek()} is {@code MONDAY} and {@code
  114.51 + * getMinimalDaysInFirstWeek()} is 4, which values are used in locales
  114.52 + * where the standard is preferred. These values can explicitly be set by
  114.53 + * calling {@link Calendar#setFirstDayOfWeek(int) setFirstDayOfWeek()} and
  114.54 + * {@link Calendar#setMinimalDaysInFirstWeek(int)
  114.55 + * setMinimalDaysInFirstWeek()}.
  114.56 + *
  114.57 + * <p>A <a name="week_year"><em>week year</em></a> is in sync with a
  114.58 + * {@code WEEK_OF_YEAR} cycle. All weeks between the first and last
  114.59 + * weeks (inclusive) have the same <em>week year</em> value.
  114.60 + * Therefore, the first and last days of a week year may have
  114.61 + * different calendar year values.
  114.62 + *
  114.63 + * <p>For example, January 1, 1998 is a Thursday. If {@code
  114.64 + * getFirstDayOfWeek()} is {@code MONDAY} and {@code
  114.65 + * getMinimalDaysInFirstWeek()} is 4 (ISO 8601 standard compatible
  114.66 + * setting), then week 1 of 1998 starts on December 29, 1997, and ends
  114.67 + * on January 4, 1998. The week year is 1998 for the last three days
  114.68 + * of calendar year 1997. If, however, {@code getFirstDayOfWeek()} is
  114.69 + * {@code SUNDAY}, then week 1 of 1998 starts on January 4, 1998, and
  114.70 + * ends on January 10, 1998; the first three days of 1998 then are
  114.71 + * part of week 53 of 1997 and their week year is 1997.
  114.72 + *
  114.73 + * <h4>Week Of Month</h4>
  114.74   *
  114.75   * <p>Values calculated for the <code>WEEK_OF_MONTH</code> field range from 0
  114.76   * to 6.  Week 1 of a month (the days with <code>WEEK_OF_MONTH =
  114.77 @@ -124,7 +150,9 @@
  114.78   * <code>getMinimalDaysInFirstWeek()</code> is changed to 3, then January 1
  114.79   * through January 3 have a <code>WEEK_OF_MONTH</code> of 1.
  114.80   *
  114.81 - * <p>The <code>clear</code> methods set calendar field(s)
  114.82 + * <h4>Default Fields Values</h4>
  114.83 + *
  114.84 + * <p>The <code>clear</code> method sets calendar field(s)
  114.85   * undefined. <code>GregorianCalendar</code> uses the following
  114.86   * default value for each calendar field if its value is undefined.
  114.87   *
  114.88 @@ -555,7 +583,7 @@
  114.89       * in the default time zone with the default locale.
  114.90       */
  114.91      public GregorianCalendar() {
  114.92 -        this(TimeZone.getDefaultRef(), Locale.getDefault());
  114.93 +        this(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT));
  114.94          setZoneShared(true);
  114.95      }
  114.96  
  114.97 @@ -566,7 +594,7 @@
  114.98       * @param zone the given time zone.
  114.99       */
 114.100      public GregorianCalendar(TimeZone zone) {
 114.101 -        this(zone, Locale.getDefault());
 114.102 +        this(zone, Locale.getDefault(Locale.Category.FORMAT));
 114.103      }
 114.104  
 114.105      /**
 114.106 @@ -1625,6 +1653,13 @@
 114.107       * is 29 because 2004 is a leap year, and if the date of this
 114.108       * instance is February 1, 2005, it's 28.
 114.109       *
 114.110 +     * <p>This method calculates the maximum value of {@link
 114.111 +     * Calendar#WEEK_OF_YEAR WEEK_OF_YEAR} based on the {@link
 114.112 +     * Calendar#YEAR YEAR} (calendar year) value, not the <a
 114.113 +     * href="#week_year">week year</a>. Call {@link
 114.114 +     * #getWeeksInWeekYear()} to get the maximum value of {@code
 114.115 +     * WEEK_OF_YEAR} in the week year of this {@code GregorianCalendar}.
 114.116 +     *
 114.117       * @param field the calendar field
 114.118       * @return the maximum of the given field for the time value of
 114.119       * this <code>GregorianCalendar</code>
 114.120 @@ -1742,8 +1777,13 @@
 114.121                  if (gc == this) {
 114.122                      gc = (GregorianCalendar) gc.clone();
 114.123                  }
 114.124 -                gc.set(DAY_OF_YEAR, getActualMaximum(DAY_OF_YEAR));
 114.125 +                int maxDayOfYear = getActualMaximum(DAY_OF_YEAR);
 114.126 +                gc.set(DAY_OF_YEAR, maxDayOfYear);
 114.127                  value = gc.get(WEEK_OF_YEAR);
 114.128 +                if (internalGet(YEAR) != gc.getWeekYear()) {
 114.129 +                    gc.set(DAY_OF_YEAR, maxDayOfYear - 7);
 114.130 +                    value = gc.get(WEEK_OF_YEAR);
 114.131 +                }
 114.132              }
 114.133              break;
 114.134  
 114.135 @@ -1934,46 +1974,241 @@
 114.136          }
 114.137      }
 114.138  
 114.139 -//////////////////////
 114.140 -// Proposed public API
 114.141 -//////////////////////
 114.142 +    /**
 114.143 +     * Returns {@code true} indicating this {@code GregorianCalendar}
 114.144 +     * supports week dates.
 114.145 +     *
 114.146 +     * @return {@code true} (always)
 114.147 +     * @see #getWeekYear()
 114.148 +     * @see #setWeekDate(int,int,int)
 114.149 +     * @see #getWeeksInWeekYear()
 114.150 +     * @since 1.7
 114.151 +     */
 114.152 +    @Override
 114.153 +    public final boolean isWeekDateSupported() {
 114.154 +        return true;
 114.155 +    }
 114.156  
 114.157      /**
 114.158 -     * Returns the year that corresponds to the <code>WEEK_OF_YEAR</code> field.
 114.159 -     * This may be one year before or after the Gregorian or Julian year stored
 114.160 -     * in the <code>YEAR</code> field.  For example, January 1, 1999 is considered
 114.161 -     * Friday of week 53 of 1998 (if minimal days in first week is
 114.162 -     * 2 or less, and the first day of the week is Sunday).  Given
 114.163 -     * these same settings, the ISO year of January 1, 1999 is
 114.164 -     * 1998.
 114.165 +     * Returns the <a href="#week_year">week year</a> represented by this
 114.166 +     * {@code GregorianCalendar}. The dates in the weeks between 1 and the
 114.167 +     * maximum week number of the week year have the same week year value
 114.168 +     * that may be one year before or after the {@link Calendar#YEAR YEAR}
 114.169 +     * (calendar year) value.
 114.170       *
 114.171 -     * <p>This method calls {@link Calendar#complete} before
 114.172 -     * calculating the week-based year.
 114.173 +     * <p>This method calls {@link Calendar#complete()} before
 114.174 +     * calculating the week year.
 114.175       *
 114.176 -     * @return the year corresponding to the <code>WEEK_OF_YEAR</code> field, which
 114.177 -     * may be one year before or after the <code>YEAR</code> field.
 114.178 -     * @see #YEAR
 114.179 -     * @see #WEEK_OF_YEAR
 114.180 +     * @return the week year represented by this {@code GregorianCalendar}.
 114.181 +     *         If the {@link Calendar#ERA ERA} value is {@link #BC}, the year is
 114.182 +     *         represented by 0 or a negative number: BC 1 is 0, BC 2
 114.183 +     *         is -1, BC 3 is -2, and so on.
 114.184 +     * @throws IllegalArgumentException
 114.185 +     *         if any of the calendar fields is invalid in non-lenient mode.
 114.186 +     * @see #isWeekDateSupported()
 114.187 +     * @see #getWeeksInWeekYear()
 114.188 +     * @see Calendar#getFirstDayOfWeek()
 114.189 +     * @see Calendar#getMinimalDaysInFirstWeek()
 114.190 +     * @since 1.7
 114.191       */
 114.192 -    /*
 114.193 -    public int getWeekBasedYear() {
 114.194 -        complete();
 114.195 -        // TODO: Below doesn't work for gregorian cutover...
 114.196 -        int weekOfYear = internalGet(WEEK_OF_YEAR);
 114.197 -        int year = internalGet(YEAR);
 114.198 -        if (internalGet(MONTH) == Calendar.JANUARY) {
 114.199 -            if (weekOfYear >= 52) {
 114.200 +    @Override
 114.201 +    public int getWeekYear() {
 114.202 +        int year = get(YEAR); // implicitly calls complete()
 114.203 +        if (internalGetEra() == BCE) {
 114.204 +            year = 1 - year;
 114.205 +        }
 114.206 +
 114.207 +        // Fast path for the Gregorian calendar years that are never
 114.208 +        // affected by the Julian-Gregorian transition
 114.209 +        if (year > gregorianCutoverYear + 1) {
 114.210 +            int weekOfYear = internalGet(WEEK_OF_YEAR);
 114.211 +            if (internalGet(MONTH) == JANUARY) {
 114.212 +                if (weekOfYear >= 52) {
 114.213 +                    --year;
 114.214 +                }
 114.215 +            } else {
 114.216 +                if (weekOfYear == 1) {
 114.217 +                    ++year;
 114.218 +                }
 114.219 +            }
 114.220 +            return year;
 114.221 +        }
 114.222 +
 114.223 +        // General (slow) path
 114.224 +        int dayOfYear = internalGet(DAY_OF_YEAR);
 114.225 +        int maxDayOfYear = getActualMaximum(DAY_OF_YEAR);
 114.226 +        int minimalDays = getMinimalDaysInFirstWeek();
 114.227 +
 114.228 +        // Quickly check the possibility of year adjustments before
 114.229 +        // cloning this GregorianCalendar.
 114.230 +        if (dayOfYear > minimalDays && dayOfYear < (maxDayOfYear - 6)) {
 114.231 +            return year;
 114.232 +        }
 114.233 +
 114.234 +        // Create a clone to work on the calculation
 114.235 +        GregorianCalendar cal = (GregorianCalendar) clone();
 114.236 +        cal.setLenient(true);
 114.237 +        // Use GMT so that intermediate date calculations won't
 114.238 +        // affect the time of day fields.
 114.239 +        cal.setTimeZone(TimeZone.getTimeZone("GMT"));
 114.240 +        // Go to the first day of the year, which is usually January 1.
 114.241 +        cal.set(DAY_OF_YEAR, 1);
 114.242 +        cal.complete();
 114.243 +
 114.244 +        // Get the first day of the first day-of-week in the year.
 114.245 +        int delta = getFirstDayOfWeek() - cal.get(DAY_OF_WEEK);
 114.246 +        if (delta != 0) {
 114.247 +            if (delta < 0) {
 114.248 +                delta += 7;
 114.249 +            }
 114.250 +            cal.add(DAY_OF_YEAR, delta);
 114.251 +        }
 114.252 +        int minDayOfYear = cal.get(DAY_OF_YEAR);
 114.253 +        if (dayOfYear < minDayOfYear) {
 114.254 +            if (minDayOfYear <= minimalDays) {
 114.255                  --year;
 114.256              }
 114.257          } else {
 114.258 -            if (weekOfYear == 1) {
 114.259 -                ++year;
 114.260 +            cal.set(YEAR, year + 1);
 114.261 +            cal.set(DAY_OF_YEAR, 1);
 114.262 +            cal.complete();
 114.263 +            int del = getFirstDayOfWeek() - cal.get(DAY_OF_WEEK);
 114.264 +            if (del != 0) {
 114.265 +                if (del < 0) {
 114.266 +                    del += 7;
 114.267 +                }
 114.268 +                cal.add(DAY_OF_YEAR, del);
 114.269 +            }
 114.270 +            minDayOfYear = cal.get(DAY_OF_YEAR) - 1;
 114.271 +            if (minDayOfYear == 0) {
 114.272 +                minDayOfYear = 7;
 114.273 +            }
 114.274 +            if (minDayOfYear >= minimalDays) {
 114.275 +                int days = maxDayOfYear - dayOfYear + 1;
 114.276 +                if (days <= (7 - minDayOfYear)) {
 114.277 +                    ++year;
 114.278 +                }
 114.279              }
 114.280          }
 114.281          return year;
 114.282      }
 114.283 -    */
 114.284  
 114.285 +    /**
 114.286 +     * Sets this {@code GregorianCalendar} to the date given by the
 114.287 +     * date specifiers - <a href="#week_year">{@code weekYear}</a>,
 114.288 +     * {@code weekOfYear}, and {@code dayOfWeek}. {@code weekOfYear}
 114.289 +     * follows the <a href="#week_and_year">{@code WEEK_OF_YEAR}
 114.290 +     * numbering</a>.  The {@code dayOfWeek} value must be one of the
 114.291 +     * {@link Calendar#DAY_OF_WEEK DAY_OF_WEEK} values: {@link
 114.292 +     * Calendar#SUNDAY SUNDAY} to {@link Calendar#SATURDAY SATURDAY}.
 114.293 +     *
 114.294 +     * <p>Note that the numeric day-of-week representation differs from
 114.295 +     * the ISO 8601 standard, and that the {@code weekOfYear}
 114.296 +     * numbering is compatible with the standard when {@code
 114.297 +     * getFirstDayOfWeek()} is {@code MONDAY} and {@code
 114.298 +     * getMinimalDaysInFirstWeek()} is 4.
 114.299 +     *
 114.300 +     * <p>Unlike the {@code set} method, all of the calendar fields
 114.301 +     * and the instant of time value are calculated upon return.
 114.302 +     *
 114.303 +     * <p>If {@code weekOfYear} is out of the valid week-of-year
 114.304 +     * range in {@code weekYear}, the {@code weekYear}
 114.305 +     * and {@code weekOfYear} values are adjusted in lenient
 114.306 +     * mode, or an {@code IllegalArgumentException} is thrown in
 114.307 +     * non-lenient mode.
 114.308 +     *
 114.309 +     * @param weekYear    the week year
 114.310 +     * @param weekOfYear  the week number based on {@code weekYear}
 114.311 +     * @param dayOfWeek   the day of week value: one of the constants
 114.312 +     *                    for the {@link #DAY_OF_WEEK DAY_OF_WEEK} field:
 114.313 +     *                    {@link Calendar#SUNDAY SUNDAY}, ...,
 114.314 +     *                    {@link Calendar#SATURDAY SATURDAY}.
 114.315 +     * @exception IllegalArgumentException
 114.316 +     *            if any of the given date specifiers is invalid,
 114.317 +     *            or if any of the calendar fields are inconsistent
 114.318 +     *            with the given date specifiers in non-lenient mode
 114.319 +     * @see GregorianCalendar#isWeekDateSupported()
 114.320 +     * @see Calendar#getFirstDayOfWeek()
 114.321 +     * @see Calendar#getMinimalDaysInFirstWeek()
 114.322 +     * @since 1.7
 114.323 +     */
 114.324 +    @Override
 114.325 +    public void setWeekDate(int weekYear, int weekOfYear, int dayOfWeek) {
 114.326 +        if (dayOfWeek < SUNDAY || dayOfWeek > SATURDAY) {
 114.327 +            throw new IllegalArgumentException("invalid dayOfWeek: " + dayOfWeek);
 114.328 +        }
 114.329 +
 114.330 +        // To avoid changing the time of day fields by date
 114.331 +        // calculations, use a clone with the GMT time zone.
 114.332 +        GregorianCalendar gc = (GregorianCalendar) clone();
 114.333 +        gc.setLenient(true);
 114.334 +        int era = gc.get(ERA);
 114.335 +        gc.clear();
 114.336 +        gc.setTimeZone(TimeZone.getTimeZone("GMT"));
 114.337 +        gc.set(ERA, era);
 114.338 +        gc.set(YEAR, weekYear);
 114.339 +        gc.set(WEEK_OF_YEAR, 1);
 114.340 +        gc.set(DAY_OF_WEEK, getFirstDayOfWeek());
 114.341 +        int days = dayOfWeek - getFirstDayOfWeek();
 114.342 +        if (days < 0) {
 114.343 +            days += 7;
 114.344 +        }
 114.345 +        days += 7 * (weekOfYear - 1);
 114.346 +        if (days != 0) {
 114.347 +            gc.add(DAY_OF_YEAR, days);
 114.348 +        } else {
 114.349 +            gc.complete();
 114.350 +        }
 114.351 +
 114.352 +        if (!isLenient() &&
 114.353 +            (gc.getWeekYear() != weekYear
 114.354 +             || gc.internalGet(WEEK_OF_YEAR) != weekOfYear
 114.355 +             || gc.internalGet(DAY_OF_WEEK) != dayOfWeek)) {
 114.356 +            throw new IllegalArgumentException();
 114.357 +        }
 114.358 +
 114.359 +        set(ERA, gc.internalGet(ERA));
 114.360 +        set(YEAR, gc.internalGet(YEAR));
 114.361 +        set(MONTH, gc.internalGet(MONTH));
 114.362 +        set(DAY_OF_MONTH, gc.internalGet(DAY_OF_MONTH));
 114.363 +
 114.364 +        // to avoid throwing an IllegalArgumentException in
 114.365 +        // non-lenient, set WEEK_OF_YEAR internally
 114.366 +        internalSet(WEEK_OF_YEAR, weekOfYear);
 114.367 +        complete();
 114.368 +    }
 114.369 +
 114.370 +    /**
 114.371 +     * Returns the number of weeks in the <a href="#week_year">week year</a>
 114.372 +     * represented by this {@code GregorianCalendar}.
 114.373 +     *
 114.374 +     * <p>For example, if this {@code GregorianCalendar}'s date is
 114.375 +     * December 31, 2008 with <a href="#iso8601_compatible_setting">the ISO
 114.376 +     * 8601 compatible setting</a>, this method will return 53 for the
 114.377 +     * period: December 29, 2008 to January 3, 2010 while {@link
 114.378 +     * #getActualMaximum(int) getActualMaximum(WEEK_OF_YEAR)} will return
 114.379 +     * 52 for the period: December 31, 2007 to December 28, 2008.
 114.380 +     *
 114.381 +     * @return the number of weeks in the week year.
 114.382 +     * @see Calendar#WEEK_OF_YEAR
 114.383 +     * @see #getWeekYear()
 114.384 +     * @see #getActualMaximum(int)
 114.385 +     * @since 1.7
 114.386 +     */
 114.387 +    public int getWeeksInWeekYear() {
 114.388 +        GregorianCalendar gc = getNormalizedCalendar();
 114.389 +        int weekYear = gc.getWeekYear();
 114.390 +        if (weekYear == gc.internalGet(YEAR)) {
 114.391 +            return gc.getActualMaximum(WEEK_OF_YEAR);
 114.392 +        }
 114.393 +
 114.394 +        // Use the 2nd week for calculating the max of WEEK_OF_YEAR
 114.395 +        if (gc == this) {
 114.396 +            gc = (GregorianCalendar) gc.clone();
 114.397 +        }
 114.398 +        gc.setWeekDate(weekYear, 2, internalGet(DAY_OF_WEEK));
 114.399 +        return gc.getActualMaximum(WEEK_OF_YEAR);
 114.400 +    }
 114.401  
 114.402  /////////////////////////////
 114.403  // Time => Fields computation
 114.404 @@ -2178,7 +2413,7 @@
 114.405              // If we are in the cutover year, we need some special handling.
 114.406              if (normalizedYear == cutoverYear) {
 114.407                  // Need to take care of the "missing" days.
 114.408 -                if (getCutoverCalendarSystem() == jcal) {
 114.409 +                if (gregorianCutoverYearJulian <= gregorianCutoverYear) {
 114.410                      // We need to find out where we are. The cutover
 114.411                      // gap could even be more than one year.  (One
 114.412                      // year difference in ~48667 years.)
 114.413 @@ -2208,27 +2443,36 @@
 114.414                  // December 31, which is not always true in
 114.415                  // GregorianCalendar.
 114.416                  long fixedDec31 = fixedDateJan1 - 1;
 114.417 -                long prevJan1;
 114.418 +                long prevJan1  = fixedDateJan1 - 365;
 114.419                  if (normalizedYear > (cutoverYear + 1)) {
 114.420 -                    prevJan1 = fixedDateJan1 - 365;
 114.421                      if (CalendarUtils.isGregorianLeapYear(normalizedYear - 1)) {
 114.422                          --prevJan1;
 114.423                      }
 114.424 +                } else if (normalizedYear <= gregorianCutoverYearJulian) {
 114.425 +                    if (CalendarUtils.isJulianLeapYear(normalizedYear - 1)) {
 114.426 +                        --prevJan1;
 114.427 +                    }
 114.428                  } else {
 114.429                      BaseCalendar calForJan1 = calsys;
 114.430 -                    int prevYear = normalizedYear - 1;
 114.431 -                    if (prevYear == cutoverYear) {
 114.432 +                    //int prevYear = normalizedYear - 1;
 114.433 +                    int prevYear = getCalendarDate(fixedDec31).getNormalizedYear();
 114.434 +                    if (prevYear == gregorianCutoverYear) {
 114.435                          calForJan1 = getCutoverCalendarSystem();
 114.436 -                    }
 114.437 -                    prevJan1 = calForJan1.getFixedDate(prevYear,
 114.438 -                                                       BaseCalendar.JANUARY,
 114.439 -                                                       1,
 114.440 -                                                       null);
 114.441 -                    while (prevJan1 > fixedDec31) {
 114.442 -                        prevJan1 = getJulianCalendarSystem().getFixedDate(--prevYear,
 114.443 -                                                                    BaseCalendar.JANUARY,
 114.444 -                                                                    1,
 114.445 -                                                                    null);
 114.446 +                        if (calForJan1 == jcal) {
 114.447 +                            prevJan1 = calForJan1.getFixedDate(prevYear,
 114.448 +                                                               BaseCalendar.JANUARY,
 114.449 +                                                               1,
 114.450 +                                                               null);
 114.451 +                        } else {
 114.452 +                            prevJan1 = gregorianCutoverDate;
 114.453 +                            calForJan1 = gcal;
 114.454 +                        }
 114.455 +                    } else if (prevYear <= gregorianCutoverYearJulian) {
 114.456 +                        calForJan1 = getJulianCalendarSystem();
 114.457 +                        prevJan1 = calForJan1.getFixedDate(prevYear,
 114.458 +                                                           BaseCalendar.JANUARY,
 114.459 +                                                           1,
 114.460 +                                                           null);
 114.461                      }
 114.462                  }
 114.463                  weekOfYear = getWeekNumber(prevJan1, fixedDec31);
 114.464 @@ -2260,14 +2504,20 @@
 114.465                      if (nextYear == gregorianCutoverYear) {
 114.466                          calForJan1 = getCutoverCalendarSystem();
 114.467                      }
 114.468 -                    long nextJan1 = calForJan1.getFixedDate(nextYear,
 114.469 -                                                            BaseCalendar.JANUARY,
 114.470 -                                                            1,
 114.471 -                                                            null);
 114.472 -                    if (nextJan1 < fixedDate) {
 114.473 +
 114.474 +                    long nextJan1;
 114.475 +                    if (nextYear > gregorianCutoverYear
 114.476 +                        || gregorianCutoverYearJulian == gregorianCutoverYear
 114.477 +                        || nextYear == gregorianCutoverYearJulian) {
 114.478 +                        nextJan1 = calForJan1.getFixedDate(nextYear,
 114.479 +                                                           BaseCalendar.JANUARY,
 114.480 +                                                           1,
 114.481 +                                                           null);
 114.482 +                    } else {
 114.483                          nextJan1 = gregorianCutoverDate;
 114.484                          calForJan1 = gcal;
 114.485                      }
 114.486 +
 114.487                      long nextJan1st = calForJan1.getDayOfWeekDateOnOrBefore(nextJan1 + 6,
 114.488                                                                              getFirstDayOfWeek());
 114.489                      int ndays = (int)(nextJan1st - nextJan1);
 114.490 @@ -2409,10 +2659,24 @@
 114.491                  }
 114.492                  gfd = jfd;
 114.493              } else {
 114.494 +                jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
 114.495                  gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
 114.496 -                jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
 114.497              }
 114.498 +
 114.499              // Now we have to determine which calendar date it is.
 114.500 +
 114.501 +            // If the date is relative from the beginning of the year
 114.502 +            // in the Julian calendar, then use jfd;
 114.503 +            if (isFieldSet(fieldMask, DAY_OF_YEAR) || isFieldSet(fieldMask, WEEK_OF_YEAR)) {
 114.504 +                if (gregorianCutoverYear == gregorianCutoverYearJulian) {
 114.505 +                    fixedDate = jfd;
 114.506 +                    break calculateFixedDate;
 114.507 +                } else if (year == gregorianCutoverYear) {
 114.508 +                    fixedDate = gfd;
 114.509 +                    break calculateFixedDate;
 114.510 +                }
 114.511 +            }
 114.512 +
 114.513              if (gfd >= gregorianCutoverDate) {
 114.514                  if (jfd >= gregorianCutoverDate) {
 114.515                      fixedDate = gfd;
 114.516 @@ -2494,9 +2758,10 @@
 114.517                      continue;
 114.518                  }
 114.519                  if (originalFields[field] != internalGet(field)) {
 114.520 +                    String s = originalFields[field] + " -> " + internalGet(field);
 114.521                      // Restore the original field values
 114.522                      System.arraycopy(originalFields, 0, fields, 0, fields.length);
 114.523 -                    throw new IllegalArgumentException(getFieldName(field));
 114.524 +                    throw new IllegalArgumentException(getFieldName(field) + ": " + s);
 114.525                  }
 114.526              }
 114.527          }
 114.528 @@ -2669,9 +2934,7 @@
 114.529       * method returns Gregorian. Otherwise, Julian.
 114.530       */
 114.531      private BaseCalendar getCutoverCalendarSystem() {
 114.532 -        CalendarDate date = getGregorianCutoverDate();
 114.533 -        if (date.getMonth() == BaseCalendar.JANUARY
 114.534 -            && date.getDayOfMonth() == 1) {
 114.535 +        if (gregorianCutoverYearJulian < gregorianCutoverYear) {
 114.536              return gcal;
 114.537          }
 114.538          return getJulianCalendarSystem();
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/src/share/classes/java/util/IllformedLocaleException.java	Fri Sep 24 16:41:32 2010 -0700
   115.3 @@ -0,0 +1,90 @@
   115.4 +/*
   115.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   115.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   115.7 + *
   115.8 + * This code is free software; you can redistribute it and/or modify it
   115.9 + * under the terms of the GNU General Public License version 2 only, as
  115.10 + * published by the Free Software Foundation.  Oracle designates this
  115.11 + * particular file as subject to the "Classpath" exception as provided
  115.12 + * by Oracle in the LICENSE file that accompanied this code.
  115.13 + *
  115.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  115.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  115.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  115.17 + * version 2 for more details (a copy is included in the LICENSE file that
  115.18 + * accompanied this code).
  115.19 + *
  115.20 + * You should have received a copy of the GNU General Public License version
  115.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  115.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  115.23 + *
  115.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  115.25 + * or visit www.oracle.com if you need additional information or have any
  115.26 + * questions.
  115.27 + */
  115.28 +
  115.29 +/*
  115.30 + *******************************************************************************
  115.31 + * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  115.32 + * others. All Rights Reserved.                                                *
  115.33 + *******************************************************************************
  115.34 + */
  115.35 +
  115.36 +package java.util;
  115.37 +
  115.38 +/**
  115.39 + * Thrown by methods in {@link Locale} and {@link Locale.Builder} to
  115.40 + * indicate that an argument is not a well-formed BCP 47 tag.
  115.41 + *
  115.42 + * @see Locale
  115.43 + * @since 1.7
  115.44 + */
  115.45 +public class IllformedLocaleException extends RuntimeException {
  115.46 +
  115.47 +    private static final long serialVersionUID = -5245986824925681401L;
  115.48 +
  115.49 +    private int _errIdx = -1;
  115.50 +
  115.51 +    /**
  115.52 +     * Constructs a new <code>IllformedLocaleException</code> with no
  115.53 +     * detail message and -1 as the error index.
  115.54 +     */
  115.55 +    public IllformedLocaleException() {
  115.56 +        super();
  115.57 +    }
  115.58 +
  115.59 +    /**
  115.60 +     * Constructs a new <code>IllformedLocaleException</code> with the
  115.61 +     * given message and -1 as the error index.
  115.62 +     *
  115.63 +     * @param message the message
  115.64 +     */
  115.65 +    public IllformedLocaleException(String message) {
  115.66 +        super(message);
  115.67 +    }
  115.68 +
  115.69 +    /**
  115.70 +     * Constructs a new <code>IllformedLocaleException</code> with the
  115.71 +     * given message and the error index.  The error index is the approximate
  115.72 +     * offset from the start of the ill-formed value to the point where the
  115.73 +     * parse first detected an error.  A negative error index value indicates
  115.74 +     * either the error index is not applicable or unknown.
  115.75 +     *
  115.76 +     * @param message the message
  115.77 +     * @param errorIndex the index
  115.78 +     */
  115.79 +    public IllformedLocaleException(String message, int errorIndex) {
  115.80 +        super(message + ((errorIndex < 0) ? "" : " [at index " + errorIndex + "]"));
  115.81 +        _errIdx = errorIndex;
  115.82 +    }
  115.83 +
  115.84 +    /**
  115.85 +     * Returns the index where the error was found. A negative value indicates
  115.86 +     * either the error index is not applicable or unknown.
  115.87 +     *
  115.88 +     * @return the error index
  115.89 +     */
  115.90 +    public int getErrorIndex() {
  115.91 +        return _errIdx;
  115.92 +    }
  115.93 +}
   116.1 --- a/src/share/classes/java/util/Locale.java	Thu Sep 23 17:33:40 2010 -0700
   116.2 +++ b/src/share/classes/java/util/Locale.java	Fri Sep 24 16:41:32 2010 -0700
   116.3 @@ -1,5 +1,5 @@
   116.4  /*
   116.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   116.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   116.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   116.8   *
   116.9   * This code is free software; you can redistribute it and/or modify it
  116.10 @@ -40,86 +40,240 @@
  116.11  
  116.12  package java.util;
  116.13  
  116.14 -import java.io.*;
  116.15 +import java.io.IOException;
  116.16 +import java.io.ObjectInputStream;
  116.17 +import java.io.ObjectOutputStream;
  116.18 +import java.io.ObjectStreamField;
  116.19 +import java.io.Serializable;
  116.20  import java.security.AccessController;
  116.21  import java.text.MessageFormat;
  116.22 -import java.util.List;
  116.23 -import java.util.concurrent.ConcurrentHashMap;
  116.24  import java.util.spi.LocaleNameProvider;
  116.25 -import java.util.spi.LocaleServiceProvider;
  116.26 +
  116.27  import sun.security.action.GetPropertyAction;
  116.28  import sun.util.LocaleServiceProviderPool;
  116.29 +import sun.util.locale.AsciiUtil;
  116.30 +import sun.util.locale.BaseLocale;
  116.31 +import sun.util.locale.InternalLocaleBuilder;
  116.32 +import sun.util.locale.LanguageTag;
  116.33 +import sun.util.locale.LocaleExtensions;
  116.34 +import sun.util.locale.LocaleObjectCache;
  116.35 +import sun.util.locale.LocaleSyntaxException;
  116.36 +import sun.util.locale.ParseStatus;
  116.37 +import sun.util.locale.UnicodeLocaleExtension;
  116.38  import sun.util.resources.LocaleData;
  116.39  import sun.util.resources.OpenListResourceBundle;
  116.40  
  116.41  /**
  116.42 - *
  116.43   * A <code>Locale</code> object represents a specific geographical, political,
  116.44   * or cultural region. An operation that requires a <code>Locale</code> to perform
  116.45   * its task is called <em>locale-sensitive</em> and uses the <code>Locale</code>
  116.46   * to tailor information for the user. For example, displaying a number
  116.47 - * is a locale-sensitive operation--the number should be formatted
  116.48 - * according to the customs/conventions of the user's native country,
  116.49 + * is a locale-sensitive operation&mdash; the number should be formatted
  116.50 + * according to the customs and conventions of the user's native country,
  116.51   * region, or culture.
  116.52   *
  116.53 - * <P>
  116.54 - * Create a <code>Locale</code> object using the constructors in this class:
  116.55 + * <p> The <code>Locale</code> class implements identifiers
  116.56 + * interchangeable with BCP 47 (IETF BCP 47, "Tags for Identifying
  116.57 + * Languages"), with support for the LDML (UTS#35, "Unicode Locale
  116.58 + * Data Markup Language") BCP 47-compatible extensions for locale data
  116.59 + * exchange.
  116.60 + *
  116.61 + * <p> A <code>Locale</code> object logically consists of the fields
  116.62 + * described below.
  116.63 + *
  116.64 + * <dl>
  116.65 + *   <dt><a name="def_language"/><b>language</b></dt>
  116.66 + *
  116.67 + *   <dd>ISO 639 alpha-2 or alpha-3 language code, or registered
  116.68 + *   language subtags up to 8 alpha letters (for future enhancements).
  116.69 + *   When a language has both an alpha-2 code and an alpha-3 code, the
  116.70 + *   alpha-2 code must be used.  You can find a full list of valid
  116.71 + *   language codes in the IANA Language Subtag Registry (search for
  116.72 + *   "Type: language").  The language field is case insensitive, but
  116.73 + *   <code>Locale</code> always canonicalizes to lower case.</dd><br>
  116.74 + *
  116.75 + *   <dd>Well-formed language values have the form
  116.76 + *   <code>[a-zA-Z]{2,8}</code>.  Note that this is not the the full
  116.77 + *   BCP47 language production, since it excludes extlang.  They are
  116.78 + *   not needed since modern three-letter language codes replace
  116.79 + *   them.</dd><br>
  116.80 + *
  116.81 + *   <dd>Example: "en" (English), "ja" (Japanese), "kok" (Konkani)</dd><br>
  116.82 + *
  116.83 + *   <dt><a name="def_script"/><b>script</b></dt>
  116.84 + *
  116.85 + *   <dd>ISO 15924 alpha-4 script code.  You can find a full list of
  116.86 + *   valid script codes in the IANA Language Subtag Registry (search
  116.87 + *   for "Type: script").  The script field is case insensitive, but
  116.88 + *   <code>Locale</code> always canonicalizes to title case (the first
  116.89 + *   letter is upper case and the rest of the letters are lower
  116.90 + *   case).</dd><br>
  116.91 + *
  116.92 + *   <dd>Well-formed script values have the form
  116.93 + *   <code>[a-zA-Z]{4}</code></dd><br>
  116.94 + *
  116.95 + *   <dd>Example: "Latn" (Latin), "Cyrl" (Cyrillic)</dd><br>
  116.96 + *
  116.97 + *   <dt><a name="def_region"/><b>country (region)</b></dt>
  116.98 + *
  116.99 + *   <dd>ISO 3166 alpha-2 country code or UN M.49 numeric-3 area code.
 116.100 + *   You can find a full list of valid country and region codes in the
 116.101 + *   IANA Language Subtag Registry (search for "Type: region").  The
 116.102 + *   country (region) field is case insensitive, but
 116.103 + *   <code>Locale</code> always canonicalizes to upper case.</dd><br>
 116.104 + *
 116.105 + *   <dd>Well-formed country/region values have
 116.106 + *   the form <code>[a-zA-Z]{2} | [0-9]{3}</code></dd><br>
 116.107 + *
 116.108 + *   <dd>Example: "US" (United States), "FR" (France), "029"
 116.109 + *   (Caribbean)</dd><br>
 116.110 + *
 116.111 + *   <dt><a name="def_variant"/><b>variant</b></dt>
 116.112 + *
 116.113 + *   <dd>Any arbitrary value used to indicate a variation of a
 116.114 + *   <code>Locale</code>.  Where there are two or more variant values
 116.115 + *   each indicating its own semantics, these values should be ordered
 116.116 + *   by importance, with most important first, separated by
 116.117 + *   underscore('_').  The variant field is case sensitive.</dd><br>
 116.118 + *
 116.119 + *   <dd>Note: IETF BCP 47 places syntactic restrictions on variant
 116.120 + *   subtags.  Also BCP 47 subtags are strictly used to indicate
 116.121 + *   additional variations that define a language or its dialects that
 116.122 + *   are not covered by any combinations of language, script and
 116.123 + *   region subtags.  You can find a full list of valid variant codes
 116.124 + *   in the IANA Language Subtag Registry (search for "Type: variant").
 116.125 + *
 116.126 + *   <p>However, the variant field in <code>Locale</code> has
 116.127 + *   historically been used for any kind of variation, not just
 116.128 + *   language variations.  For example, some supported variants
 116.129 + *   available in Java SE Runtime Environments indicate alternative
 116.130 + *   cultural behaviors such as calendar type or number script.  In
 116.131 + *   BCP 47 this kind of information, which does not identify the
 116.132 + *   language, is supported by extension subtags or private use
 116.133 + *   subtags.</dd><br>
 116.134 + *
 116.135 + *   <dd>Well-formed variant values have the form <code>SUBTAG
 116.136 + *   (('_'|'-') SUBTAG)*</code> where <code>SUBTAG =
 116.137 + *   [0-9][0-9a-zA-Z]{3} | [0-9a-zA-Z]{5,8}</code>. (Note: BCP 47 only
 116.138 + *   uses hyphen ('-') as a delimiter, this is more lenient).</dd><br>
 116.139 + *
 116.140 + *   <dd>Example: "polyton" (Polytonic Greek), "POSIX"</dd><br>
 116.141 + *
 116.142 + *   <dt><a name="def_extensions"/><b>extensions</b></dt>
 116.143 + *
 116.144 + *   <dd>A map from single character keys to string values, indicating
 116.145 + *   extensions apart from language identification.  The extensions in
 116.146 + *   <code>Locale</code> implement the semantics and syntax of BCP 47
 116.147 + *   extension subtags and private use subtags. The extensions are
 116.148 + *   case insensitive, but <code>Locale</code> canonicalizes all
 116.149 + *   extension keys and values to lower case. Note that extensions
 116.150 + *   cannot have empty values.</dd><br>
 116.151 + *
 116.152 + *   <dd>Well-formed keys are single characters from the set
 116.153 + *   <code>[0-9a-zA-Z]</code>.  Well-formed values have the form
 116.154 + *   <code>SUBTAG ('-' SUBTAG)*</code> where for the key 'x'
 116.155 + *   <code>SUBTAG = [0-9a-zA-Z]{1,8}</code> and for other keys
 116.156 + *   <code>SUBTAG = [0-9a-zA-Z]{2,8}</code> (that is, 'x' allows
 116.157 + *   single-character subtags).</dd><br>
 116.158 + *
 116.159 + *   <dd>Example: key="u"/value="ca-japanese" (Japanese Calendar),
 116.160 + *   key="x"/value="java-1-7"</dd>
 116.161 + * </dl>
 116.162 + *
 116.163 + * <b>Note:</b> Although BCP 47 requires field values to be registered
 116.164 + * in the IANA Language Subtag Registry, the <code>Locale</code> class
 116.165 + * does not provide any validation features.  The <code>Builder</code>
 116.166 + * only checks if an individual field satisfies the syntactic
 116.167 + * requirement (is well-formed), but does not validate the value
 116.168 + * itself.  See {@link Builder} for details.
 116.169 + *
 116.170 + * <h4><a name="def_locale_extension">Unicode locale/language extension</h4>
 116.171 + *
 116.172 + * <p>UTS#35, "Unicode Locale Data Markup Language" defines optional
 116.173 + * attributes and keywords to override or refine the default behavior
 116.174 + * associated with a locale.  A keyword is represented by a pair of
 116.175 + * key and type.  For example, "nu-thai" indicates that Thai local
 116.176 + * digits (value:"thai") should be used for formatting numbers
 116.177 + * (key:"nu").
 116.178 + *
 116.179 + * <p>The keywords are mapped to a BCP 47 extension value using the
 116.180 + * extension key 'u' ({@link #UNICODE_LOCALE_EXTENSION}).  The above
 116.181 + * example, "nu-thai", becomes the extension "u-nu-thai".code
 116.182 + *
 116.183 + * <p>Thus, when a <code>Locale</code> object contains Unicode locale
 116.184 + * attributes and keywords,
 116.185 + * <code>getExtension(UNICODE_LOCALE_EXTENSION)</code> will return a
 116.186 + * String representing this information, for example, "nu-thai".  The
 116.187 + * <code>Locale</code> class also provides {@link
 116.188 + * #getUnicodeLocaleAttributes}, {@link #getUnicodeLocaleKeys}, and
 116.189 + * {@link #getUnicodeLocaleType} which allow you to access Unicode
 116.190 + * locale attributes and key/type pairs directly.  When represented as
 116.191 + * a string, the Unicode Locale Extension lists attributes
 116.192 + * alphabetically, followed by key/type sequences with keys listed
 116.193 + * alphabetically (the order of subtags comprising a key's type is
 116.194 + * fixed when the type is defined)
 116.195 + *
 116.196 + * <p>A well-formed locale key has the form
 116.197 + * <code>[0-9a-zA-Z]{2}</code>.  A well-formed locale type has the
 116.198 + * form <code>"" | [0-9a-zA-Z]{3,8} ('-' [0-9a-zA-Z]{3,8})*</code> (it
 116.199 + * can be empty, or a series of subtags 3-8 alphanums in length).  A
 116.200 + * well-formed locale attribute has the form
 116.201 + * <code>[0-9a-zA-Z]{3,8}</code> (it is a single subtag with the same
 116.202 + * form as a locale type subtag).
 116.203 + *
 116.204 + * <p>The Unicode locale extension specifies optional behavior in
 116.205 + * locale-sensitive services.  Although the LDML specification defines
 116.206 + * various keys and values, actual locale-sensitive service
 116.207 + * implementations in a Java Runtime Environment might not support any
 116.208 + * particular Unicode locale attributes or key/type pairs.
 116.209 + *
 116.210 + * <h4>Creating a Locale</h4>
 116.211 + *
 116.212 + * <p>There are several different ways to create a <code>Locale</code>
 116.213 + * object.
 116.214 + *
 116.215 + * <h5>Builder</h5>
 116.216 + *
 116.217 + * <p>Using {@link Builder} you can construct a <code>Locale</code> object
 116.218 + * that conforms to BCP 47 syntax.
 116.219 + *
 116.220 + * <h5>Constructors</h5>
 116.221 + *
 116.222 + * <p>The <code>Locale</code> class provides three constructors:
 116.223   * <blockquote>
 116.224   * <pre>
 116.225 - * Locale(String language)
 116.226 - * Locale(String language, String country)
 116.227 - * Locale(String language, String country, String variant)
 116.228 + *     {@link #Locale(String language)}
 116.229 + *     {@link #Locale(String language, String country)}
 116.230 + *     {@link #Locale(String language, String country, String variant)}
 116.231   * </pre>
 116.232   * </blockquote>
 116.233 - * The language argument is a valid <STRONG>ISO Language Code.</STRONG>
 116.234 - * These codes are the lower-case, two-letter codes as defined by ISO-639.
 116.235 - * You can find a full list of these codes at a number of sites, such as:
 116.236 - * <BR><a href ="http://www.loc.gov/standards/iso639-2/php/English_list.php">
 116.237 - * <code>http://www.loc.gov/standards/iso639-2/php/English_list.php</code></a>
 116.238 + * These constructors allow you to create a <code>Locale</code> object
 116.239 + * with language, country and variant, but you cannot specify
 116.240 + * script or extensions.
 116.241   *
 116.242 - * <P>
 116.243 - * The country argument is a valid <STRONG>ISO Country Code.</STRONG> These
 116.244 - * codes are the upper-case, two-letter codes as defined by ISO-3166.
 116.245 - * You can find a full list of these codes at a number of sites, such as:
 116.246 - * <BR><a href="http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">
 116.247 - * <code>http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html</code></a>
 116.248 + * <h5>Factory Methods</h5>
 116.249   *
 116.250 - * <P>
 116.251 - * The variant argument is a vendor or browser-specific code.
 116.252 - * For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX.
 116.253 - * Where there are two variants, separate them with an underscore, and
 116.254 - * put the most important one first. For example, a Traditional Spanish collation
 116.255 - * might construct a locale with parameters for language, country and variant as:
 116.256 - * "es", "ES", "Traditional_WIN".
 116.257 + * <p>The method {@link #forLanguageTag} creates a <code>Locale</code>
 116.258 + * object for a well-formed BCP 47 language tag.
 116.259   *
 116.260 - * <P>
 116.261 - * Because a <code>Locale</code> object is just an identifier for a region,
 116.262 - * no validity check is performed when you construct a <code>Locale</code>.
 116.263 - * If you want to see whether particular resources are available for the
 116.264 - * <code>Locale</code> you construct, you must query those resources. For
 116.265 - * example, ask the <code>NumberFormat</code> for the locales it supports
 116.266 - * using its <code>getAvailableLocales</code> method.
 116.267 - * <BR><STRONG>Note:</STRONG> When you ask for a resource for a particular
 116.268 - * locale, you get back the best available match, not necessarily
 116.269 - * precisely what you asked for. For more information, look at
 116.270 - * {@link ResourceBundle}.
 116.271 + * <h5>Locale Constants</h5>
 116.272   *
 116.273 - * <P>
 116.274 - * The <code>Locale</code> class provides a number of convenient constants
 116.275 + * <p>The <code>Locale</code> class provides a number of convenient constants
 116.276   * that you can use to create <code>Locale</code> objects for commonly used
 116.277   * locales. For example, the following creates a <code>Locale</code> object
 116.278   * for the United States:
 116.279   * <blockquote>
 116.280   * <pre>
 116.281 - * Locale.US
 116.282 + *     Locale.US
 116.283   * </pre>
 116.284   * </blockquote>
 116.285   *
 116.286 - * <P>
 116.287 - * Once you've created a <code>Locale</code> you can query it for information about
 116.288 - * itself. Use <code>getCountry</code> to get the ISO Country Code and
 116.289 - * <code>getLanguage</code> to get the ISO Language Code. You can
 116.290 - * use <code>getDisplayCountry</code> to get the
 116.291 + * <h4>Use of Locale</h4>
 116.292 + *
 116.293 + * <p>Once you've created a <code>Locale</code> you can query it for information
 116.294 + * about itself. Use <code>getCountry</code> to get the country (or region)
 116.295 + * code and <code>getLanguage</code> to get the language code.
 116.296 + * You can use <code>getDisplayCountry</code> to get the
 116.297   * name of the country suitable for displaying to the user. Similarly,
 116.298   * you can use <code>getDisplayLanguage</code> to get the name of
 116.299   * the language suitable for displaying to the user. Interestingly,
 116.300 @@ -127,28 +281,27 @@
 116.301   * and have two versions: one that uses the default locale and one
 116.302   * that uses the locale specified as an argument.
 116.303   *
 116.304 - * <P>
 116.305 - * The Java Platform provides a number of classes that perform locale-sensitive
 116.306 + * <p>The Java Platform provides a number of classes that perform locale-sensitive
 116.307   * operations. For example, the <code>NumberFormat</code> class formats
 116.308 - * numbers, currency, or percentages in a locale-sensitive manner. Classes
 116.309 - * such as <code>NumberFormat</code> have a number of convenience methods
 116.310 + * numbers, currency, and percentages in a locale-sensitive manner. Classes
 116.311 + * such as <code>NumberFormat</code> have several convenience methods
 116.312   * for creating a default object of that type. For example, the
 116.313   * <code>NumberFormat</code> class provides these three convenience methods
 116.314   * for creating a default <code>NumberFormat</code> object:
 116.315   * <blockquote>
 116.316   * <pre>
 116.317 - * NumberFormat.getInstance()
 116.318 - * NumberFormat.getCurrencyInstance()
 116.319 - * NumberFormat.getPercentInstance()
 116.320 + *     NumberFormat.getInstance()
 116.321 + *     NumberFormat.getCurrencyInstance()
 116.322 + *     NumberFormat.getPercentInstance()
 116.323   * </pre>
 116.324   * </blockquote>
 116.325 - * These methods have two variants; one with an explicit locale
 116.326 - * and one without; the latter using the default locale.
 116.327 + * Each of these methods has two variants; one with an explicit locale
 116.328 + * and one without; the latter uses the default locale:
 116.329   * <blockquote>
 116.330   * <pre>
 116.331 - * NumberFormat.getInstance(myLocale)
 116.332 - * NumberFormat.getCurrencyInstance(myLocale)
 116.333 - * NumberFormat.getPercentInstance(myLocale)
 116.334 + *     NumberFormat.getInstance(myLocale)
 116.335 + *     NumberFormat.getCurrencyInstance(myLocale)
 116.336 + *     NumberFormat.getPercentInstance(myLocale)
 116.337   * </pre>
 116.338   * </blockquote>
 116.339   * A <code>Locale</code> is the mechanism for identifying the kind of object
 116.340 @@ -156,75 +309,162 @@
 116.341   * <STRONG>just</STRONG> a mechanism for identifying objects,
 116.342   * <STRONG>not</STRONG> a container for the objects themselves.
 116.343   *
 116.344 - * @see         ResourceBundle
 116.345 - * @see         java.text.Format
 116.346 - * @see         java.text.NumberFormat
 116.347 - * @see         java.text.Collator
 116.348 - * @author      Mark Davis
 116.349 - * @since       1.1
 116.350 + * <h4>Compatibility</h4>
 116.351 + *
 116.352 + * <p>In order to maintain compatibility with existing usage, Locale's
 116.353 + * constructors retain their behavior prior to the Java Runtime
 116.354 + * Environment version 1.7.  The same is largely true for the
 116.355 + * <code>toString</code> method. Thus Locale objects can continue to
 116.356 + * be used as they were. In particular, clients who parse the output
 116.357 + * of toString into language, country, and variant fields can continue
 116.358 + * to do so (although this is strongly discouraged), although the
 116.359 + * variant field will have additional information in it if script or
 116.360 + * extensions are present.
 116.361 + *
 116.362 + * <p>In addition, BCP 47 imposes syntax restrictions that are not
 116.363 + * imposed by Locale's constructors. This means that conversions
 116.364 + * between some Locales and BCP 47 language tags cannot be made without
 116.365 + * losing information. Thus <code>toLanguageTag</code> cannot
 116.366 + * represent the state of locales whose language, country, or variant
 116.367 + * do not conform to BCP 47.
 116.368 + *
 116.369 + * <p>Because of these issues, it is recommended that clients migrate
 116.370 + * away from constructing non-conforming locales and use the
 116.371 + * <code>forLanguageTag</code> and <code>Locale.Builder</code> APIs instead.
 116.372 + * Clients desiring a string representation of the complete locale can
 116.373 + * then always rely on <code>toLanguageTag</code> for this purpose.
 116.374 + *
 116.375 + * <h5><a name="special_cases_constructor"/>Special cases</h5>
 116.376 + *
 116.377 + * <p>For compatibility reasons, two
 116.378 + * non-conforming locales are treated as special cases.  These are
 116.379 + * <b><tt>ja_JP_JP</tt></b> and <b><tt>th_TH_TH</tt></b>. These are ill-formed
 116.380 + * in BCP 47 since the variants are too short. To ease migration to BCP 47,
 116.381 + * these are treated specially during construction.  These two cases (and only
 116.382 + * these) cause a constructor to generate an extension, all other values behave
 116.383 + * exactly as they did prior to Java 7.
 116.384 + *
 116.385 + * <p>Java has used <tt>ja_JP_JP</tt> to represent Japanese as used in
 116.386 + * Japan together with the Japanese Imperial calendar. This is now
 116.387 + * representable using a Unicode locale extension, by specifying the
 116.388 + * Unicode locale key <tt>ca</tt> (for "calendar") and type
 116.389 + * <tt>japanese</tt>. When the Locale constructor is called with the
 116.390 + * arguments "ja", "JP", "JP", the extension "u-ca-japanese" is
 116.391 + * automatically added.
 116.392 + *
 116.393 + * <p>Java has used <tt>th_TH_TH</tt> to represent Thai as used in
 116.394 + * Thailand together with Thai digits. This is also now representable using
 116.395 + * a Unicode locale extension, by specifying the Unicode locale key
 116.396 + * <tt>nu</tt> (for "number") and value <tt>thai</tt>. When the Locale
 116.397 + * constructor is called with the arguments "th", "TH", "TH", the
 116.398 + * extension "u-nu-thai" is automatically added.
 116.399 + *
 116.400 + * <h5>Serialization</h5>
 116.401 + *
 116.402 + * <p>During serialization, writeObject writes all fields to the output
 116.403 + * stream, including extensions.
 116.404 + *
 116.405 + * <p>During deserialization, readResolve adds extensions as described
 116.406 + * in <a href="#special_cases_constructor">Special Cases</a>, only
 116.407 + * for the two cases th_TH_TH and ja_JP_JP.
 116.408 + *
 116.409 + * <h5>Legacy language codes</h5>
 116.410 + *
 116.411 + * <p>Locale's constructor has always converted three language codes to
 116.412 + * their earlier, obsoleted forms: <tt>he</tt> maps to <tt>iw</tt>,
 116.413 + * <tt>yi</tt> maps to <tt>ji</tt>, and <tt>id</tt> maps to
 116.414 + * <tt>in</tt>.  This continues to be the case, in order to not break
 116.415 + * backwards compatibility.
 116.416 + *
 116.417 + * <p>The APIs added in 1.7 map between the old and new language codes,
 116.418 + * maintaining the old codes internal to Locale (so that
 116.419 + * <code>getLanguage</code> and <code>toString</code> reflect the old
 116.420 + * code), but using the new codes in the BCP 47 language tag APIs (so
 116.421 + * that <code>toLanguageTag</code> reflects the new one). This
 116.422 + * preserves the equivalence between Locales no matter which code or
 116.423 + * API is used to construct them. Java's default resource bundle
 116.424 + * lookup mechanism also implements this mapping, so that resources
 116.425 + * can be named using either convention, see {@link ResourceBundle.Control}.
 116.426 + *
 116.427 + * <h5>Three-letter language/country(region) codes</h5>
 116.428 + *
 116.429 + * <p>The Locale constructors have always specified that the language
 116.430 + * and the country param be two characters in length, although in
 116.431 + * practice they have accepted any length.  The specification has now
 116.432 + * been relaxed to allow language codes of two to eight characters and
 116.433 + * country (region) codes of two to three characters, and in
 116.434 + * particular, three-letter language codes and three-digit region
 116.435 + * codes as specified in the IANA Language Subtag Registry.  For
 116.436 + * compatibility, the implementation still does not impose a length
 116.437 + * constraint.
 116.438 + *
 116.439 + * @see Builder
 116.440 + * @see ResourceBundle
 116.441 + * @see java.text.Format
 116.442 + * @see java.text.NumberFormat
 116.443 + * @see java.text.Collator
 116.444 + * @author Mark Davis
 116.445 + * @since 1.1
 116.446   */
 116.447 -
 116.448  public final class Locale implements Cloneable, Serializable {
 116.449  
 116.450 -    // cache to store singleton Locales
 116.451 -    private final static ConcurrentHashMap<String, Locale> cache =
 116.452 -        new ConcurrentHashMap<String, Locale>(32);
 116.453 +    static private final  Cache LOCALECACHE = new Cache();
 116.454  
 116.455      /** Useful constant for language.
 116.456       */
 116.457 -    static public final Locale ENGLISH = createSingleton("en__", "en", "");
 116.458 +    static public final Locale ENGLISH = getInstance("en", "", "");
 116.459  
 116.460      /** Useful constant for language.
 116.461       */
 116.462 -    static public final Locale FRENCH = createSingleton("fr__", "fr", "");
 116.463 +    static public final Locale FRENCH = getInstance("fr", "", "");
 116.464  
 116.465      /** Useful constant for language.
 116.466       */
 116.467 -    static public final Locale GERMAN = createSingleton("de__", "de", "");
 116.468 +    static public final Locale GERMAN = getInstance("de", "", "");
 116.469  
 116.470      /** Useful constant for language.
 116.471       */
 116.472 -    static public final Locale ITALIAN = createSingleton("it__", "it", "");
 116.473 +    static public final Locale ITALIAN = getInstance("it", "", "");
 116.474  
 116.475      /** Useful constant for language.
 116.476       */
 116.477 -    static public final Locale JAPANESE = createSingleton("ja__", "ja", "");
 116.478 +    static public final Locale JAPANESE = getInstance("ja", "", "");
 116.479  
 116.480      /** Useful constant for language.
 116.481       */
 116.482 -    static public final Locale KOREAN = createSingleton("ko__", "ko", "");
 116.483 +    static public final Locale KOREAN = getInstance("ko", "", "");
 116.484  
 116.485      /** Useful constant for language.
 116.486       */
 116.487 -    static public final Locale CHINESE = createSingleton("zh__", "zh", "");
 116.488 +    static public final Locale CHINESE = getInstance("zh", "", "");
 116.489  
 116.490      /** Useful constant for language.
 116.491       */
 116.492 -    static public final Locale SIMPLIFIED_CHINESE = createSingleton("zh_CN_", "zh", "CN");
 116.493 +    static public final Locale SIMPLIFIED_CHINESE = getInstance("zh", "CN", "");
 116.494  
 116.495      /** Useful constant for language.
 116.496       */
 116.497 -    static public final Locale TRADITIONAL_CHINESE = createSingleton("zh_TW_", "zh", "TW");
 116.498 +    static public final Locale TRADITIONAL_CHINESE = getInstance("zh", "TW", "");
 116.499  
 116.500      /** Useful constant for country.
 116.501       */
 116.502 -    static public final Locale FRANCE = createSingleton("fr_FR_", "fr", "FR");
 116.503 +    static public final Locale FRANCE = getInstance("fr", "FR", "");
 116.504  
 116.505      /** Useful constant for country.
 116.506       */
 116.507 -    static public final Locale GERMANY = createSingleton("de_DE_", "de", "DE");
 116.508 +    static public final Locale GERMANY = getInstance("de", "DE", "");
 116.509  
 116.510      /** Useful constant for country.
 116.511       */
 116.512 -    static public final Locale ITALY = createSingleton("it_IT_", "it", "IT");
 116.513 +    static public final Locale ITALY = getInstance("it", "IT", "");
 116.514  
 116.515      /** Useful constant for country.
 116.516       */
 116.517 -    static public final Locale JAPAN = createSingleton("ja_JP_", "ja", "JP");
 116.518 +    static public final Locale JAPAN = getInstance("ja", "JP", "");
 116.519  
 116.520      /** Useful constant for country.
 116.521       */
 116.522 -    static public final Locale KOREA = createSingleton("ko_KR_", "ko", "KR");
 116.523 +    static public final Locale KOREA = getInstance("ko", "KR", "");
 116.524  
 116.525      /** Useful constant for country.
 116.526       */
 116.527 @@ -240,19 +480,19 @@
 116.528  
 116.529      /** Useful constant for country.
 116.530       */
 116.531 -    static public final Locale UK = createSingleton("en_GB_", "en", "GB");
 116.532 +    static public final Locale UK = getInstance("en", "GB", "");
 116.533  
 116.534      /** Useful constant for country.
 116.535       */
 116.536 -    static public final Locale US = createSingleton("en_US_", "en", "US");
 116.537 +    static public final Locale US = getInstance("en", "US", "");
 116.538  
 116.539      /** Useful constant for country.
 116.540       */
 116.541 -    static public final Locale CANADA = createSingleton("en_CA_", "en", "CA");
 116.542 +    static public final Locale CANADA = getInstance("en", "CA", "");
 116.543  
 116.544      /** Useful constant for country.
 116.545       */
 116.546 -    static public final Locale CANADA_FRENCH = createSingleton("fr_CA_", "fr", "CA");
 116.547 +    static public final Locale CANADA_FRENCH = getInstance("fr", "CA", "");
 116.548  
 116.549      /**
 116.550       * Useful constant for the root locale.  The root locale is the locale whose
 116.551 @@ -262,7 +502,25 @@
 116.552       *
 116.553       * @since 1.6
 116.554       */
 116.555 -    static public final Locale ROOT = createSingleton("__", "", "");
 116.556 +    static public final Locale ROOT = getInstance("", "", "");
 116.557 +
 116.558 +    /**
 116.559 +     * The key for the private use extension ('x').
 116.560 +     *
 116.561 +     * @see #getExtension(char)
 116.562 +     * @see Builder#setExtension(char, String)
 116.563 +     * @since 1.7
 116.564 +     */
 116.565 +    static public final char PRIVATE_USE_EXTENSION = 'x';
 116.566 +
 116.567 +    /**
 116.568 +     * The key for Unicode locale extension ('u').
 116.569 +     *
 116.570 +     * @see #getExtension(char)
 116.571 +     * @see Builder#setExtension(char, String)
 116.572 +     * @since 1.7
 116.573 +     */
 116.574 +    static public final char UNICODE_LOCALE_EXTENSION = 'u';
 116.575  
 116.576      /** serialization ID
 116.577       */
 116.578 @@ -274,32 +532,67 @@
 116.579      private static final int DISPLAY_LANGUAGE = 0;
 116.580      private static final int DISPLAY_COUNTRY  = 1;
 116.581      private static final int DISPLAY_VARIANT  = 2;
 116.582 +    private static final int DISPLAY_SCRIPT = 3;
 116.583  
 116.584      /**
 116.585 -     * Construct a locale from language, country, variant.
 116.586 -     * NOTE:  ISO 639 is not a stable standard; some of the language codes it defines
 116.587 -     * (specifically iw, ji, and in) have changed.  This constructor accepts both the
 116.588 -     * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
 116.589 +     * Private constructor used by getInstance method
 116.590 +     */
 116.591 +    private Locale(BaseLocale baseLocale, LocaleExtensions extensions) {
 116.592 +        _baseLocale = baseLocale;
 116.593 +        _extensions = extensions;
 116.594 +    }
 116.595 +
 116.596 +    /**
 116.597 +     * Construct a locale from language, country and variant.
 116.598 +     * This constructor normalizes the language value to lowercase and
 116.599 +     * the country value to uppercase.
 116.600 +     * <p>
 116.601 +     * <b>Note:</b>
 116.602 +     * <ul>
 116.603 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
 116.604 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
 116.605 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
 116.606       * API on Locale will return only the OLD codes.
 116.607 -     * @param language lowercase two-letter ISO-639 code.
 116.608 -     * @param country uppercase two-letter ISO-3166 code.
 116.609 -     * @param variant vendor and browser specific code. See class description.
 116.610 +     * <li>For backward compatibility reasons, this constructor does not make
 116.611 +     * any syntactic checks on the input.
 116.612 +     * <li>The two cases ("ja", "JP", "JP") and ("th", "TH", "TH") are handled specially,
 116.613 +     * see <a href="#special_cases_constructor">Special Cases</a> for more information.
 116.614 +     * </ul>
 116.615 +     *
 116.616 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
 116.617 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
 116.618 +     * valid language values.
 116.619 +     * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
 116.620 +     * See the <code>Locale</code> class description about valid country values.
 116.621 +     * @param variant Any arbitrary value used to indicate a variation of a <code>Locale</code>.
 116.622 +     * See the <code>Locale</code> class description for the details.
 116.623       * @exception NullPointerException thrown if any argument is null.
 116.624       */
 116.625      public Locale(String language, String country, String variant) {
 116.626 -        this.language = convertOldISOCodes(language);
 116.627 -        this.country = toUpperCase(country).intern();
 116.628 -        this.variant = variant.intern();
 116.629 +        _baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), "", country, variant);
 116.630 +        _extensions = getCompatibilityExtensions(language, "", country, variant);
 116.631      }
 116.632  
 116.633      /**
 116.634 -     * Construct a locale from language, country.
 116.635 -     * NOTE:  ISO 639 is not a stable standard; some of the language codes it defines
 116.636 -     * (specifically iw, ji, and in) have changed.  This constructor accepts both the
 116.637 -     * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
 116.638 +     * Construct a locale from language and country.
 116.639 +     * This constructor normalizes the language value to lowercase and
 116.640 +     * the country value to uppercase.
 116.641 +     * <p>
 116.642 +     * <b>Note:</b>
 116.643 +     * <ul>
 116.644 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
 116.645 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
 116.646 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
 116.647       * API on Locale will return only the OLD codes.
 116.648 -     * @param language lowercase two-letter ISO-639 code.
 116.649 -     * @param country uppercase two-letter ISO-3166 code.
 116.650 +     * <li>For backward compatibility reasons, this constructor does not make
 116.651 +     * any syntactic checks on the input.
 116.652 +     * </ul>
 116.653 +     *
 116.654 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
 116.655 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
 116.656 +     * valid language values.
 116.657 +     * @param country An ISO 3166 alpha-2 country code or a UN M.49 numeric-3 area code.
 116.658 +     * See the <code>Locale</code> class description about valid country values.
 116.659       * @exception NullPointerException thrown if either argument is null.
 116.660       */
 116.661      public Locale(String language, String country) {
 116.662 @@ -308,11 +601,21 @@
 116.663  
 116.664      /**
 116.665       * Construct a locale from a language code.
 116.666 -     * NOTE:  ISO 639 is not a stable standard; some of the language codes it defines
 116.667 -     * (specifically iw, ji, and in) have changed.  This constructor accepts both the
 116.668 -     * old codes (iw, ji, and in) and the new codes (he, yi, and id), but all other
 116.669 +     * This constructor normalizes the language value to lowercase.
 116.670 +     * <p>
 116.671 +     * <b>Note:</b>
 116.672 +     * <ul>
 116.673 +     * <li>ISO 639 is not a stable standard; some of the language codes it defines
 116.674 +     * (specifically "iw", "ji", and "in") have changed.  This constructor accepts both the
 116.675 +     * old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other
 116.676       * API on Locale will return only the OLD codes.
 116.677 -     * @param language lowercase two-letter ISO-639 code.
 116.678 +     * <li>For backward compatibility reasons, this constructor does not make
 116.679 +     * any syntactic checks on the input.
 116.680 +     * </ul>
 116.681 +     *
 116.682 +     * @param language An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
 116.683 +     * up to 8 characters in length.  See the <code>Locale</code> class description about
 116.684 +     * valid language values.
 116.685       * @exception NullPointerException thrown if argument is null.
 116.686       * @since 1.4
 116.687       */
 116.688 @@ -321,32 +624,6 @@
 116.689      }
 116.690  
 116.691      /**
 116.692 -     * Constructs a <code>Locale</code> using <code>language</code>
 116.693 -     * and <code>country</code>.  This constructor assumes that
 116.694 -     * <code>language</code> and <code>contry</code> are interned and
 116.695 -     * it is invoked by createSingleton only. (flag is just for
 116.696 -     * avoiding the conflict with the public constructors.
 116.697 -     */
 116.698 -    private Locale(String language, String country, boolean flag) {
 116.699 -        this.language = language;
 116.700 -        this.country = country;
 116.701 -        this.variant = "";
 116.702 -    }
 116.703 -
 116.704 -    /**
 116.705 -     * Creates a <code>Locale</code> instance with the given
 116.706 -     * <code>language</code> and <code>counry</code> and puts the
 116.707 -     * instance under the given <code>key</code> in the cache. This
 116.708 -     * method must be called only when initializing the Locale
 116.709 -     * constants.
 116.710 -     */
 116.711 -    private static Locale createSingleton(String key, String language, String country) {
 116.712 -        Locale locale = new Locale(language, country, false);
 116.713 -        cache.put(key, locale);
 116.714 -        return locale;
 116.715 -    }
 116.716 -
 116.717 -    /**
 116.718       * Returns a <code>Locale</code> constructed from the given
 116.719       * <code>language</code>, <code>country</code> and
 116.720       * <code>variant</code>. If the same <code>Locale</code> instance
 116.721 @@ -354,29 +631,70 @@
 116.722       * returned. Otherwise, a new <code>Locale</code> instance is
 116.723       * created and cached.
 116.724       *
 116.725 -     * @param language lowercase two-letter ISO-639 code.
 116.726 -     * @param country uppercase two-letter ISO-3166 code.
 116.727 +     * @param language lowercase 2 to 8 language code.
 116.728 +     * @param country uppercase two-letter ISO-3166 code and numric-3 UN M.49 area code.
 116.729       * @param variant vendor and browser specific code. See class description.
 116.730       * @return the <code>Locale</code> instance requested
 116.731       * @exception NullPointerException if any argument is null.
 116.732       */
 116.733      static Locale getInstance(String language, String country, String variant) {
 116.734 -        if (language== null || country == null || variant == null) {
 116.735 +        return getInstance(language, "", country, variant, LocaleExtensions.EMPTY_EXTENSIONS);
 116.736 +    }
 116.737 +
 116.738 +    static Locale getInstance(String language, String script, String country,
 116.739 +                                      String variant, LocaleExtensions extensions) {
 116.740 +        if (language== null || script == null || country == null || variant == null) {
 116.741              throw new NullPointerException();
 116.742          }
 116.743  
 116.744 -        StringBuilder sb = new StringBuilder();
 116.745 -        sb.append(language).append('_').append(country).append('_').append(variant);
 116.746 -        String key = sb.toString();
 116.747 -        Locale locale = cache.get(key);
 116.748 -        if (locale == null) {
 116.749 -            locale = new Locale(language, country, variant);
 116.750 -            Locale l = cache.putIfAbsent(key, locale);
 116.751 -            if (l != null) {
 116.752 -                locale = l;
 116.753 +        if (extensions == null) {
 116.754 +            extensions = LocaleExtensions.EMPTY_EXTENSIONS;
 116.755 +        }
 116.756 +
 116.757 +        if (extensions.equals(LocaleExtensions.EMPTY_EXTENSIONS)) {
 116.758 +            extensions = getCompatibilityExtensions(language, script, country, variant);
 116.759 +        }
 116.760 +
 116.761 +        BaseLocale baseloc = BaseLocale.getInstance(language, script, country, variant);
 116.762 +        return getInstance(baseloc, extensions);
 116.763 +    }
 116.764 +
 116.765 +    static Locale getInstance(BaseLocale baseloc, LocaleExtensions extensions) {
 116.766 +        LocaleKey key = new LocaleKey(baseloc, extensions);
 116.767 +        return LOCALECACHE.get(key);
 116.768 +    }
 116.769 +
 116.770 +    private static class Cache extends LocaleObjectCache<LocaleKey, Locale> {
 116.771 +        public Cache() {
 116.772 +        }
 116.773 +        protected Locale createObject(LocaleKey key) {
 116.774 +            return new Locale(key._base, key._exts);
 116.775 +        }
 116.776 +    }
 116.777 +
 116.778 +    private static class LocaleKey {
 116.779 +        private BaseLocale _base;
 116.780 +        private LocaleExtensions _exts;
 116.781 +
 116.782 +        private LocaleKey(BaseLocale baseLocale, LocaleExtensions extensions) {
 116.783 +            _base = baseLocale;
 116.784 +            _exts = extensions;
 116.785 +        }
 116.786 +
 116.787 +        public boolean equals(Object obj) {
 116.788 +            if (this == obj) {
 116.789 +                return true;
 116.790              }
 116.791 +            if (!(obj instanceof LocaleKey)) {
 116.792 +                return false;
 116.793 +            }
 116.794 +            LocaleKey other = (LocaleKey)obj;
 116.795 +            return _base.equals(other._base) && _exts.equals(other._exts);
 116.796          }
 116.797 -        return locale;
 116.798 +
 116.799 +        public int hashCode() {
 116.800 +            return _base.hashCode() ^ _exts.hashCode();
 116.801 +        }
 116.802      }
 116.803  
 116.804      /**
 116.805 @@ -395,31 +713,103 @@
 116.806          // do not synchronize this method - see 4071298
 116.807          // it's OK if more than one default locale happens to be created
 116.808          if (defaultLocale == null) {
 116.809 -            String language, region, country, variant;
 116.810 +            initDefault();
 116.811 +        }
 116.812 +        return defaultLocale;
 116.813 +    }
 116.814 +
 116.815 +    /**
 116.816 +     * Gets the current value of the default locale for the specified Category
 116.817 +     * for this instance of the Java Virtual Machine.
 116.818 +     * <p>
 116.819 +     * The Java Virtual Machine sets the default locale during startup based
 116.820 +     * on the host environment. It is used by many locale-sensitive methods
 116.821 +     * if no locale is explicitly specified. It can be changed using the
 116.822 +     * setDefault(Locale.Category, Locale) method.
 116.823 +     *
 116.824 +     * @param category - the specified category to get the default locale
 116.825 +     * @throws NullPointerException - if category is null
 116.826 +     * @return the default locale for the specified Category for this instance
 116.827 +     *     of the Java Virtual Machine
 116.828 +     * @see #setDefault(Locale.Category, Locale)
 116.829 +     * @since 1.7
 116.830 +     */
 116.831 +    public static Locale getDefault(Locale.Category category) {
 116.832 +        // do not synchronize this method - see 4071298
 116.833 +        // it's OK if more than one default locale happens to be created
 116.834 +        switch (category) {
 116.835 +        case DISPLAY:
 116.836 +            if (defaultDisplayLocale == null) {
 116.837 +                initDefault(category);
 116.838 +            }
 116.839 +            return defaultDisplayLocale;
 116.840 +        case FORMAT:
 116.841 +            if (defaultFormatLocale == null) {
 116.842 +                initDefault(category);
 116.843 +            }
 116.844 +            return defaultFormatLocale;
 116.845 +        default:
 116.846 +            assert false: "Unknown Category";
 116.847 +        }
 116.848 +        return getDefault();
 116.849 +    }
 116.850 +
 116.851 +    private static void initDefault() {
 116.852 +        String language, region, country, variant;
 116.853 +        language = AccessController.doPrivileged(
 116.854 +            new GetPropertyAction("user.language", "en"));
 116.855 +        // for compatibility, check for old user.region property
 116.856 +        region = AccessController.doPrivileged(
 116.857 +            new GetPropertyAction("user.region"));
 116.858 +        if (region != null) {
 116.859 +            // region can be of form country, country_variant, or _variant
 116.860 +            int i = region.indexOf('_');
 116.861 +            if (i >= 0) {
 116.862 +                country = region.substring(0, i);
 116.863 +                variant = region.substring(i + 1);
 116.864 +            } else {
 116.865 +                country = region;
 116.866 +                variant = "";
 116.867 +            }
 116.868 +        } else {
 116.869 +            country = AccessController.doPrivileged(
 116.870 +                new GetPropertyAction("user.country", ""));
 116.871 +            variant = AccessController.doPrivileged(
 116.872 +                new GetPropertyAction("user.variant", ""));
 116.873 +        }
 116.874 +        defaultLocale = getInstance(language, country, variant);
 116.875 +    }
 116.876 +
 116.877 +    private static void initDefault(Locale.Category category) {
 116.878 +        String language, region, country, variant;
 116.879 +        switch (category) {
 116.880 +        case DISPLAY:
 116.881              language = AccessController.doPrivileged(
 116.882 -                new GetPropertyAction("user.language", "en"));
 116.883 -            // for compatibility, check for old user.region property
 116.884 -            region = AccessController.doPrivileged(
 116.885 -                new GetPropertyAction("user.region"));
 116.886 -            if (region != null) {
 116.887 -                // region can be of form country, country_variant, or _variant
 116.888 -                int i = region.indexOf('_');
 116.889 -                if (i >= 0) {
 116.890 -                    country = region.substring(0, i);
 116.891 -                    variant = region.substring(i + 1);
 116.892 -                } else {
 116.893 -                    country = region;
 116.894 -                    variant = "";
 116.895 -                }
 116.896 +                new GetPropertyAction("user.language.display", ""));
 116.897 +            if ("".equals(language)) {
 116.898 +                defaultDisplayLocale = getDefault();
 116.899              } else {
 116.900                  country = AccessController.doPrivileged(
 116.901 -                    new GetPropertyAction("user.country", ""));
 116.902 +                    new GetPropertyAction("user.country.display", ""));
 116.903                  variant = AccessController.doPrivileged(
 116.904 -                    new GetPropertyAction("user.variant", ""));
 116.905 +                    new GetPropertyAction("user.variant.display", ""));
 116.906 +                defaultDisplayLocale = getInstance(language, country, variant);
 116.907              }
 116.908 -            defaultLocale = getInstance(language, country, variant);
 116.909 +            break;
 116.910 +        case FORMAT:
 116.911 +            language = AccessController.doPrivileged(
 116.912 +                new GetPropertyAction("user.language.format", ""));
 116.913 +            if ("".equals(language)) {
 116.914 +                defaultFormatLocale = getDefault();
 116.915 +            } else {
 116.916 +                country = AccessController.doPrivileged(
 116.917 +                    new GetPropertyAction("user.country.format", ""));
 116.918 +                variant = AccessController.doPrivileged(
 116.919 +                    new GetPropertyAction("user.variant.format", ""));
 116.920 +                defaultFormatLocale = getInstance(language, country, variant);
 116.921 +            }
 116.922 +            break;
 116.923          }
 116.924 -        return defaultLocale;
 116.925      }
 116.926  
 116.927      /**
 116.928 @@ -438,6 +828,9 @@
 116.929       * of functionality, this method should only be used if the caller
 116.930       * is prepared to reinitialize locale-sensitive code running
 116.931       * within the same Java Virtual Machine.
 116.932 +     * <p>
 116.933 +     * By setting the default locale with this method, all of the default
 116.934 +     * locales for each Category are also set to the specified default locale.
 116.935       *
 116.936       * @throws SecurityException
 116.937       *        if a security manager exists and its
 116.938 @@ -448,13 +841,59 @@
 116.939       * @see java.util.PropertyPermission
 116.940       */
 116.941      public static synchronized void setDefault(Locale newLocale) {
 116.942 +        setDefault(Category.DISPLAY, newLocale);
 116.943 +        setDefault(Category.FORMAT, newLocale);
 116.944 +        defaultLocale = newLocale;
 116.945 +    }
 116.946 +
 116.947 +    /**
 116.948 +     * Sets the default locale for the specified Category for this instance
 116.949 +     * of the Java Virtual Machine. This does not affect the host locale.
 116.950 +     * <p>
 116.951 +     * If there is a security manager, its checkPermission method is called
 116.952 +     * with a PropertyPermission("user.language", "write") permission before
 116.953 +     * the default locale is changed.
 116.954 +     * <p>
 116.955 +     * The Java Virtual Machine sets the default locale during startup based
 116.956 +     * on the host environment. It is used by many locale-sensitive methods
 116.957 +     * if no locale is explicitly specified.
 116.958 +     * <p>
 116.959 +     * Since changing the default locale may affect many different areas of
 116.960 +     * functionality, this method should only be used if the caller is
 116.961 +     * prepared to reinitialize locale-sensitive code running within the
 116.962 +     * same Java Virtual Machine.
 116.963 +     * <p>
 116.964 +     *
 116.965 +     * @param category - the specified category to set the default locale
 116.966 +     * @param newLocale - the new default locale
 116.967 +     * @throws SecurityException - if a security manager exists and its
 116.968 +     *     checkPermission method doesn't allow the operation.
 116.969 +     * @throws NullPointerException - if category and/or newLocale is null
 116.970 +     * @see SecurityManager.checkPermission(java.security.Permission)
 116.971 +     * @see PropertyPermission
 116.972 +     * @see #getDefault(Locale.Category)
 116.973 +     * @since 1.7
 116.974 +     */
 116.975 +    public static synchronized void setDefault(Locale.Category category,
 116.976 +        Locale newLocale) {
 116.977 +        if (category == null)
 116.978 +            throw new NullPointerException("Category cannot be NULL");
 116.979          if (newLocale == null)
 116.980              throw new NullPointerException("Can't set default locale to NULL");
 116.981  
 116.982          SecurityManager sm = System.getSecurityManager();
 116.983          if (sm != null) sm.checkPermission(new PropertyPermission
 116.984                          ("user.language", "write"));
 116.985 -            defaultLocale = newLocale;
 116.986 +        switch (category) {
 116.987 +        case DISPLAY:
 116.988 +            defaultDisplayLocale = newLocale;
 116.989 +            break;
 116.990 +        case FORMAT:
 116.991 +            defaultFormatLocale = newLocale;
 116.992 +            break;
 116.993 +        default:
 116.994 +            assert false: "Unknown Category";
 116.995 +        }
 116.996      }
 116.997  
 116.998      /**
 116.999 @@ -474,6 +913,11 @@
116.1000      /**
116.1001       * Returns a list of all 2-letter country codes defined in ISO 3166.
116.1002       * Can be used to create Locales.
116.1003 +     * <p>
116.1004 +     * <b>Note:</b> The <code>Locale</code> class also supports other codes for
116.1005 +     * country (region), such as 3-letter numeric UN M.49 area codes.
116.1006 +     * Therefore, the list returned by this method does not contain ALL valid
116.1007 +     * codes that can be used to create Locales.
116.1008       */
116.1009      public static String[] getISOCountries() {
116.1010          if (isoCountries == null) {
116.1011 @@ -487,9 +931,16 @@
116.1012      /**
116.1013       * Returns a list of all 2-letter language codes defined in ISO 639.
116.1014       * Can be used to create Locales.
116.1015 -     * [NOTE:  ISO 639 is not a stable standard-- some languages' codes have changed.
116.1016 +     * <p>
116.1017 +     * <b>Note:</b>
116.1018 +     * <ul>
116.1019 +     * <li>ISO 639 is not a stable standard&mdash; some languages' codes have changed.
116.1020       * The list this function returns includes both the new and the old codes for the
116.1021 -     * languages whose codes have changed.]
116.1022 +     * languages whose codes have changed.
116.1023 +     * <li>The <code>Locale</code> class also supports language codes up to
116.1024 +     * 8 characters in length.  Therefore, the list returned by this method does
116.1025 +     * not contain ALL valid codes that can be used to create Locales.
116.1026 +     * </ul>
116.1027       */
116.1028      public static String[] getISOLanguages() {
116.1029          if (isoLanguages == null) {
116.1030 @@ -510,100 +961,516 @@
116.1031      }
116.1032  
116.1033      /**
116.1034 -     * Returns the language code for this locale, which will either be the empty string
116.1035 -     * or a lowercase ISO 639 code.
116.1036 -     * <p>NOTE:  ISO 639 is not a stable standard-- some languages' codes have changed.
116.1037 +     * Returns the language code of this Locale.
116.1038 +     *
116.1039 +     * <p><b>Note:</b> ISO 639 is not a stable standard&mdash; some languages' codes have changed.
116.1040       * Locale's constructor recognizes both the new and the old codes for the languages
116.1041       * whose codes have changed, but this function always returns the old code.  If you
116.1042 -     * want to check for a specific language whose code has changed, don't do <pre>
116.1043 -     * if (locale.getLanguage().equals("he"))
116.1044 +     * want to check for a specific language whose code has changed, don't do
116.1045 +     * <pre>
116.1046 +     * if (locale.getLanguage().equals("he")) // BAD!
116.1047       *    ...
116.1048 -     * </pre>Instead, do<pre>
116.1049 -     * if (locale.getLanguage().equals(new Locale("he", "", "").getLanguage()))
116.1050 -     *    ...</pre>
116.1051 +     * </pre>
116.1052 +     * Instead, do
116.1053 +     * <pre>
116.1054 +     * if (locale.getLanguage().equals(new Locale("he").getLanguage()))
116.1055 +     *    ...
116.1056 +     * </pre>
116.1057 +     * @return The language code, or the empty string if none is defined.
116.1058       * @see #getDisplayLanguage
116.1059       */
116.1060      public String getLanguage() {
116.1061 -        return language;
116.1062 +        return _baseLocale.getLanguage();
116.1063      }
116.1064  
116.1065      /**
116.1066 -     * Returns the country/region code for this locale, which will
116.1067 -     * either be the empty string or an uppercase ISO 3166 2-letter code.
116.1068 +     * Returns the script for this locale, which should
116.1069 +     * either be the empty string or an ISO 15924 4-letter script
116.1070 +     * code. The first letter is uppercase and the rest are
116.1071 +     * lowercase, for example, 'Latn', 'Cyrl'.
116.1072 +     *
116.1073 +     * @return The script code, or the empty string if none is defined.
116.1074 +     * @see #getDisplayScript
116.1075 +     * @since 1.7
116.1076 +     */
116.1077 +    public String getScript() {
116.1078 +        return _baseLocale.getScript();
116.1079 +    }
116.1080 +
116.1081 +    /**
116.1082 +     * Returns the country/region code for this locale, which should
116.1083 +     * either be the empty string, an uppercase ISO 3166 2-letter code,
116.1084 +     * or a UN M.49 3-digit code.
116.1085 +     *
116.1086 +     * @return The country/region code, or the empty string if none is defined.
116.1087       * @see #getDisplayCountry
116.1088       */
116.1089      public String getCountry() {
116.1090 -        return country;
116.1091 +        return _baseLocale.getRegion();
116.1092      }
116.1093  
116.1094      /**
116.1095       * Returns the variant code for this locale.
116.1096 +     *
116.1097 +     * @return The variant code, or the empty string if none is defined.
116.1098       * @see #getDisplayVariant
116.1099       */
116.1100      public String getVariant() {
116.1101 -        return variant;
116.1102 +        return _baseLocale.getVariant();
116.1103      }
116.1104  
116.1105      /**
116.1106 -     * Getter for the programmatic name of the entire locale,
116.1107 -     * with the language, country and variant separated by underbars.
116.1108 -     * Language is always lower case, and country is always upper case.
116.1109 -     * If the language is missing, the string will begin with an underbar.
116.1110 -     * If both the language and country fields are missing, this function
116.1111 -     * will return the empty string, even if the variant field is filled in
116.1112 -     * (you can't have a locale with just a variant-- the variant must accompany
116.1113 -     * a valid language or country code).
116.1114 -     * Examples: "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC"
116.1115 +     * Returns the extension (or private use) value associated with
116.1116 +     * the specified key, or null if there is no extension
116.1117 +     * associated with the key. To be well-formed, the key must be one
116.1118 +     * of <code>[0-9A-Za-z]</code>. Keys are case-insensitive, so
116.1119 +     * for example 'z' and 'Z' represent the same extension.
116.1120 +     *
116.1121 +     * @param key the extension key
116.1122 +     * @return The extension, or null if this locale defines no
116.1123 +     * extension for the specified key.
116.1124 +     * @throws IllegalArgumentException if key is not well-formed
116.1125 +     * @see #PRIVATE_USE_EXTENSION
116.1126 +     * @see #UNICODE_LOCALE_EXTENSION
116.1127 +     * @since 1.7
116.1128 +     */
116.1129 +    public String getExtension(char key) {
116.1130 +        if (!LocaleExtensions.isValidKey(key)) {
116.1131 +            throw new IllegalArgumentException("Ill-formed extension key: " + key);
116.1132 +        }
116.1133 +        return _extensions.getExtensionValue(key);
116.1134 +    }
116.1135 +
116.1136 +    /**
116.1137 +     * Returns the set of extension keys associated with this locale, or the
116.1138 +     * empty set if it has no extensions. The returned set is unmodifiable.
116.1139 +     * The keys will all be lower-case.
116.1140 +     *
116.1141 +     * @return The set of extension keys, or the empty set if this locale has
116.1142 +     * no extensions.
116.1143 +     * @since 1.7
116.1144 +     */
116.1145 +    public Set<Character> getExtensionKeys() {
116.1146 +        return _extensions.getKeys();
116.1147 +    }
116.1148 +
116.1149 +    /**
116.1150 +     * Returns the set of unicode locale attributes associated with
116.1151 +     * this locale, or the empty set if it has no attributes. The
116.1152 +     * returned set is unmodifiable.
116.1153 +     *
116.1154 +     * @return The set of attributes.
116.1155 +     * @since 1.7
116.1156 +     */
116.1157 +    public Set<String> getUnicodeLocaleAttributes() {
116.1158 +        return _extensions.getUnicodeLocaleAttributes();
116.1159 +    }
116.1160 +
116.1161 +    /**
116.1162 +     * Returns the Unicode locale type associated with the specified Unicode locale key
116.1163 +     * for this locale. Returns the empty string for keys that are defined with no type.
116.1164 +     * Returns null if the key is not defined. Keys are case-insensitive. The key must
116.1165 +     * be two alphanumeric characters ([0-9a-zA-Z]), or an IllegalArgumentException is
116.1166 +     * thrown.
116.1167 +     *
116.1168 +     * @param key the Unicode locale key
116.1169 +     * @return The Unicode locale type associated with the key, or null if the
116.1170 +     * locale does not define the key.
116.1171 +     * @throws IllegalArgumentException if the key is not well-formed
116.1172 +     * @throws NullPointerException if <code>key</code> is null
116.1173 +     * @since 1.7
116.1174 +     */
116.1175 +    public String getUnicodeLocaleType(String key) {
116.1176 +        if (!UnicodeLocaleExtension.isKey(key)) {
116.1177 +            throw new IllegalArgumentException("Ill-formed Unicode locale key: " + key);
116.1178 +        }
116.1179 +        return _extensions.getUnicodeLocaleType(key);
116.1180 +    }
116.1181 +
116.1182 +    /**
116.1183 +     * Returns the set of Unicode locale keys defined by this locale, or the empty set if
116.1184 +     * this locale has none.  The returned set is immutable.  Keys are all lower case.
116.1185 +     *
116.1186 +     * @return The set of Unicode locale keys, or the empty set if this locale has
116.1187 +     * no Unicode locale keywords.
116.1188 +     * @since 1.7
116.1189 +     */
116.1190 +    public Set<String> getUnicodeLocaleKeys() {
116.1191 +        return _extensions.getUnicodeLocaleKeys();
116.1192 +    }
116.1193 +
116.1194 +    /**
116.1195 +     * Package locale method returning the Locale's BaseLocale,
116.1196 +     * used by ResourceBundle
116.1197 +     * @return base locale of this Locale
116.1198 +     */
116.1199 +    BaseLocale getBaseLocale() {
116.1200 +        return _baseLocale;
116.1201 +    }
116.1202 +
116.1203 +    /**
116.1204 +     * Package local method returning the Locale's LocaleExtensions,
116.1205 +     * used by ResourceBundle
116.1206 +     * @return locale exnteions of this Locale
116.1207 +     */
116.1208 +     LocaleExtensions getLocaleExtensions() {
116.1209 +         return _extensions;
116.1210 +     }
116.1211 +
116.1212 +    /**
116.1213 +     * Returns a string representation of this <code>Locale</code>
116.1214 +     * object, consisting of language, country, variant, script,
116.1215 +     * and extensions as below:
116.1216 +     * <p><blockquote>
116.1217 +     * language + "_" + country + "_" + (variant + "_#" | "#") + script + "-" + extensions
116.1218 +     * </blockquote>
116.1219 +     *
116.1220 +     * Language is always lower case, country is always upper case, script is always title
116.1221 +     * case, and extensions are always lower case.  Extensions and private use subtags
116.1222 +     * will be in canonical order as explained in {@link #toLanguageTag}.
116.1223 +     *
116.1224 +     * <p>When the locale has neither script nor extensions, the result is the same as in
116.1225 +     * Java 6 and prior.
116.1226 +     *
116.1227 +     * <p>If both the language and country fields are missing, this function will return
116.1228 +     * the empty string, even if the variant, script, or extensions field is present (you
116.1229 +     * can't have a locale with just a variant, the variant must accompany a well-formed
116.1230 +     * language or country code).
116.1231 +     *
116.1232 +     * <p>If script or extensions are present and variant is missing, no underscore is
116.1233 +     * added before the "#".
116.1234 +     *
116.1235 +     * <p>This behavior is designed to support debugging and to be compatible with
116.1236 +     * previous uses of <code>toString</code> that expected language, country, and variant
116.1237 +     * fields only.  To represent a Locale as a String for interchange purposes, use
116.1238 +     * {@link #toLanguageTag}.
116.1239 +     *
116.1240 +     * <p>Examples: <ul><tt>
116.1241 +     * <li>en
116.1242 +     * <li>de_DE
116.1243 +     * <li>_GB
116.1244 +     * <li>en_US_WIN
116.1245 +     * <li>de__POSIX
116.1246 +     * <li>zh_CN_#Hans
116.1247 +     * <li>zh_TW_#Hant-x-java
116.1248 +     * <li>th_TH_TH_#u-nu-thai</tt></ul>
116.1249 +     *
116.1250 +     * @return A string representation of the Locale, for debugging.
116.1251       * @see #getDisplayName
116.1252 +     * @see #toLanguageTag
116.1253       */
116.1254      public final String toString() {
116.1255 -        boolean l = language.length() != 0;
116.1256 -        boolean c = country.length() != 0;
116.1257 -        boolean v = variant.length() != 0;
116.1258 -        StringBuilder result = new StringBuilder(language);
116.1259 -        if (c||(l&&v)) {
116.1260 -            result.append('_').append(country); // This may just append '_'
116.1261 +        boolean l = (_baseLocale.getLanguage().length() != 0);
116.1262 +        boolean s = (_baseLocale.getScript().length() != 0);
116.1263 +        boolean r = (_baseLocale.getRegion().length() != 0);
116.1264 +        boolean v = (_baseLocale.getVariant().length() != 0);
116.1265 +        boolean e = (_extensions.getID().length() != 0);
116.1266 +
116.1267 +        StringBuilder result = new StringBuilder(_baseLocale.getLanguage());
116.1268 +        if (r || (l && v)) {
116.1269 +            result.append('_')
116.1270 +                .append(_baseLocale.getRegion()); // This may just append '_'
116.1271          }
116.1272 -        if (v&&(l||c)) {
116.1273 -            result.append('_').append(variant);
116.1274 +        if (v && (l || r)) {
116.1275 +            result.append('_')
116.1276 +                .append(_baseLocale.getVariant());
116.1277          }
116.1278 +
116.1279 +        if (s && (l || r)) {
116.1280 +            result.append("_#")
116.1281 +                .append(_baseLocale.getScript());
116.1282 +        }
116.1283 +
116.1284 +        if (e && (l || r)) {
116.1285 +            result.append('_');
116.1286 +            if (!s) {
116.1287 +                result.append('#');
116.1288 +            }
116.1289 +            result.append(_extensions.getID());
116.1290 +        }
116.1291 +
116.1292          return result.toString();
116.1293      }
116.1294  
116.1295      /**
116.1296 -     * Returns a three-letter abbreviation for this locale's language.  If the locale
116.1297 -     * doesn't specify a language, this will be the empty string.  Otherwise, this will
116.1298 -     * be a lowercase ISO 639-2/T language code.
116.1299 -     * The ISO 639-2 language codes can be found on-line at
116.1300 -     * <a href="http://www.loc.gov/standards/iso639-2/englangn.html">
116.1301 -     * <code>http://www.loc.gov/standards/iso639-2/englangn.html</code>.</a>
116.1302 -     * @exception MissingResourceException Throws MissingResourceException if the
116.1303 +     * Returns a well-formed IETF BCP 47 language tag representing
116.1304 +     * this locale.
116.1305 +     *
116.1306 +     * <p>If this <code>Locale</code> has a language, country, or
116.1307 +     * variant that does not satisfy the IETF BCP 47 language tag
116.1308 +     * syntax requirements, this method handles these fields as
116.1309 +     * described below:
116.1310 +     *
116.1311 +     * <p><b>Language:</b> If language is empty, or not <a
116.1312 +     * href="#def_language" >well-formed</a> (for example "a" or
116.1313 +     * "e2"), it will be emitted as "und" (Undetermined).
116.1314 +     *
116.1315 +     * <p><b>Country:</b> If country is not <a
116.1316 +     * href="#def_region">well-formed</a> (for example "12" or "USA"),
116.1317 +     * it will be omitted.
116.1318 +     *
116.1319 +     * <p><b>Variant:</b> If variant <b>is</b> <a
116.1320 +     * href="#def_variant">well-formed</a>, each sub-segment
116.1321 +     * (delimited by '-' or '_') is emitted as a subtag.  Otherwise:
116.1322 +     * <ul>
116.1323 +     *
116.1324 +     * <li>if all sub-segments match <code>[0-9a-zA-Z]{1,8}</code>
116.1325 +     * (for example "WIN" or "Oracle_JDK_Standard_Edition"), the first
116.1326 +     * ill-formed sub-segment and all following will be appended to
116.1327 +     * the private use subtag.  The first appended subtag will be
116.1328 +     * "lvariant", followed by the sub-segments in order, separated by
116.1329 +     * hyphen. For example, "x-lvariant-WIN",
116.1330 +     * "Oracle-x-lvariant-JDK-Standard-Edition".
116.1331 +     *
116.1332 +     * <li>if any sub-segment does not match
116.1333 +     * <code>[0-9a-zA-Z]{1,8}</code>, the variant will be truncated
116.1334 +     * and the problematic sub-segment and all following sub-segments
116.1335 +     * will be omitted.  If the remainder is non-empty, it will be
116.1336 +     * emitted as a private use subtag as above (even if the remainder
116.1337 +     * turns out to be well-formed).  For example,
116.1338 +     * "Solaris_isjustthecoolestthing" is emitted as
116.1339 +     * "x-lvariant-Solaris", not as "solaris".</li></ul>
116.1340 +     *
116.1341 +     * <p><b>Compatibility special cases:</b><ul>
116.1342 +     *
116.1343 +     * <li>The language codes "iw", "ji", and "in" are handled
116.1344 +     * specially. Java uses these deprecated codes for compatibility
116.1345 +     * reasons. The <code>toLanguageTag</code> method converts these
116.1346 +     * three codes (and only these three) to "he", "yi", and "id"
116.1347 +     * respectively.
116.1348 +     *
116.1349 +     * <li>A locale with language "no", country "NO", and variant
116.1350 +     * "NY", representing Norwegian Nynorsk, will be represented as
116.1351 +     * having language "nn", country "NO", and empty variant. This is
116.1352 +     * because some JVMs used the deprecated form to represent the
116.1353 +     * user's default locale, and for compatibility reasons that Take a has
116.1354 +     * not been changed.</ul>
116.1355 +     *
116.1356 +     * <p><b>Note:</b> Although the language tag created by this
116.1357 +     * method is well-formed (satisfies the syntax requirements
116.1358 +     * defined by the IETF BCP 47 specification), it is not
116.1359 +     * necessarily a valid BCP 47 language tag.  For example,
116.1360 +     * <pre>
116.1361 +     *   new Locale("xx", "YY").toLanguageTag();</pre>
116.1362 +     *
116.1363 +     * will return "xx-YY", but the language subtag "xx" and the
116.1364 +     * region subtag "YY" are invalid because they are not registered
116.1365 +     * in the IANA Language Subtag Registry.
116.1366 +     *
116.1367 +     * @return a BCP47 language tag representing the locale
116.1368 +     * @see #forLanguageTag(String)
116.1369 +     * @since 1.7
116.1370 +     */
116.1371 +    public String toLanguageTag() {
116.1372 +        LanguageTag tag = LanguageTag.parseLocale(_baseLocale, _extensions);
116.1373 +        StringBuilder buf = new StringBuilder();
116.1374 +
116.1375 +        String subtag = tag.getLanguage();
116.1376 +        buf.append(LanguageTag.canonicalizeLanguage(subtag));
116.1377 +
116.1378 +        subtag = tag.getScript();
116.1379 +        if (subtag.length() > 0) {
116.1380 +            buf.append(LanguageTag.SEP);
116.1381 +            buf.append(LanguageTag.canonicalizeScript(subtag));
116.1382 +        }
116.1383 +
116.1384 +        subtag = tag.getRegion();
116.1385 +        if (subtag.length() > 0) {
116.1386 +            buf.append(LanguageTag.SEP);
116.1387 +            buf.append(LanguageTag.canonicalizeRegion(subtag));
116.1388 +        }
116.1389 +
116.1390 +        List<String>subtags = tag.getVariants();
116.1391 +        for (String s : subtags) {
116.1392 +            buf.append(LanguageTag.SEP);
116.1393 +            // preserve casing
116.1394 +            buf.append(s);
116.1395 +        }
116.1396 +
116.1397 +        subtags = tag.getExtensions();
116.1398 +        for (String s : subtags) {
116.1399 +            buf.append(LanguageTag.SEP);
116.1400 +            buf.append(LanguageTag.canonicalizeExtension(s));
116.1401 +        }
116.1402 +
116.1403 +        subtag = tag.getPrivateuse();
116.1404 +        if (subtag.length() > 0) {
116.1405 +            buf.append(LanguageTag.SEP).append(LanguageTag.PRIVATEUSE).append(LanguageTag.SEP);
116.1406 +            // preserve casing
116.1407 +            buf.append(subtag);
116.1408 +        }
116.1409 +
116.1410 +        return buf.toString();
116.1411 +    }
116.1412 +
116.1413 +    /**
116.1414 +     * Returns a locale for the specified IETF BCP 47 language tag string.
116.1415 +     *
116.1416 +     * <p>If the specified language tag contains any ill-formed subtags,
116.1417 +     * the first such subtag and all following subtags are ignored.  Compare
116.1418 +     * to {@link Locale.Builder#setLanguageTag} which throws an exception
116.1419 +     * in this case.
116.1420 +     *
116.1421 +     * <p>The following <b>conversions</b> are performed:<ul>
116.1422 +     *
116.1423 +     * <li>The language code "und" is mapped to language "".
116.1424 +     *
116.1425 +     * <li>The language codes "he", "yi", and "id" are mapped to "iw",
116.1426 +     * "ji", and "in" respectively. (This is the same canonicalization
116.1427 +     * that's done in Locale's constructors.)
116.1428 +     *
116.1429 +     * <li>The portion of a private use subtag prefixed by "lvariant",
116.1430 +     * if any, is removed and appended to the variant field in the
116.1431 +     * result locale (without case normalization).  If it is then
116.1432 +     * empty, the private use subtag is discarded:
116.1433 +     *
116.1434 +     * <pre>
116.1435 +     *     Locale loc;
116.1436 +     *     loc = Locale.forLanguageTag("en-US-x-lvariant-POSIX);
116.1437 +     *     loc.getVariant(); // returns "POSIX"
116.1438 +     *     loc.getExtension('x'); // returns null
116.1439 +     *
116.1440 +     *     loc = Locale.forLanguageTag("de-POSIX-x-URP-lvariant-Abc-Def");
116.1441 +     *     loc.getVariant(); // returns "POSIX_Abc_Def"
116.1442 +     *     loc.getExtension('x'); // returns "urp"
116.1443 +     * </pre>
116.1444 +     *
116.1445 +     * <li>When the languageTag argument contains an extlang subtag,
116.1446 +     * the first such subtag is used as the language, and the primary
116.1447 +     * language subtag and other extlang subtags are ignored:
116.1448 +     *
116.1449 +     * <pre>
116.1450 +     *     Locale.forLanguageTag("ar-aao").getLanguage(); // returns "aao"
116.1451 +     *     Locale.forLanguageTag("en-abc-def-us").toString(); // returns "abc_US"
116.1452 +     * </pre>
116.1453 +     *
116.1454 +     * <li>Case is normalized except for variant tags, which are left
116.1455 +     * unchanged.  Language is normalized to lower case, script to
116.1456 +     * title case, country to upper case, and extensions to lower
116.1457 +     * case.
116.1458 +     *
116.1459 +     * <li>If, after processing, the locale would exactly match either
116.1460 +     * ja_JP_JP or th_TH_TH with no extensions, the appropriate
116.1461 +     * extensions are added as though the constructor had been called:
116.1462 +     *
116.1463 +     * <pre>
116.1464 +     *    Locale.forLanguageTag("ja-JP-x-lvariant-JP).toLanguageTag();
116.1465 +     *    // returns ja-JP-u-ca-japanese-x-lvariant-JP
116.1466 +     *    Locale.forLanguageTag("th-TH-x-lvariant-TH).toLanguageTag();
116.1467 +     *    // returns th-TH-u-nu-thai-x-lvariant-TH
116.1468 +     * <pre></ul>
116.1469 +     *
116.1470 +     * <p>This implements the 'Language-Tag' production of BCP47, and
116.1471 +     * so supports grandfathered (regular and irregular) as well as
116.1472 +     * private use language tags.  Stand alone private use tags are
116.1473 +     * represented as empty language and extension 'x-whatever',
116.1474 +     * and grandfathered tags are converted to their canonical replacements
116.1475 +     * where they exist.
116.1476 +     *
116.1477 +     * <p>Grandfathered tags with canonical replacements are as follows:
116.1478 +     *
116.1479 +     * <table>
116.1480 +     * <tbody align="center">
116.1481 +     * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>modern replacement</th></tr>
116.1482 +     * <tr><td>art-lojban</td><td>&nbsp;</td><td>jbo</td></tr>
116.1483 +     * <tr><td>i-ami</td><td>&nbsp;</td><td>ami</td></tr>
116.1484 +     * <tr><td>i-bnn</td><td>&nbsp;</td><td>bnn</td></tr>
116.1485 +     * <tr><td>i-hak</td><td>&nbsp;</td><td>hak</td></tr>
116.1486 +     * <tr><td>i-klingon</td><td>&nbsp;</td><td>tlh</td></tr>
116.1487 +     * <tr><td>i-lux</td><td>&nbsp;</td><td>lb</td></tr>
116.1488 +     * <tr><td>i-navajo</td><td>&nbsp;</td><td>nv</td></tr>
116.1489 +     * <tr><td>i-pwn</td><td>&nbsp;</td><td>pwn</td></tr>
116.1490 +     * <tr><td>i-tao</td><td>&nbsp;</td><td>tao</td></tr>
116.1491 +     * <tr><td>i-tay</td><td>&nbsp;</td><td>tay</td></tr>
116.1492 +     * <tr><td>i-tsu</td><td>&nbsp;</td><td>tsu</td></tr>
116.1493 +     * <tr><td>no-bok</td><td>&nbsp;</td><td>nb</td></tr>
116.1494 +     * <tr><td>no-nyn</td><td>&nbsp;</td><td>nn</td></tr>
116.1495 +     * <tr><td>sgn-BE-FR</td><td>&nbsp;</td><td>sfb</td></tr>
116.1496 +     * <tr><td>sgn-BE-NL</td><td>&nbsp;</td><td>vgt</td></tr>
116.1497 +     * <tr><td>sgn-CH-DE</td><td>&nbsp;</td><td>sgg</td></tr>
116.1498 +     * <tr><td>zh-guoyu</td><td>&nbsp;</td><td>cmn</td></tr>
116.1499 +     * <tr><td>zh-hakka</td><td>&nbsp;</td><td>hak</td></tr>
116.1500 +     * <tr><td>zh-min-nan</td><td>&nbsp;</td><td>nan</td></tr>
116.1501 +     * <tr><td>zh-xiang</td><td>&nbsp;</td><td>hsn</td></tr>
116.1502 +     * </tbody>
116.1503 +     * </table>
116.1504 +     *
116.1505 +     * <p>Grandfathered tags with no modern replacement will be
116.1506 +     * converted as follows:
116.1507 +     *
116.1508 +     * <table>
116.1509 +     * <tbody align="center">
116.1510 +     * <tr><th>grandfathered tag</th><th>&nbsp;</th><th>converts to</th></tr>
116.1511 +     * <tr><td>cel-gaulish</td><td>&nbsp;</td><td>xtg-x-cel-gaulish</td></tr>
116.1512 +     * <tr><td>en-GB-oed</td><td>&nbsp;</td><td>en-GB-x-oed</td></tr>
116.1513 +     * <tr><td>i-default</td><td>&nbsp;</td><td>en-x-i-default</td></tr>
116.1514 +     * <tr><td>i-enochian</td><td>&nbsp;</td><td>und-x-i-enochian</td></tr>
116.1515 +     * <tr><td>i-mingo</td><td>&nbsp;</td><td>see-x-i-mingo</td></tr>
116.1516 +     * <tr><td>zh-min</td><td>&nbsp;</td><td>nan-x-zh-min</td></tr>
116.1517 +     * </tbody>
116.1518 +     * </table>
116.1519 +     *
116.1520 +     * <p>For a list of all grandfathered tags, see the
116.1521 +     * IANA Language Subtag Registry (search for "Type: grandfathered").
116.1522 +     *
116.1523 +     * <p><b>Note</b>: there is no guarantee that <code>toLanguageTag</code>
116.1524 +     * and <code>forLanguageTag</code> will round-trip.
116.1525 +     *
116.1526 +     * @param languageTag the language tag
116.1527 +     * @return The locale that best represents the language tag.
116.1528 +     * @throws NullPointerException if <code>languageTag</code> is <code>null</code>
116.1529 +     * @see #toLanguageTag()
116.1530 +     * @see java.util.Locale.Builder#setLanguageTag(String)
116.1531 +     * @since 1.7
116.1532 +     */
116.1533 +    public static Locale forLanguageTag(String languageTag) {
116.1534 +        LanguageTag tag = LanguageTag.parse(languageTag, null);
116.1535 +        InternalLocaleBuilder bldr = new InternalLocaleBuilder();
116.1536 +        bldr.setLanguageTag(tag);
116.1537 +        return getInstance(bldr.getBaseLocale(), bldr.getLocaleExtensions());
116.1538 +    }
116.1539 +
116.1540 +    /**
116.1541 +     * Returns a three-letter abbreviation of this locale's language.
116.1542 +     * If the language matches an ISO 639-1 two-letter code, the
116.1543 +     * corresponding ISO 639-2/T three-letter lowercase code is
116.1544 +     * returned.  The ISO 639-2 language codes can be found on-line,
116.1545 +     * see "Codes for the Representation of Names of Languages Part 2:
116.1546 +     * Alpha-3 Code".  If the locale specifies a three-letter
116.1547 +     * language, the language is returned as is.  If the locale does
116.1548 +     * not specify a language the empty string is returned.
116.1549 +     *
116.1550 +     * @return A three-letter abbreviation of this locale's language.
116.1551 +     * @exception MissingResourceException Throws MissingResourceException if
116.1552       * three-letter language abbreviation is not available for this locale.
116.1553       */
116.1554      public String getISO3Language() throws MissingResourceException {
116.1555 -        String language3 = getISO3Code(language, LocaleISOData.isoLanguageTable);
116.1556 +        String language3 = getISO3Code(_baseLocale.getLanguage(), LocaleISOData.isoLanguageTable);
116.1557          if (language3 == null) {
116.1558              throw new MissingResourceException("Couldn't find 3-letter language code for "
116.1559 -                    + language, "FormatData_" + toString(), "ShortLanguage");
116.1560 +                    + _baseLocale.getLanguage(), "FormatData_" + toString(), "ShortLanguage");
116.1561          }
116.1562          return language3;
116.1563      }
116.1564  
116.1565      /**
116.1566 -     * Returns a three-letter abbreviation for this locale's country.  If the locale
116.1567 -     * doesn't specify a country, this will be the empty string.  Otherwise, this will
116.1568 -     * be an uppercase ISO 3166 3-letter country code.
116.1569 -     * The ISO 3166-2 country codes can be found on-line at
116.1570 -     * <a href="http://www.davros.org/misc/iso3166.txt">
116.1571 -     * <code>http://www.davros.org/misc/iso3166.txt</code>.</a>
116.1572 +     * Returns a three-letter abbreviation for this locale's country.
116.1573 +     * If the country matches an ISO 3166-1 alpha-2 code, the
116.1574 +     * corresponding ISO 3166-1 alpha-3 uppercase code is returned.
116.1575 +     * If the locale doesn't specify a country, this will be the empty
116.1576 +     * string.
116.1577 +     *
116.1578 +     * <p>The ISO 3166-1 codes can be found on-line.
116.1579 +     *
116.1580 +     * @return A three-letter abbreviation of this locale's country.
116.1581       * @exception MissingResourceException Throws MissingResourceException if the
116.1582       * three-letter country abbreviation is not available for this locale.
116.1583       */
116.1584      public String getISO3Country() throws MissingResourceException {
116.1585 -        String country3 = getISO3Code(country, LocaleISOData.isoCountryTable);
116.1586 +        String country3 = getISO3Code(_baseLocale.getRegion(), LocaleISOData.isoCountryTable);
116.1587          if (country3 == null) {
116.1588              throw new MissingResourceException("Couldn't find 3-letter country code for "
116.1589 -                    + country, "FormatData_" + toString(), "ShortCountry");
116.1590 +                    + _baseLocale.getRegion(), "FormatData_" + toString(), "ShortCountry");
116.1591          }
116.1592          return country3;
116.1593      }
116.1594 @@ -642,7 +1509,7 @@
116.1595       * value.  If the locale doesn't specify a language, this function returns the empty string.
116.1596       */
116.1597      public final String getDisplayLanguage() {
116.1598 -        return getDisplayLanguage(getDefault());
116.1599 +        return getDisplayLanguage(getDefault(Category.DISPLAY));
116.1600      }
116.1601  
116.1602      /**
116.1603 @@ -661,7 +1528,33 @@
116.1604       * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
116.1605       */
116.1606      public String getDisplayLanguage(Locale inLocale) {
116.1607 -        return getDisplayString(language, inLocale, DISPLAY_LANGUAGE);
116.1608 +        return getDisplayString(_baseLocale.getLanguage(), inLocale, DISPLAY_LANGUAGE);
116.1609 +    }
116.1610 +
116.1611 +    /**
116.1612 +     * Returns a name for the the locale's script that is appropriate for display to
116.1613 +     * the user. If possible, the name will be localized for the default locale.  Returns
116.1614 +     * the empty string if this locale doesn't specify a script code.
116.1615 +     *
116.1616 +     * @return the display name of the script code for the current default locale
116.1617 +     * @since 1.7
116.1618 +     */
116.1619 +    public String getDisplayScript() {
116.1620 +        return getDisplayScript(getDefault());
116.1621 +    }
116.1622 +
116.1623 +    /**
116.1624 +     * Returns a name for the locale's script that is appropriate
116.1625 +     * for display to the user. If possible, the name will be
116.1626 +     * localized for the given locale. Returns the empty string if
116.1627 +     * this locale doesn't specify a script code.
116.1628 +     *
116.1629 +     * @return the display name of the script code for the current default locale
116.1630 +     * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
116.1631 +     * @since 1.7
116.1632 +     */
116.1633 +    public String getDisplayScript(Locale inLocale) {
116.1634 +        return getDisplayString(_baseLocale.getScript(), inLocale, DISPLAY_SCRIPT);
116.1635      }
116.1636  
116.1637      /**
116.1638 @@ -677,7 +1570,7 @@
116.1639       * value.  If the locale doesn't specify a country, this function returns the empty string.
116.1640       */
116.1641      public final String getDisplayCountry() {
116.1642 -        return getDisplayCountry(getDefault());
116.1643 +        return getDisplayCountry(getDefault(Category.DISPLAY));
116.1644      }
116.1645  
116.1646      /**
116.1647 @@ -696,7 +1589,7 @@
116.1648       * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
116.1649       */
116.1650      public String getDisplayCountry(Locale inLocale) {
116.1651 -        return getDisplayString(country, inLocale, DISPLAY_COUNTRY);
116.1652 +        return getDisplayString(_baseLocale.getRegion(), inLocale, DISPLAY_COUNTRY);
116.1653      }
116.1654  
116.1655      private String getDisplayString(String code, Locale inLocale, int type) {
116.1656 @@ -744,7 +1637,7 @@
116.1657       * doesn't specify a variant code, this function returns the empty string.
116.1658       */
116.1659      public final String getDisplayVariant() {
116.1660 -        return getDisplayVariant(getDefault());
116.1661 +        return getDisplayVariant(getDefault(Category.DISPLAY));
116.1662      }
116.1663  
116.1664      /**
116.1665 @@ -755,7 +1648,7 @@
116.1666       * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
116.1667       */
116.1668      public String getDisplayVariant(Locale inLocale) {
116.1669 -        if (variant.length() == 0)
116.1670 +        if (_baseLocale.getVariant().length() == 0)
116.1671              return "";
116.1672  
116.1673          OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
116.1674 @@ -776,39 +1669,44 @@
116.1675  
116.1676      /**
116.1677       * Returns a name for the locale that is appropriate for display to the
116.1678 -     * user.  This will be the values returned by getDisplayLanguage(), getDisplayCountry(),
116.1679 -     * and getDisplayVariant() assembled into a single string.  The display name will have
116.1680 -     * one of the following forms:<p><blockquote>
116.1681 -     * language (country, variant)<p>
116.1682 -     * language (country)<p>
116.1683 -     * language (variant)<p>
116.1684 -     * country (variant)<p>
116.1685 -     * language<p>
116.1686 -     * country<p>
116.1687 -     * variant<p></blockquote>
116.1688 -     * depending on which fields are specified in the locale.  If the language, country,
116.1689 -     * and variant fields are all empty, this function returns the empty string.
116.1690 +     * user. This will be the values returned by getDisplayLanguage(),
116.1691 +     * getDisplayScript(), getDisplayCountry(), and getDisplayVariant() assembled
116.1692 +     * into a single string. The the non-empty values are used in order,
116.1693 +     * with the second and subsequent names in parentheses.  For example:
116.1694 +     * <blockquote>
116.1695 +     * language (script, country, variant)<br>
116.1696 +     * language (country)<br>
116.1697 +     * language (variant)<br>
116.1698 +     * script (country)<br>
116.1699 +     * country<br>
116.1700 +     * </blockquote>
116.1701 +     * depending on which fields are specified in the locale.  If the
116.1702 +     * language, sacript, country, and variant fields are all empty,
116.1703 +     * this function returns the empty string.
116.1704       */
116.1705      public final String getDisplayName() {
116.1706 -        return getDisplayName(getDefault());
116.1707 +        return getDisplayName(getDefault(Category.DISPLAY));
116.1708      }
116.1709  
116.1710      /**
116.1711 -     * Returns a name for the locale that is appropriate for display to the
116.1712 -     * user.  This will be the values returned by getDisplayLanguage(), getDisplayCountry(),
116.1713 -     * and getDisplayVariant() assembled into a single string.  The display name will have
116.1714 -     * one of the following forms:<p><blockquote>
116.1715 -     * language (country, variant)<p>
116.1716 -     * language (country)<p>
116.1717 -     * language (variant)<p>
116.1718 -     * country (variant)<p>
116.1719 -     * language<p>
116.1720 -     * country<p>
116.1721 -     * variant<p></blockquote>
116.1722 -     * depending on which fields are specified in the locale.  If the language, country,
116.1723 -     * and variant fields are all empty, this function returns the empty string.
116.1724 +     * Returns a name for the locale that is appropriate for display
116.1725 +     * to the user.  This will be the values returned by
116.1726 +     * getDisplayLanguage(), getDisplayScript(),getDisplayCountry(),
116.1727 +     * and getDisplayVariant() assembled into a single string.
116.1728 +     * The non-empty values are used in order,
116.1729 +     * with the second and subsequent names in parentheses.  For example:
116.1730 +     * <blockquote>
116.1731 +     * language (script, country, variant)<br>
116.1732 +     * language (country)<br>
116.1733 +     * language (variant)<br>
116.1734 +     * script (country)<br>
116.1735 +     * country<br>
116.1736 +     * </blockquote>
116.1737 +     * depending on which fields are specified in the locale.  If the
116.1738 +     * language, script, country, and variant fields are all empty,
116.1739 +     * this function returns the empty string.
116.1740       *
116.1741 -     * @exception NullPointerException if <code>inLocale</code> is <code>null</code>
116.1742 +     * @throws NullPointerException if <code>inLocale</code> is <code>null</code>
116.1743       */
116.1744      public String getDisplayName(Locale inLocale) {
116.1745          OpenListResourceBundle bundle = LocaleData.getLocaleNames(inLocale);
116.1746 @@ -888,7 +1786,7 @@
116.1747      }
116.1748  
116.1749      /**
116.1750 -     * Overrides Cloneable
116.1751 +     * Overrides Cloneable.
116.1752       */
116.1753      public Object clone()
116.1754      {
116.1755 @@ -908,7 +1806,7 @@
116.1756      public int hashCode() {
116.1757          int hc = hashCodeValue;
116.1758          if (hc == 0) {
116.1759 -            hc = (language.hashCode() << 8) ^ country.hashCode() ^ (variant.hashCode() << 4);
116.1760 +            hc = _baseLocale.hashCode() ^ _extensions.hashCode();
116.1761              hashCodeValue = hc;
116.1762          }
116.1763          return hc;
116.1764 @@ -918,8 +1816,8 @@
116.1765  
116.1766      /**
116.1767       * Returns true if this Locale is equal to another object.  A Locale is
116.1768 -     * deemed equal to another Locale with identical language, country,
116.1769 -     * and variant, and unequal to all other objects.
116.1770 +     * deemed equal to another Locale with identical language, script, country,
116.1771 +     * variant and extensions, and unequal to all other objects.
116.1772       *
116.1773       * @return true if this Locale is equal to the specified object.
116.1774       */
116.1775 @@ -929,47 +1827,24 @@
116.1776              return true;
116.1777          if (!(obj instanceof Locale))
116.1778              return false;
116.1779 -        Locale other = (Locale) obj;
116.1780 -        return language == other.language
116.1781 -            && country == other.country
116.1782 -            && variant == other.variant;
116.1783 +        BaseLocale otherBase = ((Locale)obj)._baseLocale;
116.1784 +        LocaleExtensions otherExt = ((Locale)obj)._extensions;
116.1785 +        return _baseLocale.equals(otherBase) && _extensions.equals(otherExt);
116.1786      }
116.1787  
116.1788      // ================= privates =====================================
116.1789  
116.1790 -    // XXX instance and class variables. For now keep these separate, since it is
116.1791 -    // faster to match. Later, make into single string.
116.1792 +    private transient BaseLocale _baseLocale;
116.1793 +    private transient LocaleExtensions _extensions;
116.1794  
116.1795      /**
116.1796 -     * @serial
116.1797 -     * @see #getLanguage
116.1798 -     */
116.1799 -    private final String language;
116.1800 -
116.1801 -    /**
116.1802 -     * @serial
116.1803 -     * @see #getCountry
116.1804 -     */
116.1805 -    private final String country;
116.1806 -
116.1807 -    /**
116.1808 -     * @serial
116.1809 -     * @see #getVariant
116.1810 -     */
116.1811 -    private final String variant;
116.1812 -
116.1813 -    /**
116.1814 -     * Placeholder for the object's hash code.  Always -1.
116.1815 -     * @serial
116.1816 -     */
116.1817 -    private volatile int hashcode = -1;        // lazy evaluate
116.1818 -
116.1819 -    /**
116.1820 -     * Calculated hashcode to fix 4518797.
116.1821 +     * Calculated hashcode
116.1822       */
116.1823      private transient volatile int hashCodeValue = 0;
116.1824  
116.1825      private static Locale defaultLocale = null;
116.1826 +    private static Locale defaultDisplayLocale = null;
116.1827 +    private static Locale defaultFormatLocale = null;
116.1828  
116.1829      /**
116.1830       * Return an array of the display names of the variant.
116.1831 @@ -978,7 +1853,7 @@
116.1832       */
116.1833      private String[] getDisplayVariantArray(OpenListResourceBundle bundle, Locale inLocale) {
116.1834          // Split the variant name into tokens separated by '_'.
116.1835 -        StringTokenizer tokenizer = new StringTokenizer(variant, "_");
116.1836 +        StringTokenizer tokenizer = new StringTokenizer(_baseLocale.getVariant(), "_");
116.1837          String[] names = new String[tokenizer.countTokens()];
116.1838  
116.1839          // For each variant token, lookup the display name.  If
116.1840 @@ -1056,49 +1931,102 @@
116.1841      }
116.1842  
116.1843      /**
116.1844 -     * Replace the deserialized Locale object with a newly
116.1845 -     * created object. Newer language codes are replaced with older ISO
116.1846 -     * codes. The country and variant codes are replaced with internalized
116.1847 -     * String copies.
116.1848 +     * @serialField language    String
116.1849 +     *      language subtag in lower case. (See <a href="java/util/Locale.html#getLanguage()">getLanguage()</a>)
116.1850 +     * @serialField country     String
116.1851 +     *      country subtag in upper case. (See <a href="java/util/Locale.html#getCountry()">getCountry()</a>)
116.1852 +     * @serialField variant     String
116.1853 +     *      variant subtags separated by LOWLINE characters. (See <a href="java/util/Locale.html#getVariant()">getVariant()</a>)
116.1854 +     * @serialField hashcode    int
116.1855 +     *      deprectated, for forward compatibility only
116.1856 +     * @serialField script      String
116.1857 +     *      script subtag in title case (See <a href="java/util/Locale.html#getScript()">getScript()</a>)
116.1858 +     * @serialField extensions  String
116.1859 +     *      canonical representation of extensions, that is,
116.1860 +     *      BCP47 extensions in alphabetical order followed by
116.1861 +     *      BCP47 private use subtags, all in lower case letters
116.1862 +     *      separated by HYPHEN-MINUS characters.
116.1863 +     *      (See <a href="java/util/Locale.html#getExtensionKeys()">getExtensionKeys()</a>,
116.1864 +     *      <a href="java/util/Locale.html#getExtension(char)">getExtension(char)</a>)
116.1865 +     */
116.1866 +    private static final ObjectStreamField[] serialPersistentFields = {
116.1867 +        new ObjectStreamField("language", String.class),
116.1868 +        new ObjectStreamField("country", String.class),
116.1869 +        new ObjectStreamField("variant", String.class),
116.1870 +        new ObjectStreamField("hashcode", int.class),
116.1871 +        new ObjectStreamField("script", String.class),
116.1872 +        new ObjectStreamField("extensions", String.class),
116.1873 +    };
116.1874 +
116.1875 +    /**
116.1876 +     * Serializes this <code>Locale</code> to the specified <code>ObjectOutputStream</code>.
116.1877 +     * @param out the <code>ObjectOutputStream</code> to write
116.1878 +     * @throws IOException
116.1879 +     * @since 1.7
116.1880 +     */
116.1881 +    private void writeObject(ObjectOutputStream out) throws IOException {
116.1882 +        ObjectOutputStream.PutField fields = out.putFields();
116.1883 +        fields.put("language", _baseLocale.getLanguage());
116.1884 +        fields.put("script", _baseLocale.getScript());
116.1885 +        fields.put("country", _baseLocale.getRegion());
116.1886 +        fields.put("variant", _baseLocale.getVariant());
116.1887 +        fields.put("extensions", _extensions.getID());
116.1888 +        fields.put("hashcode", -1); // place holder just for backward support
116.1889 +        out.writeFields();
116.1890 +    }
116.1891 +
116.1892 +    /**
116.1893 +     * Deserialize this <code>Locale</code>.
116.1894 +     * @param in the <code>ObjectInputStream</code> to read
116.1895 +     * @throws IOException
116.1896 +     * @throws ClassNotFoundException
116.1897 +     * @throws IllformdLocaleException
116.1898 +     * @since 1.7
116.1899 +     */
116.1900 +    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
116.1901 +        ObjectInputStream.GetField fields = in.readFields();
116.1902 +        String language = (String)fields.get("language", "");
116.1903 +        String script = (String)fields.get("script", "");
116.1904 +        String country = (String)fields.get("country", "");
116.1905 +        String variant = (String)fields.get("variant", "");
116.1906 +        String extStr = (String)fields.get("extensions", "");
116.1907 +        _baseLocale = BaseLocale.getInstance(convertOldISOCodes(language), script, country, variant);
116.1908 +        try {
116.1909 +            InternalLocaleBuilder bldr = new InternalLocaleBuilder();
116.1910 +            bldr.setExtensions(extStr);
116.1911 +            _extensions = bldr.getLocaleExtensions();
116.1912 +        } catch (LocaleSyntaxException e) {
116.1913 +            throw new IllformedLocaleException(e.getMessage());
116.1914 +        }
116.1915 +    }
116.1916 +
116.1917 +    /**
116.1918 +     * Returns a cached <code>Locale</code> instance equivalent to
116.1919 +     * the deserialized <code>Locale</code>. When serialized
116.1920 +     * language, country and variant fields read from the object data stream
116.1921 +     * are exactly "ja", "JP", "JP" or "th", "TH", "TH" and script/extensions
116.1922 +     * fields are empty, this method supplies <code>UNICODE_LOCALE_EXTENSION</code>
116.1923 +     * "ca"/"japanese" (calendar type is "japanese") or "nu"/"thai" (number script
116.1924 +     * type is "thai"). See <a href="Locale.html#special_cases_constructor"/>Special Cases</a>
116.1925 +     * for more information.
116.1926 +     *
116.1927 +     * @return an instance of <code>Locale</code> equivalent to
116.1928 +     * the deserialized <code>Locale</code>.
116.1929 +     * @throws java.io.ObjectStreamException
116.1930       */
116.1931      private Object readResolve() throws java.io.ObjectStreamException {
116.1932 -        return getInstance(language, country, variant);
116.1933 +        return getInstance(_baseLocale.getLanguage(), _baseLocale.getScript(),
116.1934 +                _baseLocale.getRegion(), _baseLocale.getVariant(), _extensions);
116.1935      }
116.1936  
116.1937      private static volatile String[] isoLanguages = null;
116.1938  
116.1939      private static volatile String[] isoCountries = null;
116.1940  
116.1941 -    /*
116.1942 -     * Locale needs its own, locale insensitive version of toLowerCase to
116.1943 -     * avoid circularity problems between Locale and String.
116.1944 -     * The most straightforward algorithm is used. Look at optimizations later.
116.1945 -     */
116.1946 -    private String toLowerCase(String str) {
116.1947 -        char[] buf = new char[str.length()];
116.1948 -        for (int i = 0; i < buf.length; i++) {
116.1949 -            buf[i] = Character.toLowerCase(str.charAt(i));
116.1950 -        }
116.1951 -        return new String( buf );
116.1952 -    }
116.1953 -
116.1954 -    /*
116.1955 -     * Locale needs its own, locale insensitive version of toUpperCase to
116.1956 -     * avoid circularity problems between Locale and String.
116.1957 -     * The most straightforward algorithm is used. Look at optimizations later.
116.1958 -     */
116.1959 -    private String toUpperCase(String str) {
116.1960 -        char[] buf = new char[str.length()];
116.1961 -        for (int i = 0; i < buf.length; i++) {
116.1962 -            buf[i] = Character.toUpperCase(str.charAt(i));
116.1963 -        }
116.1964 -        return new String( buf );
116.1965 -    }
116.1966 -
116.1967 -    private String convertOldISOCodes(String language) {
116.1968 +    private static String convertOldISOCodes(String language) {
116.1969          // we accept both the old and the new ISO codes for the languages whose ISO
116.1970          // codes have changed, but we always store the OLD code, for backward compatibility
116.1971 -        language = toLowerCase(language).intern();
116.1972 +        language = AsciiUtil.toLowerString(language).intern();
116.1973          if (language == "he") {
116.1974              return "iw";
116.1975          } else if (language == "yi") {
116.1976 @@ -1110,6 +2038,25 @@
116.1977          }
116.1978      }
116.1979  
116.1980 +    private static LocaleExtensions getCompatibilityExtensions(String language, String script, String country, String variant) {
116.1981 +        LocaleExtensions extensions = LocaleExtensions.EMPTY_EXTENSIONS;
116.1982 +        // Special cases for backward compatibility support
116.1983 +        if (AsciiUtil.caseIgnoreMatch(language, "ja")
116.1984 +                && script.length() == 0
116.1985 +                && AsciiUtil.caseIgnoreMatch(country, "JP")
116.1986 +                && AsciiUtil.caseIgnoreMatch(variant, "JP")) {
116.1987 +            // ja_JP_JP -> u-ca-japanese (calendar = japanese)
116.1988 +            extensions = LocaleExtensions.CALENDAR_JAPANESE;
116.1989 +        } else if (AsciiUtil.caseIgnoreMatch(language, "th")
116.1990 +                && script.length() == 0
116.1991 +                && AsciiUtil.caseIgnoreMatch(country, "TH")
116.1992 +                && AsciiUtil.caseIgnoreMatch(variant, "TH")) {
116.1993 +            // th_TH_TH -> u-nu-thai (numbersystem = thai)
116.1994 +            extensions = LocaleExtensions.NUMBER_THAI;
116.1995 +        }
116.1996 +        return extensions;
116.1997 +    }
116.1998 +
116.1999      /**
116.2000       * Obtains a localized locale names from a LocaleNameProvider
116.2001       * implementation.
116.2002 @@ -1133,6 +2080,8 @@
116.2003                  return localeNameProvider.getDisplayCountry(code, locale);
116.2004              case DISPLAY_VARIANT:
116.2005                  return localeNameProvider.getDisplayVariant(code, locale);
116.2006 +            case DISPLAY_SCRIPT:
116.2007 +                return localeNameProvider.getDisplayScript(code, locale);
116.2008              default:
116.2009                  assert false; // shouldn't happen
116.2010              }
116.2011 @@ -1140,4 +2089,370 @@
116.2012              return null;
116.2013          }
116.2014      }
116.2015 +
116.2016 +    /**
116.2017 +     * Enum for locale categories.  These locale categories are used to get/set
116.2018 +     * the default locale for the specific functionality represented by the
116.2019 +     * category.
116.2020 +     *
116.2021 +     * @see #getDefault(Locale.Category)
116.2022 +     * @see #setDefault(Locale.Category, Locale)
116.2023 +     * @since 1.7
116.2024 +     */
116.2025 +    public enum Category {
116.2026 +
116.2027 +        /**
116.2028 +         * Category used to represent the default locale for
116.2029 +         * displaying user interfaces.
116.2030 +         */
116.2031 +        DISPLAY,
116.2032 +
116.2033 +        /**
116.2034 +         * Category used to represent the default locale for
116.2035 +         * formatting dates, numbers, and/or currencies.
116.2036 +         */
116.2037 +        FORMAT,
116.2038 +    }
116.2039 +
116.2040 +    /**
116.2041 +     * <code>Builder</code> is used to build instances of <code>Locale</code>
116.2042 +     * from values configured by the setters.  Unlike the <code>Locale</code>
116.2043 +     * constructors, the <code>Builder</code> checks if a value configured by a
116.2044 +     * setter satisfies the syntax requirements defined by the <code>Locale</code>
116.2045 +     * class.  A <code>Locale</code> object created by a <code>Builder</code> is
116.2046 +     * well-formed and can be transformed to a well-formed IETF BCP 47 language tag
116.2047 +     * without losing information.
116.2048 +     *
116.2049 +     * <p><b>Note:</b> The <code>Locale</code> class does not provide any
116.2050 +     * syntactic restrictions on variant, while BCP 47 requires each variant
116.2051 +     * subtag to be 5 to 8 alphanumerics or a single numeric followed by 3
116.2052 +     * alphanumerics.  The method <code>setVariant</code> throws
116.2053 +     * <code>IllformedLocaleException</code> for a variant that does not satisfy
116.2054 +     * this restriction. If it is necessary to support such a variant, use a
116.2055 +     * Locale constructor.  However, keep in mind that a <code>Locale</code>
116.2056 +     * object created this way might lose the variant information when
116.2057 +     * transformed to a BCP 47 language tag.
116.2058 +     *
116.2059 +     * <p>The following example shows how to create a <code>Locale</code> object
116.2060 +     * with the <code>Builder</code>.
116.2061 +     * <blockquote>
116.2062 +     * <pre>
116.2063 +     *     Locale aLocale = new Builder().setLanguage("sr").setScript("Latn").setRegion("RS").build();
116.2064 +     * </pre>
116.2065 +     * </blockquote>
116.2066 +     *
116.2067 +     * <p>Builders can be reused; <code>clear()</code> resets all
116.2068 +     * fields to their default values.
116.2069 +     *
116.2070 +     * @see Locale#forLanguageTag
116.2071 +     * @since 1.7
116.2072 +     */
116.2073 +    public static final class Builder {
116.2074 +        private InternalLocaleBuilder _locbld;
116.2075 +
116.2076 +        /**
116.2077 +         * Constructs an empty Builder. The default value of all
116.2078 +         * fields, extensions, and private use information is the
116.2079 +         * empty string.
116.2080 +         */
116.2081 +        public Builder() {
116.2082 +            _locbld = new InternalLocaleBuilder();
116.2083 +        }
116.2084 +
116.2085 +        /**
116.2086 +         * Resets the <code>Builder</code> to match the provided
116.2087 +         * <code>locale</code>.  Existing state is discarded.
116.2088 +         *
116.2089 +         * <p>All fields of the locale must be well-formed, see {@link Locale}.
116.2090 +         *
116.2091 +         * <p>Locales with any ill-formed fields cause
116.2092 +         * <code>IllformedLocaleException</code> to be thrown, except for the
116.2093 +         * following three cases which are accepted for compatibility
116.2094 +         * reasons:<ul>
116.2095 +         * <li>Locale("ja", "JP", "JP") is treated as "ja-JP-u-ca-japanese"
116.2096 +         * <li>Locale("th", "TH", "TH") is treated as "th-TH-u-nu-thai"
116.2097 +         * <li>Locale("no", "NO", "NY") is treated as "nn-NO"</ul>
116.2098 +         *
116.2099 +         * @param locale the locale
116.2100 +         * @return This builder.
116.2101 +         * @throws IllformedLocaleException if <code>locale</code> has
116.2102 +         * any ill-formed fields.
116.2103 +         * @throws NullPointerException if <code>locale</code> is null.
116.2104 +         */
116.2105 +        public Builder setLocale(Locale locale) {
116.2106 +            try {
116.2107 +                _locbld.setLocale(locale._baseLocale, locale._extensions);
116.2108 +            } catch (LocaleSyntaxException e) {
116.2109 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2110 +            }
116.2111 +            return this;
116.2112 +        }
116.2113 +
116.2114 +        /**
116.2115 +         * Resets the Builder to match the provided IETF BCP 47
116.2116 +         * language tag.  Discards the existing state.  Null and the
116.2117 +         * empty string cause the builder to be reset, like {@link
116.2118 +         * #clear}.  Grandfathered tags (see {@link
116.2119 +         * Locale#forLanguageTag}) are converted to their canonical
116.2120 +         * form before being processed.  Otherwise, the language tag
116.2121 +         * must be well-formed (see {@link Locale}) or an exception is
116.2122 +         * thrown (unlike <code>Locale.forLanguageTag</code>, which
116.2123 +         * just discards ill-formed and following portions of the
116.2124 +         * tag).
116.2125 +         *
116.2126 +         * @param languageTag the language tag
116.2127 +         * @return This builder.
116.2128 +         * @throws IllformedLocaleException if <code>languageTag</code> is ill-formed
116.2129 +         * @see Locale#forLanguageTag(String)
116.2130 +         */
116.2131 +        public Builder setLanguageTag(String languageTag) {
116.2132 +            ParseStatus sts = new ParseStatus();
116.2133 +            LanguageTag tag = LanguageTag.parse(languageTag, sts);
116.2134 +            if (sts.isError()) {
116.2135 +                throw new IllformedLocaleException(sts.getErrorMessage(), sts.getErrorIndex());
116.2136 +            }
116.2137 +            _locbld.setLanguageTag(tag);
116.2138 +
116.2139 +            return this;
116.2140 +        }
116.2141 +
116.2142 +        /**
116.2143 +         * Sets the language.  If <code>language</code> is the empty string or
116.2144 +         * null, the language in this <code>Builder</code> is removed.  Otherwise,
116.2145 +         * the language must be <a href="./Locale.html#def_language">well-formed</a>
116.2146 +         * or an exception is thrown.
116.2147 +         *
116.2148 +         * <p>The typical language value is a two or three-letter language
116.2149 +         * code as defined in ISO639.
116.2150 +         *
116.2151 +         * @param language the language
116.2152 +         * @return This builder.
116.2153 +         * @throws IllformedLocaleException if <code>language</code> is ill-formed
116.2154 +         */
116.2155 +        public Builder setLanguage(String language) {
116.2156 +            try {
116.2157 +                _locbld.setLanguage(language);
116.2158 +            } catch (LocaleSyntaxException e) {
116.2159 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2160 +            }
116.2161 +            return this;
116.2162 +        }
116.2163 +
116.2164 +        /**
116.2165 +         * Sets the script. If <code>script</code> is null or the empty string,
116.2166 +         * the script in this <code>Builder</code> is removed.
116.2167 +         * Otherwise, the script must be <a href="./Locale.html#def_script">well-formed</a> or an
116.2168 +         * exception is thrown.
116.2169 +         *
116.2170 +         * <p>The typical script value is a four-letter script code as defined by ISO 15924.
116.2171 +         *
116.2172 +         * @param script the script
116.2173 +         * @return This builder.
116.2174 +         * @throws IllformedLocaleException if <code>script</code> is ill-formed
116.2175 +         */
116.2176 +        public Builder setScript(String script) {
116.2177 +            try {
116.2178 +                _locbld.setScript(script);
116.2179 +            } catch (LocaleSyntaxException e) {
116.2180 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2181 +            }
116.2182 +            return this;
116.2183 +        }
116.2184 +
116.2185 +        /**
116.2186 +         * Sets the region.  If region is null or the empty string, the region
116.2187 +         * in this <code>Builder</code> is removed.  Otherwise,
116.2188 +         * the region must be <a href="./Locale.html#def_region">well-formed</a> or an
116.2189 +         * exception is thrown.
116.2190 +         *
116.2191 +         * <p>The typical region value is a two-letter ISO 3166 code or a
116.2192 +         * three-digit UN M.49 area code.
116.2193 +         *
116.2194 +         * <p>The country value in the <code>Locale</code> created by the
116.2195 +         * <code>Builder</code> is always normalized to upper case.
116.2196 +         *
116.2197 +         * @param region the region
116.2198 +         * @return This builder.
116.2199 +         * @throws IllformedLocaleException if <code>region</code> is ill-formed
116.2200 +         */
116.2201 +        public Builder setRegion(String region) {
116.2202 +            try {
116.2203 +                _locbld.setRegion(region);
116.2204 +            } catch (LocaleSyntaxException e) {
116.2205 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2206 +            }
116.2207 +            return this;
116.2208 +        }
116.2209 +
116.2210 +        /**
116.2211 +         * Sets the variant.  If variant is null or the empty string, the
116.2212 +         * variant in this <code>Builder</code> is removed.  Otherwise, it
116.2213 +         * must consist of one or more <a href="./Locale.html#def_variant">well-formed</a>
116.2214 +         * subtags, or an exception is thrown.
116.2215 +         *
116.2216 +         * <p><b>Note:</b> This method checks if <code>variant</code>
116.2217 +         * satisfies the IETF BCP 47 variant subtag's syntax requirements,
116.2218 +         * and normalizes the value to lowercase letters.  However,
116.2219 +         * the <code>Locale</code> class does not impose any syntactic
116.2220 +         * restriction on variant, and the variant value in
116.2221 +         * <code>Locale</code> is case sensitive.  To set such a variant,
116.2222 +         * use a Locale constructor.
116.2223 +         *
116.2224 +         * @param variant the variant
116.2225 +         * @return This builder.
116.2226 +         * @throws IllformedLocaleException if <code>variant</code> is ill-formed
116.2227 +         */
116.2228 +        public Builder setVariant(String variant) {
116.2229 +            try {
116.2230 +                _locbld.setVariant(variant);
116.2231 +            } catch (LocaleSyntaxException e) {
116.2232 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2233 +            }
116.2234 +            return this;
116.2235 +        }
116.2236 +
116.2237 +        /**
116.2238 +         * Sets the extension for the given key. If the value is null or the
116.2239 +         * empty string, the extension is removed.  Otherwise, the extension
116.2240 +         * must be <a href="./Locale.html#def_extensions">well-formed</a> or an exception
116.2241 +         * is thrown.
116.2242 +         *
116.2243 +         * <p><b>Note:</b> The key {@link Locale#UNICODE_LOCALE_EXTENSION
116.2244 +         * UNICODE_LOCALE_EXTENSION} ('u') is used for the Unicode locale extension.
116.2245 +         * Setting a value for this key replaces any existing Unicode locale key/type
116.2246 +         * pairs with those defined in the extension.
116.2247 +         *
116.2248 +         * <p><b>Note:</b> The key {@link Locale#PRIVATE_USE_EXTENSION
116.2249 +         * PRIVATE_USE_EXTENSION} ('x') is used for the private use code. To be
116.2250 +         * well-formed, the value for this key needs only to have subtags of one to
116.2251 +         * eight alphanumeric characters, not two to eight as in the general case.
116.2252 +         *
116.2253 +         * @param key the extension key
116.2254 +         * @param value the extension value
116.2255 +         * @return This builder.
116.2256 +         * @throws IllformedLocaleException if <code>key</code> is illegal
116.2257 +         * or <code>value</code> is ill-formed
116.2258 +         * @see #setUnicodeLocaleKeyword(String, String)
116.2259 +         */
116.2260 +        public Builder setExtension(char key, String value) {
116.2261 +            try {
116.2262 +                _locbld.setExtension(key, value);
116.2263 +            } catch (LocaleSyntaxException e) {
116.2264 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2265 +            }
116.2266 +            return this;
116.2267 +        }
116.2268 +
116.2269 +        /**
116.2270 +         * Sets the Unicode locale keyword type for the given key.  If the type
116.2271 +         * is null, the Unicode keyword is removed.  Otherwise, the key must be
116.2272 +         * non-null and both key and type must be <a
116.2273 +         * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
116.2274 +         * is thrown.
116.2275 +         *
116.2276 +         * <p>Keys and types are converted to lower case.
116.2277 +         *
116.2278 +         * <p><b>Note</b>:Setting the 'u' extension via {@link #setExtension}
116.2279 +         * replaces all Unicode locale keywords with those defined in the
116.2280 +         * extension.
116.2281 +         *
116.2282 +         * @param key the Unicode locale key
116.2283 +         * @param type the Unicode locale type
116.2284 +         * @return This builder.
116.2285 +         * @throws IllformedLocaleException if <code>key</code> or <code>type</code>
116.2286 +         * is ill-formed
116.2287 +         * @throws NullPointerException if <code>key</code> is null
116.2288 +         * @see #setExtension(char, String)
116.2289 +         */
116.2290 +        public Builder setUnicodeLocaleKeyword(String key, String type) {
116.2291 +            try {
116.2292 +                _locbld.setUnicodeLocaleKeyword(key, type);
116.2293 +            } catch (LocaleSyntaxException e) {
116.2294 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2295 +            }
116.2296 +            return this;
116.2297 +        }
116.2298 +
116.2299 +        /**
116.2300 +         * Adds a unicode locale attribute, if not already present, otherwise
116.2301 +         * has no effect.  The attribute must not be null and must be <a
116.2302 +         * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
116.2303 +         * is thrown.
116.2304 +         *
116.2305 +         * @param attribute the attribute
116.2306 +         * @return This builder.
116.2307 +         * @throws NullPointerException if <code>attribute</code> is null
116.2308 +         * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
116.2309 +         * @see #setExtension(char, String)
116.2310 +         */
116.2311 +        public Builder addUnicodeLocaleAttribute(String attribute) {
116.2312 +            try {
116.2313 +                _locbld.addUnicodeLocaleAttribute(attribute);
116.2314 +            } catch (LocaleSyntaxException e) {
116.2315 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2316 +            }
116.2317 +            return this;
116.2318 +        }
116.2319 +
116.2320 +        /**
116.2321 +         * Removes a unicode locale attribute, if present, otherwise has no
116.2322 +         * effect.  The attribute must not be null and must be <a
116.2323 +         * href="./Locale.html#def_locale_extension">well-formed</a> or an exception
116.2324 +         * is thrown.
116.2325 +         *
116.2326 +         * <p>Attribute comparision for removal is case-insensitive.
116.2327 +         *
116.2328 +         * @param attribute the attribute
116.2329 +         * @return This builder.
116.2330 +         * @throws NullPointerException if <code>attribute</code> is null
116.2331 +         * @throws IllformedLocaleException if <code>attribute</code> is ill-formed
116.2332 +         * @see #setExtension(char, String)
116.2333 +         */
116.2334 +        public Builder removeUnicodeLocaleAttribute(String attribute) {
116.2335 +            try {
116.2336 +                _locbld.removeUnicodeLocaleAttribute(attribute);
116.2337 +            } catch (LocaleSyntaxException e) {
116.2338 +                throw new IllformedLocaleException(e.getMessage(), e.getErrorIndex());
116.2339 +            }
116.2340 +            return this;
116.2341 +        }
116.2342 +
116.2343 +        /**
116.2344 +         * Resets the builder to its initial, empty state.
116.2345 +         *
116.2346 +         * @return This builder.
116.2347 +         */
116.2348 +        public Builder clear() {
116.2349 +            _locbld.clear();
116.2350 +            return this;
116.2351 +        }
116.2352 +
116.2353 +        /**
116.2354 +         * Resets the extensions to their initial, empty state.
116.2355 +         * Language, script, region and variant are unchanged.
116.2356 +         *
116.2357 +         * @return This builder.
116.2358 +         * @see #setExtension(char, String)
116.2359 +         */
116.2360 +        public Builder clearExtensions() {
116.2361 +            _locbld.clearExtensions();
116.2362 +            return this;
116.2363 +        }
116.2364 +
116.2365 +        /**
116.2366 +         * Returns an instance of <code>Locale</code> created from the fields set
116.2367 +         * on this builder.
116.2368 +         *
116.2369 +         * <p>This applies the conversions listed in {@link Locale#forLanguageTag}
116.2370 +         * when constructing a Locale. (Grandfathered tags are handled in
116.2371 +         * {@link #setLanguageTag}.)
116.2372 +         *
116.2373 +         * @return A Locale.
116.2374 +         */
116.2375 +        public Locale build() {
116.2376 +            BaseLocale baseloc = _locbld.getBaseLocale();
116.2377 +            LocaleExtensions extensions = _locbld.getLocaleExtensions();
116.2378 +            return Locale.getInstance(baseloc, extensions);
116.2379 +        }
116.2380 +    }
116.2381  }
   117.1 --- a/src/share/classes/java/util/Properties.java	Thu Sep 23 17:33:40 2010 -0700
   117.2 +++ b/src/share/classes/java/util/Properties.java	Fri Sep 24 16:41:32 2010 -0700
   117.3 @@ -912,9 +912,13 @@
   117.4       *
   117.5       * <p>The specified stream remains open after this method returns.
   117.6       *
   117.7 -     * @param os the output stream on which to emit the XML document.
   117.8 -     * @param comment a description of the property list, or <code>null</code>
   117.9 -     *        if no comment is desired.
  117.10 +     * @param os        the output stream on which to emit the XML document.
  117.11 +     * @param comment   a description of the property list, or <code>null</code>
  117.12 +     *                  if no comment is desired.
  117.13 +     * @param  encoding the name of a supported
  117.14 +     *                  <a href="../lang/package-summary.html#charenc">
  117.15 +     *                  character encoding</a>
  117.16 +     *
  117.17       * @throws IOException if writing to the specified output stream
  117.18       *         results in an <tt>IOException</tt>.
  117.19       * @throws NullPointerException if <code>os</code> is <code>null</code>,
   118.1 --- a/src/share/classes/java/util/ResourceBundle.java	Thu Sep 23 17:33:40 2010 -0700
   118.2 +++ b/src/share/classes/java/util/ResourceBundle.java	Fri Sep 24 16:41:32 2010 -0700
   118.3 @@ -1,5 +1,5 @@
   118.4  /*
   118.5 - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   118.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   118.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   118.8   *
   118.9   * This code is free software; you can redistribute it and/or modify it
  118.10 @@ -56,16 +56,18 @@
  118.11  import java.util.concurrent.ConcurrentMap;
  118.12  import java.util.jar.JarEntry;
  118.13  
  118.14 +import sun.util.locale.BaseLocale;
  118.15 +import sun.util.locale.LocaleExtensions;
  118.16 +import sun.util.locale.LocaleObjectCache;
  118.17 +
  118.18  
  118.19  /**
  118.20   *
  118.21 - * Resource bundles contain locale-specific objects.
  118.22 - * When your program needs a locale-specific resource,
  118.23 - * a <code>String</code> for example, your program can load it
  118.24 - * from the resource bundle that is appropriate for the
  118.25 - * current user's locale. In this way, you can write
  118.26 - * program code that is largely independent of the user's
  118.27 - * locale isolating most, if not all, of the locale-specific
  118.28 + * Resource bundles contain locale-specific objects.  When your program needs a
  118.29 + * locale-specific resource, a <code>String</code> for example, your program can
  118.30 + * load it from the resource bundle that is appropriate for the current user's
  118.31 + * locale. In this way, you can write program code that is largely independent
  118.32 + * of the user's locale isolating most, if not all, of the locale-specific
  118.33   * information in resource bundles.
  118.34   *
  118.35   * <p>
  118.36 @@ -854,87 +856,140 @@
  118.37      }
  118.38  
  118.39      /**
  118.40 -     * Gets a resource bundle using the specified base name, locale, and class loader.
  118.41 +     * Gets a resource bundle using the specified base name, locale, and class
  118.42 +     * loader.
  118.43       *
  118.44 -     * <p><a name="default_behavior"/>
  118.45 -     * Conceptually, <code>getBundle</code> uses the following strategy for locating and instantiating
  118.46 -     * resource bundles:
  118.47 -     * <p>
  118.48 -     * <code>getBundle</code> uses the base name, the specified locale, and the default
  118.49 -     * locale (obtained from {@link java.util.Locale#getDefault() Locale.getDefault})
  118.50 -     * to generate a sequence of <a name="candidates"><em>candidate bundle names</em></a>.
  118.51 -     * If the specified locale's language, country, and variant are all empty
  118.52 -     * strings, then the base name is the only candidate bundle name.
  118.53 -     * Otherwise, the following sequence is generated from the attribute
  118.54 -     * values of the specified locale (language1, country1, and variant1)
  118.55 -     * and of the default locale (language2, country2, and variant2):
  118.56 -     * <ul>
  118.57 -     * <li> baseName + "_" + language1 + "_" + country1 + "_" + variant1
  118.58 -     * <li> baseName + "_" + language1 + "_" + country1
  118.59 -     * <li> baseName + "_" + language1
  118.60 -     * <li> baseName + "_" + language2 + "_" + country2 + "_" + variant2
  118.61 -     * <li> baseName + "_" + language2 + "_" + country2
  118.62 -     * <li> baseName + "_" + language2
  118.63 -     * <li> baseName
  118.64 -     * </ul>
  118.65 -     * <p>
  118.66 -     * Candidate bundle names where the final component is an empty string are omitted.
  118.67 -     * For example, if country1 is an empty string, the second candidate bundle name is omitted.
  118.68 +     * <p><a name="default_behavior"/>This method behaves the same as calling
  118.69 +     * {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
  118.70 +     * default instance of {@link Control}. The following describes this behavior.
  118.71       *
  118.72 -     * <p>
  118.73 -     * <code>getBundle</code> then iterates over the candidate bundle names to find the first
  118.74 -     * one for which it can <em>instantiate</em> an actual resource bundle. For each candidate
  118.75 -     * bundle name, it attempts to create a resource bundle:
  118.76 -     * <ul>
  118.77 -     * <li>
  118.78 -     * First, it attempts to load a class using the candidate bundle name.
  118.79 -     * If such a class can be found and loaded using the specified class loader, is assignment
  118.80 -     * compatible with ResourceBundle, is accessible from ResourceBundle, and can be instantiated,
  118.81 -     * <code>getBundle</code> creates a new instance of this class and uses it as the <em>result
  118.82 -     * resource bundle</em>.
  118.83 -     * <li>
  118.84 -     * Otherwise, <code>getBundle</code> attempts to locate a property resource file.
  118.85 -     * It generates a path name from the candidate bundle name by replacing all "." characters
  118.86 -     * with "/" and appending the string ".properties".
  118.87 -     * It attempts to find a "resource" with this name using
  118.88 -     * {@link java.lang.ClassLoader#getResource(java.lang.String) ClassLoader.getResource}.
  118.89 -     * (Note that a "resource" in the sense of <code>getResource</code> has nothing to do with
  118.90 -     * the contents of a resource bundle, it is just a container of data, such as a file.)
  118.91 -     * If it finds a "resource", it attempts to create a new
  118.92 -     * {@link PropertyResourceBundle} instance from its contents.
  118.93 -     * If successful, this instance becomes the <em>result resource bundle</em>.
  118.94 -     * </ul>
  118.95 +     * <p><code>getBundle</code> uses the base name, the specified locale, and
  118.96 +     * the default locale (obtained from {@link java.util.Locale#getDefault()
  118.97 +     * Locale.getDefault}) to generate a sequence of <a
  118.98 +     * name="candidates"><em>candidate bundle names</em></a>.  If the specified
  118.99 +     * locale's language, script, country, and variant are all empty strings,
 118.100 +     * then the base name is the only candidate bundle name.  Otherwise, a list
 118.101 +     * of candidate locales is generated from the attribute values of the
 118.102 +     * specified locale (language, script, country and variant) and appended to
 118.103 +     * the base name.  Typically, this will look like the following:
 118.104       *
 118.105 -     * <p>
 118.106 -     * If no result resource bundle has been found, a <code>MissingResourceException</code>
 118.107 -     * is thrown.
 118.108 +     * <pre>
 118.109 +     *     baseName + "_" + language + "_" + script + "_" + country + "_" + variant
 118.110 +     *     baseName + "_" + language + "_" + script + "_" + country
 118.111 +     *     baseName + "_" + language + "_" + script
 118.112 +     *     baseName + "_" + language + "_" + country + "_" + variant
 118.113 +     *     baseName + "_" + language + "_" + country
 118.114 +     *     baseName + "_" + language
 118.115 +     * </pre>
 118.116       *
 118.117 -     * <p><a name="parent_chain"/>
 118.118 -     * Once a result resource bundle has been found, its <em>parent chain</em> is instantiated.
 118.119 -     * <code>getBundle</code> iterates over the candidate bundle names that can be
 118.120 -     * obtained by successively removing variant, country, and language
 118.121 -     * (each time with the preceding "_") from the bundle name of the result resource bundle.
 118.122 -     * As above, candidate bundle names where the final component is an empty string are omitted.
 118.123 -     * With each of the candidate bundle names it attempts to instantiate a resource bundle, as
 118.124 -     * described above.
 118.125 -     * Whenever it succeeds, it calls the previously instantiated resource
 118.126 +     * <p>Candidate bundle names where the final component is an empty string
 118.127 +     * are omitted, along with the underscore.  For example, if country is an
 118.128 +     * empty string, the second and the fifth candidate bundle names above
 118.129 +     * would be omitted.  Also, if script is an empty string, the candidate names
 118.130 +     * including script are omitted.  For example, a locale with language "de"
 118.131 +     * and variant "JAVA" will produce candidate names with base name
 118.132 +     * "MyResource" below.
 118.133 +     *
 118.134 +     * <pre>
 118.135 +     *     MyResource_de__JAVA
 118.136 +     *     MyResource_de
 118.137 +     * </pre>
 118.138 +     *
 118.139 +     * In the case that the variant contains one or more underscores ('_'), a
 118.140 +     * sequence of bundle names generated by truncating the last underscore and
 118.141 +     * the part following it is inserted after a candidate bundle name with the
 118.142 +     * original variant.  For example, for a locale with language "en", script
 118.143 +     * "Latn, country "US" and variant "WINDOWS_VISTA", and bundle base name
 118.144 +     * "MyResource", the list of candidate bundle names below is generated:
 118.145 +     *
 118.146 +     * <pre>
 118.147 +     * MyResource_en_Latn_US_WINDOWS_VISTA
 118.148 +     * MyResource_en_Latn_US_WINDOWS
 118.149 +     * MyResource_en_Latn_US
 118.150 +     * MyResource_en_Latn
 118.151 +     * MyResource_en_US_WINDOWS_VISTA
 118.152 +     * MyResource_en_US_WINDOWS
 118.153 +     * MyResource_en_US
 118.154 +     * MyResource_en
 118.155 +     * </pre>
 118.156 +     *
 118.157 +     * <blockquote><b>Note:</b> For some <code>Locale</code>s, the list of
 118.158 +     * candidate bundle names contains extra names, or the order of bundle names
 118.159 +     * is slightly modified.  See the description of the default implementation
 118.160 +     * of {@link Control#getCandidateLocales(String, Locale)
 118.161 +     * getCandidateLocales} for details.</blockquote>
 118.162 +     *
 118.163 +     * <p><code>getBundle</code> then iterates over the candidate bundle names
 118.164 +     * to find the first one for which it can <em>instantiate</em> an actual
 118.165 +     * resource bundle. It uses the default controls' {@link Control#getFormats
 118.166 +     * getFormats} method, which generates two bundle names for each generated
 118.167 +     * name, the first a class name and the second a properties file name. For
 118.168 +     * each candidate bundle name, it attempts to create a resource bundle:
 118.169 +     *
 118.170 +     * <ul><li>First, it attempts to load a class using the generated class name.
 118.171 +     * If such a class can be found and loaded using the specified class
 118.172 +     * loader, is assignment compatible with ResourceBundle, is accessible from
 118.173 +     * ResourceBundle, and can be instantiated, <code>getBundle</code> creates a
 118.174 +     * new instance of this class and uses it as the <em>result resource
 118.175 +     * bundle</em>.
 118.176 +     *
 118.177 +     * <li>Otherwise, <code>getBundle</code> attempts to locate a property
 118.178 +     * resource file using the generated properties file name.  It generates a
 118.179 +     * path name from the candidate bundle name by replacing all "." characters
 118.180 +     * with "/" and appending the string ".properties".  It attempts to find a
 118.181 +     * "resource" with this name using {@link
 118.182 +     * java.lang.ClassLoader#getResource(java.lang.String)
 118.183 +     * ClassLoader.getResource}.  (Note that a "resource" in the sense of
 118.184 +     * <code>getResource</code> has nothing to do with the contents of a
 118.185 +     * resource bundle, it is just a container of data, such as a file.)  If it
 118.186 +     * finds a "resource", it attempts to create a new {@link
 118.187 +     * PropertyResourceBundle} instance from its contents.  If successful, this
 118.188 +     * instance becomes the <em>result resource bundle</em>.  </ul>
 118.189 +     *
 118.190 +     * <p>This continues until a result resource bundle is instantiated or the
 118.191 +     * list of candidate bundle names is exhausted.  If no matching resource
 118.192 +     * bundle is found, the default control's {@link Control#getFallbackLocale
 118.193 +     * getFallbackLocale} method is called, which returns the current default
 118.194 +     * locale.  A new sequence of candidate locale names is generated using this
 118.195 +     * locale and and searched again, as above.
 118.196 +     *
 118.197 +     * <p>If still no result bundle is found, the base name alone is looked up. If
 118.198 +     * this still fails, a <code>MissingResourceException</code> is thrown.
 118.199 +     *
 118.200 +     * <p><a name="parent_chain"/> Once a result resource bundle has been found,
 118.201 +     * its <em>parent chain</em> is instantiated.  If the result bundle already
 118.202 +     * has a parent (perhaps because it was returned from a cache) the chain is
 118.203 +     * complete.
 118.204 +     *
 118.205 +     * <p>Otherwise, <code>getBundle</code> examines the remainder of the
 118.206 +     * candidate locale list that was used during the pass that generated the
 118.207 +     * result resource bundle.  (As before, candidate bundle names where the
 118.208 +     * final component is an empty string are omitted.)  When it comes to the
 118.209 +     * end of the candidate list, it tries the plain bundle name.  With each of the
 118.210 +     * candidate bundle names it attempts to instantiate a resource bundle (first
 118.211 +     * looking for a class and then a properties file, as described above).
 118.212 +     *
 118.213 +     * <p>Whenever it succeeds, it calls the previously instantiated resource
 118.214       * bundle's {@link #setParent(java.util.ResourceBundle) setParent} method
 118.215 -     * with the new resource bundle, unless the previously instantiated resource
 118.216 -     * bundle already has a non-null parent.
 118.217 +     * with the new resource bundle.  This continues until the list of names
 118.218 +     * is exhausted or the current bundle already has a non-null parent.
 118.219       *
 118.220 -     * <p>
 118.221 -     * <code>getBundle</code> caches instantiated resource bundles and
 118.222 -     * may return the same resource bundle instance multiple
 118.223 -     * times.
 118.224 +     * <p>Once the parent chain is complete, the bundle is returned.
 118.225       *
 118.226 -     * <p>
 118.227 -     * The <code>baseName</code> argument should be a fully qualified class name. However, for
 118.228 -     * compatibility with earlier versions, Sun's Java SE Runtime Environments do not verify this,
 118.229 -     * and so it is possible to access <code>PropertyResourceBundle</code>s by specifying a
 118.230 -     * path name (using "/") instead of a fully qualified class name (using ".").
 118.231 +     * <p><b>Note:</b> <code>getBundle</code> caches instantiated resource
 118.232 +     * bundles and might return the same resource bundle instance multiple times.
 118.233 +     *
 118.234 +     * <p><b>Note:</b>The <code>baseName</code> argument should be a fully
 118.235 +     * qualified class name. However, for compatibility with earlier versions,
 118.236 +     * Sun's Java SE Runtime Environments do not verify this, and so it is
 118.237 +     * possible to access <code>PropertyResourceBundle</code>s by specifying a
 118.238 +     * path name (using "/") instead of a fully qualified class name (using
 118.239 +     * ".").
 118.240       *
 118.241       * <p><a name="default_behavior_example"/>
 118.242 -     * <strong>Example:</strong><br>The following class and property files are provided:
 118.243 +     * <strong>Example:</strong>
 118.244 +     * <p>
 118.245 +     * The following class and property files are provided:
 118.246       * <pre>
 118.247       *     MyResources.class
 118.248       *     MyResources.properties
 118.249 @@ -944,22 +999,26 @@
 118.250       *     MyResources_en.properties
 118.251       *     MyResources_es_ES.class
 118.252       * </pre>
 118.253 -     * The contents of all files are valid (that is, public non-abstract subclasses of <code>ResourceBundle</code> for
 118.254 -     * the ".class" files, syntactically correct ".properties" files).
 118.255 -     * The default locale is <code>Locale("en", "GB")</code>.
 118.256 -     * <p>
 118.257 -     * Calling <code>getBundle</code> with the shown locale argument values instantiates
 118.258 -     * resource bundles from the following sources:
 118.259 -     * <ul>
 118.260 -     * <li>Locale("fr", "CH"): result MyResources_fr_CH.class, parent MyResources_fr.properties, parent MyResources.class
 118.261 -     * <li>Locale("fr", "FR"): result MyResources_fr.properties, parent MyResources.class
 118.262 -     * <li>Locale("de", "DE"): result MyResources_en.properties, parent MyResources.class
 118.263 -     * <li>Locale("en", "US"): result MyResources_en.properties, parent MyResources.class
 118.264 -     * <li>Locale("es", "ES"): result MyResources_es_ES.class, parent MyResources.class
 118.265 -     * </ul>
 118.266 -     * <p>The file MyResources_fr_CH.properties is never used because it is hidden by
 118.267 -     * MyResources_fr_CH.class. Likewise, MyResources.properties is also hidden by
 118.268 -     * MyResources.class.
 118.269 +     *
 118.270 +     * The contents of all files are valid (that is, public non-abstract
 118.271 +     * subclasses of <code>ResourceBundle</code> for the ".class" files,
 118.272 +     * syntactically correct ".properties" files).  The default locale is
 118.273 +     * <code>Locale("en", "GB")</code>.
 118.274 +     *
 118.275 +     * <p>Calling <code>getBundle</code> with the locale arguments below will
 118.276 +     * instantiate resource bundles as follows:
 118.277 +     *
 118.278 +     * <table>
 118.279 +     * <tr><td>Locale("fr", "CH")</td><td>MyResources_fr_CH.class, parent MyResources_fr.properties, parent MyResources.class</td></tr>
 118.280 +     * <tr><td>Locale("fr", "FR")</td><td>MyResources_fr.properties, parent MyResources.class</td></tr>
 118.281 +     * <tr><td>Locale("de", "DE")</td><td>MyResources_en.properties, parent MyResources.class</td></tr>
 118.282 +     * <tr><td>Locale("en", "US")</td><td>MyResources_en.properties, parent MyResources.class</td></tr>
 118.283 +     * <tr><td>Locale("es", "ES")</td><td>MyResources_es_ES.class, parent MyResources.class</td></tr>
 118.284 +     * </table>
 118.285 +     *
 118.286 +     * <p>The file MyResources_fr_CH.properties is never used because it is
 118.287 +     * hidden by the MyResources_fr_CH.class. Likewise, MyResources.properties
 118.288 +     * is also hidden by MyResources.class.
 118.289       *
 118.290       * @param baseName the base name of the resource bundle, a fully qualified class name
 118.291       * @param locale the locale for which a resource bundle is desired
 118.292 @@ -1095,8 +1154,6 @@
 118.293       * href="./ResourceBundle.html#parent_chain">parent chain</a> is
 118.294       * instantiated based on the list of candidate locales from which it was
 118.295       * found. Finally, the bundle is returned to the caller.</li>
 118.296 -     *
 118.297 -     *
 118.298       * </ol>
 118.299       *
 118.300       * <p>During the resource bundle loading process above, this factory
 118.301 @@ -1119,7 +1176,6 @@
 118.302       * {@link Control#getTimeToLive(String,Locale)
 118.303       * control.getTimeToLive} for details.
 118.304       *
 118.305 -     *
 118.306       * <p>The following is an example of the bundle loading process with the
 118.307       * default <code>ResourceBundle.Control</code> implementation.
 118.308       *
 118.309 @@ -1131,7 +1187,6 @@
 118.310       * <li>Available resource bundles:
 118.311       * <code>foo/bar/Messages_fr.properties</code> and
 118.312       * <code>foo/bar/Messages.properties</code></li>
 118.313 -     *
 118.314       * </ul>
 118.315       *
 118.316       * <p>First, <code>getBundle</code> tries loading a resource bundle in
 118.317 @@ -1811,8 +1866,8 @@
 118.318       * handleGetObject} method returns <code>null</code>. Once the
 118.319       * <code>Set</code> has been created, the value is kept in this
 118.320       * <code>ResourceBundle</code> in order to avoid producing the
 118.321 -     * same <code>Set</code> in the next calls.  Override this method
 118.322 -     * in subclass implementations for faster handling.
 118.323 +     * same <code>Set</code> in subsequent calls. Subclasses can
 118.324 +     * override this method for faster handling.
 118.325       *
 118.326       * @return a <code>Set</code> of the keys contained only in this
 118.327       *        <code>ResourceBundle</code>
 118.328 @@ -2177,24 +2232,133 @@
 118.329           * <code>ResourceBundle.getBundle</code> factory method loads only
 118.330           * the base bundle as the resulting resource bundle.
 118.331           *
 118.332 -         * <p>It is not a requirement to return an immutable
 118.333 -         * (unmodifiable) <code>List</code>. However, the returned
 118.334 -         * <code>List</code> must not be mutated after it has been
 118.335 -         * returned by <code>getCandidateLocales</code>.
 118.336 +         * <p>It is not a requirement to return an immutable (unmodifiable)
 118.337 +         * <code>List</code>. However, the returned <code>List</code> must not
 118.338 +         * be mutated after it has been returned by
 118.339 +         * <code>getCandidateLocales</code>.
 118.340           *
 118.341           * <p>The default implementation returns a <code>List</code> containing
 118.342 -         * <code>Locale</code>s in the following sequence:
 118.343 -         * <pre>
 118.344 -         *     Locale(language, country, variant)
 118.345 -         *     Locale(language, country)
 118.346 -         *     Locale(language)
 118.347 -         *     Locale.ROOT
 118.348 -         * </pre>
 118.349 -         * where <code>language</code>, <code>country</code> and
 118.350 -         * <code>variant</code> are the language, country and variant values
 118.351 -         * of the given <code>locale</code>, respectively. Locales where the
 118.352 +         * <code>Locale</code>s using the rules described below.  In the
 118.353 +         * description below, <em>L</em>, <em>S</em>, <em>C</em> and <em>V</em>
 118.354 +         * respectively represent non-empty language, script, country, and
 118.355 +         * variant.  For example, [<em>L</em>, <em>C</em>] represents a
 118.356 +         * <code>Locale</code> that has non-empty values only for language and
 118.357 +         * country.  The form <em>L</em>("xx") represents the (non-empty)
 118.358 +         * language value is "xx".  For all cases, <code>Locale</code>s whose
 118.359           * final component values are empty strings are omitted.
 118.360           *
 118.361 +         * <ol><li>For an input <code>Locale</code> with an empty script value,
 118.362 +         * append candidate <code>Locale</code>s by omitting the final component
 118.363 +         * one by one as below:
 118.364 +         *
 118.365 +         * <ul>
 118.366 +         * <li> [<em>L</em>, <em>C</em>, <em>V</em>]
 118.367 +         * <li> [<em>L</em>, <em>C</em>]
 118.368 +         * <li> [<em>L</em>]
 118.369 +         * <li> <code>Locale.ROOT</code>
 118.370 +         * </ul>
 118.371 +         *
 118.372 +         * <li>For an input <code>Locale</code> with a non-empty script value,
 118.373 +         * append candidate <code>Locale</code>s by omitting the final component
 118.374 +         * up to language, then append candidates generated from the
 118.375 +         * <code>Locale</code> with country and variant restored:
 118.376 +         *
 118.377 +         * <ul>
 118.378 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V</em>]
 118.379 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>]
 118.380 +         * <li> [<em>L</em>, <em>S</em>]
 118.381 +         * <li> [<em>L</em>, <em>C</em>, <em>V</em>]
 118.382 +         * <li> [<em>L</em>, <em>C</em>]
 118.383 +         * <li> [<em>L</em>]
 118.384 +         * <li> <code>Locale.ROOT</code>
 118.385 +         * </ul>
 118.386 +         *
 118.387 +         * <li>For an input <code>Locale</code> with a variant value consisting
 118.388 +         * of multiple subtags separated by underscore, generate candidate
 118.389 +         * <code>Locale</code>s by omitting the variant subtags one by one, then
 118.390 +         * insert them after every occurence of <code> Locale</code>s with the
 118.391 +         * full variant value in the original list.  For example, if the
 118.392 +         * the variant consists of two subtags <em>V1</em> and <em>V2</em>:
 118.393 +         *
 118.394 +         * <ul>
 118.395 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]
 118.396 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>, <em>V1</em>]
 118.397 +         * <li> [<em>L</em>, <em>S</em>, <em>C</em>]
 118.398 +         * <li> [<em>L</em>, <em>S</em>]
 118.399 +         * <li> [<em>L</em>, <em>C</em>, <em>V1</em>, <em>V2</em>]
 118.400 +         * <li> [<em>L</em>, <em>C</em>, <em>V1</em>]
 118.401 +         * <li> [<em>L</em>, <em>C</em>]
 118.402 +         * <li> [<em>L</em>]
 118.403 +         * <li> <code>Locale.ROOT</code>
 118.404 +         * </ul>
 118.405 +         *
 118.406 +         * <li>Special cases for Chinese.  When an input <code>Locale</code> has the
 118.407 +         * language "zh" (Chinese) and an empty script value, either "Hans" (Simplified) or
 118.408 +         * "Hant" (Traditional) might be supplied, depending on the country.
 118.409 +         * When the country is "CN" (China) or "SG" (Singapore), "Hans" is supplied.
 118.410 +         * When the country is "HK" (Hong Kong SAR China), "MO" (Macau SAR China),
 118.411 +         * or "TW" (Taiwan), "Hant" is supplied.  For all other countries or when the country
 118.412 +         * is empty, no script is supplied.  For example, for <code>Locale("zh", "CN")
 118.413 +         * </code>, the candidate list will be:
 118.414 +         * <ul>
 118.415 +         * <li> [<em>L</em>("zh"), <em>S</em>("Hans"), <em>C</em>("CN")]
 118.416 +         * <li> [<em>L</em>("zh"), <em>S</em>("Hans")]
 118.417 +         * <li> [<em>L</em>("zh"), <em>C</em>("CN")]
 118.418 +         * <li> [<em>L</em>("zh")]
 118.419 +         * <li> <code>Locale.ROOT</code>
 118.420 +         * </ul>
 118.421 +         *
 118.422 +         * For <code>Locale("zh", "TW")</code>, the candidate list will be:
 118.423 +         * <ul>
 118.424 +         * <li> [<em>L</em>("zh"), <em>S</em>("Hant"), <em>C</em>("TW")]
 118.425 +         * <li> [<em>L</em>("zh"), <em>S</em>("Hant")]
 118.426 +         * <li> [<em>L</em>("zh"), <em>C</em>("TW")]
 118.427 +         * <li> [<em>L</em>("zh")]
 118.428 +         * <li> <code>Locale.ROOT</code>
 118.429 +         * </ul>
 118.430 +         *
 118.431 +         * <li>Special cases for Norwegian.  Both <code>Locale("no", "NO",
 118.432 +         * "NY")</code> and <code>Locale("nn", "NO")</code> represent Norwegian
 118.433 +         * Nynorsk.  When a locale's language is "nn", the standard candidate
 118.434 +         * list is generated up to [<em>L</em>("nn")], and then the following
 118.435 +         * candidates are added:
 118.436 +         *
 118.437 +         * <ul><li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("NY")]
 118.438 +         * <li> [<em>L</em>("no"), <em>C</em>("NO")]
 118.439 +         * <li> [<em>L</em>("no")]
 118.440 +         * <li> <code>Locale.ROOT</code>
 118.441 +         * </ul>
 118.442 +         *
 118.443 +         * If the locale is exactly <code>Locale("no", "NO", "NY")</code>, it is first
 118.444 +         * converted to <code>Locale("nn", "NO")</code> and then the above procedure is
 118.445 +         * followed.
 118.446 +         *
 118.447 +         * <p>Also, Java treats the language "no" as a synonym of Norwegian
 118.448 +         * Bokm&#xE5;l "nb".  Except for the single case <code>Locale("no",
 118.449 +         * "NO", "NY")</code> (handled above), when an input <code>Locale</code>
 118.450 +         * has language "no" or "nb", candidate <code>Locale</code>s with
 118.451 +         * language code "no" and "nb" are interleaved, first using the
 118.452 +         * requested language, then using its synonym. For example,
 118.453 +         * <code>Locale("nb", "NO", "POSIX")</code> generates the following
 118.454 +         * candidate list:
 118.455 +         *
 118.456 +         * <ul>
 118.457 +         * <li> [<em>L</em>("nb"), <em>C</em>("NO"), <em>V</em>("POSIX")]
 118.458 +         * <li> [<em>L</em>("no"), <em>C</em>("NO"), <em>V</em>("POSIX")]
 118.459 +         * <li> [<em>L</em>("nb"), <em>C</em>("NO")]
 118.460 +         * <li> [<em>L</em>("no"), <em>C</em>("NO")]
 118.461 +         * <li> [<em>L</em>("nb")]
 118.462 +         * <li> [<em>L</em>("no")]
 118.463 +         * <li> <code>Locale.ROOT</code>
 118.464 +         * </ul>
 118.465 +         *
 118.466 +         * <code>Locale("no", "NO", "POSIX")</code> would generate the same list
 118.467 +         * except that locales with "no" would appear before the corresponding
 118.468 +         * locales with "nb".</li>
 118.469 +         *
 118.470 +         * </li>
 118.471 +         * </ol>
 118.472 +         *
 118.473           * <p>The default implementation uses an {@link ArrayList} that
 118.474           * overriding implementations may modify before returning it to the
 118.475           * caller. However, a subclass must not modify it after it has
 118.476 @@ -2231,24 +2395,119 @@
 118.477              if (baseName == null) {
 118.478                  throw new NullPointerException();
 118.479              }
 118.480 -            String language = locale.getLanguage();
 118.481 -            String country = locale.getCountry();
 118.482 -            String variant = locale.getVariant();
 118.483 +            return new ArrayList<Locale>(CANDIDATES_CACHE.get(locale.getBaseLocale()));
 118.484 +        }
 118.485  
 118.486 -            List<Locale> locales = new ArrayList<Locale>(4);
 118.487 -            if (variant.length() > 0) {
 118.488 -                locales.add(locale);
 118.489 +        private static final CandidateListCache CANDIDATES_CACHE = new CandidateListCache();
 118.490 +
 118.491 +        private static class CandidateListCache extends LocaleObjectCache<BaseLocale, List<Locale>> {
 118.492 +            protected List<Locale> createObject(BaseLocale base) {
 118.493 +                String language = base.getLanguage();
 118.494 +                String script = base.getScript();
 118.495 +                String region = base.getRegion();
 118.496 +                String variant = base.getVariant();
 118.497 +
 118.498 +                // Special handling for Norwegian
 118.499 +                boolean isNorwegianBokmal = false;
 118.500 +                boolean isNorwegianNynorsk = false;
 118.501 +                if (language.equals("no")) {
 118.502 +                    if (region.equals("NO") && variant.equals("NY")) {
 118.503 +                        variant = "";
 118.504 +                        isNorwegianNynorsk = true;
 118.505 +                    } else {
 118.506 +                        isNorwegianBokmal = true;
 118.507 +                    }
 118.508 +                }
 118.509 +                if (language.equals("nb") || isNorwegianBokmal) {
 118.510 +                    List<Locale> tmpList = getDefaultList("nb", script, region, variant);
 118.511 +                    // Insert a locale replacing "nb" with "no" for every list entry
 118.512 +                    List<Locale> bokmalList = new LinkedList<Locale>();
 118.513 +                    for (Locale l : tmpList) {
 118.514 +                        bokmalList.add(l);
 118.515 +                        if (l.getLanguage().length() == 0) {
 118.516 +                            break;
 118.517 +                        }
 118.518 +                        bokmalList.add(Locale.getInstance("no", l.getScript(), l.getCountry(),
 118.519 +                                l.getVariant(), LocaleExtensions.EMPTY_EXTENSIONS));
 118.520 +                    }
 118.521 +                    return bokmalList;
 118.522 +                } else if (language.equals("nn") || isNorwegianNynorsk) {
 118.523 +                    // Insert no_NO_NY, no_NO, no after nn
 118.524 +                    List<Locale> nynorskList = getDefaultList("nn", script, region, variant);
 118.525 +                    int idx = nynorskList.size() - 1;
 118.526 +                    nynorskList.add(idx++, Locale.getInstance("no", "NO", "NY"));
 118.527 +                    nynorskList.add(idx++, Locale.getInstance("no", "NO", ""));
 118.528 +                    nynorskList.add(idx++, Locale.getInstance("no", "", ""));
 118.529 +                    return nynorskList;
 118.530 +                }
 118.531 +                // Special handling for Chinese
 118.532 +                else if (language.equals("zh")) {
 118.533 +                    if (script.length() == 0 && region.length() > 0) {
 118.534 +                        // Supply script for users who want to use zh_Hans/zh_Hant
 118.535 +                        // as bundle names (recommended for Java7+)
 118.536 +                        if (region.equals("TW") || region.equals("HK") || region.equals("MO")) {
 118.537 +                            script = "Hant";
 118.538 +                        } else if (region.equals("CN") || region.equals("SG")) {
 118.539 +                            script = "Hans";
 118.540 +                        }
 118.541 +                    } else if (script.length() > 0 && region.length() == 0) {
 118.542 +                        // Supply region(country) for users who still package Chinese
 118.543 +                        // bundles using old convension.
 118.544 +                        if (script.equals("Hans")) {
 118.545 +                            region = "CN";
 118.546 +                        } else if (script.equals("Hant")) {
 118.547 +                            region = "TW";
 118.548 +                        }
 118.549 +                    }
 118.550 +                }
 118.551 +
 118.552 +                return getDefaultList(language, script, region, variant);
 118.553              }
 118.554 -            if (country.length() > 0) {
 118.555 -                locales.add((locales.size() == 0) ?
 118.556 -                            locale : Locale.getInstance(language, country, ""));
 118.557 +
 118.558 +            private static List<Locale> getDefaultList(String language, String script, String region, String variant) {
 118.559 +                List<String> variants = null;
 118.560 +
 118.561 +                if (variant.length() > 0) {
 118.562 +                    variants = new LinkedList<String>();
 118.563 +                    int idx = variant.length();
 118.564 +                    while (idx != -1) {
 118.565 +                        variants.add(variant.substring(0, idx));
 118.566 +                        idx = variant.lastIndexOf('_', --idx);
 118.567 +                    }
 118.568 +                }
 118.569 +
 118.570 +                LinkedList<Locale> list = new LinkedList<Locale>();
 118.571 +
 118.572 +                if (variants != null) {
 118.573 +                    for (String v : variants) {
 118.574 +                        list.add(Locale.getInstance(language, script, region, v, LocaleExtensions.EMPTY_EXTENSIONS));
 118.575 +                    }
 118.576 +                }
 118.577 +                if (region.length() > 0) {
 118.578 +                    list.add(Locale.getInstance(language, script, region, "", LocaleExtensions.EMPTY_EXTENSIONS));
 118.579 +                }
 118.580 +                if (script.length() > 0) {
 118.581 +                    list.add(Locale.getInstance(language, script, "", "", LocaleExtensions.EMPTY_EXTENSIONS));
 118.582 +
 118.583 +                    // With script, after truncating variant, region and script,
 118.584 +                    // start over without script.
 118.585 +                    if (variants != null) {
 118.586 +                        for (String v : variants) {
 118.587 +                            list.add(Locale.getInstance(language, "", region, v, LocaleExtensions.EMPTY_EXTENSIONS));
 118.588 +                        }
 118.589 +                    }
 118.590 +                    if (region.length() > 0) {
 118.591 +                        list.add(Locale.getInstance(language, "", region, "", LocaleExtensions.EMPTY_EXTENSIONS));
 118.592 +                    }
 118.593 +                }
 118.594 +                if (language.length() > 0) {
 118.595 +                    list.add(Locale.getInstance(language, "", "", "", LocaleExtensions.EMPTY_EXTENSIONS));
 118.596 +                }
 118.597 +                // Add root locale at the end
 118.598 +                list.add(Locale.ROOT);
 118.599 +
 118.600 +                return list;
 118.601              }
 118.602 -            if (language.length() > 0) {
 118.603 -                locales.add((locales.size() == 0) ?
 118.604 -                            locale : Locale.getInstance(language, "", ""));
 118.605 -            }
 118.606 -            locales.add(Locale.ROOT);
 118.607 -            return locales;
 118.608          }
 118.609  
 118.610          /**
 118.611 @@ -2606,13 +2865,14 @@
 118.612           *
 118.613           * <p>This implementation returns the following value:
 118.614           * <pre>
 118.615 -         *     baseName + "_" + language + "_" + country + "_" + variant
 118.616 +         *     baseName + "_" + language + "_" + script + "_" + country + "_" + variant
 118.617           * </pre>
 118.618 -         * where <code>language</code>, <code>country</code> and
 118.619 -         * <code>variant</code> are the language, country and variant values
 118.620 -         * of <code>locale</code>, respectively. Final component values that
 118.621 -         * are empty Strings are omitted along with the preceding '_'. If
 118.622 -         * all of the values are empty strings, then <code>baseName</code>
 118.623 +         * where <code>language</code>, <code>script</code>, <code>country</code>,
 118.624 +         * and <code>variant</code> are the language, script, country, and variant
 118.625 +         * values of <code>locale</code>, respectively. Final component values that
 118.626 +         * are empty Strings are omitted along with the preceding '_'.  When the
 118.627 +         * script is empty, the script value is ommitted along with the preceding '_'.
 118.628 +         * If all of the values are empty strings, then <code>baseName</code>
 118.629           * is returned.
 118.630           *
 118.631           * <p>For example, if <code>baseName</code> is
 118.632 @@ -2643,6 +2903,7 @@
 118.633              }
 118.634  
 118.635              String language = locale.getLanguage();
 118.636 +            String script = locale.getScript();
 118.637              String country = locale.getCountry();
 118.638              String variant = locale.getVariant();
 118.639  
 118.640 @@ -2652,12 +2913,22 @@
 118.641  
 118.642              StringBuilder sb = new StringBuilder(baseName);
 118.643              sb.append('_');
 118.644 -            if (variant != "") {
 118.645 -                sb.append(language).append('_').append(country).append('_').append(variant);
 118.646 -            } else if (country != "") {
 118.647 -                sb.append(language).append('_').append(country);
 118.648 +            if (script != "") {
 118.649 +                if (variant != "") {
 118.650 +                    sb.append(language).append('_').append(script).append('_').append(country).append('_').append(variant);
 118.651 +                } else if (country != "") {
 118.652 +                    sb.append(language).append('_').append(script).append('_').append(country);
 118.653 +                } else {
 118.654 +                    sb.append(language).append('_').append(script);
 118.655 +                }
 118.656              } else {
 118.657 -                sb.append(language);
 118.658 +                if (variant != "") {
 118.659 +                    sb.append(language).append('_').append(country).append('_').append(variant);
 118.660 +                } else if (country != "") {
 118.661 +                    sb.append(language).append('_').append(country);
 118.662 +                } else {
 118.663 +                    sb.append(language);
 118.664 +                }
 118.665              }
 118.666              return sb.toString();
 118.667  
   119.1 --- a/src/share/classes/java/util/Scanner.java	Thu Sep 23 17:33:40 2010 -0700
   119.2 +++ b/src/share/classes/java/util/Scanner.java	Fri Sep 24 16:41:32 2010 -0700
   119.3 @@ -582,7 +582,7 @@
   119.4          matcher = delimPattern.matcher(buf);
   119.5          matcher.useTransparentBounds(true);
   119.6          matcher.useAnchoringBounds(false);
   119.7 -        useLocale(Locale.getDefault());
   119.8 +        useLocale(Locale.getDefault(Locale.Category.FORMAT));
   119.9      }
  119.10  
  119.11      /**
  119.12 @@ -2642,7 +2642,7 @@
  119.13       */
  119.14      public Scanner reset() {
  119.15          delimPattern = WHITESPACE_PATTERN;
  119.16 -        useLocale(Locale.getDefault());
  119.17 +        useLocale(Locale.getDefault(Locale.Category.FORMAT));
  119.18          useRadix(10);
  119.19          clearCaches();
  119.20          return this;
   120.1 --- a/src/share/classes/java/util/TimeZone.java	Thu Sep 23 17:33:40 2010 -0700
   120.2 +++ b/src/share/classes/java/util/TimeZone.java	Fri Sep 24 16:41:32 2010 -0700
   120.3 @@ -312,7 +312,7 @@
   120.4       * @since 1.2
   120.5       */
   120.6      public final String getDisplayName() {
   120.7 -        return getDisplayName(false, LONG, Locale.getDefault());
   120.8 +        return getDisplayName(false, LONG, Locale.getDefault(Locale.Category.DISPLAY));
   120.9      }
  120.10  
  120.11      /**
  120.12 @@ -342,7 +342,7 @@
  120.13       * @since 1.2
  120.14       */
  120.15      public final String getDisplayName(boolean daylight, int style) {
  120.16 -        return getDisplayName(daylight, style, Locale.getDefault());
  120.17 +        return getDisplayName(daylight, style, Locale.getDefault(Locale.Category.DISPLAY));
  120.18      }
  120.19  
  120.20      /**
   121.1 --- a/src/share/classes/java/util/concurrent/ForkJoinPool.java	Thu Sep 23 17:33:40 2010 -0700
   121.2 +++ b/src/share/classes/java/util/concurrent/ForkJoinPool.java	Fri Sep 24 16:41:32 2010 -0700
   121.3 @@ -40,16 +40,23 @@
   121.4  import java.util.Collection;
   121.5  import java.util.Collections;
   121.6  import java.util.List;
   121.7 -import java.util.concurrent.locks.Condition;
   121.8 +import java.util.concurrent.AbstractExecutorService;
   121.9 +import java.util.concurrent.Callable;
  121.10 +import java.util.concurrent.CountDownLatch;
  121.11 +import java.util.concurrent.ExecutorService;
  121.12 +import java.util.concurrent.Future;
  121.13 +import java.util.concurrent.RejectedExecutionException;
  121.14 +import java.util.concurrent.RunnableFuture;
  121.15 +import java.util.concurrent.TimeUnit;
  121.16 +import java.util.concurrent.TimeoutException;
  121.17 +import java.util.concurrent.atomic.AtomicInteger;
  121.18  import java.util.concurrent.locks.LockSupport;
  121.19  import java.util.concurrent.locks.ReentrantLock;
  121.20 -import java.util.concurrent.atomic.AtomicInteger;
  121.21 -import java.util.concurrent.atomic.AtomicLong;
  121.22  
  121.23  /**
  121.24   * An {@link ExecutorService} for running {@link ForkJoinTask}s.
  121.25   * A {@code ForkJoinPool} provides the entry point for submissions
  121.26 - * from non-{@code ForkJoinTask}s, as well as management and
  121.27 + * from non-{@code ForkJoinTask} clients, as well as management and
  121.28   * monitoring operations.
  121.29   *
  121.30   * <p>A {@code ForkJoinPool} differs from other kinds of {@link
  121.31 @@ -58,29 +65,19 @@
  121.32   * execute subtasks created by other active tasks (eventually blocking
  121.33   * waiting for work if none exist). This enables efficient processing
  121.34   * when most tasks spawn other subtasks (as do most {@code
  121.35 - * ForkJoinTask}s). A {@code ForkJoinPool} may also be used for mixed
  121.36 - * execution of some plain {@code Runnable}- or {@code Callable}-
  121.37 - * based activities along with {@code ForkJoinTask}s. When setting
  121.38 - * {@linkplain #setAsyncMode async mode}, a {@code ForkJoinPool} may
  121.39 - * also be appropriate for use with fine-grained tasks of any form
  121.40 - * that are never joined. Otherwise, other {@code ExecutorService}
  121.41 - * implementations are typically more appropriate choices.
  121.42 + * ForkJoinTask}s). When setting <em>asyncMode</em> to true in
  121.43 + * constructors, {@code ForkJoinPool}s may also be appropriate for use
  121.44 + * with event-style tasks that are never joined.
  121.45   *
  121.46   * <p>A {@code ForkJoinPool} is constructed with a given target
  121.47   * parallelism level; by default, equal to the number of available
  121.48 - * processors. Unless configured otherwise via {@link
  121.49 - * #setMaintainsParallelism}, the pool attempts to maintain this
  121.50 - * number of active (or available) threads by dynamically adding,
  121.51 - * suspending, or resuming internal worker threads, even if some tasks
  121.52 - * are stalled waiting to join others. However, no such adjustments
  121.53 - * are performed in the face of blocked IO or other unmanaged
  121.54 - * synchronization. The nested {@link ManagedBlocker} interface
  121.55 - * enables extension of the kinds of synchronization accommodated.
  121.56 - * The target parallelism level may also be changed dynamically
  121.57 - * ({@link #setParallelism}). The total number of threads may be
  121.58 - * limited using method {@link #setMaximumPoolSize}, in which case it
  121.59 - * may become possible for the activities of a pool to stall due to
  121.60 - * the lack of available threads to process new tasks.
  121.61 + * processors. The pool attempts to maintain enough active (or
  121.62 + * available) threads by dynamically adding, suspending, or resuming
  121.63 + * internal worker threads, even if some tasks are stalled waiting to
  121.64 + * join others. However, no such adjustments are guaranteed in the
  121.65 + * face of blocked IO or other unmanaged synchronization. The nested
  121.66 + * {@link ManagedBlocker} interface enables extension of the kinds of
  121.67 + * synchronization accommodated.
  121.68   *
  121.69   * <p>In addition to execution and lifecycle control methods, this
  121.70   * class provides status check methods (for example
  121.71 @@ -89,6 +86,40 @@
  121.72   * {@link #toString} returns indications of pool state in a
  121.73   * convenient form for informal monitoring.
  121.74   *
  121.75 + * <p> As is the case with other ExecutorServices, there are three
  121.76 + * main task execution methods summarized in the following
  121.77 + * table. These are designed to be used by clients not already engaged
  121.78 + * in fork/join computations in the current pool.  The main forms of
  121.79 + * these methods accept instances of {@code ForkJoinTask}, but
  121.80 + * overloaded forms also allow mixed execution of plain {@code
  121.81 + * Runnable}- or {@code Callable}- based activities as well.  However,
  121.82 + * tasks that are already executing in a pool should normally
  121.83 + * <em>NOT</em> use these pool execution methods, but instead use the
  121.84 + * within-computation forms listed in the table.
  121.85 + *
  121.86 + * <table BORDER CELLPADDING=3 CELLSPACING=1>
  121.87 + *  <tr>
  121.88 + *    <td></td>
  121.89 + *    <td ALIGN=CENTER> <b>Call from non-fork/join clients</b></td>
  121.90 + *    <td ALIGN=CENTER> <b>Call from within fork/join computations</b></td>
  121.91 + *  </tr>
  121.92 + *  <tr>
  121.93 + *    <td> <b>Arrange async execution</td>
  121.94 + *    <td> {@link #execute(ForkJoinTask)}</td>
  121.95 + *    <td> {@link ForkJoinTask#fork}</td>
  121.96 + *  </tr>
  121.97 + *  <tr>
  121.98 + *    <td> <b>Await and obtain result</td>
  121.99 + *    <td> {@link #invoke(ForkJoinTask)}</td>
 121.100 + *    <td> {@link ForkJoinTask#invoke}</td>
 121.101 + *  </tr>
 121.102 + *  <tr>
 121.103 + *    <td> <b>Arrange exec and obtain Future</td>
 121.104 + *    <td> {@link #submit(ForkJoinTask)}</td>
 121.105 + *    <td> {@link ForkJoinTask#fork} (ForkJoinTasks <em>are</em> Futures)</td>
 121.106 + *  </tr>
 121.107 + * </table>
 121.108 + *
 121.109   * <p><b>Sample Usage.</b> Normally a single {@code ForkJoinPool} is
 121.110   * used for all parallel task execution in a program or subsystem.
 121.111   * Otherwise, use would not usually outweigh the construction and
 121.112 @@ -113,7 +144,8 @@
 121.113   * {@code IllegalArgumentException}.
 121.114   *
 121.115   * <p>This implementation rejects submitted tasks (that is, by throwing
 121.116 - * {@link RejectedExecutionException}) only when the pool is shut down.
 121.117 + * {@link RejectedExecutionException}) only when the pool is shut down
 121.118 + * or internal resources have been exhausted.
 121.119   *
 121.120   * @since 1.7
 121.121   * @author Doug Lea
 121.122 @@ -121,16 +153,247 @@
 121.123  public class ForkJoinPool extends AbstractExecutorService {
 121.124  
 121.125      /*
 121.126 -     * See the extended comments interspersed below for design,
 121.127 -     * rationale, and walkthroughs.
 121.128 +     * Implementation Overview
 121.129 +     *
 121.130 +     * This class provides the central bookkeeping and control for a
 121.131 +     * set of worker threads: Submissions from non-FJ threads enter
 121.132 +     * into a submission queue. Workers take these tasks and typically
 121.133 +     * split them into subtasks that may be stolen by other workers.
 121.134 +     * The main work-stealing mechanics implemented in class
 121.135 +     * ForkJoinWorkerThread give first priority to processing tasks
 121.136 +     * from their own queues (LIFO or FIFO, depending on mode), then
 121.137 +     * to randomized FIFO steals of tasks in other worker queues, and
 121.138 +     * lastly to new submissions. These mechanics do not consider
 121.139 +     * affinities, loads, cache localities, etc, so rarely provide the
 121.140 +     * best possible performance on a given machine, but portably
 121.141 +     * provide good throughput by averaging over these factors.
 121.142 +     * (Further, even if we did try to use such information, we do not
 121.143 +     * usually have a basis for exploiting it. For example, some sets
 121.144 +     * of tasks profit from cache affinities, but others are harmed by
 121.145 +     * cache pollution effects.)
 121.146 +     *
 121.147 +     * Beyond work-stealing support and essential bookkeeping, the
 121.148 +     * main responsibility of this framework is to take actions when
 121.149 +     * one worker is waiting to join a task stolen (or always held by)
 121.150 +     * another.  Because we are multiplexing many tasks on to a pool
 121.151 +     * of workers, we can't just let them block (as in Thread.join).
 121.152 +     * We also cannot just reassign the joiner's run-time stack with
 121.153 +     * another and replace it later, which would be a form of
 121.154 +     * "continuation", that even if possible is not necessarily a good
 121.155 +     * idea. Given that the creation costs of most threads on most
 121.156 +     * systems mainly surrounds setting up runtime stacks, thread
 121.157 +     * creation and switching is usually not much more expensive than
 121.158 +     * stack creation and switching, and is more flexible). Instead we
 121.159 +     * combine two tactics:
 121.160 +     *
 121.161 +     *   Helping: Arranging for the joiner to execute some task that it
 121.162 +     *      would be running if the steal had not occurred.  Method
 121.163 +     *      ForkJoinWorkerThread.helpJoinTask tracks joining->stealing
 121.164 +     *      links to try to find such a task.
 121.165 +     *
 121.166 +     *   Compensating: Unless there are already enough live threads,
 121.167 +     *      method helpMaintainParallelism() may create or
 121.168 +     *      re-activate a spare thread to compensate for blocked
 121.169 +     *      joiners until they unblock.
 121.170 +     *
 121.171 +     * It is impossible to keep exactly the target (parallelism)
 121.172 +     * number of threads running at any given time.  Determining
 121.173 +     * existence of conservatively safe helping targets, the
 121.174 +     * availability of already-created spares, and the apparent need
 121.175 +     * to create new spares are all racy and require heuristic
 121.176 +     * guidance, so we rely on multiple retries of each.  Compensation
 121.177 +     * occurs in slow-motion. It is triggered only upon timeouts of
 121.178 +     * Object.wait used for joins. This reduces poor decisions that
 121.179 +     * would otherwise be made when threads are waiting for others
 121.180 +     * that are stalled because of unrelated activities such as
 121.181 +     * garbage collection.
 121.182 +     *
 121.183 +     * The ManagedBlocker extension API can't use helping so relies
 121.184 +     * only on compensation in method awaitBlocker.
 121.185 +     *
 121.186 +     * The main throughput advantages of work-stealing stem from
 121.187 +     * decentralized control -- workers mostly steal tasks from each
 121.188 +     * other. We do not want to negate this by creating bottlenecks
 121.189 +     * implementing other management responsibilities. So we use a
 121.190 +     * collection of techniques that avoid, reduce, or cope well with
 121.191 +     * contention. These entail several instances of bit-packing into
 121.192 +     * CASable fields to maintain only the minimally required
 121.193 +     * atomicity. To enable such packing, we restrict maximum
 121.194 +     * parallelism to (1<<15)-1 (enabling twice this (to accommodate
 121.195 +     * unbalanced increments and decrements) to fit into a 16 bit
 121.196 +     * field, which is far in excess of normal operating range.  Even
 121.197 +     * though updates to some of these bookkeeping fields do sometimes
 121.198 +     * contend with each other, they don't normally cache-contend with
 121.199 +     * updates to others enough to warrant memory padding or
 121.200 +     * isolation. So they are all held as fields of ForkJoinPool
 121.201 +     * objects.  The main capabilities are as follows:
 121.202 +     *
 121.203 +     * 1. Creating and removing workers. Workers are recorded in the
 121.204 +     * "workers" array. This is an array as opposed to some other data
 121.205 +     * structure to support index-based random steals by workers.
 121.206 +     * Updates to the array recording new workers and unrecording
 121.207 +     * terminated ones are protected from each other by a lock
 121.208 +     * (workerLock) but the array is otherwise concurrently readable,
 121.209 +     * and accessed directly by workers. To simplify index-based
 121.210 +     * operations, the array size is always a power of two, and all
 121.211 +     * readers must tolerate null slots. Currently, all worker thread
 121.212 +     * creation is on-demand, triggered by task submissions,
 121.213 +     * replacement of terminated workers, and/or compensation for
 121.214 +     * blocked workers. However, all other support code is set up to
 121.215 +     * work with other policies.
 121.216 +     *
 121.217 +     * To ensure that we do not hold on to worker references that
 121.218 +     * would prevent GC, ALL accesses to workers are via indices into
 121.219 +     * the workers array (which is one source of some of the unusual
 121.220 +     * code constructions here). In essence, the workers array serves
 121.221 +     * as a WeakReference mechanism. Thus for example the event queue
 121.222 +     * stores worker indices, not worker references. Access to the
 121.223 +     * workers in associated methods (for example releaseEventWaiters)
 121.224 +     * must both index-check and null-check the IDs. All such accesses
 121.225 +     * ignore bad IDs by returning out early from what they are doing,
 121.226 +     * since this can only be associated with shutdown, in which case
 121.227 +     * it is OK to give up. On termination, we just clobber these
 121.228 +     * data structures without trying to use them.
 121.229 +     *
 121.230 +     * 2. Bookkeeping for dynamically adding and removing workers. We
 121.231 +     * aim to approximately maintain the given level of parallelism.
 121.232 +     * When some workers are known to be blocked (on joins or via
 121.233 +     * ManagedBlocker), we may create or resume others to take their
 121.234 +     * place until they unblock (see below). Implementing this
 121.235 +     * requires counts of the number of "running" threads (i.e., those
 121.236 +     * that are neither blocked nor artificially suspended) as well as
 121.237 +     * the total number.  These two values are packed into one field,
 121.238 +     * "workerCounts" because we need accurate snapshots when deciding
 121.239 +     * to create, resume or suspend.  Note however that the
 121.240 +     * correspondence of these counts to reality is not guaranteed. In
 121.241 +     * particular updates for unblocked threads may lag until they
 121.242 +     * actually wake up.
 121.243 +     *
 121.244 +     * 3. Maintaining global run state. The run state of the pool
 121.245 +     * consists of a runLevel (SHUTDOWN, TERMINATING, etc) similar to
 121.246 +     * those in other Executor implementations, as well as a count of
 121.247 +     * "active" workers -- those that are, or soon will be, or
 121.248 +     * recently were executing tasks. The runLevel and active count
 121.249 +     * are packed together in order to correctly trigger shutdown and
 121.250 +     * termination. Without care, active counts can be subject to very
 121.251 +     * high contention.  We substantially reduce this contention by
 121.252 +     * relaxing update rules.  A worker must claim active status
 121.253 +     * prospectively, by activating if it sees that a submitted or
 121.254 +     * stealable task exists (it may find after activating that the
 121.255 +     * task no longer exists). It stays active while processing this
 121.256 +     * task (if it exists) and any other local subtasks it produces,
 121.257 +     * until it cannot find any other tasks. It then tries
 121.258 +     * inactivating (see method preStep), but upon update contention
 121.259 +     * instead scans for more tasks, later retrying inactivation if it
 121.260 +     * doesn't find any.
 121.261 +     *
 121.262 +     * 4. Managing idle workers waiting for tasks. We cannot let
 121.263 +     * workers spin indefinitely scanning for tasks when none are
 121.264 +     * available. On the other hand, we must quickly prod them into
 121.265 +     * action when new tasks are submitted or generated.  We
 121.266 +     * park/unpark these idle workers using an event-count scheme.
 121.267 +     * Field eventCount is incremented upon events that may enable
 121.268 +     * workers that previously could not find a task to now find one:
 121.269 +     * Submission of a new task to the pool, or another worker pushing
 121.270 +     * a task onto a previously empty queue.  (We also use this
 121.271 +     * mechanism for configuration and termination actions that
 121.272 +     * require wakeups of idle workers).  Each worker maintains its
 121.273 +     * last known event count, and blocks when a scan for work did not
 121.274 +     * find a task AND its lastEventCount matches the current
 121.275 +     * eventCount. Waiting idle workers are recorded in a variant of
 121.276 +     * Treiber stack headed by field eventWaiters which, when nonzero,
 121.277 +     * encodes the thread index and count awaited for by the worker
 121.278 +     * thread most recently calling eventSync. This thread in turn has
 121.279 +     * a record (field nextEventWaiter) for the next waiting worker.
 121.280 +     * In addition to allowing simpler decisions about need for
 121.281 +     * wakeup, the event count bits in eventWaiters serve the role of
 121.282 +     * tags to avoid ABA errors in Treiber stacks. Upon any wakeup,
 121.283 +     * released threads also try to release at most two others.  The
 121.284 +     * net effect is a tree-like diffusion of signals, where released
 121.285 +     * threads (and possibly others) help with unparks.  To further
 121.286 +     * reduce contention effects a bit, failed CASes to increment
 121.287 +     * field eventCount are tolerated without retries in signalWork.
 121.288 +     * Conceptually they are merged into the same event, which is OK
 121.289 +     * when their only purpose is to enable workers to scan for work.
 121.290 +     *
 121.291 +     * 5. Managing suspension of extra workers. When a worker notices
 121.292 +     * (usually upon timeout of a wait()) that there are too few
 121.293 +     * running threads, we may create a new thread to maintain
 121.294 +     * parallelism level, or at least avoid starvation. Usually, extra
 121.295 +     * threads are needed for only very short periods, yet join
 121.296 +     * dependencies are such that we sometimes need them in
 121.297 +     * bursts. Rather than create new threads each time this happens,
 121.298 +     * we suspend no-longer-needed extra ones as "spares". For most
 121.299 +     * purposes, we don't distinguish "extra" spare threads from
 121.300 +     * normal "core" threads: On each call to preStep (the only point
 121.301 +     * at which we can do this) a worker checks to see if there are
 121.302 +     * now too many running workers, and if so, suspends itself.
 121.303 +     * Method helpMaintainParallelism looks for suspended threads to
 121.304 +     * resume before considering creating a new replacement. The
 121.305 +     * spares themselves are encoded on another variant of a Treiber
 121.306 +     * Stack, headed at field "spareWaiters".  Note that the use of
 121.307 +     * spares is intrinsically racy.  One thread may become a spare at
 121.308 +     * about the same time as another is needlessly being created. We
 121.309 +     * counteract this and related slop in part by requiring resumed
 121.310 +     * spares to immediately recheck (in preStep) to see whether they
 121.311 +     * should re-suspend.
 121.312 +     *
 121.313 +     * 6. Killing off unneeded workers. A timeout mechanism is used to
 121.314 +     * shed unused workers: The oldest (first) event queue waiter uses
 121.315 +     * a timed rather than hard wait. When this wait times out without
 121.316 +     * a normal wakeup, it tries to shutdown any one (for convenience
 121.317 +     * the newest) other spare or event waiter via
 121.318 +     * tryShutdownUnusedWorker. This eventually reduces the number of
 121.319 +     * worker threads to a minimum of one after a long enough period
 121.320 +     * without use.
 121.321 +     *
 121.322 +     * 7. Deciding when to create new workers. The main dynamic
 121.323 +     * control in this class is deciding when to create extra threads
 121.324 +     * in method helpMaintainParallelism. We would like to keep
 121.325 +     * exactly #parallelism threads running, which is an impossible
 121.326 +     * task. We always need to create one when the number of running
 121.327 +     * threads would become zero and all workers are busy. Beyond
 121.328 +     * this, we must rely on heuristics that work well in the
 121.329 +     * presence of transient phenomena such as GC stalls, dynamic
 121.330 +     * compilation, and wake-up lags. These transients are extremely
 121.331 +     * common -- we are normally trying to fully saturate the CPUs on
 121.332 +     * a machine, so almost any activity other than running tasks
 121.333 +     * impedes accuracy. Our main defense is to allow parallelism to
 121.334 +     * lapse for a while during joins, and use a timeout to see if,
 121.335 +     * after the resulting settling, there is still a need for
 121.336 +     * additional workers.  This also better copes with the fact that
 121.337 +     * some of the methods in this class tend to never become compiled
 121.338 +     * (but are interpreted), so some components of the entire set of
 121.339 +     * controls might execute 100 times faster than others. And
 121.340 +     * similarly for cases where the apparent lack of work is just due
 121.341 +     * to GC stalls and other transient system activity.
 121.342 +     *
 121.343 +     * Beware that there is a lot of representation-level coupling
 121.344 +     * among classes ForkJoinPool, ForkJoinWorkerThread, and
 121.345 +     * ForkJoinTask.  For example, direct access to "workers" array by
 121.346 +     * workers, and direct access to ForkJoinTask.status by both
 121.347 +     * ForkJoinPool and ForkJoinWorkerThread.  There is little point
 121.348 +     * trying to reduce this, since any associated future changes in
 121.349 +     * representations will need to be accompanied by algorithmic
 121.350 +     * changes anyway.
 121.351 +     *
 121.352 +     * Style notes: There are lots of inline assignments (of form
 121.353 +     * "while ((local = field) != 0)") which are usually the simplest
 121.354 +     * way to ensure the required read orderings (which are sometimes
 121.355 +     * critical). Also several occurrences of the unusual "do {}
 121.356 +     * while (!cas...)" which is the simplest way to force an update of
 121.357 +     * a CAS'ed variable. There are also other coding oddities that
 121.358 +     * help some methods perform reasonably even when interpreted (not
 121.359 +     * compiled), at the expense of some messy constructions that
 121.360 +     * reduce byte code counts.
 121.361 +     *
 121.362 +     * The order of declarations in this file is: (1) statics (2)
 121.363 +     * fields (along with constants used when unpacking some of them)
 121.364 +     * (3) internal control methods (4) callbacks and other support
 121.365 +     * for ForkJoinTask and ForkJoinWorkerThread classes, (5) exported
 121.366 +     * methods (plus a few little helpers).
 121.367       */
 121.368  
 121.369 -    /** Mask for packing and unpacking shorts */
 121.370 -    private static final int  shortMask = 0xffff;
 121.371 -
 121.372 -    /** Max pool size -- must be a power of two minus 1 */
 121.373 -    private static final int MAX_THREADS =  0x7FFF;
 121.374 -
 121.375      /**
 121.376       * Factory for creating new {@link ForkJoinWorkerThread}s.
 121.377       * A {@code ForkJoinWorkerThreadFactory} must be defined and used
 121.378 @@ -151,14 +414,10 @@
 121.379       * Default ForkJoinWorkerThreadFactory implementation; creates a
 121.380       * new ForkJoinWorkerThread.
 121.381       */
 121.382 -    static class  DefaultForkJoinWorkerThreadFactory
 121.383 +    static class DefaultForkJoinWorkerThreadFactory
 121.384          implements ForkJoinWorkerThreadFactory {
 121.385          public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
 121.386 -            try {
 121.387 -                return new ForkJoinWorkerThread(pool);
 121.388 -            } catch (OutOfMemoryError oom)  {
 121.389 -                return null;
 121.390 -            }
 121.391 +            return new ForkJoinWorkerThread(pool);
 121.392          }
 121.393      }
 121.394  
 121.395 @@ -194,29 +453,59 @@
 121.396          new AtomicInteger();
 121.397  
 121.398      /**
 121.399 -     * Array holding all worker threads in the pool. Initialized upon
 121.400 -     * first use. Array size must be a power of two.  Updates and
 121.401 -     * replacements are protected by workerLock, but it is always kept
 121.402 -     * in a consistent enough state to be randomly accessed without
 121.403 -     * locking by workers performing work-stealing.
 121.404 +     * The time to block in a join (see awaitJoin) before checking if
 121.405 +     * a new worker should be (re)started to maintain parallelism
 121.406 +     * level. The value should be short enough to maintain global
 121.407 +     * responsiveness and progress but long enough to avoid
 121.408 +     * counterproductive firings during GC stalls or unrelated system
 121.409 +     * activity, and to not bog down systems with continual re-firings
 121.410 +     * on GCs or legitimately long waits.
 121.411 +     */
 121.412 +    private static final long JOIN_TIMEOUT_MILLIS = 250L; // 4 per second
 121.413 +
 121.414 +    /**
 121.415 +     * The wakeup interval (in nanoseconds) for the oldest worker
 121.416 +     * waiting for an event to invoke tryShutdownUnusedWorker to
 121.417 +     * shrink the number of workers.  The exact value does not matter
 121.418 +     * too much. It must be short enough to release resources during
 121.419 +     * sustained periods of idleness, but not so short that threads
 121.420 +     * are continually re-created.
 121.421 +     */
 121.422 +    private static final long SHRINK_RATE_NANOS =
 121.423 +        30L * 1000L * 1000L * 1000L; // 2 per minute
 121.424 +
 121.425 +    /**
 121.426 +     * Absolute bound for parallelism level. Twice this number plus
 121.427 +     * one (i.e., 0xfff) must fit into a 16bit field to enable
 121.428 +     * word-packing for some counts and indices.
 121.429 +     */
 121.430 +    private static final int MAX_WORKERS   = 0x7fff;
 121.431 +
 121.432 +    /**
 121.433 +     * Array holding all worker threads in the pool.  Array size must
 121.434 +     * be a power of two.  Updates and replacements are protected by
 121.435 +     * workerLock, but the array is always kept in a consistent enough
 121.436 +     * state to be randomly accessed without locking by workers
 121.437 +     * performing work-stealing, as well as other traversal-based
 121.438 +     * methods in this class. All readers must tolerate that some
 121.439 +     * array slots may be null.
 121.440       */
 121.441      volatile ForkJoinWorkerThread[] workers;
 121.442  
 121.443      /**
 121.444 -     * Lock protecting access to workers.
 121.445 +     * Queue for external submissions.
 121.446 +     */
 121.447 +    private final LinkedTransferQueue<ForkJoinTask<?>> submissionQueue;
 121.448 +
 121.449 +    /**
 121.450 +     * Lock protecting updates to workers array.
 121.451       */
 121.452      private final ReentrantLock workerLock;
 121.453  
 121.454      /**
 121.455 -     * Condition for awaitTermination.
 121.456 +     * Latch released upon termination.
 121.457       */
 121.458 -    private final Condition termination;
 121.459 -
 121.460 -    /**
 121.461 -     * The uncaught exception handler used when any worker
 121.462 -     * abruptly terminates
 121.463 -     */
 121.464 -    private Thread.UncaughtExceptionHandler ueh;
 121.465 +    private final Phaser termination;
 121.466  
 121.467      /**
 121.468       * Creation factory for worker threads.
 121.469 @@ -224,178 +513,717 @@
 121.470      private final ForkJoinWorkerThreadFactory factory;
 121.471  
 121.472      /**
 121.473 -     * Head of stack of threads that were created to maintain
 121.474 -     * parallelism when other threads blocked, but have since
 121.475 -     * suspended when the parallelism level rose.
 121.476 -     */
 121.477 -    private volatile WaitQueueNode spareStack;
 121.478 -
 121.479 -    /**
 121.480       * Sum of per-thread steal counts, updated only when threads are
 121.481       * idle or terminating.
 121.482       */
 121.483 -    private final AtomicLong stealCount;
 121.484 +    private volatile long stealCount;
 121.485  
 121.486      /**
 121.487 -     * Queue for external submissions.
 121.488 +     * Encoded record of top of Treiber stack of threads waiting for
 121.489 +     * events. The top 32 bits contain the count being waited for. The
 121.490 +     * bottom 16 bits contains one plus the pool index of waiting
 121.491 +     * worker thread. (Bits 16-31 are unused.)
 121.492       */
 121.493 -    private final LinkedTransferQueue<ForkJoinTask<?>> submissionQueue;
 121.494 +    private volatile long eventWaiters;
 121.495 +
 121.496 +    private static final int  EVENT_COUNT_SHIFT = 32;
 121.497 +    private static final long WAITER_ID_MASK    = (1L << 16) - 1L;
 121.498  
 121.499      /**
 121.500 -     * Head of Treiber stack for barrier sync. See below for explanation.
 121.501 +     * A counter for events that may wake up worker threads:
 121.502 +     *   - Submission of a new task to the pool
 121.503 +     *   - A worker pushing a task on an empty queue
 121.504 +     *   - termination
 121.505       */
 121.506 -    private volatile WaitQueueNode syncStack;
 121.507 +    private volatile int eventCount;
 121.508  
 121.509      /**
 121.510 -     * The count for event barrier
 121.511 +     * Encoded record of top of Treiber stack of spare threads waiting
 121.512 +     * for resumption. The top 16 bits contain an arbitrary count to
 121.513 +     * avoid ABA effects. The bottom 16bits contains one plus the pool
 121.514 +     * index of waiting worker thread.
 121.515       */
 121.516 -    private volatile long eventCount;
 121.517 +    private volatile int spareWaiters;
 121.518 +
 121.519 +    private static final int SPARE_COUNT_SHIFT = 16;
 121.520 +    private static final int SPARE_ID_MASK     = (1 << 16) - 1;
 121.521 +
 121.522 +    /**
 121.523 +     * Lifecycle control. The low word contains the number of workers
 121.524 +     * that are (probably) executing tasks. This value is atomically
 121.525 +     * incremented before a worker gets a task to run, and decremented
 121.526 +     * when a worker has no tasks and cannot find any.  Bits 16-18
 121.527 +     * contain runLevel value. When all are zero, the pool is
 121.528 +     * running. Level transitions are monotonic (running -> shutdown
 121.529 +     * -> terminating -> terminated) so each transition adds a bit.
 121.530 +     * These are bundled together to ensure consistent read for
 121.531 +     * termination checks (i.e., that runLevel is at least SHUTDOWN
 121.532 +     * and active threads is zero).
 121.533 +     *
 121.534 +     * Notes: Most direct CASes are dependent on these bitfield
 121.535 +     * positions.  Also, this field is non-private to enable direct
 121.536 +     * performance-sensitive CASes in ForkJoinWorkerThread.
 121.537 +     */
 121.538 +    volatile int runState;
 121.539 +
 121.540 +    // Note: The order among run level values matters.
 121.541 +    private static final int RUNLEVEL_SHIFT     = 16;
 121.542 +    private static final int SHUTDOWN           = 1 << RUNLEVEL_SHIFT;
 121.543 +    private static final int TERMINATING        = 1 << (RUNLEVEL_SHIFT + 1);
 121.544 +    private static final int TERMINATED         = 1 << (RUNLEVEL_SHIFT + 2);
 121.545 +    private static final int ACTIVE_COUNT_MASK  = (1 << RUNLEVEL_SHIFT) - 1;
 121.546 +
 121.547 +    /**
 121.548 +     * Holds number of total (i.e., created and not yet terminated)
 121.549 +     * and running (i.e., not blocked on joins or other managed sync)
 121.550 +     * threads, packed together to ensure consistent snapshot when
 121.551 +     * making decisions about creating and suspending spare
 121.552 +     * threads. Updated only by CAS. Note that adding a new worker
 121.553 +     * requires incrementing both counts, since workers start off in
 121.554 +     * running state.
 121.555 +     */
 121.556 +    private volatile int workerCounts;
 121.557 +
 121.558 +    private static final int TOTAL_COUNT_SHIFT  = 16;
 121.559 +    private static final int RUNNING_COUNT_MASK = (1 << TOTAL_COUNT_SHIFT) - 1;
 121.560 +    private static final int ONE_RUNNING        = 1;
 121.561 +    private static final int ONE_TOTAL          = 1 << TOTAL_COUNT_SHIFT;
 121.562 +
 121.563 +    /**
 121.564 +     * The target parallelism level.
 121.565 +     * Accessed directly by ForkJoinWorkerThreads.
 121.566 +     */
 121.567 +    final int parallelism;
 121.568 +
 121.569 +    /**
 121.570 +     * True if use local fifo, not default lifo, for local polling
 121.571 +     * Read by, and replicated by ForkJoinWorkerThreads
 121.572 +     */
 121.573 +    final boolean locallyFifo;
 121.574 +
 121.575 +    /**
 121.576 +     * The uncaught exception handler used when any worker abruptly
 121.577 +     * terminates.
 121.578 +     */
 121.579 +    private final Thread.UncaughtExceptionHandler ueh;
 121.580  
 121.581      /**
 121.582       * Pool number, just for assigning useful names to worker threads
 121.583       */
 121.584      private final int poolNumber;
 121.585  
 121.586 -    /**
 121.587 -     * The maximum allowed pool size
 121.588 -     */
 121.589 -    private volatile int maxPoolSize;
 121.590 +    // Utilities for CASing fields. Note that most of these
 121.591 +    // are usually manually inlined by callers
 121.592  
 121.593      /**
 121.594 -     * The desired parallelism level, updated only under workerLock.
 121.595 +     * Increments running count part of workerCounts
 121.596       */
 121.597 -    private volatile int parallelism;
 121.598 -
 121.599 -    /**
 121.600 -     * True if use local fifo, not default lifo, for local polling
 121.601 -     */
 121.602 -    private volatile boolean locallyFifo;
 121.603 -
 121.604 -    /**
 121.605 -     * Holds number of total (i.e., created and not yet terminated)
 121.606 -     * and running (i.e., not blocked on joins or other managed sync)
 121.607 -     * threads, packed into one int to ensure consistent snapshot when
 121.608 -     * making decisions about creating and suspending spare
 121.609 -     * threads. Updated only by CAS.  Note: CASes in
 121.610 -     * updateRunningCount and preJoin assume that running active count
 121.611 -     * is in low word, so need to be modified if this changes.
 121.612 -     */
 121.613 -    private volatile int workerCounts;
 121.614 -
 121.615 -    private static int totalCountOf(int s)           { return s >>> 16;  }
 121.616 -    private static int runningCountOf(int s)         { return s & shortMask; }
 121.617 -    private static int workerCountsFor(int t, int r) { return (t << 16) + r; }
 121.618 -
 121.619 -    /**
 121.620 -     * Adds delta (which may be negative) to running count.  This must
 121.621 -     * be called before (with negative arg) and after (with positive)
 121.622 -     * any managed synchronization (i.e., mainly, joins).
 121.623 -     *
 121.624 -     * @param delta the number to add
 121.625 -     */
 121.626 -    final void updateRunningCount(int delta) {
 121.627 -        int s;
 121.628 -        do {} while (!casWorkerCounts(s = workerCounts, s + delta));
 121.629 +    final void incrementRunningCount() {
 121.630 +        int c;
 121.631 +        do {} while (!UNSAFE.compareAndSwapInt(this, workerCountsOffset,
 121.632 +                                               c = workerCounts,
 121.633 +                                               c + ONE_RUNNING));
 121.634      }
 121.635  
 121.636      /**
 121.637 -     * Adds delta (which may be negative) to both total and running
 121.638 -     * count.  This must be called upon creation and termination of
 121.639 -     * worker threads.
 121.640 -     *
 121.641 -     * @param delta the number to add
 121.642 +     * Tries to decrement running count unless already zero
 121.643       */
 121.644 -    private void updateWorkerCount(int delta) {
 121.645 -        int d = delta + (delta << 16); // add to both lo and hi parts
 121.646 -        int s;
 121.647 -        do {} while (!casWorkerCounts(s = workerCounts, s + d));
 121.648 +    final boolean tryDecrementRunningCount() {
 121.649 +        int wc = workerCounts;
 121.650 +        if ((wc & RUNNING_COUNT_MASK) == 0)
 121.651 +            return false;
 121.652 +        return UNSAFE.compareAndSwapInt(this, workerCountsOffset,
 121.653 +                                        wc, wc - ONE_RUNNING);
 121.654      }
 121.655  
 121.656      /**
 121.657 -     * Lifecycle control. High word contains runState, low word
 121.658 -     * contains the number of workers that are (probably) executing
 121.659 -     * tasks. This value is atomically incremented before a worker
 121.660 -     * gets a task to run, and decremented when worker has no tasks
 121.661 -     * and cannot find any. These two fields are bundled together to
 121.662 -     * support correct termination triggering.  Note: activeCount
 121.663 -     * CAS'es cheat by assuming active count is in low word, so need
 121.664 -     * to be modified if this changes
 121.665 +     * Forces decrement of encoded workerCounts, awaiting nonzero if
 121.666 +     * (rarely) necessary when other count updates lag.
 121.667 +     *
 121.668 +     * @param dr -- either zero or ONE_RUNNING
 121.669 +     * @param dt -- either zero or ONE_TOTAL
 121.670       */
 121.671 -    private volatile int runControl;
 121.672 -
 121.673 -    // RunState values. Order among values matters
 121.674 -    private static final int RUNNING     = 0;
 121.675 -    private static final int SHUTDOWN    = 1;
 121.676 -    private static final int TERMINATING = 2;
 121.677 -    private static final int TERMINATED  = 3;
 121.678 -
 121.679 -    private static int runStateOf(int c)             { return c >>> 16; }
 121.680 -    private static int activeCountOf(int c)          { return c & shortMask; }
 121.681 -    private static int runControlFor(int r, int a)   { return (r << 16) + a; }
 121.682 -
 121.683 -    /**
 121.684 -     * Tries incrementing active count; fails on contention.
 121.685 -     * Called by workers before/during executing tasks.
 121.686 -     *
 121.687 -     * @return true on success
 121.688 -     */
 121.689 -    final boolean tryIncrementActiveCount() {
 121.690 -        int c = runControl;
 121.691 -        return casRunControl(c, c+1);
 121.692 +    private void decrementWorkerCounts(int dr, int dt) {
 121.693 +        for (;;) {
 121.694 +            int wc = workerCounts;
 121.695 +            if ((wc & RUNNING_COUNT_MASK)  - dr < 0 ||
 121.696 +                (wc >>> TOTAL_COUNT_SHIFT) - dt < 0) {
 121.697 +                if ((runState & TERMINATED) != 0)
 121.698 +                    return; // lagging termination on a backout
 121.699 +                Thread.yield();
 121.700 +            }
 121.701 +            if (UNSAFE.compareAndSwapInt(this, workerCountsOffset,
 121.702 +                                         wc, wc - (dr + dt)))
 121.703 +                return;
 121.704 +        }
 121.705      }
 121.706  
 121.707      /**
 121.708       * Tries decrementing active count; fails on contention.
 121.709 -     * Possibly triggers termination on success.
 121.710 -     * Called by workers when they can't find tasks.
 121.711 -     *
 121.712 -     * @return true on success
 121.713 +     * Called when workers cannot find tasks to run.
 121.714       */
 121.715      final boolean tryDecrementActiveCount() {
 121.716 -        int c = runControl;
 121.717 -        int nextc = c - 1;
 121.718 -        if (!casRunControl(c, nextc))
 121.719 +        int c;
 121.720 +        return UNSAFE.compareAndSwapInt(this, runStateOffset,
 121.721 +                                        c = runState, c - 1);
 121.722 +    }
 121.723 +
 121.724 +    /**
 121.725 +     * Advances to at least the given level. Returns true if not
 121.726 +     * already in at least the given level.
 121.727 +     */
 121.728 +    private boolean advanceRunLevel(int level) {
 121.729 +        for (;;) {
 121.730 +            int s = runState;
 121.731 +            if ((s & level) != 0)
 121.732 +                return false;
 121.733 +            if (UNSAFE.compareAndSwapInt(this, runStateOffset, s, s | level))
 121.734 +                return true;
 121.735 +        }
 121.736 +    }
 121.737 +
 121.738 +    // workers array maintenance
 121.739 +
 121.740 +    /**
 121.741 +     * Records and returns a workers array index for new worker.
 121.742 +     */
 121.743 +    private int recordWorker(ForkJoinWorkerThread w) {
 121.744 +        // Try using slot totalCount-1. If not available, scan and/or resize
 121.745 +        int k = (workerCounts >>> TOTAL_COUNT_SHIFT) - 1;
 121.746 +        final ReentrantLock lock = this.workerLock;
 121.747 +        lock.lock();
 121.748 +        try {
 121.749 +            ForkJoinWorkerThread[] ws = workers;
 121.750 +            int n = ws.length;
 121.751 +            if (k < 0 || k >= n || ws[k] != null) {
 121.752 +                for (k = 0; k < n && ws[k] != null; ++k)
 121.753 +                    ;
 121.754 +                if (k == n)
 121.755 +                    ws = Arrays.copyOf(ws, n << 1);
 121.756 +            }
 121.757 +            ws[k] = w;
 121.758 +            workers = ws; // volatile array write ensures slot visibility
 121.759 +        } finally {
 121.760 +            lock.unlock();
 121.761 +        }
 121.762 +        return k;
 121.763 +    }
 121.764 +
 121.765 +    /**
 121.766 +     * Nulls out record of worker in workers array.
 121.767 +     */
 121.768 +    private void forgetWorker(ForkJoinWorkerThread w) {
 121.769 +        int idx = w.poolIndex;
 121.770 +        // Locking helps method recordWorker avoid unnecessary expansion
 121.771 +        final ReentrantLock lock = this.workerLock;
 121.772 +        lock.lock();
 121.773 +        try {
 121.774 +            ForkJoinWorkerThread[] ws = workers;
 121.775 +            if (idx >= 0 && idx < ws.length && ws[idx] == w) // verify
 121.776 +                ws[idx] = null;
 121.777 +        } finally {
 121.778 +            lock.unlock();
 121.779 +        }
 121.780 +    }
 121.781 +
 121.782 +    /**
 121.783 +     * Final callback from terminating worker.  Removes record of
 121.784 +     * worker from array, and adjusts counts. If pool is shutting
 121.785 +     * down, tries to complete termination.
 121.786 +     *
 121.787 +     * @param w the worker
 121.788 +     */
 121.789 +    final void workerTerminated(ForkJoinWorkerThread w) {
 121.790 +        forgetWorker(w);
 121.791 +        decrementWorkerCounts(w.isTrimmed()? 0 : ONE_RUNNING, ONE_TOTAL);
 121.792 +        while (w.stealCount != 0) // collect final count
 121.793 +            tryAccumulateStealCount(w);
 121.794 +        tryTerminate(false);
 121.795 +    }
 121.796 +
 121.797 +    // Waiting for and signalling events
 121.798 +
 121.799 +    /**
 121.800 +     * Releases workers blocked on a count not equal to current count.
 121.801 +     * Normally called after precheck that eventWaiters isn't zero to
 121.802 +     * avoid wasted array checks. Gives up upon a change in count or
 121.803 +     * upon releasing two workers, letting others take over.
 121.804 +     */
 121.805 +    private void releaseEventWaiters() {
 121.806 +        ForkJoinWorkerThread[] ws = workers;
 121.807 +        int n = ws.length;
 121.808 +        long h = eventWaiters;
 121.809 +        int ec = eventCount;
 121.810 +        boolean releasedOne = false;
 121.811 +        ForkJoinWorkerThread w; int id;
 121.812 +        while ((id = ((int)(h & WAITER_ID_MASK)) - 1) >= 0 &&
 121.813 +               (int)(h >>> EVENT_COUNT_SHIFT) != ec &&
 121.814 +               id < n && (w = ws[id]) != null) {
 121.815 +            if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset,
 121.816 +                                          h,  w.nextWaiter)) {
 121.817 +                LockSupport.unpark(w);
 121.818 +                if (releasedOne) // exit on second release
 121.819 +                    break;
 121.820 +                releasedOne = true;
 121.821 +            }
 121.822 +            if (eventCount != ec)
 121.823 +                break;
 121.824 +            h = eventWaiters;
 121.825 +        }
 121.826 +    }
 121.827 +
 121.828 +    /**
 121.829 +     * Tries to advance eventCount and releases waiters. Called only
 121.830 +     * from workers.
 121.831 +     */
 121.832 +    final void signalWork() {
 121.833 +        int c; // try to increment event count -- CAS failure OK
 121.834 +        UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1);
 121.835 +        if (eventWaiters != 0L)
 121.836 +            releaseEventWaiters();
 121.837 +    }
 121.838 +
 121.839 +    /**
 121.840 +     * Adds the given worker to event queue and blocks until
 121.841 +     * terminating or event count advances from the given value
 121.842 +     *
 121.843 +     * @param w the calling worker thread
 121.844 +     * @param ec the count
 121.845 +     */
 121.846 +    private void eventSync(ForkJoinWorkerThread w, int ec) {
 121.847 +        long nh = (((long)ec) << EVENT_COUNT_SHIFT) | ((long)(w.poolIndex+1));
 121.848 +        long h;
 121.849 +        while ((runState < SHUTDOWN || !tryTerminate(false)) &&
 121.850 +               (((int)((h = eventWaiters) & WAITER_ID_MASK)) == 0 ||
 121.851 +                (int)(h >>> EVENT_COUNT_SHIFT) == ec) &&
 121.852 +               eventCount == ec) {
 121.853 +            if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset,
 121.854 +                                          w.nextWaiter = h, nh)) {
 121.855 +                awaitEvent(w, ec);
 121.856 +                break;
 121.857 +            }
 121.858 +        }
 121.859 +    }
 121.860 +
 121.861 +    /**
 121.862 +     * Blocks the given worker (that has already been entered as an
 121.863 +     * event waiter) until terminating or event count advances from
 121.864 +     * the given value. The oldest (first) waiter uses a timed wait to
 121.865 +     * occasionally one-by-one shrink the number of workers (to a
 121.866 +     * minimum of one) if the pool has not been used for extended
 121.867 +     * periods.
 121.868 +     *
 121.869 +     * @param w the calling worker thread
 121.870 +     * @param ec the count
 121.871 +     */
 121.872 +    private void awaitEvent(ForkJoinWorkerThread w, int ec) {
 121.873 +        while (eventCount == ec) {
 121.874 +            if (tryAccumulateStealCount(w)) { // transfer while idle
 121.875 +                boolean untimed = (w.nextWaiter != 0L ||
 121.876 +                                   (workerCounts & RUNNING_COUNT_MASK) <= 1);
 121.877 +                long startTime = untimed? 0 : System.nanoTime();
 121.878 +                Thread.interrupted();         // clear/ignore interrupt
 121.879 +                if (eventCount != ec || w.runState != 0 ||
 121.880 +                    runState >= TERMINATING)  // recheck after clear
 121.881 +                    break;
 121.882 +                if (untimed)
 121.883 +                    LockSupport.park(w);
 121.884 +                else {
 121.885 +                    LockSupport.parkNanos(w, SHRINK_RATE_NANOS);
 121.886 +                    if (eventCount != ec || w.runState != 0 ||
 121.887 +                        runState >= TERMINATING)
 121.888 +                        break;
 121.889 +                    if (System.nanoTime() - startTime >= SHRINK_RATE_NANOS)
 121.890 +                        tryShutdownUnusedWorker(ec);
 121.891 +                }
 121.892 +            }
 121.893 +        }
 121.894 +    }
 121.895 +
 121.896 +    // Maintaining parallelism
 121.897 +
 121.898 +    /**
 121.899 +     * Pushes worker onto the spare stack.
 121.900 +     */
 121.901 +    final void pushSpare(ForkJoinWorkerThread w) {
 121.902 +        int ns = (++w.spareCount << SPARE_COUNT_SHIFT) | (w.poolIndex + 1);
 121.903 +        do {} while (!UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
 121.904 +                                               w.nextSpare = spareWaiters,ns));
 121.905 +    }
 121.906 +
 121.907 +    /**
 121.908 +     * Tries (once) to resume a spare if the number of running
 121.909 +     * threads is less than target.
 121.910 +     */
 121.911 +    private void tryResumeSpare() {
 121.912 +        int sw, id;
 121.913 +        ForkJoinWorkerThread[] ws = workers;
 121.914 +        int n = ws.length;
 121.915 +        ForkJoinWorkerThread w;
 121.916 +        if ((sw = spareWaiters) != 0 &&
 121.917 +            (id = (sw & SPARE_ID_MASK) - 1) >= 0 &&
 121.918 +            id < n && (w = ws[id]) != null &&
 121.919 +            (workerCounts & RUNNING_COUNT_MASK) < parallelism &&
 121.920 +            spareWaiters == sw &&
 121.921 +            UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
 121.922 +                                     sw, w.nextSpare)) {
 121.923 +            int c; // increment running count before resume
 121.924 +            do {} while (!UNSAFE.compareAndSwapInt
 121.925 +                         (this, workerCountsOffset,
 121.926 +                          c = workerCounts, c + ONE_RUNNING));
 121.927 +            if (w.tryUnsuspend())
 121.928 +                LockSupport.unpark(w);
 121.929 +            else   // back out if w was shutdown
 121.930 +                decrementWorkerCounts(ONE_RUNNING, 0);
 121.931 +        }
 121.932 +    }
 121.933 +
 121.934 +    /**
 121.935 +     * Tries to increase the number of running workers if below target
 121.936 +     * parallelism: If a spare exists tries to resume it via
 121.937 +     * tryResumeSpare.  Otherwise, if not enough total workers or all
 121.938 +     * existing workers are busy, adds a new worker. In all cases also
 121.939 +     * helps wake up releasable workers waiting for work.
 121.940 +     */
 121.941 +    private void helpMaintainParallelism() {
 121.942 +        int pc = parallelism;
 121.943 +        int wc, rs, tc;
 121.944 +        while (((wc = workerCounts) & RUNNING_COUNT_MASK) < pc &&
 121.945 +               (rs = runState) < TERMINATING) {
 121.946 +            if (spareWaiters != 0)
 121.947 +                tryResumeSpare();
 121.948 +            else if ((tc = wc >>> TOTAL_COUNT_SHIFT) >= MAX_WORKERS ||
 121.949 +                     (tc >= pc && (rs & ACTIVE_COUNT_MASK) != tc))
 121.950 +                break;   // enough total
 121.951 +            else if (runState == rs && workerCounts == wc &&
 121.952 +                     UNSAFE.compareAndSwapInt(this, workerCountsOffset, wc,
 121.953 +                                              wc + (ONE_RUNNING|ONE_TOTAL))) {
 121.954 +                ForkJoinWorkerThread w = null;
 121.955 +                try {
 121.956 +                    w = factory.newThread(this);
 121.957 +                } finally { // adjust on null or exceptional factory return
 121.958 +                    if (w == null) {
 121.959 +                        decrementWorkerCounts(ONE_RUNNING, ONE_TOTAL);
 121.960 +                        tryTerminate(false); // handle failure during shutdown
 121.961 +                    }
 121.962 +                }
 121.963 +                if (w == null)
 121.964 +                    break;
 121.965 +                w.start(recordWorker(w), ueh);
 121.966 +                if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc) {
 121.967 +                    int c; // advance event count
 121.968 +                    UNSAFE.compareAndSwapInt(this, eventCountOffset,
 121.969 +                                             c = eventCount, c+1);
 121.970 +                    break; // add at most one unless total below target
 121.971 +                }
 121.972 +            }
 121.973 +        }
 121.974 +        if (eventWaiters != 0L)
 121.975 +            releaseEventWaiters();
 121.976 +    }
 121.977 +
 121.978 +    /**
 121.979 +     * Callback from the oldest waiter in awaitEvent waking up after a
 121.980 +     * period of non-use. If all workers are idle, tries (once) to
 121.981 +     * shutdown an event waiter or a spare, if one exists. Note that
 121.982 +     * we don't need CAS or locks here because the method is called
 121.983 +     * only from one thread occasionally waking (and even misfires are
 121.984 +     * OK). Note that until the shutdown worker fully terminates,
 121.985 +     * workerCounts will overestimate total count, which is tolerable.
 121.986 +     *
 121.987 +     * @param ec the event count waited on by caller (to abort
 121.988 +     * attempt if count has since changed).
 121.989 +     */
 121.990 +    private void tryShutdownUnusedWorker(int ec) {
 121.991 +        if (runState == 0 && eventCount == ec) { // only trigger if all idle
 121.992 +            ForkJoinWorkerThread[] ws = workers;
 121.993 +            int n = ws.length;
 121.994 +            ForkJoinWorkerThread w = null;
 121.995 +            boolean shutdown = false;
 121.996 +            int sw;
 121.997 +            long h;
 121.998 +            if ((sw = spareWaiters) != 0) { // prefer killing spares
 121.999 +                int id = (sw & SPARE_ID_MASK) - 1;
121.1000 +                if (id >= 0 && id < n && (w = ws[id]) != null &&
121.1001 +                    UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
121.1002 +                                             sw, w.nextSpare))
121.1003 +                    shutdown = true;
121.1004 +            }
121.1005 +            else if ((h = eventWaiters) != 0L) {
121.1006 +                long nh;
121.1007 +                int id = ((int)(h & WAITER_ID_MASK)) - 1;
121.1008 +                if (id >= 0 && id < n && (w = ws[id]) != null &&
121.1009 +                    (nh = w.nextWaiter) != 0L && // keep at least one worker
121.1010 +                    UNSAFE.compareAndSwapLong(this, eventWaitersOffset, h, nh))
121.1011 +                    shutdown = true;
121.1012 +            }
121.1013 +            if (w != null && shutdown) {
121.1014 +                w.shutdown();
121.1015 +                LockSupport.unpark(w);
121.1016 +            }
121.1017 +        }
121.1018 +        releaseEventWaiters(); // in case of interference
121.1019 +    }
121.1020 +
121.1021 +    /**
121.1022 +     * Callback from workers invoked upon each top-level action (i.e.,
121.1023 +     * stealing a task or taking a submission and running it).
121.1024 +     * Performs one or more of the following:
121.1025 +     *
121.1026 +     * 1. If the worker is active and either did not run a task
121.1027 +     *    or there are too many workers, try to set its active status
121.1028 +     *    to inactive and update activeCount. On contention, we may
121.1029 +     *    try again in this or a subsequent call.
121.1030 +     *
121.1031 +     * 2. If not enough total workers, help create some.
121.1032 +     *
121.1033 +     * 3. If there are too many running workers, suspend this worker
121.1034 +     *    (first forcing inactive if necessary).  If it is not needed,
121.1035 +     *    it may be shutdown while suspended (via
121.1036 +     *    tryShutdownUnusedWorker).  Otherwise, upon resume it
121.1037 +     *    rechecks running thread count and need for event sync.
121.1038 +     *
121.1039 +     * 4. If worker did not run a task, await the next task event via
121.1040 +     *    eventSync if necessary (first forcing inactivation), upon
121.1041 +     *    which the worker may be shutdown via
121.1042 +     *    tryShutdownUnusedWorker.  Otherwise, help release any
121.1043 +     *    existing event waiters that are now releasable,
121.1044 +     *
121.1045 +     * @param w the worker
121.1046 +     * @param ran true if worker ran a task since last call to this method
121.1047 +     */
121.1048 +    final void preStep(ForkJoinWorkerThread w, boolean ran) {
121.1049 +        int wec = w.lastEventCount;
121.1050 +        boolean active = w.active;
121.1051 +        boolean inactivate = false;
121.1052 +        int pc = parallelism;
121.1053 +        int rs;
121.1054 +        while (w.runState == 0 && (rs = runState) < TERMINATING) {
121.1055 +            if ((inactivate || (active && (rs & ACTIVE_COUNT_MASK) >= pc)) &&
121.1056 +                UNSAFE.compareAndSwapInt(this, runStateOffset, rs, rs - 1))
121.1057 +                inactivate = active = w.active = false;
121.1058 +            int wc = workerCounts;
121.1059 +            if ((wc & RUNNING_COUNT_MASK) > pc) {
121.1060 +                if (!(inactivate |= active) && // must inactivate to suspend
121.1061 +                    workerCounts == wc &&      // try to suspend as spare
121.1062 +                    UNSAFE.compareAndSwapInt(this, workerCountsOffset,
121.1063 +                                             wc, wc - ONE_RUNNING))
121.1064 +                    w.suspendAsSpare();
121.1065 +            }
121.1066 +            else if ((wc >>> TOTAL_COUNT_SHIFT) < pc)
121.1067 +                helpMaintainParallelism();     // not enough workers
121.1068 +            else if (!ran) {
121.1069 +                long h = eventWaiters;
121.1070 +                int ec = eventCount;
121.1071 +                if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != ec)
121.1072 +                    releaseEventWaiters();     // release others before waiting
121.1073 +                else if (ec != wec) {
121.1074 +                    w.lastEventCount = ec;     // no need to wait
121.1075 +                    break;
121.1076 +                }
121.1077 +                else if (!(inactivate |= active))
121.1078 +                    eventSync(w, wec);         // must inactivate before sync
121.1079 +            }
121.1080 +            else
121.1081 +                break;
121.1082 +        }
121.1083 +    }
121.1084 +
121.1085 +    /**
121.1086 +     * Helps and/or blocks awaiting join of the given task.
121.1087 +     * See above for explanation.
121.1088 +     *
121.1089 +     * @param joinMe the task to join
121.1090 +     * @param worker the current worker thread
121.1091 +     */
121.1092 +    final void awaitJoin(ForkJoinTask<?> joinMe, ForkJoinWorkerThread worker) {
121.1093 +        int retries = 2 + (parallelism >> 2); // #helpJoins before blocking
121.1094 +        while (joinMe.status >= 0) {
121.1095 +            int wc;
121.1096 +            worker.helpJoinTask(joinMe);
121.1097 +            if (joinMe.status < 0)
121.1098 +                break;
121.1099 +            else if (retries > 0)
121.1100 +                --retries;
121.1101 +            else if (((wc = workerCounts) & RUNNING_COUNT_MASK) != 0 &&
121.1102 +                     UNSAFE.compareAndSwapInt(this, workerCountsOffset,
121.1103 +                                              wc, wc - ONE_RUNNING)) {
121.1104 +                int stat, c; long h;
121.1105 +                while ((stat = joinMe.status) >= 0 &&
121.1106 +                       (h = eventWaiters) != 0L && // help release others
121.1107 +                       (int)(h >>> EVENT_COUNT_SHIFT) != eventCount)
121.1108 +                    releaseEventWaiters();
121.1109 +                if (stat >= 0 &&
121.1110 +                    ((workerCounts & RUNNING_COUNT_MASK) == 0 ||
121.1111 +                     (stat =
121.1112 +                      joinMe.internalAwaitDone(JOIN_TIMEOUT_MILLIS)) >= 0))
121.1113 +                    helpMaintainParallelism(); // timeout or no running workers
121.1114 +                do {} while (!UNSAFE.compareAndSwapInt
121.1115 +                             (this, workerCountsOffset,
121.1116 +                              c = workerCounts, c + ONE_RUNNING));
121.1117 +                if (stat < 0)
121.1118 +                    break;   // else restart
121.1119 +            }
121.1120 +        }
121.1121 +    }
121.1122 +
121.1123 +    /**
121.1124 +     * Same idea as awaitJoin, but no helping, retries, or timeouts.
121.1125 +     */
121.1126 +    final void awaitBlocker(ManagedBlocker blocker)
121.1127 +        throws InterruptedException {
121.1128 +        while (!blocker.isReleasable()) {
121.1129 +            int wc = workerCounts;
121.1130 +            if ((wc & RUNNING_COUNT_MASK) != 0 &&
121.1131 +                UNSAFE.compareAndSwapInt(this, workerCountsOffset,
121.1132 +                                         wc, wc - ONE_RUNNING)) {
121.1133 +                try {
121.1134 +                    while (!blocker.isReleasable()) {
121.1135 +                        long h = eventWaiters;
121.1136 +                        if (h != 0L &&
121.1137 +                            (int)(h >>> EVENT_COUNT_SHIFT) != eventCount)
121.1138 +                            releaseEventWaiters();
121.1139 +                        else if ((workerCounts & RUNNING_COUNT_MASK) == 0 &&
121.1140 +                                 runState < TERMINATING)
121.1141 +                            helpMaintainParallelism();
121.1142 +                        else if (blocker.block())
121.1143 +                            break;
121.1144 +                    }
121.1145 +                } finally {
121.1146 +                    int c;
121.1147 +                    do {} while (!UNSAFE.compareAndSwapInt
121.1148 +                                 (this, workerCountsOffset,
121.1149 +                                  c = workerCounts, c + ONE_RUNNING));
121.1150 +                }
121.1151 +                break;
121.1152 +            }
121.1153 +        }
121.1154 +    }
121.1155 +
121.1156 +    /**
121.1157 +     * Possibly initiates and/or completes termination.
121.1158 +     *
121.1159 +     * @param now if true, unconditionally terminate, else only
121.1160 +     * if shutdown and empty queue and no active workers
121.1161 +     * @return true if now terminating or terminated
121.1162 +     */
121.1163 +    private boolean tryTerminate(boolean now) {
121.1164 +        if (now)
121.1165 +            advanceRunLevel(SHUTDOWN); // ensure at least SHUTDOWN
121.1166 +        else if (runState < SHUTDOWN ||
121.1167 +                 !submissionQueue.isEmpty() ||
121.1168 +                 (runState & ACTIVE_COUNT_MASK) != 0)
121.1169              return false;
121.1170 -        if (canTerminateOnShutdown(nextc))
121.1171 -            terminateOnShutdown();
121.1172 +
121.1173 +        if (advanceRunLevel(TERMINATING))
121.1174 +            startTerminating();
121.1175 +
121.1176 +        // Finish now if all threads terminated; else in some subsequent call
121.1177 +        if ((workerCounts >>> TOTAL_COUNT_SHIFT) == 0) {
121.1178 +            advanceRunLevel(TERMINATED);
121.1179 +            termination.arrive();
121.1180 +        }
121.1181          return true;
121.1182      }
121.1183  
121.1184      /**
121.1185 -     * Returns {@code true} if argument represents zero active count
121.1186 -     * and nonzero runstate, which is the triggering condition for
121.1187 -     * terminating on shutdown.
121.1188 +     * Actions on transition to TERMINATING
121.1189 +     *
121.1190 +     * Runs up to four passes through workers: (0) shutting down each
121.1191 +     * (without waking up if parked) to quickly spread notifications
121.1192 +     * without unnecessary bouncing around event queues etc (1) wake
121.1193 +     * up and help cancel tasks (2) interrupt (3) mop up races with
121.1194 +     * interrupted workers
121.1195       */
121.1196 -    private static boolean canTerminateOnShutdown(int c) {
121.1197 -        // i.e. least bit is nonzero runState bit
121.1198 -        return ((c & -c) >>> 16) != 0;
121.1199 -    }
121.1200 -
121.1201 -    /**
121.1202 -     * Transition run state to at least the given state. Return true
121.1203 -     * if not already at least given state.
121.1204 -     */
121.1205 -    private boolean transitionRunStateTo(int state) {
121.1206 -        for (;;) {
121.1207 -            int c = runControl;
121.1208 -            if (runStateOf(c) >= state)
121.1209 -                return false;
121.1210 -            if (casRunControl(c, runControlFor(state, activeCountOf(c))))
121.1211 -                return true;
121.1212 +    private void startTerminating() {
121.1213 +        cancelSubmissions();
121.1214 +        for (int passes = 0; passes < 4 && workerCounts != 0; ++passes) {
121.1215 +            int c; // advance event count
121.1216 +            UNSAFE.compareAndSwapInt(this, eventCountOffset,
121.1217 +                                     c = eventCount, c+1);
121.1218 +            eventWaiters = 0L; // clobber lists
121.1219 +            spareWaiters = 0;
121.1220 +            for (ForkJoinWorkerThread w : workers) {
121.1221 +                if (w != null) {
121.1222 +                    w.shutdown();
121.1223 +                    if (passes > 0 && !w.isTerminated()) {
121.1224 +                        w.cancelTasks();
121.1225 +                        LockSupport.unpark(w);
121.1226 +                        if (passes > 1) {
121.1227 +                            try {
121.1228 +                                w.interrupt();
121.1229 +                            } catch (SecurityException ignore) {
121.1230 +                            }
121.1231 +                        }
121.1232 +                    }
121.1233 +                }
121.1234 +            }
121.1235          }
121.1236      }
121.1237  
121.1238      /**
121.1239 -     * Controls whether to add spares to maintain parallelism
121.1240 +     * Clears out and cancels submissions, ignoring exceptions.
121.1241       */
121.1242 -    private volatile boolean maintainsParallelism;
121.1243 +    private void cancelSubmissions() {
121.1244 +        ForkJoinTask<?> task;
121.1245 +        while ((task = submissionQueue.poll()) != null) {
121.1246 +            try {
121.1247 +                task.cancel(false);
121.1248 +            } catch (Throwable ignore) {
121.1249 +            }
121.1250 +        }
121.1251 +    }
121.1252 +
121.1253 +    // misc support for ForkJoinWorkerThread
121.1254 +
121.1255 +    /**
121.1256 +     * Returns pool number.
121.1257 +     */
121.1258 +    final int getPoolNumber() {
121.1259 +        return poolNumber;
121.1260 +    }
121.1261 +
121.1262 +    /**
121.1263 +     * Tries to accumulate steal count from a worker, clearing
121.1264 +     * the worker's value if successful.
121.1265 +     *
121.1266 +     * @return true if worker steal count now zero
121.1267 +     */
121.1268 +    final boolean tryAccumulateStealCount(ForkJoinWorkerThread w) {
121.1269 +        int sc = w.stealCount;
121.1270 +        long c = stealCount;
121.1271 +        // CAS even if zero, for fence effects
121.1272 +        if (UNSAFE.compareAndSwapLong(this, stealCountOffset, c, c + sc)) {
121.1273 +            if (sc != 0)
121.1274 +                w.stealCount = 0;
121.1275 +            return true;
121.1276 +        }
121.1277 +        return sc == 0;
121.1278 +    }
121.1279 +
121.1280 +    /**
121.1281 +     * Returns the approximate (non-atomic) number of idle threads per
121.1282 +     * active thread.
121.1283 +     */
121.1284 +    final int idlePerActive() {
121.1285 +        int pc = parallelism; // use parallelism, not rc
121.1286 +        int ac = runState;    // no mask -- artificially boosts during shutdown
121.1287 +        // Use exact results for small values, saturate past 4
121.1288 +        return ((pc <= ac) ? 0 :
121.1289 +                (pc >>> 1 <= ac) ? 1 :
121.1290 +                (pc >>> 2 <= ac) ? 3 :
121.1291 +                pc >>> 3);
121.1292 +    }
121.1293 +
121.1294 +    // Public and protected methods
121.1295  
121.1296      // Constructors
121.1297  
121.1298      /**
121.1299       * Creates a {@code ForkJoinPool} with parallelism equal to {@link
121.1300 -     * java.lang.Runtime#availableProcessors}, and using the {@linkplain
121.1301 -     * #defaultForkJoinWorkerThreadFactory default thread factory}.
121.1302 +     * java.lang.Runtime#availableProcessors}, using the {@linkplain
121.1303 +     * #defaultForkJoinWorkerThreadFactory default thread factory},
121.1304 +     * no UncaughtExceptionHandler, and non-async LIFO processing mode.
121.1305       *
121.1306       * @throws SecurityException if a security manager exists and
121.1307       *         the caller is not permitted to modify threads
121.1308 @@ -404,13 +1232,14 @@
121.1309       */
121.1310      public ForkJoinPool() {
121.1311          this(Runtime.getRuntime().availableProcessors(),
121.1312 -             defaultForkJoinWorkerThreadFactory);
121.1313 +             defaultForkJoinWorkerThreadFactory, null, false);
121.1314      }
121.1315  
121.1316      /**
121.1317       * Creates a {@code ForkJoinPool} with the indicated parallelism
121.1318 -     * level and using the {@linkplain
121.1319 -     * #defaultForkJoinWorkerThreadFactory default thread factory}.
121.1320 +     * level, the {@linkplain
121.1321 +     * #defaultForkJoinWorkerThreadFactory default thread factory},
121.1322 +     * no UncaughtExceptionHandler, and non-async LIFO processing mode.
121.1323       *
121.1324       * @param parallelism the parallelism level
121.1325       * @throws IllegalArgumentException if parallelism less than or
121.1326 @@ -421,31 +1250,25 @@
121.1327       *         java.lang.RuntimePermission}{@code ("modifyThread")}
121.1328       */
121.1329      public ForkJoinPool(int parallelism) {
121.1330 -        this(parallelism, defaultForkJoinWorkerThreadFactory);
121.1331 +        this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
121.1332      }
121.1333  
121.1334      /**
121.1335 -     * Creates a {@code ForkJoinPool} with parallelism equal to {@link
121.1336 -     * java.lang.Runtime#availableProcessors}, and using the given
121.1337 -     * thread factory.
121.1338 +     * Creates a {@code ForkJoinPool} with the given parameters.
121.1339       *
121.1340 -     * @param factory the factory for creating new threads
121.1341 -     * @throws NullPointerException if the factory is null
121.1342 -     * @throws SecurityException if a security manager exists and
121.1343 -     *         the caller is not permitted to modify threads
121.1344 -     *         because it does not hold {@link
121.1345 -     *         java.lang.RuntimePermission}{@code ("modifyThread")}
121.1346 -     */
121.1347 -    public ForkJoinPool(ForkJoinWorkerThreadFactory factory) {
121.1348 -        this(Runtime.getRuntime().availableProcessors(), factory);
121.1349 -    }
121.1350 -
121.1351 -    /**
121.1352 -     * Creates a {@code ForkJoinPool} with the given parallelism and
121.1353 -     * thread factory.
121.1354 -     *
121.1355 -     * @param parallelism the parallelism level
121.1356 -     * @param factory the factory for creating new threads
121.1357 +     * @param parallelism the parallelism level. For default value,
121.1358 +     * use {@link java.lang.Runtime#availableProcessors}.
121.1359 +     * @param factory the factory for creating new threads. For default value,
121.1360 +     * use {@link #defaultForkJoinWorkerThreadFactory}.
121.1361 +     * @param handler the handler for internal worker threads that
121.1362 +     * terminate due to unrecoverable errors encountered while executing
121.1363 +     * tasks. For default value, use {@code null}.
121.1364 +     * @param asyncMode if true,
121.1365 +     * establishes local first-in-first-out scheduling mode for forked
121.1366 +     * tasks that are never joined. This mode may be more appropriate
121.1367 +     * than default locally stack-based mode in applications in which
121.1368 +     * worker threads only process event-style asynchronous tasks.
121.1369 +     * For default value, use {@code false}.
121.1370       * @throws IllegalArgumentException if parallelism less than or
121.1371       *         equal to zero, or greater than implementation limit
121.1372       * @throws NullPointerException if the factory is null
121.1373 @@ -454,153 +1277,40 @@
121.1374       *         because it does not hold {@link
121.1375       *         java.lang.RuntimePermission}{@code ("modifyThread")}
121.1376       */
121.1377 -    public ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory) {
121.1378 -        if (parallelism <= 0 || parallelism > MAX_THREADS)
121.1379 -            throw new IllegalArgumentException();
121.1380 +    public ForkJoinPool(int parallelism,
121.1381 +                        ForkJoinWorkerThreadFactory factory,
121.1382 +                        Thread.UncaughtExceptionHandler handler,
121.1383 +                        boolean asyncMode) {
121.1384 +        checkPermission();
121.1385          if (factory == null)
121.1386              throw new NullPointerException();
121.1387 -        checkPermission();
121.1388 +        if (parallelism <= 0 || parallelism > MAX_WORKERS)
121.1389 +            throw new IllegalArgumentException();
121.1390 +        this.parallelism = parallelism;
121.1391          this.factory = factory;
121.1392 -        this.parallelism = parallelism;
121.1393 -        this.maxPoolSize = MAX_THREADS;
121.1394 -        this.maintainsParallelism = true;
121.1395 +        this.ueh = handler;
121.1396 +        this.locallyFifo = asyncMode;
121.1397 +        int arraySize = initialArraySizeFor(parallelism);
121.1398 +        this.workers = new ForkJoinWorkerThread[arraySize];
121.1399 +        this.submissionQueue = new LinkedTransferQueue<ForkJoinTask<?>>();
121.1400 +        this.workerLock = new ReentrantLock();
121.1401 +        this.termination = new Phaser(1);
121.1402          this.poolNumber = poolNumberGenerator.incrementAndGet();
121.1403 -        this.workerLock = new ReentrantLock();
121.1404 -        this.termination = workerLock.newCondition();
121.1405 -        this.stealCount = new AtomicLong();
121.1406 -        this.submissionQueue = new LinkedTransferQueue<ForkJoinTask<?>>();
121.1407 -        // worker array and workers are lazily constructed
121.1408      }
121.1409  
121.1410      /**
121.1411 -     * Creates a new worker thread using factory.
121.1412 -     *
121.1413 -     * @param index the index to assign worker
121.1414 -     * @return new worker, or null if factory failed
121.1415 +     * Returns initial power of two size for workers array.
121.1416 +     * @param pc the initial parallelism level
121.1417       */
121.1418 -    private ForkJoinWorkerThread createWorker(int index) {
121.1419 -        Thread.UncaughtExceptionHandler h = ueh;
121.1420 -        ForkJoinWorkerThread w = factory.newThread(this);
121.1421 -        if (w != null) {
121.1422 -            w.poolIndex = index;
121.1423 -            w.setDaemon(true);
121.1424 -            w.setAsyncMode(locallyFifo);
121.1425 -            w.setName("ForkJoinPool-" + poolNumber + "-worker-" + index);
121.1426 -            if (h != null)
121.1427 -                w.setUncaughtExceptionHandler(h);
121.1428 -        }
121.1429 -        return w;
121.1430 -    }
121.1431 -
121.1432 -    /**
121.1433 -     * Returns a good size for worker array given pool size.
121.1434 -     * Currently requires size to be a power of two.
121.1435 -     */
121.1436 -    private static int arraySizeFor(int poolSize) {
121.1437 -        if (poolSize <= 1)
121.1438 -            return 1;
121.1439 -        // See Hackers Delight, sec 3.2
121.1440 -        int c = poolSize >= MAX_THREADS ? MAX_THREADS : (poolSize - 1);
121.1441 -        c |= c >>>  1;
121.1442 -        c |= c >>>  2;
121.1443 -        c |= c >>>  4;
121.1444 -        c |= c >>>  8;
121.1445 -        c |= c >>> 16;
121.1446 -        return c + 1;
121.1447 -    }
121.1448 -
121.1449 -    /**
121.1450 -     * Creates or resizes array if necessary to hold newLength.
121.1451 -     * Call only under exclusion.
121.1452 -     *
121.1453 -     * @return the array
121.1454 -     */
121.1455 -    private ForkJoinWorkerThread[] ensureWorkerArrayCapacity(int newLength) {
121.1456 -        ForkJoinWorkerThread[] ws = workers;
121.1457 -        if (ws == null)
121.1458 -            return workers = new ForkJoinWorkerThread[arraySizeFor(newLength)];
121.1459 -        else if (newLength > ws.length)
121.1460 -            return workers = Arrays.copyOf(ws, arraySizeFor(newLength));
121.1461 -        else
121.1462 -            return ws;
121.1463 -    }
121.1464 -
121.1465 -    /**
121.1466 -     * Tries to shrink workers into smaller array after one or more terminate.
121.1467 -     */
121.1468 -    private void tryShrinkWorkerArray() {
121.1469 -        ForkJoinWorkerThread[] ws = workers;
121.1470 -        if (ws != null) {
121.1471 -            int len = ws.length;
121.1472 -            int last = len - 1;
121.1473 -            while (last >= 0 && ws[last] == null)
121.1474 -                --last;
121.1475 -            int newLength = arraySizeFor(last+1);
121.1476 -            if (newLength < len)
121.1477 -                workers = Arrays.copyOf(ws, newLength);
121.1478 -        }
121.1479 -    }
121.1480 -
121.1481 -    /**
121.1482 -     * Initializes workers if necessary.
121.1483 -     */
121.1484 -    final void ensureWorkerInitialization() {
121.1485 -        ForkJoinWorkerThread[] ws = workers;
121.1486 -        if (ws == null) {
121.1487 -            final ReentrantLock lock = this.workerLock;
121.1488 -            lock.lock();
121.1489 -            try {
121.1490 -                ws = workers;
121.1491 -                if (ws == null) {
121.1492 -                    int ps = parallelism;
121.1493 -                    ws = ensureWorkerArrayCapacity(ps);
121.1494 -                    for (int i = 0; i < ps; ++i) {
121.1495 -                        ForkJoinWorkerThread w = createWorker(i);
121.1496 -                        if (w != null) {
121.1497 -                            ws[i] = w;
121.1498 -                            w.start();
121.1499 -                            updateWorkerCount(1);
121.1500 -                        }
121.1501 -                    }
121.1502 -                }
121.1503 -            } finally {
121.1504 -                lock.unlock();
121.1505 -            }
121.1506 -        }
121.1507 -    }
121.1508 -
121.1509 -    /**
121.1510 -     * Worker creation and startup for threads added via setParallelism.
121.1511 -     */
121.1512 -    private void createAndStartAddedWorkers() {
121.1513 -        resumeAllSpares();  // Allow spares to convert to nonspare
121.1514 -        int ps = parallelism;
121.1515 -        ForkJoinWorkerThread[] ws = ensureWorkerArrayCapacity(ps);
121.1516 -        int len = ws.length;
121.1517 -        // Sweep through slots, to keep lowest indices most populated
121.1518 -        int k = 0;
121.1519 -        while (k < len) {
121.1520 -            if (ws[k] != null) {
121.1521 -                ++k;
121.1522 -                continue;
121.1523 -            }
121.1524 -            int s = workerCounts;
121.1525 -            int tc = totalCountOf(s);
121.1526 -            int rc = runningCountOf(s);
121.1527 -            if (rc >= ps || tc >= ps)
121.1528 -                break;
121.1529 -            if (casWorkerCounts (s, workerCountsFor(tc+1, rc+1))) {
121.1530 -                ForkJoinWorkerThread w = createWorker(k);
121.1531 -                if (w != null) {
121.1532 -                    ws[k++] = w;
121.1533 -                    w.start();
121.1534 -                }
121.1535 -                else {
121.1536 -                    updateWorkerCount(-1); // back out on failed creation
121.1537 -                    break;
121.1538 -                }
121.1539 -            }
121.1540 -        }
121.1541 +    private static int initialArraySizeFor(int pc) {
121.1542 +        // If possible, initially allocate enough space for one spare
121.1543 +        int size = pc < MAX_WORKERS ? pc + 1 : MAX_WORKERS;
121.1544 +        // See Hackers Delight, sec 3.2. We know MAX_WORKERS < (1 >>> 16)
121.1545 +        size |= size >>> 1;
121.1546 +        size |= size >>> 2;
121.1547 +        size |= size >>> 4;
121.1548 +        size |= size >>> 8;
121.1549 +        return size + 1;
121.1550      }
121.1551  
121.1552      // Execution methods
121.1553 @@ -611,12 +1321,12 @@
121.1554      private <T> void doSubmit(ForkJoinTask<T> task) {
121.1555          if (task == null)
121.1556              throw new NullPointerException();
121.1557 -        if (isShutdown())
121.1558 +        if (runState >= SHUTDOWN)
121.1559              throw new RejectedExecutionException();
121.1560 -        if (workers == null)
121.1561 -            ensureWorkerInitialization();
121.1562          submissionQueue.offer(task);
121.1563 -        signalIdleWorkers();
121.1564 +        int c; // try to increment event count -- CAS failure OK
121.1565 +        UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1);
121.1566 +        helpMaintainParallelism(); // create, start, or resume some workers
121.1567      }
121.1568  
121.1569      /**
121.1570 @@ -662,6 +1372,20 @@
121.1571      }
121.1572  
121.1573      /**
121.1574 +     * Submits a ForkJoinTask for execution.
121.1575 +     *
121.1576 +     * @param task the task to submit
121.1577 +     * @return the task
121.1578 +     * @throws NullPointerException if the task is null
121.1579 +     * @throws RejectedExecutionException if the task cannot be
121.1580 +     *         scheduled for execution
121.1581 +     */
121.1582 +    public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
121.1583 +        doSubmit(task);
121.1584 +        return task;
121.1585 +    }
121.1586 +
121.1587 +    /**
121.1588       * @throws NullPointerException if the task is null
121.1589       * @throws RejectedExecutionException if the task cannot be
121.1590       *         scheduled for execution
121.1591 @@ -699,21 +1423,6 @@
121.1592      }
121.1593  
121.1594      /**
121.1595 -     * Submits a ForkJoinTask for execution.
121.1596 -     *
121.1597 -     * @param task the task to submit
121.1598 -     * @return the task
121.1599 -     * @throws NullPointerException if the task is null
121.1600 -     * @throws RejectedExecutionException if the task cannot be
121.1601 -     *         scheduled for execution
121.1602 -     */
121.1603 -    public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
121.1604 -        doSubmit(task);
121.1605 -        return task;
121.1606 -    }
121.1607 -
121.1608 -
121.1609 -    /**
121.1610       * @throws NullPointerException       {@inheritDoc}
121.1611       * @throws RejectedExecutionException {@inheritDoc}
121.1612       */
121.1613 @@ -725,7 +1434,7 @@
121.1614          invoke(new InvokeAll<T>(forkJoinTasks));
121.1615  
121.1616          @SuppressWarnings({"unchecked", "rawtypes"})
121.1617 -        List<Future<T>> futures = (List<Future<T>>) (List) forkJoinTasks;
121.1618 +            List<Future<T>> futures = (List<Future<T>>) (List) forkJoinTasks;
121.1619          return futures;
121.1620      }
121.1621  
121.1622 @@ -739,8 +1448,6 @@
121.1623          private static final long serialVersionUID = -7914297376763021607L;
121.1624      }
121.1625  
121.1626 -    // Configuration and status settings and queries
121.1627 -
121.1628      /**
121.1629       * Returns the factory used for constructing new workers.
121.1630       *
121.1631 @@ -757,84 +1464,7 @@
121.1632       * @return the handler, or {@code null} if none
121.1633       */
121.1634      public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
121.1635 -        Thread.UncaughtExceptionHandler h;
121.1636 -        final ReentrantLock lock = this.workerLock;
121.1637 -        lock.lock();
121.1638 -        try {
121.1639 -            h = ueh;
121.1640 -        } finally {
121.1641 -            lock.unlock();
121.1642 -        }
121.1643 -        return h;
121.1644 -    }
121.1645 -
121.1646 -    /**
121.1647 -     * Sets the handler for internal worker threads that terminate due
121.1648 -     * to unrecoverable errors encountered while executing tasks.
121.1649 -     * Unless set, the current default or ThreadGroup handler is used
121.1650 -     * as handler.
121.1651 -     *
121.1652 -     * @param h the new handler
121.1653 -     * @return the old handler, or {@code null} if none
121.1654 -     * @throws SecurityException if a security manager exists and
121.1655 -     *         the caller is not permitted to modify threads
121.1656 -     *         because it does not hold {@link
121.1657 -     *         java.lang.RuntimePermission}{@code ("modifyThread")}
121.1658 -     */
121.1659 -    public Thread.UncaughtExceptionHandler
121.1660 -        setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler h) {
121.1661 -        checkPermission();
121.1662 -        Thread.UncaughtExceptionHandler old = null;
121.1663 -        final ReentrantLock lock = this.workerLock;
121.1664 -        lock.lock();
121.1665 -        try {
121.1666 -            old = ueh;
121.1667 -            ueh = h;
121.1668 -            ForkJoinWorkerThread[] ws = workers;
121.1669 -            if (ws != null) {
121.1670 -                for (int i = 0; i < ws.length; ++i) {
121.1671 -                    ForkJoinWorkerThread w = ws[i];
121.1672 -                    if (w != null)
121.1673 -                        w.setUncaughtExceptionHandler(h);
121.1674 -                }
121.1675 -            }
121.1676 -        } finally {
121.1677 -            lock.unlock();
121.1678 -        }
121.1679 -        return old;
121.1680 -    }
121.1681 -
121.1682 -
121.1683 -    /**
121.1684 -     * Sets the target parallelism level of this pool.
121.1685 -     *
121.1686 -     * @param parallelism the target parallelism
121.1687 -     * @throws IllegalArgumentException if parallelism less than or
121.1688 -     * equal to zero or greater than maximum size bounds
121.1689 -     * @throws SecurityException if a security manager exists and
121.1690 -     *         the caller is not permitted to modify threads
121.1691 -     *         because it does not hold {@link
121.1692 -     *         java.lang.RuntimePermission}{@code ("modifyThread")}
121.1693 -     */
121.1694 -    public void setParallelism(int parallelism) {
121.1695 -        checkPermission();
121.1696 -        if (parallelism <= 0 || parallelism > maxPoolSize)
121.1697 -            throw new IllegalArgumentException();
121.1698 -        final ReentrantLock lock = this.workerLock;
121.1699 -        lock.lock();
121.1700 -        try {
121.1701 -            if (isProcessingTasks()) {
121.1702 -                int p = this.parallelism;
121.1703 -                this.parallelism = parallelism;
121.1704 -                if (parallelism > p)
121.1705 -                    createAndStartAddedWorkers();
121.1706 -                else
121.1707 -                    trimSpares();
121.1708 -            }
121.1709 -        } finally {
121.1710 -            lock.unlock();
121.1711 -        }
121.1712 -        signalIdleWorkers();
121.1713 +        return ueh;
121.1714      }
121.1715  
121.1716      /**
121.1717 @@ -848,92 +1478,14 @@
121.1718  
121.1719      /**
121.1720       * Returns the number of worker threads that have started but not
121.1721 -     * yet terminated.  This result returned by this method may differ
121.1722 +     * yet terminated.  The result returned by this method may differ
121.1723       * from {@link #getParallelism} when threads are created to
121.1724       * maintain parallelism when others are cooperatively blocked.
121.1725       *
121.1726       * @return the number of worker threads
121.1727       */
121.1728      public int getPoolSize() {
121.1729 -        return totalCountOf(workerCounts);
121.1730 -    }
121.1731 -
121.1732 -    /**
121.1733 -     * Returns the maximum number of threads allowed to exist in the
121.1734 -     * pool. Unless set using {@link #setMaximumPoolSize}, the
121.1735 -     * maximum is an implementation-defined value designed only to
121.1736 -     * prevent runaway growth.
121.1737 -     *
121.1738 -     * @return the maximum
121.1739 -     */
121.1740 -    public int getMaximumPoolSize() {
121.1741 -        return maxPoolSize;
121.1742 -    }
121.1743 -
121.1744 -    /**
121.1745 -     * Sets the maximum number of threads allowed to exist in the
121.1746 -     * pool. The given value should normally be greater than or equal
121.1747 -     * to the {@link #getParallelism parallelism} level. Setting this
121.1748 -     * value has no effect on current pool size. It controls
121.1749 -     * construction of new threads.
121.1750 -     *
121.1751 -     * @throws IllegalArgumentException if negative or greater than
121.1752 -     * internal implementation limit
121.1753 -     */
121.1754 -    public void setMaximumPoolSize(int newMax) {
121.1755 -        if (newMax < 0 || newMax > MAX_THREADS)
121.1756 -            throw new IllegalArgumentException();
121.1757 -        maxPoolSize = newMax;
121.1758 -    }
121.1759 -
121.1760 -
121.1761 -    /**
121.1762 -     * Returns {@code true} if this pool dynamically maintains its
121.1763 -     * target parallelism level. If false, new threads are added only
121.1764 -     * to avoid possible starvation.  This setting is by default true.
121.1765 -     *
121.1766 -     * @return {@code true} if maintains parallelism
121.1767 -     */
121.1768 -    public boolean getMaintainsParallelism() {
121.1769 -        return maintainsParallelism;
121.1770 -    }
121.1771 -
121.1772 -    /**
121.1773 -     * Sets whether this pool dynamically maintains its target
121.1774 -     * parallelism level. If false, new threads are added only to
121.1775 -     * avoid possible starvation.
121.1776 -     *
121.1777 -     * @param enable {@code true} to maintain parallelism
121.1778 -     */
121.1779 -    public void setMaintainsParallelism(boolean enable) {
121.1780 -        maintainsParallelism = enable;
121.1781 -    }
121.1782 -
121.1783 -    /**
121.1784 -     * Establishes local first-in-first-out scheduling mode for forked
121.1785 -     * tasks that are never joined. This mode may be more appropriate
121.1786 -     * than default locally stack-based mode in applications in which
121.1787 -     * worker threads only process asynchronous tasks.  This method is
121.1788 -     * designed to be invoked only when the pool is quiescent, and
121.1789 -     * typically only before any tasks are submitted. The effects of
121.1790 -     * invocations at other times may be unpredictable.
121.1791 -     *
121.1792 -     * @param async if {@code true}, use locally FIFO scheduling
121.1793 -     * @return the previous mode
121.1794 -     * @see #getAsyncMode
121.1795 -     */
121.1796 -    public boolean setAsyncMode(boolean async) {
121.1797 -        boolean oldMode = locallyFifo;
121.1798 -        locallyFifo = async;
121.1799 -        ForkJoinWorkerThread[] ws = workers;
121.1800 -        if (ws != null) {
121.1801 -            for (int i = 0; i < ws.length; ++i) {
121.1802 -                ForkJoinWorkerThread t = ws[i];
121.1803 -                if (t != null)
121.1804 -                    t.setAsyncMode(async);
121.1805 -            }
121.1806 -        }
121.1807 -        return oldMode;
121.1808 +        return workerCounts >>> TOTAL_COUNT_SHIFT;
121.1809      }
121.1810  
121.1811      /**
121.1812 @@ -941,7 +1493,6 @@
121.1813       * scheduling mode for forked tasks that are never joined.
121.1814       *
121.1815       * @return {@code true} if this pool uses async mode
121.1816 -     * @see #setAsyncMode
121.1817       */
121.1818      public boolean getAsyncMode() {
121.1819          return locallyFifo;
121.1820 @@ -950,12 +1501,13 @@
121.1821      /**
121.1822       * Returns an estimate of the number of worker threads that are
121.1823       * not blocked waiting to join tasks or for other managed
121.1824 -     * synchronization.
121.1825 +     * synchronization. This method may overestimate the
121.1826 +     * number of running threads.
121.1827       *
121.1828       * @return the number of worker threads
121.1829       */
121.1830      public int getRunningThreadCount() {
121.1831 -        return runningCountOf(workerCounts);
121.1832 +        return workerCounts & RUNNING_COUNT_MASK;
121.1833      }
121.1834  
121.1835      /**
121.1836 @@ -966,19 +1518,7 @@
121.1837       * @return the number of active threads
121.1838       */
121.1839      public int getActiveThreadCount() {
121.1840 -        return activeCountOf(runControl);
121.1841 -    }
121.1842 -
121.1843 -    /**
121.1844 -     * Returns an estimate of the number of threads that are currently
121.1845 -     * idle waiting for tasks. This method may underestimate the
121.1846 -     * number of idle threads.
121.1847 -     *
121.1848 -     * @return the number of idle threads
121.1849 -     */
121.1850 -    final int getIdleThreadCount() {
121.1851 -        int c = runningCountOf(workerCounts) - activeCountOf(runControl);
121.1852 -        return (c <= 0) ? 0 : c;
121.1853 +        return runState & ACTIVE_COUNT_MASK;
121.1854      }
121.1855  
121.1856      /**
121.1857 @@ -993,7 +1533,7 @@
121.1858       * @return {@code true} if all threads are currently idle
121.1859       */
121.1860      public boolean isQuiescent() {
121.1861 -        return activeCountOf(runControl) == 0;
121.1862 +        return (runState & ACTIVE_COUNT_MASK) == 0;
121.1863      }
121.1864  
121.1865      /**
121.1866 @@ -1008,17 +1548,7 @@
121.1867       * @return the number of steals
121.1868       */
121.1869      public long getStealCount() {
121.1870 -        return stealCount.get();
121.1871 -    }
121.1872 -
121.1873 -    /**
121.1874 -     * Accumulates steal count from a worker.
121.1875 -     * Call only when worker known to be idle.
121.1876 -     */
121.1877 -    private void updateStealCount(ForkJoinWorkerThread w) {
121.1878 -        int sc = w.getAndClearStealCount();
121.1879 -        if (sc != 0)
121.1880 -            stealCount.addAndGet(sc);
121.1881 +        return stealCount;
121.1882      }
121.1883  
121.1884      /**
121.1885 @@ -1033,14 +1563,9 @@
121.1886       */
121.1887      public long getQueuedTaskCount() {
121.1888          long count = 0;
121.1889 -        ForkJoinWorkerThread[] ws = workers;
121.1890 -        if (ws != null) {
121.1891 -            for (int i = 0; i < ws.length; ++i) {
121.1892 -                ForkJoinWorkerThread t = ws[i];
121.1893 -                if (t != null)
121.1894 -                    count += t.getQueueSize();
121.1895 -            }
121.1896 -        }
121.1897 +        for (ForkJoinWorkerThread w : workers)
121.1898 +            if (w != null)
121.1899 +                count += w.getQueueSize();
121.1900          return count;
121.1901      }
121.1902  
121.1903 @@ -1094,16 +1619,11 @@
121.1904       * @return the number of elements transferred
121.1905       */
121.1906      protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
121.1907 -        int n = submissionQueue.drainTo(c);
121.1908 -        ForkJoinWorkerThread[] ws = workers;
121.1909 -        if (ws != null) {
121.1910 -            for (int i = 0; i < ws.length; ++i) {
121.1911 -                ForkJoinWorkerThread w = ws[i];
121.1912 -                if (w != null)
121.1913 -                    n += w.drainTasksTo(c);
121.1914 -            }
121.1915 -        }
121.1916 -        return n;
121.1917 +        int count = submissionQueue.drainTo(c);
121.1918 +        for (ForkJoinWorkerThread w : workers)
121.1919 +            if (w != null)
121.1920 +                count += w.drainTasksTo(c);
121.1921 +        return count;
121.1922      }
121.1923  
121.1924      /**
121.1925 @@ -1114,36 +1634,34 @@
121.1926       * @return a string identifying this pool, as well as its state
121.1927       */
121.1928      public String toString() {
121.1929 -        int ps = parallelism;
121.1930 -        int wc = workerCounts;
121.1931 -        int rc = runControl;
121.1932          long st = getStealCount();
121.1933          long qt = getQueuedTaskCount();
121.1934          long qs = getQueuedSubmissionCount();
121.1935 +        int wc = workerCounts;
121.1936 +        int tc = wc >>> TOTAL_COUNT_SHIFT;
121.1937 +        int rc = wc & RUNNING_COUNT_MASK;
121.1938 +        int pc = parallelism;
121.1939 +        int rs = runState;
121.1940 +        int ac = rs & ACTIVE_COUNT_MASK;
121.1941          return super.toString() +
121.1942 -            "[" + runStateToString(runStateOf(rc)) +
121.1943 -            ", parallelism = " + ps +
121.1944 -            ", size = " + totalCountOf(wc) +
121.1945 -            ", active = " + activeCountOf(rc) +
121.1946 -            ", running = " + runningCountOf(wc) +
121.1947 +            "[" + runLevelToString(rs) +
121.1948 +            ", parallelism = " + pc +
121.1949 +            ", size = " + tc +
121.1950 +            ", active = " + ac +
121.1951 +            ", running = " + rc +
121.1952              ", steals = " + st +
121.1953              ", tasks = " + qt +
121.1954              ", submissions = " + qs +
121.1955              "]";
121.1956      }
121.1957  
121.1958 -    private static String runStateToString(int rs) {
121.1959 -        switch(rs) {
121.1960 -        case RUNNING: return "Running";
121.1961 -        case SHUTDOWN: return "Shutting down";
121.1962 -        case TERMINATING: return "Terminating";
121.1963 -        case TERMINATED: return "Terminated";
121.1964 -        default: throw new Error("Unknown run state");
121.1965 -        }
121.1966 +    private static String runLevelToString(int s) {
121.1967 +        return ((s & TERMINATED) != 0 ? "Terminated" :
121.1968 +                ((s & TERMINATING) != 0 ? "Terminating" :
121.1969 +                 ((s & SHUTDOWN) != 0 ? "Shutting down" :
121.1970 +                  "Running")));
121.1971      }
121.1972  
121.1973 -    // lifecycle control
121.1974 -
121.1975      /**
121.1976       * Initiates an orderly shutdown in which previously submitted
121.1977       * tasks are executed, but no new tasks will be accepted.
121.1978 @@ -1158,23 +1676,8 @@
121.1979       */
121.1980      public void shutdown() {
121.1981          checkPermission();
121.1982 -        transitionRunStateTo(SHUTDOWN);
121.1983 -        if (canTerminateOnShutdown(runControl)) {
121.1984 -            if (workers == null) { // shutting down before workers created
121.1985 -                final ReentrantLock lock = this.workerLock;
121.1986 -                lock.lock();
121.1987 -                try {
121.1988 -                    if (workers == null) {
121.1989 -                        terminate();
121.1990 -                        transitionRunStateTo(TERMINATED);
121.1991 -                        termination.signalAll();
121.1992 -                    }
121.1993 -                } finally {
121.1994 -                    lock.unlock();
121.1995 -                }
121.1996 -            }
121.1997 -            terminateOnShutdown();
121.1998 -        }
121.1999 +        advanceRunLevel(SHUTDOWN);
121.2000 +        tryTerminate(false);
121.2001      }
121.2002  
121.2003      /**
121.2004 @@ -1195,7 +1698,7 @@
121.2005       */
121.2006      public List<Runnable> shutdownNow() {
121.2007          checkPermission();
121.2008 -        terminate();
121.2009 +        tryTerminate(true);
121.2010          return Collections.emptyList();
121.2011      }
121.2012  
121.2013 @@ -1205,7 +1708,7 @@
121.2014       * @return {@code true} if all tasks have completed following shut down
121.2015       */
121.2016      public boolean isTerminated() {
121.2017 -        return runStateOf(runControl) == TERMINATED;
121.2018 +        return runState >= TERMINATED;
121.2019      }
121.2020  
121.2021      /**
121.2022 @@ -1219,7 +1722,7 @@
121.2023       * @return {@code true} if terminating but not yet terminated
121.2024       */
121.2025      public boolean isTerminating() {
121.2026 -        return runStateOf(runControl) == TERMINATING;
121.2027 +        return (runState & (TERMINATING|TERMINATED)) == TERMINATING;
121.2028      }
121.2029  
121.2030      /**
121.2031 @@ -1228,15 +1731,7 @@
121.2032       * @return {@code true} if this pool has been shut down
121.2033       */
121.2034      public boolean isShutdown() {
121.2035 -        return runStateOf(runControl) >= SHUTDOWN;
121.2036 -    }
121.2037 -
121.2038 -    /**
121.2039 -     * Returns true if pool is not terminating or terminated.
121.2040 -     * Used internally to suppress execution when terminating.
121.2041 -     */
121.2042 -    final boolean isProcessingTasks() {
121.2043 -        return runStateOf(runControl) < TERMINATING;
121.2044 +        return runState >= SHUTDOWN;
121.2045      }
121.2046  
121.2047      /**
121.2048 @@ -1252,585 +1747,10 @@
121.2049       */
121.2050      public boolean awaitTermination(long timeout, TimeUnit unit)
121.2051          throws InterruptedException {
121.2052 -        long nanos = unit.toNanos(timeout);
121.2053 -        final ReentrantLock lock = this.workerLock;
121.2054 -        lock.lock();
121.2055          try {
121.2056 -            for (;;) {
121.2057 -                if (isTerminated())
121.2058 -                    return true;
121.2059 -                if (nanos <= 0)
121.2060 -                    return false;
121.2061 -                nanos = termination.awaitNanos(nanos);
121.2062 -            }
121.2063 -        } finally {
121.2064 -            lock.unlock();
121.2065 -        }
121.2066 -    }
121.2067 -
121.2068 -    // Shutdown and termination support
121.2069 -
121.2070 -    /**
121.2071 -     * Callback from terminating worker. Nulls out the corresponding
121.2072 -     * workers slot, and if terminating, tries to terminate; else
121.2073 -     * tries to shrink workers array.
121.2074 -     *
121.2075 -     * @param w the worker
121.2076 -     */
121.2077 -    final void workerTerminated(ForkJoinWorkerThread w) {
121.2078 -        updateStealCount(w);
121.2079 -        updateWorkerCount(-1);
121.2080 -        final ReentrantLock lock = this.workerLock;
121.2081 -        lock.lock();
121.2082 -        try {
121.2083 -            ForkJoinWorkerThread[] ws = workers;
121.2084 -            if (ws != null) {
121.2085 -                int idx = w.poolIndex;
121.2086 -                if (idx >= 0 && idx < ws.length && ws[idx] == w)
121.2087 -                    ws[idx] = null;
121.2088 -                if (totalCountOf(workerCounts) == 0) {
121.2089 -                    terminate(); // no-op if already terminating
121.2090 -                    transitionRunStateTo(TERMINATED);
121.2091 -                    termination.signalAll();
121.2092 -                }
121.2093 -                else if (isProcessingTasks()) {
121.2094 -                    tryShrinkWorkerArray();
121.2095 -                    tryResumeSpare(true); // allow replacement
121.2096 -                }
121.2097 -            }
121.2098 -        } finally {
121.2099 -            lock.unlock();
121.2100 -        }
121.2101 -        signalIdleWorkers();
121.2102 -    }
121.2103 -
121.2104 -    /**
121.2105 -     * Initiates termination.
121.2106 -     */
121.2107 -    private void terminate() {
121.2108 -        if (transitionRunStateTo(TERMINATING)) {
121.2109 -            stopAllWorkers();
121.2110 -            resumeAllSpares();
121.2111 -            signalIdleWorkers();
121.2112 -            cancelQueuedSubmissions();
121.2113 -            cancelQueuedWorkerTasks();
121.2114 -            interruptUnterminatedWorkers();
121.2115 -            signalIdleWorkers(); // resignal after interrupt
121.2116 -        }
121.2117 -    }
121.2118 -
121.2119 -    /**
121.2120 -     * Possibly terminates when on shutdown state.
121.2121 -     */
121.2122 -    private void terminateOnShutdown() {
121.2123 -        if (!hasQueuedSubmissions() && canTerminateOnShutdown(runControl))
121.2124 -            terminate();
121.2125 -    }
121.2126 -
121.2127 -    /**
121.2128 -     * Clears out and cancels submissions.
121.2129 -     */
121.2130 -    private void cancelQueuedSubmissions() {
121.2131 -        ForkJoinTask<?> task;
121.2132 -        while ((task = pollSubmission()) != null)
121.2133 -            task.cancel(false);
121.2134 -    }
121.2135 -
121.2136 -    /**
121.2137 -     * Cleans out worker queues.
121.2138 -     */
121.2139 -    private void cancelQueuedWorkerTasks() {
121.2140 -        final ReentrantLock lock = this.workerLock;
121.2141 -        lock.lock();
121.2142 -        try {
121.2143 -            ForkJoinWorkerThread[] ws = workers;
121.2144 -            if (ws != null) {
121.2145 -                for (int i = 0; i < ws.length; ++i) {
121.2146 -                    ForkJoinWorkerThread t = ws[i];
121.2147 -                    if (t != null)
121.2148 -                        t.cancelTasks();
121.2149 -                }
121.2150 -            }
121.2151 -        } finally {
121.2152 -            lock.unlock();
121.2153 -        }
121.2154 -    }
121.2155 -
121.2156 -    /**
121.2157 -     * Sets each worker's status to terminating. Requires lock to avoid
121.2158 -     * conflicts with add/remove.
121.2159 -     */
121.2160 -    private void stopAllWorkers() {
121.2161 -        final ReentrantLock lock = this.workerLock;
121.2162 -        lock.lock();
121.2163 -        try {
121.2164 -            ForkJoinWorkerThread[] ws = workers;
121.2165 -            if (ws != null) {
121.2166 -                for (int i = 0; i < ws.length; ++i) {
121.2167 -                    ForkJoinWorkerThread t = ws[i];
121.2168 -                    if (t != null)
121.2169 -                        t.shutdownNow();
121.2170 -                }
121.2171 -            }
121.2172 -        } finally {
121.2173 -            lock.unlock();
121.2174 -        }
121.2175 -    }
121.2176 -
121.2177 -    /**
121.2178 -     * Interrupts all unterminated workers.  This is not required for
121.2179 -     * sake of internal control, but may help unstick user code during
121.2180 -     * shutdown.
121.2181 -     */
121.2182 -    private void interruptUnterminatedWorkers() {
121.2183 -        final ReentrantLock lock = this.workerLock;
121.2184 -        lock.lock();
121.2185 -        try {
121.2186 -            ForkJoinWorkerThread[] ws = workers;
121.2187 -            if (ws != null) {
121.2188 -                for (int i = 0; i < ws.length; ++i) {
121.2189 -                    ForkJoinWorkerThread t = ws[i];
121.2190 -                    if (t != null && !t.isTerminated()) {
121.2191 -                        try {
121.2192 -                            t.interrupt();
121.2193 -                        } catch (SecurityException ignore) {
121.2194 -                        }
121.2195 -                    }
121.2196 -                }
121.2197 -            }
121.2198 -        } finally {
121.2199 -            lock.unlock();
121.2200 -        }
121.2201 -    }
121.2202 -
121.2203 -
121.2204 -    /*
121.2205 -     * Nodes for event barrier to manage idle threads.  Queue nodes
121.2206 -     * are basic Treiber stack nodes, also used for spare stack.
121.2207 -     *
121.2208 -     * The event barrier has an event count and a wait queue (actually
121.2209 -     * a Treiber stack).  Workers are enabled to look for work when
121.2210 -     * the eventCount is incremented. If they fail to find work, they
121.2211 -     * may wait for next count. Upon release, threads help others wake
121.2212 -     * up.
121.2213 -     *
121.2214 -     * Synchronization events occur only in enough contexts to
121.2215 -     * maintain overall liveness:
121.2216 -     *
121.2217 -     *   - Submission of a new task to the pool
121.2218 -     *   - Resizes or other changes to the workers array
121.2219 -     *   - pool termination
121.2220 -     *   - A worker pushing a task on an empty queue
121.2221 -     *
121.2222 -     * The case of pushing a task occurs often enough, and is heavy
121.2223 -     * enough compared to simple stack pushes, to require special
121.2224 -     * handling: Method signalWork returns without advancing count if
121.2225 -     * the queue appears to be empty.  This would ordinarily result in
121.2226 -     * races causing some queued waiters not to be woken up. To avoid
121.2227 -     * this, the first worker enqueued in method sync (see
121.2228 -     * syncIsReleasable) rescans for tasks after being enqueued, and
121.2229 -     * helps signal if any are found. This works well because the
121.2230 -     * worker has nothing better to do, and so might as well help
121.2231 -     * alleviate the overhead and contention on the threads actually
121.2232 -     * doing work.  Also, since event counts increments on task
121.2233 -     * availability exist to maintain liveness (rather than to force
121.2234 -     * refreshes etc), it is OK for callers to exit early if
121.2235 -     * contending with another signaller.
121.2236 -     */
121.2237 -    static final class WaitQueueNode {
121.2238 -        WaitQueueNode next; // only written before enqueued
121.2239 -        volatile ForkJoinWorkerThread thread; // nulled to cancel wait
121.2240 -        final long count; // unused for spare stack
121.2241 -
121.2242 -        WaitQueueNode(long c, ForkJoinWorkerThread w) {
121.2243 -            count = c;
121.2244 -            thread = w;
121.2245 -        }
121.2246 -
121.2247 -        /**
121.2248 -         * Wakes up waiter, returning false if known to already
121.2249 -         */
121.2250 -        boolean signal() {
121.2251 -            ForkJoinWorkerThread t = thread;
121.2252 -            if (t == null)
121.2253 -                return false;
121.2254 -            thread = null;
121.2255 -            LockSupport.unpark(t);
121.2256 -            return true;
121.2257 -        }
121.2258 -
121.2259 -        /**
121.2260 -         * Awaits release on sync.
121.2261 -         */
121.2262 -        void awaitSyncRelease(ForkJoinPool p) {
121.2263 -            while (thread != null && !p.syncIsReleasable(this))
121.2264 -                LockSupport.park(this);
121.2265 -        }
121.2266 -
121.2267 -        /**
121.2268 -         * Awaits resumption as spare.
121.2269 -         */
121.2270 -        void awaitSpareRelease() {
121.2271 -            while (thread != null) {
121.2272 -                if (!Thread.interrupted())
121.2273 -                    LockSupport.park(this);
121.2274 -            }
121.2275 -        }
121.2276 -    }
121.2277 -
121.2278 -    /**
121.2279 -     * Ensures that no thread is waiting for count to advance from the
121.2280 -     * current value of eventCount read on entry to this method, by
121.2281 -     * releasing waiting threads if necessary.
121.2282 -     *
121.2283 -     * @return the count
121.2284 -     */
121.2285 -    final long ensureSync() {
121.2286 -        long c = eventCount;
121.2287 -        WaitQueueNode q;
121.2288 -        while ((q = syncStack) != null && q.count < c) {
121.2289 -            if (casBarrierStack(q, null)) {
121.2290 -                do {
121.2291 -                    q.signal();
121.2292 -                } while ((q = q.next) != null);
121.2293 -                break;
121.2294 -            }
121.2295 -        }
121.2296 -        return c;
121.2297 -    }
121.2298 -
121.2299 -    /**
121.2300 -     * Increments event count and releases waiting threads.
121.2301 -     */
121.2302 -    private void signalIdleWorkers() {
121.2303 -        long c;
121.2304 -        do {} while (!casEventCount(c = eventCount, c+1));
121.2305 -        ensureSync();
121.2306 -    }
121.2307 -
121.2308 -    /**
121.2309 -     * Signals threads waiting to poll a task. Because method sync
121.2310 -     * rechecks availability, it is OK to only proceed if queue
121.2311 -     * appears to be non-empty, and OK to skip under contention to
121.2312 -     * increment count (since some other thread succeeded).
121.2313 -     */
121.2314 -    final void signalWork() {
121.2315 -        long c;
121.2316 -        WaitQueueNode q;
121.2317 -        if (syncStack != null &&
121.2318 -            casEventCount(c = eventCount, c+1) &&
121.2319 -            (((q = syncStack) != null && q.count <= c) &&
121.2320 -             (!casBarrierStack(q, q.next) || !q.signal())))
121.2321 -            ensureSync();
121.2322 -    }
121.2323 -
121.2324 -    /**
121.2325 -     * Waits until event count advances from last value held by
121.2326 -     * caller, or if excess threads, caller is resumed as spare, or
121.2327 -     * caller or pool is terminating. Updates caller's event on exit.
121.2328 -     *
121.2329 -     * @param w the calling worker thread
121.2330 -     */
121.2331 -    final void sync(ForkJoinWorkerThread w) {
121.2332 -        updateStealCount(w); // Transfer w's count while it is idle
121.2333 -
121.2334 -        while (!w.isShutdown() && isProcessingTasks() && !suspendIfSpare(w)) {
121.2335 -            long prev = w.lastEventCount;
121.2336 -            WaitQueueNode node = null;
121.2337 -            WaitQueueNode h;
121.2338 -            while (eventCount == prev &&
121.2339 -                   ((h = syncStack) == null || h.count == prev)) {
121.2340 -                if (node == null)
121.2341 -                    node = new WaitQueueNode(prev, w);
121.2342 -                if (casBarrierStack(node.next = h, node)) {
121.2343 -                    node.awaitSyncRelease(this);
121.2344 -                    break;
121.2345 -                }
121.2346 -            }
121.2347 -            long ec = ensureSync();
121.2348 -            if (ec != prev) {
121.2349 -                w.lastEventCount = ec;
121.2350 -                break;
121.2351 -            }
121.2352 -        }
121.2353 -    }
121.2354 -
121.2355 -    /**
121.2356 -     * Returns {@code true} if worker waiting on sync can proceed:
121.2357 -     *  - on signal (thread == null)
121.2358 -     *  - on event count advance (winning race to notify vs signaller)
121.2359 -     *  - on interrupt
121.2360 -     *  - if the first queued node, we find work available
121.2361 -     * If node was not signalled and event count not advanced on exit,
121.2362 -     * then we also help advance event count.
121.2363 -     *
121.2364 -     * @return {@code true} if node can be released
121.2365 -     */
121.2366 -    final boolean syncIsReleasable(WaitQueueNode node) {
121.2367 -        long prev = node.count;
121.2368 -        if (!Thread.interrupted() && node.thread != null &&
121.2369 -            (node.next != null ||
121.2370 -             !ForkJoinWorkerThread.hasQueuedTasks(workers)) &&
121.2371 -            eventCount == prev)
121.2372 +            return termination.awaitAdvanceInterruptibly(0, timeout, unit) > 0;
121.2373 +        } catch (TimeoutException ex) {
121.2374              return false;
121.2375 -        if (node.thread != null) {
121.2376 -            node.thread = null;
121.2377 -            long ec = eventCount;
121.2378 -            if (prev <= ec) // help signal
121.2379 -                casEventCount(ec, ec+1);
121.2380 -        }
121.2381 -        return true;
121.2382 -    }
121.2383 -
121.2384 -    /**
121.2385 -     * Returns {@code true} if a new sync event occurred since last
121.2386 -     * call to sync or this method, if so, updating caller's count.
121.2387 -     */
121.2388 -    final boolean hasNewSyncEvent(ForkJoinWorkerThread w) {
121.2389 -        long lc = w.lastEventCount;
121.2390 -        long ec = ensureSync();
121.2391 -        if (ec == lc)
121.2392 -            return false;
121.2393 -        w.lastEventCount = ec;
121.2394 -        return true;
121.2395 -    }
121.2396 -
121.2397 -    //  Parallelism maintenance
121.2398 -
121.2399 -    /**
121.2400 -     * Decrements running count; if too low, adds spare.
121.2401 -     *
121.2402 -     * Conceptually, all we need to do here is add or resume a
121.2403 -     * spare thread when one is about to block (and remove or
121.2404 -     * suspend it later when unblocked -- see suspendIfSpare).
121.2405 -     * However, implementing this idea requires coping with
121.2406 -     * several problems: we have imperfect information about the
121.2407 -     * states of threads. Some count updates can and usually do
121.2408 -     * lag run state changes, despite arrangements to keep them
121.2409 -     * accurate (for example, when possible, updating counts
121.2410 -     * before signalling or resuming), especially when running on
121.2411 -     * dynamic JVMs that don't optimize the infrequent paths that
121.2412 -     * update counts. Generating too many threads can make these
121.2413 -     * problems become worse, because excess threads are more
121.2414 -     * likely to be context-switched with others, slowing them all
121.2415 -     * down, especially if there is no work available, so all are
121.2416 -     * busy scanning or idling.  Also, excess spare threads can
121.2417 -     * only be suspended or removed when they are idle, not
121.2418 -     * immediately when they aren't needed. So adding threads will
121.2419 -     * raise parallelism level for longer than necessary.  Also,
121.2420 -     * FJ applications often encounter highly transient peaks when
121.2421 -     * many threads are blocked joining, but for less time than it
121.2422 -     * takes to create or resume spares.
121.2423 -     *
121.2424 -     * @param joinMe if non-null, return early if done
121.2425 -     * @param maintainParallelism if true, try to stay within
121.2426 -     * target counts, else create only to avoid starvation
121.2427 -     * @return true if joinMe known to be done
121.2428 -     */
121.2429 -    final boolean preJoin(ForkJoinTask<?> joinMe,
121.2430 -                          boolean maintainParallelism) {
121.2431 -        maintainParallelism &= maintainsParallelism; // overrride
121.2432 -        boolean dec = false;  // true when running count decremented
121.2433 -        while (spareStack == null || !tryResumeSpare(dec)) {
121.2434 -            int counts = workerCounts;
121.2435 -            if (dec || (dec = casWorkerCounts(counts, --counts))) {
121.2436 -                if (!needSpare(counts, maintainParallelism))
121.2437 -                    break;
121.2438 -                if (joinMe.status < 0)
121.2439 -                    return true;
121.2440 -                if (tryAddSpare(counts))
121.2441 -                    break;
121.2442 -            }
121.2443 -        }
121.2444 -        return false;
121.2445 -    }
121.2446 -
121.2447 -    /**
121.2448 -     * Same idea as preJoin
121.2449 -     */
121.2450 -    final boolean preBlock(ManagedBlocker blocker,
121.2451 -                           boolean maintainParallelism) {
121.2452 -        maintainParallelism &= maintainsParallelism;
121.2453 -        boolean dec = false;
121.2454 -        while (spareStack == null || !tryResumeSpare(dec)) {
121.2455 -            int counts = workerCounts;
121.2456 -            if (dec || (dec = casWorkerCounts(counts, --counts))) {
121.2457 -                if (!needSpare(counts, maintainParallelism))
121.2458 -                    break;
121.2459 -                if (blocker.isReleasable())
121.2460 -                    return true;
121.2461 -                if (tryAddSpare(counts))
121.2462 -                    break;
121.2463 -            }
121.2464 -        }
121.2465 -        return false;
121.2466 -    }
121.2467 -
121.2468 -    /**
121.2469 -     * Returns {@code true} if a spare thread appears to be needed.
121.2470 -     * If maintaining parallelism, returns true when the deficit in
121.2471 -     * running threads is more than the surplus of total threads, and
121.2472 -     * there is apparently some work to do.  This self-limiting rule
121.2473 -     * means that the more threads that have already been added, the
121.2474 -     * less parallelism we will tolerate before adding another.
121.2475 -     *
121.2476 -     * @param counts current worker counts
121.2477 -     * @param maintainParallelism try to maintain parallelism
121.2478 -     */
121.2479 -    private boolean needSpare(int counts, boolean maintainParallelism) {
121.2480 -        int ps = parallelism;
121.2481 -        int rc = runningCountOf(counts);
121.2482 -        int tc = totalCountOf(counts);
121.2483 -        int runningDeficit = ps - rc;
121.2484 -        int totalSurplus = tc - ps;
121.2485 -        return (tc < maxPoolSize &&
121.2486 -                (rc == 0 || totalSurplus < 0 ||
121.2487 -                 (maintainParallelism &&
121.2488 -                  runningDeficit > totalSurplus &&
121.2489 -                  ForkJoinWorkerThread.hasQueuedTasks(workers))));
121.2490 -    }
121.2491 -
121.2492 -    /**
121.2493 -     * Adds a spare worker if lock available and no more than the
121.2494 -     * expected numbers of threads exist.
121.2495 -     *
121.2496 -     * @return true if successful
121.2497 -     */
121.2498 -    private boolean tryAddSpare(int expectedCounts) {
121.2499 -        final ReentrantLock lock = this.workerLock;
121.2500 -        int expectedRunning = runningCountOf(expectedCounts);
121.2501 -        int expectedTotal = totalCountOf(expectedCounts);
121.2502 -        boolean success = false;
121.2503 -        boolean locked = false;
121.2504 -        // confirm counts while locking; CAS after obtaining lock
121.2505 -        try {
121.2506 -            for (;;) {
121.2507 -                int s = workerCounts;
121.2508 -                int tc = totalCountOf(s);
121.2509 -                int rc = runningCountOf(s);
121.2510 -                if (rc > expectedRunning || tc > expectedTotal)
121.2511 -                    break;
121.2512 -                if (!locked && !(locked = lock.tryLock()))
121.2513 -                    break;
121.2514 -                if (casWorkerCounts(s, workerCountsFor(tc+1, rc+1))) {
121.2515 -                    createAndStartSpare(tc);
121.2516 -                    success = true;
121.2517 -                    break;
121.2518 -                }
121.2519 -            }
121.2520 -        } finally {
121.2521 -            if (locked)
121.2522 -                lock.unlock();
121.2523 -        }
121.2524 -        return success;
121.2525 -    }
121.2526 -
121.2527 -    /**
121.2528 -     * Adds the kth spare worker. On entry, pool counts are already
121.2529 -     * adjusted to reflect addition.
121.2530 -     */
121.2531 -    private void createAndStartSpare(int k) {
121.2532 -        ForkJoinWorkerThread w = null;
121.2533 -        ForkJoinWorkerThread[] ws = ensureWorkerArrayCapacity(k + 1);
121.2534 -        int len = ws.length;
121.2535 -        // Probably, we can place at slot k. If not, find empty slot
121.2536 -        if (k < len && ws[k] != null) {
121.2537 -            for (k = 0; k < len && ws[k] != null; ++k)
121.2538 -                ;
121.2539 -        }
121.2540 -        if (k < len && isProcessingTasks() && (w = createWorker(k)) != null) {
121.2541 -            ws[k] = w;
121.2542 -            w.start();
121.2543 -        }
121.2544 -        else
121.2545 -            updateWorkerCount(-1); // adjust on failure
121.2546 -        signalIdleWorkers();
121.2547 -    }
121.2548 -
121.2549 -    /**
121.2550 -     * Suspends calling thread w if there are excess threads.  Called
121.2551 -     * only from sync.  Spares are enqueued in a Treiber stack using
121.2552 -     * the same WaitQueueNodes as barriers.  They are resumed mainly
121.2553 -     * in preJoin, but are also woken on pool events that require all
121.2554 -     * threads to check run state.
121.2555 -     *
121.2556 -     * @param w the caller
121.2557 -     */
121.2558 -    private boolean suspendIfSpare(ForkJoinWorkerThread w) {
121.2559 -        WaitQueueNode node = null;
121.2560 -        int s;
121.2561 -        while (parallelism < runningCountOf(s = workerCounts)) {
121.2562 -            if (node == null)
121.2563 -                node = new WaitQueueNode(0, w);
121.2564 -            if (casWorkerCounts(s, s-1)) { // representation-dependent
121.2565 -                // push onto stack
121.2566 -                do {} while (!casSpareStack(node.next = spareStack, node));
121.2567 -                // block until released by resumeSpare
121.2568 -                node.awaitSpareRelease();
121.2569 -                return true;
121.2570 -            }
121.2571 -        }
121.2572 -        return false;
121.2573 -    }
121.2574 -
121.2575 -    /**
121.2576 -     * Tries to pop and resume a spare thread.
121.2577 -     *
121.2578 -     * @param updateCount if true, increment running count on success
121.2579 -     * @return true if successful
121.2580 -     */
121.2581 -    private boolean tryResumeSpare(boolean updateCount) {
121.2582 -        WaitQueueNode q;
121.2583 -        while ((q = spareStack) != null) {
121.2584 -            if (casSpareStack(q, q.next)) {
121.2585 -                if (updateCount)
121.2586 -                    updateRunningCount(1);
121.2587 -                q.signal();
121.2588 -                return true;
121.2589 -            }
121.2590 -        }
121.2591 -        return false;
121.2592 -    }
121.2593 -
121.2594 -    /**
121.2595 -     * Pops and resumes all spare threads. Same idea as ensureSync.
121.2596 -     *
121.2597 -     * @return true if any spares released
121.2598 -     */
121.2599 -    private boolean resumeAllSpares() {
121.2600 -        WaitQueueNode q;
121.2601 -        while ( (q = spareStack) != null) {
121.2602 -            if (casSpareStack(q, null)) {
121.2603 -                do {
121.2604 -                    updateRunningCount(1);
121.2605 -                    q.signal();
121.2606 -                } while ((q = q.next) != null);
121.2607 -                return true;
121.2608 -            }
121.2609 -        }
121.2610 -        return false;
121.2611 -    }
121.2612 -
121.2613 -    /**
121.2614 -     * Pops and shuts down excessive spare threads. Call only while
121.2615 -     * holding lock. This is not guaranteed to eliminate all excess
121.2616 -     * threads, only those suspended as spares, which are the ones
121.2617 -     * unlikely to be needed in the future.
121.2618 -     */
121.2619 -    private void trimSpares() {
121.2620 -        int surplus = totalCountOf(workerCounts) - parallelism;
121.2621 -        WaitQueueNode q;
121.2622 -        while (surplus > 0 && (q = spareStack) != null) {
121.2623 -            if (casSpareStack(q, null)) {
121.2624 -                do {
121.2625 -                    updateRunningCount(1);
121.2626 -                    ForkJoinWorkerThread w = q.thread;
121.2627 -                    if (w != null && surplus > 0 &&
121.2628 -                        runningCountOf(workerCounts) > 0 && w.shutdown())
121.2629 -                        --surplus;
121.2630 -                    q.signal();
121.2631 -                } while ((q = q.next) != null);
121.2632 -            }
121.2633          }
121.2634      }
121.2635  
121.2636 @@ -1838,11 +1758,17 @@
121.2637       * Interface for extending managed parallelism for tasks running
121.2638       * in {@link ForkJoinPool}s.
121.2639       *
121.2640 -     * <p>A {@code ManagedBlocker} provides two methods.
121.2641 -     * Method {@code isReleasable} must return {@code true} if
121.2642 -     * blocking is not necessary. Method {@code block} blocks the
121.2643 -     * current thread if necessary (perhaps internally invoking
121.2644 -     * {@code isReleasable} before actually blocking).
121.2645 +     * <p>A {@code ManagedBlocker} provides two methods.  Method
121.2646 +     * {@code isReleasable} must return {@code true} if blocking is
121.2647 +     * not necessary. Method {@code block} blocks the current thread
121.2648 +     * if necessary (perhaps internally invoking {@code isReleasable}
121.2649 +     * before actually blocking). The unusual methods in this API
121.2650 +     * accommodate synchronizers that may, but don't usually, block
121.2651 +     * for long periods. Similarly, they allow more efficient internal
121.2652 +     * handling of cases in which additional workers may be, but
121.2653 +     * usually are not, needed to ensure sufficient parallelism.
121.2654 +     * Toward this end, implementations of method {@code isReleasable}
121.2655 +     * must be amenable to repeated invocation.
121.2656       *
121.2657       * <p>For example, here is a ManagedBlocker based on a
121.2658       * ReentrantLock:
121.2659 @@ -1860,6 +1786,26 @@
121.2660       *     return hasLock || (hasLock = lock.tryLock());
121.2661       *   }
121.2662       * }}</pre>
121.2663 +     *
121.2664 +     * <p>Here is a class that possibly blocks waiting for an
121.2665 +     * item on a given queue:
121.2666 +     *  <pre> {@code
121.2667 +     * class QueueTaker<E> implements ManagedBlocker {
121.2668 +     *   final BlockingQueue<E> queue;
121.2669 +     *   volatile E item = null;
121.2670 +     *   QueueTaker(BlockingQueue<E> q) { this.queue = q; }
121.2671 +     *   public boolean block() throws InterruptedException {
121.2672 +     *     if (item == null)
121.2673 +     *       item = queue.take();
121.2674 +     *     return true;
121.2675 +     *   }
121.2676 +     *   public boolean isReleasable() {
121.2677 +     *     return item != null || (item = queue.poll()) != null;
121.2678 +     *   }
121.2679 +     *   public E getItem() { // call after pool.managedBlock completes
121.2680 +     *     return item;
121.2681 +     *   }
121.2682 +     * }}</pre>
121.2683       */
121.2684      public static interface ManagedBlocker {
121.2685          /**
121.2686 @@ -1883,14 +1829,7 @@
121.2687       * Blocks in accord with the given blocker.  If the current thread
121.2688       * is a {@link ForkJoinWorkerThread}, this method possibly
121.2689       * arranges for a spare thread to be activated if necessary to
121.2690 -     * ensure parallelism while the current thread is blocked.
121.2691 -     *
121.2692 -     * <p>If {@code maintainParallelism} is {@code true} and the pool
121.2693 -     * supports it ({@link #getMaintainsParallelism}), this method
121.2694 -     * attempts to maintain the pool's nominal parallelism. Otherwise
121.2695 -     * it activates a thread only if necessary to avoid complete
121.2696 -     * starvation. This option may be preferable when blockages use
121.2697 -     * timeouts, or are almost always brief.
121.2698 +     * ensure sufficient parallelism while the current thread is blocked.
121.2699       *
121.2700       * <p>If the caller is not a {@link ForkJoinTask}, this method is
121.2701       * behaviorally equivalent to
121.2702 @@ -1904,33 +1843,18 @@
121.2703       * first be expanded to ensure parallelism, and later adjusted.
121.2704       *
121.2705       * @param blocker the blocker
121.2706 -     * @param maintainParallelism if {@code true} and supported by
121.2707 -     * this pool, attempt to maintain the pool's nominal parallelism;
121.2708 -     * otherwise activate a thread only if necessary to avoid
121.2709 -     * complete starvation.
121.2710       * @throws InterruptedException if blocker.block did so
121.2711       */
121.2712 -    public static void managedBlock(ManagedBlocker blocker,
121.2713 -                                    boolean maintainParallelism)
121.2714 +    public static void managedBlock(ManagedBlocker blocker)
121.2715          throws InterruptedException {
121.2716          Thread t = Thread.currentThread();
121.2717 -        ForkJoinPool pool = ((t instanceof ForkJoinWorkerThread) ?
121.2718 -                             ((ForkJoinWorkerThread) t).pool : null);
121.2719 -        if (!blocker.isReleasable()) {
121.2720 -            try {
121.2721 -                if (pool == null ||
121.2722 -                    !pool.preBlock(blocker, maintainParallelism))
121.2723 -                    awaitBlocker(blocker);
121.2724 -            } finally {
121.2725 -                if (pool != null)
121.2726 -                    pool.updateRunningCount(1);
121.2727 -            }
121.2728 +        if (t instanceof ForkJoinWorkerThread) {
121.2729 +            ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
121.2730 +            w.pool.awaitBlocker(blocker);
121.2731          }
121.2732 -    }
121.2733 -
121.2734 -    private static void awaitBlocker(ManagedBlocker blocker)
121.2735 -        throws InterruptedException {
121.2736 -        do {} while (!blocker.isReleasable() && !blocker.block());
121.2737 +        else {
121.2738 +            do {} while (!blocker.isReleasable() && !blocker.block());
121.2739 +        }
121.2740      }
121.2741  
121.2742      // AbstractExecutorService overrides.  These rely on undocumented
121.2743 @@ -1948,32 +1872,18 @@
121.2744      // Unsafe mechanics
121.2745  
121.2746      private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
121.2747 +    private static final long workerCountsOffset =
121.2748 +        objectFieldOffset("workerCounts", ForkJoinPool.class);
121.2749 +    private static final long runStateOffset =
121.2750 +        objectFieldOffset("runState", ForkJoinPool.class);
121.2751      private static final long eventCountOffset =
121.2752          objectFieldOffset("eventCount", ForkJoinPool.class);
121.2753 -    private static final long workerCountsOffset =
121.2754 -        objectFieldOffset("workerCounts", ForkJoinPool.class);
121.2755 -    private static final long runControlOffset =
121.2756 -        objectFieldOffset("runControl", ForkJoinPool.class);
121.2757 -    private static final long syncStackOffset =
121.2758 -        objectFieldOffset("syncStack",ForkJoinPool.class);
121.2759 -    private static final long spareStackOffset =
121.2760 -        objectFieldOffset("spareStack", ForkJoinPool.class);
121.2761 -
121.2762 -    private boolean casEventCount(long cmp, long val) {
121.2763 -        return UNSAFE.compareAndSwapLong(this, eventCountOffset, cmp, val);
121.2764 -    }
121.2765 -    private boolean casWorkerCounts(int cmp, int val) {
121.2766 -        return UNSAFE.compareAndSwapInt(this, workerCountsOffset, cmp, val);
121.2767 -    }
121.2768 -    private boolean casRunControl(int cmp, int val) {
121.2769 -        return UNSAFE.compareAndSwapInt(this, runControlOffset, cmp, val);
121.2770 -    }
121.2771 -    private boolean casSpareStack(WaitQueueNode cmp, WaitQueueNode val) {
121.2772 -        return UNSAFE.compareAndSwapObject(this, spareStackOffset, cmp, val);
121.2773 -    }
121.2774 -    private boolean casBarrierStack(WaitQueueNode cmp, WaitQueueNode val) {
121.2775 -        return UNSAFE.compareAndSwapObject(this, syncStackOffset, cmp, val);
121.2776 -    }
121.2777 +    private static final long eventWaitersOffset =
121.2778 +        objectFieldOffset("eventWaiters", ForkJoinPool.class);
121.2779 +    private static final long stealCountOffset =
121.2780 +        objectFieldOffset("stealCount", ForkJoinPool.class);
121.2781 +    private static final long spareWaitersOffset =
121.2782 +        objectFieldOffset("spareWaiters", ForkJoinPool.class);
121.2783  
121.2784      private static long objectFieldOffset(String field, Class<?> klazz) {
121.2785          try {
   122.1 --- a/src/share/classes/java/util/concurrent/ForkJoinTask.java	Thu Sep 23 17:33:40 2010 -0700
   122.2 +++ b/src/share/classes/java/util/concurrent/ForkJoinTask.java	Fri Sep 24 16:41:32 2010 -0700
   122.3 @@ -91,10 +91,7 @@
   122.4   * results of a task is {@link #join}, but there are several variants:
   122.5   * The {@link Future#get} methods support interruptible and/or timed
   122.6   * waits for completion and report results using {@code Future}
   122.7 - * conventions. Method {@link #helpJoin} enables callers to actively
   122.8 - * execute other tasks while awaiting joins, which is sometimes more
   122.9 - * efficient but only applies when all subtasks are known to be
  122.10 - * strictly tree-structured. Method {@link #invoke} is semantically
  122.11 + * conventions. Method {@link #invoke} is semantically
  122.12   * equivalent to {@code fork(); join()} but always attempts to begin
  122.13   * execution in the current thread. The "<em>quiet</em>" forms of
  122.14   * these methods do not extract results or report exceptions. These
  122.15 @@ -130,7 +127,7 @@
  122.16   * ForkJoinTasks (as may be determined using method {@link
  122.17   * #inForkJoinPool}).  Attempts to invoke them in other contexts
  122.18   * result in exceptions or errors, possibly including
  122.19 - * ClassCastException.
  122.20 + * {@code ClassCastException}.
  122.21   *
  122.22   * <p>Most base support methods are {@code final}, to prevent
  122.23   * overriding of implementations that are intrinsically tied to the
  122.24 @@ -152,9 +149,8 @@
  122.25   *
  122.26   * <p>This class provides {@code adapt} methods for {@link Runnable}
  122.27   * and {@link Callable}, that may be of use when mixing execution of
  122.28 - * {@code ForkJoinTasks} with other kinds of tasks. When all tasks
  122.29 - * are of this form, consider using a pool in
  122.30 - * {@linkplain ForkJoinPool#setAsyncMode async mode}.
  122.31 + * {@code ForkJoinTasks} with other kinds of tasks. When all tasks are
  122.32 + * of this form, consider using a pool constructed in <em>asyncMode</em>.
  122.33   *
  122.34   * <p>ForkJoinTasks are {@code Serializable}, which enables them to be
  122.35   * used in extensions such as remote execution frameworks. It is
  122.36 @@ -166,33 +162,43 @@
  122.37   */
  122.38  public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
  122.39  
  122.40 -    /**
  122.41 -     * Run control status bits packed into a single int to minimize
  122.42 -     * footprint and to ensure atomicity (via CAS).  Status is
  122.43 -     * initially zero, and takes on nonnegative values until
  122.44 -     * completed, upon which status holds COMPLETED. CANCELLED, or
  122.45 -     * EXCEPTIONAL, which use the top 3 bits.  Tasks undergoing
  122.46 -     * blocking waits by other threads have SIGNAL_MASK bits set --
  122.47 -     * bit 15 for external (nonFJ) waits, and the rest a count of
  122.48 -     * waiting FJ threads.  (This representation relies on
  122.49 -     * ForkJoinPool max thread limits). Completion of a stolen task
  122.50 -     * with SIGNAL_MASK bits set awakens waiter via notifyAll. Even
  122.51 -     * though suboptimal for some purposes, we use basic builtin
  122.52 -     * wait/notify to take advantage of "monitor inflation" in JVMs
  122.53 -     * that we would otherwise need to emulate to avoid adding further
  122.54 -     * per-task bookkeeping overhead. Note that bits 16-28 are
  122.55 -     * currently unused. Also value 0x80000000 is available as spare
  122.56 -     * completion value.
  122.57 +    /*
  122.58 +     * See the internal documentation of class ForkJoinPool for a
  122.59 +     * general implementation overview.  ForkJoinTasks are mainly
  122.60 +     * responsible for maintaining their "status" field amidst relays
  122.61 +     * to methods in ForkJoinWorkerThread and ForkJoinPool. The
  122.62 +     * methods of this class are more-or-less layered into (1) basic
  122.63 +     * status maintenance (2) execution and awaiting completion (3)
  122.64 +     * user-level methods that additionally report results. This is
  122.65 +     * sometimes hard to see because this file orders exported methods
  122.66 +     * in a way that flows well in javadocs. In particular, most
  122.67 +     * join mechanics are in method quietlyJoin, below.
  122.68       */
  122.69 +
  122.70 +    /*
  122.71 +     * The status field holds run control status bits packed into a
  122.72 +     * single int to minimize footprint and to ensure atomicity (via
  122.73 +     * CAS).  Status is initially zero, and takes on nonnegative
  122.74 +     * values until completed, upon which status holds value
  122.75 +     * NORMAL, CANCELLED, or EXCEPTIONAL. Tasks undergoing blocking
  122.76 +     * waits by other threads have the SIGNAL bit set.  Completion of
  122.77 +     * a stolen task with SIGNAL set awakens any waiters via
  122.78 +     * notifyAll. Even though suboptimal for some purposes, we use
  122.79 +     * basic builtin wait/notify to take advantage of "monitor
  122.80 +     * inflation" in JVMs that we would otherwise need to emulate to
  122.81 +     * avoid adding further per-task bookkeeping overhead.  We want
  122.82 +     * these monitors to be "fat", i.e., not use biasing or thin-lock
  122.83 +     * techniques, so use some odd coding idioms that tend to avoid
  122.84 +     * them.
  122.85 +     */
  122.86 +
  122.87 +    /** The run status of this task */
  122.88      volatile int status; // accessed directly by pool and workers
  122.89  
  122.90 -    static final int COMPLETION_MASK      = 0xe0000000;
  122.91 -    static final int NORMAL               = 0xe0000000; // == mask
  122.92 -    static final int CANCELLED            = 0xc0000000;
  122.93 -    static final int EXCEPTIONAL          = 0xa0000000;
  122.94 -    static final int SIGNAL_MASK          = 0x0000ffff;
  122.95 -    static final int INTERNAL_SIGNAL_MASK = 0x00007fff;
  122.96 -    static final int EXTERNAL_SIGNAL      = 0x00008000; // top bit of low word
  122.97 +    private static final int NORMAL      = -1;
  122.98 +    private static final int CANCELLED   = -2;
  122.99 +    private static final int EXCEPTIONAL = -3;
 122.100 +    private static final int SIGNAL      =  1;
 122.101  
 122.102      /**
 122.103       * Table of exceptions thrown by tasks, to enable reporting by
 122.104 @@ -206,176 +212,94 @@
 122.105          Collections.synchronizedMap
 122.106          (new WeakHashMap<ForkJoinTask<?>, Throwable>());
 122.107  
 122.108 -    // within-package utilities
 122.109 +    // Maintaining completion status
 122.110  
 122.111      /**
 122.112 -     * Gets current worker thread, or null if not a worker thread.
 122.113 -     */
 122.114 -    static ForkJoinWorkerThread getWorker() {
 122.115 -        Thread t = Thread.currentThread();
 122.116 -        return ((t instanceof ForkJoinWorkerThread) ?
 122.117 -                (ForkJoinWorkerThread) t : null);
 122.118 -    }
 122.119 -
 122.120 -    final boolean casStatus(int cmp, int val) {
 122.121 -        return UNSAFE.compareAndSwapInt(this, statusOffset, cmp, val);
 122.122 -    }
 122.123 -
 122.124 -    /**
 122.125 -     * Workaround for not being able to rethrow unchecked exceptions.
 122.126 -     */
 122.127 -    static void rethrowException(Throwable ex) {
 122.128 -        if (ex != null)
 122.129 -            UNSAFE.throwException(ex);
 122.130 -    }
 122.131 -
 122.132 -    // Setting completion status
 122.133 -
 122.134 -    /**
 122.135 -     * Marks completion and wakes up threads waiting to join this task.
 122.136 +     * Marks completion and wakes up threads waiting to join this task,
 122.137 +     * also clearing signal request bits.
 122.138       *
 122.139       * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
 122.140       */
 122.141 -    final void setCompletion(int completion) {
 122.142 -        ForkJoinPool pool = getPool();
 122.143 -        if (pool != null) {
 122.144 -            int s; // Clear signal bits while setting completion status
 122.145 -            do {} while ((s = status) >= 0 && !casStatus(s, completion));
 122.146 -
 122.147 -            if ((s & SIGNAL_MASK) != 0) {
 122.148 -                if ((s &= INTERNAL_SIGNAL_MASK) != 0)
 122.149 -                    pool.updateRunningCount(s);
 122.150 -                synchronized (this) { notifyAll(); }
 122.151 +    private void setCompletion(int completion) {
 122.152 +        int s;
 122.153 +        while ((s = status) >= 0) {
 122.154 +            if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) {
 122.155 +                if (s != 0)
 122.156 +                    synchronized (this) { notifyAll(); }
 122.157 +                break;
 122.158              }
 122.159          }
 122.160 -        else
 122.161 -            externallySetCompletion(completion);
 122.162 -    }
 122.163 -
 122.164 -    /**
 122.165 -     * Version of setCompletion for non-FJ threads.  Leaves signal
 122.166 -     * bits for unblocked threads to adjust, and always notifies.
 122.167 -     */
 122.168 -    private void externallySetCompletion(int completion) {
 122.169 -        int s;
 122.170 -        do {} while ((s = status) >= 0 &&
 122.171 -                     !casStatus(s, (s & SIGNAL_MASK) | completion));
 122.172 -        synchronized (this) { notifyAll(); }
 122.173 -    }
 122.174 -
 122.175 -    /**
 122.176 -     * Sets status to indicate normal completion.
 122.177 -     */
 122.178 -    final void setNormalCompletion() {
 122.179 -        // Try typical fast case -- single CAS, no signal, not already done.
 122.180 -        // Manually expand casStatus to improve chances of inlining it
 122.181 -        if (!UNSAFE.compareAndSwapInt(this, statusOffset, 0, NORMAL))
 122.182 -            setCompletion(NORMAL);
 122.183 -    }
 122.184 -
 122.185 -    // internal waiting and notification
 122.186 -
 122.187 -    /**
 122.188 -     * Performs the actual monitor wait for awaitDone.
 122.189 -     */
 122.190 -    private void doAwaitDone() {
 122.191 -        // Minimize lock bias and in/de-flation effects by maximizing
 122.192 -        // chances of waiting inside sync
 122.193 -        try {
 122.194 -            while (status >= 0)
 122.195 -                synchronized (this) { if (status >= 0) wait(); }
 122.196 -        } catch (InterruptedException ie) {
 122.197 -            onInterruptedWait();
 122.198 -        }
 122.199      }
 122.200  
 122.201      /**
 122.202 -     * Performs the actual timed monitor wait for awaitDone.
 122.203 +     * Records exception and sets exceptional completion.
 122.204 +     *
 122.205 +     * @return status on exit
 122.206       */
 122.207 -    private void doAwaitDone(long startTime, long nanos) {
 122.208 -        synchronized (this) {
 122.209 +    private void setExceptionalCompletion(Throwable rex) {
 122.210 +        exceptionMap.put(this, rex);
 122.211 +        setCompletion(EXCEPTIONAL);
 122.212 +    }
 122.213 +
 122.214 +    /**
 122.215 +     * Blocks a worker thread until completion. Called only by
 122.216 +     * pool. Currently unused -- pool-based waits use timeout
 122.217 +     * version below.
 122.218 +     */
 122.219 +    final void internalAwaitDone() {
 122.220 +        int s;         // the odd construction reduces lock bias effects
 122.221 +        while ((s = status) >= 0) {
 122.222              try {
 122.223 -                while (status >= 0) {
 122.224 -                    long nt = nanos - (System.nanoTime() - startTime);
 122.225 -                    if (nt <= 0)
 122.226 -                        break;
 122.227 -                    wait(nt / 1000000, (int) (nt % 1000000));
 122.228 +                synchronized(this) {
 122.229 +                    if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
 122.230 +                        wait();
 122.231                  }
 122.232              } catch (InterruptedException ie) {
 122.233 -                onInterruptedWait();
 122.234 +                cancelIfTerminating();
 122.235              }
 122.236          }
 122.237      }
 122.238  
 122.239 -    // Awaiting completion
 122.240 -
 122.241      /**
 122.242 -     * Sets status to indicate there is joiner, then waits for join,
 122.243 -     * surrounded with pool notifications.
 122.244 +     * Blocks a worker thread until completed or timed out.  Called
 122.245 +     * only by pool.
 122.246       *
 122.247 -     * @return status upon exit
 122.248 +     * @return status on exit
 122.249       */
 122.250 -    private int awaitDone(ForkJoinWorkerThread w,
 122.251 -                          boolean maintainParallelism) {
 122.252 -        ForkJoinPool pool = (w == null) ? null : w.pool;
 122.253 +    final int internalAwaitDone(long millis) {
 122.254          int s;
 122.255 -        while ((s = status) >= 0) {
 122.256 -            if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
 122.257 -                if (pool == null || !pool.preJoin(this, maintainParallelism))
 122.258 -                    doAwaitDone();
 122.259 -                if (((s = status) & INTERNAL_SIGNAL_MASK) != 0)
 122.260 -                    adjustPoolCountsOnUnblock(pool);
 122.261 -                break;
 122.262 +        if ((s = status) >= 0) {
 122.263 +            try {
 122.264 +                synchronized(this) {
 122.265 +                    if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
 122.266 +                        wait(millis, 0);
 122.267 +                }
 122.268 +            } catch (InterruptedException ie) {
 122.269 +                cancelIfTerminating();
 122.270              }
 122.271 +            s = status;
 122.272          }
 122.273          return s;
 122.274      }
 122.275  
 122.276      /**
 122.277 -     * Timed version of awaitDone
 122.278 -     *
 122.279 -     * @return status upon exit
 122.280 +     * Blocks a non-worker-thread until completion.
 122.281       */
 122.282 -    private int awaitDone(ForkJoinWorkerThread w, long nanos) {
 122.283 -        ForkJoinPool pool = (w == null) ? null : w.pool;
 122.284 +    private void externalAwaitDone() {
 122.285          int s;
 122.286          while ((s = status) >= 0) {
 122.287 -            if (casStatus(s, (pool == null) ? s|EXTERNAL_SIGNAL : s+1)) {
 122.288 -                long startTime = System.nanoTime();
 122.289 -                if (pool == null || !pool.preJoin(this, false))
 122.290 -                    doAwaitDone(startTime, nanos);
 122.291 -                if ((s = status) >= 0) {
 122.292 -                    adjustPoolCountsOnCancelledWait(pool);
 122.293 -                    s = status;
 122.294 -                }
 122.295 -                if (s < 0 && (s & INTERNAL_SIGNAL_MASK) != 0)
 122.296 -                    adjustPoolCountsOnUnblock(pool);
 122.297 -                break;
 122.298 -            }
 122.299 -        }
 122.300 -        return s;
 122.301 -    }
 122.302 -
 122.303 -    /**
 122.304 -     * Notifies pool that thread is unblocked. Called by signalled
 122.305 -     * threads when woken by non-FJ threads (which is atypical).
 122.306 -     */
 122.307 -    private void adjustPoolCountsOnUnblock(ForkJoinPool pool) {
 122.308 -        int s;
 122.309 -        do {} while ((s = status) < 0 && !casStatus(s, s & COMPLETION_MASK));
 122.310 -        if (pool != null && (s &= INTERNAL_SIGNAL_MASK) != 0)
 122.311 -            pool.updateRunningCount(s);
 122.312 -    }
 122.313 -
 122.314 -    /**
 122.315 -     * Notifies pool to adjust counts on cancelled or timed out wait.
 122.316 -     */
 122.317 -    private void adjustPoolCountsOnCancelledWait(ForkJoinPool pool) {
 122.318 -        if (pool != null) {
 122.319 -            int s;
 122.320 -            while ((s = status) >= 0 && (s & INTERNAL_SIGNAL_MASK) != 0) {
 122.321 -                if (casStatus(s, s - 1)) {
 122.322 -                    pool.updateRunningCount(1);
 122.323 +            synchronized(this) {
 122.324 +                if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)){
 122.325 +                    boolean interrupted = false;
 122.326 +                    while (status >= 0) {
 122.327 +                        try {
 122.328 +                            wait();
 122.329 +                        } catch (InterruptedException ie) {
 122.330 +                            interrupted = true;
 122.331 +                        }
 122.332 +                    }
 122.333 +                    if (interrupted)
 122.334 +                        Thread.currentThread().interrupt();
 122.335                      break;
 122.336                  }
 122.337              }
 122.338 @@ -383,153 +307,19 @@
 122.339      }
 122.340  
 122.341      /**
 122.342 -     * Handles interruptions during waits.
 122.343 -     */
 122.344 -    private void onInterruptedWait() {
 122.345 -        ForkJoinWorkerThread w = getWorker();
 122.346 -        if (w == null)
 122.347 -            Thread.currentThread().interrupt(); // re-interrupt
 122.348 -        else if (w.isTerminating())
 122.349 -            cancelIgnoringExceptions();
 122.350 -        // else if FJworker, ignore interrupt
 122.351 -    }
 122.352 -
 122.353 -    // Recording and reporting exceptions
 122.354 -
 122.355 -    private void setDoneExceptionally(Throwable rex) {
 122.356 -        exceptionMap.put(this, rex);
 122.357 -        setCompletion(EXCEPTIONAL);
 122.358 -    }
 122.359 -
 122.360 -    /**
 122.361 -     * Throws the exception associated with status s.
 122.362 -     *
 122.363 -     * @throws the exception
 122.364 -     */
 122.365 -    private void reportException(int s) {
 122.366 -        if ((s &= COMPLETION_MASK) < NORMAL) {
 122.367 -            if (s == CANCELLED)
 122.368 -                throw new CancellationException();
 122.369 -            else
 122.370 -                rethrowException(exceptionMap.get(this));
 122.371 -        }
 122.372 -    }
 122.373 -
 122.374 -    /**
 122.375 -     * Returns result or throws exception using j.u.c.Future conventions.
 122.376 -     * Only call when {@code isDone} known to be true or thread known
 122.377 -     * to be interrupted.
 122.378 -     */
 122.379 -    private V reportFutureResult()
 122.380 -        throws InterruptedException, ExecutionException {
 122.381 -        if (Thread.interrupted())
 122.382 -            throw new InterruptedException();
 122.383 -        int s = status & COMPLETION_MASK;
 122.384 -        if (s < NORMAL) {
 122.385 -            Throwable ex;
 122.386 -            if (s == CANCELLED)
 122.387 -                throw new CancellationException();
 122.388 -            if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
 122.389 -                throw new ExecutionException(ex);
 122.390 -        }
 122.391 -        return getRawResult();
 122.392 -    }
 122.393 -
 122.394 -    /**
 122.395 -     * Returns result or throws exception using j.u.c.Future conventions
 122.396 -     * with timeouts.
 122.397 -     */
 122.398 -    private V reportTimedFutureResult()
 122.399 -        throws InterruptedException, ExecutionException, TimeoutException {
 122.400 -        if (Thread.interrupted())
 122.401 -            throw new InterruptedException();
 122.402 -        Throwable ex;
 122.403 -        int s = status & COMPLETION_MASK;
 122.404 -        if (s == NORMAL)
 122.405 -            return getRawResult();
 122.406 -        else if (s == CANCELLED)
 122.407 -            throw new CancellationException();
 122.408 -        else if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
 122.409 -            throw new ExecutionException(ex);
 122.410 -        else
 122.411 -            throw new TimeoutException();
 122.412 -    }
 122.413 -
 122.414 -    // internal execution methods
 122.415 -
 122.416 -    /**
 122.417 -     * Calls exec, recording completion, and rethrowing exception if
 122.418 -     * encountered. Caller should normally check status before calling.
 122.419 -     *
 122.420 -     * @return true if completed normally
 122.421 -     */
 122.422 -    private boolean tryExec() {
 122.423 -        try { // try block must contain only call to exec
 122.424 -            if (!exec())
 122.425 -                return false;
 122.426 -        } catch (Throwable rex) {
 122.427 -            setDoneExceptionally(rex);
 122.428 -            rethrowException(rex);
 122.429 -            return false; // not reached
 122.430 -        }
 122.431 -        setNormalCompletion();
 122.432 -        return true;
 122.433 -    }
 122.434 -
 122.435 -    /**
 122.436 -     * Main execution method used by worker threads. Invokes
 122.437 -     * base computation unless already complete.
 122.438 +     * Unless done, calls exec and records status if completed, but
 122.439 +     * doesn't wait for completion otherwise. Primary execution method
 122.440 +     * for ForkJoinWorkerThread.
 122.441       */
 122.442      final void quietlyExec() {
 122.443 -        if (status >= 0) {
 122.444 -            try {
 122.445 -                if (!exec())
 122.446 -                    return;
 122.447 -            } catch (Throwable rex) {
 122.448 -                setDoneExceptionally(rex);
 122.449 +        try {
 122.450 +            if (status < 0 || !exec())
 122.451                  return;
 122.452 -            }
 122.453 -            setNormalCompletion();
 122.454 +        } catch (Throwable rex) {
 122.455 +            setExceptionalCompletion(rex);
 122.456 +            return;
 122.457          }
 122.458 -    }
 122.459 -
 122.460 -    /**
 122.461 -     * Calls exec(), recording but not rethrowing exception.
 122.462 -     * Caller should normally check status before calling.
 122.463 -     *
 122.464 -     * @return true if completed normally
 122.465 -     */
 122.466 -    private boolean tryQuietlyInvoke() {
 122.467 -        try {
 122.468 -            if (!exec())
 122.469 -                return false;
 122.470 -        } catch (Throwable rex) {
 122.471 -            setDoneExceptionally(rex);
 122.472 -            return false;
 122.473 -        }
 122.474 -        setNormalCompletion();
 122.475 -        return true;
 122.476 -    }
 122.477 -
 122.478 -    /**
 122.479 -     * Cancels, ignoring any exceptions it throws.
 122.480 -     */
 122.481 -    final void cancelIgnoringExceptions() {
 122.482 -        try {
 122.483 -            cancel(false);
 122.484 -        } catch (Throwable ignore) {
 122.485 -        }
 122.486 -    }
 122.487 -
 122.488 -    /**
 122.489 -     * Main implementation of helpJoin
 122.490 -     */
 122.491 -    private int busyJoin(ForkJoinWorkerThread w) {
 122.492 -        int s;
 122.493 -        ForkJoinTask<?> t;
 122.494 -        while ((s = status) >= 0 && (t = w.scanWhileJoining(this)) != null)
 122.495 -            t.quietlyExec();
 122.496 -        return (s >= 0) ? awaitDone(w, false) : s; // block if no work
 122.497 +        setCompletion(NORMAL); // must be outside try block
 122.498      }
 122.499  
 122.500      // public methods
 122.501 @@ -567,34 +357,41 @@
 122.502       * @return the computed result
 122.503       */
 122.504      public final V join() {
 122.505 -        ForkJoinWorkerThread w = getWorker();
 122.506 -        if (w == null || status < 0 || !w.unpushTask(this) || !tryExec())
 122.507 -            reportException(awaitDone(w, true));
 122.508 +        quietlyJoin();
 122.509 +        Throwable ex;
 122.510 +        if (status < NORMAL && (ex = getException()) != null)
 122.511 +            UNSAFE.throwException(ex);
 122.512          return getRawResult();
 122.513      }
 122.514  
 122.515      /**
 122.516       * Commences performing this task, awaits its completion if
 122.517 -     * necessary, and return its result, or throws an (unchecked)
 122.518 -     * exception if the underlying computation did so.
 122.519 +     * necessary, and returns its result, or throws an (unchecked)
 122.520 +     * {@code RuntimeException} or {@code Error} if the underlying
 122.521 +     * computation did so.
 122.522       *
 122.523       * @return the computed result
 122.524       */
 122.525      public final V invoke() {
 122.526 -        if (status >= 0 && tryExec())
 122.527 -            return getRawResult();
 122.528 -        else
 122.529 -            return join();
 122.530 +        quietlyInvoke();
 122.531 +        Throwable ex;
 122.532 +        if (status < NORMAL && (ex = getException()) != null)
 122.533 +            UNSAFE.throwException(ex);
 122.534 +        return getRawResult();
 122.535      }
 122.536  
 122.537      /**
 122.538       * Forks the given tasks, returning when {@code isDone} holds for
 122.539       * each task or an (unchecked) exception is encountered, in which
 122.540 -     * case the exception is rethrown.  If either task encounters an
 122.541 -     * exception, the other one may be, but is not guaranteed to be,
 122.542 -     * cancelled.  If both tasks throw an exception, then this method
 122.543 -     * throws one of them.  The individual status of each task may be
 122.544 -     * checked using {@link #getException()} and related methods.
 122.545 +     * case the exception is rethrown. If more than one task
 122.546 +     * encounters an exception, then this method throws any one of
 122.547 +     * these exceptions. If any task encounters an exception, the
 122.548 +     * other may be cancelled. However, the execution status of
 122.549 +     * individual tasks is not guaranteed upon exceptional return. The
 122.550 +     * status of each task may be obtained using {@link
 122.551 +     * #getException()} and related methods to check if they have been
 122.552 +     * cancelled, completed normally or exceptionally, or left
 122.553 +     * unprocessed.
 122.554       *
 122.555       * <p>This method may be invoked only from within {@code
 122.556       * ForkJoinTask} computations (as may be determined using method
 122.557 @@ -615,12 +412,14 @@
 122.558      /**
 122.559       * Forks the given tasks, returning when {@code isDone} holds for
 122.560       * each task or an (unchecked) exception is encountered, in which
 122.561 -     * case the exception is rethrown. If any task encounters an
 122.562 -     * exception, others may be, but are not guaranteed to be,
 122.563 -     * cancelled.  If more than one task encounters an exception, then
 122.564 -     * this method throws any one of these exceptions.  The individual
 122.565 -     * status of each task may be checked using {@link #getException()}
 122.566 -     * and related methods.
 122.567 +     * case the exception is rethrown. If more than one task
 122.568 +     * encounters an exception, then this method throws any one of
 122.569 +     * these exceptions. If any task encounters an exception, others
 122.570 +     * may be cancelled. However, the execution status of individual
 122.571 +     * tasks is not guaranteed upon exceptional return. The status of
 122.572 +     * each task may be obtained using {@link #getException()} and
 122.573 +     * related methods to check if they have been cancelled, completed
 122.574 +     * normally or exceptionally, or left unprocessed.
 122.575       *
 122.576       * <p>This method may be invoked only from within {@code
 122.577       * ForkJoinTask} computations (as may be determined using method
 122.578 @@ -644,7 +443,7 @@
 122.579                  t.fork();
 122.580              else {
 122.581                  t.quietlyInvoke();
 122.582 -                if (ex == null)
 122.583 +                if (ex == null && t.status < NORMAL)
 122.584                      ex = t.getException();
 122.585              }
 122.586          }
 122.587 @@ -655,26 +454,27 @@
 122.588                      t.cancel(false);
 122.589                  else {
 122.590                      t.quietlyJoin();
 122.591 -                    if (ex == null)
 122.592 +                    if (ex == null && t.status < NORMAL)
 122.593                          ex = t.getException();
 122.594                  }
 122.595              }
 122.596          }
 122.597          if (ex != null)
 122.598 -            rethrowException(ex);
 122.599 +            UNSAFE.throwException(ex);
 122.600      }
 122.601  
 122.602      /**
 122.603       * Forks all tasks in the specified collection, returning when
 122.604       * {@code isDone} holds for each task or an (unchecked) exception
 122.605 -     * is encountered.  If any task encounters an exception, others
 122.606 -     * may be, but are not guaranteed to be, cancelled.  If more than
 122.607 -     * one task encounters an exception, then this method throws any
 122.608 -     * one of these exceptions.  The individual status of each task
 122.609 -     * may be checked using {@link #getException()} and related
 122.610 -     * methods.  The behavior of this operation is undefined if the
 122.611 -     * specified collection is modified while the operation is in
 122.612 -     * progress.
 122.613 +     * is encountered, in which case the exception is rethrown. If
 122.614 +     * more than one task encounters an exception, then this method
 122.615 +     * throws any one of these exceptions. If any task encounters an
 122.616 +     * exception, others may be cancelled. However, the execution
 122.617 +     * status of individual tasks is not guaranteed upon exceptional
 122.618 +     * return. The status of each task may be obtained using {@link
 122.619 +     * #getException()} and related methods to check if they have been
 122.620 +     * cancelled, completed normally or exceptionally, or left
 122.621 +     * unprocessed.
 122.622       *
 122.623       * <p>This method may be invoked only from within {@code
 122.624       * ForkJoinTask} computations (as may be determined using method
 122.625 @@ -706,7 +506,7 @@
 122.626                  t.fork();
 122.627              else {
 122.628                  t.quietlyInvoke();
 122.629 -                if (ex == null)
 122.630 +                if (ex == null && t.status < NORMAL)
 122.631                      ex = t.getException();
 122.632              }
 122.633          }
 122.634 @@ -717,13 +517,13 @@
 122.635                      t.cancel(false);
 122.636                  else {
 122.637                      t.quietlyJoin();
 122.638 -                    if (ex == null)
 122.639 +                    if (ex == null && t.status < NORMAL)
 122.640                          ex = t.getException();
 122.641                  }
 122.642              }
 122.643          }
 122.644          if (ex != null)
 122.645 -            rethrowException(ex);
 122.646 +            UNSAFE.throwException(ex);
 122.647          return tasks;
 122.648      }
 122.649  
 122.650 @@ -753,7 +553,35 @@
 122.651       */
 122.652      public boolean cancel(boolean mayInterruptIfRunning) {
 122.653          setCompletion(CANCELLED);
 122.654 -        return (status & COMPLETION_MASK) == CANCELLED;
 122.655 +        return status == CANCELLED;
 122.656 +    }
 122.657 +
 122.658 +    /**
 122.659 +     * Cancels, ignoring any exceptions thrown by cancel. Used during
 122.660 +     * worker and pool shutdown. Cancel is spec'ed not to throw any
 122.661 +     * exceptions, but if it does anyway, we have no recourse during
 122.662 +     * shutdown, so guard against this case.
 122.663 +     */
 122.664 +    final void cancelIgnoringExceptions() {
 122.665 +        try {
 122.666 +            cancel(false);
 122.667 +        } catch (Throwable ignore) {
 122.668 +        }
 122.669 +    }
 122.670 +
 122.671 +    /**
 122.672 +     * Cancels if current thread is a terminating worker thread,
 122.673 +     * ignoring any exceptions thrown by cancel.
 122.674 +     */
 122.675 +    final void cancelIfTerminating() {
 122.676 +        Thread t = Thread.currentThread();
 122.677 +        if ((t instanceof ForkJoinWorkerThread) &&
 122.678 +            ((ForkJoinWorkerThread) t).isTerminating()) {
 122.679 +            try {
 122.680 +                cancel(false);
 122.681 +            } catch (Throwable ignore) {
 122.682 +            }
 122.683 +        }
 122.684      }
 122.685  
 122.686      public final boolean isDone() {
 122.687 @@ -761,7 +589,7 @@
 122.688      }
 122.689  
 122.690      public final boolean isCancelled() {
 122.691 -        return (status & COMPLETION_MASK) == CANCELLED;
 122.692 +        return status == CANCELLED;
 122.693      }
 122.694  
 122.695      /**
 122.696 @@ -770,7 +598,7 @@
 122.697       * @return {@code true} if this task threw an exception or was cancelled
 122.698       */
 122.699      public final boolean isCompletedAbnormally() {
 122.700 -        return (status & COMPLETION_MASK) < NORMAL;
 122.701 +        return status < NORMAL;
 122.702      }
 122.703  
 122.704      /**
 122.705 @@ -781,7 +609,7 @@
 122.706       * exception and was not cancelled
 122.707       */
 122.708      public final boolean isCompletedNormally() {
 122.709 -        return (status & COMPLETION_MASK) == NORMAL;
 122.710 +        return status == NORMAL;
 122.711      }
 122.712  
 122.713      /**
 122.714 @@ -792,7 +620,7 @@
 122.715       * @return the exception, or {@code null} if none
 122.716       */
 122.717      public final Throwable getException() {
 122.718 -        int s = status & COMPLETION_MASK;
 122.719 +        int s = status;
 122.720          return ((s >= NORMAL)    ? null :
 122.721                  (s == CANCELLED) ? new CancellationException() :
 122.722                  exceptionMap.get(this));
 122.723 @@ -813,20 +641,21 @@
 122.724       * thrown will be a {@code RuntimeException} with cause {@code ex}.
 122.725       */
 122.726      public void completeExceptionally(Throwable ex) {
 122.727 -        setDoneExceptionally((ex instanceof RuntimeException) ||
 122.728 -                             (ex instanceof Error) ? ex :
 122.729 -                             new RuntimeException(ex));
 122.730 +        setExceptionalCompletion((ex instanceof RuntimeException) ||
 122.731 +                                 (ex instanceof Error) ? ex :
 122.732 +                                 new RuntimeException(ex));
 122.733      }
 122.734  
 122.735      /**
 122.736       * Completes this task, and if not already aborted or cancelled,
 122.737 -     * returning a {@code null} result upon {@code join} and related
 122.738 -     * operations. This method may be used to provide results for
 122.739 -     * asynchronous tasks, or to provide alternative handling for
 122.740 -     * tasks that would not otherwise complete normally. Its use in
 122.741 -     * other situations is discouraged. This method is
 122.742 -     * overridable, but overridden versions must invoke {@code super}
 122.743 -     * implementation to maintain guarantees.
 122.744 +     * returning the given value as the result of subsequent
 122.745 +     * invocations of {@code join} and related operations. This method
 122.746 +     * may be used to provide results for asynchronous tasks, or to
 122.747 +     * provide alternative handling for tasks that would not otherwise
 122.748 +     * complete normally. Its use in other situations is
 122.749 +     * discouraged. This method is overridable, but overridden
 122.750 +     * versions must invoke {@code super} implementation to maintain
 122.751 +     * guarantees.
 122.752       *
 122.753       * @param value the result value for this task
 122.754       */
 122.755 @@ -834,97 +663,151 @@
 122.756          try {
 122.757              setRawResult(value);
 122.758          } catch (Throwable rex) {
 122.759 -            setDoneExceptionally(rex);
 122.760 +            setExceptionalCompletion(rex);
 122.761              return;
 122.762          }
 122.763 -        setNormalCompletion();
 122.764 +        setCompletion(NORMAL);
 122.765      }
 122.766  
 122.767      public final V get() throws InterruptedException, ExecutionException {
 122.768 -        ForkJoinWorkerThread w = getWorker();
 122.769 -        if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
 122.770 -            awaitDone(w, true);
 122.771 -        return reportFutureResult();
 122.772 +        quietlyJoin();
 122.773 +        if (Thread.interrupted())
 122.774 +            throw new InterruptedException();
 122.775 +        int s = status;
 122.776 +        if (s < NORMAL) {
 122.777 +            Throwable ex;
 122.778 +            if (s == CANCELLED)
 122.779 +                throw new CancellationException();
 122.780 +            if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
 122.781 +                throw new ExecutionException(ex);
 122.782 +        }
 122.783 +        return getRawResult();
 122.784      }
 122.785  
 122.786      public final V get(long timeout, TimeUnit unit)
 122.787          throws InterruptedException, ExecutionException, TimeoutException {
 122.788 +        Thread t = Thread.currentThread();
 122.789 +        ForkJoinPool pool;
 122.790 +        if (t instanceof ForkJoinWorkerThread) {
 122.791 +            ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
 122.792 +            if (status >= 0 && w.unpushTask(this))
 122.793 +                quietlyExec();
 122.794 +            pool = w.pool;
 122.795 +        }
 122.796 +        else
 122.797 +            pool = null;
 122.798 +        /*
 122.799 +         * Timed wait loop intermixes cases for FJ (pool != null) and
 122.800 +         * non FJ threads. For FJ, decrement pool count but don't try
 122.801 +         * for replacement; increment count on completion. For non-FJ,
 122.802 +         * deal with interrupts. This is messy, but a little less so
 122.803 +         * than is splitting the FJ and nonFJ cases.
 122.804 +         */
 122.805 +        boolean interrupted = false;
 122.806 +        boolean dec = false; // true if pool count decremented
 122.807          long nanos = unit.toNanos(timeout);
 122.808 -        ForkJoinWorkerThread w = getWorker();
 122.809 -        if (w == null || status < 0 || !w.unpushTask(this) || !tryQuietlyInvoke())
 122.810 -            awaitDone(w, nanos);
 122.811 -        return reportTimedFutureResult();
 122.812 -    }
 122.813 -
 122.814 -    /**
 122.815 -     * Possibly executes other tasks until this task {@link #isDone is
 122.816 -     * done}, then returns the result of the computation.  This method
 122.817 -     * may be more efficient than {@code join}, but is only applicable
 122.818 -     * when there are no potential dependencies between continuation
 122.819 -     * of the current task and that of any other task that might be
 122.820 -     * executed while helping. (This usually holds for pure
 122.821 -     * divide-and-conquer tasks).
 122.822 -     *
 122.823 -     * <p>This method may be invoked only from within {@code
 122.824 -     * ForkJoinTask} computations (as may be determined using method
 122.825 -     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
 122.826 -     * result in exceptions or errors, possibly including {@code
 122.827 -     * ClassCastException}.
 122.828 -     *
 122.829 -     * @return the computed result
 122.830 -     */
 122.831 -    public final V helpJoin() {
 122.832 -        ForkJoinWorkerThread w = (ForkJoinWorkerThread) Thread.currentThread();
 122.833 -        if (status < 0 || !w.unpushTask(this) || !tryExec())
 122.834 -            reportException(busyJoin(w));
 122.835 +        for (;;) {
 122.836 +            if (pool == null && Thread.interrupted()) {
 122.837 +                interrupted = true;
 122.838 +                break;
 122.839 +            }
 122.840 +            int s = status;
 122.841 +            if (s < 0)
 122.842 +                break;
 122.843 +            if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)) {
 122.844 +                long startTime = System.nanoTime();
 122.845 +                long nt; // wait time
 122.846 +                while (status >= 0 &&
 122.847 +                       (nt = nanos - (System.nanoTime() - startTime)) > 0) {
 122.848 +                    if (pool != null && !dec)
 122.849 +                        dec = pool.tryDecrementRunningCount();
 122.850 +                    else {
 122.851 +                        long ms = nt / 1000000;
 122.852 +                        int ns = (int) (nt % 1000000);
 122.853 +                        try {
 122.854 +                            synchronized(this) {
 122.855 +                                if (status >= 0)
 122.856 +                                    wait(ms, ns);
 122.857 +                            }
 122.858 +                        } catch (InterruptedException ie) {
 122.859 +                            if (pool != null)
 122.860 +                                cancelIfTerminating();
 122.861 +                            else {
 122.862 +                                interrupted = true;
 122.863 +                                break;
 122.864 +                            }
 122.865 +                        }
 122.866 +                    }
 122.867 +                }
 122.868 +                break;
 122.869 +            }
 122.870 +        }
 122.871 +        if (pool != null && dec)
 122.872 +            pool.incrementRunningCount();
 122.873 +        if (interrupted)
 122.874 +            throw new InterruptedException();
 122.875 +        int es = status;
 122.876 +        if (es != NORMAL) {
 122.877 +            Throwable ex;
 122.878 +            if (es == CANCELLED)
 122.879 +                throw new CancellationException();
 122.880 +            if (es == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
 122.881 +                throw new ExecutionException(ex);
 122.882 +            throw new TimeoutException();
 122.883 +        }
 122.884          return getRawResult();
 122.885      }
 122.886  
 122.887      /**
 122.888 -     * Possibly executes other tasks until this task {@link #isDone is
 122.889 -     * done}.  This method may be useful when processing collections
 122.890 -     * of tasks when some have been cancelled or otherwise known to
 122.891 -     * have aborted.
 122.892 -     *
 122.893 -     * <p>This method may be invoked only from within {@code
 122.894 -     * ForkJoinTask} computations (as may be determined using method
 122.895 -     * {@link #inForkJoinPool}).  Attempts to invoke in other contexts
 122.896 -     * result in exceptions or errors, possibly including {@code
 122.897 -     * ClassCastException}.
 122.898 -     */
 122.899 -    public final void quietlyHelpJoin() {
 122.900 -        if (status >= 0) {
 122.901 -            ForkJoinWorkerThread w =
 122.902 -                (ForkJoinWorkerThread) Thread.currentThread();
 122.903 -            if (!w.unpushTask(this) || !tryQuietlyInvoke())
 122.904 -                busyJoin(w);
 122.905 -        }
 122.906 -    }
 122.907 -
 122.908 -    /**
 122.909 -     * Joins this task, without returning its result or throwing an
 122.910 +     * Joins this task, without returning its result or throwing its
 122.911       * exception. This method may be useful when processing
 122.912       * collections of tasks when some have been cancelled or otherwise
 122.913       * known to have aborted.
 122.914       */
 122.915      public final void quietlyJoin() {
 122.916 -        if (status >= 0) {
 122.917 -            ForkJoinWorkerThread w = getWorker();
 122.918 -            if (w == null || !w.unpushTask(this) || !tryQuietlyInvoke())
 122.919 -                awaitDone(w, true);
 122.920 +        Thread t;
 122.921 +        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
 122.922 +            ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
 122.923 +            if (status >= 0) {
 122.924 +                if (w.unpushTask(this)) {
 122.925 +                    boolean completed;
 122.926 +                    try {
 122.927 +                        completed = exec();
 122.928 +                    } catch (Throwable rex) {
 122.929 +                        setExceptionalCompletion(rex);
 122.930 +                        return;
 122.931 +                    }
 122.932 +                    if (completed) {
 122.933 +                        setCompletion(NORMAL);
 122.934 +                        return;
 122.935 +                    }
 122.936 +                }
 122.937 +                w.joinTask(this);
 122.938 +            }
 122.939          }
 122.940 +        else
 122.941 +            externalAwaitDone();
 122.942      }
 122.943  
 122.944      /**
 122.945       * Commences performing this task and awaits its completion if
 122.946 -     * necessary, without returning its result or throwing an
 122.947 -     * exception. This method may be useful when processing
 122.948 -     * collections of tasks when some have been cancelled or otherwise
 122.949 -     * known to have aborted.
 122.950 +     * necessary, without returning its result or throwing its
 122.951 +     * exception.
 122.952       */
 122.953      public final void quietlyInvoke() {
 122.954 -        if (status >= 0 && !tryQuietlyInvoke())
 122.955 -            quietlyJoin();
 122.956 +        if (status >= 0) {
 122.957 +            boolean completed;
 122.958 +            try {
 122.959 +                completed = exec();
 122.960 +            } catch (Throwable rex) {
 122.961 +                setExceptionalCompletion(rex);
 122.962 +                return;
 122.963 +            }
 122.964 +            if (completed)
 122.965 +                setCompletion(NORMAL);
 122.966 +            else
 122.967 +                quietlyJoin();
 122.968 +        }
 122.969      }
 122.970  
 122.971      /**
 122.972 @@ -956,7 +839,7 @@
 122.973       * pre-constructed trees of subtasks in loops.
 122.974       */
 122.975      public void reinitialize() {
 122.976 -        if ((status & COMPLETION_MASK) == EXCEPTIONAL)
 122.977 +        if (status == EXCEPTIONAL)
 122.978              exceptionMap.remove(this);
 122.979          status = 0;
 122.980      }
 122.981 @@ -1246,7 +1129,7 @@
 122.982      private static final long serialVersionUID = -7721805057305804111L;
 122.983  
 122.984      /**
 122.985 -     * Saves the state to a stream.
 122.986 +     * Saves the state to a stream (that is, serializes it).
 122.987       *
 122.988       * @serialData the current run status and the exception thrown
 122.989       * during execution, or {@code null} if none
 122.990 @@ -1259,18 +1142,16 @@
 122.991      }
 122.992  
 122.993      /**
 122.994 -     * Reconstitutes the instance from a stream.
 122.995 +     * Reconstitutes the instance from a stream (that is, deserializes it).
 122.996       *
 122.997       * @param s the stream
 122.998       */
 122.999      private void readObject(java.io.ObjectInputStream s)
122.1000          throws java.io.IOException, ClassNotFoundException {
122.1001          s.defaultReadObject();
122.1002 -        status &= ~INTERNAL_SIGNAL_MASK; // clear internal signal counts
122.1003 -        status |= EXTERNAL_SIGNAL; // conservatively set external signal
122.1004          Object ex = s.readObject();
122.1005          if (ex != null)
122.1006 -            setDoneExceptionally((Throwable) ex);
122.1007 +            setExceptionalCompletion((Throwable) ex);
122.1008      }
122.1009  
122.1010      // Unsafe mechanics
   123.1 --- a/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Thu Sep 23 17:33:40 2010 -0700
   123.2 +++ b/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Fri Sep 24 16:41:32 2010 -0700
   123.3 @@ -35,7 +35,9 @@
   123.4  
   123.5  package java.util.concurrent;
   123.6  
   123.7 +import java.util.Random;
   123.8  import java.util.Collection;
   123.9 +import java.util.concurrent.locks.LockSupport;
  123.10  
  123.11  /**
  123.12   * A thread managed by a {@link ForkJoinPool}.  This class is
  123.13 @@ -52,46 +54,55 @@
  123.14   */
  123.15  public class ForkJoinWorkerThread extends Thread {
  123.16      /*
  123.17 -     * Algorithm overview:
  123.18 +     * Overview:
  123.19       *
  123.20 -     * 1. Work-Stealing: Work-stealing queues are special forms of
  123.21 -     * Deques that support only three of the four possible
  123.22 -     * end-operations -- push, pop, and deq (aka steal), and only do
  123.23 -     * so under the constraints that push and pop are called only from
  123.24 -     * the owning thread, while deq may be called from other threads.
  123.25 -     * (If you are unfamiliar with them, you probably want to read
  123.26 -     * Herlihy and Shavit's book "The Art of Multiprocessor
  123.27 -     * programming", chapter 16 describing these in more detail before
  123.28 -     * proceeding.)  The main work-stealing queue design is roughly
  123.29 -     * similar to "Dynamic Circular Work-Stealing Deque" by David
  123.30 -     * Chase and Yossi Lev, SPAA 2005
  123.31 -     * (http://research.sun.com/scalable/pubs/index.html).  The main
  123.32 -     * difference ultimately stems from gc requirements that we null
  123.33 -     * out taken slots as soon as we can, to maintain as small a
  123.34 -     * footprint as possible even in programs generating huge numbers
  123.35 -     * of tasks. To accomplish this, we shift the CAS arbitrating pop
  123.36 -     * vs deq (steal) from being on the indices ("base" and "sp") to
  123.37 -     * the slots themselves (mainly via method "casSlotNull()"). So,
  123.38 -     * both a successful pop and deq mainly entail CAS'ing a non-null
  123.39 -     * slot to null.  Because we rely on CASes of references, we do
  123.40 -     * not need tag bits on base or sp.  They are simple ints as used
  123.41 -     * in any circular array-based queue (see for example ArrayDeque).
  123.42 -     * Updates to the indices must still be ordered in a way that
  123.43 -     * guarantees that (sp - base) > 0 means the queue is empty, but
  123.44 -     * otherwise may err on the side of possibly making the queue
  123.45 -     * appear nonempty when a push, pop, or deq have not fully
  123.46 -     * committed. Note that this means that the deq operation,
  123.47 -     * considered individually, is not wait-free. One thief cannot
  123.48 -     * successfully continue until another in-progress one (or, if
  123.49 -     * previously empty, a push) completes.  However, in the
  123.50 -     * aggregate, we ensure at least probabilistic
  123.51 -     * non-blockingness. If an attempted steal fails, a thief always
  123.52 -     * chooses a different random victim target to try next. So, in
  123.53 -     * order for one thief to progress, it suffices for any
  123.54 -     * in-progress deq or new push on any empty queue to complete. One
  123.55 -     * reason this works well here is that apparently-nonempty often
  123.56 -     * means soon-to-be-stealable, which gives threads a chance to
  123.57 -     * activate if necessary before stealing (see below).
  123.58 +     * ForkJoinWorkerThreads are managed by ForkJoinPools and perform
  123.59 +     * ForkJoinTasks. This class includes bookkeeping in support of
  123.60 +     * worker activation, suspension, and lifecycle control described
  123.61 +     * in more detail in the internal documentation of class
  123.62 +     * ForkJoinPool. And as described further below, this class also
  123.63 +     * includes special-cased support for some ForkJoinTask
  123.64 +     * methods. But the main mechanics involve work-stealing:
  123.65 +     *
  123.66 +     * Work-stealing queues are special forms of Deques that support
  123.67 +     * only three of the four possible end-operations -- push, pop,
  123.68 +     * and deq (aka steal), under the further constraints that push
  123.69 +     * and pop are called only from the owning thread, while deq may
  123.70 +     * be called from other threads.  (If you are unfamiliar with
  123.71 +     * them, you probably want to read Herlihy and Shavit's book "The
  123.72 +     * Art of Multiprocessor programming", chapter 16 describing these
  123.73 +     * in more detail before proceeding.)  The main work-stealing
  123.74 +     * queue design is roughly similar to those in the papers "Dynamic
  123.75 +     * Circular Work-Stealing Deque" by Chase and Lev, SPAA 2005
  123.76 +     * (http://research.sun.com/scalable/pubs/index.html) and
  123.77 +     * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
  123.78 +     * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
  123.79 +     * The main differences ultimately stem from gc requirements that
  123.80 +     * we null out taken slots as soon as we can, to maintain as small
  123.81 +     * a footprint as possible even in programs generating huge
  123.82 +     * numbers of tasks. To accomplish this, we shift the CAS
  123.83 +     * arbitrating pop vs deq (steal) from being on the indices
  123.84 +     * ("base" and "sp") to the slots themselves (mainly via method
  123.85 +     * "casSlotNull()"). So, both a successful pop and deq mainly
  123.86 +     * entail a CAS of a slot from non-null to null.  Because we rely
  123.87 +     * on CASes of references, we do not need tag bits on base or sp.
  123.88 +     * They are simple ints as used in any circular array-based queue
  123.89 +     * (see for example ArrayDeque).  Updates to the indices must
  123.90 +     * still be ordered in a way that guarantees that sp == base means
  123.91 +     * the queue is empty, but otherwise may err on the side of
  123.92 +     * possibly making the queue appear nonempty when a push, pop, or
  123.93 +     * deq have not fully committed. Note that this means that the deq
  123.94 +     * operation, considered individually, is not wait-free. One thief
  123.95 +     * cannot successfully continue until another in-progress one (or,
  123.96 +     * if previously empty, a push) completes.  However, in the
  123.97 +     * aggregate, we ensure at least probabilistic non-blockingness.
  123.98 +     * If an attempted steal fails, a thief always chooses a different
  123.99 +     * random victim target to try next. So, in order for one thief to
 123.100 +     * progress, it suffices for any in-progress deq or new push on
 123.101 +     * any empty queue to complete. One reason this works well here is
 123.102 +     * that apparently-nonempty often means soon-to-be-stealable,
 123.103 +     * which gives threads a chance to set activation status if
 123.104 +     * necessary before stealing.
 123.105       *
 123.106       * This approach also enables support for "async mode" where local
 123.107       * task processing is in FIFO, not LIFO order; simply by using a
 123.108 @@ -99,24 +110,54 @@
 123.109       * by the ForkJoinPool).  This allows use in message-passing
 123.110       * frameworks in which tasks are never joined.
 123.111       *
 123.112 -     * Efficient implementation of this approach currently relies on
 123.113 -     * an uncomfortable amount of "Unsafe" mechanics. To maintain
 123.114 +     * When a worker would otherwise be blocked waiting to join a
 123.115 +     * task, it first tries a form of linear helping: Each worker
 123.116 +     * records (in field currentSteal) the most recent task it stole
 123.117 +     * from some other worker. Plus, it records (in field currentJoin)
 123.118 +     * the task it is currently actively joining. Method joinTask uses
 123.119 +     * these markers to try to find a worker to help (i.e., steal back
 123.120 +     * a task from and execute it) that could hasten completion of the
 123.121 +     * actively joined task. In essence, the joiner executes a task
 123.122 +     * that would be on its own local deque had the to-be-joined task
 123.123 +     * not been stolen. This may be seen as a conservative variant of
 123.124 +     * the approach in Wagner & Calder "Leapfrogging: a portable
 123.125 +     * technique for implementing efficient futures" SIGPLAN Notices,
 123.126 +     * 1993 (http://portal.acm.org/citation.cfm?id=155354). It differs
 123.127 +     * in that: (1) We only maintain dependency links across workers
 123.128 +     * upon steals, rather than use per-task bookkeeping.  This may
 123.129 +     * require a linear scan of workers array to locate stealers, but
 123.130 +     * usually doesn't because stealers leave hints (that may become
 123.131 +     * stale/wrong) of where to locate them. This isolates cost to
 123.132 +     * when it is needed, rather than adding to per-task overhead.
 123.133 +     * (2) It is "shallow", ignoring nesting and potentially cyclic
 123.134 +     * mutual steals.  (3) It is intentionally racy: field currentJoin
 123.135 +     * is updated only while actively joining, which means that we
 123.136 +     * miss links in the chain during long-lived tasks, GC stalls etc
 123.137 +     * (which is OK since blocking in such cases is usually a good
 123.138 +     * idea).  (4) We bound the number of attempts to find work (see
 123.139 +     * MAX_HELP_DEPTH) and fall back to suspending the worker and if
 123.140 +     * necessary replacing it with a spare (see
 123.141 +     * ForkJoinPool.awaitJoin).
 123.142 +     *
 123.143 +     * Efficient implementation of these algorithms currently relies
 123.144 +     * on an uncomfortable amount of "Unsafe" mechanics. To maintain
 123.145       * correct orderings, reads and writes of variable base require
 123.146 -     * volatile ordering.  Variable sp does not require volatile write
 123.147 -     * but needs cheaper store-ordering on writes.  Because they are
 123.148 -     * protected by volatile base reads, reads of the queue array and
 123.149 -     * its slots do not need volatile load semantics, but writes (in
 123.150 -     * push) require store order and CASes (in pop and deq) require
 123.151 -     * (volatile) CAS semantics.  (See "Idempotent work stealing" by
 123.152 -     * Michael, Saraswat, and Vechev, PPoPP 2009
 123.153 -     * http://portal.acm.org/citation.cfm?id=1504186 for an algorithm
 123.154 -     * with similar properties, but without support for nulling
 123.155 -     * slots.)  Since these combinations aren't supported using
 123.156 -     * ordinary volatiles, the only way to accomplish these
 123.157 -     * efficiently is to use direct Unsafe calls. (Using external
 123.158 -     * AtomicIntegers and AtomicReferenceArrays for the indices and
 123.159 -     * array is significantly slower because of memory locality and
 123.160 -     * indirection effects.)
 123.161 +     * volatile ordering.  Variable sp does not require volatile
 123.162 +     * writes but still needs store-ordering, which we accomplish by
 123.163 +     * pre-incrementing sp before filling the slot with an ordered
 123.164 +     * store.  (Pre-incrementing also enables backouts used in
 123.165 +     * joinTask.)  Because they are protected by volatile base reads,
 123.166 +     * reads of the queue array and its slots by other threads do not
 123.167 +     * need volatile load semantics, but writes (in push) require
 123.168 +     * store order and CASes (in pop and deq) require (volatile) CAS
 123.169 +     * semantics.  (Michael, Saraswat, and Vechev's algorithm has
 123.170 +     * similar properties, but without support for nulling slots.)
 123.171 +     * Since these combinations aren't supported using ordinary
 123.172 +     * volatiles, the only way to accomplish these efficiently is to
 123.173 +     * use direct Unsafe calls. (Using external AtomicIntegers and
 123.174 +     * AtomicReferenceArrays for the indices and array is
 123.175 +     * significantly slower because of memory locality and indirection
 123.176 +     * effects.)
 123.177       *
 123.178       * Further, performance on most platforms is very sensitive to
 123.179       * placement and sizing of the (resizable) queue array.  Even
 123.180 @@ -124,56 +165,45 @@
 123.181       * initial size must be large enough to counteract cache
 123.182       * contention effects across multiple queues (especially in the
 123.183       * presence of GC cardmarking). Also, to improve thread-locality,
 123.184 -     * queues are currently initialized immediately after the thread
 123.185 -     * gets the initial signal to start processing tasks.  However,
 123.186 -     * all queue-related methods except pushTask are written in a way
 123.187 -     * that allows them to instead be lazily allocated and/or disposed
 123.188 -     * of when empty. All together, these low-level implementation
 123.189 -     * choices produce as much as a factor of 4 performance
 123.190 -     * improvement compared to naive implementations, and enable the
 123.191 -     * processing of billions of tasks per second, sometimes at the
 123.192 -     * expense of ugliness.
 123.193 -     *
 123.194 -     * 2. Run control: The primary run control is based on a global
 123.195 -     * counter (activeCount) held by the pool. It uses an algorithm
 123.196 -     * similar to that in Herlihy and Shavit section 17.6 to cause
 123.197 -     * threads to eventually block when all threads declare they are
 123.198 -     * inactive. For this to work, threads must be declared active
 123.199 -     * when executing tasks, and before stealing a task. They must be
 123.200 -     * inactive before blocking on the Pool Barrier (awaiting a new
 123.201 -     * submission or other Pool event). In between, there is some free
 123.202 -     * play which we take advantage of to avoid contention and rapid
 123.203 -     * flickering of the global activeCount: If inactive, we activate
 123.204 -     * only if a victim queue appears to be nonempty (see above).
 123.205 -     * Similarly, a thread tries to inactivate only after a full scan
 123.206 -     * of other threads.  The net effect is that contention on
 123.207 -     * activeCount is rarely a measurable performance issue. (There
 123.208 -     * are also a few other cases where we scan for work rather than
 123.209 -     * retry/block upon contention.)
 123.210 -     *
 123.211 -     * 3. Selection control. We maintain policy of always choosing to
 123.212 -     * run local tasks rather than stealing, and always trying to
 123.213 -     * steal tasks before trying to run a new submission. All steals
 123.214 -     * are currently performed in randomly-chosen deq-order. It may be
 123.215 -     * worthwhile to bias these with locality / anti-locality
 123.216 -     * information, but doing this well probably requires more
 123.217 -     * lower-level information from JVMs than currently provided.
 123.218 +     * queues are initialized after starting.  All together, these
 123.219 +     * low-level implementation choices produce as much as a factor of
 123.220 +     * 4 performance improvement compared to naive implementations,
 123.221 +     * and enable the processing of billions of tasks per second,
 123.222 +     * sometimes at the expense of ugliness.
 123.223       */
 123.224  
 123.225      /**
 123.226 +     * Generator for initial random seeds for random victim
 123.227 +     * selection. This is used only to create initial seeds. Random
 123.228 +     * steals use a cheaper xorshift generator per steal attempt. We
 123.229 +     * expect only rare contention on seedGenerator, so just use a
 123.230 +     * plain Random.
 123.231 +     */
 123.232 +    private static final Random seedGenerator = new Random();
 123.233 +
 123.234 +    /**
 123.235 +     * The maximum stolen->joining link depth allowed in helpJoinTask.
 123.236 +     * Depths for legitimate chains are unbounded, but we use a fixed
 123.237 +     * constant to avoid (otherwise unchecked) cycles and bound
 123.238 +     * staleness of traversal parameters at the expense of sometimes
 123.239 +     * blocking when we could be helping.
 123.240 +     */
 123.241 +    private static final int MAX_HELP_DEPTH = 8;
 123.242 +
 123.243 +    /**
 123.244       * Capacity of work-stealing queue array upon initialization.
 123.245 -     * Must be a power of two. Initial size must be at least 2, but is
 123.246 +     * Must be a power of two. Initial size must be at least 4, but is
 123.247       * padded to minimize cache effects.
 123.248       */
 123.249      private static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
 123.250  
 123.251      /**
 123.252       * Maximum work-stealing queue array size.  Must be less than or
 123.253 -     * equal to 1 << 28 to ensure lack of index wraparound. (This
 123.254 -     * is less than usual bounds, because we need leftshift by 3
 123.255 -     * to be in int range).
 123.256 +     * equal to 1 << (31 - width of array entry) to ensure lack of
 123.257 +     * index wraparound. The value is set in the static block
 123.258 +     * at the end of this file after obtaining width.
 123.259       */
 123.260 -    private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 28;
 123.261 +    private static final int MAXIMUM_QUEUE_CAPACITY;
 123.262  
 123.263      /**
 123.264       * The pool this thread works in. Accessed directly by ForkJoinTask.
 123.265 @@ -182,65 +212,118 @@
 123.266  
 123.267      /**
 123.268       * The work-stealing queue array. Size must be a power of two.
 123.269 -     * Initialized when thread starts, to improve memory locality.
 123.270 +     * Initialized in onStart, to improve memory locality.
 123.271       */
 123.272      private ForkJoinTask<?>[] queue;
 123.273  
 123.274      /**
 123.275 -     * Index (mod queue.length) of next queue slot to push to or pop
 123.276 -     * from. It is written only by owner thread, via ordered store.
 123.277 -     * Both sp and base are allowed to wrap around on overflow, but
 123.278 -     * (sp - base) still estimates size.
 123.279 -     */
 123.280 -    private volatile int sp;
 123.281 -
 123.282 -    /**
 123.283       * Index (mod queue.length) of least valid queue slot, which is
 123.284       * always the next position to steal from if nonempty.
 123.285       */
 123.286      private volatile int base;
 123.287  
 123.288      /**
 123.289 -     * Activity status. When true, this worker is considered active.
 123.290 -     * Must be false upon construction. It must be true when executing
 123.291 -     * tasks, and BEFORE stealing a task. It must be false before
 123.292 -     * calling pool.sync.
 123.293 +     * Index (mod queue.length) of next queue slot to push to or pop
 123.294 +     * from. It is written only by owner thread, and accessed by other
 123.295 +     * threads only after reading (volatile) base.  Both sp and base
 123.296 +     * are allowed to wrap around on overflow, but (sp - base) still
 123.297 +     * estimates size.
 123.298       */
 123.299 -    private boolean active;
 123.300 +    private int sp;
 123.301  
 123.302      /**
 123.303 -     * Run state of this worker. Supports simple versions of the usual
 123.304 -     * shutdown/shutdownNow control.
 123.305 +     * The index of most recent stealer, used as a hint to avoid
 123.306 +     * traversal in method helpJoinTask. This is only a hint because a
 123.307 +     * worker might have had multiple steals and this only holds one
 123.308 +     * of them (usually the most current). Declared non-volatile,
 123.309 +     * relying on other prevailing sync to keep reasonably current.
 123.310       */
 123.311 -    private volatile int runState;
 123.312 +    private int stealHint;
 123.313 +
 123.314 +    /**
 123.315 +     * Run state of this worker. In addition to the usual run levels,
 123.316 +     * tracks if this worker is suspended as a spare, and if it was
 123.317 +     * killed (trimmed) while suspended. However, "active" status is
 123.318 +     * maintained separately and modified only in conjunction with
 123.319 +     * CASes of the pool's runState (which are currently sadly
 123.320 +     * manually inlined for performance.)  Accessed directly by pool
 123.321 +     * to simplify checks for normal (zero) status.
 123.322 +     */
 123.323 +    volatile int runState;
 123.324 +
 123.325 +    private static final int TERMINATING = 0x01;
 123.326 +    private static final int TERMINATED  = 0x02;
 123.327 +    private static final int SUSPENDED   = 0x04; // inactive spare
 123.328 +    private static final int TRIMMED     = 0x08; // killed while suspended
 123.329 +
 123.330 +    /**
 123.331 +     * Number of steals. Directly accessed (and reset) by
 123.332 +     * pool.tryAccumulateStealCount when idle.
 123.333 +     */
 123.334 +    int stealCount;
 123.335  
 123.336      /**
 123.337       * Seed for random number generator for choosing steal victims.
 123.338 -     * Uses Marsaglia xorshift. Must be nonzero upon initialization.
 123.339 +     * Uses Marsaglia xorshift. Must be initialized as nonzero.
 123.340       */
 123.341      private int seed;
 123.342  
 123.343      /**
 123.344 -     * Number of steals, transferred to pool when idle
 123.345 +     * Activity status. When true, this worker is considered active.
 123.346 +     * Accessed directly by pool.  Must be false upon construction.
 123.347       */
 123.348 -    private int stealCount;
 123.349 +    boolean active;
 123.350 +
 123.351 +    /**
 123.352 +     * True if use local fifo, not default lifo, for local polling.
 123.353 +     * Shadows value from ForkJoinPool.
 123.354 +     */
 123.355 +    private final boolean locallyFifo;
 123.356  
 123.357      /**
 123.358       * Index of this worker in pool array. Set once by pool before
 123.359 -     * running, and accessed directly by pool during cleanup etc.
 123.360 +     * running, and accessed directly by pool to locate this worker in
 123.361 +     * its workers array.
 123.362       */
 123.363      int poolIndex;
 123.364  
 123.365      /**
 123.366 -     * The last barrier event waited for. Accessed in pool callback
 123.367 -     * methods, but only by current thread.
 123.368 +     * The last pool event waited for. Accessed only by pool in
 123.369 +     * callback methods invoked within this thread.
 123.370       */
 123.371 -    long lastEventCount;
 123.372 +    int lastEventCount;
 123.373  
 123.374      /**
 123.375 -     * True if use local fifo, not default lifo, for local polling
 123.376 +     * Encoded index and event count of next event waiter. Accessed
 123.377 +     * only by ForkJoinPool for managing event waiters.
 123.378       */
 123.379 -    private boolean locallyFifo;
 123.380 +    volatile long nextWaiter;
 123.381 +
 123.382 +    /**
 123.383 +     * Number of times this thread suspended as spare. Accessed only
 123.384 +     * by pool.
 123.385 +     */
 123.386 +    int spareCount;
 123.387 +
 123.388 +    /**
 123.389 +     * Encoded index and count of next spare waiter. Accessed only
 123.390 +     * by ForkJoinPool for managing spares.
 123.391 +     */
 123.392 +    volatile int nextSpare;
 123.393 +
 123.394 +    /**
 123.395 +     * The task currently being joined, set only when actively trying
 123.396 +     * to help other stealers in helpJoinTask. Written only by this
 123.397 +     * thread, but read by others.
 123.398 +     */
 123.399 +    private volatile ForkJoinTask<?> currentJoin;
 123.400 +
 123.401 +    /**
 123.402 +     * The task most recently stolen from another worker (or
 123.403 +     * submission queue).  Written only by this thread, but read by
 123.404 +     * others.
 123.405 +     */
 123.406 +    private volatile ForkJoinTask<?> currentSteal;
 123.407  
 123.408      /**
 123.409       * Creates a ForkJoinWorkerThread operating in the given pool.
 123.410 @@ -249,13 +332,24 @@
 123.411       * @throws NullPointerException if pool is null
 123.412       */
 123.413      protected ForkJoinWorkerThread(ForkJoinPool pool) {
 123.414 -        if (pool == null) throw new NullPointerException();
 123.415          this.pool = pool;
 123.416 -        // Note: poolIndex is set by pool during construction
 123.417 -        // Remaining initialization is deferred to onStart
 123.418 +        this.locallyFifo = pool.locallyFifo;
 123.419 +        setDaemon(true);
 123.420 +        // To avoid exposing construction details to subclasses,
 123.421 +        // remaining initialization is in start() and onStart()
 123.422      }
 123.423  
 123.424 -    // Public access methods
 123.425 +    /**
 123.426 +     * Performs additional initialization and starts this thread.
 123.427 +     */
 123.428 +    final void start(int poolIndex, UncaughtExceptionHandler ueh) {
 123.429 +        this.poolIndex = poolIndex;
 123.430 +        if (ueh != null)
 123.431 +            setUncaughtExceptionHandler(ueh);
 123.432 +        start();
 123.433 +    }
 123.434 +
 123.435 +    // Public/protected methods
 123.436  
 123.437      /**
 123.438       * Returns the pool hosting this thread.
 123.439 @@ -280,129 +374,24 @@
 123.440      }
 123.441  
 123.442      /**
 123.443 -     * Establishes local first-in-first-out scheduling mode for forked
 123.444 -     * tasks that are never joined.
 123.445 -     *
 123.446 -     * @param async if true, use locally FIFO scheduling
 123.447 -     */
 123.448 -    void setAsyncMode(boolean async) {
 123.449 -        locallyFifo = async;
 123.450 -    }
 123.451 -
 123.452 -    // Runstate management
 123.453 -
 123.454 -    // Runstate values. Order matters
 123.455 -    private static final int RUNNING     = 0;
 123.456 -    private static final int SHUTDOWN    = 1;
 123.457 -    private static final int TERMINATING = 2;
 123.458 -    private static final int TERMINATED  = 3;
 123.459 -
 123.460 -    final boolean isShutdown()    { return runState >= SHUTDOWN;  }
 123.461 -    final boolean isTerminating() { return runState >= TERMINATING;  }
 123.462 -    final boolean isTerminated()  { return runState == TERMINATED; }
 123.463 -    final boolean shutdown()      { return transitionRunStateTo(SHUTDOWN); }
 123.464 -    final boolean shutdownNow()   { return transitionRunStateTo(TERMINATING); }
 123.465 -
 123.466 -    /**
 123.467 -     * Transitions to at least the given state.
 123.468 -     *
 123.469 -     * @return {@code true} if not already at least at given state
 123.470 -     */
 123.471 -    private boolean transitionRunStateTo(int state) {
 123.472 -        for (;;) {
 123.473 -            int s = runState;
 123.474 -            if (s >= state)
 123.475 -                return false;
 123.476 -            if (UNSAFE.compareAndSwapInt(this, runStateOffset, s, state))
 123.477 -                return true;
 123.478 -        }
 123.479 -    }
 123.480 -
 123.481 -    /**
 123.482 -     * Tries to set status to active; fails on contention.
 123.483 -     */
 123.484 -    private boolean tryActivate() {
 123.485 -        if (!active) {
 123.486 -            if (!pool.tryIncrementActiveCount())
 123.487 -                return false;
 123.488 -            active = true;
 123.489 -        }
 123.490 -        return true;
 123.491 -    }
 123.492 -
 123.493 -    /**
 123.494 -     * Tries to set status to inactive; fails on contention.
 123.495 -     */
 123.496 -    private boolean tryInactivate() {
 123.497 -        if (active) {
 123.498 -            if (!pool.tryDecrementActiveCount())
 123.499 -                return false;
 123.500 -            active = false;
 123.501 -        }
 123.502 -        return true;
 123.503 -    }
 123.504 -
 123.505 -    /**
 123.506 -     * Computes next value for random victim probe.  Scans don't
 123.507 -     * require a very high quality generator, but also not a crummy
 123.508 -     * one.  Marsaglia xor-shift is cheap and works well.
 123.509 -     */
 123.510 -    private static int xorShift(int r) {
 123.511 -        r ^= (r << 13);
 123.512 -        r ^= (r >>> 17);
 123.513 -        return r ^ (r << 5);
 123.514 -    }
 123.515 -
 123.516 -    // Lifecycle methods
 123.517 -
 123.518 -    /**
 123.519 -     * This method is required to be public, but should never be
 123.520 -     * called explicitly. It performs the main run loop to execute
 123.521 -     * ForkJoinTasks.
 123.522 -     */
 123.523 -    public void run() {
 123.524 -        Throwable exception = null;
 123.525 -        try {
 123.526 -            onStart();
 123.527 -            pool.sync(this); // await first pool event
 123.528 -            mainLoop();
 123.529 -        } catch (Throwable ex) {
 123.530 -            exception = ex;
 123.531 -        } finally {
 123.532 -            onTermination(exception);
 123.533 -        }
 123.534 -    }
 123.535 -
 123.536 -    /**
 123.537 -     * Executes tasks until shut down.
 123.538 -     */
 123.539 -    private void mainLoop() {
 123.540 -        while (!isShutdown()) {
 123.541 -            ForkJoinTask<?> t = pollTask();
 123.542 -            if (t != null || (t = pollSubmission()) != null)
 123.543 -                t.quietlyExec();
 123.544 -            else if (tryInactivate())
 123.545 -                pool.sync(this);
 123.546 -        }
 123.547 -    }
 123.548 -
 123.549 -    /**
 123.550       * Initializes internal state after construction but before
 123.551       * processing any tasks. If you override this method, you must
 123.552 -     * invoke super.onStart() at the beginning of the method.
 123.553 +     * invoke @code{super.onStart()} at the beginning of the method.
 123.554       * Initialization requires care: Most fields must have legal
 123.555       * default values, to ensure that attempted accesses from other
 123.556       * threads work correctly even before this thread starts
 123.557       * processing tasks.
 123.558       */
 123.559      protected void onStart() {
 123.560 -        // Allocate while starting to improve chances of thread-local
 123.561 -        // isolation
 123.562 +        int rs = seedGenerator.nextInt();
 123.563 +        seed = rs == 0? 1 : rs; // seed must be nonzero
 123.564 +
 123.565 +        // Allocate name string and arrays in this thread
 123.566 +        String pid = Integer.toString(pool.getPoolNumber());
 123.567 +        String wid = Integer.toString(poolIndex);
 123.568 +        setName("ForkJoinPool-" + pid + "-worker-" + wid);
 123.569 +
 123.570          queue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
 123.571 -        // Initial value of seed need not be especially random but
 123.572 -        // should differ across workers and must be nonzero
 123.573 -        int p = poolIndex + 1;
 123.574 -        seed = p + (p << 8) + (p << 16) + (p << 24); // spread bits
 123.575      }
 123.576  
 123.577      /**
 123.578 @@ -414,97 +403,187 @@
 123.579       * to an unrecoverable error, or {@code null} if completed normally
 123.580       */
 123.581      protected void onTermination(Throwable exception) {
 123.582 -        // Execute remaining local tasks unless aborting or terminating
 123.583 -        while (exception == null && pool.isProcessingTasks() && base != sp) {
 123.584 -            try {
 123.585 -                ForkJoinTask<?> t = popTask();
 123.586 -                if (t != null)
 123.587 -                    t.quietlyExec();
 123.588 -            } catch (Throwable ex) {
 123.589 -                exception = ex;
 123.590 +        try {
 123.591 +            ForkJoinPool p = pool;
 123.592 +            if (active) {
 123.593 +                int a; // inline p.tryDecrementActiveCount
 123.594 +                active = false;
 123.595 +                do {} while (!UNSAFE.compareAndSwapInt
 123.596 +                             (p, poolRunStateOffset, a = p.runState, a - 1));
 123.597              }
 123.598 -        }
 123.599 -        // Cancel other tasks, transition status, notify pool, and
 123.600 -        // propagate exception to uncaught exception handler
 123.601 -        try {
 123.602 -            do {} while (!tryInactivate()); // ensure inactive
 123.603              cancelTasks();
 123.604 -            runState = TERMINATED;
 123.605 -            pool.workerTerminated(this);
 123.606 +            setTerminated();
 123.607 +            p.workerTerminated(this);
 123.608          } catch (Throwable ex) {        // Shouldn't ever happen
 123.609              if (exception == null)      // but if so, at least rethrown
 123.610                  exception = ex;
 123.611          } finally {
 123.612              if (exception != null)
 123.613 -                ForkJoinTask.rethrowException(exception);
 123.614 +                UNSAFE.throwException(exception);
 123.615          }
 123.616      }
 123.617  
 123.618 -    // Intrinsics-based support for queue operations.
 123.619 +    /**
 123.620 +     * This method is required to be public, but should never be
 123.621 +     * called explicitly. It performs the main run loop to execute
 123.622 +     * ForkJoinTasks.
 123.623 +     */
 123.624 +    public void run() {
 123.625 +        Throwable exception = null;
 123.626 +        try {
 123.627 +            onStart();
 123.628 +            mainLoop();
 123.629 +        } catch (Throwable ex) {
 123.630 +            exception = ex;
 123.631 +        } finally {
 123.632 +            onTermination(exception);
 123.633 +        }
 123.634 +    }
 123.635  
 123.636 -    private static long slotOffset(int i) {
 123.637 -        return ((long) i << qShift) + qBase;
 123.638 +    // helpers for run()
 123.639 +
 123.640 +    /**
 123.641 +     * Finds and executes tasks, and checks status while running.
 123.642 +     */
 123.643 +    private void mainLoop() {
 123.644 +        boolean ran = false; // true if ran a task on last step
 123.645 +        ForkJoinPool p = pool;
 123.646 +        for (;;) {
 123.647 +            p.preStep(this, ran);
 123.648 +            if (runState != 0)
 123.649 +                break;
 123.650 +            ran = tryExecSteal() || tryExecSubmission();
 123.651 +        }
 123.652      }
 123.653  
 123.654      /**
 123.655 -     * Adds in store-order the given task at given slot of q to null.
 123.656 -     * Caller must ensure q is non-null and index is in range.
 123.657 +     * Tries to steal a task and execute it.
 123.658 +     *
 123.659 +     * @return true if ran a task
 123.660       */
 123.661 -    private static void setSlot(ForkJoinTask<?>[] q, int i,
 123.662 -                                ForkJoinTask<?> t) {
 123.663 -        UNSAFE.putOrderedObject(q, slotOffset(i), t);
 123.664 +    private boolean tryExecSteal() {
 123.665 +        ForkJoinTask<?> t;
 123.666 +        if ((t = scan()) != null) {
 123.667 +            t.quietlyExec();
 123.668 +            UNSAFE.putOrderedObject(this, currentStealOffset, null);
 123.669 +            if (sp != base)
 123.670 +                execLocalTasks();
 123.671 +            return true;
 123.672 +        }
 123.673 +        return false;
 123.674      }
 123.675  
 123.676      /**
 123.677 -     * CAS given slot of q to null. Caller must ensure q is non-null
 123.678 -     * and index is in range.
 123.679 +     * If a submission exists, try to activate and run it.
 123.680 +     *
 123.681 +     * @return true if ran a task
 123.682       */
 123.683 -    private static boolean casSlotNull(ForkJoinTask<?>[] q, int i,
 123.684 -                                       ForkJoinTask<?> t) {
 123.685 -        return UNSAFE.compareAndSwapObject(q, slotOffset(i), t, null);
 123.686 +    private boolean tryExecSubmission() {
 123.687 +        ForkJoinPool p = pool;
 123.688 +        // This loop is needed in case attempt to activate fails, in
 123.689 +        // which case we only retry if there still appears to be a
 123.690 +        // submission.
 123.691 +        while (p.hasQueuedSubmissions()) {
 123.692 +            ForkJoinTask<?> t; int a;
 123.693 +            if (active || // inline p.tryIncrementActiveCount
 123.694 +                (active = UNSAFE.compareAndSwapInt(p, poolRunStateOffset,
 123.695 +                                                   a = p.runState, a + 1))) {
 123.696 +                if ((t = p.pollSubmission()) != null) {
 123.697 +                    UNSAFE.putOrderedObject(this, currentStealOffset, t);
 123.698 +                    t.quietlyExec();
 123.699 +                    UNSAFE.putOrderedObject(this, currentStealOffset, null);
 123.700 +                    if (sp != base)
 123.701 +                        execLocalTasks();
 123.702 +                    return true;
 123.703 +                }
 123.704 +            }
 123.705 +        }
 123.706 +        return false;
 123.707      }
 123.708  
 123.709      /**
 123.710 -     * Sets sp in store-order.
 123.711 +     * Runs local tasks until queue is empty or shut down.  Call only
 123.712 +     * while active.
 123.713       */
 123.714 -    private void storeSp(int s) {
 123.715 -        UNSAFE.putOrderedInt(this, spOffset, s);
 123.716 +    private void execLocalTasks() {
 123.717 +        while (runState == 0) {
 123.718 +            ForkJoinTask<?> t = locallyFifo ? locallyDeqTask() : popTask();
 123.719 +            if (t != null)
 123.720 +                t.quietlyExec();
 123.721 +            else if (sp == base)
 123.722 +                break;
 123.723 +        }
 123.724      }
 123.725  
 123.726 -    // Main queue methods
 123.727 +    /*
 123.728 +     * Intrinsics-based atomic writes for queue slots. These are
 123.729 +     * basically the same as methods in AtomicReferenceArray, but
 123.730 +     * specialized for (1) ForkJoinTask elements (2) requirement that
 123.731 +     * nullness and bounds checks have already been performed by
 123.732 +     * callers and (3) effective offsets are known not to overflow
 123.733 +     * from int to long (because of MAXIMUM_QUEUE_CAPACITY). We don't
 123.734 +     * need corresponding version for reads: plain array reads are OK
 123.735 +     * because they are protected by other volatile reads and are
 123.736 +     * confirmed by CASes.
 123.737 +     *
 123.738 +     * Most uses don't actually call these methods, but instead contain
 123.739 +     * inlined forms that enable more predictable optimization.  We
 123.740 +     * don't define the version of write used in pushTask at all, but
 123.741 +     * instead inline there a store-fenced array slot write.
 123.742 +     */
 123.743  
 123.744      /**
 123.745 -     * Pushes a task. Called only by current thread.
 123.746 +     * CASes slot i of array q from t to null. Caller must ensure q is
 123.747 +     * non-null and index is in range.
 123.748 +     */
 123.749 +    private static final boolean casSlotNull(ForkJoinTask<?>[] q, int i,
 123.750 +                                             ForkJoinTask<?> t) {
 123.751 +        return UNSAFE.compareAndSwapObject(q, (i << qShift) + qBase, t, null);
 123.752 +    }
 123.753 +
 123.754 +    /**
 123.755 +     * Performs a volatile write of the given task at given slot of
 123.756 +     * array q.  Caller must ensure q is non-null and index is in
 123.757 +     * range. This method is used only during resets and backouts.
 123.758 +     */
 123.759 +    private static final void writeSlot(ForkJoinTask<?>[] q, int i,
 123.760 +                                        ForkJoinTask<?> t) {
 123.761 +        UNSAFE.putObjectVolatile(q, (i << qShift) + qBase, t);
 123.762 +    }
 123.763 +
 123.764 +    // queue methods
 123.765 +
 123.766 +    /**
 123.767 +     * Pushes a task. Call only from this thread.
 123.768       *
 123.769       * @param t the task. Caller must ensure non-null.
 123.770       */
 123.771      final void pushTask(ForkJoinTask<?> t) {
 123.772          ForkJoinTask<?>[] q = queue;
 123.773 -        int mask = q.length - 1;
 123.774 -        int s = sp;
 123.775 -        setSlot(q, s & mask, t);
 123.776 -        storeSp(++s);
 123.777 -        if ((s -= base) == 1)
 123.778 -            pool.signalWork();
 123.779 -        else if (s >= mask)
 123.780 -            growQueue();
 123.781 +        int mask = q.length - 1; // implicit assert q != null
 123.782 +        int s = sp++;            // ok to increment sp before slot write
 123.783 +        UNSAFE.putOrderedObject(q, ((s & mask) << qShift) + qBase, t);
 123.784 +        if ((s -= base) == 0)
 123.785 +            pool.signalWork();   // was empty
 123.786 +        else if (s == mask)
 123.787 +            growQueue();         // is full
 123.788      }
 123.789  
 123.790      /**
 123.791       * Tries to take a task from the base of the queue, failing if
 123.792 -     * either empty or contended.
 123.793 +     * empty or contended. Note: Specializations of this code appear
 123.794 +     * in locallyDeqTask and elsewhere.
 123.795       *
 123.796       * @return a task, or null if none or contended
 123.797       */
 123.798      final ForkJoinTask<?> deqTask() {
 123.799          ForkJoinTask<?> t;
 123.800          ForkJoinTask<?>[] q;
 123.801 -        int i;
 123.802 -        int b;
 123.803 +        int b, i;
 123.804          if (sp != (b = base) &&
 123.805              (q = queue) != null && // must read q after b
 123.806 -            (t = q[i = (q.length - 1) & b]) != null &&
 123.807 -            casSlotNull(q, i, t)) {
 123.808 +            (t = q[i = (q.length - 1) & b]) != null && base == b &&
 123.809 +            UNSAFE.compareAndSwapObject(q, (i << qShift) + qBase, t, null)) {
 123.810              base = b + 1;
 123.811              return t;
 123.812          }
 123.813 @@ -512,19 +591,20 @@
 123.814      }
 123.815  
 123.816      /**
 123.817 -     * Tries to take a task from the base of own queue, activating if
 123.818 -     * necessary, failing only if empty. Called only by current thread.
 123.819 +     * Tries to take a task from the base of own queue. Assumes active
 123.820 +     * status.  Called only by this thread.
 123.821       *
 123.822       * @return a task, or null if none
 123.823       */
 123.824      final ForkJoinTask<?> locallyDeqTask() {
 123.825 -        int b;
 123.826 -        while (sp != (b = base)) {
 123.827 -            if (tryActivate()) {
 123.828 -                ForkJoinTask<?>[] q = queue;
 123.829 -                int i = (q.length - 1) & b;
 123.830 -                ForkJoinTask<?> t = q[i];
 123.831 -                if (t != null && casSlotNull(q, i, t)) {
 123.832 +        ForkJoinTask<?>[] q = queue;
 123.833 +        if (q != null) {
 123.834 +            ForkJoinTask<?> t;
 123.835 +            int b, i;
 123.836 +            while (sp != (b = base)) {
 123.837 +                if ((t = q[i = (q.length - 1) & b]) != null && base == b &&
 123.838 +                    UNSAFE.compareAndSwapObject(q, (i << qShift) + qBase,
 123.839 +                                                t, null)) {
 123.840                      base = b + 1;
 123.841                      return t;
 123.842                  }
 123.843 @@ -534,46 +614,50 @@
 123.844      }
 123.845  
 123.846      /**
 123.847 -     * Returns a popped task, or null if empty. Ensures active status
 123.848 -     * if non-null. Called only by current thread.
 123.849 +     * Returns a popped task, or null if empty. Assumes active status.
 123.850 +     * Called only by this thread.
 123.851       */
 123.852 -    final ForkJoinTask<?> popTask() {
 123.853 -        int s = sp;
 123.854 -        while (s != base) {
 123.855 -            if (tryActivate()) {
 123.856 -                ForkJoinTask<?>[] q = queue;
 123.857 -                int mask = q.length - 1;
 123.858 -                int i = (s - 1) & mask;
 123.859 +    private ForkJoinTask<?> popTask() {
 123.860 +        ForkJoinTask<?>[] q = queue;
 123.861 +        if (q != null) {
 123.862 +            int s;
 123.863 +            while ((s = sp) != base) {
 123.864 +                int i = (q.length - 1) & --s;
 123.865 +                long u = (i << qShift) + qBase; // raw offset
 123.866                  ForkJoinTask<?> t = q[i];
 123.867 -                if (t == null || !casSlotNull(q, i, t))
 123.868 +                if (t == null)   // lost to stealer
 123.869                      break;
 123.870 -                storeSp(s - 1);
 123.871 -                return t;
 123.872 +                if (UNSAFE.compareAndSwapObject(q, u, t, null)) {
 123.873 +                    sp = s; // putOrderedInt may encourage more timely write
 123.874 +                    // UNSAFE.putOrderedInt(this, spOffset, s);
 123.875 +                    return t;
 123.876 +                }
 123.877              }
 123.878          }
 123.879          return null;
 123.880      }
 123.881  
 123.882      /**
 123.883 -     * Specialized version of popTask to pop only if
 123.884 -     * topmost element is the given task. Called only
 123.885 -     * by current thread while active.
 123.886 +     * Specialized version of popTask to pop only if topmost element
 123.887 +     * is the given task. Called only by this thread while active.
 123.888       *
 123.889       * @param t the task. Caller must ensure non-null.
 123.890       */
 123.891      final boolean unpushTask(ForkJoinTask<?> t) {
 123.892 +        int s;
 123.893          ForkJoinTask<?>[] q = queue;
 123.894 -        int mask = q.length - 1;
 123.895 -        int s = sp - 1;
 123.896 -        if (casSlotNull(q, s & mask, t)) {
 123.897 -            storeSp(s);
 123.898 +        if ((s = sp) != base && q != null &&
 123.899 +            UNSAFE.compareAndSwapObject
 123.900 +            (q, (((q.length - 1) & --s) << qShift) + qBase, t, null)) {
 123.901 +            sp = s; // putOrderedInt may encourage more timely write
 123.902 +            // UNSAFE.putOrderedInt(this, spOffset, s);
 123.903              return true;
 123.904          }
 123.905          return false;
 123.906      }
 123.907  
 123.908      /**
 123.909 -     * Returns next task or null if empty or contended
 123.910 +     * Returns next task, or null if empty or contended.
 123.911       */
 123.912      final ForkJoinTask<?> peekTask() {
 123.913          ForkJoinTask<?>[] q = queue;
 123.914 @@ -606,104 +690,209 @@
 123.915              ForkJoinTask<?> t = oldQ[oldIndex];
 123.916              if (t != null && !casSlotNull(oldQ, oldIndex, t))
 123.917                  t = null;
 123.918 -            setSlot(newQ, b & newMask, t);
 123.919 +            writeSlot(newQ, b & newMask, t);
 123.920          } while (++b != bf);
 123.921          pool.signalWork();
 123.922      }
 123.923  
 123.924      /**
 123.925 +     * Computes next value for random victim probe in scan().  Scans
 123.926 +     * don't require a very high quality generator, but also not a
 123.927 +     * crummy one.  Marsaglia xor-shift is cheap and works well enough.
 123.928 +     * Note: This is manually inlined in scan().
 123.929 +     */
 123.930 +    private static final int xorShift(int r) {
 123.931 +        r ^= r << 13;
 123.932 +        r ^= r >>> 17;
 123.933 +        return r ^ (r << 5);
 123.934 +    }
 123.935 +
 123.936 +    /**
 123.937       * Tries to steal a task from another worker. Starts at a random
 123.938       * index of workers array, and probes workers until finding one
 123.939       * with non-empty queue or finding that all are empty.  It
 123.940       * randomly selects the first n probes. If these are empty, it
 123.941 -     * resorts to a full circular traversal, which is necessary to
 123.942 -     * accurately set active status by caller. Also restarts if pool
 123.943 -     * events occurred since last scan, which forces refresh of
 123.944 -     * workers array, in case barrier was associated with resize.
 123.945 +     * resorts to a circular sweep, which is necessary to accurately
 123.946 +     * set active status. (The circular sweep uses steps of
 123.947 +     * approximately half the array size plus 1, to avoid bias
 123.948 +     * stemming from leftmost packing of the array in ForkJoinPool.)
 123.949       *
 123.950       * This method must be both fast and quiet -- usually avoiding
 123.951       * memory accesses that could disrupt cache sharing etc other than
 123.952 -     * those needed to check for and take tasks. This accounts for,
 123.953 -     * among other things, updating random seed in place without
 123.954 -     * storing it until exit.
 123.955 +     * those needed to check for and take tasks (or to activate if not
 123.956 +     * already active). This accounts for, among other things,
 123.957 +     * updating random seed in place without storing it until exit.
 123.958       *
 123.959       * @return a task, or null if none found
 123.960       */
 123.961      private ForkJoinTask<?> scan() {
 123.962 -        ForkJoinTask<?> t = null;
 123.963 -        int r = seed;                    // extract once to keep scan quiet
 123.964 -        ForkJoinWorkerThread[] ws;       // refreshed on outer loop
 123.965 -        int mask;                        // must be power 2 minus 1 and > 0
 123.966 -        outer:do {
 123.967 -            if ((ws = pool.workers) != null && (mask = ws.length - 1) > 0) {
 123.968 -                int idx = r;
 123.969 -                int probes = ~mask;      // use random index while negative
 123.970 -                for (;;) {
 123.971 -                    r = xorShift(r);     // update random seed
 123.972 -                    ForkJoinWorkerThread v = ws[mask & idx];
 123.973 -                    if (v == null || v.sp == v.base) {
 123.974 -                        if (probes <= mask)
 123.975 -                            idx = (probes++ < 0) ? r : (idx + 1);
 123.976 -                        else
 123.977 -                            break;
 123.978 +        ForkJoinPool p = pool;
 123.979 +        ForkJoinWorkerThread[] ws;        // worker array
 123.980 +        int n;                            // upper bound of #workers
 123.981 +        if ((ws = p.workers) != null && (n = ws.length) > 1) {
 123.982 +            boolean canSteal = active;    // shadow active status
 123.983 +            int r = seed;                 // extract seed once
 123.984 +            int mask = n - 1;
 123.985 +            int j = -n;                   // loop counter
 123.986 +            int k = r;                    // worker index, random if j < 0
 123.987 +            for (;;) {
 123.988 +                ForkJoinWorkerThread v = ws[k & mask];
 123.989 +                r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // inline xorshift
 123.990 +                ForkJoinTask<?>[] q; ForkJoinTask<?> t; int b, a;
 123.991 +                if (v != null && (b = v.base) != v.sp &&
 123.992 +                    (q = v.queue) != null) {
 123.993 +                    int i = (q.length - 1) & b;
 123.994 +                    long u = (i << qShift) + qBase; // raw offset
 123.995 +                    int pid = poolIndex;
 123.996 +                    if ((t = q[i]) != null) {
 123.997 +                        if (!canSteal &&  // inline p.tryIncrementActiveCount
 123.998 +                            UNSAFE.compareAndSwapInt(p, poolRunStateOffset,
 123.999 +                                                     a = p.runState, a + 1))
123.1000 +                            canSteal = active = true;
123.1001 +                        if (canSteal && v.base == b++ &&
123.1002 +                            UNSAFE.compareAndSwapObject(q, u, t, null)) {
123.1003 +                            v.base = b;
123.1004 +                            v.stealHint = pid;
123.1005 +                            UNSAFE.putOrderedObject(this,
123.1006 +                                                    currentStealOffset, t);
123.1007 +                            seed = r;
123.1008 +                            ++stealCount;
123.1009 +                            return t;
123.1010 +                        }
123.1011                      }
123.1012 -                    else if (!tryActivate() || (t = v.deqTask()) == null)
123.1013 -                        continue outer;  // restart on contention
123.1014 -                    else
123.1015 -                        break outer;
123.1016 +                    j = -n;
123.1017 +                    k = r;                // restart on contention
123.1018                  }
123.1019 +                else if (++j <= 0)
123.1020 +                    k = r;
123.1021 +                else if (j <= n)
123.1022 +                    k += (n >>> 1) | 1;
123.1023 +                else
123.1024 +                    break;
123.1025              }
123.1026 -        } while (pool.hasNewSyncEvent(this)); // retry on pool events
123.1027 -        seed = r;
123.1028 -        return t;
123.1029 -    }
123.1030 -
123.1031 -    /**
123.1032 -     * Gets and removes a local or stolen task.
123.1033 -     *
123.1034 -     * @return a task, if available
123.1035 -     */
123.1036 -    final ForkJoinTask<?> pollTask() {
123.1037 -        ForkJoinTask<?> t = locallyFifo ? locallyDeqTask() : popTask();
123.1038 -        if (t == null && (t = scan()) != null)
123.1039 -            ++stealCount;
123.1040 -        return t;
123.1041 -    }
123.1042 -
123.1043 -    /**
123.1044 -     * Gets a local task.
123.1045 -     *
123.1046 -     * @return a task, if available
123.1047 -     */
123.1048 -    final ForkJoinTask<?> pollLocalTask() {
123.1049 -        return locallyFifo ? locallyDeqTask() : popTask();
123.1050 -    }
123.1051 -
123.1052 -    /**
123.1053 -     * Returns a pool submission, if one exists, activating first.
123.1054 -     *
123.1055 -     * @return a submission, if available
123.1056 -     */
123.1057 -    private ForkJoinTask<?> pollSubmission() {
123.1058 -        ForkJoinPool p = pool;
123.1059 -        while (p.hasQueuedSubmissions()) {
123.1060 -            ForkJoinTask<?> t;
123.1061 -            if (tryActivate() && (t = p.pollSubmission()) != null)
123.1062 -                return t;
123.1063          }
123.1064          return null;
123.1065      }
123.1066  
123.1067 -    // Methods accessed only by Pool
123.1068 +    // Run State management
123.1069 +
123.1070 +    // status check methods used mainly by ForkJoinPool
123.1071 +    final boolean isRunning()     { return runState == 0; }
123.1072 +    final boolean isTerminating() { return (runState & TERMINATING) != 0; }
123.1073 +    final boolean isTerminated()  { return (runState & TERMINATED) != 0; }
123.1074 +    final boolean isSuspended()   { return (runState & SUSPENDED) != 0; }
123.1075 +    final boolean isTrimmed()     { return (runState & TRIMMED) != 0; }
123.1076 +
123.1077 +    /**
123.1078 +     * Sets state to TERMINATING. Does NOT unpark or interrupt
123.1079 +     * to wake up if currently blocked. Callers must do so if desired.
123.1080 +     */
123.1081 +    final void shutdown() {
123.1082 +        for (;;) {
123.1083 +            int s = runState;
123.1084 +            if ((s & (TERMINATING|TERMINATED)) != 0)
123.1085 +                break;
123.1086 +            if ((s & SUSPENDED) != 0) { // kill and wakeup if suspended
123.1087 +                if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
123.1088 +                                             (s & ~SUSPENDED) |
123.1089 +                                             (TRIMMED|TERMINATING)))
123.1090 +                    break;
123.1091 +            }
123.1092 +            else if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
123.1093 +                                              s | TERMINATING))
123.1094 +                break;
123.1095 +        }
123.1096 +    }
123.1097 +
123.1098 +    /**
123.1099 +     * Sets state to TERMINATED. Called only by onTermination().
123.1100 +     */
123.1101 +    private void setTerminated() {
123.1102 +        int s;
123.1103 +        do {} while (!UNSAFE.compareAndSwapInt(this, runStateOffset,
123.1104 +                                               s = runState,
123.1105 +                                               s | (TERMINATING|TERMINATED)));
123.1106 +    }
123.1107 +
123.1108 +    /**
123.1109 +     * If suspended, tries to set status to unsuspended.
123.1110 +     * Does NOT wake up if blocked.
123.1111 +     *
123.1112 +     * @return true if successful
123.1113 +     */
123.1114 +    final boolean tryUnsuspend() {
123.1115 +        int s;
123.1116 +        while (((s = runState) & SUSPENDED) != 0) {
123.1117 +            if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
123.1118 +                                         s & ~SUSPENDED))
123.1119 +                return true;
123.1120 +        }
123.1121 +        return false;
123.1122 +    }
123.1123 +
123.1124 +    /**
123.1125 +     * Sets suspended status and blocks as spare until resumed
123.1126 +     * or shutdown.
123.1127 +     */
123.1128 +    final void suspendAsSpare() {
123.1129 +        for (;;) {                  // set suspended unless terminating
123.1130 +            int s = runState;
123.1131 +            if ((s & TERMINATING) != 0) { // must kill
123.1132 +                if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
123.1133 +                                             s | (TRIMMED | TERMINATING)))
123.1134 +                    return;
123.1135 +            }
123.1136 +            else if (UNSAFE.compareAndSwapInt(this, runStateOffset, s,
123.1137 +                                              s | SUSPENDED))
123.1138 +                break;
123.1139 +        }
123.1140 +        ForkJoinPool p = pool;
123.1141 +        p.pushSpare(this);
123.1142 +        while ((runState & SUSPENDED) != 0) {
123.1143 +            if (p.tryAccumulateStealCount(this)) {
123.1144 +                interrupted();          // clear/ignore interrupts
123.1145 +                if ((runState & SUSPENDED) == 0)
123.1146 +                    break;
123.1147 +                LockSupport.park(this);
123.1148 +            }
123.1149 +        }
123.1150 +    }
123.1151 +
123.1152 +    // Misc support methods for ForkJoinPool
123.1153 +
123.1154 +    /**
123.1155 +     * Returns an estimate of the number of tasks in the queue.  Also
123.1156 +     * used by ForkJoinTask.
123.1157 +     */
123.1158 +    final int getQueueSize() {
123.1159 +        int n; // external calls must read base first
123.1160 +        return (n = -base + sp) <= 0 ? 0 : n;
123.1161 +    }
123.1162  
123.1163      /**
123.1164       * Removes and cancels all tasks in queue.  Can be called from any
123.1165       * thread.
123.1166       */
123.1167      final void cancelTasks() {
123.1168 -        ForkJoinTask<?> t;
123.1169 -        while (base != sp && (t = deqTask()) != null)
123.1170 -            t.cancelIgnoringExceptions();
123.1171 +        ForkJoinTask<?> cj = currentJoin; // try to cancel ongoing tasks
123.1172 +        if (cj != null) {
123.1173 +            currentJoin = null;
123.1174 +            cj.cancelIgnoringExceptions();
123.1175 +            try {
123.1176 +                this.interrupt(); // awaken wait
123.1177 +            } catch (SecurityException ignore) {
123.1178 +            }
123.1179 +        }
123.1180 +        ForkJoinTask<?> cs = currentSteal;
123.1181 +        if (cs != null) {
123.1182 +            currentSteal = null;
123.1183 +            cs.cancelIgnoringExceptions();
123.1184 +        }
123.1185 +        while (base != sp) {
123.1186 +            ForkJoinTask<?> t = deqTask();
123.1187 +            if (t != null)
123.1188 +                t.cancelIgnoringExceptions();
123.1189 +        }
123.1190      }
123.1191  
123.1192      /**
123.1193 @@ -713,87 +902,266 @@
123.1194       */
123.1195      final int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
123.1196          int n = 0;
123.1197 -        ForkJoinTask<?> t;
123.1198 -        while (base != sp && (t = deqTask()) != null) {
123.1199 -            c.add(t);
123.1200 -            ++n;
123.1201 +        while (base != sp) {
123.1202 +            ForkJoinTask<?> t = deqTask();
123.1203 +            if (t != null) {
123.1204 +                c.add(t);
123.1205 +                ++n;
123.1206 +            }
123.1207          }
123.1208          return n;
123.1209      }
123.1210  
123.1211 -    /**
123.1212 -     * Gets and clears steal count for accumulation by pool.  Called
123.1213 -     * only when known to be idle (in pool.sync and termination).
123.1214 -     */
123.1215 -    final int getAndClearStealCount() {
123.1216 -        int sc = stealCount;
123.1217 -        stealCount = 0;
123.1218 -        return sc;
123.1219 -    }
123.1220 -
123.1221 -    /**
123.1222 -     * Returns {@code true} if at least one worker in the given array
123.1223 -     * appears to have at least one queued task.
123.1224 -     *
123.1225 -     * @param ws array of workers
123.1226 -     */
123.1227 -    static boolean hasQueuedTasks(ForkJoinWorkerThread[] ws) {
123.1228 -        if (ws != null) {
123.1229 -            int len = ws.length;
123.1230 -            for (int j = 0; j < 2; ++j) { // need two passes for clean sweep
123.1231 -                for (int i = 0; i < len; ++i) {
123.1232 -                    ForkJoinWorkerThread w = ws[i];
123.1233 -                    if (w != null && w.sp != w.base)
123.1234 -                        return true;
123.1235 -                }
123.1236 -            }
123.1237 -        }
123.1238 -        return false;
123.1239 -    }
123.1240 -
123.1241      // Support methods for ForkJoinTask
123.1242  
123.1243      /**
123.1244 -     * Returns an estimate of the number of tasks in the queue.
123.1245 +     * Gets and removes a local task.
123.1246 +     *
123.1247 +     * @return a task, if available
123.1248       */
123.1249 -    final int getQueueSize() {
123.1250 -        // suppress momentarily negative values
123.1251 -        return Math.max(0, sp - base);
123.1252 +    final ForkJoinTask<?> pollLocalTask() {
123.1253 +        ForkJoinPool p = pool;
123.1254 +        while (sp != base) {
123.1255 +            int a; // inline p.tryIncrementActiveCount
123.1256 +            if (active ||
123.1257 +                (active = UNSAFE.compareAndSwapInt(p, poolRunStateOffset,
123.1258 +                                                   a = p.runState, a + 1)))
123.1259 +                return locallyFifo ? locallyDeqTask() : popTask();
123.1260 +        }
123.1261 +        return null;
123.1262      }
123.1263  
123.1264      /**
123.1265 -     * Returns an estimate of the number of tasks, offset by a
123.1266 -     * function of number of idle workers.
123.1267 +     * Gets and removes a local or stolen task.
123.1268 +     *
123.1269 +     * @return a task, if available
123.1270       */
123.1271 -    final int getEstimatedSurplusTaskCount() {
123.1272 -        // The halving approximates weighting idle vs non-idle workers
123.1273 -        return (sp - base) - (pool.getIdleThreadCount() >>> 1);
123.1274 +    final ForkJoinTask<?> pollTask() {
123.1275 +        ForkJoinTask<?> t = pollLocalTask();
123.1276 +        if (t == null) {
123.1277 +            t = scan();
123.1278 +            // cannot retain/track/help steal
123.1279 +            UNSAFE.putOrderedObject(this, currentStealOffset, null);
123.1280 +        }
123.1281 +        return t;
123.1282      }
123.1283  
123.1284      /**
123.1285 -     * Scans, returning early if joinMe done.
123.1286 +     * Possibly runs some tasks and/or blocks, until task is done.
123.1287 +     *
123.1288 +     * @param joinMe the task to join
123.1289       */
123.1290 -    final ForkJoinTask<?> scanWhileJoining(ForkJoinTask<?> joinMe) {
123.1291 -        ForkJoinTask<?> t = pollTask();
123.1292 -        if (t != null && joinMe.status < 0 && sp == base) {
123.1293 -            pushTask(t); // unsteal if done and this task would be stealable
123.1294 -            t = null;
123.1295 +    final void joinTask(ForkJoinTask<?> joinMe) {
123.1296 +        // currentJoin only written by this thread; only need ordered store
123.1297 +        ForkJoinTask<?> prevJoin = currentJoin;
123.1298 +        UNSAFE.putOrderedObject(this, currentJoinOffset, joinMe);
123.1299 +        if (sp != base)
123.1300 +            localHelpJoinTask(joinMe);
123.1301 +        if (joinMe.status >= 0)
123.1302 +            pool.awaitJoin(joinMe, this);
123.1303 +        UNSAFE.putOrderedObject(this, currentJoinOffset, prevJoin);
123.1304 +    }
123.1305 +
123.1306 +    /**
123.1307 +     * Run tasks in local queue until given task is done.
123.1308 +     *
123.1309 +     * @param joinMe the task to join
123.1310 +     */
123.1311 +    private void localHelpJoinTask(ForkJoinTask<?> joinMe) {
123.1312 +        int s;
123.1313 +        ForkJoinTask<?>[] q;
123.1314 +        while (joinMe.status >= 0 && (s = sp) != base && (q = queue) != null) {
123.1315 +            int i = (q.length - 1) & --s;
123.1316 +            long u = (i << qShift) + qBase; // raw offset
123.1317 +            ForkJoinTask<?> t = q[i];
123.1318 +            if (t == null)  // lost to a stealer
123.1319 +                break;
123.1320 +            if (UNSAFE.compareAndSwapObject(q, u, t, null)) {
123.1321 +                /*
123.1322 +                 * This recheck (and similarly in helpJoinTask)
123.1323 +                 * handles cases where joinMe is independently
123.1324 +                 * cancelled or forced even though there is other work
123.1325 +                 * available. Back out of the pop by putting t back
123.1326 +                 * into slot before we commit by writing sp.
123.1327 +                 */
123.1328 +                if (joinMe.status < 0) {
123.1329 +                    UNSAFE.putObjectVolatile(q, u, t);
123.1330 +                    break;
123.1331 +                }
123.1332 +                sp = s;
123.1333 +                // UNSAFE.putOrderedInt(this, spOffset, s);
123.1334 +                t.quietlyExec();
123.1335 +            }
123.1336          }
123.1337 -        return t;
123.1338 +    }
123.1339 +
123.1340 +    /**
123.1341 +     * Unless terminating, tries to locate and help perform tasks for
123.1342 +     * a stealer of the given task, or in turn one of its stealers.
123.1343 +     * Traces currentSteal->currentJoin links looking for a thread
123.1344 +     * working on a descendant of the given task and with a non-empty
123.1345 +     * queue to steal back and execute tasks from.
123.1346 +     *
123.1347 +     * The implementation is very branchy to cope with potential
123.1348 +     * inconsistencies or loops encountering chains that are stale,
123.1349 +     * unknown, or of length greater than MAX_HELP_DEPTH links.  All
123.1350 +     * of these cases are dealt with by just returning back to the
123.1351 +     * caller, who is expected to retry if other join mechanisms also
123.1352 +     * don't work out.
123.1353 +     *
123.1354 +     * @param joinMe the task to join
123.1355 +     */
123.1356 +    final void helpJoinTask(ForkJoinTask<?> joinMe) {
123.1357 +        ForkJoinWorkerThread[] ws;
123.1358 +        int n;
123.1359 +        if (joinMe.status < 0)                // already done
123.1360 +            return;
123.1361 +        if ((runState & TERMINATING) != 0) {  // cancel if shutting down
123.1362 +            joinMe.cancelIgnoringExceptions();
123.1363 +            return;
123.1364 +        }
123.1365 +        if ((ws = pool.workers) == null || (n = ws.length) <= 1)
123.1366 +            return;                           // need at least 2 workers
123.1367 +
123.1368 +        ForkJoinTask<?> task = joinMe;        // base of chain
123.1369 +        ForkJoinWorkerThread thread = this;   // thread with stolen task
123.1370 +        for (int d = 0; d < MAX_HELP_DEPTH; ++d) { // chain length
123.1371 +            // Try to find v, the stealer of task, by first using hint
123.1372 +            ForkJoinWorkerThread v = ws[thread.stealHint & (n - 1)];
123.1373 +            if (v == null || v.currentSteal != task) {
123.1374 +                for (int j = 0; ; ++j) {      // search array
123.1375 +                    if (j < n) {
123.1376 +                        ForkJoinTask<?> vs;
123.1377 +                        if ((v = ws[j]) != null &&
123.1378 +                            (vs = v.currentSteal) != null) {
123.1379 +                            if (joinMe.status < 0 || task.status < 0)
123.1380 +                                return;       // stale or done
123.1381 +                            if (vs == task) {
123.1382 +                                thread.stealHint = j;
123.1383 +                                break;        // save hint for next time
123.1384 +                            }
123.1385 +                        }
123.1386 +                    }
123.1387 +                    else
123.1388 +                        return;               // no stealer
123.1389 +                }
123.1390 +            }
123.1391 +            for (;;) { // Try to help v, using specialized form of deqTask
123.1392 +                if (joinMe.status < 0)
123.1393 +                    return;
123.1394 +                int b = v.base;
123.1395 +                ForkJoinTask<?>[] q = v.queue;
123.1396 +                if (b == v.sp || q == null)
123.1397 +                    break;
123.1398 +                int i = (q.length - 1) & b;
123.1399 +                long u = (i << qShift) + qBase;
123.1400 +                ForkJoinTask<?> t = q[i];
123.1401 +                int pid = poolIndex;
123.1402 +                ForkJoinTask<?> ps = currentSteal;
123.1403 +                if (task.status < 0)
123.1404 +                    return;                   // stale or done
123.1405 +                if (t != null && v.base == b++ &&
123.1406 +                    UNSAFE.compareAndSwapObject(q, u, t, null)) {
123.1407 +                    if (joinMe.status < 0) {
123.1408 +                        UNSAFE.putObjectVolatile(q, u, t);
123.1409 +                        return;               // back out on cancel
123.1410 +                    }
123.1411 +                    v.base = b;
123.1412 +                    v.stealHint = pid;
123.1413 +                    UNSAFE.putOrderedObject(this, currentStealOffset, t);
123.1414 +                    t.quietlyExec();
123.1415 +                    UNSAFE.putOrderedObject(this, currentStealOffset, ps);
123.1416 +                }
123.1417 +            }
123.1418 +            // Try to descend to find v's stealer
123.1419 +            ForkJoinTask<?> next = v.currentJoin;
123.1420 +            if (task.status < 0 || next == null || next == task ||
123.1421 +                joinMe.status < 0)
123.1422 +                return;
123.1423 +            task = next;
123.1424 +            thread = v;
123.1425 +        }
123.1426 +    }
123.1427 +
123.1428 +    /**
123.1429 +     * Implements ForkJoinTask.getSurplusQueuedTaskCount().
123.1430 +     * Returns an estimate of the number of tasks, offset by a
123.1431 +     * function of number of idle workers.
123.1432 +     *
123.1433 +     * This method provides a cheap heuristic guide for task
123.1434 +     * partitioning when programmers, frameworks, tools, or languages
123.1435 +     * have little or no idea about task granularity.  In essence by
123.1436 +     * offering this method, we ask users only about tradeoffs in
123.1437 +     * overhead vs expected throughput and its variance, rather than
123.1438 +     * how finely to partition tasks.
123.1439 +     *
123.1440 +     * In a steady state strict (tree-structured) computation, each
123.1441 +     * thread makes available for stealing enough tasks for other
123.1442 +     * threads to remain active. Inductively, if all threads play by
123.1443 +     * the same rules, each thread should make available only a
123.1444 +     * constant number of tasks.
123.1445 +     *
123.1446 +     * The minimum useful constant is just 1. But using a value of 1
123.1447 +     * would require immediate replenishment upon each steal to
123.1448 +     * maintain enough tasks, which is infeasible.  Further,
123.1449 +     * partitionings/granularities of offered tasks should minimize
123.1450 +     * steal rates, which in general means that threads nearer the top
123.1451 +     * of computation tree should generate more than those nearer the
123.1452 +     * bottom. In perfect steady state, each thread is at
123.1453 +     * approximately the same level of computation tree. However,
123.1454 +     * producing extra tasks amortizes the uncertainty of progress and
123.1455 +     * diffusion assumptions.
123.1456 +     *
123.1457 +     * So, users will want to use values larger, but not much larger
123.1458 +     * than 1 to both smooth over transient shortages and hedge
123.1459 +     * against uneven progress; as traded off against the cost of
123.1460 +     * extra task overhead. We leave the user to pick a threshold
123.1461 +     * value to compare with the results of this call to guide
123.1462 +     * decisions, but recommend values such as 3.
123.1463 +     *
123.1464 +     * When all threads are active, it is on average OK to estimate
123.1465 +     * surplus strictly locally. In steady-state, if one thread is
123.1466 +     * maintaining say 2 surplus tasks, then so are others. So we can
123.1467 +     * just use estimated queue length (although note that (sp - base)
123.1468 +     * can be an overestimate because of stealers lagging increments
123.1469 +     * of base).  However, this strategy alone leads to serious
123.1470 +     * mis-estimates in some non-steady-state conditions (ramp-up,
123.1471 +     * ramp-down, other stalls). We can detect many of these by
123.1472 +     * further considering the number of "idle" threads, that are
123.1473 +     * known to have zero queued tasks, so compensate by a factor of
123.1474 +     * (#idle/#active) threads.
123.1475 +     */
123.1476 +    final int getEstimatedSurplusTaskCount() {
123.1477 +        return sp - base - pool.idlePerActive();
123.1478      }
123.1479  
123.1480      /**
123.1481       * Runs tasks until {@code pool.isQuiescent()}.
123.1482       */
123.1483      final void helpQuiescePool() {
123.1484 +        ForkJoinTask<?> ps = currentSteal; // to restore below
123.1485          for (;;) {
123.1486 -            ForkJoinTask<?> t = pollTask();
123.1487 -            if (t != null)
123.1488 +            ForkJoinTask<?> t = pollLocalTask();
123.1489 +            if (t != null || (t = scan()) != null)
123.1490                  t.quietlyExec();
123.1491 -            else if (tryInactivate() && pool.isQuiescent())
123.1492 -                break;
123.1493 +            else {
123.1494 +                ForkJoinPool p = pool;
123.1495 +                int a; // to inline CASes
123.1496 +                if (active) {
123.1497 +                    if (!UNSAFE.compareAndSwapInt
123.1498 +                        (p, poolRunStateOffset, a = p.runState, a - 1))
123.1499 +                        continue;   // retry later
123.1500 +                    active = false; // inactivate
123.1501 +                    UNSAFE.putOrderedObject(this, currentStealOffset, ps);
123.1502 +                }
123.1503 +                if (p.isQuiescent()) {
123.1504 +                    active = true; // re-activate
123.1505 +                    do {} while (!UNSAFE.compareAndSwapInt
123.1506 +                                 (p, poolRunStateOffset, a = p.runState, a+1));
123.1507 +                    return;
123.1508 +                }
123.1509 +            }
123.1510          }
123.1511 -        do {} while (!tryActivate()); // re-activate on exit
123.1512      }
123.1513  
123.1514      // Unsafe mechanics
123.1515 @@ -803,15 +1171,23 @@
123.1516          objectFieldOffset("sp", ForkJoinWorkerThread.class);
123.1517      private static final long runStateOffset =
123.1518          objectFieldOffset("runState", ForkJoinWorkerThread.class);
123.1519 -    private static final long qBase;
123.1520 +    private static final long currentJoinOffset =
123.1521 +        objectFieldOffset("currentJoin", ForkJoinWorkerThread.class);
123.1522 +    private static final long currentStealOffset =
123.1523 +        objectFieldOffset("currentSteal", ForkJoinWorkerThread.class);
123.1524 +    private static final long qBase =
123.1525 +        UNSAFE.arrayBaseOffset(ForkJoinTask[].class);
123.1526 +    private static final long poolRunStateOffset = // to inline CAS
123.1527 +        objectFieldOffset("runState", ForkJoinPool.class);
123.1528 +
123.1529      private static final int qShift;
123.1530  
123.1531      static {
123.1532 -        qBase = UNSAFE.arrayBaseOffset(ForkJoinTask[].class);
123.1533          int s = UNSAFE.arrayIndexScale(ForkJoinTask[].class);
123.1534          if ((s & (s-1)) != 0)
123.1535              throw new Error("data type scale not a power of two");
123.1536          qShift = 31 - Integer.numberOfLeadingZeros(s);
123.1537 +        MAXIMUM_QUEUE_CAPACITY = 1 << (31 - qShift);
123.1538      }
123.1539  
123.1540      private static long objectFieldOffset(String field, Class<?> klazz) {
   124.1 --- a/src/share/classes/java/util/concurrent/LinkedTransferQueue.java	Thu Sep 23 17:33:40 2010 -0700
   124.2 +++ b/src/share/classes/java/util/concurrent/LinkedTransferQueue.java	Fri Sep 24 16:41:32 2010 -0700
   124.3 @@ -42,6 +42,7 @@
   124.4  import java.util.NoSuchElementException;
   124.5  import java.util.Queue;
   124.6  import java.util.concurrent.locks.LockSupport;
   124.7 +
   124.8  /**
   124.9   * An unbounded {@link TransferQueue} based on linked nodes.
  124.10   * This queue orders elements FIFO (first-in-first-out) with respect
  124.11 @@ -233,24 +234,6 @@
  124.12       * additional GC bookkeeping ("write barriers") that are sometimes
  124.13       * more costly than the writes themselves because of contention).
  124.14       *
  124.15 -     * Removal of interior nodes (due to timed out or interrupted
  124.16 -     * waits, or calls to remove(x) or Iterator.remove) can use a
  124.17 -     * scheme roughly similar to that described in Scherer, Lea, and
  124.18 -     * Scott's SynchronousQueue. Given a predecessor, we can unsplice
  124.19 -     * any node except the (actual) tail of the queue. To avoid
  124.20 -     * build-up of cancelled trailing nodes, upon a request to remove
  124.21 -     * a trailing node, it is placed in field "cleanMe" to be
  124.22 -     * unspliced upon the next call to unsplice any other node.
  124.23 -     * Situations needing such mechanics are not common but do occur
  124.24 -     * in practice; for example when an unbounded series of short
  124.25 -     * timed calls to poll repeatedly time out but never otherwise
  124.26 -     * fall off the list because of an untimed call to take at the
  124.27 -     * front of the queue. Note that maintaining field cleanMe does
  124.28 -     * not otherwise much impact garbage retention even if never
  124.29 -     * cleared by some other call because the held node will
  124.30 -     * eventually either directly or indirectly lead to a self-link
  124.31 -     * once off the list.
  124.32 -     *
  124.33       * *** Overview of implementation ***
  124.34       *
  124.35       * We use a threshold-based approach to updates, with a slack
  124.36 @@ -266,15 +249,10 @@
  124.37       * per-thread one available, but even ThreadLocalRandom is too
  124.38       * heavy for these purposes.
  124.39       *
  124.40 -     * With such a small slack threshold value, it is rarely
  124.41 -     * worthwhile to augment this with path short-circuiting; i.e.,
  124.42 -     * unsplicing nodes between head and the first unmatched node, or
  124.43 -     * similarly for tail, rather than advancing head or tail
  124.44 -     * proper. However, it is used (in awaitMatch) immediately before
  124.45 -     * a waiting thread starts to block, as a final bit of helping at
  124.46 -     * a point when contention with others is extremely unlikely
  124.47 -     * (since if other threads that could release it are operating,
  124.48 -     * then the current thread wouldn't be blocking).
  124.49 +     * With such a small slack threshold value, it is not worthwhile
  124.50 +     * to augment this with path short-circuiting (i.e., unsplicing
  124.51 +     * interior nodes) except in the case of cancellation/removal (see
  124.52 +     * below).
  124.53       *
  124.54       * We allow both the head and tail fields to be null before any
  124.55       * nodes are enqueued; initializing upon first append.  This
  124.56 @@ -356,6 +334,70 @@
  124.57       *    versa) compared to their predecessors receive additional
  124.58       *    chained spins, reflecting longer paths typically required to
  124.59       *    unblock threads during phase changes.
  124.60 +     *
  124.61 +     *
  124.62 +     * ** Unlinking removed interior nodes **
  124.63 +     *
  124.64 +     * In addition to minimizing garbage retention via self-linking
  124.65 +     * described above, we also unlink removed interior nodes. These
  124.66 +     * may arise due to timed out or interrupted waits, or calls to
  124.67 +     * remove(x) or Iterator.remove.  Normally, given a node that was
  124.68 +     * at one time known to be the predecessor of some node s that is
  124.69 +     * to be removed, we can unsplice s by CASing the next field of
  124.70 +     * its predecessor if it still points to s (otherwise s must
  124.71 +     * already have been removed or is now offlist). But there are two
  124.72 +     * situations in which we cannot guarantee to make node s
  124.73 +     * unreachable in this way: (1) If s is the trailing node of list
  124.74 +     * (i.e., with null next), then it is pinned as the target node
  124.75 +     * for appends, so can only be removed later after other nodes are
  124.76 +     * appended. (2) We cannot necessarily unlink s given a
  124.77 +     * predecessor node that is matched (including the case of being
  124.78 +     * cancelled): the predecessor may already be unspliced, in which
  124.79 +     * case some previous reachable node may still point to s.
  124.80 +     * (For further explanation see Herlihy & Shavit "The Art of
  124.81 +     * Multiprocessor Programming" chapter 9).  Although, in both
  124.82 +     * cases, we can rule out the need for further action if either s
  124.83 +     * or its predecessor are (or can be made to be) at, or fall off
  124.84 +     * from, the head of list.
  124.85 +     *
  124.86 +     * Without taking these into account, it would be possible for an
  124.87 +     * unbounded number of supposedly removed nodes to remain
  124.88 +     * reachable.  Situations leading to such buildup are uncommon but
  124.89 +     * can occur in practice; for example when a series of short timed
  124.90 +     * calls to poll repeatedly time out but never otherwise fall off
  124.91 +     * the list because of an untimed call to take at the front of the
  124.92 +     * queue.
  124.93 +     *
  124.94 +     * When these cases arise, rather than always retraversing the
  124.95 +     * entire list to find an actual predecessor to unlink (which
  124.96 +     * won't help for case (1) anyway), we record a conservative
  124.97 +     * estimate of possible unsplice failures (in "sweepVotes").
  124.98 +     * We trigger a full sweep when the estimate exceeds a threshold
  124.99 +     * ("SWEEP_THRESHOLD") indicating the maximum number of estimated
 124.100 +     * removal failures to tolerate before sweeping through, unlinking
 124.101 +     * cancelled nodes that were not unlinked upon initial removal.
 124.102 +     * We perform sweeps by the thread hitting threshold (rather than
 124.103 +     * background threads or by spreading work to other threads)
 124.104 +     * because in the main contexts in which removal occurs, the
 124.105 +     * caller is already timed-out, cancelled, or performing a
 124.106 +     * potentially O(n) operation (e.g. remove(x)), none of which are
 124.107 +     * time-critical enough to warrant the overhead that alternatives
 124.108 +     * would impose on other threads.
 124.109 +     *
 124.110 +     * Because the sweepVotes estimate is conservative, and because
 124.111 +     * nodes become unlinked "naturally" as they fall off the head of
 124.112 +     * the queue, and because we allow votes to accumulate even while
 124.113 +     * sweeps are in progress, there are typically significantly fewer
 124.114 +     * such nodes than estimated.  Choice of a threshold value
 124.115 +     * balances the likelihood of wasted effort and contention, versus
 124.116 +     * providing a worst-case bound on retention of interior nodes in
 124.117 +     * quiescent queues. The value defined below was chosen
 124.118 +     * empirically to balance these under various timeout scenarios.
 124.119 +     *
 124.120 +     * Note that we cannot self-link unlinked interior nodes during
 124.121 +     * sweeps. However, the associated garbage chains terminate when
 124.122 +     * some successor ultimately falls off the head of the list and is
 124.123 +     * self-linked.
 124.124       */
 124.125  
 124.126      /** True if on multiprocessor */
 124.127 @@ -382,11 +424,19 @@
 124.128      private static final int CHAINED_SPINS = FRONT_SPINS >>> 1;
 124.129  
 124.130      /**
 124.131 +     * The maximum number of estimated removal failures (sweepVotes)
 124.132 +     * to tolerate before sweeping through the queue unlinking
 124.133 +     * cancelled nodes that were not unlinked upon initial
 124.134 +     * removal. See above for explanation. The value must be at least
 124.135 +     * two to avoid useless sweeps when removing trailing nodes.
 124.136 +     */
 124.137 +    static final int SWEEP_THRESHOLD = 32;
 124.138 +
 124.139 +    /**
 124.140       * Queue nodes. Uses Object, not E, for items to allow forgetting
 124.141       * them after use.  Relies heavily on Unsafe mechanics to minimize
 124.142 -     * unnecessary ordering constraints: Writes that intrinsically
 124.143 -     * precede or follow CASes use simple relaxed forms.  Other
 124.144 -     * cleanups use releasing/lazy writes.
 124.145 +     * unnecessary ordering constraints: Writes that are intrinsically
 124.146 +     * ordered wrt other accesses or CASes use simple relaxed forms.
 124.147       */
 124.148      static final class Node {
 124.149          final boolean isData;   // false if this is a request node
 124.150 @@ -400,13 +450,13 @@
 124.151          }
 124.152  
 124.153          final boolean casItem(Object cmp, Object val) {
 124.154 -            // assert cmp == null || cmp.getClass() != Node.class;
 124.155 +            //            assert cmp == null || cmp.getClass() != Node.class;
 124.156              return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
 124.157          }
 124.158  
 124.159          /**
 124.160 -         * Creates a new node. Uses relaxed write because item can only
 124.161 -         * be seen if followed by CAS.
 124.162 +         * Constructs a new node.  Uses relaxed write because item can
 124.163 +         * only be seen after publication via casNext.
 124.164           */
 124.165          Node(Object item, boolean isData) {
 124.166              UNSAFE.putObject(this, itemOffset, item); // relaxed write
 124.167 @@ -422,13 +472,17 @@
 124.168          }
 124.169  
 124.170          /**
 124.171 -         * Sets item to self (using a releasing/lazy write) and waiter
 124.172 -         * to null, to avoid garbage retention after extracting or
 124.173 -         * cancelling.
 124.174 +         * Sets item to self and waiter to null, to avoid garbage
 124.175 +         * retention after matching or cancelling. Uses relaxed writes
 124.176 +         * because order is already constrained in the only calling
 124.177 +         * contexts: item is forgotten only after volatile/atomic
 124.178 +         * mechanics that extract items.  Similarly, clearing waiter
 124.179 +         * follows either CAS or return from park (if ever parked;
 124.180 +         * else we don't care).
 124.181           */
 124.182          final void forgetContents() {
 124.183 -            UNSAFE.putOrderedObject(this, itemOffset, this);
 124.184 -            UNSAFE.putOrderedObject(this, waiterOffset, null);
 124.185 +            UNSAFE.putObject(this, itemOffset, this);
 124.186 +            UNSAFE.putObject(this, waiterOffset, null);
 124.187          }
 124.188  
 124.189          /**
 124.190 @@ -462,7 +516,7 @@
 124.191           * Tries to artificially match a data node -- used by remove.
 124.192           */
 124.193          final boolean tryMatchData() {
 124.194 -            // assert isData;
 124.195 +            //            assert isData;
 124.196              Object x = item;
 124.197              if (x != null && x != this && casItem(x, null)) {
 124.198                  LockSupport.unpark(waiter);
 124.199 @@ -486,12 +540,12 @@
 124.200      /** head of the queue; null until first enqueue */
 124.201      transient volatile Node head;
 124.202  
 124.203 -    /** predecessor of dangling unspliceable node */
 124.204 -    private transient volatile Node cleanMe; // decl here reduces contention
 124.205 -
 124.206      /** tail of the queue; null until first append */
 124.207      private transient volatile Node tail;
 124.208  
 124.209 +    /** The number of apparent failures to unsplice removed nodes */
 124.210 +    private transient volatile int sweepVotes;
 124.211 +
 124.212      // CAS methods for fields
 124.213      private boolean casTail(Node cmp, Node val) {
 124.214          return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
 124.215 @@ -501,8 +555,8 @@
 124.216          return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
 124.217      }
 124.218  
 124.219 -    private boolean casCleanMe(Node cmp, Node val) {
 124.220 -        return UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
 124.221 +    private boolean casSweepVotes(int cmp, int val) {
 124.222 +        return UNSAFE.compareAndSwapInt(this, sweepVotesOffset, cmp, val);
 124.223      }
 124.224  
 124.225      /*
 124.226 @@ -515,7 +569,7 @@
 124.227  
 124.228      @SuppressWarnings("unchecked")
 124.229      static <E> E cast(Object item) {
 124.230 -        // assert item == null || item.getClass() != Node.class;
 124.231 +        //        assert item == null || item.getClass() != Node.class;
 124.232          return (E) item;
 124.233      }
 124.234  
 124.235 @@ -544,10 +598,8 @@
 124.236                          break;
 124.237                      if (p.casItem(item, e)) { // match
 124.238                          for (Node q = p; q != h;) {
 124.239 -                            Node n = q.next;  // update head by 2
 124.240 -                            if (n != null)    // unless singleton
 124.241 -                                q = n;
 124.242 -                            if (head == h && casHead(h, q)) {
 124.243 +                            Node n = q.next;  // update by 2 unless singleton
 124.244 +                            if (head == h && casHead(h, n == null? q : n)) {
 124.245                                  h.forgetNext();
 124.246                                  break;
 124.247                              }                 // advance and retry
 124.248 @@ -632,12 +684,12 @@
 124.249          for (;;) {
 124.250              Object item = s.item;
 124.251              if (item != e) {                  // matched
 124.252 -                // assert item != s;
 124.253 +                //                assert item != s;
 124.254                  s.forgetContents();           // avoid garbage
 124.255                  return this.<E>cast(item);
 124.256              }
 124.257              if ((w.isInterrupted() || (timed && nanos <= 0)) &&
 124.258 -                    s.casItem(e, s)) {       // cancel
 124.259 +                    s.casItem(e, s)) {        // cancel
 124.260                  unsplice(pred, s);
 124.261                  return e;
 124.262              }
 124.263 @@ -647,9 +699,8 @@
 124.264                      randomYields = ThreadLocalRandom.current();
 124.265              }
 124.266              else if (spins > 0) {             // spin
 124.267 -                if (--spins == 0)
 124.268 -                    shortenHeadPath();        // reduce slack before blocking
 124.269 -                else if (randomYields.nextInt(CHAINED_SPINS) == 0)
 124.270 +                --spins;
 124.271 +                if (randomYields.nextInt(CHAINED_SPINS) == 0)
 124.272                      Thread.yield();           // occasionally yield
 124.273              }
 124.274              else if (s.waiter == null) {
 124.275 @@ -663,8 +714,6 @@
 124.276              }
 124.277              else {
 124.278                  LockSupport.park(this);
 124.279 -                s.waiter = null;
 124.280 -                spins = -1;                   // spin if front upon wakeup
 124.281              }
 124.282          }
 124.283      }
 124.284 @@ -685,27 +734,6 @@
 124.285          return 0;
 124.286      }
 124.287  
 124.288 -    /**
 124.289 -     * Tries (once) to unsplice nodes between head and first unmatched
 124.290 -     * or trailing node; failing on contention.
 124.291 -     */
 124.292 -    private void shortenHeadPath() {
 124.293 -        Node h, hn, p, q;
 124.294 -        if ((p = h = head) != null && h.isMatched() &&
 124.295 -            (q = hn = h.next) != null) {
 124.296 -            Node n;
 124.297 -            while ((n = q.next) != q) {
 124.298 -                if (n == null || !q.isMatched()) {
 124.299 -                    if (hn != q && h.next == hn)
 124.300 -                        h.casNext(hn, q);
 124.301 -                    break;
 124.302 -                }
 124.303 -                p = q;
 124.304 -                q = n;
 124.305 -            }
 124.306 -        }
 124.307 -    }
 124.308 -
 124.309      /* -------------- Traversal methods -------------- */
 124.310  
 124.311      /**
 124.312 @@ -818,7 +846,8 @@
 124.313          public final void remove() {
 124.314              Node p = lastRet;
 124.315              if (p == null) throw new IllegalStateException();
 124.316 -            findAndRemoveDataNode(lastPred, p);
 124.317 +            if (p.tryMatchData())
 124.318 +                unsplice(lastPred, p);
 124.319          }
 124.320      }
 124.321  
 124.322 @@ -828,99 +857,68 @@
 124.323       * Unsplices (now or later) the given deleted/cancelled node with
 124.324       * the given predecessor.
 124.325       *
 124.326 -     * @param pred predecessor of node to be unspliced
 124.327 +     * @param pred a node that was at one time known to be the
 124.328 +     * predecessor of s, or null or s itself if s is/was at head
 124.329       * @param s the node to be unspliced
 124.330       */
 124.331 -    private void unsplice(Node pred, Node s) {
 124.332 -        s.forgetContents(); // clear unneeded fields
 124.333 +    final void unsplice(Node pred, Node s) {
 124.334 +        s.forgetContents(); // forget unneeded fields
 124.335          /*
 124.336 -         * At any given time, exactly one node on list cannot be
 124.337 -         * unlinked -- the last inserted node. To accommodate this, if
 124.338 -         * we cannot unlink s, we save its predecessor as "cleanMe",
 124.339 -         * processing the previously saved version first. Because only
 124.340 -         * one node in the list can have a null next, at least one of
 124.341 -         * node s or the node previously saved can always be
 124.342 -         * processed, so this always terminates.
 124.343 +         * See above for rationale. Briefly: if pred still points to
 124.344 +         * s, try to unlink s.  If s cannot be unlinked, because it is
 124.345 +         * trailing node or pred might be unlinked, and neither pred
 124.346 +         * nor s are head or offlist, add to sweepVotes, and if enough
 124.347 +         * votes have accumulated, sweep.
 124.348           */
 124.349 -        if (pred != null && pred != s) {
 124.350 -            while (pred.next == s) {
 124.351 -                Node oldpred = (cleanMe == null) ? null : reclean();
 124.352 -                Node n = s.next;
 124.353 -                if (n != null) {
 124.354 -                    if (n != s)
 124.355 -                        pred.casNext(s, n);
 124.356 -                    break;
 124.357 +        if (pred != null && pred != s && pred.next == s) {
 124.358 +            Node n = s.next;
 124.359 +            if (n == null ||
 124.360 +                (n != s && pred.casNext(s, n) && pred.isMatched())) {
 124.361 +                for (;;) {               // check if at, or could be, head
 124.362 +                    Node h = head;
 124.363 +                    if (h == pred || h == s || h == null)
 124.364 +                        return;          // at head or list empty
 124.365 +                    if (!h.isMatched())
 124.366 +                        break;
 124.367 +                    Node hn = h.next;
 124.368 +                    if (hn == null)
 124.369 +                        return;          // now empty
 124.370 +                    if (hn != h && casHead(h, hn))
 124.371 +                        h.forgetNext();  // advance head
 124.372                  }
 124.373 -                if (oldpred == pred ||      // Already saved
 124.374 -                    ((oldpred == null || oldpred.next == s) &&
 124.375 -                     casCleanMe(oldpred, pred))) {
 124.376 -                    break;
 124.377 +                if (pred.next != pred && s.next != s) { // recheck if offlist
 124.378 +                    for (;;) {           // sweep now if enough votes
 124.379 +                        int v = sweepVotes;
 124.380 +                        if (v < SWEEP_THRESHOLD) {
 124.381 +                            if (casSweepVotes(v, v + 1))
 124.382 +                                break;
 124.383 +                        }
 124.384 +                        else if (casSweepVotes(v, 0)) {
 124.385 +                            sweep();
 124.386 +                            break;
 124.387 +                        }
 124.388 +                    }
 124.389                  }
 124.390              }
 124.391          }
 124.392      }
 124.393  
 124.394      /**
 124.395 -     * Tries to unsplice the deleted/cancelled node held in cleanMe
 124.396 -     * that was previously uncleanable because it was at tail.
 124.397 -     *
 124.398 -     * @return current cleanMe node (or null)
 124.399 +     * Unlinks matched (typically cancelled) nodes encountered in a
 124.400 +     * traversal from head.
 124.401       */
 124.402 -    private Node reclean() {
 124.403 -        /*
 124.404 -         * cleanMe is, or at one time was, predecessor of a cancelled
 124.405 -         * node s that was the tail so could not be unspliced.  If it
 124.406 -         * is no longer the tail, try to unsplice if necessary and
 124.407 -         * make cleanMe slot available.  This differs from similar
 124.408 -         * code in unsplice() because we must check that pred still
 124.409 -         * points to a matched node that can be unspliced -- if not,
 124.410 -         * we can (must) clear cleanMe without unsplicing.  This can
 124.411 -         * loop only due to contention.
 124.412 -         */
 124.413 -        Node pred;
 124.414 -        while ((pred = cleanMe) != null) {
 124.415 -            Node s = pred.next;
 124.416 -            Node n;
 124.417 -            if (s == null || s == pred || !s.isMatched())
 124.418 -                casCleanMe(pred, null); // already gone
 124.419 -            else if ((n = s.next) != null) {
 124.420 -                if (n != s)
 124.421 -                    pred.casNext(s, n);
 124.422 -                casCleanMe(pred, null);
 124.423 -            }
 124.424 +    private void sweep() {
 124.425 +        for (Node p = head, s, n; p != null && (s = p.next) != null; ) {
 124.426 +            if (!s.isMatched())
 124.427 +                // Unmatched nodes are never self-linked
 124.428 +                p = s;
 124.429 +            else if ((n = s.next) == null) // trailing node is pinned
 124.430 +                break;
 124.431 +            else if (s == n)    // stale
 124.432 +                // No need to also check for p == s, since that implies s == n
 124.433 +                p = head;
 124.434              else
 124.435 -                break;
 124.436 -        }
 124.437 -        return pred;
 124.438 -    }
 124.439 -
 124.440 -    /**
 124.441 -     * Main implementation of Iterator.remove(). Finds
 124.442 -     * and unsplices the given data node.
 124.443 -     *
 124.444 -     * @param possiblePred possible predecessor of s
 124.445 -     * @param s the node to remove
 124.446 -     */
 124.447 -    final void findAndRemoveDataNode(Node possiblePred, Node s) {
 124.448 -        // assert s.isData;
 124.449 -        if (s.tryMatchData()) {
 124.450 -            if (possiblePred != null && possiblePred.next == s)
 124.451 -                unsplice(possiblePred, s); // was actual predecessor
 124.452 -            else {
 124.453 -                for (Node pred = null, p = head; p != null; ) {
 124.454 -                    if (p == s) {
 124.455 -                        unsplice(pred, p);
 124.456 -                        break;
 124.457 -                    }
 124.458 -                    if (p.isUnmatchedRequest())
 124.459 -                        break;
 124.460 -                    pred = p;
 124.461 -                    if ((p = p.next) == pred) { // stale
 124.462 -                        pred = null;
 124.463 -                        p = head;
 124.464 -                    }
 124.465 -                }
 124.466 -            }
 124.467 +                p.casNext(s, n);
 124.468          }
 124.469      }
 124.470  
 124.471 @@ -1158,7 +1156,11 @@
 124.472       * @return {@code true} if this queue contains no elements
 124.473       */
 124.474      public boolean isEmpty() {
 124.475 -        return firstOfMode(true) == null;
 124.476 +        for (Node p = head; p != null; p = succ(p)) {
 124.477 +            if (!p.isMatched())
 124.478 +                return !p.isData;
 124.479 +        }
 124.480 +        return true;
 124.481      }
 124.482  
 124.483      public boolean hasWaitingConsumer() {
 124.484 @@ -1252,8 +1254,8 @@
 124.485          objectFieldOffset(UNSAFE, "head", LinkedTransferQueue.class);
 124.486      private static final long tailOffset =
 124.487          objectFieldOffset(UNSAFE, "tail", LinkedTransferQueue.class);
 124.488 -    private static final long cleanMeOffset =
 124.489 -        objectFieldOffset(UNSAFE, "cleanMe", LinkedTransferQueue.class);
 124.490 +    private static final long sweepVotesOffset =
 124.491 +        objectFieldOffset(UNSAFE, "sweepVotes", LinkedTransferQueue.class);
 124.492  
 124.493      static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
 124.494                                    String field, Class<?> klazz) {
 124.495 @@ -1266,5 +1268,4 @@
 124.496              throw error;
 124.497          }
 124.498      }
 124.499 -
 124.500  }
   125.1 --- a/src/share/classes/java/util/concurrent/Phaser.java	Thu Sep 23 17:33:40 2010 -0700
   125.2 +++ b/src/share/classes/java/util/concurrent/Phaser.java	Fri Sep 24 16:41:32 2010 -0700
   125.3 @@ -898,7 +898,7 @@
   125.4          boolean doWait() {
   125.5              if (thread != null) {
   125.6                  try {
   125.7 -                    ForkJoinPool.managedBlock(this, false);
   125.8 +                    ForkJoinPool.managedBlock(this);
   125.9                  } catch (InterruptedException ie) {
  125.10                  }
  125.11              }
   126.1 --- a/src/share/classes/java/util/spi/LocaleNameProvider.java	Thu Sep 23 17:33:40 2010 -0700
   126.2 +++ b/src/share/classes/java/util/spi/LocaleNameProvider.java	Fri Sep 24 16:41:32 2010 -0700
   126.3 @@ -1,5 +1,5 @@
   126.4  /*
   126.5 - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
   126.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   126.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   126.8   *
   126.9   * This code is free software; you can redistribute it and/or modify it
  126.10 @@ -44,22 +44,23 @@
  126.11      }
  126.12  
  126.13      /**
  126.14 -     * Returns a localized name for the given ISO 639 language code and the
  126.15 -     * given locale that is appropriate for display to the user.
  126.16 +     * Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
  126.17 +     * IETF BCP47</a> language code and the given locale that is appropriate for
  126.18 +     * display to the user.
  126.19       * For example, if <code>languageCode</code> is "fr" and <code>locale</code>
  126.20       * is en_US, getDisplayLanguage() will return "French"; if <code>languageCode</code>
  126.21       * is "en" and <code>locale</code> is fr_FR, getDisplayLanguage() will return "anglais".
  126.22       * If the name returned cannot be localized according to <code>locale</code>,
  126.23       * (say, the provider does not have a Japanese name for Croatian),
  126.24       * this method returns null.
  126.25 -     * @param languageCode the ISO 639 language code string in the form of two
  126.26 +     * @param languageCode the language code string in the form of two to eight
  126.27       *     lower-case letters between 'a' (U+0061) and 'z' (U+007A)
  126.28       * @param locale the desired locale
  126.29       * @return the name of the given language code for the specified locale, or null if it's not
  126.30       *     available.
  126.31       * @exception NullPointerException if <code>languageCode</code> or <code>locale</code> is null
  126.32       * @exception IllegalArgumentException if <code>languageCode</code> is not in the form of
  126.33 -     *     two lower-case letters, or <code>locale</code> isn't
  126.34 +     *     two or three lower-case letters, or <code>locale</code> isn't
  126.35       *     one of the locales returned from
  126.36       *     {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
  126.37       *     getAvailableLocales()}.
  126.38 @@ -68,22 +69,52 @@
  126.39      public abstract String getDisplayLanguage(String languageCode, Locale locale);
  126.40  
  126.41      /**
  126.42 -     * Returns a localized name for the given ISO 3166 country code and the
  126.43 -     * given locale that is appropriate for display to the user.
  126.44 +     * Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
  126.45 +     * IETF BCP47</a> script code and the given locale that is appropriate for
  126.46 +     * display to the user.
  126.47 +     * For example, if <code>scriptCode</code> is "Latn" and <code>locale</code>
  126.48 +     * is en_US, getDisplayScript() will return "Latin"; if <code>scriptCode</code>
  126.49 +     * is "Cyrl" and <code>locale</code> is fr_FR, getDisplayScript() will return "cyrillique".
  126.50 +     * If the name returned cannot be localized according to <code>locale</code>,
  126.51 +     * (say, the provider does not have a Japanese name for Cyrillic),
  126.52 +     * this method returns null.
  126.53 +     * @param scriptCode the four letter script code string in the form of title-case
  126.54 +     *     letters (the first letter is upper-case character between 'A' (U+0041) and
  126.55 +     *     'Z' (U+005A) followed by three lower-case character between 'a' (U+0061)
  126.56 +     *     and 'z' (U+007A)).
  126.57 +     * @param locale the desired locale
  126.58 +     * @return the name of the given script code for the specified locale, or null if it's not
  126.59 +     *     available.
  126.60 +     * @exception NullPointerException if <code>scriptCode</code> or <code>locale</code> is null
  126.61 +     * @exception IllegalArgumentException if <code>scriptCode</code> is not in the form of
  126.62 +     *     four title case letters, or <code>locale</code> isn't
  126.63 +     *     one of the locales returned from
  126.64 +     *     {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
  126.65 +     *     getAvailableLocales()}.
  126.66 +     * @see java.util.Locale#getDisplayScript(java.util.Locale)
  126.67 +     * @since 1.7
  126.68 +     */
  126.69 +    public abstract String getDisplayScript(String scriptCode, Locale locale);
  126.70 +
  126.71 +    /**
  126.72 +     * Returns a localized name for the given <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
  126.73 +     * IETF BCP47</a> region code (either ISO 3166 country code or UN M.49 area
  126.74 +     * codes) and the given locale that is appropriate for display to the user.
  126.75       * For example, if <code>countryCode</code> is "FR" and <code>locale</code>
  126.76       * is en_US, getDisplayCountry() will return "France"; if <code>countryCode</code>
  126.77       * is "US" and <code>locale</code> is fr_FR, getDisplayCountry() will return "Etats-Unis".
  126.78       * If the name returned cannot be localized according to <code>locale</code>,
  126.79       * (say, the provider does not have a Japanese name for Croatia),
  126.80       * this method returns null.
  126.81 -     * @param countryCode the ISO 3166 country code string in the form of two
  126.82 -     *     upper-case letters between 'A' (U+0041) and 'Z' (U+005A)
  126.83 +     * @param countryCode the country(region) code string in the form of two
  126.84 +     *     upper-case letters between 'A' (U+0041) and 'Z' (U+005A) or the UN M.49 area code
  126.85 +     *     in the form of three digit letters between '0' (U+0030) and '9' (U+0039).
  126.86       * @param locale the desired locale
  126.87       * @return the name of the given country code for the specified locale, or null if it's not
  126.88       *     available.
  126.89       * @exception NullPointerException if <code>countryCode</code> or <code>locale</code> is null
  126.90       * @exception IllegalArgumentException if <code>countryCode</code> is not in the form of
  126.91 -     *     two upper-case letters, or <code>locale</code> isn't
  126.92 +     *     two upper-case letters or three digit letters, or <code>locale</code> isn't
  126.93       *     one of the locales returned from
  126.94       *     {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
  126.95       *     getAvailableLocales()}.
   127.1 --- a/src/share/classes/java/util/spi/LocaleServiceProvider.java	Thu Sep 23 17:33:40 2010 -0700
   127.2 +++ b/src/share/classes/java/util/spi/LocaleServiceProvider.java	Fri Sep 24 16:41:32 2010 -0700
   127.3 @@ -86,18 +86,19 @@
   127.4   * Otherwise, they call the <code>getAvailableLocales()</code> methods of
   127.5   * installed providers for the appropriate interface to find one that
   127.6   * supports the requested locale. If such a provider is found, its other
   127.7 - * methods are called to obtain the requested object or name. If neither
   127.8 - * the Java runtime environment itself nor an installed provider supports
   127.9 - * the requested locale, a fallback locale is constructed by replacing the
  127.10 - * first of the variant, country, or language strings of the locale that's
  127.11 - * not an empty string with an empty string, and the lookup process is
  127.12 - * restarted. In the case that the variant contains one or more '_'s, the
  127.13 - * fallback locale is constructed by replacing the variant with a new variant
  127.14 - * which eliminates the last '_' and the part following it.  Even if a
  127.15 - * fallback occurs, methods that return requested objects or name are
  127.16 - * invoked with the original locale before the fallback.The Java runtime
  127.17 - * environment must support the root locale for all locale sensitive services
  127.18 - * in order to guarantee that this process terminates.
  127.19 + * methods are called to obtain the requested object or name.  When checking
  127.20 + * whether a locale is supported, the locale's extensions are ignored.
  127.21 + * If neither the Java runtime environment itself nor an installed provider
  127.22 + * supports the requested locale, the methods go through a list of candidate
  127.23 + * locales and repeat the availability check for each until a match is found.
  127.24 + * The algorithm used for creating a list of candidate locales is same as
  127.25 + * the one used by <code>ResourceBunlde</code> by default (see
  127.26 + * {@link java.util.ResourceBundle.Control#getCandidateLocales getCandidateLocales}
  127.27 + * for the details).  Even if a locale is resolved from the candidate list,
  127.28 + * methods that return requested objects or names are invoked with the original
  127.29 + * requested locale including extensions.  The Java runtime environment must
  127.30 + * support the root locale for all locale sensitive services in order to
  127.31 + * guarantee that this process terminates.
  127.32   * <p>
  127.33   * Providers of names (but not providers of other objects) are allowed to
  127.34   * return null for some name requests even for locales that they claim to
  127.35 @@ -124,6 +125,11 @@
  127.36      /**
  127.37       * Returns an array of all locales for which this locale service provider
  127.38       * can provide localized objects or names.
  127.39 +     * <p>
  127.40 +     * <b>Note:</b> Extensions in a <code>Locale</code> are ignored during
  127.41 +     * service provider lookup.  So the array returned by this method should
  127.42 +     * not include two or more <code>Locale</code> objects only differing in
  127.43 +     * their extensions.
  127.44       *
  127.45       * @return An array of all locales for which this locale service provider
  127.46       * can provide localized objects or names.
   128.1 --- a/src/share/classes/javax/sound/midi/MidiDevice.java	Thu Sep 23 17:33:40 2010 -0700
   128.2 +++ b/src/share/classes/javax/sound/midi/MidiDevice.java	Fri Sep 24 16:41:32 2010 -0700
   128.3 @@ -204,6 +204,9 @@
   128.4       * MIDI data.  The returned receiver must be closed when the application
   128.5       * has finished using it.
   128.6       *
   128.7 +     * <p>Usually the returned receiver implements
   128.8 +     * the {@code MidiDeviceReceiver} interface.
   128.9 +     *
  128.10       * <p>Obtaining a <code>Receiver</code> with this method does not
  128.11       * open the device. To be able to use the device, it has to be
  128.12       * opened explicitly by calling {@link #open}. Also, closing the
  128.13 @@ -223,6 +226,10 @@
  128.14       * connected with this MidiDevice.
  128.15       * A receiver can be removed
  128.16       * from the device by closing it.
  128.17 +     *
  128.18 +     * <p>Usually the returned receivers implement
  128.19 +     * the {@code MidiDeviceReceiver} interface.
  128.20 +     *
  128.21       * @return an unmodifiable list of the open receivers
  128.22       * @since 1.5
  128.23       */
  128.24 @@ -234,6 +241,9 @@
  128.25       * MIDI data  The returned transmitter must be closed when the application
  128.26       * has finished using it.
  128.27       *
  128.28 +     * <p>Usually the returned transmitter implements
  128.29 +     * the {@code MidiDeviceTransmitter} interface.
  128.30 +     *
  128.31       * <p>Obtaining a <code>Transmitter</code> with this method does not
  128.32       * open the device. To be able to use the device, it has to be
  128.33       * opened explicitly by calling {@link #open}. Also, closing the
  128.34 @@ -253,6 +263,10 @@
  128.35       * connected with this MidiDevice.
  128.36       * A transmitter can be removed
  128.37       * from the device by closing it.
  128.38 +     *
  128.39 +     * <p>Usually the returned transmitters implement
  128.40 +     * the {@code MidiDeviceTransmitter} interface.
  128.41 +     *
  128.42       * @return an unmodifiable list of the open transmitters
  128.43       * @since 1.5
  128.44       */
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/src/share/classes/javax/sound/midi/MidiDeviceReceiver.java	Fri Sep 24 16:41:32 2010 -0700
   129.3 @@ -0,0 +1,39 @@
   129.4 +/*
   129.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   129.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   129.7 + *
   129.8 + * This code is free software; you can redistribute it and/or modify it
   129.9 + * under the terms of the GNU General Public License version 2 only, as
  129.10 + * published by the Free Software Foundation.  Oracle designates this
  129.11 + * particular file as subject to the "Classpath" exception as provided
  129.12 + * by Oracle in the LICENSE file that accompanied this code.
  129.13 + *
  129.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  129.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  129.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  129.17 + * version 2 for more details (a copy is included in the LICENSE file that
  129.18 + * accompanied this code).
  129.19 + *
  129.20 + * You should have received a copy of the GNU General Public License version
  129.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  129.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  129.23 + *
  129.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  129.25 + * or visit www.oracle.com if you need additional information or have any
  129.26 + * questions.
  129.27 + */
  129.28 +
  129.29 +package javax.sound.midi;
  129.30 +
  129.31 +/**
  129.32 + * <p>{@code MidiDeviceReceiver} is a {@code Receiver} which represents
  129.33 + * a MIDI input connector of a {@code MidiDevice}
  129.34 + * (see {@link MidiDevice#getReceiver()}).
  129.35 + *
  129.36 + * @since 1.7
  129.37 + */
  129.38 +public interface MidiDeviceReceiver extends Receiver {
  129.39 +    /** Obtains a MidiDevice object which is an owner of this Receiver.
  129.40 +     */
  129.41 +    public MidiDevice getMidiDevice();
  129.42 +}
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/src/share/classes/javax/sound/midi/MidiDeviceTransmitter.java	Fri Sep 24 16:41:32 2010 -0700
   130.3 @@ -0,0 +1,41 @@
   130.4 +/*
   130.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   130.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   130.7 + *
   130.8 + * This code is free software; you can redistribute it and/or modify it
   130.9 + * under the terms of the GNU General Public License version 2 only, as
  130.10 + * published by the Free Software Foundation.  Oracle designates this
  130.11 + * particular file as subject to the "Classpath" exception as provided
  130.12 + * by Oracle in the LICENSE file that accompanied this code.
  130.13 + *
  130.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  130.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  130.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  130.17 + * version 2 for more details (a copy is included in the LICENSE file that
  130.18 + * accompanied this code).
  130.19 + *
  130.20 + * You should have received a copy of the GNU General Public License version
  130.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  130.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  130.23 + *
  130.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  130.25 + * or visit www.oracle.com if you need additional information or have any
  130.26 + * questions.
  130.27 + */
  130.28 +
  130.29 +package javax.sound.midi;
  130.30 +
  130.31 +
  130.32 +/**
  130.33 + * <p>{@code MidiDeviceTransmitter} is a {@code Transmitter} which represents
  130.34 + * a MIDI input connector of a {@code MidiDevice}
  130.35 + * (see {@link MidiDevice#getTransmitter()}).
  130.36 + *
  130.37 + * @since 1.7
  130.38 + */
  130.39 +public interface MidiDeviceTransmitter extends Transmitter {
  130.40 +
  130.41 +    /** Obtains a MidiDevice object which is an owner of this Transmitter.
  130.42 +     */
  130.43 +    public MidiDevice getMidiDevice();
  130.44 +}
   131.1 --- a/src/share/classes/javax/sound/midi/MidiSystem.java	Thu Sep 23 17:33:40 2010 -0700
   131.2 +++ b/src/share/classes/javax/sound/midi/MidiSystem.java	Fri Sep 24 16:41:32 2010 -0700
   131.3 @@ -47,6 +47,8 @@
   131.4  import com.sun.media.sound.JDK13Services;
   131.5  import com.sun.media.sound.ReferenceCountingDevice;
   131.6  import com.sun.media.sound.AutoConnectSequencer;
   131.7 +import com.sun.media.sound.MidiDeviceReceiverEnvelope;
   131.8 +import com.sun.media.sound.MidiDeviceTransmitterEnvelope;
   131.9  
  131.10  
  131.11  /**
  131.12 @@ -225,6 +227,8 @@
  131.13      /**
  131.14       * Obtains a MIDI receiver from an external MIDI port
  131.15       * or other default device.
  131.16 +     * The returned receiver always implements
  131.17 +     * the {@code MidiDeviceReceiver} interface.
  131.18       *
  131.19       * <p>If the system property
  131.20       * <code>javax.sound.midi.Receiver</code>
  131.21 @@ -261,6 +265,9 @@
  131.22          } else {
  131.23              receiver = device.getReceiver();
  131.24          }
  131.25 +        if (!(receiver instanceof MidiDeviceReceiver)) {
  131.26 +            receiver = new MidiDeviceReceiverEnvelope(device, receiver);
  131.27 +        }
  131.28          return receiver;
  131.29      }
  131.30  
  131.31 @@ -268,6 +275,8 @@
  131.32      /**
  131.33       * Obtains a MIDI transmitter from an external MIDI port
  131.34       * or other default source.
  131.35 +     * The returned transmitter always implements
  131.36 +     * the {@code MidiDeviceTransmitter} interface.
  131.37       *
  131.38       * <p>If the system property
  131.39       * <code>javax.sound.midi.Transmitter</code>
  131.40 @@ -301,6 +310,9 @@
  131.41          } else {
  131.42              transmitter = device.getTransmitter();
  131.43          }
  131.44 +        if (!(transmitter instanceof MidiDeviceReceiver)) {
  131.45 +            transmitter = new MidiDeviceTransmitterEnvelope(device, transmitter);
  131.46 +        }
  131.47          return transmitter;
  131.48      }
  131.49  
   132.1 --- a/src/share/classes/javax/sound/sampled/AudioFormat.java	Thu Sep 23 17:33:40 2010 -0700
   132.2 +++ b/src/share/classes/javax/sound/sampled/AudioFormat.java	Fri Sep 24 16:41:32 2010 -0700
   132.3 @@ -1,5 +1,5 @@
   132.4  /*
   132.5 - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
   132.6 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
   132.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   132.8   *
   132.9   * This code is free software; you can redistribute it and/or modify it
  132.10 @@ -431,34 +431,36 @@
  132.11  
  132.12  
  132.13      /**
  132.14 -     * Indicates whether this format matches the one specified.  To match,
  132.15 -     * two formats must have the same encoding, the same number of channels,
  132.16 -     * and the same number of bits per sample and bytes per frame.
  132.17 -     * The two formats must also have the same sample rate,
  132.18 -     * unless the specified format has the sample rate value <code>AudioSystem.NOT_SPECIFIED</code>,
  132.19 -     * which any sample rate will match.  The frame rates must
  132.20 -     * similarly be equal, unless the specified format has the frame rate
  132.21 -     * value <code>AudioSystem.NOT_SPECIFIED</code>.  The byte order (big-endian or little-endian)
  132.22 -     * must match if the sample size is greater than one byte.
  132.23 +     * Indicates whether this format matches the one specified.
  132.24 +     * To match, two formats must have the same encoding,
  132.25 +     * and consistent values of the number of channels, sample rate, sample size,
  132.26 +     * frame rate, and frame size.
  132.27 +     * The values of the property are consistent if they are equal
  132.28 +     * or the specified format has the property value
  132.29 +     * {@code AudioSystem.NOT_SPECIFIED}.
  132.30 +     * The byte order (big-endian or little-endian) must be the same
  132.31 +     * if the sample size is greater than one byte.
  132.32       *
  132.33       * @param format format to test for match
  132.34 -     * @return <code>true</code> if this format matches the one specified,
  132.35 -     * <code>false</code> otherwise.
  132.36 -     */
  132.37 -    /*
  132.38 -     * $$kk: 04.20.99: i changed the semantics of this.
  132.39 +     * @return {@code true} if this format matches the one specified,
  132.40 +     *         {@code false} otherwise.
  132.41       */
  132.42      public boolean matches(AudioFormat format) {
  132.43 -
  132.44 -        if (format.getEncoding().equals(getEncoding()) &&
  132.45 -            ( (format.getSampleRate() == (float)AudioSystem.NOT_SPECIFIED) || (format.getSampleRate() == getSampleRate()) ) &&
  132.46 -            (format.getSampleSizeInBits() == getSampleSizeInBits()) &&
  132.47 -            (format.getChannels() == getChannels() &&
  132.48 -             (format.getFrameSize() == getFrameSize()) &&
  132.49 -             ( (format.getFrameRate() == (float)AudioSystem.NOT_SPECIFIED) || (format.getFrameRate() == getFrameRate()) ) &&
  132.50 -             ( (format.getSampleSizeInBits() <= 8)  || (format.isBigEndian() == isBigEndian()) ) ) )
  132.51 +        if (format.getEncoding().equals(getEncoding())
  132.52 +                && (format.getChannels() == AudioSystem.NOT_SPECIFIED
  132.53 +                    || format.getChannels() == getChannels())
  132.54 +                && (format.getSampleRate() == (float)AudioSystem.NOT_SPECIFIED
  132.55 +                    || format.getSampleRate() == getSampleRate())
  132.56 +                && (format.getSampleSizeInBits() == AudioSystem.NOT_SPECIFIED
  132.57 +                    || format.getSampleSizeInBits() == getSampleSizeInBits())
  132.58 +                && (format.getFrameRate() == (float)AudioSystem.NOT_SPECIFIED
  132.59 +                    || format.getFrameRate() == getFrameRate())
  132.60 +                && (format.getFrameSize() == AudioSystem.NOT_SPECIFIED
  132.61 +                    || format.getFrameSize() == getFrameSize())
  132.62 +                && (getSampleSizeInBits() <= 8
  132.63 +                    || format.isBigEndian() == isBigEndian())) {
  132.64              return true;
  132.65 -
  132.66 +        }
  132.67          return false;
  132.68      }
  132.69  
  132.70 @@ -552,14 +554,14 @@
  132.71       * which is simply a linear (proportional) representation of the sound
  132.72       * waveform.  With PCM, the number stored in each sample is proportional
  132.73       * to the instantaneous amplitude of the sound pressure at that point in
  132.74 -     * time.  The numbers are frequently signed or unsigned integers.
  132.75 +     * time.  The numbers may be signed or unsigned integers or floats.
  132.76       * Besides PCM, other encodings include mu-law and a-law, which are nonlinear
  132.77       * mappings of the sound amplitude that are often used for recording speech.
  132.78       * <p>
  132.79       * You can use a predefined encoding by referring to one of the static
  132.80       * objects created by this class, such as PCM_SIGNED or
  132.81       * PCM_UNSIGNED.  Service providers can create new encodings, such as
  132.82 -     * compressed audio formats or floating-point PCM samples, and make
  132.83 +     * compressed audio formats, and make
  132.84       * these available through the <code>{@link AudioSystem}</code> class.
  132.85       * <p>
  132.86       * The <code>Encoding</code> class is static, so that all
  132.87 @@ -590,6 +592,13 @@
  132.88          public static final Encoding PCM_UNSIGNED = new Encoding("PCM_UNSIGNED");
  132.89  
  132.90          /**
  132.91 +         * Specifies floating-point PCM data.
  132.92 +         *
  132.93 +         * @since 1.7
  132.94 +         */
  132.95 +        public static final Encoding PCM_FLOAT = new Encoding("PCM_FLOAT");
  132.96 +
  132.97 +        /**
  132.98           * Specifies u-law encoded data.
  132.99           */
 132.100          public static final Encoding ULAW = new Encoding("ULAW");
   133.1 --- a/src/share/classes/javax/sql/CommonDataSource.java	Thu Sep 23 17:33:40 2010 -0700
   133.2 +++ b/src/share/classes/javax/sql/CommonDataSource.java	Fri Sep 24 16:41:32 2010 -0700
   133.3 @@ -1,5 +1,5 @@
   133.4  /*
   133.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
   133.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   133.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   133.8   *
   133.9   * This code is free software; you can redistribute it and/or modify it
  133.10 @@ -27,6 +27,8 @@
  133.11  
  133.12  import java.sql.SQLException;
  133.13  import java.io.PrintWriter;
  133.14 +import java.sql.SQLFeatureNotSupportedException;
  133.15 +import java.util.logging.Logger;
  133.16  
  133.17  /**
  133.18   * Interface that defines the methods which are common between <code>DataSource</code>,
  133.19 @@ -35,79 +37,93 @@
  133.20   */
  133.21  public interface CommonDataSource {
  133.22  
  133.23 -  /**
  133.24 -   * <p>Retrieves the log writer for this <code>DataSource</code>
  133.25 -   * object.
  133.26 -   *
  133.27 -   * <p>The log writer is a character output stream to which all logging
  133.28 -   * and tracing messages for this data source will be
  133.29 -   * printed.  This includes messages printed by the methods of this
  133.30 -   * object, messages printed by methods of other objects manufactured
  133.31 -   * by this object, and so on.  Messages printed to a data source
  133.32 -   * specific log writer are not printed to the log writer associated
  133.33 -   * with the <code>java.sql.DriverManager</code> class.  When a
  133.34 -   * <code>DataSource</code> object is
  133.35 -   * created, the log writer is initially null; in other words, the
  133.36 -   * default is for logging to be disabled.
  133.37 -   *
  133.38 -   * @return the log writer for this data source or null if
  133.39 -   *        logging is disabled
  133.40 -   * @exception java.sql.SQLException if a database access error occurs
  133.41 -   * @see #setLogWriter
  133.42 -   * @since 1.4
  133.43 -   */
  133.44 -  java.io.PrintWriter getLogWriter() throws SQLException;
  133.45 +    /**
  133.46 +     * <p>Retrieves the log writer for this <code>DataSource</code>
  133.47 +     * object.
  133.48 +     *
  133.49 +     * <p>The log writer is a character output stream to which all logging
  133.50 +     * and tracing messages for this data source will be
  133.51 +     * printed.  This includes messages printed by the methods of this
  133.52 +     * object, messages printed by methods of other objects manufactured
  133.53 +     * by this object, and so on.  Messages printed to a data source
  133.54 +     * specific log writer are not printed to the log writer associated
  133.55 +     * with the <code>java.sql.DriverManager</code> class.  When a
  133.56 +     * <code>DataSource</code> object is
  133.57 +     * created, the log writer is initially null; in other words, the
  133.58 +     * default is for logging to be disabled.
  133.59 +     *
  133.60 +     * @return the log writer for this data source or null if
  133.61 +     *        logging is disabled
  133.62 +     * @exception java.sql.SQLException if a database access error occurs
  133.63 +     * @see #setLogWriter
  133.64 +     * @since 1.4
  133.65 +     */
  133.66 +    java.io.PrintWriter getLogWriter() throws SQLException;
  133.67  
  133.68 -  /**
  133.69 -   * <p>Sets the log writer for this <code>DataSource</code>
  133.70 -   * object to the given <code>java.io.PrintWriter</code> object.
  133.71 -   *
  133.72 -   * <p>The log writer is a character output stream to which all logging
  133.73 -   * and tracing messages for this data source will be
  133.74 -   * printed.  This includes messages printed by the methods of this
  133.75 -   * object, messages printed by methods of other objects manufactured
  133.76 -   * by this object, and so on.  Messages printed to a data source-
  133.77 -   * specific log writer are not printed to the log writer associated
  133.78 -   * with the <code>java.sql.DriverManager</code> class. When a
  133.79 -   * <code>DataSource</code> object is created the log writer is
  133.80 -   * initially null; in other words, the default is for logging to be
  133.81 -   * disabled.
  133.82 -   *
  133.83 -   * @param out the new log writer; to disable logging, set to null
  133.84 -   * @exception SQLException if a database access error occurs
  133.85 -   * @see #getLogWriter
  133.86 -   * @since 1.4
  133.87 -   */
  133.88 -  void setLogWriter(java.io.PrintWriter out) throws SQLException;
  133.89 +    /**
  133.90 +     * <p>Sets the log writer for this <code>DataSource</code>
  133.91 +     * object to the given <code>java.io.PrintWriter</code> object.
  133.92 +     *
  133.93 +     * <p>The log writer is a character output stream to which all logging
  133.94 +     * and tracing messages for this data source will be
  133.95 +     * printed.  This includes messages printed by the methods of this
  133.96 +     * object, messages printed by methods of other objects manufactured
  133.97 +     * by this object, and so on.  Messages printed to a data source-
  133.98 +     * specific log writer are not printed to the log writer associated
  133.99 +     * with the <code>java.sql.DriverManager</code> class. When a
 133.100 +     * <code>DataSource</code> object is created the log writer is
 133.101 +     * initially null; in other words, the default is for logging to be
 133.102 +     * disabled.
 133.103 +     *
 133.104 +     * @param out the new log writer; to disable logging, set to null
 133.105 +     * @exception SQLException if a database access error occurs
 133.106 +     * @see #getLogWriter
 133.107 +     * @since 1.4
 133.108 +     */
 133.109 +    void setLogWriter(java.io.PrintWriter out) throws SQLException;
 133.110  
 133.111 -  /**
 133.112 -   * <p>Sets the maximum time in seconds that this data source will wait
 133.113 -   * while attempting to connect to a database.  A value of zero
 133.114 -   * specifies that the timeout is the default system timeout
 133.115 -   * if there is one; otherwise, it specifies that there is no timeout.
 133.116 -   * When a <code>DataSource</code> object is created, the login timeout is
 133.117 -   * initially zero.
 133.118 -   *
 133.119 -   * @param seconds the data source login time limit
 133.120 -   * @exception SQLException if a database access error occurs.
 133.121 -   * @see #getLoginTimeout
 133.122 -   * @since 1.4
 133.123 -   */
 133.124 -  void setLoginTimeout(int seconds) throws SQLException;
 133.125 +    /**
 133.126 +     * <p>Sets the maximum time in seconds that this data source will wait
 133.127 +     * while attempting to connect to a database.  A value of zero
 133.128 +     * specifies that the timeout is the default system timeout
 133.129 +     * if there is one; otherwise, it specifies that there is no timeout.
 133.130 +     * When a <code>DataSource</code> object is created, the login timeout is
 133.131 +     * initially zero.
 133.132 +     *
 133.133 +     * @param seconds the data source login time limit
 133.134 +     * @exception SQLException if a database access error occurs.
 133.135 +     * @see #getLoginTimeout
 133.136 +     * @since 1.4
 133.137 +     */
 133.138 +    void setLoginTimeout(int seconds) throws SQLException;
 133.139  
 133.140 -  /**
 133.141 -   * Gets the maximum time in seconds that this data source can wait
 133.142 -   * while attempting to connect to a database.  A value of zero
 133.143 -   * means that the timeout is the default system timeout
 133.144 -   * if there is one; otherwise, it means that there is no timeout.
 133.145 -   * When a <code>DataSource</code> object is created, the login timeout is
 133.146 -   * initially zero.
 133.147 -   *
 133.148 -   * @return the data source login time limit
 133.149 -   * @exception SQLException if a database access error occurs.
 133.150 -   * @see #setLoginTimeout
 133.151 -   * @since 1.4
 133.152 -   */
 133.153 -  int getLoginTimeout() throws SQLException;
 133.154 +    /**
 133.155 +     * Gets the maximum time in seconds that this data source can wait
 133.156 +     * while attempting to connect to a database.  A value of zero
 133.157 +     * means that the timeout is the default system timeout
 133.158 +     * if there is one; otherwise, it means that there is no timeout.
 133.159 +     * When a <code>DataSource</code> object is created, the login timeout is
 133.160 +     * initially zero.
 133.161 +     *
 133.162 +     * @return the data source login time limit
 133.163 +     * @exception SQLException if a database access error occurs.
 133.164 +     * @see #setLoginTimeout
 133.165 +     * @since 1.4
 133.166 +     */
 133.167 +    int getLoginTimeout() throws SQLException;
 133.168  
 133.169 +    //------------------------- JDBC 4.1 -----------------------------------
 133.170 +
 133.171 +    /**
 133.172 +     * Return the parent Logger of all the Loggers used by this data source. This
 133.173 +     * should be the Logger farthest from the root Logger that is
 133.174 +     * still an ancestor of all of the Loggers used by this data source. Configuring
 133.175 +     * this Logger will affect all of the log messages generated by the data source.
 133.176 +     * In the worst case, this may be the root Logger.
 133.177 +     *
 133.178 +     * @return the parent Logger for this data source
 133.179 +     * @throws SQLFeatureNotSupportedException if the data source does not use <code>java.util.logging<code>.
 133.180 +     * @since 1.7
 133.181 +     */
 133.182 +    public Logger getParentLogger() throws SQLFeatureNotSupportedException;
 133.183  }
   134.1 --- a/src/share/classes/javax/sql/rowset/CachedRowSet.java	Thu Sep 23 17:33:40 2010 -0700
   134.2 +++ b/src/share/classes/javax/sql/rowset/CachedRowSet.java	Fri Sep 24 16:41:32 2010 -0700
   134.3 @@ -1,5 +1,5 @@
   134.4  /*
   134.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
   134.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   134.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   134.8   *
   134.9   * This code is free software; you can redistribute it and/or modify it
  134.10 @@ -644,10 +644,10 @@
  134.11      * of <code>execute</code> that takes a <code>ResultSet</code> object.
  134.12      *
  134.13      * @param data the <code>ResultSet</code> object containing the data
  134.14 -    *           to be read into this <code>CachedRowSet</code> object
  134.15 +    * to be read into this <code>CachedRowSet</code> object
  134.16      * @throws SQLException if a null <code>ResultSet</code> object is supplied
  134.17 -    *           or this <code>CachedRowSet</code> object cannot
  134.18 -    *           retrieve the associated <code>ResultSetMetaData</code> object
  134.19 +    * or this <code>CachedRowSet</code> object cannot
  134.20 +    * retrieve the associated <code>ResultSetMetaData</code> object
  134.21      * @see #execute
  134.22      * @see java.sql.ResultSet
  134.23      * @see java.sql.ResultSetMetaData
  134.24 @@ -674,10 +674,10 @@
  134.25      * to commit outstanding updates, those updates are lost.
  134.26      *
  134.27      * @param conn a standard JDBC <code>Connection</code> object with valid
  134.28 -    *           properties
  134.29 +    * properties
  134.30      * @throws SQLException if an invalid <code>Connection</code> object is supplied
  134.31 -    *           or an error occurs in establishing the connection to the
  134.32 -    *           data source
  134.33 +    * or an error occurs in establishing the connection to the
  134.34 +    * data source
  134.35      * @see #populate
  134.36      * @see java.sql.Connection
  134.37      */
  134.38 @@ -736,8 +736,8 @@
  134.39      *
  134.40      * @throws SQLException if the cursor is on the insert row
  134.41      * @throws SyncProviderException if the underlying
  134.42 -    *           synchronization provider's writer fails to write the updates
  134.43 -    *           back to the data source
  134.44 +    * synchronization provider's writer fails to write the updates
  134.45 +    * back to the data source
  134.46      * @see #acceptChanges(java.sql.Connection)
  134.47      * @see javax.sql.RowSetWriter
  134.48      * @see javax.sql.rowset.spi.SyncFactory
  134.49 @@ -807,8 +807,8 @@
  134.50      * @param con a standard JDBC <code>Connection</code> object
  134.51      * @throws SQLException if the cursor is on the insert row
  134.52      * @throws SyncProviderException if the underlying
  134.53 -    *           synchronization provider's writer fails to write the updates
  134.54 -    *           back to the data source
  134.55 +    * synchronization provider's writer fails to write the updates
  134.56 +    * back to the data source
  134.57      * @see #acceptChanges()
  134.58      * @see javax.sql.RowSetWriter
  134.59      * @see javax.sql.rowset.spi.SyncFactory
  134.60 @@ -867,7 +867,7 @@
  134.61      * the rowset's Java VM resources.
  134.62      *
  134.63      * @throws SQLException if an error occurs flushing the contents of this
  134.64 -    *           <code>CachedRowSet</code> object
  134.65 +    * <code>CachedRowSet</code> object
  134.66      * @see javax.sql.RowSetListener#rowSetChanged
  134.67      * @see java.sql.ResultSet#close
  134.68      */
  134.69 @@ -948,9 +948,9 @@
  134.70      *
  134.71      * @param idx an <code>int</code> identifying the column to be checked for updates
  134.72      * @return <code>true</code> if the designated column has been visibly updated;
  134.73 -    *           <code>false</code> otherwise
  134.74 +    * <code>false</code> otherwise
  134.75      * @throws SQLException if the cursor is on the insert row, before the first row,
  134.76 -    *       or after the last row
  134.77 +    *     or after the last row
  134.78      * @see java.sql.DatabaseMetaData#updatesAreDetected
  134.79      */
  134.80      public boolean columnUpdated(int idx) throws SQLException;
  134.81 @@ -963,9 +963,9 @@
  134.82      * @param columnName a <code>String</code> object giving the name of the
  134.83      *        column to be checked for updates
  134.84      * @return <code>true</code> if the column has been visibly updated;
  134.85 -    *           <code>false</code> otherwise
  134.86 +    * <code>false</code> otherwise
  134.87      * @throws SQLException if the cursor is on the insert row, before the first row,
  134.88 -    *       or after the last row
  134.89 +    *      or after the last row
  134.90      * @see java.sql.DatabaseMetaData#updatesAreDetected
  134.91      */
  134.92      public boolean columnUpdated(String columnName) throws SQLException;
  134.93 @@ -1003,7 +1003,7 @@
  134.94      * <P>
  134.95      *
  134.96      * @return a <code>Collection</code> object that contains the values in
  134.97 -    *           each row in this <code>CachedRowSet</code> object
  134.98 +    * each row in this <code>CachedRowSet</code> object
  134.99      * @throws SQLException if an error occurs generating the collection
 134.100      * @see #toCollection(int)
 134.101      * @see #toCollection(String)
 134.102 @@ -1030,10 +1030,10 @@
 134.103      * @param column an <code>int</code> indicating the column whose values
 134.104      *        are to be represented in a <code>Collection</code> object
 134.105      * @return a <code>Collection</code> object that contains the values
 134.106 -    *           stored in the specified column of this <code>CachedRowSet</code>
 134.107 -    *           object
 134.108 +    * stored in the specified column of this <code>CachedRowSet</code>
 134.109 +    * object
 134.110      * @throws SQLException if an error occurs generating the collection or
 134.111 -    *           an invalid column id is provided
 134.112 +    * an invalid column id is provided
 134.113      * @see #toCollection
 134.114      * @see #toCollection(String)
 134.115      */
 134.116 @@ -1059,10 +1059,10 @@
 134.117      * @param column a <code>String</code> object giving the name of the
 134.118      *        column whose values are to be represented in a collection
 134.119      * @return a <code>Collection</code> object that contains the values
 134.120 -    *           stored in the specified column of this <code>CachedRowSet</code>
 134.121 -    *           object
 134.122 +    * stored in the specified column of this <code>CachedRowSet</code>
 134.123 +    * object
 134.124      * @throws SQLException if an error occurs generating the collection or
 134.125 -    *           an invalid column id is provided
 134.126 +    * an invalid column id is provided
 134.127      * @see #toCollection
 134.128      * @see #toCollection(int)
 134.129      */
 134.130 @@ -1100,7 +1100,7 @@
 134.131      * @return the <code>SyncProvider</code> object that was set when the rowset
 134.132      *      was instantiated, or if none was was set, the default provider
 134.133      * @throws SQLException if an error occurs while returning the
 134.134 -    *           <code>SyncProvider</code> object
 134.135 +    * <code>SyncProvider</code> object
 134.136      * @see #setSyncProvider
 134.137      */
 134.138      public SyncProvider getSyncProvider() throws SQLException;
 134.139 @@ -1127,7 +1127,7 @@
 134.140      * @param provider a <code>String</code> object giving the fully qualified class
 134.141      *        name of a <code>SyncProvider</code> implementation
 134.142      * @throws SQLException if an error occurs while attempting to reset the
 134.143 -    *           <code>SyncProvider</code> implementation
 134.144 +    * <code>SyncProvider</code> implementation
 134.145      * @see #getSyncProvider
 134.146      */
 134.147      public void setSyncProvider(String provider) throws SQLException;
 134.148 @@ -1152,9 +1152,9 @@
 134.149      * object to the rowset.
 134.150      *
 134.151      * @param md a <code>RowSetMetaData</code> object containing
 134.152 -    *           metadata about the columns in this <code>CachedRowSet</code> object
 134.153 +    * metadata about the columns in this <code>CachedRowSet</code> object
 134.154      * @throws SQLException if invalid metadata is supplied to the
 134.155 -    *           rowset
 134.156 +    * rowset
 134.157      */
 134.158      public void setMetaData(RowSetMetaData md) throws SQLException;
 134.159  
 134.160 @@ -1183,7 +1183,7 @@
 134.161      * @return a <code>ResultSet</code> object that contains the original value for
 134.162      *         this <code>CachedRowSet</code> object
 134.163      * @throws SQLException if an error occurs producing the
 134.164 -    *           <code>ResultSet</code> object
 134.165 +    * <code>ResultSet</code> object
 134.166      */
 134.167     public ResultSet getOriginal() throws SQLException;
 134.168  
 134.169 @@ -1217,7 +1217,7 @@
 134.170      * A call to <code>setOriginalRow</code> is irreversible.
 134.171      *
 134.172      * @throws SQLException if there is no current row or an error is
 134.173 -    *           encountered resetting the contents of the original row
 134.174 +    * encountered resetting the contents of the original row
 134.175      * @see #getOriginalRow
 134.176      */
 134.177      public void setOriginalRow() throws SQLException;
 134.178 @@ -1326,7 +1326,7 @@
 134.179      *         as this <code>CachedRowSet</code> object and that has a cursor over
 134.180      *         the same data
 134.181      * @throws SQLException if an error occurs or cloning is not
 134.182 -    *           supported in the underlying platform
 134.183 +    * supported in the underlying platform
 134.184      * @see javax.sql.RowSetEvent
 134.185      * @see javax.sql.RowSetListener
 134.186      */
 134.187 @@ -1344,10 +1344,10 @@
 134.188      * established must be maintained.
 134.189      *
 134.190      * @return a new <code>RowSet</code> object that is a deep copy
 134.191 -    *         of this <code>CachedRowSet</code> object and is
 134.192 -    *         completely independent of this <code>CachedRowSet</code> object
 134.193 +    * of this <code>CachedRowSet</code> object and is
 134.194 +    * completely independent of this <code>CachedRowSet</code> object
 134.195      * @throws SQLException if an error occurs in generating the copy of
 134.196 -    *         the of this <code>CachedRowSet</code> object
 134.197 +    * the of this <code>CachedRowSet</code> object
 134.198      * @see #createShared
 134.199      * @see #createCopySchema
 134.200      * @see #createCopyNoConstraints
 134.201 @@ -1396,10 +1396,10 @@
 134.202       * in the copy.
 134.203       *
 134.204       * @return a new <code>CachedRowSet</code> object that is a deep copy
 134.205 -     *        of this <code>CachedRowSet</code> object and is
 134.206 -     *        completely independent of this  <code>CachedRowSet</code> object
 134.207 +     *     of this <code>CachedRowSet</code> object and is
 134.208 +     *     completely independent of this  <code>CachedRowSet</code> object
 134.209       * @throws SQLException if an error occurs in generating the copy of
 134.210 -     *        the of this <code>CachedRowSet</code> object
 134.211 +     *     the of this <code>CachedRowSet</code> object
 134.212       * @see #createCopy
 134.213       * @see #createShared
 134.214       * @see #createCopySchema
 134.215 @@ -1445,7 +1445,7 @@
 134.216       * @return <code>true</code> if deleted rows are visible;
 134.217       *         <code>false</code> otherwise
 134.218       * @throws SQLException if a rowset implementation is unable to
 134.219 -     *          to determine whether rows marked for deletion are visible
 134.220 +     * to determine whether rows marked for deletion are visible
 134.221       * @see #setShowDeleted
 134.222       */
 134.223      public boolean getShowDeleted() throws SQLException;
 134.224 @@ -1467,7 +1467,7 @@
 134.225       * @param b <code>true</code> if deleted rows should be shown;
 134.226       *              <code>false</code> otherwise
 134.227       * @exception SQLException if a rowset implementation is unable to
 134.228 -     *          to reset whether deleted rows should be visible
 134.229 +     * to reset whether deleted rows should be visible
 134.230       * @see #getShowDeleted
 134.231       */
 134.232      public void setShowDeleted(boolean b) throws SQLException;
 134.233 @@ -1523,9 +1523,12 @@
 134.234       * set to false, the changes will <b>not</b> be committed until one of the
 134.235       * <code>CachedRowSet</code> interface transaction methods is called.
 134.236       *
 134.237 +     * @deprecated Because this field is final (it is part of an interface),
 134.238 +     *  its value cannot be changed.
 134.239       * @see #commit
 134.240       * @see #rollback
 134.241       */
 134.242 +    @Deprecated
 134.243      public static final boolean COMMIT_ON_ACCEPT_CHANGES = true;
 134.244  
 134.245      /**
 134.246 @@ -1562,10 +1565,10 @@
 134.247       * @param startRow the position in the <code>ResultSet</code> from where to start
 134.248       *                populating the records in this <code>CachedRowSet</code>
 134.249       * @param rs the <code>ResultSet</code> object containing the data
 134.250 -     *          to be read into this <code>CachedRowSet</code> object
 134.251 +     * to be read into this <code>CachedRowSet</code> object
 134.252       * @throws SQLException if a null <code>ResultSet</code> object is supplied
 134.253 -     *          or this <code>CachedRowSet</code> object cannot
 134.254 -     *          retrieve the associated <code>ResultSetMetaData</code> object
 134.255 +     * or this <code>CachedRowSet</code> object cannot
 134.256 +     * retrieve the associated <code>ResultSetMetaData</code> object
 134.257       * @see #execute
 134.258       * @see #populate(ResultSet)
 134.259       * @see java.sql.ResultSet
 134.260 @@ -1620,3 +1623,4 @@
 134.261      public boolean previousPage() throws SQLException;
 134.262  
 134.263  }
 134.264 +
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/src/share/classes/javax/sql/rowset/RowSetFactory.java	Fri Sep 24 16:41:32 2010 -0700
   135.3 @@ -0,0 +1,99 @@
   135.4 +/*
   135.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   135.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   135.7 + *
   135.8 + * This code is free software; you can redistribute it and/or modify it
   135.9 + * under the terms of the GNU General Public License version 2 only, as
  135.10 + * published by the Free Software Foundation.  Oracle designates this
  135.11 + * particular file as subject to the "Classpath" exception as provided
  135.12 + * by Oracle in the LICENSE file that accompanied this code.
  135.13 + *
  135.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  135.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  135.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  135.17 + * version 2 for more details (a copy is included in the LICENSE file that
  135.18 + * accompanied this code).
  135.19 + *
  135.20 + * You should have received a copy of the GNU General Public License version
  135.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  135.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  135.23 + *
  135.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  135.25 + * or visit www.oracle.com if you need additional information or have any
  135.26 + * questions.
  135.27 + */
  135.28 +
  135.29 +package javax.sql.rowset;
  135.30 +
  135.31 +import java.sql.SQLException;
  135.32 +
  135.33 +/**
  135.34 + * An interface that defines the implementation of a factory that is used
  135.35 + * to obtain different types of {@code RowSet} implementations.
  135.36 + *
  135.37 + * @author Lance Andersen
  135.38 + * @since 1.7
  135.39 + */
  135.40 +public interface RowSetFactory{
  135.41 +
  135.42 +    /**
  135.43 +     * <p>Creates a new instance of a CachedRowSet.</p>
  135.44 +     *
  135.45 +     * @return A new instance of a CachedRowSet.
  135.46 +     *
  135.47 +     * @throws SQLException if a CachedRowSet cannot
  135.48 +     *   be created.
  135.49 +     *
  135.50 +     * @since 1.7
  135.51 +     */
  135.52 +    public CachedRowSet createCachedRowSet() throws SQLException;
  135.53 +
  135.54 +    /**
  135.55 +     * <p>Creates a new instance of a FilteredRowSet.</p>
  135.56 +     *
  135.57 +     * @return A new instance of a FilteredRowSet.
  135.58 +     *
  135.59 +     * @throws SQLException if a FilteredRowSet cannot
  135.60 +     *   be created.
  135.61 +     *
  135.62 +     * @since 1.7
  135.63 +     */
  135.64 +    public FilteredRowSet createFilteredRowSet() throws SQLException;
  135.65 +
  135.66 +    /**
  135.67 +     * <p>Creates a new instance of a JdbcRowSet.</p>
  135.68 +     *
  135.69 +     * @return A new instance of a JdbcRowSet.
  135.70 +     *
  135.71 +     * @throws SQLException if a JdbcRowSet cannot
  135.72 +     *   be created.
  135.73 +     *
  135.74 +     * @since 1.7
  135.75 +     */
  135.76 +    public  JdbcRowSet createJdbcRowSet() throws SQLException;
  135.77 +
  135.78 +    /**
  135.79 +     * <p>Creates a new instance of a JoinRowSet.</p>
  135.80 +     *
  135.81 +     * @return A new instance of a JoinRowSet.
  135.82 +     *
  135.83 +     * @throws SQLException if a JoinRowSet cannot
  135.84 +     *   be created.
  135.85 +     *
  135.86 +     * @since 1.7
  135.87 +     */
  135.88 +    public  JoinRowSet createJoinRowSet() throws SQLException;
  135.89 +
  135.90 +    /**
  135.91 +     * <p>Creates a new instance of a WebRowSet.</p>
  135.92 +     *
  135.93 +     * @return A new instance of a WebRowSet.
  135.94 +     *
  135.95 +     * @throws SQLException if a WebRowSet cannot
  135.96 +     *   be created.
  135.97 +     *
  135.98 +     * @since 1.7
  135.99 +     */
 135.100 +    public  WebRowSet createWebRowSet() throws SQLException;
 135.101 +
 135.102 +}
 135.103 \ No newline at end of file
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/src/share/classes/javax/sql/rowset/RowSetProvider.java	Fri Sep 24 16:41:32 2010 -0700
   136.3 @@ -0,0 +1,305 @@
   136.4 +/*
   136.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   136.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   136.7 + *
   136.8 + * This code is free software; you can redistribute it and/or modify it
   136.9 + * under the terms of the GNU General Public License version 2 only, as
  136.10 + * published by the Free Software Foundation.  Oracle designates this
  136.11 + * particular file as subject to the "Classpath" exception as provided
  136.12 + * by Oracle in the LICENSE file that accompanied this code.
  136.13 + *
  136.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  136.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  136.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  136.17 + * version 2 for more details (a copy is included in the LICENSE file that
  136.18 + * accompanied this code).
  136.19 + *
  136.20 + * You should have received a copy of the GNU General Public License version
  136.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  136.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  136.23 + *
  136.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  136.25 + * or visit www.oracle.com if you need additional information or have any
  136.26 + * questions.
  136.27 + */
  136.28 +
  136.29 +package javax.sql.rowset;
  136.30 +
  136.31 +import java.security.AccessController;
  136.32 +import java.security.PrivilegedAction;
  136.33 +import java.sql.SQLException;
  136.34 +import java.util.ServiceLoader;
  136.35 +import javax.sql.rowset.RowSetFactory;
  136.36 +
  136.37 +/**
  136.38 + * A factory API that enables applications to obtain a
  136.39 + * {@code RowSetFactory} implementation  that can be used to create different
  136.40 + * types of {@code RowSet} implementations.
  136.41 + * <p>
  136.42 + * Example:
  136.43 + * </p>
  136.44 + * <pre>
  136.45 + * RowSetFactory aFactory = RowSetProvider.newFactory();
  136.46 + * CachedRowSet crs = aFactory.createCachedRowSet();
  136.47 + * ...
  136.48 + * RowSetFactory rsf = RowSetProvider.newFactory("com.sun.rowset.RowSetFactoryImpl", null);
  136.49 + * WebRowSet wrs = rsf.createWebRowSet();
  136.50 + * </pre>
  136.51 + *<p>
  136.52 + * Tracing of this class may be enabled by setting the System property
  136.53 + * {@code javax.sql.rowset.RowSetFactory.debug} to any value but {@code false}.
  136.54 + * </p>
  136.55 + *
  136.56 + * @author Lance Andersen
  136.57 + * @since 1.7
  136.58 + */
  136.59 +public class RowSetProvider {
  136.60 +
  136.61 +    private static final String ROWSET_DEBUG_PROPERTY = "javax.sql.rowset.RowSetProvider.debug";
  136.62 +    private static final String ROWSET_FACTORY_IMPL = "com.sun.rowset.RowSetFactoryImpl";
  136.63 +    private static final String ROWSET_FACTORY_NAME = "javax.sql.rowset.RowSetFactory";
  136.64 +    /**
  136.65 +     * Internal debug flag.
  136.66 +     */
  136.67 +    private static boolean debug = true;
  136.68 +
  136.69 +
  136.70 +    static {
  136.71 +        // Check to see if the debug property is set
  136.72 +        String val = getSystemProperty(ROWSET_DEBUG_PROPERTY);
  136.73 +        // Allow simply setting the prop to turn on debug
  136.74 +        debug = val != null && !"false".equals(val);
  136.75 +    }
  136.76 +
  136.77 +
  136.78 +    protected RowSetProvider () {
  136.79 +    }
  136.80 +
  136.81 +    /**
  136.82 +     * <p>Creates a new instance of a <code>RowSetFactory</code>
  136.83 +     * implementation.  This method uses the following
  136.84 +     * look up order to determine
  136.85 +     * the <code>RowSetFactory</code> implementation class to load:</p>
  136.86 +     * <ul>
  136.87 +     * <li>
  136.88 +     * The System property {@code javax.sql.rowset.RowsetFactory}.  For example:
  136.89 +     * <ul>
  136.90 +     * <li>
  136.91 +     * -Djavax.sql.rowset.RowsetFactory=com.sun.rowset.RowSetFactoryImpl
  136.92 +     * </li>
  136.93 +     * </ul>
  136.94 +     * <li>
  136.95 +     * The ServiceLocator API. The ServiceLocator API will look
  136.96 +     * for a classname in the file
  136.97 +     * {@code META-INF/services/javax.sql.rowset.RowSetFactory}
  136.98 +     * in jars available to the runtime. For example, to have the the RowSetFactory
  136.99 +     * implementation {@code com.sun.rowset.RowSetFactoryImpl } loaded, the
 136.100 +     * entry in {@code META-INF/services/javax.sql.rowset.RowSetFactory} would be:
 136.101 +     *  <ul>
 136.102 +     * <li>
 136.103 +     * {@code com.sun.rowset.RowSetFactoryImpl }
 136.104 +     * </li>
 136.105 +     * </ul>
 136.106 +     * </li>
 136.107 +     * <li>
 136.108 +     * Platform default <code>RowSetFactory</code> instance.
 136.109 +     * </li>
 136.110 +     * </ul>
 136.111 +     *
 136.112 +     * <p>Once an application has obtained a reference to a {@code RowSetFactory},
 136.113 +     * it can use the factory to obtain RowSet instances.</p>
 136.114 +     *
 136.115 +     * @return New instance of a <code>RowSetFactory</code>
 136.116 +     *
 136.117 +     * @throws SQLException if the default factory class cannot be loaded,
 136.118 +     * instantiated. The cause will be set to actual Exception
 136.119 +     *
 136.120 +     * @see ServiceLoader
 136.121 +     * @since 1.7
 136.122 +     */
 136.123 +    public static RowSetFactory newFactory()
 136.124 +            throws SQLException {
 136.125 +        // Use the system property first
 136.126 +        RowSetFactory factory = null;
 136.127 +        String factoryClassName = null;
 136.128 +        try {
 136.129 +            trace("Checking for Rowset System Property...");
 136.130 +            factoryClassName = getSystemProperty(ROWSET_FACTORY_NAME);
 136.131 +            if (factoryClassName != null) {
 136.132 +                trace("Found system property, value=" + factoryClassName);
 136.133 +                factory = (RowSetFactory) getFactoryClass(factoryClassName, null, true).newInstance();
 136.134 +            }
 136.135 +        } catch (ClassNotFoundException e) {
 136.136 +            throw new SQLException(
 136.137 +                    "RowSetFactory: " + factoryClassName + " not found", e);
 136.138 +        } catch (Exception e) {
 136.139 +            throw new SQLException(
 136.140 +                    "RowSetFactory: " + factoryClassName + " could not be instantiated: " + e,
 136.141 +                    e);
 136.142 +        }
 136.143 +
 136.144 +        // Check to see if we found the RowSetFactory via a System property
 136.145 +        if (factory == null) {
 136.146 +            // If the RowSetFactory is not found via a System Property, now
 136.147 +            // look it up via the ServiceLoader API and if not found, use the
 136.148 +            // Java SE default.
 136.149 +            factory = loadViaServiceLoader();
 136.150 +            factory =
 136.151 +                    factory == null ? newFactory(ROWSET_FACTORY_IMPL, null) : factory;
 136.152 +        }
 136.153 +        return (factory);
 136.154 +    }
 136.155 +
 136.156 +    /**
 136.157 +     * <p>Creates  a new instance of a <code>RowSetFactory</code> from the
 136.158 +     * specified factory class name.
 136.159 +     * This function is useful when there are multiple providers in the classpath.
 136.160 +     * It gives more control to the application as it can specify which provider
 136.161 +     * should be loaded.</p>
 136.162 +     *
 136.163 +     * <p>Once an application has obtained a reference to a <code>RowSetFactory</code>
 136.164 +     * it can use the factory to obtain RowSet instances.</p>
 136.165 +     *
 136.166 +     * @param factoryClassName fully qualified factory class name that
 136.167 +     * provides  an implementation of <code>javax.sql.rowset.RowSetFactory</code>.
 136.168 +     *
 136.169 +     * @param cl <code>ClassLoader</code> used to load the factory
 136.170 +     * class. If <code>null</code> current <code>Thread</code>'s context
 136.171 +     * classLoader is used to load the factory class.
 136.172 +     *
 136.173 +     * @return New instance of a <code>RowSetFactory</code>
 136.174 +     *
 136.175 +     * @throws SQLException if <code>factoryClassName</code> is
 136.176 +     * <code>null</code>, or the factory class cannot be loaded, instantiated.
 136.177 +     *
 136.178 +     * @see #newFactory()
 136.179 +     *
 136.180 +     * @since 1.7
 136.181 +     */
 136.182 +    public static RowSetFactory newFactory(String factoryClassName, ClassLoader cl)
 136.183 +            throws SQLException {
 136.184 +
 136.185 +        trace("***In newInstance()");
 136.186 +        try {
 136.187 +            Class providerClass = getFactoryClass(factoryClassName, cl, false);
 136.188 +            RowSetFactory instance = (RowSetFactory) providerClass.newInstance();
 136.189 +            if (debug) {
 136.190 +                trace("Created new instance of " + providerClass +
 136.191 +                        " using ClassLoader: " + cl);
 136.192 +            }
 136.193 +            return instance;
 136.194 +        } catch (ClassNotFoundException x) {
 136.195 +            throw new SQLException(
 136.196 +                    "Provider " + factoryClassName + " not found", x);
 136.197 +        } catch (Exception x) {
 136.198 +            throw new SQLException(
 136.199 +                    "Provider " + factoryClassName + " could not be instantiated: " + x,
 136.200 +                    x);
 136.201 +        }
 136.202 +    }
 136.203 +
 136.204 +    /*
 136.205 +     * Returns the class loader to be used.
 136.206 +     * @return The ClassLoader to use.
 136.207 +     *
 136.208 +     */
 136.209 +    static private ClassLoader getContextClassLoader() throws SecurityException {
 136.210 +        return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
 136.211 +
 136.212 +            public Object run() {
 136.213 +                ClassLoader cl = null;
 136.214 +
 136.215 +                cl = Thread.currentThread().getContextClassLoader();
 136.216 +
 136.217 +                if (cl == null) {
 136.218 +                    cl = ClassLoader.getSystemClassLoader();
 136.219 +                }
 136.220 +
 136.221 +                return cl;
 136.222 +            }
 136.223 +        });
 136.224 +    }
 136.225 +
 136.226 +    /**
 136.227 +     * Attempt to load a class using the class loader supplied. If that fails
 136.228 +     * and fall back is enabled, the current (i.e. bootstrap) class loader is
 136.229 +     * tried.
 136.230 +     *
 136.231 +     * If the class loader supplied is <code>null</code>, first try using the
 136.232 +     * context class loader followed by the current class loader.
 136.233 +     *  @return The class which was loaded
 136.234 +     */
 136.235 +    static private Class getFactoryClass(String factoryClassName, ClassLoader cl,
 136.236 +            boolean doFallback) throws ClassNotFoundException {
 136.237 +        try {
 136.238 +            if (cl == null) {
 136.239 +                cl = getContextClassLoader();
 136.240 +                if (cl == null) {
 136.241 +                    throw new ClassNotFoundException();
 136.242 +                } else {
 136.243 +                    return cl.loadClass(factoryClassName);
 136.244 +                }
 136.245 +            } else {
 136.246 +                return cl.loadClass(factoryClassName);
 136.247 +            }
 136.248 +        } catch (ClassNotFoundException e) {
 136.249 +            if (doFallback) {
 136.250 +                // Use current class loader
 136.251 +                return Class.forName(factoryClassName, true, RowSetFactory.class.getClassLoader());
 136.252 +            } else {
 136.253 +                throw e;
 136.254 +            }
 136.255 +        }
 136.256 +    }
 136.257 +
 136.258 +    /**
 136.259 +     * Use the ServiceLoader mechanism to load  the default RowSetFactory
 136.260 +     * @return default RowSetFactory Implementation
 136.261 +     */
 136.262 +    static private RowSetFactory loadViaServiceLoader() {
 136.263 +        RowSetFactory theFactory = null;
 136.264 +        trace("***in loadViaServiceLoader()");
 136.265 +        for (RowSetFactory factory : ServiceLoader.load(javax.sql.rowset.RowSetFactory.class)) {
 136.266 +            trace(" Loading done by the java.util.ServiceLoader :" + factory.getClass().getName());
 136.267 +            theFactory = factory;
 136.268 +            break;
 136.269 +        }
 136.270 +        return theFactory;
 136.271 +
 136.272 +    }
 136.273 +
 136.274 +    /**
 136.275 +     * Returns the requested System Property.  If a {@code SecurityException}
 136.276 +     * occurs, just return NULL
 136.277 +     * @param propName - System property to retreive
 136.278 +     * @return The System property value or NULL if the property does not exist
 136.279 +     * or a {@code SecurityException} occurs.
 136.280 +     */
 136.281 +    static private String getSystemProperty(final String propName) {
 136.282 +        String property = null;
 136.283 +        try {
 136.284 +            property = (String) AccessController.doPrivileged(new PrivilegedAction() {
 136.285 +
 136.286 +                public Object run() {
 136.287 +                    return System.getProperty(propName);
 136.288 +                }
 136.289 +            });
 136.290 +        } catch (SecurityException se) {
 136.291 +            if (debug) {
 136.292 +                se.printStackTrace();
 136.293 +            }
 136.294 +        }
 136.295 +        return property;
 136.296 +    }
 136.297 +
 136.298 +    /**
 136.299 +     * Debug routine which will output tracing if the System Property
 136.300 +     * -Djavax.sql.rowset.RowSetFactory.debug is set
 136.301 +     * @param msg - The debug message to display
 136.302 +     */
 136.303 +    private static void trace(String msg) {
 136.304 +        if (debug) {
 136.305 +            System.err.println("###RowSets: " + msg);
 136.306 +        }
 136.307 +    }
 136.308 +}
   137.1 --- a/src/share/classes/javax/sql/rowset/package.html	Thu Sep 23 17:33:40 2010 -0700
   137.2 +++ b/src/share/classes/javax/sql/rowset/package.html	Fri Sep 24 16:41:32 2010 -0700
   137.3 @@ -5,7 +5,7 @@
   137.4    <meta http-equiv="Content-Type"
   137.5   content="text/html; charset=iso-8859-1">
   137.6  <!--
   137.7 -Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
   137.8 +Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   137.9  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  137.10  
  137.11  This code is free software; you can redistribute it and/or modify it
  137.12 @@ -78,7 +78,7 @@
  137.13  data structure as defined in the JDBC 3.0 specification.
  137.14  <p>
  137.15  <li><a href="CachedRowSet.html">
  137.16 -<b><code>CachedRowSet</code><sup><font size=-2>TM></font></sup</b></a> 
  137.17 +<b><code>CachedRowSet</code>&trade;</b></a>
  137.18   - A <tt>CachedRowSet</tt> object is a JavaBeans<sup><font size=-2>TM</font></sup>
  137.19   component that is scrollable, updatable, serializable, and generally disconnected from
  137.20   the source of its data. A <tt>CachedRowSet</tt> object
  137.21 @@ -148,7 +148,12 @@
  137.22  on <a href="spi/SyncProvider.html"><code>SyncProvider</code></a> implementations.
  137.23  <p>
  137.24  <ul>
  137.25 -<li><b>3.1 Role of the <code>BaseRowSet</code> Class</b>
  137.26 +<li><b>3.1 Constructor</b>
  137.27 +<p>
  137.28 +    All <code>RowSet</code> implementations <strong>must</strong> provide a
  137.29 +no-argument constructor.
  137.30 +</li>
  137.31 +<li><b>3.2 Role of the <code>BaseRowSet</code> Class</b>
  137.32  <p>
  137.33  A compliant JDBC <code>RowSet</code> implementation <b>must</b> implement one or more 
  137.34  standard interfaces specified in this package and and <b>may</b> extend the 
  137.35 @@ -215,7 +220,7 @@
  137.36      </table>
  137.37      </blockquote>
  137.38  <p>
  137.39 -<li><b>3.2 Connected RowSet Requirements</b> 
  137.40 +<li><b>3.3 Connected RowSet Requirements</b>
  137.41  <p>
  137.42  The <code>JdbcRowSet</code> describes a <code>RowSet</code> object that <b>must</b> always
  137.43  be connected to the originating data source. Implementations of the <code>JdbcRowSet</code>
  137.44 @@ -229,7 +234,7 @@
  137.45  <p>
  137.46  
  137.47  <li>
  137.48 -<b>3.3 Disconnected RowSet Requirements</b> 
  137.49 +<b>3.4 Disconnected RowSet Requirements</b>
  137.50  <p> 
  137.51  A disconnected <code>RowSet</code> object, such as a <code>CachedRowSet</code> object, 
  137.52  <b>should</b> delegate  
  137.53 @@ -244,7 +249,7 @@
  137.54  therefore ensure that no 
  137.55  extraneous references remain on the <code>Connection</code> object.
  137.56  <p>
  137.57 -<li><b>3.4 Role of RowSetMetaDataImpl</b>
  137.58 +<li><b>3.5 Role of RowSetMetaDataImpl</b>
  137.59  <p>
  137.60  The <code>RowsetMetaDataImpl</code> class is a utility class that provides an implementation of the
  137.61  <a href="../RowSetMetaData.html">RowSetMetaData</a> interface, supplying standard setter
  137.62 @@ -252,7 +257,7 @@
  137.63  <code>RowSet</code> objects. All implementations are free to use this standard
  137.64  implementation but are not required to do so.
  137.65  <p>
  137.66 -<li><b>3.5 RowSetWarning Class</b>
  137.67 +<li><b>3.6 RowSetWarning Class</b>
  137.68  <p>
  137.69  The <code>RowSetWarning</code> class provides warnings that can be set
  137.70  on <code>RowSet</code> implementations.
  137.71 @@ -270,7 +275,7 @@
  137.72  
  137.73  
  137.74  <P>
  137.75 -<li><b>3.6 The Joinable Interface</b>
  137.76 +<li><b>3.7 The Joinable Interface</b>
  137.77  <P>
  137.78  The <code>Joinable</code> interface provides both connected and disconnected 
  137.79  <code>RowSet</code> objects with the capability to be added to a 
  137.80 @@ -278,7 +283,14 @@
  137.81  A <code>RowSet</code> object that has  implemented the <code>Joinable</code> 
  137.82  interface can set a match column, retrieve a match column, or unset a match column.
  137.83  A <code>JoinRowSet</code> object can then use the <code>RowSet</code> object's
  137.84 -match column as a basis for adding the <code>RowSet</code> object. 
  137.85 +match column as a basis for adding the <code>RowSet</code> object.
  137.86 +</li>
  137.87 +
  137.88 +<li><b>3.8 The RowSetFactory Interface</b>
  137.89 +    <p>
  137.90 +        A <code>RowSetFactory</code> implementation <strong>must</strong>
  137.91 +        be provided.
  137.92 +</li>
  137.93  </ul>
  137.94  
  137.95  <h3><a name="relspec">4.0 Related Specifications</a></h3>
   138.1 --- a/src/share/classes/javax/sql/rowset/spi/SyncFactory.java	Thu Sep 23 17:33:40 2010 -0700
   138.2 +++ b/src/share/classes/javax/sql/rowset/spi/SyncFactory.java	Fri Sep 24 16:41:32 2010 -0700
   138.3 @@ -1,5 +1,5 @@
   138.4  /*
   138.5 - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
   138.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   138.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   138.8   *
   138.9   * This code is free software; you can redistribute it and/or modify it
  138.10 @@ -25,13 +25,6 @@
  138.11  
  138.12  package javax.sql.rowset.spi;
  138.13  
  138.14 -import java.util.Map;
  138.15 -import java.util.Hashtable;
  138.16 -import java.util.Enumeration;
  138.17 -import java.util.Vector;
  138.18 -import java.util.Properties;
  138.19 -import java.util.Collection;
  138.20 -import java.util.StringTokenizer;
  138.21  import java.util.logging.*;
  138.22  import java.util.*;
  138.23  
  138.24 @@ -216,68 +209,64 @@
  138.25       * Having a private constructor guarantees that no more than
  138.26       * one <code>SyncProvider</code> object can exist at a time.
  138.27       */
  138.28 -    private SyncFactory() {};
  138.29 +    private SyncFactory() {
  138.30 +    }
  138.31  
  138.32      /**
  138.33       * The standard property-id for a synchronization provider implementation
  138.34       * name.
  138.35       */
  138.36 -    public static String ROWSET_SYNC_PROVIDER =
  138.37 -        "rowset.provider.classname";
  138.38 -
  138.39 +    public static final String ROWSET_SYNC_PROVIDER =
  138.40 +            "rowset.provider.classname";
  138.41      /**
  138.42       * The standard property-id for a synchronization provider implementation
  138.43       * vendor name.
  138.44       */
  138.45 -    public static String ROWSET_SYNC_VENDOR =
  138.46 -        "rowset.provider.vendor";
  138.47 -
  138.48 +    public static final String ROWSET_SYNC_VENDOR =
  138.49 +            "rowset.provider.vendor";
  138.50      /**
  138.51       * The standard property-id for a synchronization provider implementation
  138.52       * version tag.
  138.53       */
  138.54 -    public static String ROWSET_SYNC_PROVIDER_VERSION =
  138.55 -        "rowset.provider.version";
  138.56 -
  138.57 +    public static final String ROWSET_SYNC_PROVIDER_VERSION =
  138.58 +            "rowset.provider.version";
  138.59      /**
  138.60       * The standard resource file name.
  138.61       */
  138.62      private static String ROWSET_PROPERTIES = "rowset.properties";
  138.63 -
  138.64      /**
  138.65       * The RI Optimistic Provider.
  138.66       */
  138.67      private static String default_provider =
  138.68 -        "com.sun.rowset.providers.RIOptimisticProvider";
  138.69 -
  138.70 +            "com.sun.rowset.providers.RIOptimisticProvider";
  138.71 +    /**
  138.72 +     *  Permission required to invoke setJNDIContext and setLogger
  138.73 +     */
  138.74 +    private static final SQLPermission SET_SYNCFACTORY_PERMISSION =
  138.75 +            new SQLPermission("setSyncFactory");
  138.76      /**
  138.77       * The initial JNDI context where <code>SyncProvider</code> implementations can
  138.78       * be stored and from which they can be invoked.
  138.79       */
  138.80      private static Context ic;
  138.81 -
  138.82      /**
  138.83       * The <code>Logger</code> object to be used by the <code>SyncFactory</code>.
  138.84       */
  138.85      private static Logger rsLogger;
  138.86 -
  138.87      /**
  138.88       *
  138.89       */
  138.90      private static Level rsLevel;
  138.91 -
  138.92      /**
  138.93       * The registry of available <code>SyncProvider</code> implementations.
  138.94       * See section 2.0 of the class comment for <code>SyncFactory</code> for an
  138.95       * explanation of how a provider can be added to this registry.
  138.96       */
  138.97      private static Hashtable implementations;
  138.98 -
  138.99      /**
 138.100       * Internal sync object used to maintain the SPI as a singleton
 138.101       */
 138.102      private static Object logSync = new Object();
 138.103 -
 138.104      /**
 138.105       * Internal PrintWriter field for logging facility
 138.106       */
 138.107 @@ -311,7 +300,7 @@
 138.108       * @see #setJNDIContext
 138.109       */
 138.110      public static synchronized void registerProvider(String providerID)
 138.111 -        throws SyncFactoryException {
 138.112 +            throws SyncFactoryException {
 138.113  
 138.114          ProviderImpl impl = new ProviderImpl();
 138.115          impl.setClassname(providerID);
 138.116 @@ -325,29 +314,29 @@
 138.117       *
 138.118       * @return the <code>SyncFactory</code> instance
 138.119       */
 138.120 -     public static SyncFactory getSyncFactory(){
 138.121 +    public static SyncFactory getSyncFactory() {
 138.122  
 138.123 -         // This method uses the Singleton Design Pattern
 138.124 -         // with Double-Checked Locking Pattern for
 138.125 -         // 1. Creating single instance of the SyncFactory
 138.126 -         // 2. Make the class thread safe, so that at one time
 138.127 -         //    only one thread enters the synchronized block
 138.128 -         //    to instantiate.
 138.129 +        // This method uses the Singleton Design Pattern
 138.130 +        // with Double-Checked Locking Pattern for
 138.131 +        // 1. Creating single instance of the SyncFactory
 138.132 +        // 2. Make the class thread safe, so that at one time
 138.133 +        //    only one thread enters the synchronized block
 138.134 +        //    to instantiate.
 138.135  
 138.136 -         // if syncFactory object is already there
 138.137 -         // don't go into synchronized block and return
 138.138 -         // that object.
 138.139 -         // else go into synchronized block
 138.140 +        // if syncFactory object is already there
 138.141 +        // don't go into synchronized block and return
 138.142 +        // that object.
 138.143 +        // else go into synchronized block
 138.144  
 138.145 -         if(syncFactory == null){
 138.146 -             synchronized(SyncFactory.class) {
 138.147 -                if(syncFactory == null){
 138.148 +        if (syncFactory == null) {
 138.149 +            synchronized (SyncFactory.class) {
 138.150 +                if (syncFactory == null) {
 138.151                      syncFactory = new SyncFactory();
 138.152                  } //end if
 138.153 -             } //end synchronized block
 138.154 -         } //end if
 138.155 -         return syncFactory;
 138.156 -     }
 138.157 +            } //end synchronized block
 138.158 +        } //end if
 138.159 +        return syncFactory;
 138.160 +    }
 138.161  
 138.162      /**
 138.163       * Removes the designated currently registered synchronization provider from the
 138.164 @@ -358,13 +347,12 @@
 138.165       * unregister a SyncProvider implementation that was not registered.
 138.166       */
 138.167      public static synchronized void unregisterProvider(String providerID)
 138.168 -        throws SyncFactoryException {
 138.169 +            throws SyncFactoryException {
 138.170          initMapIfNecessary();
 138.171          if (implementations.containsKey(providerID)) {
 138.172              implementations.remove(providerID);
 138.173          }
 138.174      }
 138.175 -
 138.176      private static String colon = ":";
 138.177      private static String strFileSep = "/";
 138.178  
 138.179 @@ -395,7 +383,7 @@
 138.180                   * Dependent on application
 138.181                   */
 138.182                  String strRowsetProperties = System.getProperty("rowset.properties");
 138.183 -                if ( strRowsetProperties != null) {
 138.184 +                if (strRowsetProperties != null) {
 138.185                      // Load user's implementation of SyncProvider
 138.186                      // here. -Drowset.properties=/abc/def/pqr.txt
 138.187                      ROWSET_PROPERTIES = strRowsetProperties;
 138.188 @@ -407,8 +395,8 @@
 138.189                   * Always available
 138.190                   */
 138.191                  ROWSET_PROPERTIES = "javax" + strFileSep + "sql" +
 138.192 -                    strFileSep + "rowset" + strFileSep +
 138.193 -                    "rowset.properties";
 138.194 +                        strFileSep + "rowset" + strFileSep +
 138.195 +                        "rowset.properties";
 138.196                  // properties.load(
 138.197                  //                ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES));
 138.198  
 138.199 @@ -417,7 +405,7 @@
 138.200                  properties.load(cl.getResourceAsStream(ROWSET_PROPERTIES));
 138.201                  parseProperties(properties);
 138.202  
 138.203 -                // removed else, has properties should sum together
 138.204 +            // removed else, has properties should sum together
 138.205  
 138.206              } catch (FileNotFoundException e) {
 138.207                  throw new SyncFactoryException("Cannot locate properties file: " + e);
 138.208 @@ -447,18 +435,15 @@
 138.209              }
 138.210          }
 138.211      }
 138.212 -
 138.213      /**
 138.214       * The internal boolean switch that indicates whether a JNDI
 138.215       * context has been established or not.
 138.216       */
 138.217      private static boolean jndiCtxEstablished = false;
 138.218 -
 138.219      /**
 138.220       * The internal debug switch.
 138.221       */
 138.222      private static boolean debug = false;
 138.223 -
 138.224      /**
 138.225       * Internal registry count for the number of providers contained in the
 138.226       * registry.
 138.227 @@ -475,9 +460,9 @@
 138.228          String key = null;
 138.229          String[] propertyNames = null;
 138.230  
 138.231 -        for (Enumeration e = p.propertyNames(); e.hasMoreElements() ;) {
 138.232 +        for (Enumeration e = p.propertyNames(); e.hasMoreElements();) {
 138.233  
 138.234 -            String str = (String)e.nextElement();
 138.235 +            String str = (String) e.nextElement();
 138.236  
 138.237              int w = str.length();
 138.238  
 138.239 @@ -491,7 +476,7 @@
 138.240                      propertyNames = getPropertyNames(false);
 138.241                  } else {
 138.242                      // property index has been set.
 138.243 -                    propertyNames = getPropertyNames(true, str.substring(w-1));
 138.244 +                    propertyNames = getPropertyNames(true, str.substring(w - 1));
 138.245                  }
 138.246  
 138.247                  key = p.getProperty(propertyNames[0]);
 138.248 @@ -515,17 +500,17 @@
 138.249       * overloaded property names that contain indexes.
 138.250       */
 138.251      private static String[] getPropertyNames(boolean append,
 138.252 -                                             String propertyIndex) {
 138.253 +            String propertyIndex) {
 138.254          String dot = ".";
 138.255          String[] propertyNames =
 138.256 -            new String[] {SyncFactory.ROWSET_SYNC_PROVIDER,
 138.257 -                              SyncFactory.ROWSET_SYNC_VENDOR,
 138.258 -                              SyncFactory.ROWSET_SYNC_PROVIDER_VERSION};
 138.259 +                new String[]{SyncFactory.ROWSET_SYNC_PROVIDER,
 138.260 +            SyncFactory.ROWSET_SYNC_VENDOR,
 138.261 +            SyncFactory.ROWSET_SYNC_PROVIDER_VERSION};
 138.262          if (append) {
 138.263              for (int i = 0; i < propertyNames.length; i++) {
 138.264                  propertyNames[i] = propertyNames[i] +
 138.265 -                    dot +
 138.266 -                    propertyIndex;
 138.267 +                        dot +
 138.268 +                        propertyIndex;
 138.269              }
 138.270              return propertyNames;
 138.271          } else {
 138.272 @@ -549,15 +534,21 @@
 138.273       *
 138.274       * @param providerID the unique identifier of the provider
 138.275       * @return a <code>SyncProvider</code> implementation
 138.276 -     * @throws SyncFactoryException If the SyncProvider cannot be found or
 138.277 +     * @throws SyncFactoryException If the SyncProvider cannot be found,
 138.278 +     * the providerID is {@code null}, or
 138.279       * some error was encountered when trying to invoke this provider.
 138.280       */
 138.281      public static SyncProvider getInstance(String providerID)
 138.282 -        throws SyncFactoryException {
 138.283 +            throws SyncFactoryException {
 138.284 +
 138.285 +        if(providerID == null) {
 138.286 +            throw new SyncFactoryException("The providerID cannot be null");
 138.287 +        }
 138.288 +
 138.289          initMapIfNecessary(); // populate HashTable
 138.290          initJNDIContext();    // check JNDI context for any additional bindings
 138.291  
 138.292 -        ProviderImpl impl = (ProviderImpl)implementations.get(providerID);
 138.293 +        ProviderImpl impl = (ProviderImpl) implementations.get(providerID);
 138.294  
 138.295          if (impl == null) {
 138.296              // Requested SyncProvider is unavailable. Return default provider.
 138.297 @@ -575,11 +566,10 @@
 138.298               * this SyncFactory and try to laod the SyncProvider class from
 138.299               * there.
 138.300               **/
 138.301 -
 138.302              c = Class.forName(providerID, true, cl);
 138.303  
 138.304              if (c != null) {
 138.305 -                return (SyncProvider)c.newInstance();
 138.306 +                return (SyncProvider) c.newInstance();
 138.307              } else {
 138.308                  return new com.sun.rowset.providers.RIOptimisticProvider();
 138.309              }
 138.310 @@ -592,6 +582,7 @@
 138.311              throw new SyncFactoryException("ClassNotFoundException: " + e.getMessage());
 138.312          }
 138.313      }
 138.314 +
 138.315      /**
 138.316       * Returns an Enumeration of currently registered synchronization
 138.317       * providers.  A <code>RowSet</code> implementation may use any provider in
 138.318 @@ -605,7 +596,7 @@
 138.319       * providers that are registered with this Factory
 138.320       */
 138.321      public static Enumeration<SyncProvider> getRegisteredProviders()
 138.322 -        throws SyncFactoryException {
 138.323 +            throws SyncFactoryException {
 138.324          initMapIfNecessary();
 138.325          // return a collection of classnames
 138.326          // of type SyncProvider
 138.327 @@ -618,10 +609,26 @@
 138.328       * <code>SyncProvider</code> implementations can log their events to
 138.329       * this object and the application can retrieve a handle to this
 138.330       * object using the <code>getLogger</code> method.
 138.331 +     * <p>
 138.332 +     * This method checks to see that there is an {@code SQLPermission}
 138.333 +     * object  which grants the permission {@code setSyncFactory}
 138.334 +     * before allowing the method to succeed.  If a
 138.335 +     * {@code SecurityManager} exists and its
 138.336 +     * {@code checkPermission} method denies calling {@code setLogger},
 138.337 +     * this method throws a
 138.338 +     * {@code java.lang.SecurityException}.
 138.339       *
 138.340       * @param logger A Logger object instance
 138.341 +     * @throws java.lang.SecurityException if a security manager exists and its
 138.342 +     *   {@code checkPermission} method denies calling {@code setLogger}
 138.343 +     * @see SecurityManager#checkPermission
 138.344       */
 138.345      public static void setLogger(Logger logger) {
 138.346 +
 138.347 +        SecurityManager sec = System.getSecurityManager();
 138.348 +        if (sec != null) {
 138.349 +            sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
 138.350 +        }
 138.351          rsLogger = logger;
 138.352      }
 138.353  
 138.354 @@ -631,14 +638,28 @@
 138.355       * <code>SyncProvider</code> implementations can log their events
 138.356       * to this object and the application can retrieve a handle to this
 138.357       * object using the <code>getLogger</code> method.
 138.358 +     * <p>
 138.359 +     * This method checks to see that there is an {@code SQLPermission}
 138.360 +     * object  which grants the permission {@code setSyncFactory}
 138.361 +     * before allowing the method to succeed.  If a
 138.362 +     * {@code SecurityManager} exists and its
 138.363 +     * {@code checkPermission} method denies calling {@code setLogger},
 138.364 +     * this method throws a
 138.365 +     * {@code java.lang.SecurityException}.
 138.366       *
 138.367       * @param logger a Logger object instance
 138.368       * @param level a Level object instance indicating the degree of logging
 138.369       * required
 138.370 +     * @throws java.lang.SecurityException if a security manager exists and its
 138.371 +     *   {@code checkPermission} method denies calling {@code setLogger}
 138.372 +     * @see SecurityManager#checkPermission
 138.373       */
 138.374      public static void setLogger(Logger logger, Level level) {
 138.375          // singleton
 138.376 -
 138.377 +        SecurityManager sec = System.getSecurityManager();
 138.378 +        if (sec != null) {
 138.379 +            sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
 138.380 +        }
 138.381          rsLogger = logger;
 138.382          rsLogger.setLevel(level);
 138.383      }
 138.384 @@ -651,27 +672,42 @@
 138.385       */
 138.386      public static Logger getLogger() throws SyncFactoryException {
 138.387          // only one logger per session
 138.388 -        if(rsLogger == null){
 138.389 -           throw new SyncFactoryException("(SyncFactory) : No logger has been set");
 138.390 +        if (rsLogger == null) {
 138.391 +            throw new SyncFactoryException("(SyncFactory) : No logger has been set");
 138.392          }
 138.393          return rsLogger;
 138.394      }
 138.395  
 138.396 -   /**
 138.397 -    * Sets the initial JNDI context from which SyncProvider implementations
 138.398 -    * can be retrieved from a JNDI namespace
 138.399 -    *
 138.400 -    * @param ctx a valid JNDI context
 138.401 -    * @throws SyncFactoryException if the supplied JNDI context is null
 138.402 -    */
 138.403 +    /**
 138.404 +     * Sets the initial JNDI context from which SyncProvider implementations
 138.405 +     * can be retrieved from a JNDI namespace
 138.406 +     * <p>
 138.407 +     *  This method checks to see that there is an {@code SQLPermission}
 138.408 +     * object  which grants the permission {@code setSyncFactory}
 138.409 +     * before allowing the method to succeed.  If a
 138.410 +     * {@code SecurityManager} exists and its
 138.411 +     * {@code checkPermission} method denies calling {@code setJNDIContext},
 138.412 +     * this method throws a
 138.413 +     * {@code java.lang.SecurityException}.
 138.414 +     *
 138.415 +     * @param ctx a valid JNDI context
 138.416 +     * @throws SyncFactoryException if the supplied JNDI context is null
 138.417 +     * @throws java.lang.SecurityException if a security manager exists and its
 138.418 +     *  {@code checkPermission} method denies calling {@code setJNDIContext}
 138.419 +     * @see SecurityManager#checkPermission
 138.420 +     */
 138.421      public static void setJNDIContext(javax.naming.Context ctx)
 138.422 -        throws SyncFactoryException {
 138.423 +            throws SyncFactoryException {
 138.424 +        SecurityManager sec = System.getSecurityManager();
 138.425 +        if (sec != null) {
 138.426 +            sec.checkPermission(SET_SYNCFACTORY_PERMISSION);
 138.427 +        }
 138.428          if (ctx == null) {
 138.429              throw new SyncFactoryException("Invalid JNDI context supplied");
 138.430          }
 138.431          ic = ctx;
 138.432          jndiCtxEstablished = true;
 138.433 -   }
 138.434 +    }
 138.435  
 138.436      /**
 138.437       * Controls JNDI context intialization.
 138.438 @@ -689,7 +725,7 @@
 138.439                  throw new SyncFactoryException("SPI: NamingException: " + e.getExplanation());
 138.440              } catch (Exception e) {
 138.441                  e.printStackTrace();
 138.442 -        throw new SyncFactoryException("SPI: Exception: " + e.getMessage());
 138.443 +                throw new SyncFactoryException("SPI: Exception: " + e.getMessage());
 138.444              }
 138.445          }
 138.446      }
 138.447 @@ -720,7 +756,7 @@
 138.448       * bindings have been enumerated.
 138.449       */
 138.450      private static void enumerateBindings(NamingEnumeration bindings,
 138.451 -        Properties properties) throws NamingException {
 138.452 +            Properties properties) throws NamingException {
 138.453  
 138.454          boolean syncProviderObj = false; // move to parameters ?
 138.455  
 138.456 @@ -729,21 +765,21 @@
 138.457              Object elementObj = null;
 138.458              String element = null;
 138.459              while (bindings.hasMore()) {
 138.460 -                bd = (Binding)bindings.next();
 138.461 +                bd = (Binding) bindings.next();
 138.462                  element = bd.getName();
 138.463                  elementObj = bd.getObject();
 138.464  
 138.465                  if (!(ic.lookup(element) instanceof Context)) {
 138.466 -                     // skip directories/sub-contexts
 138.467 -                     if (ic.lookup(element) instanceof SyncProvider) {
 138.468 +                    // skip directories/sub-contexts
 138.469 +                    if (ic.lookup(element) instanceof SyncProvider) {
 138.470                          syncProviderObj = true;
 138.471 -                     }
 138.472 +                    }
 138.473                  }
 138.474  
 138.475                  if (syncProviderObj) {
 138.476 -                    SyncProvider sync = (SyncProvider)elementObj;
 138.477 +                    SyncProvider sync = (SyncProvider) elementObj;
 138.478                      properties.put(SyncFactory.ROWSET_SYNC_PROVIDER,
 138.479 -                        sync.getProviderID());
 138.480 +                            sync.getProviderID());
 138.481                      syncProviderObj = false; // reset
 138.482                  }
 138.483  
 138.484 @@ -756,142 +792,136 @@
 138.485      }
 138.486  }
 138.487  
 138.488 -   /**
 138.489 -     * Internal class that defines the lazy reference construct for each registered
 138.490 -     * SyncProvider implementation.
 138.491 -     */
 138.492 -   class ProviderImpl extends SyncProvider {
 138.493 -        private String className = null;
 138.494 -        private String vendorName = null;
 138.495 -        private String ver = null;
 138.496 -        private int index;
 138.497 +/**
 138.498 + * Internal class that defines the lazy reference construct for each registered
 138.499 + * SyncProvider implementation.
 138.500 + */
 138.501 +class ProviderImpl extends SyncProvider {
 138.502  
 138.503 -        public void setClassname(String classname) {
 138.504 -            className = classname;
 138.505 +    private String className = null;
 138.506 +    private String vendorName = null;
 138.507 +    private String ver = null;
 138.508 +    private int index;
 138.509 +
 138.510 +    public void setClassname(String classname) {
 138.511 +        className = classname;
 138.512 +    }
 138.513 +
 138.514 +    public String getClassname() {
 138.515 +        return className;
 138.516 +    }
 138.517 +
 138.518 +    public void setVendor(String vendor) {
 138.519 +        vendorName = vendor;
 138.520 +    }
 138.521 +
 138.522 +    public String getVendor() {
 138.523 +        return vendorName;
 138.524 +    }
 138.525 +
 138.526 +    public void setVersion(String providerVer) {
 138.527 +        ver = providerVer;
 138.528 +    }
 138.529 +
 138.530 +    public String getVersion() {
 138.531 +        return ver;
 138.532 +    }
 138.533 +
 138.534 +    public void setIndex(int i) {
 138.535 +        index = i;
 138.536 +    }
 138.537 +
 138.538 +    public int getIndex() {
 138.539 +        return index;
 138.540 +    }
 138.541 +
 138.542 +    public int getDataSourceLock() throws SyncProviderException {
 138.543 +
 138.544 +        int dsLock = 0;
 138.545 +        try {
 138.546 +            dsLock = SyncFactory.getInstance(className).getDataSourceLock();
 138.547 +        } catch (SyncFactoryException sfEx) {
 138.548 +
 138.549 +            throw new SyncProviderException(sfEx.getMessage());
 138.550          }
 138.551  
 138.552 -        public String getClassname() {
 138.553 -            return className;
 138.554 +        return dsLock;
 138.555 +    }
 138.556 +
 138.557 +    public int getProviderGrade() {
 138.558 +
 138.559 +        int grade = 0;
 138.560 +
 138.561 +        try {
 138.562 +            grade = SyncFactory.getInstance(className).getProviderGrade();
 138.563 +        } catch (SyncFactoryException sfEx) {
 138.564 +            //
 138.565          }
 138.566  
 138.567 -        public void setVendor(String vendor) {
 138.568 -            vendorName = vendor;
 138.569 +        return grade;
 138.570 +    }
 138.571 +
 138.572 +    public String getProviderID() {
 138.573 +        return className;
 138.574 +    }
 138.575 +
 138.576 +    /*
 138.577 +    public javax.sql.RowSetInternal getRowSetInternal() {
 138.578 +    try
 138.579 +    {
 138.580 +    return SyncFactory.getInstance(className).getRowSetInternal();
 138.581 +    } catch(SyncFactoryException sfEx) {
 138.582 +    //
 138.583 +    }
 138.584 +    }
 138.585 +     */
 138.586 +    public javax.sql.RowSetReader getRowSetReader() {
 138.587 +
 138.588 +        RowSetReader rsReader = null;
 138.589 +
 138.590 +        try {
 138.591 +            rsReader = SyncFactory.getInstance(className).getRowSetReader();
 138.592 +        } catch (SyncFactoryException sfEx) {
 138.593 +            //
 138.594          }
 138.595  
 138.596 -        public String getVendor() {
 138.597 -            return vendorName;
 138.598 +        return rsReader;
 138.599 +
 138.600 +    }
 138.601 +
 138.602 +    public javax.sql.RowSetWriter getRowSetWriter() {
 138.603 +
 138.604 +        RowSetWriter rsWriter = null;
 138.605 +        try {
 138.606 +            rsWriter = SyncFactory.getInstance(className).getRowSetWriter();
 138.607 +        } catch (SyncFactoryException sfEx) {
 138.608 +            //
 138.609          }
 138.610  
 138.611 -        public void setVersion(String providerVer) {
 138.612 -            ver = providerVer;
 138.613 +        return rsWriter;
 138.614 +    }
 138.615 +
 138.616 +    public void setDataSourceLock(int param)
 138.617 +            throws SyncProviderException {
 138.618 +
 138.619 +        try {
 138.620 +            SyncFactory.getInstance(className).setDataSourceLock(param);
 138.621 +        } catch (SyncFactoryException sfEx) {
 138.622 +
 138.623 +            throw new SyncProviderException(sfEx.getMessage());
 138.624          }
 138.625 +    }
 138.626  
 138.627 -        public String getVersion() {
 138.628 -            return ver;
 138.629 -        }
 138.630 -
 138.631 -        public void setIndex(int i) {
 138.632 -            index = i;
 138.633 -        }
 138.634 -
 138.635 -        public int getIndex() {
 138.636 -            return index;
 138.637 -        }
 138.638 -
 138.639 -        public int getDataSourceLock() throws SyncProviderException {
 138.640 -
 138.641 -           int dsLock = 0;
 138.642 -            try
 138.643 -            {
 138.644 -               dsLock = SyncFactory.getInstance(className).getDataSourceLock();
 138.645 -            } catch(SyncFactoryException sfEx) {
 138.646 -
 138.647 -                 throw new SyncProviderException(sfEx.getMessage());
 138.648 -             }
 138.649 -
 138.650 -            return dsLock;
 138.651 -        }
 138.652 -
 138.653 -        public int getProviderGrade() {
 138.654 -
 138.655 -           int grade = 0;
 138.656 -
 138.657 -           try
 138.658 -           {
 138.659 -              grade =  SyncFactory.getInstance(className).getProviderGrade();
 138.660 -           } catch(SyncFactoryException sfEx) {
 138.661 -               //
 138.662 -           }
 138.663 -
 138.664 -           return grade;
 138.665 -        }
 138.666 -
 138.667 -        public String getProviderID() {
 138.668 -            return className;
 138.669 -        }
 138.670 -
 138.671 -        /*
 138.672 -        public javax.sql.RowSetInternal getRowSetInternal() {
 138.673 -          try
 138.674 -           {
 138.675 -              return SyncFactory.getInstance(className).getRowSetInternal();
 138.676 -           } catch(SyncFactoryException sfEx) {
 138.677 -               //
 138.678 -           }
 138.679 -        }
 138.680 -        */
 138.681 -
 138.682 -        public javax.sql.RowSetReader getRowSetReader() {
 138.683 -
 138.684 -        RowSetReader rsReader = null;;
 138.685 -
 138.686 -        try
 138.687 -        {
 138.688 -           rsReader = SyncFactory.getInstance(className).getRowSetReader();
 138.689 -         } catch(SyncFactoryException sfEx) {
 138.690 -               //
 138.691 -         }
 138.692 -
 138.693 -         return rsReader;
 138.694 -
 138.695 -        }
 138.696 -
 138.697 -        public javax.sql.RowSetWriter getRowSetWriter() {
 138.698 -
 138.699 -        RowSetWriter rsWriter = null;
 138.700 -        try
 138.701 -           {
 138.702 -            rsWriter =  SyncFactory.getInstance(className).getRowSetWriter();
 138.703 -           } catch(SyncFactoryException sfEx) {
 138.704 -               //
 138.705 -           }
 138.706 -
 138.707 -           return rsWriter;
 138.708 -        }
 138.709 -        public void setDataSourceLock(int param)
 138.710 -        throws SyncProviderException {
 138.711 -
 138.712 -         try
 138.713 -           {
 138.714 -              SyncFactory.getInstance(className).setDataSourceLock(param);
 138.715 -           } catch(SyncFactoryException sfEx) {
 138.716 -
 138.717 -               throw new SyncProviderException(sfEx.getMessage());
 138.718 -           }
 138.719 -        }
 138.720 -
 138.721 -        public int supportsUpdatableView() {
 138.722 +    public int supportsUpdatableView() {
 138.723  
 138.724          int view = 0;
 138.725  
 138.726 -        try
 138.727 -         {
 138.728 -           view = SyncFactory.getInstance(className).supportsUpdatableView();
 138.729 -         } catch(SyncFactoryException sfEx) {
 138.730 -               //
 138.731 -         }
 138.732 +        try {
 138.733 +            view = SyncFactory.getInstance(className).supportsUpdatableView();
 138.734 +        } catch (SyncFactoryException sfEx) {
 138.735 +            //
 138.736 +        }
 138.737  
 138.738 -         return view;
 138.739 -       }
 138.740 -
 138.741 +        return view;
 138.742      }
 138.743 +}
   139.1 --- a/src/share/classes/javax/sql/rowset/spi/SyncProvider.java	Thu Sep 23 17:33:40 2010 -0700
   139.2 +++ b/src/share/classes/javax/sql/rowset/spi/SyncProvider.java	Fri Sep 24 16:41:32 2010 -0700
   139.3 @@ -1,5 +1,5 @@
   139.4  /*
   139.5 - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
   139.6 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   139.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   139.8   *
   139.9   * This code is free software; you can redistribute it and/or modify it
  139.10 @@ -344,7 +344,7 @@
  139.11       * source without checking the validity of any data.
  139.12       *
  139.13       */
  139.14 -    public static int GRADE_NONE = 1;
  139.15 +    public static final int GRADE_NONE = 1;
  139.16  
  139.17      /**
  139.18       * Indicates a low level optimistic synchronization grade with
  139.19 @@ -354,7 +354,7 @@
  139.20       * returning this grade will check only rows that have changed.
  139.21       *
  139.22       */
  139.23 -    public static int GRADE_CHECK_MODIFIED_AT_COMMIT = 2;
  139.24 +    public static final int GRADE_CHECK_MODIFIED_AT_COMMIT = 2;
  139.25  
  139.26      /**
  139.27       * Indicates a high level optimistic synchronization grade with
  139.28 @@ -364,7 +364,7 @@
  139.29       * returning this grade will check all rows, including rows that have not
  139.30       * changed.
  139.31       */
  139.32 -    public static int GRADE_CHECK_ALL_AT_COMMIT = 3;
  139.33 +    public static final int GRADE_CHECK_ALL_AT_COMMIT = 3;
  139.34  
  139.35      /**
  139.36       * Indicates a pessimistic synchronization grade with
  139.37 @@ -374,7 +374,7 @@
  139.38       * implementation returning this grade will lock the row in the originating
  139.39       * data source.
  139.40       */
  139.41 -    public static int GRADE_LOCK_WHEN_MODIFIED = 4;
  139.42 +    public static final int GRADE_LOCK_WHEN_MODIFIED = 4;
  139.43  
  139.44      /**
  139.45       * Indicates the most pessimistic synchronization grade with
  139.46 @@ -384,47 +384,47 @@
  139.47       * table affected by the original statement used to populate a
  139.48       * <code>RowSet</code> object.
  139.49       */
  139.50 -    public static int GRADE_LOCK_WHEN_LOADED = 5;
  139.51 +    public static final int GRADE_LOCK_WHEN_LOADED = 5;
  139.52  
  139.53      /**
  139.54       * Indicates that no locks remain on the originating data source. This is the default
  139.55       * lock setting for all <code>SyncProvider</code> implementations unless
  139.56       * otherwise directed by a <code>RowSet</code> object.
  139.57       */
  139.58 -    public static int DATASOURCE_NO_LOCK = 1;
  139.59 +    public static final int DATASOURCE_NO_LOCK = 1;
  139.60  
  139.61      /**
  139.62       * Indicates that a lock is placed on the rows that are touched by the original
  139.63       * SQL statement used to populate the <code>RowSet</code> object
  139.64       * that is using this <code>SyncProvider</code> object.
  139.65       */
  139.66 -    public static int DATASOURCE_ROW_LOCK = 2;
  139.67 +    public static final int DATASOURCE_ROW_LOCK = 2;
  139.68  
  139.69      /**
  139.70       * Indicates that a lock is placed on all tables that are touched by the original
  139.71       * SQL statement used to populate the <code>RowSet</code> object
  139.72       * that is using this <code>SyncProvider</code> object.
  139.73       */
  139.74 -    public static int DATASOURCE_TABLE_LOCK = 3;
  139.75 +    public static final int DATASOURCE_TABLE_LOCK = 3;
  139.76  
  139.77      /**
  139.78       * Indicates that a lock is placed on the entire data source that is the source of
  139.79       * data for the <code>RowSet</code> object
  139.80       * that is using this <code>SyncProvider</code> object.
  139.81       */
  139.82 -    public static int DATASOURCE_DB_LOCK = 4;
  139.83 +    public static final int DATASOURCE_DB_LOCK = 4;
  139.84  
  139.85      /**
  139.86       * Indicates that a <code>SyncProvider</code> implementation
  139.87       * supports synchronization between a <code>RowSet</code> object and
  139.88       * the SQL <code>VIEW</code> used to populate it.
  139.89       */
  139.90 -    public static int UPDATABLE_VIEW_SYNC = 5;
  139.91 +    public static final int UPDATABLE_VIEW_SYNC = 5;
  139.92  
  139.93      /**
  139.94       * Indicates that a <code>SyncProvider</code> implementation
  139.95       * does <B>not</B> support synchronization between a <code>RowSet</code>
  139.96       * object and the SQL <code>VIEW</code> used to populate it.
  139.97       */
  139.98 -    public static int NONUPDATABLE_VIEW_SYNC = 6;
  139.99 +    public static final int NONUPDATABLE_VIEW_SYNC = 6;
 139.100  }
   140.1 --- a/src/share/classes/javax/swing/JColorChooser.java	Thu Sep 23 17:33:40 2010 -0700
   140.2 +++ b/src/share/classes/javax/swing/JColorChooser.java	Fri Sep 24 16:41:32 2010 -0700
   140.3 @@ -27,13 +27,11 @@
   140.4  
   140.5  import java.awt.*;
   140.6  import java.awt.event.*;
   140.7 -import java.beans.*;
   140.8  import java.io.*;
   140.9  import java.util.*;
  140.10  
  140.11  import javax.swing.colorchooser.*;
  140.12  import javax.swing.plaf.ColorChooserUI;
  140.13 -import javax.swing.event.*;
  140.14  import javax.accessibility.*;
  140.15  
  140.16  import sun.swing.SwingUtilities2;
  140.17 @@ -95,7 +93,7 @@
  140.18  
  140.19      private ColorSelectionModel selectionModel;
  140.20  
  140.21 -    private JComponent previewPanel;
  140.22 +    private JComponent previewPanel = ColorChooserComponentFactory.getPreviewPanel();
  140.23  
  140.24      private AbstractColorChooserPanel[] chooserPanels = new AbstractColorChooserPanel[0];
  140.25  
   141.1 --- a/src/share/classes/javax/swing/JDialog.java	Thu Sep 23 17:33:40 2010 -0700
   141.2 +++ b/src/share/classes/javax/swing/JDialog.java	Fri Sep 24 16:41:32 2010 -0700
   141.3 @@ -1,5 +1,5 @@
   141.4  /*
   141.5 - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
   141.6 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
   141.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   141.8   *
   141.9   * This code is free software; you can redistribute it and/or modify it
  141.10 @@ -26,12 +26,7 @@
  141.11  
  141.12  import java.awt.*;
  141.13  import java.awt.event.*;
  141.14 -import java.beans.PropertyChangeListener;
  141.15 -import java.util.Locale;
  141.16 -import java.util.Vector;
  141.17 -import java.io.Serializable;
  141.18  import javax.accessibility.*;
  141.19 -import java.applet.Applet;
  141.20  
  141.21  /**
  141.22   * The main class for creating a dialog window. You can use this class
  141.23 @@ -45,30 +40,30 @@
  141.24   *
  141.25   * <p>
  141.26   *
  141.27 - * The <code>JDialog</code> component contains a <code>JRootPane</code>
  141.28 + * The {@code JDialog} component contains a {@code JRootPane}
  141.29   * as its only child.
  141.30 - * The <code>contentPane</code> should be the parent of any children of the
  141.31 - * <code>JDialog</code>.
  141.32 - * As a convenience <code>add</code> and its variants, <code>remove</code> and
  141.33 - * <code>setLayout</code> have been overridden to forward to the
  141.34 - * <code>contentPane</code> as necessary. This means you can write:
  141.35 + * The {@code contentPane} should be the parent of any children of the
  141.36 + * {@code JDialog}.
  141.37 + * As a convenience {@code add} and its variants, {@code remove} and
  141.38 + * {@code setLayout} have been overridden to forward to the
  141.39 + * {@code contentPane} as necessary. This means you can write:
  141.40   * <pre>
  141.41   *       dialog.add(child);
  141.42   * </pre>
  141.43   * And the child will be added to the contentPane.
  141.44 - * The <code>contentPane</code> is always non-<code>null</code>.
  141.45 - * Attempting to set it to <code>null</code> generates an exception.
  141.46 - * The default <code>contentPane</code> has a <code>BorderLayout</code>
  141.47 + * The {@code contentPane} is always non-{@code null}.
  141.48 + * Attempting to set it to {@code null} generates an exception.
  141.49 + * The default {@code contentPane} has a {@code BorderLayout}
  141.50   * manager set on it.
  141.51   * Refer to {@link javax.swing.RootPaneContainer}
  141.52 - * for details on adding, removing and setting the <code>LayoutManager</code>
  141.53 - * of a <code>JDialog</code>.
  141.54 + * for details on adding, removing and setting the {@code LayoutManager}
  141.55 + * of a {@code JDialog}.
  141.56   * <p>
  141.57 - * Please see the <code>JRootPane</code> documentation for a complete
  141.58 - * description of the <code>contentPane</code>, <code>glassPane</code>,
  141.59 - * and <code>layeredPane</code> components.
  141.60 + * Please see the {@code JRootPane} documentation for a complete
  141.61 + * description of the {@code contentPane}, {@code glassPane},
  141.62 + * and {@code layeredPane} components.
  141.63   * <p>
  141.64 - * In a multi-screen environment, you can create a <code>JDialog</code>
  141.65 + * In a multi-screen environment, you can create a {@code JDialog}
  141.66   * on a different screen device than its owner.  See {@link java.awt.Frame} for
  141.67   * more information.
  141.68   * <p>
  141.69 @@ -83,7 +78,7 @@
  141.70   * appropriate for short term storage or RMI between applications running
  141.71   * the same version of Swing.  As of 1.4, support for long term storage
  141.72   * of all JavaBeans<sup><font size="-2">TM</font></sup>
  141.73 - * has been added to the <code>java.beans</code> package.
  141.74 + * has been added to the {@code java.beans} package.
  141.75   * Please see {@link java.beans.XMLEncoder}.
  141.76   *
  141.77   * @see JOptionPane
  141.78 @@ -120,9 +115,9 @@
  141.79      protected JRootPane rootPane;
  141.80  
  141.81      /**
  141.82 -     * If true then calls to <code>add</code> and <code>setLayout</code>
  141.83 -     * will be forwarded to the <code>contentPane</code>. This is initially
  141.84 -     * false, but is set to true when the <code>JDialog</code> is constructed.
  141.85 +     * If true then calls to {@code add} and {@code setLayout}
  141.86 +     * will be forwarded to the {@code contentPane}. This is initially
  141.87 +     * false, but is set to true when the {@code JDialog} is constructed.
  141.88       *
  141.89       * @see #isRootPaneCheckingEnabled
  141.90       * @see #setRootPaneCheckingEnabled
  141.91 @@ -131,26 +126,26 @@
  141.92      protected boolean rootPaneCheckingEnabled = false;
  141.93  
  141.94      /**
  141.95 -     * The <code>TransferHandler</code> for this dialog.
  141.96 +     * The {@code TransferHandler} for this dialog.
  141.97       */
  141.98      private TransferHandler transferHandler;
  141.99  
 141.100      /**
 141.101       * Creates a modeless dialog without a title and without a specified
 141.102 -     * <code>Frame</code> owner.  A shared, hidden frame will be
 141.103 +     * {@code Frame} owner.  A shared, hidden frame will be
 141.104       * set as the owner of the dialog.
 141.105       * <p>
 141.106       * This constructor sets the component's locale property to the value
 141.107 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.108 +     * returned by {@code JComponent.getDefaultLocale}.
 141.109       * <p>
 141.110       * NOTE: This constructor does not allow you to create an unowned
 141.111 -     * <code>JDialog</code>. To create an unowned <code>JDialog</code>
 141.112 -     * you must use either the <code>JDialog(Window)</code> or
 141.113 -     * <code>JDialog(Dialog)</code> constructor with an argument of
 141.114 -     * <code>null</code>.
 141.115 +     * {@code JDialog}. To create an unowned {@code JDialog}
 141.116 +     * you must use either the {@code JDialog(Window)} or
 141.117 +     * {@code JDialog(Dialog)} constructor with an argument of
 141.118 +     * {@code null}.
 141.119       *
 141.120 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.121 -     *     returns <code>true</code>.
 141.122 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.123 +     *     returns {@code true}.
 141.124       * @see java.awt.GraphicsEnvironment#isHeadless
 141.125       * @see JComponent#getDefaultLocale
 141.126       */
 141.127 @@ -160,22 +155,22 @@
 141.128  
 141.129      /**
 141.130       * Creates a modeless dialog without a title with the
 141.131 -     * specified <code>Frame</code> as its owner.  If <code>owner</code>
 141.132 -     * is <code>null</code>, a shared, hidden frame will be set as the
 141.133 +     * specified {@code Frame} as its owner.  If {@code owner}
 141.134 +     * is {@code null}, a shared, hidden frame will be set as the
 141.135       * owner of the dialog.
 141.136       * <p>
 141.137       * This constructor sets the component's locale property to the value
 141.138 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.139 +     * returned by {@code JComponent.getDefaultLocale}.
 141.140       * <p>
 141.141       * NOTE: This constructor does not allow you to create an unowned
 141.142 -     * <code>JDialog</code>. To create an unowned <code>JDialog</code>
 141.143 -     * you must use either the <code>JDialog(Window)</code> or
 141.144 -     * <code>JDialog(Dialog)</code> constructor with an argument of
 141.145 -     * <code>null</code>.
 141.146 +     * {@code JDialog}. To create an unowned {@code JDialog}
 141.147 +     * you must use either the {@code JDialog(Window)} or
 141.148 +     * {@code JDialog(Dialog)} constructor with an argument of
 141.149 +     * {@code null}.
 141.150       *
 141.151 -     * @param owner the <code>Frame</code> from which the dialog is displayed
 141.152 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.153 -     *     returns <code>true</code>.
 141.154 +     * @param owner the {@code Frame} from which the dialog is displayed
 141.155 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.156 +     *     returns {@code true}.
 141.157       * @see java.awt.GraphicsEnvironment#isHeadless
 141.158       * @see JComponent#getDefaultLocale
 141.159       */
 141.160 @@ -184,25 +179,25 @@
 141.161      }
 141.162  
 141.163      /**
 141.164 -     * Creates a dialog with the specified owner <code>Frame</code>, modality
 141.165 -     * and an empty title. If <code>owner</code> is <code>null</code>,
 141.166 +     * Creates a dialog with the specified owner {@code Frame}, modality
 141.167 +     * and an empty title. If {@code owner} is {@code null},
 141.168       * a shared, hidden frame will be set as the owner of the dialog.
 141.169       * <p>
 141.170       * This constructor sets the component's locale property to the value
 141.171 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.172 +     * returned by {@code JComponent.getDefaultLocale}.
 141.173       * <p>
 141.174       * NOTE: This constructor does not allow you to create an unowned
 141.175 -     * <code>JDialog</code>. To create an unowned <code>JDialog</code>
 141.176 -     * you must use either the <code>JDialog(Window)</code> or
 141.177 -     * <code>JDialog(Dialog)</code> constructor with an argument of
 141.178 -     * <code>null</code>.
 141.179 +     * {@code JDialog}. To create an unowned {@code JDialog}
 141.180 +     * you must use either the {@code JDialog(Window)} or
 141.181 +     * {@code JDialog(Dialog)} constructor with an argument of
 141.182 +     * {@code null}.
 141.183       *
 141.184 -     * @param owner the <code>Frame</code> from which the dialog is displayed
 141.185 +     * @param owner the {@code Frame} from which the dialog is displayed
 141.186       * @param modal specifies whether dialog blocks user input to other top-level
 141.187 -     *     windows when shown. If <code>true</code>, the modality type property is set to
 141.188 -     *     <code>DEFAULT_MODALITY_TYPE</code>, otherwise the dialog is modeless.
 141.189 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.190 -     *     returns <code>true</code>.
 141.191 +     *     windows when shown. If {@code true}, the modality type property is set to
 141.192 +     *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless.
 141.193 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.194 +     *     returns {@code true}.
 141.195       * @see java.awt.GraphicsEnvironment#isHeadless
 141.196       * @see JComponent#getDefaultLocale
 141.197       */
 141.198 @@ -212,24 +207,24 @@
 141.199  
 141.200      /**
 141.201       * Creates a modeless dialog with the specified title and
 141.202 -     * with the specified owner frame.  If <code>owner</code>
 141.203 -     * is <code>null</code>, a shared, hidden frame will be set as the
 141.204 +     * with the specified owner frame.  If {@code owner}
 141.205 +     * is {@code null}, a shared, hidden frame will be set as the
 141.206       * owner of the dialog.
 141.207       * <p>
 141.208       * This constructor sets the component's locale property to the value
 141.209 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.210 +     * returned by {@code JComponent.getDefaultLocale}.
 141.211       * <p>
 141.212       * NOTE: This constructor does not allow you to create an unowned
 141.213 -     * <code>JDialog</code>. To create an unowned <code>JDialog</code>
 141.214 -     * you must use either the <code>JDialog(Window)</code> or
 141.215 -     * <code>JDialog(Dialog)</code> constructor with an argument of
 141.216 -     * <code>null</code>.
 141.217 +     * {@code JDialog}. To create an unowned {@code JDialog}
 141.218 +     * you must use either the {@code JDialog(Window)} or
 141.219 +     * {@code JDialog(Dialog)} constructor with an argument of
 141.220 +     * {@code null}.
 141.221       *
 141.222 -     * @param owner the <code>Frame</code> from which the dialog is displayed
 141.223 -     * @param title  the <code>String</code> to display in the dialog's
 141.224 +     * @param owner the {@code Frame} from which the dialog is displayed
 141.225 +     * @param title  the {@code String} to display in the dialog's
 141.226       *                  title bar
 141.227 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.228 -     *     returns <code>true</code>.
 141.229 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.230 +     *     returns {@code true}.
 141.231       * @see java.awt.GraphicsEnvironment#isHeadless
 141.232       * @see JComponent#getDefaultLocale
 141.233       */
 141.234 @@ -238,31 +233,31 @@
 141.235      }
 141.236  
 141.237      /**
 141.238 -     * Creates a dialog with the specified title, owner <code>Frame</code>
 141.239 -     * and modality. If <code>owner</code> is <code>null</code>,
 141.240 +     * Creates a dialog with the specified title, owner {@code Frame}
 141.241 +     * and modality. If {@code owner} is {@code null},
 141.242       * a shared, hidden frame will be set as the owner of this dialog.
 141.243       * <p>
 141.244       * This constructor sets the component's locale property to the value
 141.245 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.246 +     * returned by {@code JComponent.getDefaultLocale}.
 141.247       * <p>
 141.248 -     * NOTE: Any popup components (<code>JComboBox</code>,
 141.249 -     * <code>JPopupMenu</code>, <code>JMenuBar</code>)
 141.250 +     * NOTE: Any popup components ({@code JComboBox},
 141.251 +     * {@code JPopupMenu}, {@code JMenuBar})
 141.252       * created within a modal dialog will be forced to be lightweight.
 141.253       * <p>
 141.254       * NOTE: This constructor does not allow you to create an unowned
 141.255 -     * <code>JDialog</code>. To create an unowned <code>JDialog</code>
 141.256 -     * you must use either the <code>JDialog(Window)</code> or
 141.257 -     * <code>JDialog(Dialog)</code> constructor with an argument of
 141.258 -     * <code>null</code>.
 141.259 +     * {@code JDialog}. To create an unowned {@code JDialog}
 141.260 +     * you must use either the {@code JDialog(Window)} or
 141.261 +     * {@code JDialog(Dialog)} constructor with an argument of
 141.262 +     * {@code null}.
 141.263       *
 141.264 -     * @param owner the <code>Frame</code> from which the dialog is displayed
 141.265 -     * @param title  the <code>String</code> to display in the dialog's
 141.266 +     * @param owner the {@code Frame} from which the dialog is displayed
 141.267 +     * @param title  the {@code String} to display in the dialog's
 141.268       *     title bar
 141.269       * @param modal specifies whether dialog blocks user input to other top-level
 141.270 -     *     windows when shown. If <code>true</code>, the modality type property is set to
 141.271 -     *     <code>DEFAULT_MODALITY_TYPE</code> otherwise the dialog is modeless
 141.272 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.273 -     *     returns <code>true</code>.
 141.274 +     *     windows when shown. If {@code true}, the modality type property is set to
 141.275 +     *     {@code DEFAULT_MODALITY_TYPE} otherwise the dialog is modeless
 141.276 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.277 +     *     returns {@code true}.
 141.278       *
 141.279       * @see java.awt.Dialog.ModalityType
 141.280       * @see java.awt.Dialog.ModalityType#MODELESS
 141.281 @@ -285,35 +280,35 @@
 141.282  
 141.283      /**
 141.284       * Creates a dialog with the specified title,
 141.285 -     * owner <code>Frame</code>, modality and <code>GraphicsConfiguration</code>.
 141.286 -     * If <code>owner</code> is <code>null</code>,
 141.287 +     * owner {@code Frame}, modality and {@code GraphicsConfiguration}.
 141.288 +     * If {@code owner} is {@code null},
 141.289       * a shared, hidden frame will be set as the owner of this dialog.
 141.290       * <p>
 141.291       * This constructor sets the component's locale property to the value
 141.292 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.293 +     * returned by {@code JComponent.getDefaultLocale}.
 141.294       * <p>
 141.295 -     * NOTE: Any popup components (<code>JComboBox</code>,
 141.296 -     * <code>JPopupMenu</code>, <code>JMenuBar</code>)
 141.297 +     * NOTE: Any popup components ({@code JComboBox},
 141.298 +     * {@code JPopupMenu}, {@code JMenuBar})
 141.299       * created within a modal dialog will be forced to be lightweight.
 141.300       * <p>
 141.301       * NOTE: This constructor does not allow you to create an unowned
 141.302 -     * <code>JDialog</code>. To create an unowned <code>JDialog</code>
 141.303 -     * you must use either the <code>JDialog(Window)</code> or
 141.304 -     * <code>JDialog(Dialog)</code> constructor with an argument of
 141.305 -     * <code>null</code>.
 141.306 +     * {@code JDialog}. To create an unowned {@code JDialog}
 141.307 +     * you must use either the {@code JDialog(Window)} or
 141.308 +     * {@code JDialog(Dialog)} constructor with an argument of
 141.309 +     * {@code null}.
 141.310       *
 141.311 -     * @param owner the <code>Frame</code> from which the dialog is displayed
 141.312 -     * @param title  the <code>String</code> to display in the dialog's
 141.313 +     * @param owner the {@code Frame} from which the dialog is displayed
 141.314 +     * @param title  the {@code String} to display in the dialog's
 141.315       *     title bar
 141.316       * @param modal specifies whether dialog blocks user input to other top-level
 141.317 -     *     windows when shown. If <code>true</code>, the modality type property is set to
 141.318 -     *     <code>DEFAULT_MODALITY_TYPE</code>, otherwise the dialog is modeless.
 141.319 -     * @param gc the <code>GraphicsConfiguration</code>
 141.320 -     *     of the target screen device.  If <code>gc</code> is
 141.321 -     *     <code>null</code>, the same
 141.322 -     *     <code>GraphicsConfiguration</code> as the owning Frame is used.
 141.323 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.324 -     *     returns <code>true</code>.
 141.325 +     *     windows when shown. If {@code true}, the modality type property is set to
 141.326 +     *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless.
 141.327 +     * @param gc the {@code GraphicsConfiguration}
 141.328 +     *     of the target screen device.  If {@code gc} is
 141.329 +     *     {@code null}, the same
 141.330 +     *     {@code GraphicsConfiguration} as the owning Frame is used.
 141.331 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.332 +     *     returns {@code true}.
 141.333       * @see java.awt.Dialog.ModalityType
 141.334       * @see java.awt.Dialog.ModalityType#MODELESS
 141.335       * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
 141.336 @@ -337,15 +332,15 @@
 141.337  
 141.338      /**
 141.339       * Creates a modeless dialog without a title with the
 141.340 -     * specified <code>Dialog</code> as its owner.
 141.341 +     * specified {@code Dialog} as its owner.
 141.342       * <p>
 141.343       * This constructor sets the component's locale property to the value
 141.344 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.345 +     * returned by {@code JComponent.getDefaultLocale}.
 141.346       *
 141.347 -     * @param owner the owner <code>Dialog</code> from which the dialog is displayed
 141.348 -     *     or <code>null</code> if this dialog has no owner
 141.349 -     * @exception HeadlessException <code>if GraphicsEnvironment.isHeadless()</code>
 141.350 -     *     returns <code>true</code>.
 141.351 +     * @param owner the owner {@code Dialog} from which the dialog is displayed
 141.352 +     *     or {@code null} if this dialog has no owner
 141.353 +     * @throws HeadlessException {@code if GraphicsEnvironment.isHeadless()}
 141.354 +     *     returns {@code true}.
 141.355       * @see java.awt.GraphicsEnvironment#isHeadless
 141.356       * @see JComponent#getDefaultLocale
 141.357       */
 141.358 @@ -354,18 +349,18 @@
 141.359      }
 141.360  
 141.361      /**
 141.362 -     * Creates a dialog with the specified owner <code>Dialog</code> and modality.
 141.363 +     * Creates a dialog with the specified owner {@code Dialog} and modality.
 141.364       * <p>
 141.365       * This constructor sets the component's locale property to the value
 141.366 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.367 +     * returned by {@code JComponent.getDefaultLocale}.
 141.368       *
 141.369 -     * @param owner the owner <code>Dialog</code> from which the dialog is displayed
 141.370 -     *     or <code>null</code> if this dialog has no owner
 141.371 +     * @param owner the owner {@code Dialog} from which the dialog is displayed
 141.372 +     *     or {@code null} if this dialog has no owner
 141.373       * @param modal specifies whether dialog blocks user input to other top-level
 141.374 -     *     windows when shown. If <code>true</code>, the modality type property is set to
 141.375 -     *     <code>DEFAULT_MODALITY_TYPE</code>, otherwise the dialog is modeless.
 141.376 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.377 -     *     returns <code>true</code>.
 141.378 +     *     windows when shown. If {@code true}, the modality type property is set to
 141.379 +     *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless.
 141.380 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.381 +     *     returns {@code true}.
 141.382       * @see java.awt.Dialog.ModalityType
 141.383       * @see java.awt.Dialog.ModalityType#MODELESS
 141.384       * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
 141.385 @@ -383,14 +378,14 @@
 141.386       * with the specified owner dialog.
 141.387       * <p>
 141.388       * This constructor sets the component's locale property to the value
 141.389 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.390 +     * returned by {@code JComponent.getDefaultLocale}.
 141.391       *
 141.392 -     * @param owner the owner <code>Dialog</code> from which the dialog is displayed
 141.393 -     *     or <code>null</code> if this dialog has no owner
 141.394 -     * @param title  the <code>String</code> to display in the dialog's
 141.395 +     * @param owner the owner {@code Dialog} from which the dialog is displayed
 141.396 +     *     or {@code null} if this dialog has no owner
 141.397 +     * @param title  the {@code String} to display in the dialog's
 141.398       *                  title bar
 141.399 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.400 -     *     returns <code>true</code>.
 141.401 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.402 +     *     returns {@code true}.
 141.403       * @see java.awt.GraphicsEnvironment#isHeadless
 141.404       * @see JComponent#getDefaultLocale
 141.405       */
 141.406 @@ -400,20 +395,20 @@
 141.407  
 141.408      /**
 141.409       * Creates a dialog with the specified title, modality
 141.410 -     * and the specified owner <code>Dialog</code>.
 141.411 +     * and the specified owner {@code Dialog}.
 141.412       * <p>
 141.413       * This constructor sets the component's locale property to the value
 141.414 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.415 +     * returned by {@code JComponent.getDefaultLocale}.
 141.416       *
 141.417 -     * @param owner the owner <code>Dialog</code> from which the dialog is displayed
 141.418 -     *     or <code>null</code> if this dialog has no owner
 141.419 -     * @param title  the <code>String</code> to display in the dialog's
 141.420 +     * @param owner the owner {@code Dialog} from which the dialog is displayed
 141.421 +     *     or {@code null} if this dialog has no owner
 141.422 +     * @param title  the {@code String} to display in the dialog's
 141.423       *     title bar
 141.424       * @param modal specifies whether dialog blocks user input to other top-level
 141.425 -     *     windows when shown. If <code>true</code>, the modality type property is set to
 141.426 -     *     <code>DEFAULT_MODALITY_TYPE</code>, otherwise the dialog is modeless
 141.427 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.428 -     *     returns <code>true</code>.
 141.429 +     *     windows when shown. If {@code true}, the modality type property is set to
 141.430 +     *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless
 141.431 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.432 +     *     returns {@code true}.
 141.433       * @see java.awt.Dialog.ModalityType
 141.434       * @see java.awt.Dialog.ModalityType#MODELESS
 141.435       * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
 141.436 @@ -428,30 +423,30 @@
 141.437      }
 141.438  
 141.439      /**
 141.440 -     * Creates a dialog with the specified title, owner <code>Dialog</code>,
 141.441 -     * modality and <code>GraphicsConfiguration</code>.
 141.442 +     * Creates a dialog with the specified title, owner {@code Dialog},
 141.443 +     * modality and {@code GraphicsConfiguration}.
 141.444       *
 141.445       * <p>
 141.446 -     * NOTE: Any popup components (<code>JComboBox</code>,
 141.447 -     * <code>JPopupMenu</code>, <code>JMenuBar</code>)
 141.448 +     * NOTE: Any popup components ({@code JComboBox},
 141.449 +     * {@code JPopupMenu}, {@code JMenuBar})
 141.450       * created within a modal dialog will be forced to be lightweight.
 141.451       * <p>
 141.452       * This constructor sets the component's locale property to the value
 141.453 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.454 +     * returned by {@code JComponent.getDefaultLocale}.
 141.455       *
 141.456 -     * @param owner the owner <code>Dialog</code> from which the dialog is displayed
 141.457 -     *     or <code>null</code> if this dialog has no owner
 141.458 -     * @param title  the <code>String</code> to display in the dialog's
 141.459 +     * @param owner the owner {@code Dialog} from which the dialog is displayed
 141.460 +     *     or {@code null} if this dialog has no owner
 141.461 +     * @param title  the {@code String} to display in the dialog's
 141.462       *     title bar
 141.463       * @param modal specifies whether dialog blocks user input to other top-level
 141.464 -     *     windows when shown. If <code>true</code>, the modality type property is set to
 141.465 -     *     <code>DEFAULT_MODALITY_TYPE</code>, otherwise the dialog is modeless
 141.466 -     * @param gc the <code>GraphicsConfiguration</code>
 141.467 -     *     of the target screen device.  If <code>gc</code> is
 141.468 -     *     <code>null</code>, the same
 141.469 -     *     <code>GraphicsConfiguration</code> as the owning Dialog is used.
 141.470 -     * @exception HeadlessException if <code>GraphicsEnvironment.isHeadless()</code>
 141.471 -     *     returns <code>true</code>.
 141.472 +     *     windows when shown. If {@code true}, the modality type property is set to
 141.473 +     *     {@code DEFAULT_MODALITY_TYPE}, otherwise the dialog is modeless
 141.474 +     * @param gc the {@code GraphicsConfiguration}
 141.475 +     *     of the target screen device.  If {@code gc} is
 141.476 +     *     {@code null}, the same
 141.477 +     *     {@code GraphicsConfiguration} as the owning Dialog is used.
 141.478 +     * @throws HeadlessException if {@code GraphicsEnvironment.isHeadless()}
 141.479 +     *     returns {@code true}.
 141.480       * @see java.awt.Dialog.ModalityType
 141.481       * @see java.awt.Dialog.ModalityType#MODELESS
 141.482       * @see java.awt.Dialog#DEFAULT_MODALITY_TYPE
 141.483 @@ -468,16 +463,22 @@
 141.484      }
 141.485  
 141.486      /**
 141.487 -     * Creates a modeless dialog with the specified owner <code>Window</code> and
 141.488 +     * Creates a modeless dialog with the specified owner {@code Window} and
 141.489       * an empty title.
 141.490       * <p>
 141.491       * This constructor sets the component's locale property to the value
 141.492 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.493 +     * returned by {@code JComponent.getDefaultLocale}.
 141.494       *
 141.495 -     * @param owner the <code>Window</code> from which the dialog is displayed or
 141.496 -     *     <code>null</code> if this dialog has no owner
 141.497 -     * @exception HeadlessException when
 141.498 -     *    <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 141.499 +     * @param owner the {@code Window} from which the dialog is displayed or
 141.500 +     *     {@code null} if this dialog has no owner
 141.501 +     *
 141.502 +     * @throws IllegalArgumentException
 141.503 +     *     if the {@code owner} is not an instance of {@link java.awt.Dialog Dialog}
 141.504 +     *     or {@link java.awt.Frame Frame}
 141.505 +     * @throws IllegalArgumentException
 141.506 +     *     if the {@code owner}'s {@code GraphicsConfiguration} is not from a screen device
 141.507 +     * @throws HeadlessException
 141.508 +     *     when {@code GraphicsEnvironment.isHeadless()} returns {@code true}
 141.509       *
 141.510       * @see java.awt.GraphicsEnvironment#isHeadless
 141.511       * @see JComponent#getDefaultLocale
 141.512 @@ -489,19 +490,28 @@
 141.513      }
 141.514  
 141.515      /**
 141.516 -     * Creates a dialog with the specified owner <code>Window</code>, modality
 141.517 +     * Creates a dialog with the specified owner {@code Window}, modality
 141.518       * and an empty title.
 141.519       * <p>
 141.520       * This constructor sets the component's locale property to the value
 141.521 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.522 +     * returned by {@code JComponent.getDefaultLocale}.
 141.523       *
 141.524 -     * @param owner the <code>Window</code> from which the dialog is displayed or
 141.525 -     *     <code>null</code> if this dialog has no owner
 141.526 +     * @param owner the {@code Window} from which the dialog is displayed or
 141.527 +     *     {@code null} if this dialog has no owner
 141.528       * @param modalityType specifies whether dialog blocks input to other
 141.529 -     *     windows when shown. <code>null</code> value and unsupported modality
 141.530 -     *     types are equivalent to <code>MODELESS</code>
 141.531 -     * @exception HeadlessException when
 141.532 -     *    <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 141.533 +     *     windows when shown. {@code null} value and unsupported modality
 141.534 +     *     types are equivalent to {@code MODELESS}
 141.535 +     *
 141.536 +     * @throws IllegalArgumentException
 141.537 +     *     if the {@code owner} is not an instance of {@link java.awt.Dialog Dialog}
 141.538 +     *     or {@link java.awt.Frame Frame}
 141.539 +     * @throws IllegalArgumentException
 141.540 +     *     if the {@code owner}'s {@code GraphicsConfiguration} is not from a screen device
 141.541 +     * @throws HeadlessException
 141.542 +     *     when {@code GraphicsEnvironment.isHeadless()} returns {@code true}
 141.543 +     * @throws SecurityException
 141.544 +     *     if the calling thread does not have permission to create modal dialogs
 141.545 +     *     with the given {@code modalityType}
 141.546       *
 141.547       * @see java.awt.Dialog.ModalityType
 141.548       * @see java.awt.Dialog#setModal
 141.549 @@ -517,17 +527,23 @@
 141.550  
 141.551      /**
 141.552       * Creates a modeless dialog with the specified title and owner
 141.553 -     * <code>Window</code>.
 141.554 +     * {@code Window}.
 141.555       * <p>
 141.556       * This constructor sets the component's locale property to the value
 141.557 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.558 +     * returned by {@code JComponent.getDefaultLocale}.
 141.559       *
 141.560 -     * @param owner the <code>Window</code> from which the dialog is displayed or
 141.561 -     *     <code>null</code> if this dialog has no owner
 141.562 -     * @param title the <code>String</code> to display in the dialog's
 141.563 -     *     title bar or <code>null</code> if the dialog has no title
 141.564 -     * @exception java.awt.HeadlessException when
 141.565 -     *     <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 141.566 +     * @param owner the {@code Window} from which the dialog is displayed or
 141.567 +     *     {@code null} if this dialog has no owner
 141.568 +     * @param title the {@code String} to display in the dialog's
 141.569 +     *     title bar or {@code null} if the dialog has no title
 141.570 +     *
 141.571 +     * @throws IllegalArgumentException
 141.572 +     *     if the {@code owner} is not an instance of {@link java.awt.Dialog Dialog}
 141.573 +     *     or {@link java.awt.Frame Frame}
 141.574 +     * @throws IllegalArgumentException
 141.575 +     *     if the {@code owner}'s {@code GraphicsConfiguration} is not from a screen device
 141.576 +     * @throws HeadlessException
 141.577 +     *     when {@code GraphicsEnvironment.isHeadless()} returns {@code true}
 141.578       *
 141.579       * @see java.awt.GraphicsEnvironment#isHeadless
 141.580       * @see JComponent#getDefaultLocale
 141.581 @@ -539,21 +555,30 @@
 141.582      }
 141.583  
 141.584      /**
 141.585 -     * Creates a dialog with the specified title, owner <code>Window</code> and
 141.586 +     * Creates a dialog with the specified title, owner {@code Window} and
 141.587       * modality.
 141.588       * <p>
 141.589       * This constructor sets the component's locale property to the value
 141.590 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.591 +     * returned by {@code JComponent.getDefaultLocale}.
 141.592       *
 141.593 -     * @param owner the <code>Window</code> from which the dialog is displayed or
 141.594 -     *     <code>null</code> if this dialog has no owner
 141.595 -     * @param title the <code>String</code> to display in the dialog's
 141.596 -     *     title bar or <code>null</code> if the dialog has no title
 141.597 +     * @param owner the {@code Window} from which the dialog is displayed or
 141.598 +     *     {@code null} if this dialog has no owner
 141.599 +     * @param title the {@code String} to display in the dialog's
 141.600 +     *     title bar or {@code null} if the dialog has no title
 141.601       * @param modalityType specifies whether dialog blocks input to other
 141.602 -     *     windows when shown. <code>null</code> value and unsupported modality
 141.603 -     *     types are equivalent to <code>MODELESS</code>
 141.604 -     * @exception java.awt.HeadlessException when
 141.605 -     *     <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 141.606 +     *     windows when shown. {@code null} value and unsupported modality
 141.607 +     *     types are equivalent to {@code MODELESS}
 141.608 +     *
 141.609 +     * @throws IllegalArgumentException
 141.610 +     *     if the {@code owner} is not an instance of {@link java.awt.Dialog Dialog}
 141.611 +     *     or {@link java.awt.Frame Frame}
 141.612 +     * @throws IllegalArgumentException
 141.613 +     *     if the {@code owner}'s {@code GraphicsConfiguration} is not from a screen device
 141.614 +     * @throws HeadlessException
 141.615 +     *     when {@code GraphicsEnvironment.isHeadless()} returns {@code true}
 141.616 +     * @throws SecurityException
 141.617 +     *     if the calling thread does not have permission to create modal dialogs
 141.618 +     *     with the given {@code modalityType}
 141.619       *
 141.620       * @see java.awt.Dialog.ModalityType
 141.621       * @see java.awt.Dialog#setModal
 141.622 @@ -569,29 +594,38 @@
 141.623      }
 141.624  
 141.625      /**
 141.626 -     * Creates a dialog with the specified title, owner <code>Window</code>,
 141.627 -     * modality and <code>GraphicsConfiguration</code>.
 141.628 +     * Creates a dialog with the specified title, owner {@code Window},
 141.629 +     * modality and {@code GraphicsConfiguration}.
 141.630       * <p>
 141.631 -     * NOTE: Any popup components (<code>JComboBox</code>,
 141.632 -     * <code>JPopupMenu</code>, <code>JMenuBar</code>)
 141.633 +     * NOTE: Any popup components ({@code JComboBox},
 141.634 +     * {@code JPopupMenu}, {@code JMenuBar})
 141.635       * created within a modal dialog will be forced to be lightweight.
 141.636       * <p>
 141.637       * This constructor sets the component's locale property to the value
 141.638 -     * returned by <code>JComponent.getDefaultLocale</code>.
 141.639 +     * returned by {@code JComponent.getDefaultLocale}.
 141.640       *
 141.641 -     * @param owner the <code>Window</code> from which the dialog is displayed or
 141.642 -     *     <code>null</code> if this dialog has no owner
 141.643 -     * @param title the <code>String</code> to display in the dialog's
 141.644 -     *     title bar or <code>null</code> if the dialog has no title
 141.645 +     * @param owner the {@code Window} from which the dialog is displayed or
 141.646 +     *     {@code null} if this dialog has no owner
 141.647 +     * @param title the {@code String} to display in the dialog's
 141.648 +     *     title bar or {@code null} if the dialog has no title
 141.649       * @param modalityType specifies whether dialog blocks input to other
 141.650 -     *     windows when shown. <code>null</code> value and unsupported modality
 141.651 -     *     types are equivalent to <code>MODELESS</code>
 141.652 -     * @param gc the <code>GraphicsConfiguration</code> of the target screen device;
 141.653 -     *     if <code>null</code>, the <code>GraphicsConfiguration</code> from the owning
 141.654 -     *     window is used; if <code>owner</code> is also <code>null</code>, the
 141.655 -     *     system default <code>GraphicsConfiguration</code> is assumed
 141.656 -     * @exception java.awt.HeadlessException when
 141.657 -     *    <code>GraphicsEnvironment.isHeadless()</code> returns <code>true</code>
 141.658 +     *     windows when shown. {@code null} value and unsupported modality
 141.659 +     *     types are equivalent to {@code MODELESS}
 141.660 +     * @param gc the {@code GraphicsConfiguration} of the target screen device;
 141.661 +     *     if {@code null}, the {@code GraphicsConfiguration} from the owning
 141.662 +     *     window is used; if {@code owner} is also {@code null}, the
 141.663 +     *     system default {@code GraphicsConfiguration} is assumed
 141.664 +     *
 141.665 +     * @throws IllegalArgumentException
 141.666 +     *     if the {@code owner} is not an instance of {@link java.awt.Dialog Dialog}
 141.667 +     *     or {@link java.awt.Frame Frame}
 141.668 +     * @throws IllegalArgumentException
 141.669 +     *     if the {@code owner}'s {@code GraphicsConfiguration} is not from a screen device
 141.670 +     * @throws HeadlessException
 141.671 +     *     when {@code GraphicsEnvironment.isHeadless()} returns {@code true}
 141.672 +     * @throws SecurityException
 141.673 +     *     if the calling thread does not have permission to create modal dialogs
 141.674 +     *     with the given {@code modalityType}
 141.675       *
 141.676       * @see java.awt.Dialog.ModalityType
 141.677       * @see java.awt.Dialog#setModal
 141.678 @@ -608,7 +642,7 @@
 141.679      }
 141.680  
 141.681      /**
 141.682 -     * Called by the constructors to init the <code>JDialog</code> properly.
 141.683 +     * Called by the constructors to init the {@code JDialog} properly.
 141.684       */
 141.685      protected void dialogInit() {
 141.686          enableEvents(AWTEvent.KEY_EVENT_MASK | AWTEvent.WINDOW_EVENT_MASK);
 141.687 @@ -628,7 +662,7 @@
 141.688  
 141.689      /**
 141.690       * Called by the constructor methods to create the default
 141.691 -     * <code>rootPane</code>.
 141.692 +     * {@code rootPane}.
 141.693       */
 141.694      protected JRootPane createRootPane() {
 141.695          JRootPane rp = new JRootPane();
 141.696 @@ -642,7 +676,7 @@
 141.697  
 141.698      /**
 141.699       * Handles window events depending on the state of the
 141.700 -     * <code>defaultCloseOperation</code> property.
 141.701 +     * {@code defaultCloseOperation} property.
 141.702       *
 141.703       * @see #setDefaultCloseOperation
 141.704       */
 141.705 @@ -671,26 +705,26 @@
 141.706       * You must specify one of the following choices:
 141.707       * <p>
 141.708       * <ul>
 141.709 -     * <li><code>DO_NOTHING_ON_CLOSE</code>
 141.710 -     * (defined in <code>WindowConstants</code>):
 141.711 +     * <li>{@code DO_NOTHING_ON_CLOSE}
 141.712 +     * (defined in {@code WindowConstants}):
 141.713       * Don't do anything; require the
 141.714 -     * program to handle the operation in the <code>windowClosing</code>
 141.715 -     * method of a registered <code>WindowListener</code> object.
 141.716 +     * program to handle the operation in the {@code windowClosing}
 141.717 +     * method of a registered {@code WindowListener} object.
 141.718       *
 141.719 -     * <li><code>HIDE_ON_CLOSE</code>
 141.720 -     * (defined in <code>WindowConstants</code>):
 141.721 +     * <li>{@code HIDE_ON_CLOSE}
 141.722 +     * (defined in {@code WindowConstants}):
 141.723       * Automatically hide the dialog after
 141.724 -     * invoking any registered <code>WindowListener</code>
 141.725 +     * invoking any registered {@code WindowListener}
 141.726       * objects.
 141.727       *
 141.728 -     * <li><code>DISPOSE_ON_CLOSE</code>
 141.729 -     * (defined in <code>WindowConstants</code>):
 141.730 +     * <li>{@code DISPOSE_ON_CLOSE}
 141.731 +     * (defined in {@code WindowConstants}):
 141.732       * Automatically hide and dispose the
 141.733 -     * dialog after invoking any registered <code>WindowListener</code>
 141.734 +     * dialog after invoking any registered {@code WindowListener}
 141.735       * objects.
 141.736       * </ul>
 141.737       * <p>
 141.738 -     * The value is set to <code>HIDE_ON_CLOSE</code> by default. Changes
 141.739 +     * The value is set to {@code HIDE_ON_CLOSE} by default. Changes
 141.740       * to the value of this property cause the firing of a property
 141.741       * change event, with property name "defaultCloseOperation".
 141.742       * <p>
 141.743 @@ -779,9 +813,9 @@
 141.744      }
 141.745  
 141.746      /**
 141.747 -     * Gets the <code>transferHandler</code> property.
 141.748 +     * Gets the {@code transferHandler} property.
 141.749       *
 141.750 -     * @return the value of the <code>transferHandler</code> property
 141.751 +     * @return the value of the {@code transferHandler} property
 141.752       *
 141.753       * @see TransferHandler
 141.754       * @see #setTransferHandler
 141.755 @@ -792,10 +826,10 @@
 141.756      }
 141.757  
 141.758      /**
 141.759 -     * Calls <code>paint(g)</code>.  This method was overridden to
 141.760 +     * Calls {@code paint(g)}.  This method was overridden to
 141.761       * prevent an unnecessary call to clear the background.
 141.762       *
 141.763 -     * @param g  the <code>Graphics</code> context in which to paint
 141.764 +     * @param g  the {@code Graphics} context in which to paint
 141.765       */
 141.766      public void update(Graphics g) {
 141.767          paint(g);
 141.768 @@ -827,10 +861,10 @@
 141.769  
 141.770  
 141.771      /**
 141.772 -     * Returns whether calls to <code>add</code> and
 141.773 -     * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
 141.774 +     * Returns whether calls to {@code add} and
 141.775 +     * {@code setLayout} are forwarded to the {@code contentPane}.
 141.776       *
 141.777 -     * @return true if <code>add</code> and <code>setLayout</code>
 141.778 +     * @return true if {@code add} and {@code setLayout}
 141.779       *         are fowarded; false otherwise
 141.780       *
 141.781       * @see #addImpl
 141.782 @@ -844,12 +878,12 @@
 141.783  
 141.784  
 141.785      /**
 141.786 -     * Sets whether calls to <code>add</code> and
 141.787 -     * <code>setLayout</code> are forwarded to the <code>contentPane</code>.
 141.788 +     * Sets whether calls to {@code add} and
 141.789 +     * {@code setLayout} are forwarded to the {@code contentPane}.
 141.790       *
 141.791 -     * @param enabled  true if <code>add</code> and <code>setLayout</code>
 141.792 +     * @param enabled  true if {@code add} and {@code setLayout}
 141.793       *        are forwarded, false if they should operate directly on the
 141.794 -     *        <code>JDialog</code>.
 141.795 +     *        {@code JDialog}.
 141.796       *
 141.797       * @see #addImpl
 141.798       * @see #setLayout
 141.799 @@ -864,20 +898,20 @@
 141.800      }
 141.801  
 141.802      /**
 141.803 -     * Adds the specified child <code>Component</code>.
 141.804 +     * Adds the specified child {@code Component}.
 141.805       * This method is overridden to conditionally forward calls to the
 141.806 -     * <code>contentPane</code>.
 141.807 -     * By default, children are added to the <code>contentPane</code> instead
 141.808 +     * {@code contentPane}.
 141.809 +     * By default, children are added to the {@code contentPane} instead
 141.810       * of the frame, refer to {@link javax.swing.RootPaneContainer} for
 141.811       * details.
 141.812       *
 141.813       * @param comp the component to be enhanced
 141.814       * @param constraints the constraints to be respected
 141.815       * @param index the index
 141.816 -     * @exception IllegalArgumentException if <code>index</code> is invalid
 141.817 -     * @exception IllegalArgumentException if adding the container's parent
 141.818 +     * @throws IllegalArgumentException if {@code index} is invalid
 141.819 +     * @throws IllegalArgumentException if adding the container's parent
 141.820       *                  to itself
 141.821 -     * @exception IllegalArgumentException if adding a window to a container
 141.822 +     * @throws IllegalArgumentException if adding a window to a container
 141.823       *
 141.824       * @see #setRootPaneCheckingEnabled
 141.825       * @see javax.swing.RootPaneContainer
 141.826 @@ -894,13 +928,13 @@
 141.827  
 141.828      /**
 141.829       * Removes the specified component from the container. If
 141.830 -     * <code>comp</code> is not the <code>rootPane</code>, this will forward
 141.831 -     * the call to the <code>contentPane</code>. This will do nothing if
 141.832 -     * <code>comp</code> is not a child of the <code>JDialog</code> or
 141.833 -     * <code>contentPane</code>.
 141.834 +     * {@code comp} is not the {@code rootPane}, this will forward
 141.835 +     * the call to the {@code contentPane}. This will do nothing if
 141.836 +     * {@code comp} is not a child of the {@code JDialog} or
 141.837 +     * {@code contentPane}.
 141.838       *
 141.839       * @param comp the component to be removed
 141.840 -     * @throws NullPointerException if <code>comp</code> is null
 141.841 +     * @throws NullPointerException if {@code comp} is null
 141.842       * @see #add
 141.843       * @see javax.swing.RootPaneContainer
 141.844       */
 141.845 @@ -914,13 +948,13 @@
 141.846  
 141.847  
 141.848      /**
 141.849 -     * Sets the <code>LayoutManager</code>.
 141.850 +     * Sets the {@code LayoutManager}.
 141.851       * Overridden to conditionally forward the call to the
 141.852 -     * <code>contentPane</code>.
 141.853 +     * {@code contentPane}.
 141.854       * Refer to {@link javax.swing.RootPaneContainer} for
 141.855       * more information.
 141.856       *
 141.857 -     * @param manager the <code>LayoutManager</code>
 141.858 +     * @param manager the {@code LayoutManager}
 141.859       * @see #setRootPaneCheckingEnabled
 141.860       * @see javax.swing.RootPaneContainer
 141.861       */
 141.862 @@ -935,7 +969,7 @@
 141.863  
 141.864  
 141.865      /**
 141.866 -     * Returns the <code>rootPane</code> object for this dialog.
 141.867 +     * Returns the {@code rootPane} object for this dialog.
 141.868       *
 141.869       * @see #setRootPane
 141.870       * @see RootPaneContainer#getRootPane
 141.871 @@ -946,10 +980,10 @@
 141.872  
 141.873  
 141.874      /**
 141.875 -     * Sets the <code>rootPane</code> property.
 141.876 +     * Sets the {@code rootPane} property.
 141.877       * This method is called by the constructor.
 141.878       *
 141.879 -     * @param root the <code>rootPane</code> object for this dialog
 141.880 +     * @param root the {@code rootPane} object for this dialog
 141.881       *
 141.882       * @see #getRootPane
 141.883       *
 141.884 @@ -976,9 +1010,9 @@
 141.885  
 141.886  
 141.887      /**
 141.888 -     * Returns the <code>contentPane</code> object for this dialog.
 141.889 +     * Returns the {@code contentPane} object for this dialog.
 141.890       *
 141.891 -     * @return the <code>contentPane</code> property
 141.892 +     * @return the {@code contentPane} property
 141.893       *
 141.894       * @see #setContentPane
 141.895       * @see RootPaneContainer#getContentPane
 141.896 @@ -989,19 +1023,19 @@
 141.897  
 141.898  
 141.899     /**
 141.900 -     * Sets the <code>contentPane</code> property.
 141.901 +     * Sets the {@code contentPane} property.
 141.902       * This method is called by the constructor.
 141.903       * <p>
 141.904 -     * Swing's painting architecture requires an opaque <code>JComponent</code>
 141.905 +     * Swing's painting architecture requires an opaque {@code JComponent}
 141.906       * in the containment hiearchy. This is typically provided by the
 141.907       * content pane. If you replace the content pane it is recommended you
 141.908 -     * replace it with an opaque <code>JComponent</code>.
 141.909 +     * replace it with an opaque {@code JComponent}.
 141.910       * @see JRootPane
 141.911       *
 141.912 -     * @param contentPane the <code>contentPane</code> object for this dialog
 141.913 +     * @param contentPane the {@code contentPane} object for this dialog
 141.914       *
 141.915 -     * @exception java.awt.IllegalComponentStateException (a runtime
 141.916 -     *            exception) if the content pane parameter is <code>null</code>
 141.917 +     * @throws java.awt.IllegalComponentStateException (a runtime
 141.918 +     *            exception) if the content pane parameter is {@code null}
 141.919       * @see #getContentPane
 141.920       * @see RootPaneContainer#setContentPane
 141.921       *
 141.922 @@ -1015,9 +1049,9 @@
 141.923      }
 141.924  
 141.925      /**
 141.926 -     * Returns the <code>layeredPane</code> object for this dialog.
 141.927 +     * Returns the {@code layeredPane} object for this dialog.
 141.928       *
 141.929 -     * @return the <code>layeredPane</code> property
 141.930 +     * @return the {@code layeredPane} property
 141.931       *
 141.932       * @see #setLayeredPane
 141.933       * @see RootPaneContainer#getLayeredPane
 141.934 @@ -1027,12 +1061,12 @@
 141.935      }
 141.936  
 141.937      /**
 141.938 -     * Sets the <code>layeredPane</code> property.
 141.939 +     * Sets the {@code layeredPane} property.
 141.940       * This method is called by the constructor.
 141.941       *
 141.942 -     * @param layeredPane the new <code>layeredPane</code> property
 141.943 +     * @param layeredPane the new {@code layeredPane} property
 141.944       *
 141.945 -     * @exception java.awt.IllegalComponentStateException (a runtime
 141.946 +     * @throws java.awt.IllegalComponentStateException (a runtime
 141.947       *            exception) if the layered pane parameter is null
 141.948       * @see #getLayeredPane
 141.949       * @see RootPaneContainer#setLayeredPane
 141.950 @@ -1046,9 +1080,9 @@
 141.951      }
 141.952  
 141.953      /**
 141.954 -     * Returns the <code>glassPane</code> object for this dialog.
 141.955 +     * Returns the {@code glassPane} object for this dialog.
 141.956       *
 141.957 -     * @return the <code>glassPane</code> property
 141.958 +     * @return the {@code glassPane} property
 141.959       *
 141.960       * @see #setGlassPane
 141.961       * @see RootPaneContainer#getGlassPane
 141.962 @@ -1058,10 +1092,10 @@
 141.963      }
 141.964  
 141.965      /**
 141.966 -     * Sets the <code>glassPane</code> property.
 141.967 +     * Sets the {@code glassPane} property.
 141.968       * This method is called by the constructor.
 141.969       *
 141.970 -     * @param glassPane the <code>glassPane</code> object for this dialog
 141.971 +     * @param glassPane the {@code glassPane} object for this dialog
 141.972       * @see #getGlassPane
 141.973       * @see RootPaneContainer#setGlassPane
 141.974       *
 141.975 @@ -1085,7 +1119,7 @@
 141.976  
 141.977      /**
 141.978       * Repaints the specified rectangle of this component within
 141.979 -     * <code>time</code> milliseconds.  Refer to <code>RepaintManager</code>
 141.980 +     * {@code time} milliseconds.  Refer to {@code RepaintManager}
 141.981       * for details on how the repaint is handled.
 141.982       *
 141.983       * @param     time   maximum time in milliseconds before update
 141.984 @@ -1107,15 +1141,15 @@
 141.985      }
 141.986  
 141.987      /**
 141.988 -     * Provides a hint as to whether or not newly created <code>JDialog</code>s
 141.989 +     * Provides a hint as to whether or not newly created {@code JDialog}s
 141.990       * should have their Window decorations (such as borders, widgets to
 141.991       * close the window, title...) provided by the current look
 141.992 -     * and feel. If <code>defaultLookAndFeelDecorated</code> is true,
 141.993 -     * the current <code>LookAndFeel</code> supports providing window
 141.994 +     * and feel. If {@code defaultLookAndFeelDecorated} is true,
 141.995 +     * the current {@code LookAndFeel} supports providing window
 141.996       * decorations, and the current window manager supports undecorated
 141.997 -     * windows, then newly created <code>JDialog</code>s will have their
 141.998 -     * Window decorations provided by the current <code>LookAndFeel</code>.
 141.999 -     * Otherwise, newly created <code>JDialog</code>s will have their
141.1000 +     * windows, then newly created {@code JDialog}s will have their
141.1001 +     * Window decorations provided by the current {@code LookAndFeel}.
141.1002 +     * Otherwise, newly created {@code JDialog}s will have their
141.1003       * Window decorations provided by the current window manager.
141.1004       * <p>
141.1005       * You can get the same effect on a single JDialog by doing the following:
141.1006 @@ -1139,7 +1173,7 @@
141.1007      }
141.1008  
141.1009      /**
141.1010 -     * Returns true if newly created <code>JDialog</code>s should have their
141.1011 +     * Returns true if newly created {@code JDialog}s should have their
141.1012       * Window decorations provided by the current look and feel. This is only
141.1013       * a hint, as certain look and feels may not support this feature.
141.1014       *
141.1015 @@ -1156,14 +1190,14 @@
141.1016      }
141.1017  
141.1018      /**
141.1019 -     * Returns a string representation of this <code>JDialog</code>.
141.1020 +     * Returns a string representation of this {@code JDialog}.
141.1021       * This method
141.1022       * is intended to be used only for debugging purposes, and the
141.1023       * content and format of the returned string may vary between
141.1024       * implementations. The returned string may be empty but may not
141.1025 -     * be <code>null</code>.
141.1026 +     * be {@code null}.
141.1027       *
141.1028 -     * @return  a string representation of this <code>JDialog</code>.
141.1029 +     * @return  a string representation of this {@code JDialog}.
141.1030       */
141.1031      protected String paramString() {
141.1032          String defaultCloseOperationString;
141.1033 @@ -1210,7 +1244,7 @@
141.1034  
141.1035      /**
141.1036       * This class implements accessibility support for the
141.1037 -     * <code>JDialog</code> class.  It provides an implementation of the
141.1038 +     * {@code JDialog} class.  It provides an implementation of the
141.1039       * Java Accessibility API appropriate to dialog user-interface
141.1040       * elements.
141.1041       */
   142.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicBorders.java	Thu Sep 23 17:33:40 2010 -0700
   142.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicBorders.java	Fri Sep 24 16:41:32 2010 -0700
   142.3 @@ -1,5 +1,5 @@
   142.4  /*
   142.5 - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
   142.6 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
   142.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   142.8   *
   142.9   * This code is free software; you can redistribute it and/or modify it
  142.10 @@ -36,8 +36,6 @@
  142.11  import java.awt.Rectangle;
  142.12  import java.awt.Color;
  142.13  import java.awt.Graphics;
  142.14 -import java.io.Serializable;
  142.15 -
  142.16  
  142.17  /**
  142.18   * Factory object that can vend Borders appropriate for the basic L & F.
  142.19 @@ -431,6 +429,9 @@
  142.20  
  142.21          public void paintBorder(Component c, Graphics g, int x, int y,
  142.22                                  int width, int height) {
  142.23 +            if (!(c instanceof BasicSplitPaneDivider)) {
  142.24 +                return;
  142.25 +            }
  142.26              Component          child;
  142.27              Rectangle          cBounds;
  142.28              JSplitPane         splitPane = ((BasicSplitPaneDivider)c).
  142.29 @@ -510,6 +511,9 @@
  142.30  
  142.31          public void paintBorder(Component c, Graphics g, int x, int y,
  142.32                                  int width, int height) {
  142.33 +            if (!(c instanceof JSplitPane)) {
  142.34 +                return;
  142.35 +            }
  142.36              // The only tricky part with this border is that the divider is
  142.37              // not positioned at the top (for horizontal) or left (for vert),
  142.38              // so this border draws to where the divider is:
   143.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java	Thu Sep 23 17:33:40 2010 -0700
   143.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicColorChooserUI.java	Fri Sep 24 16:41:32 2010 -0700
   143.3 @@ -142,11 +142,8 @@
   143.4          if (previewPanel == null) {
   143.5              previewPanel = ColorChooserComponentFactory.getPreviewPanel();
   143.6          }
   143.7 -        else {
   143.8 -            Dimension size = new BorderLayout().minimumLayoutSize(previewPanel);
   143.9 -            if ((size.width == 0) && (size.height == 0)) {
  143.10 -                previewPanel = null;
  143.11 -            }
  143.12 +        else if (JPanel.class.equals(previewPanel.getClass()) && (0 == previewPanel.getComponentCount())) {
  143.13 +            previewPanel = null;
  143.14          }
  143.15          this.previewPanel = previewPanel;
  143.16          if (previewPanel != null) {
  143.17 @@ -215,9 +212,10 @@
  143.18      }
  143.19  
  143.20      private void selectionChanged(ColorSelectionModel model) {
  143.21 -        if (this.previewPanel != null) {
  143.22 -            this.previewPanel.setForeground(model.getSelectedColor());
  143.23 -            this.previewPanel.repaint();
  143.24 +        JComponent previewPanel = this.chooser.getPreviewPanel();
  143.25 +        if (previewPanel != null) {
  143.26 +            previewPanel.setForeground(model.getSelectedColor());
  143.27 +            previewPanel.repaint();
  143.28          }
  143.29          AbstractColorChooserPanel[] panels = this.chooser.getChooserPanels();
  143.30          if (panels != null) {
   144.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalBorders.java	Thu Sep 23 17:33:40 2010 -0700
   144.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalBorders.java	Fri Sep 24 16:41:32 2010 -0700
   144.3 @@ -1,5 +1,5 @@
   144.4  /*
   144.5 - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
   144.6 + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
   144.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   144.8   *
   144.9   * This code is free software; you can redistribute it and/or modify it
  144.10 @@ -33,14 +33,11 @@
  144.11  
  144.12  import java.awt.Component;
  144.13  import java.awt.Insets;
  144.14 -import java.awt.Dimension;
  144.15 -import java.awt.Rectangle;
  144.16  import java.awt.Color;
  144.17  import java.awt.Dialog;
  144.18  import java.awt.Frame;
  144.19  import java.awt.Graphics;
  144.20  import java.awt.Window;
  144.21 -import java.io.Serializable;
  144.22  
  144.23  import sun.swing.StringUIClientPropertyKey;
  144.24  
  144.25 @@ -81,6 +78,9 @@
  144.26          protected static Insets borderInsets = new Insets( 3, 3, 3, 3 );
  144.27  
  144.28          public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
  144.29 +            if (!(c instanceof AbstractButton)) {
  144.30 +                return;
  144.31 +            }
  144.32              if (MetalLookAndFeel.usingOcean()) {
  144.33                  paintOceanBorder(c, g, x, y, w, h);
  144.34                  return;
  144.35 @@ -473,8 +473,8 @@
  144.36              if (c instanceof JInternalFrame) {
  144.37                  Object obj = ((JInternalFrame) c).getClientProperty(
  144.38                                "JInternalFrame.messageType");
  144.39 -                if (obj != null && (obj instanceof Integer)) {
  144.40 -                    messageType = ((Integer) obj).intValue();
  144.41 +                if (obj instanceof Integer) {
  144.42 +                    messageType = (Integer) obj;
  144.43                  }
  144.44              }
  144.45  
  144.46 @@ -533,7 +533,7 @@
  144.47              if (MetalLookAndFeel.usingOcean()) {
  144.48                  // Only paint a border if we're not next to a horizontal
  144.49                  // toolbar
  144.50 -                if (!MetalToolBarUI.doesMenuBarBorderToolBar((JMenuBar)c)) {
  144.51 +                if ((c instanceof JMenuBar) && !MetalToolBarUI.doesMenuBarBorderToolBar((JMenuBar)c)) {
  144.52                      g.setColor(MetalLookAndFeel.getControl());
  144.53                      g.drawLine(0, h - 2, w, h - 2);
  144.54                      g.setColor(UIManager.getColor("MenuBar.borderColor"));
  144.55 @@ -564,6 +564,9 @@
  144.56          protected static Insets borderInsets = new Insets( 2, 2, 2, 2 );
  144.57  
  144.58          public void paintBorder( Component c, Graphics g, int x, int y, int w, int h ) {
  144.59 +            if (!(c instanceof JMenuItem)) {
  144.60 +                return;
  144.61 +            }
  144.62              JMenuItem b = (JMenuItem) c;
  144.63              ButtonModel model = b.getModel();
  144.64  
  144.65 @@ -687,6 +690,9 @@
  144.66  
  144.67          public void paintBorder( Component c, Graphics g, int x, int y, int w, int h )
  144.68          {
  144.69 +            if (!(c instanceof JToolBar)) {
  144.70 +                return;
  144.71 +            }
  144.72              g.translate( x, y );
  144.73  
  144.74              if ( ((JToolBar) c).isFloatable() )
  144.75 @@ -729,6 +735,9 @@
  144.76                  newInsets.top = newInsets.left = newInsets.bottom = newInsets.right = 2;
  144.77              }
  144.78  
  144.79 +            if (!(c instanceof JToolBar)) {
  144.80 +                return newInsets;
  144.81 +            }
  144.82              if ( ((JToolBar) c).isFloatable() ) {
  144.83                  if ( ((JToolBar) c).getOrientation() == HORIZONTAL ) {
  144.84                      if (c.getComponentOrientation().isLeftToRight()) {
  144.85 @@ -827,6 +836,9 @@
  144.86          public void paintBorder(Component c, Graphics g, int x, int y,
  144.87                            int w, int h) {
  144.88  
  144.89 +            if (!(c instanceof JScrollPane)) {
  144.90 +                return;
  144.91 +            }
  144.92              JScrollPane scroll = (JScrollPane)c;
  144.93              JComponent colHeader = scroll.getColumnHeader();
  144.94              int colHeaderHeight = 0;
   145.1 --- a/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Thu Sep 23 17:33:40 2010 -0700
   145.2 +++ b/src/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Fri Sep 24 16:41:32 2010 -0700
   145.3 @@ -1,5 +1,5 @@
   145.4  /*
   145.5 - * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
   145.6 + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
   145.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   145.8   *
   145.9   * This code is free software; you can redistribute it and/or modify it
  145.10 @@ -914,6 +914,7 @@
  145.11              UIResource {
  145.12          public SynthScrollableTabButton(int direction) {
  145.13              super(direction);
  145.14 +            setName("TabbedPane.button");
  145.15          }
  145.16      }
  145.17  }
   146.1 --- a/src/share/classes/sun/font/FontUtilities.java	Thu Sep 23 17:33:40 2010 -0700
   146.2 +++ b/src/share/classes/sun/font/FontUtilities.java	Fri Sep 24 16:41:32 2010 -0700
   146.3 @@ -373,8 +373,7 @@
   146.4       */
   146.5      public static FontUIResource getCompositeFontUIResource(Font font) {
   146.6  
   146.7 -        FontUIResource fuir =
   146.8 -            new FontUIResource(font.getName(),font.getStyle(),font.getSize());
   146.9 +        FontUIResource fuir = new FontUIResource(font);
  146.10          Font2D font2D = FontUtilities.getFont2D(font);
  146.11  
  146.12          if (!(font2D instanceof PhysicalFont)) {
   147.1 --- a/src/share/classes/sun/java2d/cmm/CMSManager.java	Thu Sep 23 17:33:40 2010 -0700
   147.2 +++ b/src/share/classes/sun/java2d/cmm/CMSManager.java	Fri Sep 24 16:41:32 2010 -0700
   147.3 @@ -100,12 +100,12 @@
   147.4          public long loadProfile(byte[] data) {
   147.5              System.err.print(cName + ".loadProfile");
   147.6              long profileID = tcmm.loadProfile(data);
   147.7 -            System.err.println("(ID=" + profileID + ")");
   147.8 +            System.err.printf("(ID=%x)\n", profileID);
   147.9              return profileID;
  147.10          }
  147.11  
  147.12          public void freeProfile(long profileID) {
  147.13 -            System.err.println(cName + ".freeProfile(ID=" + profileID + ")");
  147.14 +            System.err.printf(cName + ".freeProfile(ID=%x)\n", profileID);
  147.15              tcmm.freeProfile(profileID);
  147.16          }
  147.17  
  147.18 @@ -123,8 +123,8 @@
  147.19          }
  147.20  
  147.21          public int getTagSize(long profileID, int tagSignature) {
  147.22 -            System.err.print(cName + ".getTagSize(ID=" + profileID +
  147.23 -                               ", TagSig=" + tagSignature + ")");
  147.24 +            System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)",
  147.25 +                              profileID, signatureToString(tagSignature));
  147.26              int size = tcmm.getTagSize(profileID, tagSignature);
  147.27              System.err.println("=" + size);
  147.28              return size;
  147.29 @@ -132,8 +132,8 @@
  147.30  
  147.31          public void getTagData(long profileID, int tagSignature,
  147.32                                 byte[] data) {
  147.33 -            System.err.print(cName + ".getTagData(ID=" + profileID +
  147.34 -                             ", TagSig=" + tagSignature + ")");
  147.35 +            System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)",
  147.36 +                              profileID, signatureToString(tagSignature));
  147.37              System.err.println(" requested " + data.length + " byte(s)");
  147.38              tcmm.getTagData(profileID, tagSignature, data);
  147.39          }
  147.40 @@ -158,5 +158,13 @@
  147.41              System.err.println(cName + ".createTransform(ColorTransform[])");
  147.42              return tcmm.createTransform(transforms);
  147.43          }
  147.44 +
  147.45 +        private static String signatureToString(int sig) {
  147.46 +            return String.format("%c%c%c%c",
  147.47 +                                 (char)(0xff & (sig >> 24)),
  147.48 +                                 (char)(0xff & (sig >> 16)),
  147.49 +                                 (char)(0xff & (sig >>  8)),
  147.50 +                                 (char)(0xff & (sig      )));
  147.51 +        }
  147.52      }
  147.53  }
   148.1 --- a/src/share/classes/sun/java2d/cmm/lcms/LCMS.java	Thu Sep 23 17:33:40 2010 -0700
   148.2 +++ b/src/share/classes/sun/java2d/cmm/lcms/LCMS.java	Fri Sep 24 16:41:32 2010 -0700
   148.3 @@ -53,7 +53,8 @@
   148.4      public static native long getProfileID(ICC_Profile profile);
   148.5  
   148.6      public static native long createNativeTransform(
   148.7 -        long[] profileIDs, int renderType, Object disposerRef);
   148.8 +        long[] profileIDs, int renderType, int inFormatter, int outFormatter,
   148.9 +        Object disposerRef);
  148.10  
  148.11     /**
  148.12       * Constructs ColorTransform object corresponding to an ICC_profile
   149.1 --- a/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java	Thu Sep 23 17:33:40 2010 -0700
   149.2 +++ b/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java	Fri Sep 24 16:41:32 2010 -0700
   149.3 @@ -55,11 +55,17 @@
   149.4  
   149.5  public class LCMSTransform implements ColorTransform {
   149.6      long ID;
   149.7 +    private int inFormatter;
   149.8 +    private int outFormatter;
   149.9 +
  149.10      ICC_Profile[] profiles;
  149.11      long [] profileIDs;
  149.12      int renderType;
  149.13      int transformType;
  149.14  
  149.15 +    private int numInComponents = -1;
  149.16 +    private int numOutComponents = -1;
  149.17 +
  149.18      private Object disposerReferent = new Object();
  149.19  
  149.20      /* the class initializer */
  149.21 @@ -80,6 +86,14 @@
  149.22          this.renderType = (renderType == ColorTransform.Any)?
  149.23                                ICC_Profile.icPerceptual : renderType;
  149.24          this.transformType = transformType;
  149.25 +
  149.26 +        /* Note that ICC_Profile.getNumComponents() is quite expensive
  149.27 +         * (it may results in a reading of the profile header).
  149.28 +         * So, here we cache the number of components of input and
  149.29 +         * output profiles for further usage.
  149.30 +         */
  149.31 +        numInComponents = profiles[0].getNumComponents();
  149.32 +        numOutComponents = profiles[profiles.length - 1].getNumComponents();
  149.33      }
  149.34  
  149.35      public LCMSTransform (ColorTransform[] transforms) {
  149.36 @@ -99,26 +113,51 @@
  149.37              j += curTrans.profiles.length;
  149.38          }
  149.39          renderType = ((LCMSTransform)transforms[0]).renderType;
  149.40 -        ID = LCMS.createNativeTransform(profileIDs, renderType,
  149.41 -                                        disposerReferent);
  149.42 +
  149.43 +        /* Note that ICC_Profile.getNumComponents() is quite expensive
  149.44 +         * (it may results in a reading of the profile header).
  149.45 +         * So, here we cache the number of components of input and
  149.46 +         * output profiles for further usage.
  149.47 +         */
  149.48 +        numInComponents = profiles[0].getNumComponents();
  149.49 +        numOutComponents = profiles[profiles.length - 1].getNumComponents();
  149.50      }
  149.51  
  149.52      public int getNumInComponents() {
  149.53 -        return profiles[0].getNumComponents();
  149.54 +        return numInComponents;
  149.55      }
  149.56  
  149.57      public int getNumOutComponents() {
  149.58 -        return profiles[profiles.length - 1].getNumComponents();
  149.59 +        return numOutComponents;
  149.60 +    }
  149.61 +
  149.62 +    private synchronized void doTransform(LCMSImageLayout in,
  149.63 +                                          LCMSImageLayout out) {
  149.64 +        // update native transfrom if needed
  149.65 +        if (ID == 0L ||
  149.66 +            inFormatter != in.pixelType ||
  149.67 +            outFormatter != out.pixelType) {
  149.68 +
  149.69 +            if (ID != 0L) {
  149.70 +                // Disposer will destroy forgotten transform
  149.71 +                disposerReferent = new Object();
  149.72 +            }
  149.73 +            inFormatter = in.pixelType;
  149.74 +            outFormatter = out.pixelType;
  149.75 +
  149.76 +            ID = LCMS.createNativeTransform(profileIDs, renderType,
  149.77 +                                            inFormatter, outFormatter,
  149.78 +                                            disposerReferent);
  149.79 +        }
  149.80 +
  149.81 +        LCMS.colorConvert(this, in, out);
  149.82      }
  149.83  
  149.84      public void colorConvert(BufferedImage src, BufferedImage dst) {
  149.85          if (LCMSImageLayout.isSupported(src) &&
  149.86              LCMSImageLayout.isSupported(dst))
  149.87          {
  149.88 -            synchronized(this) {
  149.89 -                LCMS.colorConvert(this, new LCMSImageLayout(src),
  149.90 -                                  new LCMSImageLayout(dst));
  149.91 -            }
  149.92 +            doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst));
  149.93              return;
  149.94          }
  149.95          LCMSImageLayout srcIL, dstIL;
  149.96 @@ -204,9 +243,8 @@
  149.97                      }
  149.98                  }
  149.99                  // color convert srcLine to dstLine
 149.100 -                synchronized (this) {
 149.101 -                    LCMS.colorConvert(this, srcIL, dstIL);
 149.102 -                }
 149.103 +                doTransform(srcIL, dstIL);
 149.104 +
 149.105                  // convert dst scanline
 149.106                  pixel = null;
 149.107                  idx = 0;
 149.108 @@ -263,9 +301,8 @@
 149.109                      }
 149.110                  }
 149.111                  // color convert srcLine to dstLine
 149.112 -                synchronized(this) {
 149.113 -                    LCMS.colorConvert(this, srcIL, dstIL);
 149.114 -                }
 149.115 +                doTransform(srcIL, dstIL);
 149.116 +
 149.117                  // convert dst scanline
 149.118                  pixel = null;
 149.119                  idx = 0;
 149.120 @@ -377,9 +414,7 @@
 149.121              }
 149.122  
 149.123              // color convert srcLine to dstLine
 149.124 -            synchronized(this) {
 149.125 -                LCMS.colorConvert(this, srcIL, dstIL);
 149.126 -            }
 149.127 +            doTransform(srcIL, dstIL);
 149.128  
 149.129              // store dst scanline
 149.130              xd = dst.getMinX();
 149.131 @@ -470,9 +505,7 @@
 149.132                  }
 149.133  
 149.134                  // color convert srcLine to dstLine
 149.135 -                synchronized(this) {
 149.136 -                    LCMS.colorConvert(this, srcIL, dstIL);
 149.137 -                }
 149.138 +                doTransform(srcIL, dstIL);
 149.139  
 149.140                  // store dst scanline
 149.141                  xd = dst.getMinX();
 149.142 @@ -513,9 +546,8 @@
 149.143                  }
 149.144  
 149.145                  // color convert srcLine to dstLine
 149.146 -                synchronized(this) {
 149.147 -                    LCMS.colorConvert(this, srcIL, dstIL);
 149.148 -                }
 149.149 +                doTransform(srcIL, dstIL);
 149.150 +
 149.151                  // store dst scanline
 149.152                  xd = dst.getMinX();
 149.153                  idx = 0;
 149.154 @@ -550,9 +582,7 @@
 149.155              LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
 149.156              LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
 149.157  
 149.158 -        synchronized(this) {
 149.159 -            LCMS.colorConvert(this, srcIL, dstIL);
 149.160 -        }
 149.161 +        doTransform(srcIL, dstIL);
 149.162  
 149.163          return dst;
 149.164      }
 149.165 @@ -572,9 +602,7 @@
 149.166              LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
 149.167              LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
 149.168  
 149.169 -        synchronized(this) {
 149.170 -            LCMS.colorConvert(this, srcIL, dstIL);
 149.171 -        }
 149.172 +        doTransform(srcIL, dstIL);
 149.173  
 149.174          return dst;
 149.175      }
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/src/share/classes/sun/net/sdp/SdpSupport.java	Fri Sep 24 16:41:32 2010 -0700
   150.3 @@ -0,0 +1,81 @@
   150.4 +/*
   150.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   150.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   150.7 + *
   150.8 + * This code is free software; you can redistribute it and/or modify it
   150.9 + * under the terms of the GNU General Public License version 2 only, as
  150.10 + * published by the Free Software Foundation.  Oracle designates this
  150.11 + * particular file as subject to the "Classpath" exception as provided
  150.12 + * by Oracle in the LICENSE file that accompanied this code.
  150.13 + *
  150.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  150.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  150.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  150.17 + * version 2 for more details (a copy is included in the LICENSE file that
  150.18 + * accompanied this code).
  150.19 + *
  150.20 + * You should have received a copy of the GNU General Public License version
  150.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  150.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  150.23 + *
  150.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  150.25 + * or visit www.oracle.com if you need additional information or have any
  150.26 + * questions.
  150.27 + */
  150.28 +
  150.29 +package sun.net.sdp;
  150.30 +
  150.31 +import java.io.IOException;
  150.32 +import java.io.FileDescriptor;
  150.33 +import java.security.AccessController;
  150.34 +
  150.35 +import sun.misc.SharedSecrets;
  150.36 +import sun.misc.JavaIOFileDescriptorAccess;
  150.37 +
  150.38 +
  150.39 +/**
  150.40 + * This class defines methods for creating SDP sockets or "converting" existing
  150.41 + * file descriptors, referencing (unbound) TCP sockets, to SDP.
  150.42 + */
  150.43 +
  150.44 +public final class SdpSupport {
  150.45 +    private static final String os = AccessController
  150.46 +        .doPrivileged(new sun.security.action.GetPropertyAction("os.name"));
  150.47 +    private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux")));
  150.48 +    private static final JavaIOFileDescriptorAccess fdAccess =
  150.49 +        SharedSecrets.getJavaIOFileDescriptorAccess();
  150.50 +
  150.51 +    private SdpSupport() { }
  150.52 +
  150.53 +    /**
  150.54 +     * Creates a SDP socket, returning file descriptor referencing the socket.
  150.55 +     */
  150.56 +    public static FileDescriptor createSocket() throws IOException {
  150.57 +        if (!isSupported)
  150.58 +            throw new UnsupportedOperationException("SDP not supported on this platform");
  150.59 +        int fdVal = create0();
  150.60 +        FileDescriptor fd = new FileDescriptor();
  150.61 +        fdAccess.set(fd, fdVal);
  150.62 +        return fd;
  150.63 +    }
  150.64 +
  150.65 +    /**
  150.66 +     * Converts an existing file descriptor, that references an unbound TCP socket,
  150.67 +     * to SDP.
  150.68 +     */
  150.69 +    public static void convertSocket(FileDescriptor fd) throws IOException {
  150.70 +        if (!isSupported)
  150.71 +            throw new UnsupportedOperationException("SDP not supported on this platform");
  150.72 +        int fdVal = fdAccess.get(fd);
  150.73 +        convert0(fdVal);
  150.74 +    }
  150.75 +
  150.76 +    private static native int create0() throws IOException;
  150.77 +
  150.78 +    private static native void convert0(int fd) throws IOException;
  150.79 +
  150.80 +    static {
  150.81 +        AccessController.doPrivileged(
  150.82 +            new sun.security.action.LoadLibraryAction("net"));
  150.83 +    }
  150.84 +}
   151.1 --- a/src/share/classes/sun/nio/ch/FileChannelImpl.java	Thu Sep 23 17:33:40 2010 -0700
   151.2 +++ b/src/share/classes/sun/nio/ch/FileChannelImpl.java	Fri Sep 24 16:41:32 2010 -0700
   151.3 @@ -545,6 +545,8 @@
   151.4                                           long position, long count)
   151.5          throws IOException
   151.6      {
   151.7 +        if (!src.readable)
   151.8 +            throw new NonReadableChannelException();
   151.9          synchronized (src.positionLock) {
  151.10              long pos = src.position();
  151.11              long max = Math.min(count, src.size() - pos);
   152.1 --- a/src/share/classes/sun/nio/ch/IOUtil.java	Thu Sep 23 17:33:40 2010 -0700
   152.2 +++ b/src/share/classes/sun/nio/ch/IOUtil.java	Fri Sep 24 16:41:32 2010 -0700
   152.3 @@ -319,7 +319,12 @@
   152.4  
   152.5      static native boolean randomBytes(byte[] someBytes);
   152.6  
   152.7 -    static native void initPipe(int[] fda, boolean blocking);
   152.8 +    /**
   152.9 +     * Returns two file descriptors for a pipe encoded in a long.
  152.10 +     * The read end of the pipe is returned in the high 32 bits,
  152.11 +     * while the write end is returned in the low 32 bits.
  152.12 +     */
  152.13 +    static native long makePipe(boolean blocking);
  152.14  
  152.15      static native boolean drain(int fd) throws IOException;
  152.16  
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/src/share/classes/sun/nio/ch/Secrets.java	Fri Sep 24 16:41:32 2010 -0700
   153.3 @@ -0,0 +1,63 @@
   153.4 +/*
   153.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   153.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   153.7 + *
   153.8 + * This code is free software; you can redistribute it and/or modify it
   153.9 + * under the terms of the GNU General Public License version 2 only, as
  153.10 + * published by the Free Software Foundation.  Oracle designates this
  153.11 + * particular file as subject to the "Classpath" exception as provided
  153.12 + * by Oracle in the LICENSE file that accompanied this code.
  153.13 + *
  153.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  153.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  153.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  153.17 + * version 2 for more details (a copy is included in the LICENSE file that
  153.18 + * accompanied this code).
  153.19 + *
  153.20 + * You should have received a copy of the GNU General Public License version
  153.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  153.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  153.23 + *
  153.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  153.25 + * or visit www.oracle.com if you need additional information or have any
  153.26 + * questions.
  153.27 + */
  153.28 +
  153.29 +package sun.nio.ch;
  153.30 +
  153.31 +import java.nio.channels.SocketChannel;
  153.32 +import java.nio.channels.ServerSocketChannel;
  153.33 +import java.nio.channels.spi.SelectorProvider;
  153.34 +import java.io.FileDescriptor;
  153.35 +import java.io.IOException;
  153.36 +
  153.37 +/**
  153.38 + * Provides access to implementation private constructors and methods.
  153.39 + */
  153.40 +
  153.41 +public final class Secrets {
  153.42 +    private Secrets() { }
  153.43 +
  153.44 +    private static SelectorProvider provider() {
  153.45 +        SelectorProvider p = SelectorProvider.provider();
  153.46 +        if (!(p instanceof SelectorProviderImpl))
  153.47 +            throw new UnsupportedOperationException();
  153.48 +        return p;
  153.49 +    }
  153.50 +
  153.51 +    public static SocketChannel newSocketChannel(FileDescriptor fd) {
  153.52 +        try {
  153.53 +            return new SocketChannelImpl(provider(), fd, false);
  153.54 +        } catch (IOException ioe) {
  153.55 +            throw new AssertionError(ioe);
  153.56 +        }
  153.57 +    }
  153.58 +
  153.59 +    public static ServerSocketChannel newServerSocketChannel(FileDescriptor fd) {
  153.60 +        try {
  153.61 +            return new ServerSocketChannelImpl(provider(), fd, false);
  153.62 +        } catch (IOException ioe) {
  153.63 +            throw new AssertionError(ioe);
  153.64 +        }
  153.65 +    }
  153.66 +}
   154.1 --- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Thu Sep 23 17:33:40 2010 -0700
   154.2 +++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Fri Sep 24 16:41:32 2010 -0700
   154.3 @@ -80,21 +80,24 @@
   154.4      // -- End of fields protected by stateLock
   154.5  
   154.6  
   154.7 -    public ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
   154.8 +    ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
   154.9          super(sp);
  154.10          this.fd =  Net.serverSocket(true);
  154.11          this.fdVal = IOUtil.fdVal(fd);
  154.12          this.state = ST_INUSE;
  154.13      }
  154.14  
  154.15 -    public ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd)
  154.16 +    ServerSocketChannelImpl(SelectorProvider sp,
  154.17 +                            FileDescriptor fd,
  154.18 +                            boolean bound)
  154.19          throws IOException
  154.20      {
  154.21          super(sp);
  154.22          this.fd =  fd;
  154.23          this.fdVal = IOUtil.fdVal(fd);
  154.24          this.state = ST_INUSE;
  154.25 -        localAddress = Net.localAddress(fd);
  154.26 +        if (bound)
  154.27 +            localAddress = Net.localAddress(fd);
  154.28      }
  154.29  
  154.30      public ServerSocket socket() {
   155.1 --- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Thu Sep 23 17:33:40 2010 -0700
   155.2 +++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Fri Sep 24 16:41:32 2010 -0700
   155.3 @@ -103,6 +103,19 @@
   155.4          this.state = ST_UNCONNECTED;
   155.5      }
   155.6  
   155.7 +    SocketChannelImpl(SelectorProvider sp,
   155.8 +                      FileDescriptor fd,
   155.9 +                      boolean bound)
  155.10 +        throws IOException
  155.11 +    {
  155.12 +        super(sp);
  155.13 +        this.fd = fd;
  155.14 +        this.fdVal = IOUtil.fdVal(fd);
  155.15 +        this.state = ST_UNCONNECTED;
  155.16 +        if (bound)
  155.17 +            this.localAddress = Net.localAddress(fd);
  155.18 +    }
  155.19 +
  155.20      // Constructor for sockets obtained from server sockets
  155.21      //
  155.22      SocketChannelImpl(SelectorProvider sp,
   156.1 --- a/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Thu Sep 23 17:33:40 2010 -0700
   156.2 +++ b/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Fri Sep 24 16:41:32 2010 -0700
   156.3 @@ -4231,7 +4231,10 @@
   156.4      super("SQLPermission",
   156.5          "java.sql.SQLPermission",
   156.6          new String[]    {
   156.7 -                "setLog"
   156.8 +                "setLog",
   156.9 +                "callAbort",
  156.10 +                "setSyncFactory",
  156.11 +                "setNetworkTimeout",
  156.12                  },
  156.13          null);
  156.14      }
   157.1 --- a/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUI.java	Thu Sep 23 17:33:40 2010 -0700
   157.2 +++ b/src/share/classes/sun/swing/plaf/synth/SynthFileChooserUI.java	Fri Sep 24 16:41:32 2010 -0700
   157.3 @@ -1,5 +1,5 @@
   157.4  /*
   157.5 - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
   157.6 + * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
   157.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   157.8   *
   157.9   * This code is free software; you can redistribute it and/or modify it
  157.10 @@ -551,6 +551,9 @@
  157.11  
  157.12          public void paintBorder(Component c, Graphics g, int x, int y,
  157.13                                  int width, int height) {
  157.14 +            if (!(c instanceof JComponent)) {
  157.15 +                return;
  157.16 +            }
  157.17              JComponent jc = (JComponent)c;
  157.18              SynthContext context = getContext(jc);
  157.19              SynthStyle style = context.getStyle();
   158.1 --- a/src/share/classes/sun/util/LocaleServiceProviderPool.java	Thu Sep 23 17:33:40 2010 -0700
   158.2 +++ b/src/share/classes/sun/util/LocaleServiceProviderPool.java	Fri Sep 24 16:41:32 2010 -0700
   158.3 @@ -1,5 +1,5 @@
   158.4  /*
   158.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
   158.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   158.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   158.8   *
   158.9   * This code is free software; you can redistribute it and/or modify it
  158.10 @@ -28,18 +28,20 @@
  158.11  import java.security.AccessController;
  158.12  import java.security.PrivilegedActionException;
  158.13  import java.security.PrivilegedExceptionAction;
  158.14 -import java.util.Arrays;
  158.15 +import java.util.ArrayList;
  158.16  import java.util.HashSet;
  158.17 -import java.util.Iterator;
  158.18 +import java.util.IllformedLocaleException;
  158.19  import java.util.LinkedHashSet;
  158.20  import java.util.List;
  158.21  import java.util.Locale;
  158.22 +import java.util.Locale.Builder;
  158.23  import java.util.Map;
  158.24 +import java.util.ResourceBundle.Control;
  158.25  import java.util.ServiceLoader;
  158.26 -import java.util.ServiceConfigurationError;
  158.27  import java.util.Set;
  158.28  import java.util.concurrent.ConcurrentHashMap;
  158.29  import java.util.spi.LocaleServiceProvider;
  158.30 +
  158.31  import sun.util.logging.PlatformLogger;
  158.32  import sun.util.resources.LocaleData;
  158.33  import sun.util.resources.OpenListResourceBundle;
  158.34 @@ -90,6 +92,16 @@
  158.35      private Set<Locale> providerLocales = null;
  158.36  
  158.37      /**
  158.38 +     * Special locale for ja_JP with Japanese calendar
  158.39 +     */
  158.40 +    private static Locale locale_ja_JP_JP = new Locale("ja", "JP", "JP");
  158.41 +
  158.42 +    /**
  158.43 +     * Special locale for th_TH with Thai numbering system
  158.44 +     */
  158.45 +    private static Locale locale_th_TH_TH = new Locale("th", "TH", "TH");
  158.46 +
  158.47 +    /**
  158.48       * A factory method that returns a singleton instance
  158.49       */
  158.50      public static LocaleServiceProviderPool getPool(Class<? extends LocaleServiceProvider> providerClass) {
  158.51 @@ -153,14 +165,20 @@
  158.52                  java.util.spi.CurrencyNameProvider.class,
  158.53                  java.util.spi.LocaleNameProvider.class,
  158.54                  java.util.spi.TimeZoneNameProvider.class };
  158.55 -            Set<Locale> all = new HashSet<Locale>(Arrays.asList(
  158.56 -                    LocaleData.getAvailableLocales())
  158.57 -            );
  158.58 +
  158.59 +            // Normalize locales for look up
  158.60 +            Locale[] allLocales = LocaleData.getAvailableLocales();
  158.61 +            Set<Locale> all = new HashSet<Locale>(allLocales.length);
  158.62 +            for (Locale locale : allLocales) {
  158.63 +                all.add(getLookupLocale(locale));
  158.64 +            }
  158.65 +
  158.66              for (Class providerClass : providerClasses) {
  158.67                  LocaleServiceProviderPool pool =
  158.68                      LocaleServiceProviderPool.getPool(providerClass);
  158.69                  all.addAll(pool.getProviderLocales());
  158.70              }
  158.71 +
  158.72              allAvailableLocales = all.toArray(new Locale[0]);
  158.73          }
  158.74      }
  158.75 @@ -196,7 +214,8 @@
  158.76      }
  158.77  
  158.78      /**
  158.79 -     * Returns an array of available locales from providers.
  158.80 +     * Returns an array of available locales (already normalized
  158.81 +     * for service lookup) from providers.
  158.82       * Note that this method does not return a defensive copy.
  158.83       *
  158.84       * @return list of the provider locales
  158.85 @@ -208,7 +227,7 @@
  158.86                  for (LocaleServiceProvider lsp : providers) {
  158.87                      Locale[] locales = lsp.getAvailableLocales();
  158.88                      for (Locale locale: locales) {
  158.89 -                        providerLocales.add(locale);
  158.90 +                        providerLocales.add(getLookupLocale(locale));
  158.91                      }
  158.92                  }
  158.93              }
  158.94 @@ -227,15 +246,19 @@
  158.95      }
  158.96  
  158.97      /**
  158.98 -     * Returns an array of available locales supported by the JRE.
  158.99 +     * Returns an array of available locales (already normalized for
 158.100 +     * service lookup) supported by the JRE.
 158.101       * Note that this method does not return a defensive copy.
 158.102       *
 158.103       * @return list of the available JRE locales
 158.104       */
 158.105      private synchronized List<Locale> getJRELocales() {
 158.106          if (availableJRELocales == null) {
 158.107 -            availableJRELocales =
 158.108 -                Arrays.asList(LocaleData.getAvailableLocales());
 158.109 +            Locale[] allLocales = LocaleData.getAvailableLocales();
 158.110 +            availableJRELocales = new ArrayList<Locale>(allLocales.length);
 158.111 +            for (Locale locale : allLocales) {
 158.112 +                availableJRELocales.add(getLookupLocale(locale));
 158.113 +            }
 158.114          }
 158.115          return availableJRELocales;
 158.116      }
 158.117 @@ -249,7 +272,7 @@
 158.118       */
 158.119      private boolean isJRESupported(Locale locale) {
 158.120          List<Locale> locales = getJRELocales();
 158.121 -        return locales.contains(locale);
 158.122 +        return locales.contains(getLookupLocale(locale));
 158.123      }
 158.124  
 158.125      /**
 158.126 @@ -325,7 +348,7 @@
 158.127                  bundleKey = key;
 158.128              }
 158.129              Locale bundleLocale = (bundle != null ? bundle.getLocale() : null);
 158.130 -            Locale requested = locale;
 158.131 +            List<Locale> lookupLocales = getLookupLocales(locale);
 158.132              P lsp;
 158.133              S providersObj = null;
 158.134  
 158.135 @@ -333,21 +356,30 @@
 158.136              // to the requested locale than the bundle we've found (for
 158.137              // localized names), or Java runtime's supported locale
 158.138              // (for localized objects)
 158.139 -            while ((locale = findProviderLocale(locale, bundleLocale)) != null) {
 158.140 -
 158.141 -                lsp = (P)findProvider(locale);
 158.142 -
 158.143 -                if (lsp != null) {
 158.144 -                    providersObj = getter.getObject(lsp, requested, key, params);
 158.145 -                    if (providersObj != null) {
 158.146 -                        return providersObj;
 158.147 -                    } else if (isObjectProvider) {
 158.148 -                        config(
 158.149 -                            "A locale sensitive service provider returned null for a localized objects,  which should not happen.  provider: " + lsp + " locale: " + requested);
 158.150 +            Set<Locale> provLoc = getProviderLocales();
 158.151 +            for (int i = 0; i < lookupLocales.size(); i++) {
 158.152 +                Locale current = lookupLocales.get(i);
 158.153 +                if (bundleLocale != null) {
 158.154 +                    if (current.equals(bundleLocale)) {
 158.155 +                        break;
 158.156 +                    }
 158.157 +                } else {
 158.158 +                    if (isJRESupported(current)) {
 158.159 +                        break;
 158.160                      }
 158.161                  }
 158.162 -
 158.163 -                locale = getParentLocale(locale);
 158.164 +                if (provLoc.contains(current)) {
 158.165 +                    lsp = (P)findProvider(current);
 158.166 +                    if (lsp != null) {
 158.167 +                        providersObj = getter.getObject(lsp, locale, key, params);
 158.168 +                        if (providersObj != null) {
 158.169 +                            return providersObj;
 158.170 +                        } else if (isObjectProvider) {
 158.171 +                            config(
 158.172 +                                "A locale sensitive service provider returned null for a localized objects,  which should not happen.  provider: " + lsp + " locale: " + locale);
 158.173 +                        }
 158.174 +                    }
 158.175 +                }
 158.176              }
 158.177  
 158.178              // look up the JRE bundle and its parent chain.  Only
 158.179 @@ -361,7 +393,7 @@
 158.180                  } else {
 158.181                      lsp = (P)findProvider(bundleLocale);
 158.182                      if (lsp != null) {
 158.183 -                        providersObj = getter.getObject(lsp, requested, key, params);
 158.184 +                        providersObj = getter.getObject(lsp, locale, key, params);
 158.185                          if (providersObj != null) {
 158.186                              return providersObj;
 158.187                          }
 158.188 @@ -399,6 +431,8 @@
 158.189              for (LocaleServiceProvider lsp : providers) {
 158.190                  Locale[] locales = lsp.getAvailableLocales();
 158.191                  for (Locale available: locales) {
 158.192 +                    // normalize
 158.193 +                    available = getLookupLocale(available);
 158.194                      if (locale.equals(available)) {
 158.195                          LocaleServiceProvider providerInCache =
 158.196                              providersCache.put(locale, lsp);
 158.197 @@ -414,66 +448,51 @@
 158.198      }
 158.199  
 158.200      /**
 158.201 -     * Returns the provider's locale that is the most appropriate
 158.202 -     * within the range
 158.203 -     *
 158.204 -     * @param start the given locale that is used as the starting one
 158.205 -     * @param end the given locale that is used as the end one (exclusive),
 158.206 -     *     or null if it reaching any of the JRE supported locale should
 158.207 -     *     terminate the look up.
 158.208 -     * @return the most specific locale within the range, or null
 158.209 -     *     if no provider locale found in that range.
 158.210 +     * Returns a list of candidate locales for service look up.
 158.211 +     * @param locale the input locale
 158.212 +     * @return the list of candiate locales for the given locale
 158.213       */
 158.214 -    private Locale findProviderLocale(Locale start, Locale end) {
 158.215 -        Set<Locale> provLoc = getProviderLocales();
 158.216 -        Locale current = start;
 158.217 -
 158.218 -        while (current != null) {
 158.219 -            if (end != null) {
 158.220 -                if (current.equals(end)) {
 158.221 -                    current = null;
 158.222 -                    break;
 158.223 -                }
 158.224 -            } else {
 158.225 -                if (isJRESupported(current)) {
 158.226 -                    current = null;
 158.227 -                    break;
 158.228 -                }
 158.229 -            }
 158.230 -
 158.231 -            if (provLoc.contains(current)) {
 158.232 -                break;
 158.233 -            }
 158.234 -
 158.235 -            current = getParentLocale(current);
 158.236 -        }
 158.237 -
 158.238 -        return current;
 158.239 +    private static List<Locale> getLookupLocales(Locale locale) {
 158.240 +        // Note: We currently use the default implementation of
 158.241 +        // ResourceBundle.Control.getCandidateLocales. The result
 158.242 +        // returned by getCandidateLocales are already normalized
 158.243 +        // (no extensions) for service look up.
 158.244 +        List<Locale> lookupLocales = new Control(){}.getCandidateLocales("", locale);
 158.245 +        return lookupLocales;
 158.246      }
 158.247  
 158.248      /**
 158.249 -     * Returns the parent locale.
 158.250 +     * Returns an instance of Locale used for service look up.
 158.251 +     * The result Locale has no extensions except for ja_JP_JP
 158.252 +     * and th_TH_TH
 158.253       *
 158.254       * @param locale the locale
 158.255 -     * @return the parent locale
 158.256 +     * @return the locale used for service look up
 158.257       */
 158.258 -    private static Locale getParentLocale(Locale locale) {
 158.259 -        String variant = locale.getVariant();
 158.260 -        if (variant != "") {
 158.261 -            int underscoreIndex = variant.lastIndexOf('_');
 158.262 -            if (underscoreIndex != (-1)) {
 158.263 -                return new Locale(locale.getLanguage(), locale.getCountry(),
 158.264 -                                  variant.substring(0, underscoreIndex));
 158.265 -            } else {
 158.266 -                return new Locale(locale.getLanguage(), locale.getCountry());
 158.267 +    private static Locale getLookupLocale(Locale locale) {
 158.268 +        Locale lookupLocale = locale;
 158.269 +        Set<Character> extensions = locale.getExtensionKeys();
 158.270 +        if (!extensions.isEmpty()
 158.271 +                && !locale.equals(locale_ja_JP_JP)
 158.272 +                && !locale.equals(locale_th_TH_TH)) {
 158.273 +            // remove extensions
 158.274 +            Builder locbld = new Builder();
 158.275 +            try {
 158.276 +                locbld.setLocale(locale);
 158.277 +                locbld.clearExtensions();
 158.278 +                lookupLocale = locbld.build();
 158.279 +            } catch (IllformedLocaleException e) {
 158.280 +                // A Locale with non-empty extensions
 158.281 +                // should have well-formed fields except
 158.282 +                // for ja_JP_JP and th_TH_TH. Therefore,
 158.283 +                // it should never enter in this catch clause.
 158.284 +                config("A locale(" + locale + ") has non-empty extensions, but has illformed fields.");
 158.285 +
 158.286 +                // Fallback - script field will be lost.
 158.287 +                lookupLocale = new Locale(locale.getLanguage(), locale.getCountry(), locale.getVariant());
 158.288              }
 158.289 -        } else if (locale.getCountry() != "") {
 158.290 -            return new Locale(locale.getLanguage());
 158.291 -        } else if (locale.getLanguage() != "") {
 158.292 -            return Locale.ROOT;
 158.293 -        } else {
 158.294 -            return null;
 158.295          }
 158.296 +        return lookupLocale;
 158.297      }
 158.298  
 158.299      /**
   159.1 --- a/src/share/classes/sun/util/calendar/ZoneInfoFile.java	Thu Sep 23 17:33:40 2010 -0700
   159.2 +++ b/src/share/classes/sun/util/calendar/ZoneInfoFile.java	Fri Sep 24 16:41:32 2010 -0700
   159.3 @@ -30,6 +30,7 @@
   159.4  import  java.io.FileNotFoundException;
   159.5  import  java.io.IOException;
   159.6  import  java.lang.ref.SoftReference;
   159.7 +import  java.nio.file.FileSystems;
   159.8  import  java.security.AccessController;
   159.9  import  java.security.PrivilegedAction;
  159.10  import  java.security.PrivilegedActionException;
  159.11 @@ -472,17 +473,18 @@
  159.12  
  159.13      private static Map<String, ZoneInfo> zoneInfoObjects = null;
  159.14  
  159.15 -    private static final String ziDir;
  159.16 -    static {
  159.17 -        String zi = (String) AccessController.doPrivileged(
  159.18 -                         new sun.security.action.GetPropertyAction("java.home"))
  159.19 -                    + File.separator + "lib" + File.separator + "zi";
  159.20 -        try {
  159.21 -            zi = new File(zi).getCanonicalPath();
  159.22 -        } catch (Exception e) {
  159.23 -        }
  159.24 -        ziDir = zi;
  159.25 -    }
  159.26 +    private static final String ziDir = AccessController.doPrivileged(
  159.27 +        new PrivilegedAction<String>() {
  159.28 +            public String run() {
  159.29 +                String zi = System.getProperty("java.home") +
  159.30 +                    File.separator + "lib" + File.separator + "zi";
  159.31 +                try {
  159.32 +                    zi = FileSystems.getDefault().getPath(zi).toRealPath(true).toString();
  159.33 +                } catch(Exception e) {
  159.34 +                }
  159.35 +                return zi;
  159.36 +            }
  159.37 +        });
  159.38  
  159.39      /**
  159.40       * Converts the given time zone ID to a platform dependent path
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/src/share/classes/sun/util/locale/AsciiUtil.java	Fri Sep 24 16:41:32 2010 -0700
   160.3 @@ -0,0 +1,208 @@
   160.4 +/*
   160.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   160.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   160.7 + *
   160.8 + * This code is free software; you can redistribute it and/or modify it
   160.9 + * under the terms of the GNU General Public License version 2 only, as
  160.10 + * published by the Free Software Foundation.  Oracle designates this
  160.11 + * particular file as subject to the "Classpath" exception as provided
  160.12 + * by Oracle in the LICENSE file that accompanied this code.
  160.13 + *
  160.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  160.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  160.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  160.17 + * version 2 for more details (a copy is included in the LICENSE file that
  160.18 + * accompanied this code).
  160.19 + *
  160.20 + * You should have received a copy of the GNU General Public License version
  160.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  160.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  160.23 + *
  160.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  160.25 + * or visit www.oracle.com if you need additional information or have any
  160.26 + * questions.
  160.27 + */
  160.28 +
  160.29 +/*
  160.30 + *******************************************************************************
  160.31 + * Copyright (C) 2009, International Business Machines Corporation and         *
  160.32 + * others. All Rights Reserved.                                                *
  160.33 + *******************************************************************************
  160.34 + */
  160.35 +package sun.util.locale;
  160.36 +
  160.37 +public final class AsciiUtil {
  160.38 +    public static boolean caseIgnoreMatch(String s1, String s2) {
  160.39 +        if (s1 == s2) {
  160.40 +            return true;
  160.41 +        }
  160.42 +        int len = s1.length();
  160.43 +        if (len != s2.length()) {
  160.44 +            return false;
  160.45 +        }
  160.46 +        int i = 0;
  160.47 +        while (i < len) {
  160.48 +            char c1 = s1.charAt(i);
  160.49 +            char c2 = s2.charAt(i);
  160.50 +            if (c1 != c2 && toLower(c1) != toLower(c2)) {
  160.51 +                break;
  160.52 +            }
  160.53 +            i++;
  160.54 +        }
  160.55 +        return (i == len);
  160.56 +    }
  160.57 +
  160.58 +    public static int caseIgnoreCompare(String s1, String s2) {
  160.59 +        if (s1 == s2) {
  160.60 +            return 0;
  160.61 +        }
  160.62 +        return AsciiUtil.toLowerString(s1).compareTo(AsciiUtil.toLowerString(s2));
  160.63 +    }
  160.64 +
  160.65 +
  160.66 +    public static char toUpper(char c) {
  160.67 +        if (c >= 'a' && c <= 'z') {
  160.68 +            c -= 0x20;
  160.69 +        }
  160.70 +        return c;
  160.71 +    }
  160.72 +
  160.73 +    public static char toLower(char c) {
  160.74 +        if (c >= 'A' && c <= 'Z') {
  160.75 +            c += 0x20;
  160.76 +        }
  160.77 +        return c;
  160.78 +    }
  160.79 +
  160.80 +    public static String toLowerString(String s) {
  160.81 +        int idx = 0;
  160.82 +        for (; idx < s.length(); idx++) {
  160.83 +            char c = s.charAt(idx);
  160.84 +            if (c >= 'A' && c <= 'Z') {
  160.85 +                break;
  160.86 +            }
  160.87 +        }
  160.88 +        if (idx == s.length()) {
  160.89 +            return s;
  160.90 +        }
  160.91 +        StringBuilder buf = new StringBuilder(s.substring(0, idx));
  160.92 +        for (; idx < s.length(); idx++) {
  160.93 +            buf.append(toLower(s.charAt(idx)));
  160.94 +        }
  160.95 +        return buf.toString();
  160.96 +    }
  160.97 +
  160.98 +    public static String toUpperString(String s) {
  160.99 +        int idx = 0;
 160.100 +        for (; idx < s.length(); idx++) {
 160.101 +            char c = s.charAt(idx);
 160.102 +            if (c >= 'a' && c <= 'z') {
 160.103 +                break;
 160.104 +            }
 160.105 +        }
 160.106 +        if (idx == s.length()) {
 160.107 +            return s;
 160.108 +        }
 160.109 +        StringBuilder buf = new StringBuilder(s.substring(0, idx));
 160.110 +        for (; idx < s.length(); idx++) {
 160.111 +            buf.append(toUpper(s.charAt(idx)));
 160.112 +        }
 160.113 +        return buf.toString();
 160.114 +    }
 160.115 +
 160.116 +    public static String toTitleString(String s) {
 160.117 +        if (s.length() == 0) {
 160.118 +            return s;
 160.119 +        }
 160.120 +        int idx = 0;
 160.121 +        char c = s.charAt(idx);
 160.122 +        if (!(c >= 'a' && c <= 'z')) {
 160.123 +            for (idx = 1; idx < s.length(); idx++) {
 160.124 +                if (c >= 'A' && c <= 'Z') {
 160.125 +                    break;
 160.126 +                }
 160.127 +            }
 160.128 +        }
 160.129 +        if (idx == s.length()) {
 160.130 +            return s;
 160.131 +        }
 160.132 +        StringBuilder buf = new StringBuilder(s.substring(0, idx));
 160.133 +        if (idx == 0) {
 160.134 +            buf.append(toUpper(s.charAt(idx)));
 160.135 +            idx++;
 160.136 +        }
 160.137 +        for (; idx < s.length(); idx++) {
 160.138 +            buf.append(toLower(s.charAt(idx)));
 160.139 +        }
 160.140 +        return buf.toString();
 160.141 +    }
 160.142 +
 160.143 +    public static boolean isAlpha(char c) {
 160.144 +        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
 160.145 +    }
 160.146 +
 160.147 +    public static boolean isAlphaString(String s) {
 160.148 +        boolean b = true;
 160.149 +        for (int i = 0; i < s.length(); i++) {
 160.150 +            if (!isAlpha(s.charAt(i))) {
 160.151 +                b = false;
 160.152 +                break;
 160.153 +            }
 160.154 +        }
 160.155 +        return b;
 160.156 +    }
 160.157 +
 160.158 +    public static boolean isNumeric(char c) {
 160.159 +        return (c >= '0' && c <= '9');
 160.160 +    }
 160.161 +
 160.162 +    public static boolean isNumericString(String s) {
 160.163 +        boolean b = true;
 160.164 +        for (int i = 0; i < s.length(); i++) {
 160.165 +            if (!isNumeric(s.charAt(i))) {
 160.166 +                b = false;
 160.167 +                break;
 160.168 +            }
 160.169 +        }
 160.170 +        return b;
 160.171 +    }
 160.172 +
 160.173 +    public static boolean isAlphaNumeric(char c) {
 160.174 +        return isAlpha(c) || isNumeric(c);
 160.175 +    }
 160.176 +
 160.177 +    public static boolean isAlphaNumericString(String s) {
 160.178 +        boolean b = true;
 160.179 +        for (int i = 0; i < s.length(); i++) {
 160.180 +            if (!isAlphaNumeric(s.charAt(i))) {
 160.181 +                b = false;
 160.182 +                break;
 160.183 +            }
 160.184 +        }
 160.185 +        return b;
 160.186 +    }
 160.187 +
 160.188 +    public static class CaseInsensitiveKey {
 160.189 +        private String _key;
 160.190 +        private int _hash;
 160.191 +
 160.192 +        public CaseInsensitiveKey(String key) {
 160.193 +            _key = key;
 160.194 +            _hash = AsciiUtil.toLowerString(key).hashCode();
 160.195 +        }
 160.196 +
 160.197 +        public boolean equals(Object o) {
 160.198 +            if (this == o) {
 160.199 +                return true;
 160.200 +            }
 160.201 +            if (o instanceof CaseInsensitiveKey) {
 160.202 +                return AsciiUtil.caseIgnoreMatch(_key, ((CaseInsensitiveKey)o)._key);
 160.203 +            }
 160.204 +            return false;
 160.205 +        }
 160.206 +
 160.207 +        public int hashCode() {
 160.208 +            return _hash;
 160.209 +        }
 160.210 +    }
 160.211 +}
   161.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.2 +++ b/src/share/classes/sun/util/locale/BaseLocale.java	Fri Sep 24 16:41:32 2010 -0700
   161.3 @@ -0,0 +1,253 @@
   161.4 +/*
   161.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   161.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   161.7 + *
   161.8 + * This code is free software; you can redistribute it and/or modify it
   161.9 + * under the terms of the GNU General Public License version 2 only, as
  161.10 + * published by the Free Software Foundation.  Oracle designates this
  161.11 + * particular file as subject to the "Classpath" exception as provided
  161.12 + * by Oracle in the LICENSE file that accompanied this code.
  161.13 + *
  161.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  161.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  161.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  161.17 + * version 2 for more details (a copy is included in the LICENSE file that
  161.18 + * accompanied this code).
  161.19 + *
  161.20 + * You should have received a copy of the GNU General Public License version
  161.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  161.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  161.23 + *
  161.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  161.25 + * or visit www.oracle.com if you need additional information or have any
  161.26 + * questions.
  161.27 + */
  161.28 +
  161.29 +/*
  161.30 + *******************************************************************************
  161.31 + * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  161.32 + * others. All Rights Reserved.                                                *
  161.33 + *******************************************************************************
  161.34 + */
  161.35 +
  161.36 +package sun.util.locale;
  161.37 +
  161.38 +
  161.39 +public final class BaseLocale {
  161.40 +
  161.41 +    public static final String SEP = "_";
  161.42 +
  161.43 +    private static final Cache CACHE = new Cache();
  161.44 +    public static final BaseLocale ROOT = BaseLocale.getInstance("", "", "", "");
  161.45 +
  161.46 +    private String _language = "";
  161.47 +    private String _script = "";
  161.48 +    private String _region = "";
  161.49 +    private String _variant = "";
  161.50 +
  161.51 +    private transient volatile int _hash = 0;
  161.52 +
  161.53 +    private BaseLocale(String language, String script, String region, String variant) {
  161.54 +        if (language != null) {
  161.55 +            _language = AsciiUtil.toLowerString(language).intern();
  161.56 +        }
  161.57 +        if (script != null) {
  161.58 +            _script = AsciiUtil.toTitleString(script).intern();
  161.59 +        }
  161.60 +        if (region != null) {
  161.61 +            _region = AsciiUtil.toUpperString(region).intern();
  161.62 +        }
  161.63 +        if (variant != null) {
  161.64 +            _variant = variant.intern();
  161.65 +        }
  161.66 +    }
  161.67 +
  161.68 +    public static BaseLocale getInstance(String language, String script, String region, String variant) {
  161.69 +        // JDK uses deprecated ISO639.1 language codes for he, yi and id
  161.70 +        if (AsciiUtil.caseIgnoreMatch(language, "he")) {
  161.71 +            language = "iw";
  161.72 +        } else if (AsciiUtil.caseIgnoreMatch(language, "yi")) {
  161.73 +            language = "ji";
  161.74 +        } else if (AsciiUtil.caseIgnoreMatch(language, "id")) {
  161.75 +            language = "in";
  161.76 +        }
  161.77 +
  161.78 +        Key key = new Key(language, script, region, variant);
  161.79 +        BaseLocale baseLocale = CACHE.get(key);
  161.80 +        return baseLocale;
  161.81 +    }
  161.82 +
  161.83 +    public String getLanguage() {
  161.84 +        return _language;
  161.85 +    }
  161.86 +
  161.87 +    public String getScript() {
  161.88 +        return _script;
  161.89 +    }
  161.90 +
  161.91 +    public String getRegion() {
  161.92 +        return _region;
  161.93 +    }
  161.94 +
  161.95 +    public String getVariant() {
  161.96 +        return _variant;
  161.97 +    }
  161.98 +
  161.99 +    public boolean equals(Object obj) {
 161.100 +        if (this == obj) {
 161.101 +            return true;
 161.102 +        }
 161.103 +        if (!(obj instanceof BaseLocale)) {
 161.104 +            return false;
 161.105 +        }
 161.106 +        BaseLocale other = (BaseLocale)obj;
 161.107 +        return hashCode() == other.hashCode()
 161.108 +                && _language.equals(other._language)
 161.109 +                && _script.equals(other._script)
 161.110 +                && _region.equals(other._region)
 161.111 +                && _variant.equals(other._variant);
 161.112 +    }
 161.113 +
 161.114 +    public String toString() {
 161.115 +        StringBuilder buf = new StringBuilder();
 161.116 +        if (_language.length() > 0) {
 161.117 +            buf.append("language=");
 161.118 +            buf.append(_language);
 161.119 +        }
 161.120 +        if (_script.length() > 0) {
 161.121 +            if (buf.length() > 0) {
 161.122 +                buf.append(", ");
 161.123 +            }
 161.124 +            buf.append("script=");
 161.125 +            buf.append(_script);
 161.126 +        }
 161.127 +        if (_region.length() > 0) {
 161.128 +            if (buf.length() > 0) {
 161.129 +                buf.append(", ");
 161.130 +            }
 161.131 +            buf.append("region=");
 161.132 +            buf.append(_region);
 161.133 +        }
 161.134 +        if (_variant.length() > 0) {
 161.135 +            if (buf.length() > 0) {
 161.136 +                buf.append(", ");
 161.137 +            }
 161.138 +            buf.append("variant=");
 161.139 +            buf.append(_variant);
 161.140 +        }
 161.141 +        return buf.toString();
 161.142 +    }
 161.143 +
 161.144 +    public int hashCode() {
 161.145 +        int h = _hash;
 161.146 +        if (h == 0) {
 161.147 +            // Generating a hash value from language, script, region and variant
 161.148 +            for (int i = 0; i < _language.length(); i++) {
 161.149 +                h = 31*h + _language.charAt(i);
 161.150 +            }
 161.151 +            for (int i = 0; i < _script.length(); i++) {
 161.152 +                h = 31*h + _script.charAt(i);
 161.153 +            }
 161.154 +            for (int i = 0; i < _region.length(); i++) {
 161.155 +                h = 31*h + _region.charAt(i);
 161.156 +            }
 161.157 +            for (int i = 0; i < _variant.length(); i++) {
 161.158 +                h = 31*h + _variant.charAt(i);
 161.159 +            }
 161.160 +            _hash = h;
 161.161 +        }
 161.162 +        return h;
 161.163 +    }
 161.164 +
 161.165 +    private static class Key implements Comparable<Key> {
 161.166 +        private String _lang = "";
 161.167 +        private String _scrt = "";
 161.168 +        private String _regn = "";
 161.169 +        private String _vart = "";
 161.170 +
 161.171 +        private volatile int _hash; // Default to 0
 161.172 +
 161.173 +        public Key(String language, String script, String region, String variant) {
 161.174 +            if (language != null) {
 161.175 +                _lang = language;
 161.176 +            }
 161.177 +            if (script != null) {
 161.178 +                _scrt = script;
 161.179 +            }
 161.180 +            if (region != null) {
 161.181 +                _regn = region;
 161.182 +            }
 161.183 +            if (variant != null) {
 161.184 +                _vart = variant;
 161.185 +            }
 161.186 +        }
 161.187 +
 161.188 +        public boolean equals(Object obj) {
 161.189 +            return (this == obj) ||
 161.190 +                    (obj instanceof Key)
 161.191 +                    && AsciiUtil.caseIgnoreMatch(((Key)obj)._lang, this._lang)
 161.192 +                    && AsciiUtil.caseIgnoreMatch(((Key)obj)._scrt, this._scrt)
 161.193 +                    && AsciiUtil.caseIgnoreMatch(((Key)obj)._regn, this._regn)
 161.194 +                    && ((Key)obj)._vart.equals(_vart); // variant is case sensitive in JDK!
 161.195 +        }
 161.196 +
 161.197 +        public int compareTo(Key other) {
 161.198 +            int res = AsciiUtil.caseIgnoreCompare(this._lang, other._lang);
 161.199 +            if (res == 0) {
 161.200 +                res = AsciiUtil.caseIgnoreCompare(this._scrt, other._scrt);
 161.201 +                if (res == 0) {
 161.202 +                    res = AsciiUtil.caseIgnoreCompare(this._regn, other._regn);
 161.203 +                    if (res == 0) {
 161.204 +                        res = this._vart.compareTo(other._vart);
 161.205 +                    }
 161.206 +                }
 161.207 +            }
 161.208 +            return res;
 161.209 +        }
 161.210 +
 161.211 +        public int hashCode() {
 161.212 +            int h = _hash;
 161.213 +            if (h == 0) {
 161.214 +                // Generating a hash value from language, script, region and variant
 161.215 +                for (int i = 0; i < _lang.length(); i++) {
 161.216 +                    h = 31*h + AsciiUtil.toLower(_lang.charAt(i));
 161.217 +                }
 161.218 +                for (int i = 0; i < _scrt.length(); i++) {
 161.219 +                    h = 31*h + AsciiUtil.toLower(_scrt.charAt(i));
 161.220 +                }
 161.221 +                for (int i = 0; i < _regn.length(); i++) {
 161.222 +                    h = 31*h + AsciiUtil.toLower(_regn.charAt(i));
 161.223 +                }
 161.224 +                for (int i = 0; i < _vart.length(); i++) {
 161.225 +                    h = 31*h + _vart.charAt(i);
 161.226 +                }
 161.227 +                _hash = h;
 161.228 +            }
 161.229 +            return h;
 161.230 +        }
 161.231 +
 161.232 +        public static Key normalize(Key key) {
 161.233 +            String lang = AsciiUtil.toLowerString(key._lang).intern();
 161.234 +            String scrt = AsciiUtil.toTitleString(key._scrt).intern();
 161.235 +            String regn = AsciiUtil.toUpperString(key._regn).intern();
 161.236 +            String vart = key._vart.intern(); // preserve upper/lower cases
 161.237 +
 161.238 +            return new Key(lang, scrt, regn, vart);
 161.239 +        }
 161.240 +    }
 161.241 +
 161.242 +    private static class Cache extends LocaleObjectCache<Key, BaseLocale> {
 161.243 +
 161.244 +        public Cache() {
 161.245 +        }
 161.246 +
 161.247 +        protected Key normalizeKey(Key key) {
 161.248 +            return Key.normalize(key);
 161.249 +        }
 161.250 +
 161.251 +        protected BaseLocale createObject(Key key) {
 161.252 +            return new BaseLocale(key._lang, key._scrt, key._regn, key._vart);
 161.253 +        }
 161.254 +
 161.255 +    }
 161.256 +}
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/src/share/classes/sun/util/locale/Extension.java	Fri Sep 24 16:41:32 2010 -0700
   162.3 @@ -0,0 +1,63 @@
   162.4 +/*
   162.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   162.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   162.7 + *
   162.8 + * This code is free software; you can redistribute it and/or modify it
   162.9 + * under the terms of the GNU General Public License version 2 only, as
  162.10 + * published by the Free Software Foundation.  Oracle designates this
  162.11 + * particular file as subject to the "Classpath" exception as provided
  162.12 + * by Oracle in the LICENSE file that accompanied this code.
  162.13 + *
  162.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  162.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  162.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  162.17 + * version 2 for more details (a copy is included in the LICENSE file that
  162.18 + * accompanied this code).
  162.19 + *
  162.20 + * You should have received a copy of the GNU General Public License version
  162.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  162.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  162.23 + *
  162.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  162.25 + * or visit www.oracle.com if you need additional information or have any
  162.26 + * questions.
  162.27 + */
  162.28 +
  162.29 +/*
  162.30 + *******************************************************************************
  162.31 + * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  162.32 + * others. All Rights Reserved.                                                *
  162.33 + *******************************************************************************
  162.34 + */
  162.35 +package sun.util.locale;
  162.36 +
  162.37 +
  162.38 +public class Extension {
  162.39 +    private char _key;
  162.40 +    protected String _value;
  162.41 +
  162.42 +    protected Extension(char key) {
  162.43 +        _key = key;
  162.44 +    }
  162.45 +
  162.46 +    Extension(char key, String value) {
  162.47 +        _key = key;
  162.48 +        _value = value;
  162.49 +    }
  162.50 +
  162.51 +    public char getKey() {
  162.52 +        return _key;
  162.53 +    }
  162.54 +
  162.55 +    public String getValue() {
  162.56 +        return _value;
  162.57 +    }
  162.58 +
  162.59 +    public String getID() {
  162.60 +        return _key + LanguageTag.SEP + _value;
  162.61 +    }
  162.62 +
  162.63 +    public String toString() {
  162.64 +        return getID();
  162.65 +    }
  162.66 +}
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/src/share/classes/sun/util/locale/InternalLocaleBuilder.java	Fri Sep 24 16:41:32 2010 -0700
   163.3 @@ -0,0 +1,705 @@
   163.4 +/*
   163.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   163.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   163.7 + *
   163.8 + * This code is free software; you can redistribute it and/or modify it
   163.9 + * under the terms of the GNU General Public License version 2 only, as
  163.10 + * published by the Free Software Foundation.  Oracle designates this
  163.11 + * particular file as subject to the "Classpath" exception as provided
  163.12 + * by Oracle in the LICENSE file that accompanied this code.
  163.13 + *
  163.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  163.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  163.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  163.17 + * version 2 for more details (a copy is included in the LICENSE file that
  163.18 + * accompanied this code).
  163.19 + *
  163.20 + * You should have received a copy of the GNU General Public License version
  163.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  163.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  163.23 + *
  163.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  163.25 + * or visit www.oracle.com if you need additional information or have any
  163.26 + * questions.
  163.27 + */
  163.28 +
  163.29 +/*
  163.30 + *******************************************************************************
  163.31 + * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  163.32 + * others. All Rights Reserved.                                                *
  163.33 + *******************************************************************************
  163.34 + */
  163.35 +package sun.util.locale;
  163.36 +
  163.37 +import java.util.ArrayList;
  163.38 +import java.util.HashMap;
  163.39 +import java.util.HashSet;
  163.40 +import java.util.List;
  163.41 +import java.util.Set;
  163.42 +
  163.43 +public final class InternalLocaleBuilder {
  163.44 +
  163.45 +    private String _language = "";
  163.46 +    private String _script = "";
  163.47 +    private String _region = "";
  163.48 +    private String _variant = "";
  163.49 +
  163.50 +    private static final CaseInsensitiveChar PRIVUSE_KEY = new CaseInsensitiveChar(LanguageTag.PRIVATEUSE.charAt(0));
  163.51 +
  163.52 +    private HashMap<CaseInsensitiveChar, String> _extensions;
  163.53 +    private HashSet<CaseInsensitiveString> _uattributes;
  163.54 +    private HashMap<CaseInsensitiveString, String> _ukeywords;
  163.55 +
  163.56 +
  163.57 +    public InternalLocaleBuilder() {
  163.58 +    }
  163.59 +
  163.60 +    public InternalLocaleBuilder setLanguage(String language) throws LocaleSyntaxException {
  163.61 +        if (language == null || language.length() == 0) {
  163.62 +            _language = "";
  163.63 +        } else {
  163.64 +            if (!LanguageTag.isLanguage(language)) {
  163.65 +                throw new LocaleSyntaxException("Ill-formed language: " + language, 0);
  163.66 +            }
  163.67 +            _language = language;
  163.68 +        }
  163.69 +        return this;
  163.70 +    }
  163.71 +
  163.72 +    public InternalLocaleBuilder setScript(String script) throws LocaleSyntaxException {
  163.73 +        if (script == null || script.length() == 0) {
  163.74 +            _script = "";
  163.75 +        } else {
  163.76 +            if (!LanguageTag.isScript(script)) {
  163.77 +                throw new LocaleSyntaxException("Ill-formed script: " + script, 0);
  163.78 +            }
  163.79 +            _script = script;
  163.80 +        }
  163.81 +        return this;
  163.82 +    }
  163.83 +
  163.84 +    public InternalLocaleBuilder setRegion(String region) throws LocaleSyntaxException {
  163.85 +        if (region == null || region.length() == 0) {
  163.86 +            _region = "";
  163.87 +        } else {
  163.88 +            if (!LanguageTag.isRegion(region)) {
  163.89 +                throw new LocaleSyntaxException("Ill-formed region: " + region, 0);
  163.90 +            }
  163.91 +            _region = region;
  163.92 +        }
  163.93 +        return this;
  163.94 +    }
  163.95 +
  163.96 +    public InternalLocaleBuilder setVariant(String variant) throws LocaleSyntaxException {
  163.97 +        if (variant == null || variant.length() == 0) {
  163.98 +            _variant = "";
  163.99 +        } else {
 163.100 +            // normalize separators to "_"
 163.101 +            String var = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP);
 163.102 +            int errIdx = checkVariants(var, BaseLocale.SEP);
 163.103 +            if (errIdx != -1) {
 163.104 +                throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
 163.105 +            }
 163.106 +            _variant = var;
 163.107 +        }
 163.108 +        return this;
 163.109 +    }
 163.110 +
 163.111 +    public InternalLocaleBuilder addUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException {
 163.112 +        if (!UnicodeLocaleExtension.isAttribute(attribute)) {
 163.113 +            throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
 163.114 +        }
 163.115 +        // Use case insensitive string to prevent duplication
 163.116 +        if (_uattributes == null) {
 163.117 +            _uattributes = new HashSet<CaseInsensitiveString>(4);
 163.118 +        }
 163.119 +        _uattributes.add(new CaseInsensitiveString(attribute));
 163.120 +        return this;
 163.121 +    }
 163.122 +
 163.123 +    public InternalLocaleBuilder removeUnicodeLocaleAttribute(String attribute) throws LocaleSyntaxException {
 163.124 +        if (attribute == null || !UnicodeLocaleExtension.isAttribute(attribute)) {
 163.125 +            throw new LocaleSyntaxException("Ill-formed Unicode locale attribute: " + attribute);
 163.126 +        }
 163.127 +        if (_uattributes != null) {
 163.128 +            _uattributes.remove(new CaseInsensitiveString(attribute));
 163.129 +        }
 163.130 +        return this;
 163.131 +    }
 163.132 +
 163.133 +    public InternalLocaleBuilder setUnicodeLocaleKeyword(String key, String type) throws LocaleSyntaxException {
 163.134 +        if (!UnicodeLocaleExtension.isKey(key)) {
 163.135 +            throw new LocaleSyntaxException("Ill-formed Unicode locale keyword key: " + key);
 163.136 +        }
 163.137 +
 163.138 +        CaseInsensitiveString cikey = new CaseInsensitiveString(key);
 163.139 +        if (type == null) {
 163.140 +            if (_ukeywords != null) {
 163.141 +                // null type is used for remove the key
 163.142 +                _ukeywords.remove(cikey);
 163.143 +            }
 163.144 +        } else {
 163.145 +            if (type.length() != 0) {
 163.146 +                // normalize separator to "-"
 163.147 +                String tp = type.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
 163.148 +                // validate
 163.149 +                StringTokenIterator itr = new StringTokenIterator(tp, LanguageTag.SEP);
 163.150 +                while (!itr.isDone()) {
 163.151 +                    String s = itr.current();
 163.152 +                    if (!UnicodeLocaleExtension.isTypeSubtag(s)) {
 163.153 +                        throw new LocaleSyntaxException("Ill-formed Unicode locale keyword type: " + type, itr.currentStart());
 163.154 +                    }
 163.155 +                    itr.next();
 163.156 +                }
 163.157 +            }
 163.158 +            if (_ukeywords == null) {
 163.159 +                _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
 163.160 +            }
 163.161 +            _ukeywords.put(cikey, type);
 163.162 +        }
 163.163 +        return this;
 163.164 +    }
 163.165 +
 163.166 +    public InternalLocaleBuilder setExtension(char singleton, String value) throws LocaleSyntaxException {
 163.167 +        // validate key
 163.168 +        boolean isBcpPrivateuse = LanguageTag.isPrivateusePrefixChar(singleton);
 163.169 +        if (!isBcpPrivateuse && !LanguageTag.isExtensionSingletonChar(singleton)) {
 163.170 +            throw new LocaleSyntaxException("Ill-formed extension key: " + singleton);
 163.171 +        }
 163.172 +
 163.173 +        boolean remove = (value == null || value.length() == 0);
 163.174 +        CaseInsensitiveChar key = new CaseInsensitiveChar(singleton);
 163.175 +
 163.176 +        if (remove) {
 163.177 +            if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
 163.178 +                // clear entire Unicode locale extension
 163.179 +                if (_uattributes != null) {
 163.180 +                    _uattributes.clear();
 163.181 +                }
 163.182 +                if (_ukeywords != null) {
 163.183 +                    _ukeywords.clear();
 163.184 +                }
 163.185 +            } else {
 163.186 +                if (_extensions != null && _extensions.containsKey(key)) {
 163.187 +                    _extensions.remove(key);
 163.188 +                }
 163.189 +            }
 163.190 +        } else {
 163.191 +            // validate value
 163.192 +            String val = value.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
 163.193 +            StringTokenIterator itr = new StringTokenIterator(val, LanguageTag.SEP);
 163.194 +            while (!itr.isDone()) {
 163.195 +                String s = itr.current();
 163.196 +                boolean validSubtag;
 163.197 +                if (isBcpPrivateuse) {
 163.198 +                    validSubtag = LanguageTag.isPrivateuseSubtag(s);
 163.199 +                } else {
 163.200 +                    validSubtag = LanguageTag.isExtensionSubtag(s);
 163.201 +                }
 163.202 +                if (!validSubtag) {
 163.203 +                    throw new LocaleSyntaxException("Ill-formed extension value: " + s, itr.currentStart());
 163.204 +                }
 163.205 +                itr.next();
 163.206 +            }
 163.207 +
 163.208 +            if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
 163.209 +                setUnicodeLocaleExtension(val);
 163.210 +            } else {
 163.211 +                if (_extensions == null) {
 163.212 +                    _extensions = new HashMap<CaseInsensitiveChar, String>(4);
 163.213 +                }
 163.214 +                _extensions.put(key, val);
 163.215 +            }
 163.216 +        }
 163.217 +        return this;
 163.218 +    }
 163.219 +
 163.220 +    /*
 163.221 +     * Set extension/private subtags in a single string representation
 163.222 +     */
 163.223 +    public InternalLocaleBuilder setExtensions(String subtags) throws LocaleSyntaxException {
 163.224 +        if (subtags == null || subtags.length() == 0) {
 163.225 +            clearExtensions();
 163.226 +            return this;
 163.227 +        }
 163.228 +        subtags = subtags.replaceAll(BaseLocale.SEP, LanguageTag.SEP);
 163.229 +        StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
 163.230 +
 163.231 +        List<String> extensions = null;
 163.232 +        String privateuse = null;
 163.233 +
 163.234 +        int parsed = 0;
 163.235 +        int start;
 163.236 +
 163.237 +        // Make a list of extension subtags
 163.238 +        while (!itr.isDone()) {
 163.239 +            String s = itr.current();
 163.240 +            if (LanguageTag.isExtensionSingleton(s)) {
 163.241 +                start = itr.currentStart();
 163.242 +                String singleton = s;
 163.243 +                StringBuilder sb = new StringBuilder(singleton);
 163.244 +
 163.245 +                itr.next();
 163.246 +                while (!itr.isDone()) {
 163.247 +                    s = itr.current();
 163.248 +                    if (LanguageTag.isExtensionSubtag(s)) {
 163.249 +                        sb.append(LanguageTag.SEP).append(s);
 163.250 +                        parsed = itr.currentEnd();
 163.251 +                    } else {
 163.252 +                        break;
 163.253 +                    }
 163.254 +                    itr.next();
 163.255 +                }
 163.256 +
 163.257 +                if (parsed < start) {
 163.258 +                    throw new LocaleSyntaxException("Incomplete extension '" + singleton + "'", start);
 163.259 +                }
 163.260 +
 163.261 +                if (extensions == null) {
 163.262 +                    extensions = new ArrayList<String>(4);
 163.263 +                }
 163.264 +                extensions.add(sb.toString());
 163.265 +            } else {
 163.266 +                break;
 163.267 +            }
 163.268 +        }
 163.269 +        if (!itr.isDone()) {
 163.270 +            String s = itr.current();
 163.271 +            if (LanguageTag.isPrivateusePrefix(s)) {
 163.272 +                start = itr.currentStart();
 163.273 +                StringBuilder sb = new StringBuilder(s);
 163.274 +
 163.275 +                itr.next();
 163.276 +                while (!itr.isDone()) {
 163.277 +                    s = itr.current();
 163.278 +                    if (!LanguageTag.isPrivateuseSubtag(s)) {
 163.279 +                        break;
 163.280 +                    }
 163.281 +                    sb.append(LanguageTag.SEP).append(s);
 163.282 +                    parsed = itr.currentEnd();
 163.283 +
 163.284 +                    itr.next();
 163.285 +                }
 163.286 +                if (parsed <= start) {
 163.287 +                    throw new LocaleSyntaxException("Incomplete privateuse:" + subtags.substring(start), start);
 163.288 +                } else {
 163.289 +                    privateuse = sb.toString();
 163.290 +                }
 163.291 +            }
 163.292 +        }
 163.293 +
 163.294 +        if (!itr.isDone()) {
 163.295 +            throw new LocaleSyntaxException("Ill-formed extension subtags:" + subtags.substring(itr.currentStart()), itr.currentStart());
 163.296 +        }
 163.297 +
 163.298 +        return setExtensions(extensions, privateuse);
 163.299 +    }
 163.300 +
 163.301 +    /*
 163.302 +     * Set a list of BCP47 extensions and private use subtags
 163.303 +     * BCP47 extensions are already validated and well-formed, but may contain duplicates
 163.304 +     */
 163.305 +    private InternalLocaleBuilder setExtensions(List<String> bcpExtensions, String privateuse) {
 163.306 +        clearExtensions();
 163.307 +
 163.308 +        if (bcpExtensions != null && bcpExtensions.size() > 0) {
 163.309 +            HashSet<CaseInsensitiveChar> processedExntensions = new HashSet<CaseInsensitiveChar>(bcpExtensions.size());
 163.310 +            for (String bcpExt : bcpExtensions) {
 163.311 +                CaseInsensitiveChar key = new CaseInsensitiveChar(bcpExt.charAt(0));
 163.312 +                // ignore duplicates
 163.313 +                if (!processedExntensions.contains(key)) {
 163.314 +                    // each extension string contains singleton, e.g. "a-abc-def"
 163.315 +                    if (UnicodeLocaleExtension.isSingletonChar(key.value())) {
 163.316 +                        setUnicodeLocaleExtension(bcpExt.substring(2));
 163.317 +                    } else {
 163.318 +                        if (_extensions == null) {
 163.319 +                            _extensions = new HashMap<CaseInsensitiveChar, String>(4);
 163.320 +                        }
 163.321 +                        _extensions.put(key, bcpExt.substring(2));
 163.322 +                    }
 163.323 +                }
 163.324 +            }
 163.325 +        }
 163.326 +        if (privateuse != null && privateuse.length() > 0) {
 163.327 +            // privateuse string contains prefix, e.g. "x-abc-def"
 163.328 +            if (_extensions == null) {
 163.329 +                _extensions = new HashMap<CaseInsensitiveChar, String>(1);
 163.330 +            }
 163.331 +            _extensions.put(new CaseInsensitiveChar(privateuse.charAt(0)), privateuse.substring(2));
 163.332 +        }
 163.333 +
 163.334 +        return this;
 163.335 +    }
 163.336 +
 163.337 +    /*
 163.338 +     * Reset Builder's internal state with the given language tag
 163.339 +     */
 163.340 +    public InternalLocaleBuilder setLanguageTag(LanguageTag langtag) {
 163.341 +        clear();
 163.342 +        if (langtag.getExtlangs().size() > 0) {
 163.343 +            _language = langtag.getExtlangs().get(0);
 163.344 +        } else {
 163.345 +            String language = langtag.getLanguage();
 163.346 +            if (!language.equals(LanguageTag.UNDETERMINED)) {
 163.347 +                _language = language;
 163.348 +            }
 163.349 +        }
 163.350 +        _script = langtag.getScript();
 163.351 +        _region = langtag.getRegion();
 163.352 +
 163.353 +        List<String> bcpVariants = langtag.getVariants();
 163.354 +        if (bcpVariants.size() > 0) {
 163.355 +            StringBuilder var = new StringBuilder(bcpVariants.get(0));
 163.356 +            for (int i = 1; i < bcpVariants.size(); i++) {
 163.357 +                var.append(BaseLocale.SEP).append(bcpVariants.get(i));
 163.358 +            }
 163.359 +            _variant = var.toString();
 163.360 +        }
 163.361 +
 163.362 +        setExtensions(langtag.getExtensions(), langtag.getPrivateuse());
 163.363 +
 163.364 +        return this;
 163.365 +    }
 163.366 +
 163.367 +    public InternalLocaleBuilder setLocale(BaseLocale base, LocaleExtensions extensions) throws LocaleSyntaxException {
 163.368 +        String language = base.getLanguage();
 163.369 +        String script = base.getScript();
 163.370 +        String region = base.getRegion();
 163.371 +        String variant = base.getVariant();
 163.372 +
 163.373 +        // Special backward compatibility support
 163.374 +
 163.375 +        // Exception 1 - ja_JP_JP
 163.376 +        if (language.equals("ja") && region.equals("JP") && variant.equals("JP")) {
 163.377 +            // When locale ja_JP_JP is created, ca-japanese is always there.
 163.378 +            // The builder ignores the variant "JP"
 163.379 +            assert("japanese".equals(extensions.getUnicodeLocaleType("ca")));
 163.380 +            variant = "";
 163.381 +        }
 163.382 +        // Exception 2 - th_TH_TH
 163.383 +        else if (language.equals("th") && region.equals("TH") && variant.equals("TH")) {
 163.384 +            // When locale th_TH_TH is created, nu-thai is always there.
 163.385 +            // The builder ignores the variant "TH"
 163.386 +            assert("thai".equals(extensions.getUnicodeLocaleType("nu")));
 163.387 +            variant = "";
 163.388 +        }
 163.389 +        // Exception 3 - no_NO_NY
 163.390 +        else if (language.equals("no") && region.equals("NO") && variant.equals("NY")) {
 163.391 +            // no_NO_NY is a valid locale and used by Java 6 or older versions.
 163.392 +            // The build ignores the variant "NY" and change the language to "nn".
 163.393 +            language = "nn";
 163.394 +            variant = "";
 163.395 +        }
 163.396 +
 163.397 +        // Validate base locale fields before updating internal state.
 163.398 +        // LocaleExtensions always store validated/canonicalized values,
 163.399 +        // so no checks are necessary.
 163.400 +        if (language.length() > 0 && !LanguageTag.isLanguage(language)) {
 163.401 +            throw new LocaleSyntaxException("Ill-formed language: " + language);
 163.402 +        }
 163.403 +
 163.404 +        if (script.length() > 0 && !LanguageTag.isScript(script)) {
 163.405 +            throw new LocaleSyntaxException("Ill-formed script: " + script);
 163.406 +        }
 163.407 +
 163.408 +        if (region.length() > 0 && !LanguageTag.isRegion(region)) {
 163.409 +            throw new LocaleSyntaxException("Ill-formed region: " + region);
 163.410 +        }
 163.411 +
 163.412 +        if (variant.length() > 0) {
 163.413 +            int errIdx = checkVariants(variant, BaseLocale.SEP);
 163.414 +            if (errIdx != -1) {
 163.415 +                throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
 163.416 +            }
 163.417 +        }
 163.418 +
 163.419 +        // The input locale is validated at this point.
 163.420 +        // Now, updating builder's internal fields.
 163.421 +        _language = language;
 163.422 +        _script = script;
 163.423 +        _region = region;
 163.424 +        _variant = variant;
 163.425 +        clearExtensions();
 163.426 +
 163.427 +        Set<Character> extKeys = (extensions == null) ? null : extensions.getKeys();
 163.428 +        if (extKeys != null) {
 163.429 +            // map extensions back to builder's internal format
 163.430 +            for (Character key : extKeys) {
 163.431 +                Extension e = extensions.getExtension(key);
 163.432 +                if (e instanceof UnicodeLocaleExtension) {
 163.433 +                    UnicodeLocaleExtension ue = (UnicodeLocaleExtension)e;
 163.434 +                    for (String uatr : ue.getUnicodeLocaleAttributes()) {
 163.435 +                        if (_uattributes == null) {
 163.436 +                            _uattributes = new HashSet<CaseInsensitiveString>(4);
 163.437 +                        }
 163.438 +                        _uattributes.add(new CaseInsensitiveString(uatr));
 163.439 +                    }
 163.440 +                    for (String ukey : ue.getUnicodeLocaleKeys()) {
 163.441 +                        if (_ukeywords == null) {
 163.442 +                            _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
 163.443 +                        }
 163.444 +                        _ukeywords.put(new CaseInsensitiveString(ukey), ue.getUnicodeLocaleType(ukey));
 163.445 +                    }
 163.446 +                } else {
 163.447 +                    if (_extensions == null) {
 163.448 +                        _extensions = new HashMap<CaseInsensitiveChar, String>(4);
 163.449 +                    }
 163.450 +                    _extensions.put(new CaseInsensitiveChar(key.charValue()), e.getValue());
 163.451 +                }
 163.452 +            }
 163.453 +        }
 163.454 +        return this;
 163.455 +    }
 163.456 +
 163.457 +    public InternalLocaleBuilder clear() {
 163.458 +        _language = "";
 163.459 +        _script = "";
 163.460 +        _region = "";
 163.461 +        _variant = "";
 163.462 +        clearExtensions();
 163.463 +        return this;
 163.464 +    }
 163.465 +
 163.466 +    public InternalLocaleBuilder clearExtensions() {
 163.467 +        if (_extensions != null) {
 163.468 +            _extensions.clear();
 163.469 +        }
 163.470 +        if (_uattributes != null) {
 163.471 +            _uattributes.clear();
 163.472 +        }
 163.473 +        if (_ukeywords != null) {
 163.474 +            _ukeywords.clear();
 163.475 +        }
 163.476 +        return this;
 163.477 +    }
 163.478 +
 163.479 +    public BaseLocale getBaseLocale() {
 163.480 +        String language = _language;
 163.481 +        String script = _script;
 163.482 +        String region = _region;
 163.483 +        String variant = _variant;
 163.484 +
 163.485 +        // Special private use subtag sequence identified by "lvariant" will be
 163.486 +        // interpreted as Java variant.
 163.487 +        if (_extensions != null) {
 163.488 +            String privuse = _extensions.get(PRIVUSE_KEY);
 163.489 +            if (privuse != null) {
 163.490 +                StringTokenIterator itr = new StringTokenIterator(privuse, LanguageTag.SEP);
 163.491 +                boolean sawPrefix = false;
 163.492 +                int privVarStart = -1;
 163.493 +                while (!itr.isDone()) {
 163.494 +                    if (sawPrefix) {
 163.495 +                        privVarStart = itr.currentStart();
 163.496 +                        break;
 163.497 +                    }
 163.498 +                    if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
 163.499 +                        sawPrefix = true;
 163.500 +                    }
 163.501 +                    itr.next();
 163.502 +                }
 163.503 +                if (privVarStart != -1) {
 163.504 +                    StringBuilder sb = new StringBuilder(variant);
 163.505 +                    if (sb.length() != 0) {
 163.506 +                        sb.append(BaseLocale.SEP);
 163.507 +                    }
 163.508 +                    sb.append(privuse.substring(privVarStart).replaceAll(LanguageTag.SEP, BaseLocale.SEP));
 163.509 +                    variant = sb.toString();
 163.510 +                }
 163.511 +            }
 163.512 +        }
 163.513 +
 163.514 +        return BaseLocale.getInstance(language, script, region, variant);
 163.515 +    }
 163.516 +
 163.517 +    public LocaleExtensions getLocaleExtensions() {
 163.518 +        if ((_extensions == null || _extensions.size() == 0)
 163.519 +                && (_uattributes == null || _uattributes.size() == 0)
 163.520 +                && (_ukeywords == null || _ukeywords.size() == 0)) {
 163.521 +            return LocaleExtensions.EMPTY_EXTENSIONS;
 163.522 +        }
 163.523 +
 163.524 +        return new LocaleExtensions(_extensions, _uattributes, _ukeywords);
 163.525 +    }
 163.526 +
 163.527 +    /*
 163.528 +     * Remove special private use subtag sequence identified by "lvariant"
 163.529 +     * and return the rest. Only used by LocaleExtensions
 163.530 +     */
 163.531 +    static String removePrivateuseVariant(String privuseVal) {
 163.532 +        StringTokenIterator itr = new StringTokenIterator(privuseVal, LanguageTag.SEP);
 163.533 +
 163.534 +        // Note: privateuse value "abc-lvariant" is unchanged
 163.535 +        // because no subtags after "lvariant".
 163.536 +
 163.537 +        int prefixStart = -1;
 163.538 +        boolean sawPrivuseVar = false;
 163.539 +        while (!itr.isDone()) {
 163.540 +            if (prefixStart != -1) {
 163.541 +                // Note: privateuse value "abc-lvariant" is unchanged
 163.542 +                // because no subtags after "lvariant".
 163.543 +                sawPrivuseVar = true;
 163.544 +                break;
 163.545 +            }
 163.546 +            if (AsciiUtil.caseIgnoreMatch(itr.current(), LanguageTag.PRIVUSE_VARIANT_PREFIX)) {
 163.547 +                prefixStart = itr.currentStart();
 163.548 +            }
 163.549 +            itr.next();
 163.550 +        }
 163.551 +        if (!sawPrivuseVar) {
 163.552 +            return privuseVal;
 163.553 +        }
 163.554 +
 163.555 +        assert(prefixStart == 0 || prefixStart > 1);
 163.556 +        return (prefixStart == 0) ? null : privuseVal.substring(0, prefixStart -1);
 163.557 +    }
 163.558 +
 163.559 +    /*
 163.560 +     * Check if the given variant subtags separated by the given
 163.561 +     * separator(s) are valid
 163.562 +     */
 163.563 +    private int checkVariants(String variants, String sep) {
 163.564 +        StringTokenIterator itr = new StringTokenIterator(variants, sep);
 163.565 +        while (!itr.isDone()) {
 163.566 +            String s = itr.current();
 163.567 +            if (!LanguageTag.isVariant(s)) {
 163.568 +                return itr.currentStart();
 163.569 +            }
 163.570 +            itr.next();
 163.571 +        }
 163.572 +        return -1;
 163.573 +    }
 163.574 +
 163.575 +    /*
 163.576 +     * Private methods parsing Unicode Locale Extension subtags.
 163.577 +     * Duplicated attributes/keywords will be ignored.
 163.578 +     * The input must be a valid extension subtags (excluding singleton).
 163.579 +     */
 163.580 +    private void setUnicodeLocaleExtension(String subtags) {
 163.581 +        // wipe out existing attributes/keywords
 163.582 +        if (_uattributes != null) {
 163.583 +            _uattributes.clear();
 163.584 +        }
 163.585 +        if (_ukeywords != null) {
 163.586 +            _ukeywords.clear();
 163.587 +        }
 163.588 +
 163.589 +        StringTokenIterator itr = new StringTokenIterator(subtags, LanguageTag.SEP);
 163.590 +
 163.591 +        // parse attributes
 163.592 +        while (!itr.isDone()) {
 163.593 +            if (!UnicodeLocaleExtension.isAttribute(itr.current())) {
 163.594 +                break;
 163.595 +            }
 163.596 +            if (_uattributes == null) {
 163.597 +                _uattributes = new HashSet<CaseInsensitiveString>(4);
 163.598 +            }
 163.599 +            _uattributes.add(new CaseInsensitiveString(itr.current()));
 163.600 +            itr.next();
 163.601 +        }
 163.602 +
 163.603 +        // parse keywords
 163.604 +        CaseInsensitiveString key = null;
 163.605 +        String type;
 163.606 +        int typeStart = -1;
 163.607 +        int typeEnd = -1;
 163.608 +        while (!itr.isDone()) {
 163.609 +            if (key != null) {
 163.610 +                if (UnicodeLocaleExtension.isKey(itr.current())) {
 163.611 +                    // next keyword - emit previous one
 163.612 +                    assert(typeStart == -1 || typeEnd != -1);
 163.613 +                    type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
 163.614 +                    if (_ukeywords == null) {
 163.615 +                        _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
 163.616 +                    }
 163.617 +                    _ukeywords.put(key, type);
 163.618 +
 163.619 +                    // reset keyword info
 163.620 +                    CaseInsensitiveString tmpKey = new CaseInsensitiveString(itr.current());
 163.621 +                    key = _ukeywords.containsKey(tmpKey) ? null : tmpKey;
 163.622 +                    typeStart = typeEnd = -1;
 163.623 +                } else {
 163.624 +                    if (typeStart == -1) {
 163.625 +                        typeStart = itr.currentStart();
 163.626 +                    }
 163.627 +                    typeEnd = itr.currentEnd();
 163.628 +                }
 163.629 +            } else if (UnicodeLocaleExtension.isKey(itr.current())) {
 163.630 +                // 1. first keyword or
 163.631 +                // 2. next keyword, but previous one was duplicate
 163.632 +                key = new CaseInsensitiveString(itr.current());
 163.633 +                if (_ukeywords != null && _ukeywords.containsKey(key)) {
 163.634 +                    // duplicate
 163.635 +                    key = null;
 163.636 +                }
 163.637 +            }
 163.638 +
 163.639 +            if (!itr.hasNext()) {
 163.640 +                if (key != null) {
 163.641 +                    // last keyword
 163.642 +                    assert(typeStart == -1 || typeEnd != -1);
 163.643 +                    type = (typeStart == -1) ? "" : subtags.substring(typeStart, typeEnd);
 163.644 +                    if (_ukeywords == null) {
 163.645 +                        _ukeywords = new HashMap<CaseInsensitiveString, String>(4);
 163.646 +                    }
 163.647 +                    _ukeywords.put(key, type);
 163.648 +                }
 163.649 +                break;
 163.650 +            }
 163.651 +
 163.652 +            itr.next();
 163.653 +        }
 163.654 +    }
 163.655 +
 163.656 +    static class CaseInsensitiveString {
 163.657 +        private String _s;
 163.658 +
 163.659 +        CaseInsensitiveString(String s) {
 163.660 +            _s = s;
 163.661 +        }
 163.662 +
 163.663 +        public String value() {
 163.664 +            return _s;
 163.665 +        }
 163.666 +
 163.667 +        public int hashCode() {
 163.668 +            return AsciiUtil.toLowerString(_s).hashCode();
 163.669 +        }
 163.670 +
 163.671 +        public boolean equals(Object obj) {
 163.672 +            if (this == obj) {
 163.673 +                return true;
 163.674 +            }
 163.675 +            if (!(obj instanceof CaseInsensitiveString)) {
 163.676 +                return false;
 163.677 +            }
 163.678 +            return AsciiUtil.caseIgnoreMatch(_s, ((CaseInsensitiveString)obj).value());
 163.679 +        }
 163.680 +    }
 163.681 +
 163.682 +    static class CaseInsensitiveChar {
 163.683 +        private char _c;
 163.684 +
 163.685 +        CaseInsensitiveChar(char c) {
 163.686 +            _c = c;
 163.687 +        }
 163.688 +
 163.689 +        public char value() {
 163.690 +            return _c;
 163.691 +        }
 163.692 +
 163.693 +        public int hashCode() {
 163.694 +            return AsciiUtil.toLower(_c);
 163.695 +        }
 163.696 +
 163.697 +        public boolean equals(Object obj) {
 163.698 +            if (this == obj) {
 163.699 +                return true;
 163.700 +            }
 163.701 +            if (!(obj instanceof CaseInsensitiveChar)) {
 163.702 +                return false;
 163.703 +            }
 163.704 +            return _c ==  AsciiUtil.toLower(((CaseInsensitiveChar)obj).value());
 163.705 +        }
 163.706 +
 163.707 +    }
 163.708 +}
   164.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.2 +++ b/src/share/classes/sun/util/locale/LanguageTag.java	Fri Sep 24 16:41:32 2010 -0700
   164.3 @@ -0,0 +1,726 @@
   164.4 +/*
   164.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   164.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   164.7 + *
   164.8 + * This code is free software; you can redistribute it and/or modify it
   164.9 + * under the terms of the GNU General Public License version 2 only, as
  164.10 + * published by the Free Software Foundation.  Oracle designates this
  164.11 + * particular file as subject to the "Classpath" exception as provided
  164.12 + * by Oracle in the LICENSE file that accompanied this code.
  164.13 + *
  164.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  164.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  164.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  164.17 + * version 2 for more details (a copy is included in the LICENSE file that
  164.18 + * accompanied this code).
  164.19 + *
  164.20 + * You should have received a copy of the GNU General Public License version
  164.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  164.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  164.23 + *
  164.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  164.25 + * or visit www.oracle.com if you need additional information or have any
  164.26 + * questions.
  164.27 + */
  164.28 +
  164.29 +/*
  164.30 + *******************************************************************************
  164.31 + * Copyright (C) 2010, International Business Machines Corporation and         *
  164.32 + * others. All Rights Reserved.                                                *
  164.33 + *******************************************************************************
  164.34 + */
  164.35 +package sun.util.locale;
  164.36 +
  164.37 +import java.util.ArrayList;
  164.38 +import java.util.Collections;
  164.39 +import java.util.HashMap;
  164.40 +import java.util.List;
  164.41 +import java.util.Map;
  164.42 +import java.util.Set;
  164.43 +
  164.44 +public class LanguageTag {
  164.45 +    //
  164.46 +    // static fields
  164.47 +    //
  164.48 +    public static final String SEP = "-";
  164.49 +    public static final String PRIVATEUSE = "x";
  164.50 +    public static String UNDETERMINED = "und";
  164.51 +    public static final String PRIVUSE_VARIANT_PREFIX = "lvariant";
  164.52 +
  164.53 +    //
  164.54 +    // Language subtag fields
  164.55 +    //
  164.56 +    private String _language = "";      // language subtag
  164.57 +    private String _script = "";        // script subtag
  164.58 +    private String _region = "";        // region subtag
  164.59 +    private String _privateuse = "";    // privateuse
  164.60 +
  164.61 +    private List<String> _extlangs = Collections.emptyList();   // extlang subtags
  164.62 +    private List<String> _variants = Collections.emptyList();   // variant subtags
  164.63 +    private List<String> _extensions = Collections.emptyList(); // extensions
  164.64 +
  164.65 +    // Map contains grandfathered tags and its preferred mappings from
  164.66 +    // http://www.ietf.org/rfc/rfc5646.txt
  164.67 +    private static final Map<AsciiUtil.CaseInsensitiveKey, String[]> GRANDFATHERED =
  164.68 +        new HashMap<AsciiUtil.CaseInsensitiveKey, String[]>();
  164.69 +
  164.70 +    static {
  164.71 +        // grandfathered = irregular           ; non-redundant tags registered
  164.72 +        //               / regular             ; during the RFC 3066 era
  164.73 +        //
  164.74 +        // irregular     = "en-GB-oed"         ; irregular tags do not match
  164.75 +        //               / "i-ami"             ; the 'langtag' production and
  164.76 +        //               / "i-bnn"             ; would not otherwise be
  164.77 +        //               / "i-default"         ; considered 'well-formed'
  164.78 +        //               / "i-enochian"        ; These tags are all valid,
  164.79 +        //               / "i-hak"             ; but most are deprecated
  164.80 +        //               / "i-klingon"         ; in favor of more modern
  164.81 +        //               / "i-lux"             ; subtags or subtag
  164.82 +        //               / "i-mingo"           ; combination
  164.83 +        //               / "i-navajo"
  164.84 +        //               / "i-pwn"
  164.85 +        //               / "i-tao"
  164.86 +        //               / "i-tay"
  164.87 +        //               / "i-tsu"
  164.88 +        //               / "sgn-BE-FR"
  164.89 +        //               / "sgn-BE-NL"
  164.90 +        //               / "sgn-CH-DE"
  164.91 +        //
  164.92 +        // regular       = "art-lojban"        ; these tags match the 'langtag'
  164.93 +        //               / "cel-gaulish"       ; production, but their subtags
  164.94 +        //               / "no-bok"            ; are not extended language
  164.95 +        //               / "no-nyn"            ; or variant subtags: their meaning
  164.96 +        //               / "zh-guoyu"          ; is defined by their registration
  164.97 +        //               / "zh-hakka"          ; and all of these are deprecated
  164.98 +        //               / "zh-min"            ; in favor of a more modern
  164.99 +        //               / "zh-min-nan"        ; subtag or sequence of subtags
 164.100 +        //               / "zh-xiang"
 164.101 +
 164.102 +        final String[][] entries = {
 164.103 +          //{"tag",         "preferred"},
 164.104 +            {"art-lojban",  "jbo"},
 164.105 +            {"cel-gaulish", "xtg-x-cel-gaulish"},   // fallback
 164.106 +            {"en-GB-oed",   "en-GB-x-oed"},         // fallback
 164.107 +            {"i-ami",       "ami"},
 164.108 +            {"i-bnn",       "bnn"},
 164.109 +            {"i-default",   "en-x-i-default"},      // fallback
 164.110 +            {"i-enochian",  "und-x-i-enochian"},    // fallback
 164.111 +            {"i-hak",       "hak"},
 164.112 +            {"i-klingon",   "tlh"},
 164.113 +            {"i-lux",       "lb"},
 164.114 +            {"i-mingo",     "see-x-i-mingo"},       // fallback
 164.115 +            {"i-navajo",    "nv"},
 164.116 +            {"i-pwn",       "pwn"},
 164.117 +            {"i-tao",       "tao"},
 164.118 +            {"i-tay",       "tay"},
 164.119 +            {"i-tsu",       "tsu"},
 164.120 +            {"no-bok",      "nb"},
 164.121 +            {"no-nyn",      "nn"},
 164.122 +            {"sgn-BE-FR",   "sfb"},
 164.123 +            {"sgn-BE-NL",   "vgt"},
 164.124 +            {"sgn-CH-DE",   "sgg"},
 164.125 +            {"zh-guoyu",    "cmn"},
 164.126 +            {"zh-hakka",    "hak"},
 164.127 +            {"zh-min",      "nan-x-zh-min"},        // fallback
 164.128 +            {"zh-min-nan",  "nan"},
 164.129 +            {"zh-xiang",    "hsn"},
 164.130 +        };
 164.131 +        for (String[] e : entries) {
 164.132 +            GRANDFATHERED.put(new AsciiUtil.CaseInsensitiveKey(e[0]), e);
 164.133 +        }
 164.134 +    }
 164.135 +
 164.136 +    private LanguageTag() {
 164.137 +    }
 164.138 +
 164.139 +    /*
 164.140 +     * BNF in RFC5464
 164.141 +     *
 164.142 +     * Language-Tag  = langtag             ; normal language tags
 164.143 +     *               / privateuse          ; private use tag
 164.144 +     *               / grandfathered       ; grandfathered tags
 164.145 +     *
 164.146 +     *
 164.147 +     * langtag       = language
 164.148 +     *                 ["-" script]
 164.149 +     *                 ["-" region]
 164.150 +     *                 *("-" variant)
 164.151 +     *                 *("-" extension)
 164.152 +     *                 ["-" privateuse]
 164.153 +     *
 164.154 +     * language      = 2*3ALPHA            ; shortest ISO 639 code
 164.155 +     *                 ["-" extlang]       ; sometimes followed by
 164.156 +     *                                     ; extended language subtags
 164.157 +     *               / 4ALPHA              ; or reserved for future use
 164.158 +     *               / 5*8ALPHA            ; or registered language subtag
 164.159 +     *
 164.160 +     * extlang       = 3ALPHA              ; selected ISO 639 codes
 164.161 +     *                 *2("-" 3ALPHA)      ; permanently reserved
 164.162 +     *
 164.163 +     * script        = 4ALPHA              ; ISO 15924 code
 164.164 +     *
 164.165 +     * region        = 2ALPHA              ; ISO 3166-1 code
 164.166 +     *               / 3DIGIT              ; UN M.49 code
 164.167 +     *
 164.168 +     * variant       = 5*8alphanum         ; registered variants
 164.169 +     *               / (DIGIT 3alphanum)
 164.170 +     *
 164.171 +     * extension     = singleton 1*("-" (2*8alphanum))
 164.172 +     *
 164.173 +     *                                     ; Single alphanumerics
 164.174 +     *                                     ; "x" reserved for private use
 164.175 +     * singleton     = DIGIT               ; 0 - 9
 164.176 +     *               / %x41-57             ; A - W
 164.177 +     *               / %x59-5A             ; Y - Z
 164.178 +     *               / %x61-77             ; a - w
 164.179 +     *               / %x79-7A             ; y - z
 164.180 +     *
 164.181 +     * privateuse    = "x" 1*("-" (1*8alphanum))
 164.182 +     *
 164.183 +     */
 164.184 +    public static LanguageTag parse(String languageTag, ParseStatus sts) {
 164.185 +        if (sts == null) {
 164.186 +            sts = new ParseStatus();
 164.187 +        } else {
 164.188 +            sts.reset();
 164.189 +        }
 164.190 +
 164.191 +        StringTokenIterator itr;
 164.192 +
 164.193 +        // Check if the tag is grandfathered
 164.194 +        String[] gfmap = GRANDFATHERED.get(new AsciiUtil.CaseInsensitiveKey(languageTag));
 164.195 +        if (gfmap != null) {
 164.196 +            // use preferred mapping
 164.197 +            itr = new StringTokenIterator(gfmap[1], SEP);
 164.198 +        } else {
 164.199 +            itr = new StringTokenIterator(languageTag, SEP);
 164.200 +        }
 164.201 +
 164.202 +        LanguageTag tag = new LanguageTag();
 164.203 +
 164.204 +        // langtag must start with either language or privateuse
 164.205 +        if (tag.parseLanguage(itr, sts)) {
 164.206 +            tag.parseExtlangs(itr, sts);
 164.207 +            tag.parseScript(itr, sts);
 164.208 +            tag.parseRegion(itr, sts);
 164.209 +            tag.parseVariants(itr, sts);
 164.210 +            tag.parseExtensions(itr, sts);
 164.211 +        }
 164.212 +        tag.parsePrivateuse(itr, sts);
 164.213 +
 164.214 +        if (!itr.isDone() && !sts.isError()) {
 164.215 +            String s = itr.current();
 164.216 +            sts._errorIndex = itr.currentStart();
 164.217 +            if (s.length() == 0) {
 164.218 +                sts._errorMsg = "Empty subtag";
 164.219 +            } else {
 164.220 +                sts._errorMsg = "Invalid subtag: " + s;
 164.221 +            }
 164.222 +        }
 164.223 +
 164.224 +        return tag;
 164.225 +    }
 164.226 +
 164.227 +    //
 164.228 +    // Language subtag parsers
 164.229 +    //
 164.230 +
 164.231 +    private boolean parseLanguage(StringTokenIterator itr, ParseStatus sts) {
 164.232 +        if (itr.isDone() || sts.isError()) {
 164.233 +            return false;
 164.234 +        }
 164.235 +
 164.236 +        boolean found = false;
 164.237 +
 164.238 +        String s = itr.current();
 164.239 +        if (isLanguage(s)) {
 164.240 +            found = true;
 164.241 +            _language = s;
 164.242 +            sts._parseLength = itr.currentEnd();
 164.243 +            itr.next();
 164.244 +        }
 164.245 +
 164.246 +        return found;
 164.247 +    }
 164.248 +
 164.249 +    private boolean parseExtlangs(StringTokenIterator itr, ParseStatus sts) {
 164.250 +        if (itr.isDone() || sts.isError()) {
 164.251 +            return false;
 164.252 +        }
 164.253 +
 164.254 +        boolean found = false;
 164.255 +
 164.256 +        while (!itr.isDone()) {
 164.257 +            String s = itr.current();
 164.258 +            if (!isExtlang(s)) {
 164.259 +                break;
 164.260 +            }
 164.261 +            found = true;
 164.262 +            if (_extlangs.isEmpty()) {
 164.263 +                _extlangs = new ArrayList<String>(3);
 164.264 +            }
 164.265 +            _extlangs.add(s);
 164.266 +            sts._parseLength = itr.currentEnd();
 164.267 +            itr.next();
 164.268 +
 164.269 +            if (_extlangs.size() == 3) {
 164.270 +                // Maximum 3 extlangs
 164.271 +                break;
 164.272 +            }
 164.273 +        }
 164.274 +
 164.275 +        return found;
 164.276 +    }
 164.277 +
 164.278 +    private boolean parseScript(StringTokenIterator itr, ParseStatus sts) {
 164.279 +        if (itr.isDone() || sts.isError()) {
 164.280 +            return false;
 164.281 +        }
 164.282 +
 164.283 +        boolean found = false;
 164.284 +
 164.285 +        String s = itr.current();
 164.286 +        if (isScript(s)) {
 164.287 +            found = true;
 164.288 +            _script = s;
 164.289 +            sts._parseLength = itr.currentEnd();
 164.290 +            itr.next();
 164.291 +        }
 164.292 +
 164.293 +        return found;
 164.294 +    }
 164.295 +
 164.296 +    private boolean parseRegion(StringTokenIterator itr, ParseStatus sts) {
 164.297 +        if (itr.isDone() || sts.isError()) {
 164.298 +            return false;
 164.299 +        }
 164.300 +
 164.301 +        boolean found = false;
 164.302 +
 164.303 +        String s = itr.current();
 164.304 +        if (isRegion(s)) {
 164.305 +            found = true;
 164.306 +            _region = s;
 164.307 +            sts._parseLength = itr.currentEnd();
 164.308 +            itr.next();
 164.309 +        }
 164.310 +
 164.311 +        return found;
 164.312 +    }
 164.313 +
 164.314 +    private boolean parseVariants(StringTokenIterator itr, ParseStatus sts) {
 164.315 +        if (itr.isDone() || sts.isError()) {
 164.316 +            return false;
 164.317 +        }
 164.318 +
 164.319 +        boolean found = false;
 164.320 +
 164.321 +        while (!itr.isDone()) {
 164.322 +            String s = itr.current();
 164.323 +            if (!isVariant(s)) {
 164.324 +                break;
 164.325 +            }
 164.326 +            found = true;
 164.327 +            if (_variants.isEmpty()) {
 164.328 +                _variants = new ArrayList<String>(3);
 164.329 +            }
 164.330 +            _variants.add(s);
 164.331 +            sts._parseLength = itr.currentEnd();
 164.332 +            itr.next();
 164.333 +        }
 164.334 +
 164.335 +        return found;
 164.336 +    }
 164.337 +
 164.338 +    private boolean parseExtensions(StringTokenIterator itr, ParseStatus sts) {
 164.339 +        if (itr.isDone() || sts.isError()) {
 164.340 +            return false;
 164.341 +        }
 164.342 +
 164.343 +        boolean found = false;
 164.344 +
 164.345 +        while (!itr.isDone()) {
 164.346 +            String s = itr.current();
 164.347 +            if (isExtensionSingleton(s)) {
 164.348 +                int start = itr.currentStart();
 164.349 +                String singleton = s;
 164.350 +                StringBuilder sb = new StringBuilder(singleton);
 164.351 +
 164.352 +                itr.next();
 164.353 +                while (!itr.isDone()) {
 164.354 +                    s = itr.current();
 164.355 +                    if (isExtensionSubtag(s)) {
 164.356 +                        sb.append(SEP).append(s);
 164.357 +                        sts._parseLength = itr.currentEnd();
 164.358 +                    } else {
 164.359 +                        break;
 164.360 +                    }
 164.361 +                    itr.next();
 164.362 +                }
 164.363 +
 164.364 +                if (sts._parseLength <= start) {
 164.365 +                    sts._errorIndex = start;
 164.366 +                    sts._errorMsg = "Incomplete extension '" + singleton + "'";
 164.367 +                    break;
 164.368 +                }
 164.369 +
 164.370 +                if (_extensions.size() == 0) {
 164.371 +                    _extensions = new ArrayList<String>(4);
 164.372 +                }
 164.373 +                _extensions.add(sb.toString());
 164.374 +                found = true;
 164.375 +            } else {
 164.376 +                break;
 164.377 +            }
 164.378 +        }
 164.379 +        return found;
 164.380 +    }
 164.381 +
 164.382 +    private boolean parsePrivateuse(StringTokenIterator itr, ParseStatus sts) {
 164.383 +        if (itr.isDone() || sts.isError()) {
 164.384 +            return false;
 164.385 +        }
 164.386 +
 164.387 +        boolean found = false;
 164.388 +
 164.389 +        String s = itr.current();
 164.390 +        if (isPrivateusePrefix(s)) {
 164.391 +            int start = itr.currentStart();
 164.392 +            StringBuilder sb = new StringBuilder(s);
 164.393 +
 164.394 +            itr.next();
 164.395 +            while (!itr.isDone()) {
 164.396 +                s = itr.current();
 164.397 +                if (!isPrivateuseSubtag(s)) {
 164.398 +                    break;
 164.399 +                }
 164.400 +                sb.append(SEP).append(s);
 164.401 +                sts._parseLength = itr.currentEnd();
 164.402 +
 164.403 +                itr.next();
 164.404 +            }
 164.405 +
 164.406 +            if (sts._parseLength <= start) {
 164.407 +                // need at least 1 private subtag
 164.408 +                sts._errorIndex = start;
 164.409 +                sts._errorMsg = "Incomplete privateuse";
 164.410 +            } else {
 164.411 +                _privateuse = sb.toString();
 164.412 +                found = true;
 164.413 +            }
 164.414 +        }
 164.415 +
 164.416 +        return found;
 164.417 +    }
 164.418 +
 164.419 +    public static LanguageTag parseLocale(BaseLocale baseLocale, LocaleExtensions localeExtensions) {
 164.420 +        LanguageTag tag = new LanguageTag();
 164.421 +
 164.422 +        String language = baseLocale.getLanguage();
 164.423 +        String script = baseLocale.getScript();
 164.424 +        String region = baseLocale.getRegion();
 164.425 +        String variant = baseLocale.getVariant();
 164.426 +
 164.427 +        String privuseVar = null;   // store ill-formed variant subtags
 164.428 +
 164.429 +        if (language.length() == 0 || !isLanguage(language)) {
 164.430 +            tag._language = UNDETERMINED;
 164.431 +        } else {
 164.432 +            // Convert a deprecated language code used by Java to
 164.433 +            // a new code
 164.434 +            if (language.equals("iw")) {
 164.435 +                language = "he";
 164.436 +            } else if (language.equals("ji")) {
 164.437 +                language = "yi";
 164.438 +            } else if (language.equals("in")) {
 164.439 +                language = "id";
 164.440 +            }
 164.441 +            tag._language = language;
 164.442 +        }
 164.443 +
 164.444 +        if (script.length() > 0 && isScript(script)) {
 164.445 +            tag._script = canonicalizeScript(script);
 164.446 +        }
 164.447 +
 164.448 +        if (region.length() > 0 && isRegion(region)) {
 164.449 +            tag._region = canonicalizeRegion(region);
 164.450 +        }
 164.451 +
 164.452 +        // Special handling for no_NO_NY - use nn_NO for language tag
 164.453 +        if (tag._language.equals("no") && tag._region.equals("NO") && variant.equals("NY")) {
 164.454 +            tag._language = "nn";
 164.455 +            variant = "";
 164.456 +        }
 164.457 +
 164.458 +        if (variant.length() > 0) {
 164.459 +            List<String> variants = null;
 164.460 +            StringTokenIterator varitr = new StringTokenIterator(variant, BaseLocale.SEP);
 164.461 +            while (!varitr.isDone()) {
 164.462 +                String var = varitr.current();
 164.463 +                if (!isVariant(var)) {
 164.464 +                    break;
 164.465 +                }
 164.466 +                if (variants == null) {
 164.467 +                    variants = new ArrayList<String>();
 164.468 +                }
 164.469 +                variants.add(var);  // Do not canonicalize!
 164.470 +                varitr.next();
 164.471 +            }
 164.472 +            if (variants != null) {
 164.473 +                tag._variants = variants;
 164.474 +            }
 164.475 +            if (!varitr.isDone()) {
 164.476 +                // ill-formed variant subtags
 164.477 +                StringBuilder buf = new StringBuilder();
 164.478 +                while (!varitr.isDone()) {
 164.479 +                    String prvv = varitr.current();
 164.480 +                    if (!isPrivateuseSubtag(prvv)) {
 164.481 +                        // cannot use private use subtag - truncated
 164.482 +                        break;
 164.483 +                    }
 164.484 +                    if (buf.length() > 0) {
 164.485 +                        buf.append(SEP);
 164.486 +                    }
 164.487 +                    buf.append(prvv);
 164.488 +                    varitr.next();
 164.489 +                }
 164.490 +                if (buf.length() > 0) {
 164.491 +                    privuseVar = buf.toString();
 164.492 +                }
 164.493 +            }
 164.494 +        }
 164.495 +
 164.496 +        List<String> extensions = null;
 164.497 +        String privateuse = null;
 164.498 +
 164.499 +        Set<Character> locextKeys = localeExtensions.getKeys();
 164.500 +        for (Character locextKey : locextKeys) {
 164.501 +            Extension ext = localeExtensions.getExtension(locextKey);
 164.502 +            if (isPrivateusePrefixChar(locextKey.charValue())) {
 164.503 +                privateuse = ext.getValue();
 164.504 +            } else {
 164.505 +                if (extensions == null) {
 164.506 +                    extensions = new ArrayList<String>();
 164.507 +                }
 164.508 +                extensions.add(locextKey.toString() + SEP + ext.getValue());
 164.509 +            }
 164.510 +        }
 164.511 +
 164.512 +        if (extensions != null) {
 164.513 +            tag._extensions = extensions;
 164.514 +        }
 164.515 +
 164.516 +        // append ill-formed variant subtags to private use
 164.517 +        if (privuseVar != null) {
 164.518 +            if (privateuse == null) {
 164.519 +                privateuse = PRIVUSE_VARIANT_PREFIX + SEP + privuseVar;
 164.520 +            } else {
 164.521 +                privateuse = privateuse + SEP + PRIVUSE_VARIANT_PREFIX + SEP + privuseVar.replace(BaseLocale.SEP, SEP);
 164.522 +            }
 164.523 +        }
 164.524 +
 164.525 +        if (privateuse != null) {
 164.526 +            tag._privateuse = privateuse;
 164.527 +        } else if (tag._language.length() == 0) {
 164.528 +            // use "und" if neither language nor privateuse is available
 164.529 +            tag._language = UNDETERMINED;
 164.530 +        }
 164.531 +
 164.532 +        return tag;
 164.533 +    }
 164.534 +
 164.535 +    //
 164.536 +    // Getter methods for language subtag fields
 164.537 +    //
 164.538 +
 164.539 +    public String getLanguage() {
 164.540 +        return _language;
 164.541 +    }
 164.542 +
 164.543 +    public List<String> getExtlangs() {
 164.544 +        return Collections.unmodifiableList(_extlangs);
 164.545 +    }
 164.546 +
 164.547 +    public String getScript() {
 164.548 +        return _script;
 164.549 +    }
 164.550 +
 164.551 +    public String getRegion() {
 164.552 +        return _region;
 164.553 +    }
 164.554 +
 164.555 +    public List<String> getVariants() {
 164.556 +        return Collections.unmodifiableList(_variants);
 164.557 +    }
 164.558 +
 164.559 +    public List<String> getExtensions() {
 164.560 +        return Collections.unmodifiableList(_extensions);
 164.561 +    }
 164.562 +
 164.563 +    public String getPrivateuse() {
 164.564 +        return _privateuse;
 164.565 +    }
 164.566 +
 164.567 +    //
 164.568 +    // Language subtag syntax checking methods
 164.569 +    //
 164.570 +
 164.571 +    public static boolean isLanguage(String s) {
 164.572 +        // language      = 2*3ALPHA            ; shortest ISO 639 code
 164.573 +        //                 ["-" extlang]       ; sometimes followed by
 164.574 +        //                                     ;   extended language subtags
 164.575 +        //               / 4ALPHA              ; or reserved for future use
 164.576 +        //               / 5*8ALPHA            ; or registered language subtag
 164.577 +        return (s.length() >= 2) && (s.length() <= 8) && AsciiUtil.isAlphaString(s);
 164.578 +    }
 164.579 +
 164.580 +    public static boolean isExtlang(String s) {
 164.581 +        // extlang       = 3ALPHA              ; selected ISO 639 codes
 164.582 +        //                 *2("-" 3ALPHA)      ; permanently reserved
 164.583 +        return (s.length() == 3) && AsciiUtil.isAlphaString(s);
 164.584 +    }
 164.585 +
 164.586 +    public static boolean isScript(String s) {
 164.587 +        // script        = 4ALPHA              ; ISO 15924 code
 164.588 +        return (s.length() == 4) && AsciiUtil.isAlphaString(s);
 164.589 +    }
 164.590 +
 164.591 +    public static boolean isRegion(String s) {
 164.592 +        // region        = 2ALPHA              ; ISO 3166-1 code
 164.593 +        //               / 3DIGIT              ; UN M.49 code
 164.594 +        return ((s.length() == 2) && AsciiUtil.isAlphaString(s))
 164.595 +                || ((s.length() == 3) && AsciiUtil.isNumericString(s));
 164.596 +    }
 164.597 +
 164.598 +    public static boolean isVariant(String s) {
 164.599 +        // variant       = 5*8alphanum         ; registered variants
 164.600 +        //               / (DIGIT 3alphanum)
 164.601 +        int len = s.length();
 164.602 +        if (len >= 5 && len <= 8) {
 164.603 +            return AsciiUtil.isAlphaNumericString(s);
 164.604 +        }
 164.605 +        if (len == 4) {
 164.606 +            return AsciiUtil.isNumeric(s.charAt(0))
 164.607 +                    && AsciiUtil.isAlphaNumeric(s.charAt(1))
 164.608 +                    && AsciiUtil.isAlphaNumeric(s.charAt(2))
 164.609 +                    && AsciiUtil.isAlphaNumeric(s.charAt(3));
 164.610 +        }
 164.611 +        return false;
 164.612 +    }
 164.613 +
 164.614 +    public static boolean isExtensionSingleton(String s) {
 164.615 +        // singleton     = DIGIT               ; 0 - 9
 164.616 +        //               / %x41-57             ; A - W
 164.617 +        //               / %x59-5A             ; Y - Z
 164.618 +        //               / %x61-77             ; a - w
 164.619 +        //               / %x79-7A             ; y - z
 164.620 +
 164.621 +        return (s.length() == 1)
 164.622 +                && AsciiUtil.isAlphaString(s)
 164.623 +                && !AsciiUtil.caseIgnoreMatch(PRIVATEUSE, s);
 164.624 +    }
 164.625 +
 164.626 +    public static boolean isExtensionSingletonChar(char c) {
 164.627 +        return isExtensionSingleton(String.valueOf(c));
 164.628 +    }
 164.629 +
 164.630 +    public static boolean isExtensionSubtag(String s) {
 164.631 +        // extension     = singleton 1*("-" (2*8alphanum))
 164.632 +        return (s.length() >= 2) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
 164.633 +    }
 164.634 +
 164.635 +    public static boolean isPrivateusePrefix(String s) {
 164.636 +        // privateuse    = "x" 1*("-" (1*8alphanum))
 164.637 +        return (s.length() == 1)
 164.638 +                && AsciiUtil.caseIgnoreMatch(PRIVATEUSE, s);
 164.639 +    }
 164.640 +
 164.641 +    public static boolean isPrivateusePrefixChar(char c) {
 164.642 +        return (AsciiUtil.caseIgnoreMatch(PRIVATEUSE, String.valueOf(c)));
 164.643 +    }
 164.644 +
 164.645 +    public static boolean isPrivateuseSubtag(String s) {
 164.646 +        // privateuse    = "x" 1*("-" (1*8alphanum))
 164.647 +        return (s.length() >= 1) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
 164.648 +    }
 164.649 +
 164.650 +    //
 164.651 +    // Language subtag canonicalization methods
 164.652 +    //
 164.653 +
 164.654 +    public static String canonicalizeLanguage(String s) {
 164.655 +        return AsciiUtil.toLowerString(s);
 164.656 +    }
 164.657 +
 164.658 +    public static String canonicalizeExtlang(String s) {
 164.659 +        return AsciiUtil.toLowerString(s);
 164.660 +    }
 164.661 +
 164.662 +    public static String canonicalizeScript(String s) {
 164.663 +        return AsciiUtil.toTitleString(s);
 164.664 +    }
 164.665 +
 164.666 +    public static String canonicalizeRegion(String s) {
 164.667 +        return AsciiUtil.toUpperString(s);
 164.668 +    }
 164.669 +
 164.670 +    public static String canonicalizeVariant(String s) {
 164.671 +        return AsciiUtil.toLowerString(s);
 164.672 +    }
 164.673 +
 164.674 +    public static String canonicalizeExtension(String s) {
 164.675 +        return AsciiUtil.toLowerString(s);
 164.676 +    }
 164.677 +
 164.678 +    public static String canonicalizeExtensionSingleton(String s) {
 164.679 +        return AsciiUtil.toLowerString(s);
 164.680 +    }
 164.681 +
 164.682 +    public static String canonicalizeExtensionSubtag(String s) {
 164.683 +        return AsciiUtil.toLowerString(s);
 164.684 +    }
 164.685 +
 164.686 +    public static String canonicalizePrivateuse(String s) {
 164.687 +        return AsciiUtil.toLowerString(s);
 164.688 +    }
 164.689 +
 164.690 +    public static String canonicalizePrivateuseSubtag(String s) {
 164.691 +        return AsciiUtil.toLowerString(s);
 164.692 +    }
 164.693 +
 164.694 +    public String toString() {
 164.695 +        StringBuilder sb = new StringBuilder();
 164.696 +
 164.697 +        if (_language.length() > 0) {
 164.698 +            sb.append(_language);
 164.699 +
 164.700 +            for (String extlang : _extlangs) {
 164.701 +                sb.append(SEP).append(extlang);
 164.702 +            }
 164.703 +
 164.704 +            if (_script.length() > 0) {
 164.705 +                sb.append(SEP).append(_script);
 164.706 +            }
 164.707 +
 164.708 +            if (_region.length() > 0) {
 164.709 +                sb.append(SEP).append(_region);
 164.710 +            }
 164.711 +
 164.712 +            for (String variant : _extlangs) {
 164.713 +                sb.append(SEP).append(variant);
 164.714 +            }
 164.715 +
 164.716 +            for (String extension : _extensions) {
 164.717 +                sb.append(SEP).append(extension);
 164.718 +            }
 164.719 +        }
 164.720 +        if (_privateuse.length() > 0) {
 164.721 +            if (sb.length() > 0) {
 164.722 +                sb.append(SEP);
 164.723 +            }
 164.724 +            sb.append(_privateuse);
 164.725 +        }
 164.726 +
 164.727 +        return sb.toString();
 164.728 +    }
 164.729 +}
   165.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.2 +++ b/src/share/classes/sun/util/locale/LocaleExtensions.java	Fri Sep 24 16:41:32 2010 -0700
   165.3 @@ -0,0 +1,246 @@
   165.4 +/*
   165.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   165.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   165.7 + *
   165.8 + * This code is free software; you can redistribute it and/or modify it
   165.9 + * under the terms of the GNU General Public License version 2 only, as
  165.10 + * published by the Free Software Foundation.  Oracle designates this
  165.11 + * particular file as subject to the "Classpath" exception as provided
  165.12 + * by Oracle in the LICENSE file that accompanied this code.
  165.13 + *
  165.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  165.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  165.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  165.17 + * version 2 for more details (a copy is included in the LICENSE file that
  165.18 + * accompanied this code).
  165.19 + *
  165.20 + * You should have received a copy of the GNU General Public License version
  165.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  165.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  165.23 + *
  165.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  165.25 + * or visit www.oracle.com if you need additional information or have any
  165.26 + * questions.
  165.27 + */
  165.28 +
  165.29 +/*
  165.30 + *******************************************************************************
  165.31 + * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  165.32 + * others. All Rights Reserved.                                                *
  165.33 + *******************************************************************************
  165.34 + */
  165.35 +package sun.util.locale;
  165.36 +
  165.37 +import java.util.Collections;
  165.38 +import java.util.Map;
  165.39 +import java.util.Map.Entry;
  165.40 +import java.util.Set;
  165.41 +import java.util.SortedMap;
  165.42 +import java.util.TreeMap;
  165.43 +import java.util.TreeSet;
  165.44 +
  165.45 +import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveChar;
  165.46 +import sun.util.locale.InternalLocaleBuilder.CaseInsensitiveString;
  165.47 +
  165.48 +
  165.49 +public class LocaleExtensions {
  165.50 +
  165.51 +    private SortedMap<Character, Extension> _map;
  165.52 +    private String _id;
  165.53 +
  165.54 +    private static final SortedMap<Character, Extension> EMPTY_MAP =
  165.55 +        Collections.unmodifiableSortedMap(new TreeMap<Character, Extension>());
  165.56 +
  165.57 +    public static final LocaleExtensions EMPTY_EXTENSIONS;
  165.58 +    public static final LocaleExtensions CALENDAR_JAPANESE;
  165.59 +    public static final LocaleExtensions NUMBER_THAI;
  165.60 +
  165.61 +    static {
  165.62 +        EMPTY_EXTENSIONS = new LocaleExtensions();
  165.63 +        EMPTY_EXTENSIONS._id = "";
  165.64 +        EMPTY_EXTENSIONS._map = EMPTY_MAP;
  165.65 +
  165.66 +        CALENDAR_JAPANESE = new LocaleExtensions();
  165.67 +        CALENDAR_JAPANESE._id = "u-ca-japanese";
  165.68 +        CALENDAR_JAPANESE._map = new TreeMap<Character, Extension>();
  165.69 +        CALENDAR_JAPANESE._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.CA_JAPANESE);
  165.70 +
  165.71 +        NUMBER_THAI = new LocaleExtensions();
  165.72 +        NUMBER_THAI._id = "u-nu-thai";
  165.73 +        NUMBER_THAI._map = new TreeMap<Character, Extension>();
  165.74 +        NUMBER_THAI._map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), UnicodeLocaleExtension.NU_THAI);
  165.75 +    }
  165.76 +
  165.77 +    private LocaleExtensions() {
  165.78 +    }
  165.79 +
  165.80 +    /*
  165.81 +     * Package local constructor, only used by InternalLocaleBuilder.
  165.82 +     */
  165.83 +    LocaleExtensions(Map<CaseInsensitiveChar, String> extensions,
  165.84 +            Set<CaseInsensitiveString> uattributes, Map<CaseInsensitiveString, String> ukeywords) {
  165.85 +        boolean hasExtension = (extensions != null && extensions.size() > 0);
  165.86 +        boolean hasUAttributes = (uattributes != null && uattributes.size() > 0);
  165.87 +        boolean hasUKeywords = (ukeywords != null && ukeywords.size() > 0);
  165.88 +
  165.89 +        if (!hasExtension && !hasUAttributes && !hasUKeywords) {
  165.90 +            _map = EMPTY_MAP;
  165.91 +            _id = "";
  165.92 +            return;
  165.93 +        }
  165.94 +
  165.95 +        // Build extension map
  165.96 +        _map = new TreeMap<Character, Extension>();
  165.97 +        if (hasExtension) {
  165.98 +            for (Entry<CaseInsensitiveChar, String> ext : extensions.entrySet()) {
  165.99 +                char key = AsciiUtil.toLower(ext.getKey().value());
 165.100 +                String value = ext.getValue();
 165.101 +
 165.102 +                if (LanguageTag.isPrivateusePrefixChar(key)) {
 165.103 +                    // we need to exclude special variant in privuateuse, e.g. "x-abc-lvariant-DEF"
 165.104 +                    value = InternalLocaleBuilder.removePrivateuseVariant(value);
 165.105 +                    if (value == null) {
 165.106 +                        continue;
 165.107 +                    }
 165.108 +                }
 165.109 +
 165.110 +                Extension e = new Extension(key, AsciiUtil.toLowerString(value));
 165.111 +                _map.put(Character.valueOf(key), e);
 165.112 +            }
 165.113 +        }
 165.114 +
 165.115 +        if (hasUAttributes || hasUKeywords) {
 165.116 +            TreeSet<String> uaset = null;
 165.117 +            TreeMap<String, String> ukmap = null;
 165.118 +
 165.119 +            if (hasUAttributes) {
 165.120 +                uaset = new TreeSet<String>();
 165.121 +                for (CaseInsensitiveString cis : uattributes) {
 165.122 +                    uaset.add(AsciiUtil.toLowerString(cis.value()));
 165.123 +                }
 165.124 +            }
 165.125 +
 165.126 +            if (hasUKeywords) {
 165.127 +                ukmap = new TreeMap<String, String>();
 165.128 +                for (Entry<CaseInsensitiveString, String> kwd : ukeywords.entrySet()) {
 165.129 +                    String key = AsciiUtil.toLowerString(kwd.getKey().value());
 165.130 +                    String type = AsciiUtil.toLowerString(kwd.getValue());
 165.131 +                    ukmap.put(key, type);
 165.132 +                }
 165.133 +            }
 165.134 +
 165.135 +            UnicodeLocaleExtension ule = new UnicodeLocaleExtension(uaset, ukmap);
 165.136 +            _map.put(Character.valueOf(UnicodeLocaleExtension.SINGLETON), ule);
 165.137 +        }
 165.138 +
 165.139 +        if (_map.size() == 0) {
 165.140 +            // this could happen when only privuateuse with special variant
 165.141 +            _map = EMPTY_MAP;
 165.142 +            _id = "";
 165.143 +        } else {
 165.144 +            _id = toID(_map);
 165.145 +        }
 165.146 +    }
 165.147 +
 165.148 +    public Set<Character> getKeys() {
 165.149 +        return Collections.unmodifiableSet(_map.keySet());
 165.150 +    }
 165.151 +
 165.152 +    public Extension getExtension(Character key) {
 165.153 +        return _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
 165.154 +    }
 165.155 +
 165.156 +    public String getExtensionValue(Character key) {
 165.157 +        Extension ext = _map.get(Character.valueOf(AsciiUtil.toLower(key.charValue())));
 165.158 +        if (ext == null) {
 165.159 +            return null;
 165.160 +        }
 165.161 +        return ext.getValue();
 165.162 +    }
 165.163 +
 165.164 +    public Set<String> getUnicodeLocaleAttributes() {
 165.165 +        Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
 165.166 +        if (ext == null) {
 165.167 +            return Collections.emptySet();
 165.168 +        }
 165.169 +        assert (ext instanceof UnicodeLocaleExtension);
 165.170 +        return ((UnicodeLocaleExtension)ext).getUnicodeLocaleAttributes();
 165.171 +    }
 165.172 +
 165.173 +    public Set<String> getUnicodeLocaleKeys() {
 165.174 +        Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
 165.175 +        if (ext == null) {
 165.176 +            return Collections.emptySet();
 165.177 +        }
 165.178 +        assert (ext instanceof UnicodeLocaleExtension);
 165.179 +        return ((UnicodeLocaleExtension)ext).getUnicodeLocaleKeys();
 165.180 +    }
 165.181 +
 165.182 +    public String getUnicodeLocaleType(String unicodeLocaleKey) {
 165.183 +        Extension ext = _map.get(Character.valueOf(UnicodeLocaleExtension.SINGLETON));
 165.184 +        if (ext == null) {
 165.185 +            return null;
 165.186 +        }
 165.187 +        assert (ext instanceof UnicodeLocaleExtension);
 165.188 +        return ((UnicodeLocaleExtension)ext).getUnicodeLocaleType(AsciiUtil.toLowerString(unicodeLocaleKey));
 165.189 +    }
 165.190 +
 165.191 +    public boolean isEmpty() {
 165.192 +        return _map.isEmpty();
 165.193 +    }
 165.194 +
 165.195 +    public static boolean isValidKey(char c) {
 165.196 +        return LanguageTag.isExtensionSingletonChar(c) || LanguageTag.isPrivateusePrefixChar(c);
 165.197 +    }
 165.198 +
 165.199 +    public static boolean isValidUnicodeLocaleKey(String ukey) {
 165.200 +        return UnicodeLocaleExtension.isKey(ukey);
 165.201 +    }
 165.202 +
 165.203 +    private static String toID(SortedMap<Character, Extension> map) {
 165.204 +        StringBuilder buf = new StringBuilder();
 165.205 +        Extension privuse = null;
 165.206 +        for (Entry<Character, Extension> entry : map.entrySet()) {
 165.207 +            char singleton = entry.getKey().charValue();
 165.208 +            Extension extension = entry.getValue();
 165.209 +            if (LanguageTag.isPrivateusePrefixChar(singleton)) {
 165.210 +                privuse = extension;
 165.211 +            } else {
 165.212 +                if (buf.length() > 0) {
 165.213 +                    buf.append(LanguageTag.SEP);
 165.214 +                }
 165.215 +                buf.append(extension);
 165.216 +            }
 165.217 +        }
 165.218 +        if (privuse != null) {
 165.219 +            if (buf.length() > 0) {
 165.220 +                buf.append(LanguageTag.SEP);
 165.221 +            }
 165.222 +            buf.append(privuse);
 165.223 +        }
 165.224 +        return buf.toString();
 165.225 +    }
 165.226 +
 165.227 +
 165.228 +    public String toString() {
 165.229 +        return _id;
 165.230 +    }
 165.231 +
 165.232 +    public String getID() {
 165.233 +        return _id;
 165.234 +    }
 165.235 +
 165.236 +    public int hashCode() {
 165.237 +        return _id.hashCode();
 165.238 +    }
 165.239 +
 165.240 +    public boolean equals(Object other) {
 165.241 +        if (this == other) {
 165.242 +            return true;
 165.243 +        }
 165.244 +        if (!(other instanceof LocaleExtensions)) {
 165.245 +            return false;
 165.246 +        }
 165.247 +        return this._id.equals(((LocaleExtensions)other)._id);
 165.248 +    }
 165.249 +}
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/src/share/classes/sun/util/locale/LocaleObjectCache.java	Fri Sep 24 16:41:32 2010 -0700
   166.3 @@ -0,0 +1,108 @@
   166.4 +/*
   166.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   166.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   166.7 + *
   166.8 + * This code is free software; you can redistribute it and/or modify it
   166.9 + * under the terms of the GNU General Public License version 2 only, as
  166.10 + * published by the Free Software Foundation.  Oracle designates this
  166.11 + * particular file as subject to the "Classpath" exception as provided
  166.12 + * by Oracle in the LICENSE file that accompanied this code.
  166.13 + *
  166.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  166.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  166.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  166.17 + * version 2 for more details (a copy is included in the LICENSE file that
  166.18 + * accompanied this code).
  166.19 + *
  166.20 + * You should have received a copy of the GNU General Public License version
  166.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  166.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  166.23 + *
  166.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  166.25 + * or visit www.oracle.com if you need additional information or have any
  166.26 + * questions.
  166.27 + */
  166.28 +
  166.29 +/*
  166.30 + *******************************************************************************
  166.31 + * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  166.32 + * others. All Rights Reserved.                                                *
  166.33 + *******************************************************************************
  166.34 + */
  166.35 +package sun.util.locale;
  166.36 +
  166.37 +import java.lang.ref.ReferenceQueue;
  166.38 +import java.lang.ref.SoftReference;
  166.39 +import java.util.concurrent.ConcurrentHashMap;
  166.40 +
  166.41 +public abstract class LocaleObjectCache<K, V> {
  166.42 +    private ConcurrentHashMap<K, CacheEntry<K, V>> _map;
  166.43 +    private ReferenceQueue<V> _queue = new ReferenceQueue<V>();
  166.44 +
  166.45 +    public LocaleObjectCache() {
  166.46 +        this(16, 0.75f, 16);
  166.47 +    }
  166.48 +
  166.49 +    public LocaleObjectCache(int initialCapacity, float loadFactor, int concurrencyLevel) {
  166.50 +        _map = new ConcurrentHashMap<K, CacheEntry<K, V>>(initialCapacity, loadFactor, concurrencyLevel);
  166.51 +    }
  166.52 +
  166.53 +    public V get(K key) {
  166.54 +        V value = null;
  166.55 +
  166.56 +        cleanStaleEntries();
  166.57 +        CacheEntry<K, V> entry = _map.get(key);
  166.58 +        if (entry != null) {
  166.59 +            value = entry.get();
  166.60 +        }
  166.61 +        if (value == null) {
  166.62 +            key = normalizeKey(key);
  166.63 +            V newVal = createObject(key);
  166.64 +            if (key == null || newVal == null) {
  166.65 +                // subclass must return non-null key/value object
  166.66 +                return null;
  166.67 +            }
  166.68 +
  166.69 +            CacheEntry<K, V> newEntry = new CacheEntry<K, V>(key, newVal, _queue);
  166.70 +
  166.71 +            while (value == null) {
  166.72 +                cleanStaleEntries();
  166.73 +                entry = _map.putIfAbsent(key, newEntry);
  166.74 +                if (entry == null) {
  166.75 +                    value = newVal;
  166.76 +                    break;
  166.77 +                } else {
  166.78 +                    value = entry.get();
  166.79 +                }
  166.80 +            }
  166.81 +        }
  166.82 +        return value;
  166.83 +    }
  166.84 +
  166.85 +    @SuppressWarnings("unchecked")
  166.86 +    private void cleanStaleEntries() {
  166.87 +        CacheEntry<K, V> entry;
  166.88 +        while ((entry = (CacheEntry<K, V>)_queue.poll()) != null) {
  166.89 +            _map.remove(entry.getKey());
  166.90 +        }
  166.91 +    }
  166.92 +
  166.93 +    protected abstract V createObject(K key);
  166.94 +
  166.95 +    protected K normalizeKey(K key) {
  166.96 +        return key;
  166.97 +    }
  166.98 +
  166.99 +    private static class CacheEntry<K, V> extends SoftReference<V> {
 166.100 +        private K _key;
 166.101 +
 166.102 +        CacheEntry(K key, V value, ReferenceQueue<V> queue) {
 166.103 +            super(value, queue);
 166.104 +            _key = key;
 166.105 +        }
 166.106 +
 166.107 +        K getKey() {
 166.108 +            return _key;
 166.109 +        }
 166.110 +    }
 166.111 +}
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/src/share/classes/sun/util/locale/LocaleSyntaxException.java	Fri Sep 24 16:41:32 2010 -0700
   167.3 @@ -0,0 +1,52 @@
   167.4 +/*
   167.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   167.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   167.7 + *
   167.8 + * This code is free software; you can redistribute it and/or modify it
   167.9 + * under the terms of the GNU General Public License version 2 only, as
  167.10 + * published by the Free Software Foundation.  Oracle designates this
  167.11 + * particular file as subject to the "Classpath" exception as provided
  167.12 + * by Oracle in the LICENSE file that accompanied this code.
  167.13 + *
  167.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  167.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  167.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  167.17 + * version 2 for more details (a copy is included in the LICENSE file that
  167.18 + * accompanied this code).
  167.19 + *
  167.20 + * You should have received a copy of the GNU General Public License version
  167.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  167.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  167.23 + *
  167.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  167.25 + * or visit www.oracle.com if you need additional information or have any
  167.26 + * questions.
  167.27 + */
  167.28 +
  167.29 +/*
  167.30 + *******************************************************************************
  167.31 + * Copyright (C) 2009, International Business Machines Corporation and         *
  167.32 + * others. All Rights Reserved.                                                *
  167.33 + *******************************************************************************
  167.34 + */
  167.35 +package sun.util.locale;
  167.36 +
  167.37 +public class LocaleSyntaxException extends Exception {
  167.38 +
  167.39 +    private static final long serialVersionUID = 1L;
  167.40 +
  167.41 +    private int _index = -1;
  167.42 +
  167.43 +    public LocaleSyntaxException(String msg) {
  167.44 +        this(msg, 0);
  167.45 +    }
  167.46 +
  167.47 +    public LocaleSyntaxException(String msg, int errorIndex) {
  167.48 +        super(msg);
  167.49 +        _index = errorIndex;
  167.50 +    }
  167.51 +
  167.52 +    public int getErrorIndex() {
  167.53 +        return _index;
  167.54 +    }
  167.55 +}
   168.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   168.2 +++ b/src/share/classes/sun/util/locale/ParseStatus.java	Fri Sep 24 16:41:32 2010 -0700
   168.3 @@ -0,0 +1,60 @@
   168.4 +/*
   168.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   168.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   168.7 + *
   168.8 + * This code is free software; you can redistribute it and/or modify it
   168.9 + * under the terms of the GNU General Public License version 2 only, as
  168.10 + * published by the Free Software Foundation.  Oracle designates this
  168.11 + * particular file as subject to the "Classpath" exception as provided
  168.12 + * by Oracle in the LICENSE file that accompanied this code.
  168.13 + *
  168.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  168.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  168.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  168.17 + * version 2 for more details (a copy is included in the LICENSE file that
  168.18 + * accompanied this code).
  168.19 + *
  168.20 + * You should have received a copy of the GNU General Public License version
  168.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  168.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  168.23 + *
  168.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  168.25 + * or visit www.oracle.com if you need additional information or have any
  168.26 + * questions.
  168.27 + */
  168.28 +
  168.29 +/*
  168.30 + *******************************************************************************
  168.31 + * Copyright (C) 2010, International Business Machines Corporation and         *
  168.32 + * others. All Rights Reserved.                                                *
  168.33 + *******************************************************************************
  168.34 + */
  168.35 +package sun.util.locale;
  168.36 +
  168.37 +public class ParseStatus {
  168.38 +    int _parseLength = 0;
  168.39 +    int _errorIndex = -1;
  168.40 +    String _errorMsg = null;
  168.41 +
  168.42 +    public void reset() {
  168.43 +        _parseLength = 0;
  168.44 +        _errorIndex = -1;
  168.45 +        _errorMsg = null;
  168.46 +    }
  168.47 +
  168.48 +    public boolean isError() {
  168.49 +        return (_errorIndex >= 0);
  168.50 +    }
  168.51 +
  168.52 +    public int getErrorIndex() {
  168.53 +        return _errorIndex;
  168.54 +    }
  168.55 +
  168.56 +    public int getParseLength() {
  168.57 +        return _parseLength;
  168.58 +    }
  168.59 +
  168.60 +    public String getErrorMessage() {
  168.61 +        return _errorMsg;
  168.62 +    }
  168.63 +}
   169.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   169.2 +++ b/src/share/classes/sun/util/locale/StringTokenIterator.java	Fri Sep 24 16:41:32 2010 -0700
   169.3 @@ -0,0 +1,117 @@
   169.4 +/*
   169.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   169.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   169.7 + *
   169.8 + * This code is free software; you can redistribute it and/or modify it
   169.9 + * under the terms of the GNU General Public License version 2 only, as
  169.10 + * published by the Free Software Foundation.  Oracle designates this
  169.11 + * particular file as subject to the "Classpath" exception as provided
  169.12 + * by Oracle in the LICENSE file that accompanied this code.
  169.13 + *
  169.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  169.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  169.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  169.17 + * version 2 for more details (a copy is included in the LICENSE file that
  169.18 + * accompanied this code).
  169.19 + *
  169.20 + * You should have received a copy of the GNU General Public License version
  169.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  169.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  169.23 + *
  169.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  169.25 + * or visit www.oracle.com if you need additional information or have any
  169.26 + * questions.
  169.27 + */
  169.28 +/*
  169.29 + *******************************************************************************
  169.30 + * Copyright (C) 2009, International Business Machines Corporation and         *
  169.31 + * others. All Rights Reserved.                                                *
  169.32 + *******************************************************************************
  169.33 + */
  169.34 +package sun.util.locale;
  169.35 +
  169.36 +public class StringTokenIterator {
  169.37 +    private String _text;
  169.38 +    private String _dlms;
  169.39 +
  169.40 +    private String _token;
  169.41 +    private int _start;
  169.42 +    private int _end;
  169.43 +    private boolean _done;
  169.44 +
  169.45 +    public StringTokenIterator(String text, String dlms) {
  169.46 +        _text = text;
  169.47 +        _dlms = dlms;
  169.48 +        setStart(0);
  169.49 +    }
  169.50 +
  169.51 +    public String first() {
  169.52 +        setStart(0);
  169.53 +        return _token;
  169.54 +    }
  169.55 +
  169.56 +    public String current() {
  169.57 +        return _token;
  169.58 +    }
  169.59 +
  169.60 +    public int currentStart() {
  169.61 +        return _start;
  169.62 +    }
  169.63 +
  169.64 +    public int currentEnd() {
  169.65 +        return _end;
  169.66 +    }
  169.67 +
  169.68 +    public boolean isDone() {
  169.69 +        return _done;
  169.70 +    }
  169.71 +
  169.72 +    public String next() {
  169.73 +        if (hasNext()) {
  169.74 +            _start = _end + 1;
  169.75 +            _end = nextDelimiter(_start);
  169.76 +            _token = _text.substring(_start, _end);
  169.77 +        } else {
  169.78 +            _start = _end;
  169.79 +            _token = null;
  169.80 +            _done = true;
  169.81 +        }
  169.82 +        return _token;
  169.83 +    }
  169.84 +
  169.85 +    public boolean hasNext() {
  169.86 +        return (_end < _text.length());
  169.87 +    }
  169.88 +
  169.89 +    public StringTokenIterator setStart(int offset) {
  169.90 +        if (offset > _text.length()) {
  169.91 +            throw new IndexOutOfBoundsException();
  169.92 +        }
  169.93 +        _start = offset;
  169.94 +        _end = nextDelimiter(_start);
  169.95 +        _token = _text.substring(_start, _end);
  169.96 +        _done = false;
  169.97 +        return this;
  169.98 +    }
  169.99 +
 169.100 +    public StringTokenIterator setText(String text) {
 169.101 +        _text = text;
 169.102 +        setStart(0);
 169.103 +        return this;
 169.104 +    }
 169.105 +
 169.106 +    private int nextDelimiter(int start) {
 169.107 +        int idx = start;
 169.108 +        outer: while (idx < _text.length()) {
 169.109 +            char c = _text.charAt(idx);
 169.110 +            for (int i = 0; i < _dlms.length(); i++) {
 169.111 +                if (c == _dlms.charAt(i)) {
 169.112 +                    break outer;
 169.113 +                }
 169.114 +            }
 169.115 +            idx++;
 169.116 +        }
 169.117 +        return idx;
 169.118 +    }
 169.119 +}
 169.120 +
   170.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   170.2 +++ b/src/share/classes/sun/util/locale/UnicodeLocaleExtension.java	Fri Sep 24 16:41:32 2010 -0700
   170.3 @@ -0,0 +1,127 @@
   170.4 +/*
   170.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   170.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   170.7 + *
   170.8 + * This code is free software; you can redistribute it and/or modify it
   170.9 + * under the terms of the GNU General Public License version 2 only, as
  170.10 + * published by the Free Software Foundation.  Oracle designates this
  170.11 + * particular file as subject to the "Classpath" exception as provided
  170.12 + * by Oracle in the LICENSE file that accompanied this code.
  170.13 + *
  170.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  170.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  170.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  170.17 + * version 2 for more details (a copy is included in the LICENSE file that
  170.18 + * accompanied this code).
  170.19 + *
  170.20 + * You should have received a copy of the GNU General Public License version
  170.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  170.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  170.23 + *
  170.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  170.25 + * or visit www.oracle.com if you need additional information or have any
  170.26 + * questions.
  170.27 + */
  170.28 +
  170.29 +/*
  170.30 + *******************************************************************************
  170.31 + * Copyright (C) 2009-2010, International Business Machines Corporation and    *
  170.32 + * others. All Rights Reserved.                                                *
  170.33 + *******************************************************************************
  170.34 + */
  170.35 +package sun.util.locale;
  170.36 +
  170.37 +import java.util.Collections;
  170.38 +import java.util.Map.Entry;
  170.39 +import java.util.Set;
  170.40 +import java.util.SortedMap;
  170.41 +import java.util.SortedSet;
  170.42 +import java.util.TreeMap;
  170.43 +import java.util.TreeSet;
  170.44 +
  170.45 +public class UnicodeLocaleExtension extends Extension {
  170.46 +    public static final char SINGLETON = 'u';
  170.47 +
  170.48 +    private static final SortedSet<String> EMPTY_SORTED_SET = new TreeSet<String>();
  170.49 +    private static final SortedMap<String, String> EMPTY_SORTED_MAP = new TreeMap<String, String>();
  170.50 +
  170.51 +    private SortedSet<String> _attributes = EMPTY_SORTED_SET;
  170.52 +    private SortedMap<String, String> _keywords = EMPTY_SORTED_MAP;
  170.53 +
  170.54 +    public static final UnicodeLocaleExtension CA_JAPANESE;
  170.55 +    public static final UnicodeLocaleExtension NU_THAI;
  170.56 +
  170.57 +    static {
  170.58 +        CA_JAPANESE = new UnicodeLocaleExtension();
  170.59 +        CA_JAPANESE._keywords = new TreeMap<String, String>();
  170.60 +        CA_JAPANESE._keywords.put("ca", "japanese");
  170.61 +        CA_JAPANESE._value = "ca-japanese";
  170.62 +
  170.63 +        NU_THAI = new UnicodeLocaleExtension();
  170.64 +        NU_THAI._keywords = new TreeMap<String, String>();
  170.65 +        NU_THAI._keywords.put("nu", "thai");
  170.66 +        NU_THAI._value = "nu-thai";
  170.67 +    }
  170.68 +
  170.69 +    private UnicodeLocaleExtension() {
  170.70 +        super(SINGLETON);
  170.71 +    }
  170.72 +
  170.73 +    UnicodeLocaleExtension(SortedSet<String> attributes, SortedMap<String, String> keywords) {
  170.74 +        this();
  170.75 +        if (attributes != null && attributes.size() > 0) {
  170.76 +            _attributes = attributes;
  170.77 +        }
  170.78 +        if (keywords != null && keywords.size() > 0) {
  170.79 +            _keywords = keywords;
  170.80 +        }
  170.81 +
  170.82 +        if (_attributes.size() > 0 || _keywords.size() > 0) {
  170.83 +            StringBuilder sb = new StringBuilder();
  170.84 +            for (String attribute : _attributes) {
  170.85 +                sb.append(LanguageTag.SEP).append(attribute);
  170.86 +            }
  170.87 +            for (Entry<String, String> keyword : _keywords.entrySet()) {
  170.88 +                String key = keyword.getKey();
  170.89 +                String value = keyword.getValue();
  170.90 +
  170.91 +                sb.append(LanguageTag.SEP).append(key);
  170.92 +                if (value.length() > 0) {
  170.93 +                    sb.append(LanguageTag.SEP).append(value);
  170.94 +                }
  170.95 +            }
  170.96 +            _value = sb.substring(1);   // skip leading '-'
  170.97 +        }
  170.98 +    }
  170.99 +
 170.100 +    public Set<String> getUnicodeLocaleAttributes() {
 170.101 +        return Collections.unmodifiableSet(_attributes);
 170.102 +    }
 170.103 +
 170.104 +    public Set<String> getUnicodeLocaleKeys() {
 170.105 +        return Collections.unmodifiableSet(_keywords.keySet());
 170.106 +    }
 170.107 +
 170.108 +    public String getUnicodeLocaleType(String unicodeLocaleKey) {
 170.109 +        return _keywords.get(unicodeLocaleKey);
 170.110 +    }
 170.111 +
 170.112 +    public static boolean isSingletonChar(char c) {
 170.113 +        return (SINGLETON == AsciiUtil.toLower(c));
 170.114 +    }
 170.115 +
 170.116 +    public static boolean isAttribute(String s) {
 170.117 +        // 3*8alphanum
 170.118 +        return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
 170.119 +    }
 170.120 +
 170.121 +    public static boolean isKey(String s) {
 170.122 +        // 2alphanum
 170.123 +        return (s.length() == 2) && AsciiUtil.isAlphaNumericString(s);
 170.124 +    }
 170.125 +
 170.126 +    public static boolean isTypeSubtag(String s) {
 170.127 +        // 3*8alphanum
 170.128 +        return (s.length() >= 3) && (s.length() <= 8) && AsciiUtil.isAlphaNumericString(s);
 170.129 +    }
 170.130 +}
   171.1 --- a/src/share/classes/sun/util/resources/LocaleData.java	Thu Sep 23 17:33:40 2010 -0700
   171.2 +++ b/src/share/classes/sun/util/resources/LocaleData.java	Fri Sep 24 16:41:32 2010 -0700
   171.3 @@ -1,5 +1,5 @@
   171.4  /*
   171.5 - * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
   171.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   171.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   171.8   *
   171.9   * This code is free software; you can redistribute it and/or modify it
  171.10 @@ -177,6 +177,11 @@
  171.11  
  171.12              for (Iterator<Locale> l = candidates.iterator(); l.hasNext(); ) {
  171.13                  String lstr = l.next().toString();
  171.14 +                /* truncate extra segment introduced by Java 7 for script and extesions */
  171.15 +                int idx = lstr.indexOf("_#");
  171.16 +                if (idx >= 0) {
  171.17 +                    lstr = lstr.substring(0, idx);
  171.18 +                }
  171.19                  /* Every locale string in the locale string list returned from
  171.20                     the above getSupportedLocaleString is enclosed
  171.21                     within two white spaces so that we could check some locale
   172.1 --- a/src/share/classes/sun/util/resources/LocaleNames.properties	Thu Sep 23 17:33:40 2010 -0700
   172.2 +++ b/src/share/classes/sun/util/resources/LocaleNames.properties	Fri Sep 24 16:41:32 2010 -0700
   172.3 @@ -228,6 +228,157 @@
   172.4  zh=Chinese
   172.5  zu=Zulu
   172.6  
   172.7 +# script names
   172.8 +# key is ISO 15924 script code
   172.9 +
  172.10 +Arab=Arabic
  172.11 +Armi=Imperial Aramaic
  172.12 +Armn=Armenian
  172.13 +Avst=Avestan
  172.14 +Bali=Balinese
  172.15 +Bamu=Bamum
  172.16 +Bass=Bassa Vah
  172.17 +Batk=Batak
  172.18 +Beng=Bengali
  172.19 +Blis=Blissymbols
  172.20 +Bopo=Bopomofo
  172.21 +Brah=Brahmi
  172.22 +Brai=Braille
  172.23 +Bugi=Buginese
  172.24 +Buhd=Buhid
  172.25 +Cakm=Chakma
  172.26 +Cans=Unified Canadian Aboriginal Syllabics
  172.27 +Cari=Carian
  172.28 +Cham=Cham
  172.29 +Cher=Cherokee
  172.30 +Cirt=Cirth
  172.31 +Copt=Coptic
  172.32 +Cprt=Cypriot
  172.33 +Cyrl=Cyrillic
  172.34 +Cyrs=Old Church Slavonic Cyrillic
  172.35 +Deva=Devanagari
  172.36 +Dsrt=Deseret
  172.37 +Dupl=Duployan shorthand
  172.38 +Egyd=Egyptian demotic
  172.39 +Egyh=Egyptian hieratic
  172.40 +Egyp=Egyptian hieroglyphs
  172.41 +Elba=Elbasan
  172.42 +Ethi=Ethiopic
  172.43 +Geok=Khutsuri
  172.44 +Geor=Georgian
  172.45 +Glag=Glagolitic
  172.46 +Goth=Gothic
  172.47 +Gran=Grantha
  172.48 +Grek=Greek
  172.49 +Gujr=Gujarati
  172.50 +Guru=Gurmukhi
  172.51 +Hang=Hangul
  172.52 +Hani=Han
  172.53 +Hano=Hanunoo
  172.54 +Hans=Simplified Han
  172.55 +Hant=Traditional Han
  172.56 +Hebr=Hebrew
  172.57 +Hira=Hiragana
  172.58 +Hmng=Pahawh Hmong
  172.59 +Hrkt=Katakana or Hiragana
  172.60 +Hung=Old Hungarian
  172.61 +Inds=Indus
  172.62 +Ital=Old Italic
  172.63 +Java=Javanese
  172.64 +Jpan=Japanese
  172.65 +Kali=Kayah Li
  172.66 +Kana=Katakana
  172.67 +Khar=Kharoshthi
  172.68 +Khmr=Khmer
  172.69 +Knda=Kannada
  172.70 +Kore=Korean
  172.71 +Kpel=Kpelle
  172.72 +Kthi=Kaithi
  172.73 +Lana=Tai Tham
  172.74 +Laoo=Lao
  172.75 +Latf=Fraktur Latin
  172.76 +Latg=Gaelic Latin
  172.77 +Latn=Latin
  172.78 +Lepc=Lepcha
  172.79 +Limb=Limbu
  172.80 +Lina=Linear A
  172.81 +Linb=Linear B
  172.82 +Lisu=Lisu
  172.83 +Loma=Loma
  172.84 +Lyci=Lycian
  172.85 +Lydi=Lydian
  172.86 +Mand=Mandaic
  172.87 +Mani=Manichaean
  172.88 +Maya=Mayan hieroglyphs
  172.89 +Mend=Mende
  172.90 +Merc=Meroitic Cursive
  172.91 +Mero=Meroitic
  172.92 +Mlym=Malayalam
  172.93 +Mong=Mongolian
  172.94 +Moon=Moon
  172.95 +Mtei=Meitei Mayek
  172.96 +Mymr=Myanmar
  172.97 +Narb=Old North Arabian
  172.98 +Nbat=Nabataean
  172.99 +Nkgb=Nakhi Geba
 172.100 +Nkoo=N\u2019Ko
 172.101 +Ogam=Ogham
 172.102 +Olck=Ol Chiki
 172.103 +Orkh=Orkhon
 172.104 +Orya=Oriya
 172.105 +Osma=Osmanya
 172.106 +Palm=Palmyrene
 172.107 +Perm=Old Permic
 172.108 +Phag=Phags-pa
 172.109 +Phli=Inscriptional Pahlavi
 172.110 +Phlp=Psalter Pahlavi
 172.111 +Phlv=Book Pahlavi
 172.112 +Phnx=Phoenician
 172.113 +Plrd=Miao
 172.114 +Prti=Inscriptional Parthian
 172.115 +Rjng=Rejang
 172.116 +Roro=Rongorongo
 172.117 +Runr=Runic
 172.118 +Samr=Samaritan
 172.119 +Sara=Sarati
 172.120 +Sarb=Old South Arabian
 172.121 +Saur=Saurashtra
 172.122 +Sgnw=SignWriting
 172.123 +Shaw=Shavian
 172.124 +Sind=Sindhi
 172.125 +Sinh=Sinhala
 172.126 +Sund=Sundanese
 172.127 +Sylo=Syloti Nagri
 172.128 +Syrc=Syriac
 172.129 +Syre=Estrangelo Syriac
 172.130 +Syrj=Western Syriac
 172.131 +Syrn=Eastern Syriac
 172.132 +Tagb=Tagbanwa
 172.133 +Tale=Tai Le
 172.134 +Talu=New Tai Lue
 172.135 +Taml=Tamil
 172.136 +Tavt=Tai Viet
 172.137 +Telu=Telugu
 172.138 +Teng=Tengwar
 172.139 +Tfng=Tifinagh
 172.140 +Tglg=Tagalog
 172.141 +Thaa=Thaana
 172.142 +Thai=Thai
 172.143 +Tibt=Tibetan
 172.144 +Ugar=Ugaritic
 172.145 +Vaii=Vai
 172.146 +Visp=Visible Speech
 172.147 +Wara=Warang Citi
 172.148 +Xpeo=Old Persian
 172.149 +Xsux=Sumero-Akkadian Cuneiform
 172.150 +Yiii=Yi
 172.151 +Zinh=Inherited script
 172.152 +Zmth=Mathematical Notation
 172.153 +Zsym=Symbols
 172.154 +Zxxx=Unwritten
 172.155 +Zyyy=Undetermined script
 172.156 +Zzzz=Uncoded script
 172.157 +
 172.158  # country names
 172.159  # key is ISO 3166 country code
 172.160  
 172.161 @@ -479,6 +630,39 @@
 172.162  ZM=Zambia
 172.163  ZW=Zimbabwe
 172.164  
 172.165 +# territory names
 172.166 +# key is UN M.49 country and area code
 172.167 +
 172.168 +001=World
 172.169 +002=Africa
 172.170 +003=North America
 172.171 +005=South America
 172.172 +009=Oceania
 172.173 +011=Western Africa
 172.174 +013=Central America
 172.175 +014=Eastern Africa
 172.176 +015=Northern Africa
 172.177 +017=Middle Africa
 172.178 +018=Southern Africa
 172.179 +019=Americas
 172.180 +021=Northern America
 172.181 +029=Caribbean
 172.182 +030=Eastern Asia
 172.183 +034=Southern Asia
 172.184 +035=South-Eastern Asia
 172.185 +039=Southern Europe
 172.186 +053=Australia and New Zealand
 172.187 +054=Melanesia
 172.188 +057=Micronesian Region
 172.189 +061=Polynesia
 172.190 +142=Asia
 172.191 +143=Central Asia
 172.192 +145=Western Asia
 172.193 +150=Europe
 172.194 +151=Eastern Europe
 172.195 +154=Northern Europe
 172.196 +155=Western Europe
 172.197 +419=Latin America and the Caribbean
 172.198  
 172.199  # variant names
 172.200  # key is %%variant
   173.1 --- a/src/share/classes/sun/util/resources/LocaleNames_zh.properties	Thu Sep 23 17:33:40 2010 -0700
   173.2 +++ b/src/share/classes/sun/util/resources/LocaleNames_zh.properties	Fri Sep 24 16:41:32 2010 -0700
   173.3 @@ -227,6 +227,12 @@
   173.4  zh=\u4e2d\u6587
   173.5  zu=\u7956\u9c81\u6587
   173.6  
   173.7 +# script names
   173.8 +# key is ISO 15924 script code
   173.9 +
  173.10 +Hans=\u7b80\u4f53\u4e2d\u6587
  173.11 +Hant=\u7e41\u4f53\u4e2d\u6587
  173.12 +
  173.13  # country names
  173.14  # key is ISO 3166 country code
  173.15  
   174.1 --- a/src/share/classes/sun/util/resources/LocaleNames_zh_TW.properties	Thu Sep 23 17:33:40 2010 -0700
   174.2 +++ b/src/share/classes/sun/util/resources/LocaleNames_zh_TW.properties	Fri Sep 24 16:41:32 2010 -0700
   174.3 @@ -227,6 +227,12 @@
   174.4  zh=\u4e2d\u6587
   174.5  zu=\u7956\u9b6f\u6587
   174.6  
   174.7 +# script names
   174.8 +# key is ISO 15924 script code
   174.9 +
  174.10 +Hans=\u7c21\u9ad4\u4e2d\u6587
  174.11 +Hant=\u7e41\u9ad4\u4e2d\u6587
  174.12 +
  174.13  # country names
  174.14  # key is ISO 3166 country code
  174.15  
   175.1 --- a/src/share/native/java/lang/System.c	Thu Sep 23 17:33:40 2010 -0700
   175.2 +++ b/src/share/native/java/lang/System.c	Fri Sep 24 16:41:32 2010 -0700
   175.3 @@ -80,6 +80,21 @@
   175.4          (*env)->DeleteLocalRef(env, jval); \
   175.5          (*env)->DeleteLocalRef(env, r); \
   175.6      } else ((void) 0)
   175.7 +#define REMOVEPROP(props, key) \
   175.8 +    if (1) { \
   175.9 +        jstring jkey = JNU_NewStringPlatform(env, key); \
  175.10 +        jobject r = (*env)->CallObjectMethod(env, props, removeID, jkey); \
  175.11 +        if ((*env)->ExceptionOccurred(env)) return NULL; \
  175.12 +        (*env)->DeleteLocalRef(env, jkey); \
  175.13 +        (*env)->DeleteLocalRef(env, r); \
  175.14 +    } else ((void) 0)
  175.15 +#define GETPROP(props, key, jret) \
  175.16 +    if (1) { \
  175.17 +        jstring jkey = JNU_NewStringPlatform(env, key); \
  175.18 +        jret = (*env)->CallObjectMethod(env, props, getPropID, jkey); \
  175.19 +        if ((*env)->ExceptionOccurred(env)) return NULL; \
  175.20 +        (*env)->DeleteLocalRef(env, jkey); \
  175.21 +    } else ((void) 0)
  175.22  
  175.23  #ifndef VENDOR /* Third party may overwrite this. */
  175.24  #define VENDOR "Sun Microsystems Inc."
  175.25 @@ -90,6 +105,60 @@
  175.26  #define JAVA_MAX_SUPPORTED_VERSION 51
  175.27  #define JAVA_MAX_SUPPORTED_MINOR_VERSION 0
  175.28  
  175.29 +static int fmtdefault; // boolean value
  175.30 +jobject fillI18nProps(JNIEnv *env, jobject props, char *baseKey,
  175.31 +                      char *platformDispVal, char *platformFmtVal,
  175.32 +                      jmethodID putID, jmethodID getPropID) {
  175.33 +    jstring jVMBaseVal = NULL;
  175.34 +
  175.35 +    GETPROP(props, baseKey, jVMBaseVal);
  175.36 +    if (jVMBaseVal) {
  175.37 +        // user specified the base property.  there's nothing to do here.
  175.38 +        (*env)->DeleteLocalRef(env, jVMBaseVal);
  175.39 +    } else {
  175.40 +        char buf[64];
  175.41 +        jstring jVMVal = NULL;
  175.42 +        const char *baseVal = "";
  175.43 +
  175.44 +        /* user.xxx base property */
  175.45 +        if (fmtdefault) {
  175.46 +            if (platformFmtVal) {
  175.47 +                PUTPROP(props, baseKey, platformFmtVal);
  175.48 +                baseVal = platformFmtVal;
  175.49 +            }
  175.50 +        } else {
  175.51 +            if (platformDispVal) {
  175.52 +                PUTPROP(props, baseKey, platformDispVal);
  175.53 +                baseVal = platformDispVal;
  175.54 +            }
  175.55 +        }
  175.56 +
  175.57 +        /* user.xxx.display property */
  175.58 +        jio_snprintf(buf, sizeof(buf), "%s.display", baseKey);
  175.59 +        GETPROP(props, buf, jVMVal);
  175.60 +        if (jVMVal == NULL) {
  175.61 +            if (platformDispVal && (strcmp(baseVal, platformDispVal) != 0)) {
  175.62 +                PUTPROP(props, buf, platformDispVal);
  175.63 +            }
  175.64 +        } else {
  175.65 +            (*env)->DeleteLocalRef(env, jVMVal);
  175.66 +        }
  175.67 +
  175.68 +        /* user.xxx.format property */
  175.69 +        jio_snprintf(buf, sizeof(buf), "%s.format", baseKey);
  175.70 +        GETPROP(props, buf, jVMVal);
  175.71 +        if (jVMVal == NULL) {
  175.72 +            if (platformFmtVal && (strcmp(baseVal, platformFmtVal) != 0)) {
  175.73 +                PUTPROP(props, buf, platformFmtVal);
  175.74 +            }
  175.75 +        } else {
  175.76 +            (*env)->DeleteLocalRef(env, jVMVal);
  175.77 +        }
  175.78 +    }
  175.79 +
  175.80 +    return NULL;
  175.81 +}
  175.82 +
  175.83  JNIEXPORT jobject JNICALL
  175.84  Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props)
  175.85  {
  175.86 @@ -99,6 +168,16 @@
  175.87                                            (*env)->GetObjectClass(env, props),
  175.88                                            "put",
  175.89              "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
  175.90 +    jmethodID removeID = (*env)->GetMethodID(env,
  175.91 +                                          (*env)->GetObjectClass(env, props),
  175.92 +                                          "remove",
  175.93 +            "(Ljava/lang/Object;)Ljava/lang/Object;");
  175.94 +    jmethodID getPropID = (*env)->GetMethodID(env,
  175.95 +                                          (*env)->GetObjectClass(env, props),
  175.96 +                                          "getProperty",
  175.97 +            "(Ljava/lang/String;)Ljava/lang/String;");
  175.98 +    jobject ret = NULL;
  175.99 +    jstring jVMVal = NULL;
 175.100  
 175.101      if (sprops == NULL || putID == NULL ) return NULL;
 175.102  
 175.103 @@ -218,7 +297,46 @@
 175.104          PUTPROP(props, "sun.desktop", sprops->desktop);
 175.105      }
 175.106  
 175.107 -    return JVM_InitProperties(env, props);
 175.108 +    /*
 175.109 +     * unset "user.language", "user.country", and "user.variant"
 175.110 +     * in order to tell whether the command line option "-DXXXX=YYYY" is
 175.111 +     * specified or not.  They will be reset in fillI18nProps() below.
 175.112 +     */
 175.113 +    REMOVEPROP(props, "user.language");
 175.114 +    REMOVEPROP(props, "user.country");
 175.115 +    REMOVEPROP(props, "user.variant");
 175.116 +    REMOVEPROP(props, "file.encoding");
 175.117 +
 175.118 +    ret = JVM_InitProperties(env, props);
 175.119 +
 175.120 +    /* Check the compatibility flag */
 175.121 +    GETPROP(props, "sun.locale.formatasdefault", jVMVal);
 175.122 +    if (jVMVal) {
 175.123 +        const char * val = (*env)->GetStringUTFChars(env, jVMVal, 0);
 175.124 +        fmtdefault = !strcmp(val, "true");
 175.125 +        (*env)->ReleaseStringUTFChars(env, jVMVal, val);
 175.126 +        (*env)->DeleteLocalRef(env, jVMVal);
 175.127 +    }
 175.128 +
 175.129 +    /* reconstruct i18n related properties */
 175.130 +    fillI18nProps(env, props, "user.language", sprops->display_language,
 175.131 +        sprops->format_language, putID, getPropID);
 175.132 +    fillI18nProps(env, props, "user.country",
 175.133 +        sprops->display_country, sprops->format_country, putID, getPropID);
 175.134 +    fillI18nProps(env, props, "user.variant",
 175.135 +        sprops->display_variant, sprops->format_variant, putID, getPropID);
 175.136 +    GETPROP(props, "file.encoding", jVMVal);
 175.137 +    if (jVMVal == NULL) {
 175.138 +        if (fmtdefault) {
 175.139 +            PUTPROP(props, "file.encoding", sprops->encoding);
 175.140 +        } else {
 175.141 +            PUTPROP(props, "file.encoding", sprops->sun_jnu_encoding);
 175.142 +        }
 175.143 +    } else {
 175.144 +        (*env)->DeleteLocalRef(env, jVMVal);
 175.145 +    }
 175.146 +
 175.147 +    return ret;
 175.148  }
 175.149  
 175.150  /*
   176.1 --- a/src/share/native/java/lang/java_props.h	Thu Sep 23 17:33:40 2010 -0700
   176.2 +++ b/src/share/native/java/lang/java_props.h	Fri Sep 24 16:41:32 2010 -0700
   176.3 @@ -53,8 +53,14 @@
   176.4      nchar *user_home;
   176.5  
   176.6      char *language;
   176.7 +    char *format_language;
   176.8 +    char *display_language;
   176.9      char *country;
  176.10 +    char *format_country;
  176.11 +    char *display_country;
  176.12      char *variant;
  176.13 +    char *format_variant;
  176.14 +    char *display_variant;
  176.15      char *encoding;
  176.16      char *sun_jnu_encoding;
  176.17      char *timezone;
   177.1 --- a/src/share/native/sun/java2d/cmm/lcms/LCMS.c	Thu Sep 23 17:33:40 2010 -0700
   177.2 +++ b/src/share/native/sun/java2d/cmm/lcms/LCMS.c	Fri Sep 24 16:41:32 2010 -0700
   177.3 @@ -24,11 +24,13 @@
   177.4   */
   177.5  
   177.6  #include <stdio.h>
   177.7 +#include <stdlib.h>
   177.8 +#include <memory.h>
   177.9  #include "sun_java2d_cmm_lcms_LCMS.h"
  177.10  #include "jni_util.h"
  177.11  #include "Trace.h"
  177.12  #include "Disposer.h"
  177.13 -#include "lcms.h"
  177.14 +#include "lcms2.h"
  177.15  
  177.16  
  177.17  #define ALIGNLONG(x) (((x)+3) & ~(3))         // Aligns to DWORD boundary
  177.18 @@ -38,10 +40,10 @@
  177.19  #else
  177.20  
  177.21  static
  177.22 -void AdjustEndianess32(LPBYTE pByte)
  177.23 +void AdjustEndianess32(cmsUInt8Number *pByte)
  177.24  {
  177.25 -    BYTE temp1;
  177.26 -    BYTE temp2;
  177.27 +    cmsUInt8Number temp1;
  177.28 +    cmsUInt8Number temp2;
  177.29  
  177.30      temp1 = *pByte++;
  177.31      temp2 = *pByte++;
  177.32 @@ -57,11 +59,11 @@
  177.33  // big endian notation.
  177.34  
  177.35  static
  177.36 -icInt32Number TransportValue32(icInt32Number Value)
  177.37 +cmsInt32Number TransportValue32(cmsInt32Number Value)
  177.38  {
  177.39 -    icInt32Number Temp = Value;
  177.40 +    cmsInt32Number Temp = Value;
  177.41  
  177.42 -    AdjustEndianess32((LPBYTE) &Temp);
  177.43 +    AdjustEndianess32((cmsUInt8Number*) &Temp);
  177.44      return Temp;
  177.45  }
  177.46  
  177.47 @@ -84,7 +86,13 @@
  177.48  /* Default temp profile list size */
  177.49  #define DF_ICC_BUF_SIZE 32
  177.50  
  177.51 -#define ERR_MSG_SIZE 20
  177.52 +#define ERR_MSG_SIZE 256
  177.53 +
  177.54 +#ifdef _MSC_VER
  177.55 +# ifndef snprintf
  177.56 +#       define snprintf  _snprintf
  177.57 +# endif
  177.58 +#endif
  177.59  
  177.60  typedef union storeID_s {    /* store SProfile stuff in a Java Long */
  177.61      cmsHPROFILE pf;
  177.62 @@ -93,6 +101,11 @@
  177.63      jlong j;
  177.64  } storeID_t, *storeID_p;
  177.65  
  177.66 +typedef union {
  177.67 +    cmsTagSignature cms;
  177.68 +    jint j;
  177.69 +} TagSignature_t, *TagSignature_p;
  177.70 +
  177.71  static jfieldID Trans_profileIDs_fID;
  177.72  static jfieldID Trans_renderType_fID;
  177.73  static jfieldID Trans_ID_fID;
  177.74 @@ -108,21 +121,26 @@
  177.75  
  177.76  JavaVM *javaVM;
  177.77  
  177.78 -int errorHandler(int errorCode, const char *errorText) {
  177.79 +void errorHandler(cmsContext ContextID, cmsUInt32Number errorCode,
  177.80 +                  const char *errorText) {
  177.81      JNIEnv *env;
  177.82      char errMsg[ERR_MSG_SIZE];
  177.83 -    /* We can safely use sprintf here because error message has limited size */
  177.84 -    sprintf(errMsg, "LCMS error %d", errorCode);
  177.85 +
  177.86 +    int count = snprintf(errMsg, ERR_MSG_SIZE,
  177.87 +                          "LCMS error %d: %s", errorCode, errorText);
  177.88 +    if (count < 0 || count >= ERR_MSG_SIZE) {
  177.89 +        count = ERR_MSG_SIZE - 1;
  177.90 +    }
  177.91 +    errMsg[count] = 0;
  177.92  
  177.93      (*javaVM)->AttachCurrentThread(javaVM, (void**)&env, NULL);
  177.94      JNU_ThrowByName(env, "java/awt/color/CMMException", errMsg);
  177.95 -    return 1;
  177.96  }
  177.97  
  177.98  JNIEXPORT int JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
  177.99      javaVM = jvm;
 177.100  
 177.101 -    cmsSetErrorHandler(errorHandler);
 177.102 +    cmsSetLogErrorHandler(errorHandler);
 177.103      return JNI_VERSION_1_6;
 177.104  }
 177.105  
 177.106 @@ -141,11 +159,10 @@
 177.107   */
 177.108  JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
 177.109    (JNIEnv *env, jclass cls, jlongArray profileIDs, jint renderType,
 177.110 -   jobject disposerRef)
 177.111 +   jint inFormatter, jint outFormatter, jobject disposerRef)
 177.112  {
 177.113 -    LPLCMSICCPROFILE _iccArray[DF_ICC_BUF_SIZE];
 177.114 -    LPLCMSICCPROFILE *iccArray = &_iccArray[0];
 177.115 -    cmsHTRANSFORM transform;
 177.116 +    cmsHPROFILE _iccArray[DF_ICC_BUF_SIZE];
 177.117 +    cmsHPROFILE *iccArray = &_iccArray[0];
 177.118      storeID_t sTrans;
 177.119      int i, j, size;
 177.120      jlong* ids;
 177.121 @@ -154,17 +171,19 @@
 177.122      ids = (*env)->GetPrimitiveArrayCritical(env, profileIDs, 0);
 177.123  
 177.124      if (DF_ICC_BUF_SIZE < size*2) {
 177.125 -        iccArray = (LPLCMSICCPROFILE*) malloc(
 177.126 -            size*2*sizeof(LPLCMSICCPROFILE));
 177.127 +        iccArray = (cmsHPROFILE*) malloc(
 177.128 +            size*2*sizeof(cmsHPROFILE));
 177.129          if (iccArray == NULL) {
 177.130              J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL");
 177.131 -            return NULL;
 177.132 +            return 0L;
 177.133          }
 177.134      }
 177.135  
 177.136      j = 0;
 177.137      for (i = 0; i < size; i++) {
 177.138 -        LPLCMSICCPROFILE icc;
 177.139 +        cmsHPROFILE icc;
 177.140 +        cmsColorSpaceSignature cs;
 177.141 +
 177.142          sTrans.j = ids[i];
 177.143          icc = sTrans.pf;
 177.144          iccArray[j++] = icc;
 177.145 @@ -172,16 +191,17 @@
 177.146          /* Middle non-abstract profiles should be doubled before passing to
 177.147           * the cmsCreateMultiprofileTransform function
 177.148           */
 177.149 +
 177.150 +        cs = cmsGetColorSpace(icc);
 177.151          if (size > 2 && i != 0 && i != size - 1 &&
 177.152 -            icc->ColorSpace != icSigXYZData &&
 177.153 -            icc->ColorSpace != icSigLabData)
 177.154 +            cs != cmsSigXYZData && cs != cmsSigLabData)
 177.155          {
 177.156              iccArray[j++] = icc;
 177.157          }
 177.158      }
 177.159  
 177.160      sTrans.xf = cmsCreateMultiprofileTransform(iccArray, j,
 177.161 -        0, 0, renderType, 0);
 177.162 +        inFormatter, outFormatter, renderType, 0);
 177.163  
 177.164      (*env)->ReleasePrimitiveArrayCritical(env, profileIDs, ids, 0);
 177.165  
 177.166 @@ -190,12 +210,13 @@
 177.167                                         "sTrans.xf == NULL");
 177.168          JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.169                          "Cannot get color transform");
 177.170 +    } else {
 177.171 +        Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j);
 177.172      }
 177.173  
 177.174      if (iccArray != &_iccArray[0]) {
 177.175          free(iccArray);
 177.176      }
 177.177 -    Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j);
 177.178      return sTrans.j;
 177.179  }
 177.180  
 177.181 @@ -215,7 +236,8 @@
 177.182      dataArray = (*env)->GetByteArrayElements (env, data, 0);
 177.183      dataSize = (*env)->GetArrayLength (env, data);
 177.184  
 177.185 -    sProf.pf = cmsOpenProfileFromMem((LPVOID)dataArray, (DWORD) dataSize);
 177.186 +    sProf.pf = cmsOpenProfileFromMem((const void *)dataArray,
 177.187 +                                     (cmsUInt32Number) dataSize);
 177.188  
 177.189      (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 177.190  
 177.191 @@ -254,20 +276,17 @@
 177.192  JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSize
 177.193    (JNIEnv *env, jobject obj, jlong id)
 177.194  {
 177.195 -    LPLCMSICCPROFILE Icc;
 177.196      storeID_t sProf;
 177.197 -    unsigned char pfSize[4];
 177.198 +    cmsUInt32Number pfSize = 0;
 177.199 +    sProf.j = id;
 177.200  
 177.201 -    sProf.j = id;
 177.202 -    Icc = (LPLCMSICCPROFILE) sProf.pf;
 177.203 -    Icc -> Seek(Icc, 0);
 177.204 -    Icc -> Read(pfSize, 4, 1, Icc);
 177.205 -
 177.206 -    /* TODO: It's a correct but non-optimal for BE machines code, so should
 177.207 -     * be special cased for them
 177.208 -     */
 177.209 -    return (pfSize[0]<<24) | (pfSize[1]<<16) | (pfSize[2]<<8) |
 177.210 -        pfSize[3];
 177.211 +    if (cmsSaveProfileToMem(sProf.pf, NULL, &pfSize) && ((jint)pfSize > 0)) {
 177.212 +        return (jint)pfSize;
 177.213 +    } else {
 177.214 +      JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.215 +                      "Can not access specified profile.");
 177.216 +        return -1;
 177.217 +    }
 177.218  }
 177.219  
 177.220  /*
 177.221 @@ -278,29 +297,46 @@
 177.222  JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
 177.223    (JNIEnv *env, jobject obj, jlong id, jbyteArray data)
 177.224  {
 177.225 -    LPLCMSICCPROFILE Icc;
 177.226      storeID_t sProf;
 177.227 -    unsigned char pfSize[4];
 177.228      jint size;
 177.229      jbyte* dataArray;
 177.230 +    cmsUInt32Number pfSize = 0;
 177.231 +    cmsBool status;
 177.232  
 177.233      sProf.j = id;
 177.234 -    Icc = (LPLCMSICCPROFILE) sProf.pf;
 177.235 -    Icc -> Seek(Icc, 0);
 177.236 -    Icc -> Read(pfSize, 4, 1, Icc);
 177.237 +
 177.238 +    // determine actual profile size
 177.239 +    if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize)) {
 177.240 +        JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.241 +                        "Can not access specified profile.");
 177.242 +        return;
 177.243 +    }
 177.244 +
 177.245 +    // verify java buffer capacity
 177.246 +    size = (*env)->GetArrayLength(env, data);
 177.247 +    if (0 >= size || pfSize > (cmsUInt32Number)size) {
 177.248 +        JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.249 +                        "Insufficient buffer capacity.");
 177.250 +        return;
 177.251 +    }
 177.252  
 177.253      dataArray = (*env)->GetByteArrayElements (env, data, 0);
 177.254 -    Icc->Seek(Icc, 0);
 177.255  
 177.256 -    /* TODO: It's a correct but non-optimal for BE machines code, so should
 177.257 -     * be special cased for them
 177.258 -     */
 177.259 -    Icc->Read(dataArray, 1,
 177.260 -              (pfSize[0]<<24) | (pfSize[1]<<16) | (pfSize[2]<<8) | pfSize[3],
 177.261 -              Icc);
 177.262 +    status = cmsSaveProfileToMem(sProf.pf, dataArray, &pfSize);
 177.263 +
 177.264      (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 177.265 +
 177.266 +    if (!status) {
 177.267 +        JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.268 +                        "Can not access specified profile.");
 177.269 +        return;
 177.270 +    }
 177.271  }
 177.272  
 177.273 +/* Get profile header info */
 177.274 +cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
 177.275 +cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
 177.276 +
 177.277  /*
 177.278   * Class:     sun_java2d_cmm_lcms_LCMS
 177.279   * Method:    getTagSize
 177.280 @@ -309,24 +345,21 @@
 177.281  JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagSize
 177.282    (JNIEnv *env, jobject obj, jlong id, jint tagSig)
 177.283  {
 177.284 -    LPLCMSICCPROFILE Icc;
 177.285      storeID_t sProf;
 177.286 -    int i;
 177.287 -    jint result;
 177.288 +    TagSignature_t sig;
 177.289 +    jint result = -1;
 177.290  
 177.291      sProf.j = id;
 177.292 -    Icc = (LPLCMSICCPROFILE) sProf.pf;
 177.293 +    sig.j = tagSig;
 177.294  
 177.295      if (tagSig == SigHead) {
 177.296 -        result = sizeof(icHeader);
 177.297 +        result = sizeof(cmsICCHeader);
 177.298      } else {
 177.299 -        i =  _cmsSearchTag(Icc, tagSig, FALSE);
 177.300 -        if (i >= 0) {
 177.301 -            result = Icc->TagSizes[i];
 177.302 +      if (cmsIsTag(sProf.pf, sig.cms)) {
 177.303 +            result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0);
 177.304          } else {
 177.305              JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.306                              "ICC profile tag not found");
 177.307 -            result = -1;
 177.308          }
 177.309      }
 177.310  
 177.311 @@ -341,43 +374,83 @@
 177.312  JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
 177.313    (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
 177.314  {
 177.315 -    LPLCMSICCPROFILE Icc;
 177.316      storeID_t sProf;
 177.317 +    TagSignature_t sig;
 177.318 +    cmsInt32Number tagSize;
 177.319 +
 177.320      jbyte* dataArray;
 177.321 -    int i, tagSize;
 177.322 +    jint bufSize;
 177.323  
 177.324      sProf.j = id;
 177.325 -    Icc = (LPLCMSICCPROFILE) sProf.pf;
 177.326 +    sig.j = tagSig;
 177.327  
 177.328      if (tagSig == SigHead) {
 177.329 +        cmsBool status;
 177.330 +
 177.331 +        bufSize =(*env)->GetArrayLength(env, data);
 177.332 +
 177.333 +        if (bufSize < sizeof(cmsICCHeader)) {
 177.334 +           JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.335 +                            "Insufficient buffer capacity");
 177.336 +           return;
 177.337 +        }
 177.338 +
 177.339          dataArray = (*env)->GetByteArrayElements (env, data, 0);
 177.340 -        tagSize =(*env)->GetArrayLength(env, data);
 177.341 -        Icc -> Seek(Icc, 0);
 177.342 -        Icc -> Read(dataArray, sizeof(icHeader), 1, Icc);
 177.343 +
 177.344 +        if (dataArray == NULL) {
 177.345 +           JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.346 +                            "Unable to get buffer");
 177.347 +           return;
 177.348 +        }
 177.349 +
 177.350 +        status = _getHeaderInfo(sProf.pf, dataArray, bufSize);
 177.351 +
 177.352          (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 177.353 +
 177.354 +        if (!status) {
 177.355 +            JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.356 +                            "ICC Profile header not found");
 177.357 +        }
 177.358 +
 177.359          return;
 177.360      }
 177.361  
 177.362 -
 177.363 -    i =  _cmsSearchTag(Icc, tagSig, FALSE);
 177.364 -    if (i >=0) {
 177.365 -        tagSize = Icc->TagSizes[i];
 177.366 -        dataArray = (*env)->GetByteArrayElements (env, data, 0);
 177.367 -        Icc->Seek(Icc, Icc->TagOffsets[i]);
 177.368 -        Icc->Read(dataArray, 1, tagSize, Icc);
 177.369 -        (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 177.370 +    if (cmsIsTag(sProf.pf, sig.cms)) {
 177.371 +        tagSize = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0);
 177.372 +    } else {
 177.373 +        JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.374 +                        "ICC profile tag not found");
 177.375          return;
 177.376      }
 177.377  
 177.378 -    JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.379 -                    "ICC profile tag not found");
 177.380 +    // verify data buffer capacity
 177.381 +    bufSize = (*env)->GetArrayLength(env, data);
 177.382 +
 177.383 +    if (tagSize < 0 || 0 > bufSize || tagSize > bufSize) {
 177.384 +        JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.385 +                        "Insufficient buffer capacity.");
 177.386 +        return;
 177.387 +    }
 177.388 +
 177.389 +    dataArray = (*env)->GetByteArrayElements (env, data, 0);
 177.390 +
 177.391 +    if (dataArray == NULL) {
 177.392 +        JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.393 +                        "Unable to get buffer");
 177.394 +        return;
 177.395 +    }
 177.396 +
 177.397 +    bufSize = cmsReadRawTag(sProf.pf, sig.cms, dataArray, tagSize);
 177.398 +
 177.399 +    (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 177.400 +
 177.401 +    if (bufSize != tagSize) {
 177.402 +        JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.403 +                        "Can not get tag data.");
 177.404 +    }
 177.405      return;
 177.406  }
 177.407  
 177.408 -// Modify data for a tag in a profile
 177.409 -LCMSBOOL LCMSEXPORT _cmsModifyTagData(cmsHPROFILE hProfile,
 177.410 -                                 icTagSignature sig, void *data, size_t size);
 177.411 -
 177.412  /*
 177.413   * Class:     sun_java2d_cmm_lcms_LCMS
 177.414   * Method:    setTagData
 177.415 @@ -386,23 +459,32 @@
 177.416  JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData
 177.417    (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
 177.418  {
 177.419 -    cmsHPROFILE profile;
 177.420      storeID_t sProf;
 177.421 +    TagSignature_t sig;
 177.422 +    cmsBool status;
 177.423      jbyte* dataArray;
 177.424      int tagSize;
 177.425  
 177.426 +    sProf.j = id;
 177.427 +    sig.j = tagSig;
 177.428 +
 177.429 +
 177.430 +    tagSize =(*env)->GetArrayLength(env, data);
 177.431 +
 177.432 +    dataArray = (*env)->GetByteArrayElements(env, data, 0);
 177.433 +
 177.434      if (tagSig == SigHead) {
 177.435 -        J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_setTagData on icSigHead not "
 177.436 -                      "permitted");
 177.437 -        return;
 177.438 +        status = _setHeaderInfo(sProf.pf, dataArray, tagSize);
 177.439 +    } else {
 177.440 +        status = cmsWriteRawTag(sProf.pf, sig.cms, dataArray, tagSize);
 177.441      }
 177.442  
 177.443 -    sProf.j = id;
 177.444 -    profile = (cmsHPROFILE) sProf.pf;
 177.445 -    dataArray = (*env)->GetByteArrayElements(env, data, 0);
 177.446 -    tagSize =(*env)->GetArrayLength(env, data);
 177.447 -    _cmsModifyTagData(profile, (icTagSignature) tagSig, dataArray, tagSize);
 177.448      (*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
 177.449 +
 177.450 +    if (!status) {
 177.451 +        JNU_ThrowByName(env, "java/awt/color/CMMException",
 177.452 +                        "Can not write tag data.");
 177.453 +    }
 177.454  }
 177.455  
 177.456  void* getILData (JNIEnv *env, jobject img, jint* pDataType,
 177.457 @@ -456,7 +538,7 @@
 177.458    (JNIEnv *env, jclass obj, jobject trans, jobject src, jobject dst)
 177.459  {
 177.460      storeID_t sTrans;
 177.461 -    int size, inFmt, outFmt, srcDType, dstDType, outSize, renderType;
 177.462 +    int inFmt, outFmt, srcDType, dstDType;
 177.463      int srcOffset, srcNextRowOffset, dstOffset, dstNextRowOffset;
 177.464      int width, height, i;
 177.465      void* inputBuffer;
 177.466 @@ -483,8 +565,6 @@
 177.467      }
 177.468  #endif
 177.469      sTrans.j = (*env)->GetLongField (env, trans, Trans_ID_fID);
 177.470 -    cmsChangeBuffersFormat(sTrans.xf, inFmt, outFmt);
 177.471 -
 177.472  
 177.473      if (sTrans.xf == NULL) {
 177.474          J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_colorConvert: transform == NULL");
 177.475 @@ -565,190 +645,54 @@
 177.476      PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
 177.477  }
 177.478  
 177.479 -LCMSBOOL _cmsModifyTagData(cmsHPROFILE hProfile, icTagSignature sig,
 177.480 -                       void *data, size_t size)
 177.481 +cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
 177.482  {
 177.483 -    LCMSBOOL isNew;
 177.484 -    int i, idx, delta, count;
 177.485 -    LPBYTE padChars[3] = {0, 0, 0};
 177.486 -    LPBYTE beforeBuf, afterBuf, ptr;
 177.487 -    size_t beforeSize, afterSize;
 177.488 -    icUInt32Number profileSize, temp;
 177.489 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
 177.490 +  cmsUInt32Number pfSize = 0;
 177.491 +  cmsUInt8Number* pfBuffer = NULL;
 177.492 +  cmsBool status = FALSE;
 177.493  
 177.494 -    isNew = FALSE;
 177.495 -    idx = _cmsSearchTag(Icc, sig, FALSE);
 177.496 -    if (idx < 0) {
 177.497 -        isNew = TRUE;
 177.498 -        idx = Icc->TagCount++;
 177.499 -        if (Icc->TagCount >= MAX_TABLE_TAG) {
 177.500 -            J2dRlsTraceLn1(J2D_TRACE_ERROR, "_cmsModifyTagData: Too many tags "
 177.501 -                           "(%d)\n", Icc->TagCount);
 177.502 -            Icc->TagCount = MAX_TABLE_TAG-1;
 177.503 -            return FALSE;
 177.504 -        }
 177.505 -    }
 177.506 +  if (!cmsSaveProfileToMem(pf, NULL, &pfSize) ||
 177.507 +      pfSize < sizeof(cmsICCHeader) ||
 177.508 +      bufferSize < sizeof(cmsICCHeader))
 177.509 +  {
 177.510 +    return FALSE;
 177.511 +  }
 177.512  
 177.513 -    /* Read in size from header */
 177.514 -    Icc->Seek(Icc, 0);
 177.515 -    Icc->Read(&profileSize, sizeof(icUInt32Number), 1, Icc);
 177.516 -    AdjustEndianess32((LPBYTE) &profileSize);
 177.517 +  pfBuffer = malloc(pfSize);
 177.518 +  if (pfBuffer == NULL) {
 177.519 +    return FALSE;
 177.520 +  }
 177.521  
 177.522 -    /* Compute the change in profile size */
 177.523 -    if (isNew) {
 177.524 -        delta = sizeof(icTag) + ALIGNLONG(size);
 177.525 -    } else {
 177.526 -        delta = ALIGNLONG(size) - ALIGNLONG(Icc->TagSizes[idx]);
 177.527 -    }
 177.528 -    /* Add tag to internal structures */
 177.529 -    ptr = malloc(size);
 177.530 -    if (ptr == NULL) {
 177.531 -        if(isNew) {
 177.532 -            Icc->TagCount--;
 177.533 -        }
 177.534 -        J2dRlsTraceLn(J2D_TRACE_ERROR, "_cmsModifyTagData: ptr == NULL");
 177.535 -        return FALSE;
 177.536 -    }
 177.537 +  // load raw profile data into the buffer
 177.538 +  if (cmsSaveProfileToMem(pf, pfBuffer, &pfSize)) {
 177.539 +    memcpy(pBuffer, pfBuffer, sizeof(cmsICCHeader));
 177.540 +    status = TRUE;
 177.541 +  }
 177.542 +  free(pfBuffer);
 177.543 +  return status;
 177.544 +}
 177.545  
 177.546 -    /* We change the size of Icc here only if we know it'll actually
 177.547 -     * grow: if Icc is about to shrink we must wait until we've read
 177.548 -     * the previous data.  */
 177.549 -    if (delta > 0) {
 177.550 -        if (!Icc->Grow(Icc, delta)) {
 177.551 -            free(ptr);
 177.552 -            if(isNew) {
 177.553 -                Icc->TagCount--;
 177.554 -            }
 177.555 -            J2dRlsTraceLn(J2D_TRACE_ERROR,
 177.556 -                          "_cmsModifyTagData: Icc->Grow() == FALSE");
 177.557 -            return FALSE;
 177.558 -        }
 177.559 -    }
 177.560 +cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
 177.561 +{
 177.562 +  cmsICCHeader pfHeader = { 0 };
 177.563  
 177.564 -    /* Compute size of tag data before/after the modified tag */
 177.565 -    beforeSize = ((isNew)?profileSize:Icc->TagOffsets[idx]) -
 177.566 -                 Icc->TagOffsets[0];
 177.567 -    if (Icc->TagCount == (idx + 1)) {
 177.568 -        afterSize = 0;
 177.569 -    } else {
 177.570 -        afterSize = profileSize - Icc->TagOffsets[idx+1];
 177.571 -    }
 177.572 -    /* Make copies of the data before/after the modified tag */
 177.573 -    if (beforeSize > 0) {
 177.574 -        beforeBuf = malloc(beforeSize);
 177.575 -        if (!beforeBuf) {
 177.576 -            if(isNew) {
 177.577 -                Icc->TagCount--;
 177.578 -            }
 177.579 -            free(ptr);
 177.580 -            J2dRlsTraceLn(J2D_TRACE_ERROR,
 177.581 -                          "_cmsModifyTagData: beforeBuf == NULL");
 177.582 -            return FALSE;
 177.583 -        }
 177.584 -        Icc->Seek(Icc, Icc->TagOffsets[0]);
 177.585 -        Icc->Read(beforeBuf, beforeSize, 1, Icc);
 177.586 -    }
 177.587 +  if (pBuffer == NULL || bufferSize < sizeof(cmsICCHeader)) {
 177.588 +    return FALSE;
 177.589 +  }
 177.590  
 177.591 -    if (afterSize > 0) {
 177.592 -        afterBuf = malloc(afterSize);
 177.593 -        if (!afterBuf) {
 177.594 -            free(ptr);
 177.595 -            if(isNew) {
 177.596 -                Icc->TagCount--;
 177.597 -            }
 177.598 -            if (beforeSize > 0) {
 177.599 -                free(beforeBuf);
 177.600 -            }
 177.601 -            J2dRlsTraceLn(J2D_TRACE_ERROR,
 177.602 -                          "_cmsModifyTagData: afterBuf == NULL");
 177.603 -            return FALSE;
 177.604 -        }
 177.605 -        Icc->Seek(Icc, Icc->TagOffsets[idx+1]);
 177.606 -        Icc->Read(afterBuf, afterSize, 1, Icc);
 177.607 -    }
 177.608 +  memcpy(&pfHeader, pBuffer, sizeof(cmsICCHeader));
 177.609  
 177.610 -    CopyMemory(ptr, data, size);
 177.611 -    Icc->TagSizes[idx] = size;
 177.612 -    Icc->TagNames[idx] = sig;
 177.613 -    if (Icc->TagPtrs[idx]) {
 177.614 -        free(Icc->TagPtrs[idx]);
 177.615 -    }
 177.616 -    Icc->TagPtrs[idx] = ptr;
 177.617 -    if (isNew) {
 177.618 -        Icc->TagOffsets[idx] = profileSize;
 177.619 -    }
 177.620 +  // now set header fields, which we can access using the lcms2 public API
 177.621 +  cmsSetHeaderFlags(pf, pfHeader.flags);
 177.622 +  cmsSetHeaderManufacturer(pf, pfHeader.manufacturer);
 177.623 +  cmsSetHeaderModel(pf, pfHeader.model);
 177.624 +  cmsSetHeaderAttributes(pf, pfHeader.attributes);
 177.625 +  cmsSetHeaderProfileID(pf, (cmsUInt8Number*)&(pfHeader.profileID));
 177.626 +  cmsSetHeaderRenderingIntent(pf, pfHeader.renderingIntent);
 177.627 +  cmsSetPCS(pf, pfHeader.pcs);
 177.628 +  cmsSetColorSpace(pf, pfHeader.colorSpace);
 177.629 +  cmsSetDeviceClass(pf, pfHeader.deviceClass);
 177.630 +  cmsSetEncodedICCversion(pf, pfHeader.version);
 177.631  
 177.632 -
 177.633 -    /* Update the profile size in the header */
 177.634 -    profileSize += delta;
 177.635 -    Icc->Seek(Icc, 0);
 177.636 -    temp = TransportValue32(profileSize);
 177.637 -    Icc->Write(Icc, sizeof(icUInt32Number), &temp);
 177.638 -
 177.639 -    /* Shrink Icc, if needed.  */
 177.640 -    if (delta < 0) {
 177.641 -        if (!Icc->Grow(Icc, delta)) {
 177.642 -            free(ptr);
 177.643 -            if(isNew) {
 177.644 -                Icc->TagCount--;
 177.645 -            }
 177.646 -            J2dRlsTraceLn(J2D_TRACE_ERROR,
 177.647 -                          "_cmsModifyTagData: Icc->Grow() == FALSE");
 177.648 -            return FALSE;
 177.649 -        }
 177.650 -    }
 177.651 -
 177.652 -    /* Adjust tag offsets: if the tag is new, we must account
 177.653 -       for the new tag table entry; otherwise, only those tags after
 177.654 -       the modified tag are changed (by delta) */
 177.655 -    if (isNew) {
 177.656 -        for (i = 0; i < Icc->TagCount; ++i) {
 177.657 -            Icc->TagOffsets[i] += sizeof(icTag);
 177.658 -        }
 177.659 -    } else {
 177.660 -        for (i = idx+1; i < Icc->TagCount; ++i) {
 177.661 -            Icc->TagOffsets[i] += delta;
 177.662 -        }
 177.663 -    }
 177.664 -
 177.665 -    /* Write out a new tag table */
 177.666 -    count = 0;
 177.667 -    for (i = 0; i < Icc->TagCount; ++i) {
 177.668 -        if (Icc->TagNames[i] != 0) {
 177.669 -            ++count;
 177.670 -        }
 177.671 -    }
 177.672 -    Icc->Seek(Icc, sizeof(icHeader));
 177.673 -    temp = TransportValue32(count);
 177.674 -    Icc->Write(Icc, sizeof(icUInt32Number), &temp);
 177.675 -
 177.676 -    for (i = 0; i < Icc->TagCount; ++i) {
 177.677 -        if (Icc->TagNames[i] != 0) {
 177.678 -            icTag tag;
 177.679 -            tag.sig = TransportValue32(Icc->TagNames[i]);
 177.680 -            tag.offset = TransportValue32((icInt32Number) Icc->TagOffsets[i]);
 177.681 -            tag.size = TransportValue32((icInt32Number) Icc->TagSizes[i]);
 177.682 -            Icc->Write(Icc, sizeof(icTag), &tag);
 177.683 -        }
 177.684 -    }
 177.685 -
 177.686 -    /* Write unchanged data before the modified tag */
 177.687 -    if (beforeSize > 0) {
 177.688 -        Icc->Write(Icc, beforeSize, beforeBuf);
 177.689 -        free(beforeBuf);
 177.690 -    }
 177.691 -
 177.692 -    /* Write modified tag data */
 177.693 -    Icc->Write(Icc, size, data);
 177.694 -    if (size % 4) {
 177.695 -        Icc->Write(Icc, 4 - (size % 4), padChars);
 177.696 -    }
 177.697 -
 177.698 -    /* Write unchanged data after the modified tag */
 177.699 -    if (afterSize > 0) {
 177.700 -        Icc->Write(Icc, afterSize, afterBuf);
 177.701 -        free(afterBuf);
 177.702 -    }
 177.703 -
 177.704 -    return TRUE;
 177.705 +  return TRUE;
 177.706  }
   178.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmscam02.c	Thu Sep 23 17:33:40 2010 -0700
   178.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmscam02.c	Fri Sep 24 16:41:32 2010 -0700
   178.3 @@ -27,9 +27,10 @@
   178.4  // However, the following notice accompanied the original version of this
   178.5  // file:
   178.6  //
   178.7 +//---------------------------------------------------------------------------------
   178.8  //
   178.9 -//  Little cms
  178.10 -//  Copyright (C) 1998-2007 Marti Maria
  178.11 +//  Little Color Management System
  178.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  178.13  //
  178.14  // Permission is hereby granted, free of charge, to any person obtaining
  178.15  // a copy of this software and associated documentation files (the "Software"),
  178.16 @@ -48,69 +49,65 @@
  178.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  178.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  178.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  178.20 +//
  178.21 +//---------------------------------------------------------------------------------
  178.22 +//
  178.23  
  178.24 -
  178.25 +#include "lcms2_internal.h"
  178.26  
  178.27  // CIECAM 02 appearance model. Many thanks to Jordi Vilar for the debugging.
  178.28  
  178.29 -#include "lcms.h"
  178.30 -
  178.31 -
  178.32 -LCMSAPI LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC);
  178.33 -LCMSAPI void       LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel);
  178.34 -LCMSAPI void       LCMSEXPORT cmsCIECAM02Forward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh pOut);
  178.35 -LCMSAPI void       LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn,    LPcmsCIEXYZ pOut);
  178.36 -
  178.37 -
  178.38  // ---------- Implementation --------------------------------------------
  178.39  
  178.40  typedef struct  {
  178.41  
  178.42 -    double XYZ[3];
  178.43 -    double RGB[3];
  178.44 -    double RGBc[3];
  178.45 -    double RGBp[3];
  178.46 -    double RGBpa[3];
  178.47 -    double a, b, h, e, H, A, J, Q, s, t, C, M;
  178.48 -    double abC[2];
  178.49 -    double abs[2];
  178.50 -    double abM[2];
  178.51 +    cmsFloat64Number XYZ[3];
  178.52 +    cmsFloat64Number RGB[3];
  178.53 +    cmsFloat64Number RGBc[3];
  178.54 +    cmsFloat64Number RGBp[3];
  178.55 +    cmsFloat64Number RGBpa[3];
  178.56 +    cmsFloat64Number a, b, h, e, H, A, J, Q, s, t, C, M;
  178.57 +    cmsFloat64Number abC[2];
  178.58 +    cmsFloat64Number abs[2];
  178.59 +    cmsFloat64Number abM[2];
  178.60  
  178.61 -} CAM02COLOR, *LPCAM02COLOR;
  178.62 +} CAM02COLOR;
  178.63  
  178.64  typedef struct  {
  178.65  
  178.66      CAM02COLOR adoptedWhite;
  178.67 -    double LA, Yb;
  178.68 -    double F, c, Nc;
  178.69 -    int surround;
  178.70 -    double n, Nbb, Ncb, z, FL, D;
  178.71 +    cmsFloat64Number LA, Yb;
  178.72 +    cmsFloat64Number F, c, Nc;
  178.73 +    cmsUInt32Number surround;
  178.74 +    cmsFloat64Number n, Nbb, Ncb, z, FL, D;
  178.75  
  178.76 -} cmsCIECAM02, *LPcmsCIECAM02;
  178.77 +       cmsContext ContextID;
  178.78 +
  178.79 +} cmsCIECAM02;
  178.80  
  178.81  
  178.82  static
  178.83 -double compute_n(LPcmsCIECAM02 pMod)
  178.84 +cmsFloat64Number compute_n(cmsCIECAM02* pMod)
  178.85  {
  178.86 -    return(pMod -> Yb / pMod -> adoptedWhite.XYZ[1]);
  178.87 +    return (pMod -> Yb / pMod -> adoptedWhite.XYZ[1]);
  178.88  }
  178.89  
  178.90  static
  178.91 -double compute_z(LPcmsCIECAM02 pMod)
  178.92 +cmsFloat64Number compute_z(cmsCIECAM02* pMod)
  178.93  {
  178.94 -    return(1.48 + pow(pMod -> n, 0.5));
  178.95 +    return (1.48 + pow(pMod -> n, 0.5));
  178.96  }
  178.97  
  178.98  static
  178.99 -double computeNbb(LPcmsCIECAM02 pMod)
 178.100 +cmsFloat64Number computeNbb(cmsCIECAM02* pMod)
 178.101  {
 178.102 -    return(0.725 * pow((1.0 / pMod -> n), 0.2));
 178.103 +    return (0.725 * pow((1.0 / pMod -> n), 0.2));
 178.104  }
 178.105  
 178.106  static
 178.107 -double computeFL(LPcmsCIECAM02 pMod)
 178.108 +cmsFloat64Number computeFL(cmsCIECAM02* pMod)
 178.109  {
 178.110 -    double k, FL;
 178.111 +    cmsFloat64Number k, FL;
 178.112  
 178.113      k = 1.0 / ((5.0 * pMod->LA) + 1.0);
 178.114      FL = 0.2 * pow(k, 4.0) * (5.0 * pMod->LA) + 0.1 *
 178.115 @@ -121,9 +118,9 @@
 178.116  }
 178.117  
 178.118  static
 178.119 -double computeD(LPcmsCIECAM02 pMod)
 178.120 +cmsFloat64Number computeD(cmsCIECAM02* pMod)
 178.121  {
 178.122 -    double D;
 178.123 +    cmsFloat64Number D;
 178.124  
 178.125      D = pMod->F - (1.0/3.6)*(exp(((-pMod ->LA-42) / 92.0)));
 178.126  
 178.127 @@ -142,9 +139,10 @@
 178.128  }
 178.129  
 178.130  static
 178.131 -CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, LPcmsCIECAM02 pMod)
 178.132 +CAM02COLOR ChromaticAdaptation(CAM02COLOR clr, cmsCIECAM02* pMod)
 178.133  {
 178.134 -    int i;
 178.135 +    cmsUInt32Number i;
 178.136 +
 178.137      for (i = 0; i < 3; i++) {
 178.138          clr.RGBc[i] = ((pMod -> adoptedWhite.XYZ[1] *
 178.139              (pMod->D / pMod -> adoptedWhite.RGB[i])) +
 178.140 @@ -156,11 +154,9 @@
 178.141  
 178.142  
 178.143  static
 178.144 -CAM02COLOR CAT02toHPE (CAM02COLOR clr)
 178.145 +CAM02COLOR CAT02toHPE(CAM02COLOR clr)
 178.146  {
 178.147 -
 178.148 -    double M[9];
 178.149 -
 178.150 +    cmsFloat64Number M[9];
 178.151  
 178.152      M[0] =(( 0.38971 *  1.096124) + (0.68898 * 0.454369) + (-0.07868 * -0.009628));
 178.153      M[1] =(( 0.38971 * -0.278869) + (0.68898 * 0.473533) + (-0.07868 * -0.005698));
 178.154 @@ -180,10 +176,10 @@
 178.155  }
 178.156  
 178.157  static
 178.158 -CAM02COLOR NonlinearCompression(CAM02COLOR clr, LPcmsCIECAM02 pMod)
 178.159 +CAM02COLOR NonlinearCompression(CAM02COLOR clr, cmsCIECAM02* pMod)
 178.160  {
 178.161 -    int i;
 178.162 -    double temp;
 178.163 +    cmsUInt32Number i;
 178.164 +    cmsFloat64Number temp;
 178.165  
 178.166      for (i = 0; i < 3; i++) {
 178.167          if (clr.RGBp[i] < 0) {
 178.168 @@ -204,9 +200,9 @@
 178.169  }
 178.170  
 178.171  static
 178.172 -CAM02COLOR ComputeCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod)
 178.173 +CAM02COLOR ComputeCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
 178.174  {
 178.175 -    double a, b, temp, e, t, r2d, d2r;
 178.176 +    cmsFloat64Number a, b, temp, e, t, r2d, d2r;
 178.177  
 178.178      a = clr.RGBpa[0] - (12.0 * clr.RGBpa[1] / 11.0) + (clr.RGBpa[2] / 11.0);
 178.179      b = (clr.RGBpa[0] + clr.RGBpa[1] - (2.0 * clr.RGBpa[2])) / 9.0;
 178.180 @@ -274,10 +270,10 @@
 178.181  
 178.182  
 178.183  static
 178.184 -CAM02COLOR InverseCorrelates(CAM02COLOR clr, LPcmsCIECAM02 pMod)
 178.185 +CAM02COLOR InverseCorrelates(CAM02COLOR clr, cmsCIECAM02* pMod)
 178.186  {
 178.187  
 178.188 -    double t, e, p1, p2, p3, p4, p5, hr, d2r;
 178.189 +    cmsFloat64Number t, e, p1, p2, p3, p4, p5, hr, d2r;
 178.190      d2r = 3.141592654 / 180.0;
 178.191  
 178.192      t = pow( (clr.C / (pow((clr.J / 100.0), 0.5) *
 178.193 @@ -327,10 +323,10 @@
 178.194  }
 178.195  
 178.196  static
 178.197 -CAM02COLOR InverseNonlinearity(CAM02COLOR clr, LPcmsCIECAM02 pMod)
 178.198 +CAM02COLOR InverseNonlinearity(CAM02COLOR clr, cmsCIECAM02* pMod)
 178.199  {
 178.200 -    int i;
 178.201 -    double c1;
 178.202 +    cmsUInt32Number i;
 178.203 +    cmsFloat64Number c1;
 178.204  
 178.205      for (i = 0; i < 3; i++) {
 178.206          if ((clr.RGBpa[i] - 0.1) < 0) c1 = -1;
 178.207 @@ -347,7 +343,7 @@
 178.208  static
 178.209  CAM02COLOR HPEtoCAT02(CAM02COLOR clr)
 178.210  {
 178.211 -    double M[9];
 178.212 +    cmsFloat64Number M[9];
 178.213  
 178.214      M[0] = (( 0.7328 *  1.910197) + (0.4296 * 0.370950));
 178.215      M[1] = (( 0.7328 * -1.112124) + (0.4296 * 0.629054));
 178.216 @@ -362,19 +358,19 @@
 178.217      clr.RGBc[0] = (clr.RGBp[0] * M[0]) + (clr.RGBp[1] * M[1]) + (clr.RGBp[2] * M[2]);
 178.218      clr.RGBc[1] = (clr.RGBp[0] * M[3]) + (clr.RGBp[1] * M[4]) + (clr.RGBp[2] * M[5]);
 178.219      clr.RGBc[2] = (clr.RGBp[0] * M[6]) + (clr.RGBp[1] * M[7]) + (clr.RGBp[2] * M[8]);
 178.220 -    return (clr);
 178.221 +    return clr;
 178.222  }
 178.223  
 178.224  
 178.225  static
 178.226 -CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr,  LPcmsCIECAM02 pMod)
 178.227 +CAM02COLOR InverseChromaticAdaptation(CAM02COLOR clr,  cmsCIECAM02* pMod)
 178.228  {
 178.229 -    int i;
 178.230 +    cmsUInt32Number i;
 178.231      for (i = 0; i < 3; i++) {
 178.232          clr.RGB[i] = clr.RGBc[i] /
 178.233              ((pMod->adoptedWhite.XYZ[1] * pMod->D / pMod->adoptedWhite.RGB[i]) + 1.0 - pMod->D);
 178.234      }
 178.235 -    return(clr);
 178.236 +    return clr;
 178.237  }
 178.238  
 178.239  
 178.240 @@ -385,23 +381,21 @@
 178.241      clr.XYZ[1] = (clr.RGB[0] *  0.454369) + (clr.RGB[1] *  0.473533) + (clr.RGB[2] *  0.072098);
 178.242      clr.XYZ[2] = (clr.RGB[0] * -0.009628) + (clr.RGB[1] * -0.005698) + (clr.RGB[2] *  1.015326);
 178.243  
 178.244 -    return(clr);
 178.245 +    return clr;
 178.246  }
 178.247  
 178.248  
 178.249 +cmsHANDLE  CMSEXPORT cmsCIECAM02Init(cmsContext ContextID, const cmsViewingConditions* pVC)
 178.250 +{
 178.251 +    cmsCIECAM02* lpMod;
 178.252  
 178.253 +    _cmsAssert(pVC != NULL);
 178.254  
 178.255 -LCMSHANDLE LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC)
 178.256 -{
 178.257 -    LPcmsCIECAM02 lpMod;
 178.258 -
 178.259 -
 178.260 -   if((lpMod = (LPcmsCIECAM02) _cmsMalloc(sizeof(cmsCIECAM02))) == NULL) {
 178.261 -        return (LCMSHANDLE) NULL;
 178.262 +    if((lpMod = (cmsCIECAM02*) _cmsMallocZero(ContextID, sizeof(cmsCIECAM02))) == NULL) {
 178.263 +        return NULL;
 178.264      }
 178.265  
 178.266 -
 178.267 -    ZeroMemory(lpMod, sizeof(cmsCIECAM02));
 178.268 +    lpMod ->ContextID = ContextID;
 178.269  
 178.270      lpMod ->adoptedWhite.XYZ[0] = pVC ->whitePoint.X;
 178.271      lpMod ->adoptedWhite.XYZ[1] = pVC ->whitePoint.Y;
 178.272 @@ -414,36 +408,30 @@
 178.273  
 178.274      switch (lpMod -> surround) {
 178.275  
 178.276 -    case AVG_SURROUND_4:
 178.277 -        lpMod->F = 1.0;     // Not included in CAM02
 178.278 -        lpMod->c = 0.69;
 178.279 -        lpMod->Nc = 1.0;
 178.280 -        break;
 178.281  
 178.282 -    case CUTSHEET_SURROUND:
 178.283 -        lpMod->F = 0.8;
 178.284 -        lpMod->c = 0.41;
 178.285 -        lpMod->Nc = 0.8;
 178.286 -        break;
 178.287 +      case CUTSHEET_SURROUND:
 178.288 +          lpMod->F = 0.8;
 178.289 +          lpMod->c = 0.41;
 178.290 +          lpMod->Nc = 0.8;
 178.291 +          break;
 178.292  
 178.293 -    case DARK_SURROUND:
 178.294 -        lpMod -> F  = 0.8;
 178.295 -        lpMod -> c  = 0.525;
 178.296 -        lpMod -> Nc = 0.8;
 178.297 -        break;
 178.298 +      case DARK_SURROUND:
 178.299 +          lpMod -> F  = 0.8;
 178.300 +          lpMod -> c  = 0.525;
 178.301 +          lpMod -> Nc = 0.8;
 178.302 +          break;
 178.303  
 178.304 +      case DIM_SURROUND:
 178.305 +          lpMod -> F  = 0.9;
 178.306 +          lpMod -> c  = 0.59;
 178.307 +          lpMod -> Nc = 0.95;
 178.308 +          break;
 178.309  
 178.310 -    case DIM_SURROUND:
 178.311 -        lpMod -> F  = 0.9;
 178.312 -        lpMod -> c  = 0.59;
 178.313 -        lpMod -> Nc = 0.95;
 178.314 -        break;
 178.315 -
 178.316 -    default:
 178.317 -        // Average surround
 178.318 -        lpMod -> F  = 1.0;
 178.319 -        lpMod -> c  = 0.69;
 178.320 -        lpMod -> Nc = 1.0;
 178.321 +      default:
 178.322 +          // Average surround
 178.323 +          lpMod -> F  = 1.0;
 178.324 +          lpMod -> c  = 0.69;
 178.325 +          lpMod -> Nc = 1.0;
 178.326      }
 178.327  
 178.328      lpMod -> n   = compute_n(lpMod);
 178.329 @@ -451,10 +439,8 @@
 178.330      lpMod -> Nbb = computeNbb(lpMod);
 178.331      lpMod -> FL  = computeFL(lpMod);
 178.332  
 178.333 -    if (lpMod -> D == D_CALCULATE ||
 178.334 -        lpMod -> D == D_CALCULATE_DISCOUNT) {
 178.335 -
 178.336 -    lpMod -> D   = computeD(lpMod);
 178.337 +    if (lpMod -> D == D_CALCULATE) {
 178.338 +        lpMod -> D   = computeD(lpMod);
 178.339      }
 178.340  
 178.341      lpMod -> Ncb = lpMod -> Nbb;
 178.342 @@ -464,21 +450,26 @@
 178.343      lpMod -> adoptedWhite = CAT02toHPE(lpMod -> adoptedWhite);
 178.344      lpMod -> adoptedWhite = NonlinearCompression(lpMod -> adoptedWhite, lpMod);
 178.345  
 178.346 -    return (LCMSHANDLE) lpMod;
 178.347 +    return (cmsHANDLE) lpMod;
 178.348  
 178.349  }
 178.350  
 178.351 -void LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel)
 178.352 +void CMSEXPORT cmsCIECAM02Done(cmsHANDLE hModel)
 178.353  {
 178.354 -    LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel;
 178.355 -    if (lpMod) _cmsFree(lpMod);
 178.356 +    cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
 178.357 +
 178.358 +    if (lpMod) _cmsFree(lpMod ->ContextID, lpMod);
 178.359  }
 178.360  
 178.361  
 178.362 -void LCMSEXPORT cmsCIECAM02Forward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh pOut)
 178.363 +void CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut)
 178.364  {
 178.365      CAM02COLOR clr;
 178.366 -    LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel;
 178.367 +    cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
 178.368 +
 178.369 +    _cmsAssert(lpMod != NULL);
 178.370 +    _cmsAssert(pIn != NULL);
 178.371 +    _cmsAssert(pOut != NULL);
 178.372  
 178.373      clr.XYZ[0] = pIn ->X;
 178.374      clr.XYZ[1] = pIn ->Y;
 178.375 @@ -495,11 +486,14 @@
 178.376      pOut ->h = clr.h;
 178.377  }
 178.378  
 178.379 -void LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn, LPcmsCIEXYZ pOut)
 178.380 +void CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn, cmsCIEXYZ* pOut)
 178.381  {
 178.382      CAM02COLOR clr;
 178.383 -    LPcmsCIECAM02 lpMod = (LPcmsCIECAM02) (LPSTR) hModel;
 178.384 +    cmsCIECAM02* lpMod = (cmsCIECAM02*) hModel;
 178.385  
 178.386 +    _cmsAssert(lpMod != NULL);
 178.387 +    _cmsAssert(pIn != NULL);
 178.388 +    _cmsAssert(pOut != NULL);
 178.389  
 178.390      clr.J = pIn -> J;
 178.391      clr.C = pIn -> C;
 178.392 @@ -514,6 +508,5 @@
 178.393      pOut ->X = clr.XYZ[0];
 178.394      pOut ->Y = clr.XYZ[1];
 178.395      pOut ->Z = clr.XYZ[2];
 178.396 -
 178.397  }
 178.398  
   179.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmscam97.c	Thu Sep 23 17:33:40 2010 -0700
   179.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.3 @@ -1,750 +0,0 @@
   179.4 -/*
   179.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   179.6 - *
   179.7 - * This code is free software; you can redistribute it and/or modify it
   179.8 - * under the terms of the GNU General Public License version 2 only, as
   179.9 - * published by the Free Software Foundation.  Oracle designates this
  179.10 - * particular file as subject to the "Classpath" exception as provided
  179.11 - * by Oracle in the LICENSE file that accompanied this code.
  179.12 - *
  179.13 - * This code is distributed in the hope that it will be useful, but WITHOUT
  179.14 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  179.15 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  179.16 - * version 2 for more details (a copy is included in the LICENSE file that
  179.17 - * accompanied this code).
  179.18 - *
  179.19 - * You should have received a copy of the GNU General Public License version
  179.20 - * 2 along with this work; if not, write to the Free Software Foundation,
  179.21 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  179.22 - *
  179.23 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  179.24 - * or visit www.oracle.com if you need additional information or have any
  179.25 - * questions.
  179.26 - */
  179.27 -
  179.28 -// This file is available under and governed by the GNU General Public
  179.29 -// License version 2 only, as published by the Free Software Foundation.
  179.30 -// However, the following notice accompanied the original version of this
  179.31 -// file:
  179.32 -//
  179.33 -//
  179.34 -//  Little cms
  179.35 -//  Copyright (C) 1998-2007 Marti Maria
  179.36 -//
  179.37 -// Permission is hereby granted, free of charge, to any person obtaining
  179.38 -// a copy of this software and associated documentation files (the "Software"),
  179.39 -// to deal in the Software without restriction, including without limitation
  179.40 -// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  179.41 -// and/or sell copies of the Software, and to permit persons to whom the Software
  179.42 -// is furnished to do so, subject to the following conditions:
  179.43 -//
  179.44 -// The above copyright notice and this permission notice shall be included in
  179.45 -// all copies or substantial portions of the Software.
  179.46 -//
  179.47 -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  179.48 -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  179.49 -// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  179.50 -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  179.51 -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  179.52 -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  179.53 -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  179.54 -
  179.55 -
  179.56 -#include "lcms.h"
  179.57 -
  179.58 -
  179.59 -/*
  179.60 -typedef struct {
  179.61 -               double J;
  179.62 -               double C;
  179.63 -               double h;
  179.64 -
  179.65 -               } cmsJCh, FAR* LPcmsJCh;
  179.66 -
  179.67 -
  179.68 -#define AVG_SURROUND_4     0
  179.69 -#define AVG_SURROUND       1
  179.70 -#define DIM_SURROUND       2
  179.71 -#define DARK_SURROUND      3
  179.72 -#define CUTSHEET_SURROUND  4
  179.73 -
  179.74 -
  179.75 -typedef struct {
  179.76 -
  179.77 -              cmsCIEXYZ whitePoint;
  179.78 -              double    Yb;
  179.79 -              double    La;
  179.80 -              int       surround;
  179.81 -              double    D_value;
  179.82 -
  179.83 -              } cmsViewingConditions, FAR* LPcmsViewingConditions;
  179.84 -
  179.85 -
  179.86 -
  179.87 -LCMSAPI LCMSHANDLE LCMSEXPORT cmsCIECAM97sInit(LPcmsViewingConditions pVC);
  179.88 -LCMSAPI void   LCMSEXPORT cmsCIECAM97sDone(LCMSHANDLE hModel);
  179.89 -LCMSAPI void   LCMSEXPORT cmsCIECAM97sForward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh pOut);
  179.90 -LCMSAPI void   LCMSEXPORT cmsCIECAM97sReverse(LCMSHANDLE hModel, LPcmsJCh pIn,    LPcmsCIEXYZ pOut);
  179.91 -
  179.92 -*/
  179.93 -
  179.94 -// ---------- Implementation --------------------------------------------
  179.95 -
  179.96 -// #define USE_CIECAM97s2  1
  179.97 -
  179.98 -#ifdef USE_CIECAM97s2
  179.99 -
 179.100 -#       define NOISE_CONSTANT   3.05
 179.101 -#else
 179.102 -#       define NOISE_CONSTANT   2.05
 179.103 -#endif
 179.104 -
 179.105 -
 179.106 -/*
 179.107 -  The model input data are the adapting field luminance in cd/m2
 179.108 -  (normally taken to be 20% of the luminance of white in the adapting field),
 179.109 -  LA , the relative tristimulus values of the stimulus, XYZ, the relative
 179.110 -  tristimulus values of white in the same viewing conditions, Xw Yw Zw ,
 179.111 -  and the relative luminance of the background, Yb . Relative tristimulus
 179.112 -  values should be expressed on a scale from Y = 0 for a perfect black
 179.113 -  to Y = 100 for a perfect reflecting diffuser. Additionally, the
 179.114 -  parameters c, for the impact of surround, Nc , a chromatic induction factor,
 179.115 -  and F, a factor for degree of adaptation, must be selected according to the
 179.116 -  guidelines in table
 179.117 -
 179.118 -  All CIE tristimulus values are obtained using the CIE 1931
 179.119 -  Standard Colorimetric Observer (2°).
 179.120 -
 179.121 -*/
 179.122 -
 179.123 -typedef struct {
 179.124 -
 179.125 -    cmsCIEXYZ WP;
 179.126 -    int surround;
 179.127 -    int calculate_D;
 179.128 -
 179.129 -    double  Yb;         // rel. luminance of background
 179.130 -
 179.131 -    cmsCIEXYZ RefWhite;
 179.132 -
 179.133 -    double La;    // The adapting field luminance in cd/m2
 179.134 -
 179.135 -    double c;     // Impact of surround
 179.136 -    double Nc;    // Chromatic induction factor
 179.137 -    double Fll;   // Lightness contrast factor (Removed on rev 2)
 179.138 -    double F;     // Degree of adaptation
 179.139 -
 179.140 -
 179.141 -    double k;
 179.142 -    double Fl;
 179.143 -
 179.144 -    double Nbb;  // The background and chromatic brightness induction factors.
 179.145 -    double Ncb;
 179.146 -    double z;    // base exponential nonlinearity
 179.147 -    double n;    // background induction factor
 179.148 -    double D;
 179.149 -
 179.150 -    MAT3 MlamRigg;
 179.151 -    MAT3 MlamRigg_1;
 179.152 -
 179.153 -    MAT3 Mhunt;
 179.154 -    MAT3 Mhunt_1;
 179.155 -
 179.156 -    MAT3 Mhunt_x_MlamRigg_1;
 179.157 -    MAT3 MlamRigg_x_Mhunt_1;
 179.158 -
 179.159 -
 179.160 -    VEC3 RGB_subw;
 179.161 -    VEC3 RGB_subw_prime;
 179.162 -
 179.163 -    double p;
 179.164 -
 179.165 -    VEC3 RGB_subwc;
 179.166 -
 179.167 -    VEC3 RGB_subaw_prime;
 179.168 -    double A_subw;
 179.169 -    double Q_subw;
 179.170 -
 179.171 -    } cmsCIECAM97s,FAR *LPcmsCIECAM97s;
 179.172 -
 179.173 -
 179.174 -
 179.175 -// Free model structure
 179.176 -
 179.177 -LCMSAPI void LCMSEXPORT cmsCIECAM97sDone(LCMSHANDLE hModel)
 179.178 -{
 179.179 -    LPcmsCIECAM97s lpMod = (LPcmsCIECAM97s) (LPSTR) hModel;
 179.180 -    if (lpMod) _cmsFree(lpMod);
 179.181 -}
 179.182 -
 179.183 -// Partial discounting for adaptation degree computation
 179.184 -
 179.185 -static
 179.186 -double discount(double d, double chan)
 179.187 -{
 179.188 -    return (d * chan + 1 - d);
 179.189 -}
 179.190 -
 179.191 -
 179.192 -// This routine does model exponential nonlinearity on the short wavelenght
 179.193 -// sensitive channel. On CIECAM97s rev 2 this has been reverted to linear.
 179.194 -
 179.195 -static
 179.196 -void FwAdaptationDegree(LPcmsCIECAM97s lpMod, LPVEC3 RGBc, LPVEC3 RGB)
 179.197 -{
 179.198 -
 179.199 -
 179.200 -#ifdef USE_CIECAM97s2
 179.201 -    RGBc->n[0] = RGB->n[0]* discount(lpMod->D, 100.0/lpMod->RGB_subw.n[0]);
 179.202 -    RGBc->n[1] = RGB->n[1]* discount(lpMod->D, 100.0/lpMod->RGB_subw.n[1]);
 179.203 -    RGBc->n[2] = RGB->n[2]* discount(lpMod->D, 100.0/lpMod->RGB_subw.n[2]);
 179.204 -#else
 179.205 -
 179.206 -    RGBc->n[0] = RGB->n[0]* discount(lpMod->D, 1.0/lpMod->RGB_subw.n[0]);
 179.207 -    RGBc->n[1] = RGB->n[1]* discount(lpMod->D, 1.0/lpMod->RGB_subw.n[1]);
 179.208 -
 179.209 -    RGBc->n[2] = pow(fabs(RGB->n[2]), lpMod ->p) * discount(lpMod->D, (1.0/pow(lpMod->RGB_subw.n[2], lpMod->p)));
 179.210 -
 179.211 -    // If B happens to be negative, Then Bc is also set to be negative
 179.212 -
 179.213 -    if (RGB->n[2] < 0)
 179.214 -           RGBc->n[2] = -RGBc->n[2];
 179.215 -#endif
 179.216 -}
 179.217 -
 179.218 -
 179.219 -static
 179.220 -void RvAdaptationDegree(LPcmsCIECAM97s lpMod, LPVEC3 RGBc, LPVEC3 RGB)
 179.221 -{
 179.222 -
 179.223 -
 179.224 -#ifdef USE_CIECAM97s2
 179.225 -    RGBc->n[0] = RGB->n[0]/discount(lpMod->D, 100.0/lpMod->RGB_subw.n[0]);
 179.226 -    RGBc->n[1] = RGB->n[1]/discount(lpMod->D, 100.0/lpMod->RGB_subw.n[1]);
 179.227 -    RGBc->n[2] = RGB->n[2]/discount(lpMod->D, 100.0/lpMod->RGB_subw.n[2]);
 179.228 -#else
 179.229 -
 179.230 -    RGBc->n[0] = RGB->n[0]/discount(lpMod->D, 1.0/lpMod->RGB_subw.n[0]);
 179.231 -    RGBc->n[1] = RGB->n[1]/discount(lpMod->D, 1.0/lpMod->RGB_subw.n[1]);
 179.232 -    RGBc->n[2] = pow(fabs(RGB->n[2]), 1.0/lpMod->p)/pow(discount(lpMod->D, 1.0/pow(lpMod->RGB_subw.n[2], lpMod->p)), 1.0/lpMod->p);
 179.233 -    if (RGB->n[2] < 0)
 179.234 -           RGBc->n[2] = -RGBc->n[2];
 179.235 -#endif
 179.236 -}
 179.237 -
 179.238 -
 179.239 -
 179.240 -static
 179.241 -void PostAdaptationConeResponses(LPcmsCIECAM97s lpMod, LPVEC3 RGBa_prime, LPVEC3 RGBprime)
 179.242 -{
 179.243 -     if (RGBprime->n[0]>=0.0) {
 179.244 -
 179.245 -            RGBa_prime->n[0]=((40.0*pow(lpMod -> Fl * RGBprime->n[0]/100.0, 0.73))/(pow(lpMod -> Fl * RGBprime->n[0]/100.0, 0.73)+2))+1;
 179.246 -     }
 179.247 -     else
 179.248 -     {
 179.249 -            RGBa_prime->n[0]=((-40.0*pow((-lpMod -> Fl * RGBprime->n[0])/100.0, 0.73))/(pow((-lpMod -> Fl * RGBprime->n[0])/100.0, 0.73)+2))+1;
 179.250 -     }
 179.251 -
 179.252 -     if (RGBprime->n[1]>=0.0)
 179.253 -     {
 179.254 -            RGBa_prime->n[1]=((40.0*pow(lpMod -> Fl * RGBprime->n[1]/100.0, 0.73))/(pow(lpMod -> Fl * RGBprime->n[1]/100.0, 0.73)+2))+1;
 179.255 -     }
 179.256 -     else
 179.257 -     {
 179.258 -            RGBa_prime->n[1]=((-40.0*pow((-lpMod -> Fl * RGBprime->n[1])/100.0, 0.73))/(pow((-lpMod -> Fl * RGBprime->n[1])/100.0, 0.73)+2))+1;
 179.259 -     }
 179.260 -
 179.261 -     if (RGBprime->n[2]>=0.0)
 179.262 -     {
 179.263 -            RGBa_prime->n[2]=((40.0*pow(lpMod -> Fl * RGBprime->n[2]/100.0, 0.73))/(pow(lpMod -> Fl * RGBprime->n[2]/100.0, 0.73)+2))+1;
 179.264 -     }
 179.265 -     else
 179.266 -     {
 179.267 -            RGBa_prime->n[2]=((-40.0*pow((-lpMod -> Fl * RGBprime->n[2])/100.0, 0.73))/(pow((-lpMod -> Fl * RGBprime->n[2])/100.0, 0.73)+2))+1;
 179.268 -     }
 179.269 -}
 179.270 -
 179.271 -
 179.272 -// Compute hue quadrature, eccentricity factor, e
 179.273 -
 179.274 -static
 179.275 -void ComputeHueQuadrature(double h, double* H, double* e)
 179.276 -{
 179.277 -
 179.278 -
 179.279 -#define IRED    0
 179.280 -#define IYELLOW 1
 179.281 -#define IGREEN  2
 179.282 -#define IBLUE   3
 179.283 -
 179.284 -      double e_tab[] = {0.8, 0.7, 1.0, 1.2};
 179.285 -      double H_tab[] = {  0, 100, 200, 300};
 179.286 -      int p1, p2;
 179.287 -      double e1, e2, h1, h2;
 179.288 -
 179.289 -
 179.290 -       if (h >= 20.14 && h < 90.0) { // Red
 179.291 -
 179.292 -                        p1 = IRED;
 179.293 -                        p2 = IYELLOW;
 179.294 -       }
 179.295 -       else
 179.296 -       if (h >= 90.0 && h < 164.25) { // Yellow
 179.297 -
 179.298 -                        p1 = IYELLOW;
 179.299 -                        p2 = IGREEN;
 179.300 -       }
 179.301 -       else
 179.302 -       if (h >= 164.25 && h < 237.53) { // Green
 179.303 -
 179.304 -                        p1 = IGREEN;
 179.305 -                        p2 = IBLUE;       }
 179.306 -       else {                         // Blue
 179.307 -
 179.308 -                        p1 = IBLUE;
 179.309 -                        p2 = IRED;
 179.310 -       }
 179.311 -
 179.312 -       e1 = e_tab[p1]; e2 = e_tab[p2];
 179.313 -       h1 = H_tab[p1]; h2 = H_tab[p2];
 179.314 -
 179.315 -
 179.316 -
 179.317 -       *e = e1 + ((e2-e1)*(h-h1)/(h2 - h1));
 179.318 -       *H = h1 + (100. * (h - h1) / e1) / ((h - h1)/e1 + (h2 - h) / e2);
 179.319 -
 179.320 -#undef IRED
 179.321 -#undef IYELLOW
 179.322 -#undef IGREEN
 179.323 -#undef IBLUE
 179.324 -
 179.325 -}
 179.326 -
 179.327 -
 179.328 -
 179.329 -
 179.330 -
 179.331 -
 179.332 -LCMSAPI LCMSHANDLE LCMSEXPORT cmsCIECAM97sInit(LPcmsViewingConditions pVC)
 179.333 -{
 179.334 -    LPcmsCIECAM97s lpMod;
 179.335 -    VEC3 tmp;
 179.336 -
 179.337 -    if((lpMod = (LPcmsCIECAM97s) _cmsMalloc(sizeof(cmsCIECAM97s))) == NULL) {
 179.338 -        return (LCMSHANDLE) NULL;
 179.339 -    }
 179.340 -
 179.341 -
 179.342 -    lpMod->WP.X = pVC->whitePoint.X;
 179.343 -    lpMod->WP.Y = pVC->whitePoint.Y;
 179.344 -    lpMod->WP.Z = pVC->whitePoint.Z;
 179.345 -
 179.346 -    lpMod->Yb   = pVC->Yb;
 179.347 -    lpMod->La   = pVC->La;
 179.348 -
 179.349 -    lpMod->surround = pVC->surround;
 179.350 -
 179.351 -    lpMod->RefWhite.X = 100.0;
 179.352 -    lpMod->RefWhite.Y = 100.0;
 179.353 -    lpMod->RefWhite.Z = 100.0;
 179.354 -
 179.355 -#ifdef USE_CIECAM97s2
 179.356 -
 179.357 -    VEC3init(&lpMod->MlamRigg.v[0],  0.8562, 0.3372, -0.1934);
 179.358 -    VEC3init(&lpMod->MlamRigg.v[1], -0.8360, 1.8327,  0.0033);
 179.359 -    VEC3init(&lpMod->MlamRigg.v[2],  0.0357,-0.0469,  1.0112);
 179.360 -
 179.361 -    VEC3init(&lpMod->MlamRigg_1.v[0], 0.9874, -0.1768, 0.1894);
 179.362 -    VEC3init(&lpMod->MlamRigg_1.v[1], 0.4504,  0.4649, 0.0846);
 179.363 -    VEC3init(&lpMod->MlamRigg_1.v[2],-0.0139,  0.0278, 0.9861);
 179.364 -
 179.365 -#else
 179.366 -    // Bradford transform: Lam-Rigg cone responses
 179.367 -    VEC3init(&lpMod->MlamRigg.v[0],  0.8951,  0.2664, -0.1614);
 179.368 -    VEC3init(&lpMod->MlamRigg.v[1], -0.7502,  1.7135,  0.0367);
 179.369 -    VEC3init(&lpMod->MlamRigg.v[2],  0.0389, -0.0685,  1.0296);
 179.370 -
 179.371 -
 179.372 -    // Inverse of Lam-Rigg
 179.373 -    VEC3init(&lpMod->MlamRigg_1.v[0],  0.98699, -0.14705,  0.15996);
 179.374 -    VEC3init(&lpMod->MlamRigg_1.v[1],  0.43231,  0.51836,  0.04929);
 179.375 -    VEC3init(&lpMod->MlamRigg_1.v[2], -0.00853,  0.04004,  0.96849);
 179.376 -
 179.377 -#endif
 179.378 -
 179.379 -    // Hunt-Pointer-Estevez cone responses
 179.380 -    VEC3init(&lpMod->Mhunt.v[0],   0.38971,  0.68898, -0.07868);
 179.381 -    VEC3init(&lpMod->Mhunt.v[1],  -0.22981,  1.18340,  0.04641);
 179.382 -    VEC3init(&lpMod->Mhunt.v[2],   0.0,      0.0,      1.0);
 179.383 -
 179.384 -    // Inverse of Hunt-Pointer-Estevez
 179.385 -    VEC3init(&lpMod->Mhunt_1.v[0],     1.91019, -1.11214, 0.20195);
 179.386 -    VEC3init(&lpMod->Mhunt_1.v[1],     0.37095,  0.62905, 0.0);
 179.387 -    VEC3init(&lpMod->Mhunt_1.v[2],     0.0,      0.0,     1.0);
 179.388 -
 179.389 -
 179.390 -    if (pVC->D_value == -1.0)
 179.391 -          lpMod->calculate_D = 1;
 179.392 -    else
 179.393 -    if (pVC->D_value == -2.0)
 179.394 -           lpMod->calculate_D = 2;
 179.395 -    else {
 179.396 -        lpMod->calculate_D = 0;
 179.397 -        lpMod->D = pVC->D_value;
 179.398 -    }
 179.399 -
 179.400 -   // Table I (revised)
 179.401 -
 179.402 -   switch (lpMod->surround) {
 179.403 -
 179.404 -    case AVG_SURROUND_4:
 179.405 -       lpMod->F = 1.0;
 179.406 -       lpMod->c = 0.69;
 179.407 -       lpMod->Fll = 0.0;    // Not included on Rev 2
 179.408 -       lpMod->Nc = 1.0;
 179.409 -       break;
 179.410 -    case AVG_SURROUND:
 179.411 -       lpMod->F = 1.0;
 179.412 -       lpMod->c = 0.69;
 179.413 -       lpMod->Fll = 1.0;
 179.414 -       lpMod->Nc = 1.0;
 179.415 -       break;
 179.416 -    case DIM_SURROUND:
 179.417 -       lpMod->F = 0.99;
 179.418 -       lpMod->c = 0.59;
 179.419 -       lpMod->Fll = 1.0;
 179.420 -       lpMod->Nc = 0.95;
 179.421 -       break;
 179.422 -    case DARK_SURROUND:
 179.423 -       lpMod->F = 0.9;
 179.424 -       lpMod->c = 0.525;
 179.425 -       lpMod->Fll = 1.0;
 179.426 -       lpMod->Nc = 0.8;
 179.427 -       break;
 179.428 -    case CUTSHEET_SURROUND:
 179.429 -       lpMod->F = 0.9;
 179.430 -       lpMod->c = 0.41;
 179.431 -       lpMod->Fll = 1.0;
 179.432 -       lpMod->Nc = 0.8;
 179.433 -       break;
 179.434 -    default:
 179.435 -       lpMod->F = 1.0;
 179.436 -       lpMod->c = 0.69;
 179.437 -       lpMod->Fll = 1.0;
 179.438 -       lpMod->Nc = 1.0;
 179.439 -       break;
 179.440 -    }
 179.441 -
 179.442 -    lpMod->k = 1 / (5 * lpMod->La  + 1);
 179.443 -    lpMod->Fl = lpMod->La * pow(lpMod->k, 4) + 0.1*pow(1 - pow(lpMod->k, 4), 2.0) * pow(5*lpMod->La, 1.0/3.0);
 179.444 -
 179.445 -    if (lpMod->calculate_D > 0) {
 179.446 -
 179.447 -       lpMod->D = lpMod->F * (1 - 1 / (1 + 2*pow(lpMod->La, 0.25) + pow(lpMod->La, 2)/300.0));
 179.448 -       if (lpMod->calculate_D > 1)
 179.449 -           lpMod->D = (lpMod->D + 1.0) / 2;
 179.450 -    }
 179.451 -
 179.452 -
 179.453 -    // RGB_subw = [MlamRigg][WP/YWp]
 179.454 -#ifdef USE_CIECAM97s2
 179.455 -    MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, &lpMod -> WP);
 179.456 -#else
 179.457 -    VEC3divK(&tmp, (LPVEC3) &lpMod -> WP, lpMod->WP.Y);
 179.458 -    MAT3eval(&lpMod -> RGB_subw, &lpMod -> MlamRigg, &tmp);
 179.459 -#endif
 179.460 -
 179.461 -
 179.462 -
 179.463 -    MAT3per(&lpMod -> Mhunt_x_MlamRigg_1,   &lpMod -> Mhunt,   &lpMod->MlamRigg_1  );
 179.464 -    MAT3per(&lpMod -> MlamRigg_x_Mhunt_1,   &lpMod -> MlamRigg, &lpMod -> Mhunt_1  );
 179.465 -
 179.466 -    // p is used on forward model
 179.467 -    lpMod->p = pow(lpMod->RGB_subw.n[2], 0.0834);
 179.468 -
 179.469 -    FwAdaptationDegree(lpMod, &lpMod->RGB_subwc, &lpMod->RGB_subw);
 179.470 -
 179.471 -#if USE_CIECAM97s2
 179.472 -    MAT3eval(&lpMod->RGB_subw_prime, &lpMod->Mhunt_x_MlamRigg_1, &lpMod -> RGB_subwc);
 179.473 -#else
 179.474 -    VEC3perK(&tmp, &lpMod -> RGB_subwc, lpMod->WP.Y);
 179.475 -    MAT3eval(&lpMod->RGB_subw_prime, &lpMod->Mhunt_x_MlamRigg_1, &tmp);
 179.476 -#endif
 179.477 -
 179.478 -    lpMod->n = lpMod-> Yb / lpMod-> WP.Y;
 179.479 -
 179.480 -    lpMod->z = 1 + lpMod->Fll * sqrt(lpMod->n);
 179.481 -    lpMod->Nbb = lpMod->Ncb = 0.725 / pow(lpMod->n, 0.2);
 179.482 -
 179.483 -    PostAdaptationConeResponses(lpMod, &lpMod->RGB_subaw_prime, &lpMod->RGB_subw_prime);
 179.484 -
 179.485 -    lpMod->A_subw=lpMod->Nbb*(2.0*lpMod->RGB_subaw_prime.n[0]+lpMod->RGB_subaw_prime.n[1]+lpMod->RGB_subaw_prime.n[2]/20.0-NOISE_CONSTANT);
 179.486 -
 179.487 -    return (LCMSHANDLE) lpMod;
 179.488 -}
 179.489 -
 179.490 -
 179.491 -
 179.492 -
 179.493 -//
 179.494 -// The forward model: XYZ -> JCh
 179.495 -//
 179.496 -
 179.497 -LCMSAPI void LCMSEXPORT cmsCIECAM97sForward(LCMSHANDLE hModel, LPcmsCIEXYZ inPtr, LPcmsJCh outPtr)
 179.498 -{
 179.499 -
 179.500 -        LPcmsCIECAM97s lpMod = (LPcmsCIECAM97s) (LPSTR) hModel;
 179.501 -        double a, b, h, s, H1val, es, A;
 179.502 -        VEC3 In, RGB, RGBc, RGBprime, RGBa_prime;
 179.503 -
 179.504 -        if (inPtr -> Y <= 0.0) {
 179.505 -
 179.506 -      outPtr -> J = outPtr -> C = outPtr -> h = 0.0;
 179.507 -          return;
 179.508 -        }
 179.509 -
 179.510 -       // An initial chromatic adaptation transform is used to go from the source
 179.511 -       // viewing conditions to corresponding colours under the equal-energy-illuminant
 179.512 -       // reference viewing conditions. This is handled differently on rev 2
 179.513 -
 179.514 -       VEC3init(&In, inPtr -> X, inPtr -> Y, inPtr -> Z);    // 2.1
 179.515 -
 179.516 -#ifdef USE_CIECAM97s2
 179.517 -       // Since the chromatic adaptation transform has been linearized, it
 179.518 -       // is no longer required to divide the stimulus tristimulus values
 179.519 -       // by their own Y tristimulus value prior to the chromatic adaptation.
 179.520 -#else
 179.521 -       VEC3divK(&In, &In, inPtr -> Y);
 179.522 -#endif
 179.523 -
 179.524 -       MAT3eval(&RGB, &lpMod -> MlamRigg, &In);              // 2.2
 179.525 -
 179.526 -       FwAdaptationDegree(lpMod, &RGBc, &RGB);
 179.527 -
 179.528 -       // The post-adaptation signals for both the sample and the white are then
 179.529 -       // transformed from the sharpened cone responses to the Hunt-Pointer-Estevez
 179.530 -       // cone responses.
 179.531 -#ifdef USE_CIECAM97s2
 179.532 -#else
 179.533 -       VEC3perK(&RGBc, &RGBc, inPtr->Y);
 179.534 -#endif
 179.535 -
 179.536 -       MAT3eval(&RGBprime, &lpMod->Mhunt_x_MlamRigg_1, &RGBc);
 179.537 -
 179.538 -       // The post-adaptation cone responses (for both the stimulus and the white)
 179.539 -       // are then calculated.
 179.540 -
 179.541 -       PostAdaptationConeResponses(lpMod, &RGBa_prime, &RGBprime);
 179.542 -
 179.543 -       // Preliminary red-green and yellow-blue opponent dimensions are calculated
 179.544 -
 179.545 -       a = RGBa_prime.n[0] - (12.0 * RGBa_prime.n[1] / 11.0) + RGBa_prime.n[2]/11.0;
 179.546 -       b = (RGBa_prime.n[0] + RGBa_prime.n[1] - 2.0 * RGBa_prime.n[2]) / 9.0;
 179.547 -
 179.548 -
 179.549 -       // The CIECAM97s hue angle, h, is then calculated
 179.550 -       h = (180.0/M_PI)*(atan2(b, a));
 179.551 -
 179.552 -
 179.553 -       while (h < 0)
 179.554 -              h += 360.0;
 179.555 -
 179.556 -       outPtr->h = h;
 179.557 -
 179.558 -       // hue quadrature and eccentricity factors, e, are calculated
 179.559 -
 179.560 -       ComputeHueQuadrature(h, &H1val, &es);
 179.561 -
 179.562 -       // ComputeHueQuadrature(h, &H1val, &h1, &e1, &h2, &e2, &es);
 179.563 -
 179.564 -
 179.565 -      // The achromatic response A
 179.566 -      A = lpMod->Nbb * (2.0 * RGBa_prime.n[0] + RGBa_prime.n[1] + RGBa_prime.n[2]/20.0 - NOISE_CONSTANT);
 179.567 -
 179.568 -      // CIECAM97s Lightness J
 179.569 -      outPtr -> J = 100.0 * pow(A / lpMod->A_subw, lpMod->c * lpMod->z);
 179.570 -
 179.571 -      // CIECAM97s saturation s
 179.572 -      s =  (50 * hypot (a, b) * 100 * es * (10.0/13.0) * lpMod-> Nc * lpMod->Ncb) / (RGBa_prime.n[0] + RGBa_prime.n[1] + 1.05 * RGBa_prime.n[2]);
 179.573 -
 179.574 -      // CIECAM97s Chroma C
 179.575 -
 179.576 -#ifdef USE_CIECAM97s2
 179.577 -      // Eq. 26 has been modified to allow accurate prediction of the Munsell chroma scales.
 179.578 -      outPtr->C = 0.7487 * pow(s, 0.973) * pow(outPtr->J/100.0, 0.945 * lpMod->n) * (1.64 - pow(0.29, lpMod->n));
 179.579 -
 179.580 -#else
 179.581 -      outPtr->C = 2.44 * pow(s, 0.69) * pow(outPtr->J/100.0, 0.67 * lpMod->n) * (1.64 - pow(0.29, lpMod->n));
 179.582 -#endif
 179.583 -}
 179.584 -
 179.585 -
 179.586 -//
 179.587 -// The reverse model JCh -> XYZ
 179.588 -//
 179.589 -
 179.590 -
 179.591 -LCMSAPI void LCMSEXPORT cmsCIECAM97sReverse(LCMSHANDLE hModel, LPcmsJCh inPtr, LPcmsCIEXYZ outPtr)
 179.592 -{
 179.593 -    LPcmsCIECAM97s lpMod = (LPcmsCIECAM97s) (LPSTR) hModel;
 179.594 -    double J, C, h, A, H1val, es, s, a, b;
 179.595 -    double tan_h, sec_h;
 179.596 -    double R_suba_prime, G_suba_prime, B_suba_prime;
 179.597 -    double R_prime, G_prime, B_prime;
 179.598 -    double Y_subc, Y_prime, B_term;
 179.599 -    VEC3 tmp;
 179.600 -    VEC3 RGB_prime, RGB_subc_Y;
 179.601 -    VEC3 Y_over_Y_subc_RGB;
 179.602 -    VEC3 XYZ_primeprime_over_Y_subc;
 179.603 -#ifdef USE_CIECAM92s2
 179.604 -    VEC3 RGBY;
 179.605 -    VEC3 Out;
 179.606 -#endif
 179.607 -
 179.608 -    J = inPtr->J;
 179.609 -    h = inPtr->h;
 179.610 -    C = inPtr->C;
 179.611 -
 179.612 -    if (J <= 0) {
 179.613 -
 179.614 -        outPtr->X =  0.0;
 179.615 -        outPtr->Y =  0.0;
 179.616 -        outPtr->Z =  0.0;
 179.617 -        return;
 179.618 -    }
 179.619 -
 179.620 -
 179.621 -
 179.622 -    // (2) From J Obtain A
 179.623 -
 179.624 -    A =  pow(J/100.0, 1/(lpMod->c * lpMod->z)) * lpMod->A_subw;
 179.625 -
 179.626 -
 179.627 -    // (3), (4), (5) Using H Determine h1, h2, e1, e2
 179.628 -    // e1 and h1 are the values  of e and h for the unique hue having the
 179.629 -    // nearest lower valur of h and e2 and h2 are the values of e and h for
 179.630 -    // the unique hue having the nearest higher value of h.
 179.631 -
 179.632 -
 179.633 -    ComputeHueQuadrature(h, &H1val, &es);
 179.634 -
 179.635 -    // (7) Calculate s
 179.636 -
 179.637 -    s = pow(C / (2.44 * pow(J/100.0, 0.67*lpMod->n) * (1.64 - pow(0.29, lpMod->n))) , (1./0.69));
 179.638 -
 179.639 -
 179.640 -    // (8) Calculate a and b.
 179.641 -    // NOTE: sqrt(1 + tan^2) == sec(h)
 179.642 -
 179.643 -    tan_h = tan ((M_PI/180.)*(h));
 179.644 -    sec_h = sqrt(1 + tan_h * tan_h);
 179.645 -
 179.646 -    if ((h > 90) && (h < 270))
 179.647 -            sec_h = -sec_h;
 179.648 -
 179.649 -    a = s * ( A/lpMod->Nbb + NOISE_CONSTANT) / ( sec_h * 50000.0 * es * lpMod->Nc * lpMod->Ncb/ 13.0 +
 179.650 -           s * (11.0 / 23.0 + (108.0/23.0) * tan_h));
 179.651 -
 179.652 -    b = a * tan_h;
 179.653 -
 179.654 -    //(9) Calculate R'a G'a and B'a
 179.655 -
 179.656 -    R_suba_prime = (20.0/61.0) * (A/lpMod->Nbb + NOISE_CONSTANT) + (41.0/61.0) * (11.0/23.0) * a + (288.0/61.0) / 23.0 * b;
 179.657 -    G_suba_prime = (20.0/61.0) * (A/lpMod->Nbb + NOISE_CONSTANT) - (81.0/61.0) * (11.0/23.0) * a - (261.0/61.0) / 23.0 * b;
 179.658 -    B_suba_prime = (20.0/61.0) * (A/lpMod->Nbb + NOISE_CONSTANT) - (20.0/61.0) * (11.0/23.0) * a - (20.0/61.0) * (315.0/23.0) * b;
 179.659 -
 179.660 -    // (10) Calculate R', G' and B'
 179.661 -
 179.662 -    if ((R_suba_prime - 1) < 0) {
 179.663 -
 179.664 -         R_prime = -100.0 * pow((2.0 - 2.0 * R_suba_prime) /
 179.665 -                            (39.0 + R_suba_prime), 1.0/0.73);
 179.666 -    }
 179.667 -    else
 179.668 -    {
 179.669 -         R_prime = 100.0 * pow((2.0 * R_suba_prime - 2.0) /
 179.670 -                            (41.0 - R_suba_prime), 1.0/0.73);
 179.671 -    }
 179.672 -
 179.673 -    if ((G_suba_prime - 1) < 0)
 179.674 -    {
 179.675 -         G_prime = -100.0 * pow((2.0 - 2.0 * G_suba_prime) /
 179.676 -                            (39.0 + G_suba_prime), 1.0/0.73);
 179.677 -    }
 179.678 -    else
 179.679 -    {
 179.680 -         G_prime = 100.0 * pow((2.0 * G_suba_prime - 2.0) /
 179.681 -                            (41.0 - G_suba_prime), 1.0/0.73);
 179.682 -    }
 179.683 -
 179.684 -    if ((B_suba_prime - 1) < 0)
 179.685 -    {
 179.686 -         B_prime = -100.0 * pow((2.0 - 2.0 * B_suba_prime) /
 179.687 -                            (39.0 + B_suba_prime), 1.0/0.73);
 179.688 -    }
 179.689 -    else
 179.690 -    {
 179.691 -         B_prime = 100.0 * pow((2.0 * B_suba_prime - 2.0) /
 179.692 -                            (41.0 - B_suba_prime), 1.0/0.73);
 179.693 -    }
 179.694 -
 179.695 -
 179.696 -    // (11) Calculate RcY, GcY and BcY
 179.697 -
 179.698 -    VEC3init(&RGB_prime, R_prime, G_prime, B_prime);
 179.699 -    VEC3divK(&tmp, &RGB_prime, lpMod -> Fl);
 179.700 -
 179.701 -    MAT3eval(&RGB_subc_Y, &lpMod->MlamRigg_x_Mhunt_1, &tmp);
 179.702 -
 179.703 -
 179.704 -
 179.705 -
 179.706 -#ifdef USE_CIECAM97s2
 179.707 -
 179.708 -       // (12)
 179.709 -
 179.710 -
 179.711 -           RvAdaptationDegree(lpMod, &RGBY, &RGB_subc_Y);
 179.712 -           MAT3eval(&Out, &lpMod->MlamRigg_1, &RGBY);
 179.713 -
 179.714 -           outPtr -> X = Out.n[0];
 179.715 -           outPtr -> Y = Out.n[1];
 179.716 -           outPtr -> Z = Out.n[2];
 179.717 -
 179.718 -#else
 179.719 -
 179.720 -           // (12) Calculate Yc
 179.721 -
 179.722 -       Y_subc = 0.43231*RGB_subc_Y.n[0]+0.51836*RGB_subc_Y.n[1]+0.04929*RGB_subc_Y.n[2];
 179.723 -
 179.724 -           // (13) Calculate (Y/Yc)R, (Y/Yc)G and (Y/Yc)B
 179.725 -
 179.726 -           VEC3divK(&RGB_subc_Y, &RGB_subc_Y, Y_subc);
 179.727 -           RvAdaptationDegree(lpMod, &Y_over_Y_subc_RGB, &RGB_subc_Y);
 179.728 -
 179.729 -           // (14) Calculate Y'
 179.730 -       Y_prime = 0.43231*(Y_over_Y_subc_RGB.n[0]*Y_subc) + 0.51836*(Y_over_Y_subc_RGB.n[1]*Y_subc) + 0.04929 * (Y_over_Y_subc_RGB.n[2]*Y_subc);
 179.731 -
 179.732 -           if (Y_prime < 0 || Y_subc < 0)
 179.733 -           {
 179.734 -                // Discard to near black point
 179.735 -
 179.736 -                outPtr -> X = 0;
 179.737 -                outPtr -> Y = 0;
 179.738 -                outPtr -> Z = 0;
 179.739 -                return;
 179.740 -           }
 179.741 -
 179.742 -       B_term = pow(Y_prime / Y_subc, (1.0 / lpMod->p) - 1);
 179.743 -
 179.744 -          // (15) Calculate X'', Y'' and Z''
 179.745 -           Y_over_Y_subc_RGB.n[2] /= B_term;
 179.746 -           MAT3eval(&XYZ_primeprime_over_Y_subc, &lpMod->MlamRigg_1, &Y_over_Y_subc_RGB);
 179.747 -
 179.748 -           outPtr->X =  XYZ_primeprime_over_Y_subc.n[0] * Y_subc;
 179.749 -           outPtr->Y =  XYZ_primeprime_over_Y_subc.n[1] * Y_subc;
 179.750 -           outPtr->Z =  XYZ_primeprime_over_Y_subc.n[2] * Y_subc;
 179.751 -#endif
 179.752 -
 179.753 -}
   180.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Thu Sep 23 17:33:40 2010 -0700
   180.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmscgats.c	Fri Sep 24 16:41:32 2010 -0700
   180.3 @@ -27,9 +27,10 @@
   180.4  // However, the following notice accompanied the original version of this
   180.5  // file:
   180.6  //
   180.7 +//---------------------------------------------------------------------------------
   180.8  //
   180.9 -//  Little cms
  180.10 -//  Copyright (C) 1998-2007 Marti Maria
  180.11 +//  Little Color Management System
  180.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  180.13  //
  180.14  // Permission is hereby granted, free of charge, to any person obtaining
  180.15  // a copy of this software and associated documentation files (the "Software"),
  180.16 @@ -49,104 +50,30 @@
  180.17  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  180.18  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  180.19  //
  180.20 -// IT8.7 / CGATS.17-200x handling
  180.21 -
  180.22 -#include "lcms.h"
  180.23 -
  180.24 -
  180.25 -LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8Alloc(void);
  180.26 -LCMSAPI void            LCMSEXPORT cmsIT8Free(LCMSHANDLE IT8);
  180.27 -
  180.28 -// Tables
  180.29 -
  180.30 -LCMSAPI int             LCMSEXPORT cmsIT8TableCount(LCMSHANDLE IT8);
  180.31 -LCMSAPI int             LCMSEXPORT cmsIT8SetTable(LCMSHANDLE IT8, int nTable);
  180.32 -
  180.33 -// Persistence
  180.34 -LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName);
  180.35 -LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len);
  180.36 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
  180.37 -
  180.38 -// Properties
  180.39 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8);
  180.40 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
  180.41 -
  180.42 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
  180.43 -
  180.44 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
  180.45 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
  180.46 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
  180.47 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val);
  180.48 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
  180.49 -
  180.50 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp);
  180.51 -LCMSAPI double          LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp);
  180.52 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp);
  180.53 -LCMSAPI int             LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE IT8, const char ***PropertyNames);
  180.54 -LCMSAPI int             LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames);
  180.55 -
  180.56 -// Datasets
  180.57 -
  180.58 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer);
  180.59 -
  180.60 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col);
  180.61 -LCMSAPI double          LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int col, int row);
  180.62 -
  180.63 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
  180.64 -                                                const char* Val);
  180.65 -
  180.66 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
  180.67 -                                                double Val);
  180.68 -
  180.69 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
  180.70 -
  180.71 -
  180.72 -LCMSAPI double          LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
  180.73 -
  180.74 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
  180.75 -                                                const char* cSample,
  180.76 -                                                const char *Val);
  180.77 -
  180.78 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
  180.79 -                                                const char* cSample,
  180.80 -                                                double Val);
  180.81 -
  180.82 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
  180.83 -LCMSAPI int             LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames);
  180.84 -
  180.85 -LCMSAPI void            LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter);
  180.86 -
  180.87 -LCMSAPI int             LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet,
  180.88 -                                                                          const char* cField,
  180.89 -                                                                          const char* ExpectedType);
  180.90 -
  180.91 -// ------------------------------------------------------------- Implementation
  180.92 -
  180.93 -
  180.94 -#define SIZEOFLONGMINUS1    (sizeof(long)-1)
  180.95 -#define ALIGNLONG(x) (((x)+SIZEOFLONGMINUS1) & ~(SIZEOFLONGMINUS1))
  180.96 -
  180.97 -// #define STRICT_CGATS  1
  180.98 -
  180.99 -#define MAXID       128     // Max lenght of identifier
 180.100 +//---------------------------------------------------------------------------------
 180.101 +//
 180.102 +
 180.103 +#include "lcms2_internal.h"
 180.104 +
 180.105 +
 180.106 +// IT8.7 / CGATS.17-200x handling -----------------------------------------------------------------------------
 180.107 +
 180.108 +
 180.109 +#define MAXID        128     // Max lenght of identifier
 180.110  #define MAXSTR      1024     // Max lenght of string
 180.111 -#define MAXTABLES   255     // Max Number of tables in a single stream
 180.112 -#define MAXINCLUDE   20     // Max number of nested includes
 180.113 +#define MAXTABLES    255     // Max Number of tables in a single stream
 180.114 +#define MAXINCLUDE    20     // Max number of nested includes
 180.115  
 180.116  #define DEFAULT_DBL_FORMAT  "%.10g" // Double formatting
 180.117  
 180.118 -#include <ctype.h>
 180.119 -#include <limits.h>
 180.120 -
 180.121 -#ifndef NON_WINDOWS
 180.122 -#include <io.h>
 180.123 -#define DIR_CHAR    '\\'
 180.124 +#ifdef CMS_IS_WINDOWS_
 180.125 +#    include <io.h>
 180.126 +#    define DIR_CHAR    '\\'
 180.127  #else
 180.128 -#define DIR_CHAR    '/'
 180.129 +#    define DIR_CHAR    '/'
 180.130  #endif
 180.131  
 180.132  // Symbols
 180.133 -
 180.134  typedef enum {
 180.135  
 180.136          SNONE,
 180.137 @@ -173,8 +100,8 @@
 180.138  
 180.139  
 180.140  // How to write the value
 180.141 -
 180.142  typedef enum {
 180.143 +
 180.144          WRITE_UNCOOKED,
 180.145          WRITE_STRINGIFY,
 180.146          WRITE_HEXADECIMAL,
 180.147 @@ -184,7 +111,6 @@
 180.148      } WRITEMODE;
 180.149  
 180.150  // Linked list of variable names
 180.151 -
 180.152  typedef struct _KeyVal {
 180.153  
 180.154          struct _KeyVal*  Next;
 180.155 @@ -194,108 +120,101 @@
 180.156          char*            Value;         // Points to value
 180.157          WRITEMODE        WriteAs;       // How to write the value
 180.158  
 180.159 -   } KEYVALUE, *LPKEYVALUE;
 180.160 +   } KEYVALUE;
 180.161  
 180.162  
 180.163  // Linked list of memory chunks (Memory sink)
 180.164 -
 180.165  typedef struct _OwnedMem {
 180.166  
 180.167          struct _OwnedMem* Next;
 180.168          void *            Ptr;          // Point to value
 180.169  
 180.170 -   } OWNEDMEM, *LPOWNEDMEM;
 180.171 +   } OWNEDMEM;
 180.172  
 180.173  // Suballocator
 180.174 -
 180.175  typedef struct _SubAllocator {
 180.176  
 180.177 -         LPBYTE Block;
 180.178 -         size_t BlockSize;
 180.179 -         size_t Used;
 180.180 -
 180.181 -    } SUBALLOCATOR, *LPSUBALLOCATOR;
 180.182 +         cmsUInt8Number* Block;
 180.183 +         cmsUInt32Number BlockSize;
 180.184 +         cmsUInt32Number Used;
 180.185 +
 180.186 +    } SUBALLOCATOR;
 180.187  
 180.188  // Table. Each individual table can hold properties and rows & cols
 180.189 -
 180.190  typedef struct _Table {
 180.191  
 180.192          int            nSamples, nPatches;    // Cols, Rows
 180.193          int            SampleID;              // Pos of ID
 180.194  
 180.195 -        LPKEYVALUE     HeaderList;            // The properties
 180.196 +        KEYVALUE*      HeaderList;            // The properties
 180.197  
 180.198          char**         DataFormat;            // The binary stream descriptor
 180.199          char**         Data;                  // The binary stream
 180.200  
 180.201 -    } TABLE, *LPTABLE;
 180.202 +    } TABLE;
 180.203  
 180.204  // File stream being parsed
 180.205 -
 180.206  typedef struct _FileContext {
 180.207 -        char           FileName[MAX_PATH];    // File name if being readed from file
 180.208 -        FILE*          Stream;                // File stream or NULL if holded in memory
 180.209 -    } FILECTX, *LPFILECTX;
 180.210 -
 180.211 -// This struct hold all information about an openened
 180.212 -// IT8 handler. Only one dataset is allowed.
 180.213 -
 180.214 +        char           FileName[cmsMAX_PATH];    // File name if being readed from file
 180.215 +        FILE*          Stream;                   // File stream or NULL if holded in memory
 180.216 +    } FILECTX;
 180.217 +
 180.218 +// This struct hold all information about an open IT8 handler.
 180.219  typedef struct {
 180.220  
 180.221 -        char SheetType[MAXSTR];
 180.222 -
 180.223 -        int  TablesCount;                     // How many tables in this stream
 180.224 -        int  nTable;                          // The actual table
 180.225 +        char SheetType[MAXSTR];               // The first row of the IT8 (the type)
 180.226 +
 180.227 +        cmsUInt32Number  TablesCount;                     // How many tables in this stream
 180.228 +        cmsUInt32Number  nTable;                          // The actual table
 180.229  
 180.230          TABLE Tab[MAXTABLES];
 180.231  
 180.232          // Memory management
 180.233 -
 180.234 -        LPOWNEDMEM     MemorySink;            // The storage backend
 180.235 +        OWNEDMEM*      MemorySink;            // The storage backend
 180.236          SUBALLOCATOR   Allocator;             // String suballocator -- just to keep it fast
 180.237  
 180.238          // Parser state machine
 180.239 -
 180.240          SYMBOL         sy;                    // Current symbol
 180.241          int            ch;                    // Current character
 180.242  
 180.243          int            inum;                  // integer value
 180.244 -        double         dnum;                  // real value
 180.245 +        cmsFloat64Number         dnum;                  // real value
 180.246          char           id[MAXID];             // identifier
 180.247          char           str[MAXSTR];           // string
 180.248  
 180.249          // Allowed keywords & datasets. They have visibility on whole stream
 180.250 -
 180.251 -        LPKEYVALUE     ValidKeywords;
 180.252 -        LPKEYVALUE     ValidSampleID;
 180.253 +        KEYVALUE*     ValidKeywords;
 180.254 +        KEYVALUE*     ValidSampleID;
 180.255  
 180.256          char*          Source;                // Points to loc. being parsed
 180.257          int            lineno;                // line counter for error reporting
 180.258  
 180.259 -        LPFILECTX      FileStack[MAXINCLUDE]; // Stack of files being parsed
 180.260 +        FILECTX*       FileStack[MAXINCLUDE]; // Stack of files being parsed
 180.261          int            IncludeSP;             // Include Stack Pointer
 180.262  
 180.263          char*          MemoryBlock;           // The stream if holded in memory
 180.264  
 180.265 -        char           DoubleFormatter[MAXID];   // Printf-like 'double' formatter
 180.266 -
 180.267 -   } IT8, *LPIT8;
 180.268 -
 180.269 -
 180.270 -
 180.271 +        char           DoubleFormatter[MAXID];// Printf-like 'cmsFloat64Number' formatter
 180.272 +
 180.273 +        cmsContext    ContextID;              // The threading context
 180.274 +
 180.275 +   } cmsIT8;
 180.276 +
 180.277 +
 180.278 +// The stream for save operations
 180.279  typedef struct {
 180.280  
 180.281          FILE* stream;   // For save-to-file behaviour
 180.282  
 180.283 -        LPBYTE Base;
 180.284 -        LPBYTE Ptr;     // For save-to-mem behaviour
 180.285 -        size_t Used;
 180.286 -        size_t Max;
 180.287 -
 180.288 -    } SAVESTREAM, FAR* LPSAVESTREAM;
 180.289 -
 180.290 -
 180.291 -// ------------------------------------------------------ IT8 parsing routines
 180.292 +        cmsUInt8Number* Base;
 180.293 +        cmsUInt8Number* Ptr;        // For save-to-mem behaviour
 180.294 +        cmsUInt32Number Used;
 180.295 +        cmsUInt32Number Max;
 180.296 +
 180.297 +    } SAVESTREAM;
 180.298 +
 180.299 +
 180.300 +// ------------------------------------------------------ cmsIT8 parsing routines
 180.301  
 180.302  
 180.303  // A keyword
 180.304 @@ -309,14 +228,15 @@
 180.305  // The keyword->symbol translation table. Sorting is required.
 180.306  static const KEYWORD TabKeys[] = {
 180.307  
 180.308 -        {"$INCLUDE",            SINCLUDE},
 180.309 -        {".INCLUDE",            SINCLUDE},
 180.310 -        {"BEGIN_DATA",          SBEGIN_DATA },
 180.311 -        {"BEGIN_DATA_FORMAT",   SBEGIN_DATA_FORMAT },
 180.312 +        {"$INCLUDE",               SINCLUDE},   // This is an extension!
 180.313 +        {".INCLUDE",               SINCLUDE},   // This is an extension!
 180.314 +
 180.315 +        {"BEGIN_DATA",             SBEGIN_DATA },
 180.316 +        {"BEGIN_DATA_FORMAT",      SBEGIN_DATA_FORMAT },
 180.317          {"DATA_FORMAT_IDENTIFIER", SDATA_FORMAT_ID},
 180.318 -        {"END_DATA",            SEND_DATA},
 180.319 -        {"END_DATA_FORMAT",     SEND_DATA_FORMAT},
 180.320 -        {"KEYWORD",             SKEYWORD}
 180.321 +        {"END_DATA",               SEND_DATA},
 180.322 +        {"END_DATA_FORMAT",        SEND_DATA_FORMAT},
 180.323 +        {"KEYWORD",                SKEYWORD}
 180.324          };
 180.325  
 180.326  #define NUMKEYS (sizeof(TabKeys)/sizeof(KEYWORD))
 180.327 @@ -325,8 +245,8 @@
 180.328  
 180.329  // A property
 180.330  typedef struct {
 180.331 -        const char *id;
 180.332 -        WRITEMODE as;
 180.333 +        const char *id;    // The identifier
 180.334 +        WRITEMODE as;      // How is supposed to be written
 180.335      } PROPERTY;
 180.336  
 180.337  static PROPERTY PredefinedProperties[] = {
 180.338 @@ -366,7 +286,8 @@
 180.339  
 180.340          {"CHISQ_DOF",        WRITE_STRINGIFY},   // Degrees of freedom associated with the Chi squared statistic
 180.341  
 180.342 -//    new in recent specs:
 180.343 +       // below properties are new in recent specs:
 180.344 +
 180.345          {"MEASUREMENT_GEOMETRY", WRITE_STRINGIFY}, // The type of measurement, either reflection or transmission, should be indicated
 180.346                                 // along with details of the geometry and the aperture size and shape. For example,
 180.347                                 // for transmission measurements it is important to identify 0/diffuse, diffuse/0,
 180.348 @@ -438,9 +359,9 @@
 180.349          "LAB_B",          // b* component of Lab data
 180.350          "LAB_C",          // C*ab component of Lab data
 180.351          "LAB_H",          // hab component of Lab data
 180.352 -        "LAB_DE",         //  CIE dE
 180.353 -        "LAB_DE_94",      //  CIE dE using CIE 94
 180.354 -        "LAB_DE_CMC",     //  dE using CMC
 180.355 +        "LAB_DE",         // CIE dE
 180.356 +        "LAB_DE_94",      // CIE dE using CIE 94
 180.357 +        "LAB_DE_CMC",     // dE using CMC
 180.358          "LAB_DE_2000",    // CIE dE using CIE DE 2000
 180.359          "MEAN_DE",        // Mean Delta E (LAB_DE) of samples compared to batch average
 180.360                            // (Used for data files for ANSI IT8.7/1 and IT8.7/2 targets)
 180.361 @@ -458,84 +379,94 @@
 180.362  #define NUMPREDEFINEDSAMPLEID (sizeof(PredefinedSampleID)/sizeof(char *))
 180.363  
 180.364  //Forward declaration of some internal functions
 180.365 -static
 180.366 -void* AllocChunk(LPIT8 it8, size_t size);
 180.367 +static void* AllocChunk(cmsIT8* it8, cmsUInt32Number size);
 180.368  
 180.369  // Checks if c is a separator
 180.370  static
 180.371 -LCMSBOOL isseparator(int c)
 180.372 +cmsBool isseparator(int c)
 180.373  {
 180.374          return (c == ' ') || (c == '\t') || (c == '\r');
 180.375  }
 180.376  
 180.377  // Checks whatever if c is a valid identifier char
 180.378  static
 180.379 -LCMSBOOL ismiddle(int c)
 180.380 +cmsBool ismiddle(int c)
 180.381  {
 180.382     return (!isseparator(c) && (c != '#') && (c !='\"') && (c != '\'') && (c > 32) && (c < 127));
 180.383  }
 180.384  
 180.385  // Checks whatsever if c is a valid identifier middle char.
 180.386  static
 180.387 -LCMSBOOL isidchar(int c)
 180.388 +cmsBool isidchar(int c)
 180.389  {
 180.390     return isalnum(c) || ismiddle(c);
 180.391  }
 180.392  
 180.393  // Checks whatsever if c is a valid identifier first char.
 180.394  static
 180.395 -LCMSBOOL isfirstidchar(int c)
 180.396 +cmsBool isfirstidchar(int c)
 180.397  {
 180.398       return !isdigit(c) && ismiddle(c);
 180.399  }
 180.400  
 180.401 -// checks whether the supplied path looks like an absolute path
 180.402 -// NOTE: this function doesn't checks if the path exists or even if it's legal
 180.403 +// Guess whether the supplied path looks like an absolute path
 180.404  static
 180.405 -LCMSBOOL isabsolutepath(const char *path)
 180.406 +cmsBool isabsolutepath(const char *path)
 180.407  {
 180.408 +    char ThreeChars[4];
 180.409 +
 180.410      if(path == NULL)
 180.411          return FALSE;
 180.412 -
 180.413 -    if(path[0] == DIR_CHAR)
 180.414 +    if (path[0] == 0)
 180.415 +        return FALSE;
 180.416 +
 180.417 +    strncpy(ThreeChars, path, 3);
 180.418 +    ThreeChars[3] = 0;
 180.419 +
 180.420 +    if(ThreeChars[0] == DIR_CHAR)
 180.421          return TRUE;
 180.422  
 180.423 -#ifndef NON_WINDOWS
 180.424 -    if(isalpha(path[0]) && path[1] == ':')
 180.425 +#ifdef  CMS_IS_WINDOWS_
 180.426 +    if (isalpha((int) ThreeChars[0]) && ThreeChars[1] == ':')
 180.427          return TRUE;
 180.428  #endif
 180.429      return FALSE;
 180.430  }
 180.431  
 180.432  // Makes a file path based on a given reference path
 180.433 -// NOTE: buffer is assumed to point to at least MAX_PATH bytes
 180.434 -// NOTE: both relPath and basePath are assumed to be no more than MAX_PATH characters long (including the null terminator!)
 180.435  // NOTE: this function doesn't check if the path exists or even if it's legal
 180.436  static
 180.437 -LCMSBOOL _cmsMakePath(const char *relPath, const char *basePath, char *buffer)
 180.438 +cmsBool BuildAbsolutePath(const char *relPath, const char *basePath, char *buffer, cmsUInt32Number MaxLen)
 180.439  {
 180.440 -    if (!isabsolutepath(relPath)) {
 180.441 -
 180.442 -        char *tail;
 180.443 -
 180.444 -        strncpy(buffer, basePath, MAX_PATH-1);
 180.445 -        tail = strrchr(buffer, DIR_CHAR);
 180.446 -        if (tail != NULL) {
 180.447 -
 180.448 -            size_t len = tail - buffer;
 180.449 -            strncpy(tail + 1, relPath, MAX_PATH - len -1);
 180.450 -            //  TODO: if combined path is longer than MAX_PATH, this should return FALSE!
 180.451 -            return TRUE;
 180.452 -        }
 180.453 +    char *tail;
 180.454 +    cmsUInt32Number len;
 180.455 +
 180.456 +    // Already absolute?
 180.457 +    if (isabsolutepath(relPath)) {
 180.458 +
 180.459 +        strncpy(buffer, relPath, MaxLen);
 180.460 +        buffer[MaxLen-1] = 0;
 180.461 +        return TRUE;
 180.462      }
 180.463 -    strncpy(buffer, relPath, MAX_PATH - 1);
 180.464 -        buffer[MAX_PATH-1] = 0;
 180.465 +
 180.466 +    // No, search for last
 180.467 +    strncpy(buffer, basePath, MaxLen);
 180.468 +    buffer[MaxLen-1] = 0;
 180.469 +
 180.470 +    tail = strrchr(buffer, DIR_CHAR);
 180.471 +    if (tail == NULL) return FALSE;    // Is not absolute and has no separators??
 180.472 +
 180.473 +    len = (cmsUInt32Number) (tail - buffer);
 180.474 +    if (len >= MaxLen) return FALSE;
 180.475 +
 180.476 +    // No need to assure zero terminator over here
 180.477 +    strncpy(tail + 1, relPath, MaxLen - len);
 180.478 +
 180.479      return TRUE;
 180.480  }
 180.481  
 180.482  
 180.483  // Make sure no exploit is being even tried
 180.484 -
 180.485  static
 180.486  const char* NoMeta(const char* str)
 180.487  {
 180.488 @@ -545,40 +476,37 @@
 180.489      return str;
 180.490  }
 180.491  
 180.492 -
 180.493  // Syntax error
 180.494  static
 180.495 -LCMSBOOL SynError(LPIT8 it8, const char *Txt, ...)
 180.496 +cmsBool SynError(cmsIT8* it8, const char *Txt, ...)
 180.497  {
 180.498 -        char Buffer[256], ErrMsg[1024];
 180.499 -        va_list args;
 180.500 -
 180.501 -        va_start(args, Txt);
 180.502 -        vsnprintf(Buffer, 255, Txt, args);
 180.503 -        Buffer[255] = 0;
 180.504 -        va_end(args);
 180.505 -
 180.506 -        snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer);
 180.507 -        ErrMsg[1023] = 0;
 180.508 -        it8->sy = SSYNERROR;
 180.509 -        cmsSignalError(LCMS_ERRC_ABORTED, "%s", ErrMsg);
 180.510 -        return FALSE;
 180.511 +    char Buffer[256], ErrMsg[1024];
 180.512 +    va_list args;
 180.513 +
 180.514 +    va_start(args, Txt);
 180.515 +    vsnprintf(Buffer, 255, Txt, args);
 180.516 +    Buffer[255] = 0;
 180.517 +    va_end(args);
 180.518 +
 180.519 +    snprintf(ErrMsg, 1023, "%s: Line %d, %s", it8->FileStack[it8 ->IncludeSP]->FileName, it8->lineno, Buffer);
 180.520 +    ErrMsg[1023] = 0;
 180.521 +    it8->sy = SSYNERROR;
 180.522 +    cmsSignalError(it8 ->ContextID, cmsERROR_CORRUPTION_DETECTED, "%s", ErrMsg);
 180.523 +    return FALSE;
 180.524  }
 180.525  
 180.526  // Check if current symbol is same as specified. issue an error else.
 180.527  static
 180.528 -LCMSBOOL Check(LPIT8 it8, SYMBOL sy, const char* Err)
 180.529 +cmsBool Check(cmsIT8* it8, SYMBOL sy, const char* Err)
 180.530  {
 180.531          if (it8 -> sy != sy)
 180.532                  return SynError(it8, NoMeta(Err));
 180.533          return TRUE;
 180.534  }
 180.535  
 180.536 -
 180.537 -
 180.538  // Read Next character from stream
 180.539  static
 180.540 -void NextCh(LPIT8 it8)
 180.541 +void NextCh(cmsIT8* it8)
 180.542  {
 180.543      if (it8 -> FileStack[it8 ->IncludeSP]->Stream) {
 180.544  
 180.545 @@ -594,9 +522,6 @@
 180.546              } else
 180.547                  it8 ->ch = 0;   // EOF
 180.548          }
 180.549 -
 180.550 -
 180.551 -
 180.552      }
 180.553      else {
 180.554          it8->ch = *it8->Source;
 180.555 @@ -609,100 +534,98 @@
 180.556  static
 180.557  SYMBOL BinSrchKey(const char *id)
 180.558  {
 180.559 -        int l = 1;
 180.560 -        int r = NUMKEYS;
 180.561 -        int x, res;
 180.562 -
 180.563 -        while (r >= l)
 180.564 -        {
 180.565 -                x = (l+r)/2;
 180.566 -                res = stricmp(id, TabKeys[x-1].id);
 180.567 -                if (res == 0) return TabKeys[x-1].sy;
 180.568 -                if (res < 0) r = x - 1;
 180.569 -                else l = x + 1;
 180.570 -        }
 180.571 -
 180.572 -        return SNONE;
 180.573 +    int l = 1;
 180.574 +    int r = NUMKEYS;
 180.575 +    int x, res;
 180.576 +
 180.577 +    while (r >= l)
 180.578 +    {
 180.579 +        x = (l+r)/2;
 180.580 +        res = cmsstrcasecmp(id, TabKeys[x-1].id);
 180.581 +        if (res == 0) return TabKeys[x-1].sy;
 180.582 +        if (res < 0) r = x - 1;
 180.583 +        else l = x + 1;
 180.584 +    }
 180.585 +
 180.586 +    return SNONE;
 180.587  }
 180.588  
 180.589  
 180.590  // 10 ^n
 180.591  static
 180.592 -double xpow10(int n)
 180.593 +cmsFloat64Number xpow10(int n)
 180.594  {
 180.595 -    return pow(10, (double) n);
 180.596 +    return pow(10, (cmsFloat64Number) n);
 180.597  }
 180.598  
 180.599  
 180.600  //  Reads a Real number, tries to follow from integer number
 180.601  static
 180.602 -void ReadReal(LPIT8 it8, int inum)
 180.603 +void ReadReal(cmsIT8* it8, int inum)
 180.604  {
 180.605 -        it8->dnum = (double) inum;
 180.606 -
 180.607 -        while (isdigit(it8->ch)) {
 180.608 +    it8->dnum = (cmsFloat64Number) inum;
 180.609 +
 180.610 +    while (isdigit(it8->ch)) {
 180.611  
 180.612          it8->dnum = it8->dnum * 10.0 + (it8->ch - '0');
 180.613          NextCh(it8);
 180.614 +    }
 180.615 +
 180.616 +    if (it8->ch == '.') {        // Decimal point
 180.617 +
 180.618 +        cmsFloat64Number frac = 0.0;      // fraction
 180.619 +        int prec = 0;           // precision
 180.620 +
 180.621 +        NextCh(it8);               // Eats dec. point
 180.622 +
 180.623 +        while (isdigit(it8->ch)) {
 180.624 +
 180.625 +            frac = frac * 10.0 + (it8->ch - '0');
 180.626 +            prec++;
 180.627 +            NextCh(it8);
 180.628          }
 180.629  
 180.630 -        if (it8->ch == '.') {        // Decimal point
 180.631 -
 180.632 -                double frac = 0.0;      // fraction
 180.633 -                int prec = 0;           // precission
 180.634 -
 180.635 -                NextCh(it8);               // Eats dec. point
 180.636 -
 180.637 -                while (isdigit(it8->ch)) {
 180.638 -
 180.639 -                        frac = frac * 10.0 + (it8->ch - '0');
 180.640 -                        prec++;
 180.641 -                        NextCh(it8);
 180.642 -                }
 180.643 -
 180.644 -                it8->dnum = it8->dnum + (frac / xpow10(prec));
 180.645 +        it8->dnum = it8->dnum + (frac / xpow10(prec));
 180.646 +    }
 180.647 +
 180.648 +    // Exponent, example 34.00E+20
 180.649 +    if (toupper(it8->ch) == 'E') {
 180.650 +
 180.651 +        int e;
 180.652 +        int sgn;
 180.653 +
 180.654 +        NextCh(it8); sgn = 1;
 180.655 +
 180.656 +        if (it8->ch == '-') {
 180.657 +
 180.658 +            sgn = -1; NextCh(it8);
 180.659          }
 180.660 -
 180.661 -        // Exponent, example 34.00E+20
 180.662 -        if (toupper(it8->ch) == 'E') {
 180.663 -
 180.664 -                int e;
 180.665 -                int sgn;
 180.666 -
 180.667 -                NextCh(it8); sgn = 1;
 180.668 -
 180.669 -                if (it8->ch == '-') {
 180.670 -
 180.671 -                        sgn = -1; NextCh(it8);
 180.672 -                }
 180.673 -                else
 180.674 -                if (it8->ch == '+') {
 180.675 -
 180.676 -                        sgn = +1;
 180.677 -                        NextCh(it8);
 180.678 -                }
 180.679 -
 180.680 -
 180.681 -                e = 0;
 180.682 -                while (isdigit(it8->ch)) {
 180.683 -
 180.684 -                        if ((double) e * 10L < INT_MAX)
 180.685 -                            e = e * 10 + (it8->ch - '0');
 180.686 -
 180.687 -                        NextCh(it8);
 180.688 -                }
 180.689 -
 180.690 -                e = sgn*e;
 180.691 -
 180.692 -                it8 -> dnum = it8 -> dnum * xpow10(e);
 180.693 -        }
 180.694 +        else
 180.695 +            if (it8->ch == '+') {
 180.696 +
 180.697 +                sgn = +1;
 180.698 +                NextCh(it8);
 180.699 +            }
 180.700 +
 180.701 +            e = 0;
 180.702 +            while (isdigit(it8->ch)) {
 180.703 +
 180.704 +                if ((cmsFloat64Number) e * 10L < INT_MAX)
 180.705 +                    e = e * 10 + (it8->ch - '0');
 180.706 +
 180.707 +                NextCh(it8);
 180.708 +            }
 180.709 +
 180.710 +            e = sgn*e;
 180.711 +            it8 -> dnum = it8 -> dnum * xpow10(e);
 180.712 +    }
 180.713  }
 180.714  
 180.715  
 180.716  
 180.717  // Reads next symbol
 180.718  static
 180.719 -void InSymbol(LPIT8 it8)
 180.720 +void InSymbol(cmsIT8* it8)
 180.721  {
 180.722      register char *idptr;
 180.723      register int k;
 180.724 @@ -716,7 +639,6 @@
 180.725  
 180.726          if (isfirstidchar(it8->ch)) {          // Identifier
 180.727  
 180.728 -
 180.729              k = 0;
 180.730              idptr = it8->id;
 180.731  
 180.732 @@ -845,7 +767,6 @@
 180.733                      } while (isidchar(it8->ch));
 180.734  
 180.735                      *idptr = '\0';
 180.736 -
 180.737                      it8->sy = SIDENT;
 180.738                  }
 180.739                  return;
 180.740 @@ -860,7 +781,6 @@
 180.741              break;
 180.742  
 180.743          // Eof stream markers
 180.744 -
 180.745          case 0:
 180.746          case -1:
 180.747              it8->sy = SEOF;
 180.748 @@ -868,7 +788,6 @@
 180.749  
 180.750  
 180.751          // Next line
 180.752 -
 180.753          case '\n':
 180.754              NextCh(it8);
 180.755              it8->sy = SEOLN;
 180.756 @@ -876,7 +795,6 @@
 180.757              break;
 180.758  
 180.759          // Comment
 180.760 -
 180.761          case '#':
 180.762              NextCh(it8);
 180.763              while (it8->ch && it8->ch != '\n')
 180.764 @@ -885,8 +803,7 @@
 180.765              it8->sy = SCOMMENT;
 180.766              break;
 180.767  
 180.768 -            // String.
 180.769 -
 180.770 +        // String.
 180.771          case '\'':
 180.772          case '\"':
 180.773              idptr = it8->str;
 180.774 @@ -921,10 +838,10 @@
 180.775  
 180.776      if (it8 -> sy == SINCLUDE) {
 180.777  
 180.778 -                LPFILECTX FileNest;
 180.779 -
 180.780 -                if(it8 -> IncludeSP >= (MAXINCLUDE-1))
 180.781 -                {
 180.782 +                FILECTX* FileNest;
 180.783 +
 180.784 +                if(it8 -> IncludeSP >= (MAXINCLUDE-1)) {
 180.785 +
 180.786                      SynError(it8, "Too many recursion levels");
 180.787                      return;
 180.788                  }
 180.789 @@ -933,15 +850,16 @@
 180.790                  if (!Check(it8, SSTRING, "Filename expected")) return;
 180.791  
 180.792                  FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
 180.793 -                if(FileNest == NULL)
 180.794 -                {
 180.795 -                    FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
 180.796 +                if(FileNest == NULL) {
 180.797 +
 180.798 +                    FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
 180.799                      //if(FileNest == NULL)
 180.800 -                        //  TODO: how to manage out-of-memory conditions?
 180.801 +                    //  TODO: how to manage out-of-memory conditions?
 180.802                  }
 180.803  
 180.804 -                if(_cmsMakePath(it8->str, it8->FileStack[it8->IncludeSP]->FileName, FileNest->FileName) == FALSE)
 180.805 -                {
 180.806 +                if (BuildAbsolutePath(it8->str,
 180.807 +                                      it8->FileStack[it8->IncludeSP]->FileName,
 180.808 +                                      FileNest->FileName, cmsMAX_PATH-1) == FALSE) {
 180.809                      SynError(it8, "File path too long");
 180.810                      return;
 180.811                  }
 180.812 @@ -962,7 +880,7 @@
 180.813  
 180.814  // Checks end of line separator
 180.815  static
 180.816 -LCMSBOOL CheckEOLN(LPIT8 it8)
 180.817 +cmsBool CheckEOLN(cmsIT8* it8)
 180.818  {
 180.819          if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
 180.820          while (it8 -> sy == SEOLN)
 180.821 @@ -974,7 +892,7 @@
 180.822  // Skip a symbol
 180.823  
 180.824  static
 180.825 -void Skip(LPIT8 it8, SYMBOL sy)
 180.826 +void Skip(cmsIT8* it8, SYMBOL sy)
 180.827  {
 180.828          if (it8->sy == sy && it8->sy != SEOF)
 180.829                          InSymbol(it8);
 180.830 @@ -983,7 +901,7 @@
 180.831  
 180.832  // Skip multiple EOLN
 180.833  static
 180.834 -void SkipEOLN(LPIT8 it8)
 180.835 +void SkipEOLN(cmsIT8* it8)
 180.836  {
 180.837      while (it8->sy == SEOLN) {
 180.838               InSymbol(it8);
 180.839 @@ -993,7 +911,7 @@
 180.840  
 180.841  // Returns a string holding current value
 180.842  static
 180.843 -LCMSBOOL GetVal(LPIT8 it8, char* Buffer, size_t max, const char* ErrorTitle)
 180.844 +cmsBool GetVal(cmsIT8* it8, char* Buffer, cmsUInt32Number max, const char* ErrorTitle)
 180.845  {
 180.846      switch (it8->sy) {
 180.847  
 180.848 @@ -1018,9 +936,9 @@
 180.849  // ---------------------------------------------------------- Table
 180.850  
 180.851  static
 180.852 -LPTABLE GetTable(LPIT8 it8)
 180.853 +TABLE* GetTable(cmsIT8* it8)
 180.854  {
 180.855 -   if ((it8 -> nTable >= it8 ->TablesCount) || (it8 -> nTable < 0)) {
 180.856 +   if ((it8 -> nTable >= it8 ->TablesCount)) {
 180.857  
 180.858             SynError(it8, "Table %d out of sequence", it8 -> nTable);
 180.859             return it8 -> Tab;
 180.860 @@ -1032,75 +950,70 @@
 180.861  // ---------------------------------------------------------- Memory management
 180.862  
 180.863  
 180.864 -
 180.865  // Frees an allocator and owned memory
 180.866 -void LCMSEXPORT cmsIT8Free(LCMSHANDLE hIT8)
 180.867 +void CMSEXPORT cmsIT8Free(cmsHANDLE hIT8)
 180.868  {
 180.869 -   LPIT8 it8 = (LPIT8) hIT8;
 180.870 +   cmsIT8* it8 = (cmsIT8*) hIT8;
 180.871  
 180.872      if (it8 == NULL)
 180.873          return;
 180.874  
 180.875 -
 180.876      if (it8->MemorySink) {
 180.877  
 180.878 -        LPOWNEDMEM p;
 180.879 -        LPOWNEDMEM n;
 180.880 +        OWNEDMEM* p;
 180.881 +        OWNEDMEM* n;
 180.882  
 180.883          for (p = it8->MemorySink; p != NULL; p = n) {
 180.884  
 180.885              n = p->Next;
 180.886 -            if (p->Ptr) _cmsFree(p->Ptr);
 180.887 -            _cmsFree(p);
 180.888 +            if (p->Ptr) _cmsFree(it8 ->ContextID, p->Ptr);
 180.889 +            _cmsFree(it8 ->ContextID, p);
 180.890          }
 180.891      }
 180.892  
 180.893      if (it8->MemoryBlock)
 180.894 -        _cmsFree(it8->MemoryBlock);
 180.895 -
 180.896 -     _cmsFree(it8);
 180.897 +        _cmsFree(it8 ->ContextID, it8->MemoryBlock);
 180.898 +
 180.899 +    _cmsFree(it8 ->ContextID, it8);
 180.900  }
 180.901  
 180.902  
 180.903  // Allocates a chunk of data, keep linked list
 180.904  static
 180.905 -void* AllocBigBlock(LPIT8 it8, size_t size)
 180.906 +void* AllocBigBlock(cmsIT8* it8, cmsUInt32Number size)
 180.907  {
 180.908 -   LPOWNEDMEM ptr1;
 180.909 -   void* ptr = _cmsMalloc(size);
 180.910 -
 180.911 -        if (ptr) {
 180.912 -
 180.913 -                ZeroMemory(ptr, size);
 180.914 -                ptr1 = (LPOWNEDMEM) _cmsMalloc(sizeof(OWNEDMEM));
 180.915 -
 180.916 -                if (ptr1 == NULL) {
 180.917 -
 180.918 -                     _cmsFree(ptr);
 180.919 -                    return NULL;
 180.920 -                }
 180.921 -
 180.922 -                ZeroMemory(ptr1, sizeof(OWNEDMEM));
 180.923 -
 180.924 -                ptr1-> Ptr        = ptr;
 180.925 -                ptr1-> Next       = it8 -> MemorySink;
 180.926 -                it8 -> MemorySink = ptr1;
 180.927 +    OWNEDMEM* ptr1;
 180.928 +    void* ptr = _cmsMallocZero(it8->ContextID, size);
 180.929 +
 180.930 +    if (ptr != NULL) {
 180.931 +
 180.932 +        ptr1 = (OWNEDMEM*) _cmsMallocZero(it8 ->ContextID, sizeof(OWNEDMEM));
 180.933 +
 180.934 +        if (ptr1 == NULL) {
 180.935 +
 180.936 +            _cmsFree(it8 ->ContextID, ptr);
 180.937 +            return NULL;
 180.938          }
 180.939  
 180.940 -        return ptr;
 180.941 +        ptr1-> Ptr        = ptr;
 180.942 +        ptr1-> Next       = it8 -> MemorySink;
 180.943 +        it8 -> MemorySink = ptr1;
 180.944 +    }
 180.945 +
 180.946 +    return ptr;
 180.947  }
 180.948  
 180.949  
 180.950  // Suballocator.
 180.951  static
 180.952 -void* AllocChunk(LPIT8 it8, size_t size)
 180.953 +void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
 180.954  {
 180.955 -    size_t free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used;
 180.956 -    LPBYTE ptr;
 180.957 -
 180.958 -    size = ALIGNLONG(size);
 180.959 -
 180.960 -    if (size > free) {
 180.961 +    cmsUInt32Number Free = it8 ->Allocator.BlockSize - it8 ->Allocator.Used;
 180.962 +    cmsUInt8Number* ptr;
 180.963 +
 180.964 +    size = _cmsALIGNLONG(size);
 180.965 +
 180.966 +    if (size > Free) {
 180.967  
 180.968          if (it8 -> Allocator.BlockSize == 0)
 180.969  
 180.970 @@ -1112,7 +1025,7 @@
 180.971                  it8 ->Allocator.BlockSize = size;
 180.972  
 180.973          it8 ->Allocator.Used = 0;
 180.974 -        it8 ->Allocator.Block = (LPBYTE) AllocBigBlock(it8, it8 ->Allocator.BlockSize);
 180.975 +        it8 ->Allocator.Block = (cmsUInt8Number*)  AllocBigBlock(it8, it8 ->Allocator.BlockSize);
 180.976      }
 180.977  
 180.978      ptr = it8 ->Allocator.Block + it8 ->Allocator.Used;
 180.979 @@ -1125,9 +1038,9 @@
 180.980  
 180.981  // Allocates a string
 180.982  static
 180.983 -char *AllocString(LPIT8 it8, const char* str)
 180.984 +char *AllocString(cmsIT8* it8, const char* str)
 180.985  {
 180.986 -    size_t Size = strlen(str)+1;
 180.987 +    cmsUInt32Number Size = (cmsUInt32Number) strlen(str)+1;
 180.988      char *ptr;
 180.989  
 180.990  
 180.991 @@ -1140,7 +1053,7 @@
 180.992  // Searches through linked list
 180.993  
 180.994  static
 180.995 -LCMSBOOL IsAvailableOnList(LPKEYVALUE p, const char* Key, const char* Subkey, LPKEYVALUE* LastPtr)
 180.996 +cmsBool IsAvailableOnList(KEYVALUE* p, const char* Key, const char* Subkey, KEYVALUE** LastPtr)
 180.997  {
 180.998      if (LastPtr) *LastPtr = p;
 180.999  
180.1000 @@ -1150,7 +1063,7 @@
180.1001  
180.1002          if (*Key != '#') { // Comments are ignored
180.1003  
180.1004 -            if (stricmp(Key, p->Keyword) == 0)
180.1005 +            if (cmsstrcasecmp(Key, p->Keyword) == 0)
180.1006                      break;
180.1007          }
180.1008          }
180.1009 @@ -1165,9 +1078,9 @@
180.1010  
180.1011          if (LastPtr) *LastPtr = p;
180.1012  
180.1013 -        if (stricmp(Subkey, p->Subkey) == 0)
180.1014 -            return TRUE;
180.1015 -    }
180.1016 +        if (cmsstrcasecmp(Subkey, p->Subkey) == 0)
180.1017 +                    return TRUE;
180.1018 +        }
180.1019  
180.1020      return FALSE;
180.1021  }
180.1022 @@ -1176,55 +1089,62 @@
180.1023  
180.1024  // Add a property into a linked list
180.1025  static
180.1026 -LPKEYVALUE AddToList(LPIT8 it8, LPKEYVALUE* Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs)
180.1027 +KEYVALUE* AddToList(cmsIT8* it8, KEYVALUE** Head, const char *Key, const char *Subkey, const char* xValue, WRITEMODE WriteAs)
180.1028  {
180.1029 -    LPKEYVALUE p;
180.1030 -
180.1031 -    // Check if property is already in list (this is an error)
180.1032 +    KEYVALUE* p;
180.1033 +    KEYVALUE* last;
180.1034 +
180.1035 +
180.1036 +    // Check if property is already in list
180.1037  
180.1038      if (IsAvailableOnList(*Head, Key, Subkey, &p)) {
180.1039  
180.1040 -            // This may work for editing properties
180.1041 +        // This may work for editing properties
180.1042  
180.1043          //     return SynError(it8, "duplicate key <%s>", Key);
180.1044      }
180.1045      else {
180.1046 -        LPKEYVALUE last = p;
180.1047 -
180.1048 -    // Allocate the container
180.1049 -    p = (LPKEYVALUE) AllocChunk(it8, sizeof(KEYVALUE));
180.1050 -    if (p == NULL)
180.1051 -    {
180.1052 +
180.1053 +        last = p;
180.1054 +
180.1055 +        // Allocate the container
180.1056 +        p = (KEYVALUE*) AllocChunk(it8, sizeof(KEYVALUE));
180.1057 +        if (p == NULL)
180.1058 +        {
180.1059              SynError(it8, "AddToList: out of memory");
180.1060              return NULL;
180.1061 -    }
180.1062 -
180.1063 -    // Store name and value
180.1064 -    p->Keyword = AllocString(it8, Key);
180.1065 +        }
180.1066 +
180.1067 +        // Store name and value
180.1068 +        p->Keyword = AllocString(it8, Key);
180.1069          p->Subkey = (Subkey == NULL) ? NULL : AllocString(it8, Subkey);
180.1070  
180.1071          // Keep the container in our list
180.1072 -        if (*Head == NULL)
180.1073 +        if (*Head == NULL) {
180.1074              *Head = p;
180.1075 +        }
180.1076          else
180.1077          {
180.1078 -            if(Subkey != 0 && last != 0) {
180.1079 +            if (Subkey != NULL && last != NULL) {
180.1080 +
180.1081                  last->NextSubkey = p;
180.1082  
180.1083                  // If Subkey is not null, then last is the last property with the same key,
180.1084                  // but not necessarily is the last property in the list, so we need to move
180.1085                  // to the actual list end
180.1086 -                while(last->Next != 0)
180.1087 -                    last = last->Next;
180.1088 -    }
180.1089 -            last->Next = p;
180.1090 -    }
180.1091 -
180.1092 -    p->Next    = NULL;
180.1093 +                while (last->Next != NULL)
180.1094 +                         last = last->Next;
180.1095 +            }
180.1096 +
180.1097 +            if (last != NULL) last->Next = p;
180.1098 +        }
180.1099 +
180.1100 +        p->Next    = NULL;
180.1101          p->NextSubkey = NULL;
180.1102      }
180.1103  
180.1104      p->WriteAs = WriteAs;
180.1105 +
180.1106      if (xValue != NULL) {
180.1107  
180.1108          p->Value   = AllocString(it8, xValue);
180.1109 @@ -1237,23 +1157,23 @@
180.1110  }
180.1111  
180.1112  static
180.1113 -LPKEYVALUE AddAvailableProperty(LPIT8 it8, const char* Key, WRITEMODE as)
180.1114 +KEYVALUE* AddAvailableProperty(cmsIT8* it8, const char* Key, WRITEMODE as)
180.1115  {
180.1116 -        return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as);
180.1117 +    return AddToList(it8, &it8->ValidKeywords, Key, NULL, NULL, as);
180.1118  }
180.1119  
180.1120  
180.1121  static
180.1122 -LPKEYVALUE AddAvailableSampleID(LPIT8 it8, const char* Key)
180.1123 +KEYVALUE* AddAvailableSampleID(cmsIT8* it8, const char* Key)
180.1124  {
180.1125 -        return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED);
180.1126 +    return AddToList(it8, &it8->ValidSampleID, Key, NULL, NULL, WRITE_UNCOOKED);
180.1127  }
180.1128  
180.1129  
180.1130  static
180.1131 -void AllocTable(LPIT8 it8)
180.1132 +void AllocTable(cmsIT8* it8)
180.1133  {
180.1134 -    LPTABLE t;
180.1135 +    TABLE* t;
180.1136  
180.1137      t = it8 ->Tab + it8 ->TablesCount;
180.1138  
180.1139 @@ -1265,9 +1185,9 @@
180.1140  }
180.1141  
180.1142  
180.1143 -int LCMSEXPORT cmsIT8SetTable(LCMSHANDLE IT8, int nTable)
180.1144 +cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE  IT8, cmsUInt32Number nTable)
180.1145  {
180.1146 -     LPIT8 it8 = (LPIT8) IT8;
180.1147 +     cmsIT8* it8 = (cmsIT8*) IT8;
180.1148  
180.1149       if (nTable >= it8 ->TablesCount) {
180.1150  
180.1151 @@ -1289,16 +1209,14 @@
180.1152  
180.1153  
180.1154  // Init an empty container
180.1155 -LCMSHANDLE LCMSEXPORT cmsIT8Alloc(void)
180.1156 +cmsHANDLE  CMSEXPORT cmsIT8Alloc(cmsContext ContextID)
180.1157  {
180.1158 -    LPIT8 it8;
180.1159 +    cmsIT8* it8;
180.1160      int i;
180.1161  
180.1162 -    it8 = (LPIT8) malloc(sizeof(IT8));
180.1163 +    it8 = (cmsIT8*) _cmsMallocZero(ContextID, sizeof(cmsIT8));
180.1164      if (it8 == NULL) return NULL;
180.1165  
180.1166 -    ZeroMemory(it8, sizeof(IT8));
180.1167 -
180.1168      AllocTable(it8);
180.1169  
180.1170      it8->MemoryBlock = NULL;
180.1171 @@ -1306,6 +1224,7 @@
180.1172  
180.1173      it8 ->nTable = 0;
180.1174  
180.1175 +    it8->ContextID = ContextID;
180.1176      it8->Allocator.Used = 0;
180.1177      it8->Allocator.Block = NULL;
180.1178      it8->Allocator.BlockSize = 0;
180.1179 @@ -1319,7 +1238,7 @@
180.1180      it8 -> inum = 0;
180.1181      it8 -> dnum = 0.0;
180.1182  
180.1183 -    it8->FileStack[0] = (LPFILECTX)AllocChunk(it8, sizeof(FILECTX));
180.1184 +    it8->FileStack[0] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
180.1185      it8->IncludeSP   = 0;
180.1186      it8 -> lineno = 1;
180.1187  
180.1188 @@ -1335,30 +1254,30 @@
180.1189              AddAvailableSampleID(it8, PredefinedSampleID[i]);
180.1190  
180.1191  
180.1192 -   return (LCMSHANDLE) it8;
180.1193 +   return (cmsHANDLE) it8;
180.1194  }
180.1195  
180.1196  
180.1197 -const char* LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8)
180.1198 +const char* CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8)
180.1199  {
180.1200 -        LPIT8 it8 = (LPIT8) hIT8;
180.1201 +        cmsIT8* it8 = (cmsIT8*) hIT8;
180.1202  
180.1203          return it8 ->SheetType;
180.1204  
180.1205  }
180.1206  
180.1207 -LCMSBOOL  LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type)
180.1208 +cmsBool CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type)
180.1209  {
180.1210 -        LPIT8 it8 = (LPIT8) hIT8;
180.1211 +        cmsIT8* it8 = (cmsIT8*) hIT8;
180.1212  
180.1213          strncpy(it8 ->SheetType, Type, MAXSTR-1);
180.1214          it8 ->SheetType[MAXSTR-1] = 0;
180.1215          return TRUE;
180.1216  }
180.1217  
180.1218 -LCMSBOOL LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* Val)
180.1219 +cmsBool CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* Val)
180.1220  {
180.1221 -    LPIT8 it8 = (LPIT8) hIT8;
180.1222 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1223  
180.1224      if (!Val) return FALSE;
180.1225      if (!*Val) return FALSE;
180.1226 @@ -1369,9 +1288,9 @@
180.1227  
180.1228  
180.1229  // Sets a property
180.1230 -LCMSBOOL LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* Key, const char *Val)
180.1231 +cmsBool CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* Key, const char *Val)
180.1232  {
180.1233 -    LPIT8 it8 = (LPIT8) hIT8;
180.1234 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1235  
180.1236      if (!Val) return FALSE;
180.1237      if (!*Val) return FALSE;
180.1238 @@ -1380,9 +1299,9 @@
180.1239  }
180.1240  
180.1241  
180.1242 -LCMSBOOL LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val)
180.1243 +cmsBool CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val)
180.1244  {
180.1245 -    LPIT8 it8 = (LPIT8) hIT8;
180.1246 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1247      char Buffer[1024];
180.1248  
180.1249      sprintf(Buffer, it8->DoubleFormatter, Val);
180.1250 @@ -1390,9 +1309,9 @@
180.1251      return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_UNCOOKED) != NULL;
180.1252  }
180.1253  
180.1254 -LCMSBOOL LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val)
180.1255 +cmsBool CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val)
180.1256  {
180.1257 -    LPIT8 it8 = (LPIT8) hIT8;
180.1258 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1259      char Buffer[1024];
180.1260  
180.1261      sprintf(Buffer, "%d", Val);
180.1262 @@ -1400,25 +1319,25 @@
180.1263      return AddToList(it8, &GetTable(it8)->HeaderList, cProp, NULL, Buffer, WRITE_HEXADECIMAL) != NULL;
180.1264  }
180.1265  
180.1266 -LCMSBOOL LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer)
180.1267 +cmsBool CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer)
180.1268  {
180.1269 -    LPIT8 it8 = (LPIT8) hIT8;
180.1270 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1271  
180.1272      return AddToList(it8, &GetTable(it8)->HeaderList, Key, NULL, Buffer, WRITE_UNCOOKED) != NULL;
180.1273  }
180.1274  
180.1275 -LCMSBOOL LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer)
180.1276 +cmsBool CMSEXPORT cmsIT8SetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char* SubKey, const char *Buffer)
180.1277  {
180.1278 -    LPIT8 it8 = (LPIT8) hIT8;
180.1279 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1280  
180.1281      return AddToList(it8, &GetTable(it8)->HeaderList, Key, SubKey, Buffer, WRITE_PAIR) != NULL;
180.1282  }
180.1283  
180.1284  // Gets a property
180.1285 -const char* LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* Key)
180.1286 +const char* CMSEXPORT cmsIT8GetProperty(cmsHANDLE hIT8, const char* Key)
180.1287  {
180.1288 -    LPIT8 it8 = (LPIT8) hIT8;
180.1289 -    LPKEYVALUE p;
180.1290 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1291 +    KEYVALUE* p;
180.1292  
180.1293      if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, NULL, &p))
180.1294      {
180.1295 @@ -1428,7 +1347,7 @@
180.1296  }
180.1297  
180.1298  
180.1299 -double LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp)
180.1300 +cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cProp)
180.1301  {
180.1302      const char *v = cmsIT8GetProperty(hIT8, cProp);
180.1303  
180.1304 @@ -1436,13 +1355,12 @@
180.1305      else return 0.0;
180.1306  }
180.1307  
180.1308 -const char* LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* Key, const char *SubKey)
180.1309 +const char* CMSEXPORT cmsIT8GetPropertyMulti(cmsHANDLE hIT8, const char* Key, const char *SubKey)
180.1310  {
180.1311 -    LPIT8 it8 = (LPIT8) hIT8;
180.1312 -    LPKEYVALUE p;
180.1313 -
180.1314 -    if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p))
180.1315 -    {
180.1316 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1317 +    KEYVALUE* p;
180.1318 +
180.1319 +    if (IsAvailableOnList(GetTable(it8) -> HeaderList, Key, SubKey, &p)) {
180.1320          return p -> Value;
180.1321      }
180.1322      return NULL;
180.1323 @@ -1452,9 +1370,9 @@
180.1324  
180.1325  
180.1326  static
180.1327 -void AllocateDataFormat(LPIT8 it8)
180.1328 +void AllocateDataFormat(cmsIT8* it8)
180.1329  {
180.1330 -    LPTABLE t = GetTable(it8);
180.1331 +    TABLE* t = GetTable(it8);
180.1332  
180.1333      if (t -> DataFormat) return;    // Already allocated
180.1334  
180.1335 @@ -1467,17 +1385,17 @@
180.1336          }
180.1337  
180.1338      t -> DataFormat = (char**) AllocChunk (it8, (t->nSamples + 1) * sizeof(char *));
180.1339 -    if (t->DataFormat == NULL)
180.1340 -    {
180.1341 +    if (t->DataFormat == NULL) {
180.1342 +
180.1343          SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
180.1344      }
180.1345  
180.1346  }
180.1347  
180.1348  static
180.1349 -const char *GetDataFormat(LPIT8 it8, int n)
180.1350 +const char *GetDataFormat(cmsIT8* it8, int n)
180.1351  {
180.1352 -    LPTABLE t = GetTable(it8);
180.1353 +    TABLE* t = GetTable(it8);
180.1354  
180.1355      if (t->DataFormat)
180.1356          return t->DataFormat[n];
180.1357 @@ -1486,16 +1404,9 @@
180.1358  }
180.1359  
180.1360  static
180.1361 -LCMSBOOL SetDataFormat(LPIT8 it8, int n, const char *label)
180.1362 +cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label)
180.1363  {
180.1364 -    LPTABLE t = GetTable(it8);
180.1365 -
180.1366 -#ifdef  STRICT_CGATS
180.1367 -    if (!IsAvailableOnList(it8-> ValidSampleID, label, NULL, NULL)) {
180.1368 -        SynError(it8, "Invalid data format '%s'.", label);
180.1369 -        return FALSE;
180.1370 -    }
180.1371 -#endif
180.1372 +    TABLE* t = GetTable(it8);
180.1373  
180.1374      if (!t->DataFormat)
180.1375          AllocateDataFormat(it8);
180.1376 @@ -1505,7 +1416,6 @@
180.1377          return FALSE;
180.1378      }
180.1379  
180.1380 -
180.1381      if (t->DataFormat) {
180.1382          t->DataFormat[n] = AllocString(it8, label);
180.1383      }
180.1384 @@ -1514,16 +1424,16 @@
180.1385  }
180.1386  
180.1387  
180.1388 -LCMSBOOL LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE h, int n, const char *Sample)
180.1389 +cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE  h, int n, const char *Sample)
180.1390  {
180.1391 -        LPIT8 it8 = (LPIT8) h;
180.1392 +        cmsIT8* it8 = (cmsIT8*) h;
180.1393          return SetDataFormat(it8, n, Sample);
180.1394  }
180.1395  
180.1396  static
180.1397 -void AllocateDataSet(LPIT8 it8)
180.1398 +void AllocateDataSet(cmsIT8* it8)
180.1399  {
180.1400 -    LPTABLE t = GetTable(it8);
180.1401 +    TABLE* t = GetTable(it8);
180.1402  
180.1403      if (t -> Data) return;    // Already allocated
180.1404  
180.1405 @@ -1531,21 +1441,20 @@
180.1406      t-> nPatches   = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
180.1407  
180.1408      t-> Data = (char**)AllocChunk (it8, (t->nSamples + 1) * (t->nPatches + 1) *sizeof (char*));
180.1409 -    if (t->Data == NULL)
180.1410 -    {
180.1411 +    if (t->Data == NULL) {
180.1412 +
180.1413          SynError(it8, "AllocateDataSet: Unable to allocate data array");
180.1414      }
180.1415  
180.1416  }
180.1417  
180.1418  static
180.1419 -char* GetData(LPIT8 it8, int nSet, int nField)
180.1420 +char* GetData(cmsIT8* it8, int nSet, int nField)
180.1421  {
180.1422 -    LPTABLE t = GetTable(it8);
180.1423 +    TABLE* t = GetTable(it8);
180.1424      int  nSamples   = t -> nSamples;
180.1425      int  nPatches   = t -> nPatches;
180.1426  
180.1427 -
180.1428      if (nSet >= nPatches || nField >= nSamples)
180.1429          return NULL;
180.1430  
180.1431 @@ -1554,17 +1463,15 @@
180.1432  }
180.1433  
180.1434  static
180.1435 -LCMSBOOL SetData(LPIT8 it8, int nSet, int nField, const char *Val)
180.1436 +cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
180.1437  {
180.1438 -    LPTABLE t = GetTable(it8);
180.1439 +    TABLE* t = GetTable(it8);
180.1440  
180.1441      if (!t->Data)
180.1442          AllocateDataSet(it8);
180.1443  
180.1444      if (!t->Data) return FALSE;
180.1445  
180.1446 -
180.1447 -
180.1448      if (nSet > t -> nPatches || nSet < 0) {
180.1449  
180.1450              return SynError(it8, "Patch %d out of range, there are %d patches", nSet, t -> nPatches);
180.1451 @@ -1575,7 +1482,6 @@
180.1452  
180.1453      }
180.1454  
180.1455 -
180.1456      t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val);
180.1457      return TRUE;
180.1458  }
180.1459 @@ -1586,38 +1492,38 @@
180.1460  
180.1461  // Writes a string to file
180.1462  static
180.1463 -void WriteStr(LPSAVESTREAM f, const char *str)
180.1464 +void WriteStr(SAVESTREAM* f, const char *str)
180.1465  {
180.1466 -
180.1467 -    size_t len;
180.1468 +    cmsUInt32Number len;
180.1469  
180.1470      if (str == NULL)
180.1471          str = " ";
180.1472  
180.1473      // Lenghth to write
180.1474 -    len = strlen(str);
180.1475 +    len = (cmsUInt32Number) strlen(str);
180.1476      f ->Used += len;
180.1477  
180.1478  
180.1479      if (f ->stream) {   // Should I write it to a file?
180.1480  
180.1481 -        fwrite(str, 1, len, f->stream);
180.1482 +        if (fwrite(str, 1, len, f->stream) != len) {
180.1483 +            cmsSignalError(0, cmsERROR_WRITE, "Write to file error in CGATS parser");
180.1484 +            return;
180.1485 +        }
180.1486  
180.1487      }
180.1488      else {  // Or to a memory block?
180.1489  
180.1490 -
180.1491          if (f ->Base) {   // Am I just counting the bytes?
180.1492  
180.1493              if (f ->Used > f ->Max) {
180.1494  
180.1495 -                cmsSignalError(LCMS_ERRC_ABORTED, "Write to memory overflows in CGATS parser");
180.1496 -                return;
180.1497 +                 cmsSignalError(0, cmsERROR_WRITE, "Write to memory overflows in CGATS parser");
180.1498 +                 return;
180.1499              }
180.1500  
180.1501 -            CopyMemory(f ->Ptr, str, len);
180.1502 +            memmove(f ->Ptr, str, len);
180.1503              f->Ptr += len;
180.1504 -
180.1505          }
180.1506  
180.1507      }
180.1508 @@ -1627,7 +1533,7 @@
180.1509  // Write formatted
180.1510  
180.1511  static
180.1512 -void Writef(LPSAVESTREAM f, const char* frm, ...)
180.1513 +void Writef(SAVESTREAM* f, const char* frm, ...)
180.1514  {
180.1515      char Buffer[4096];
180.1516      va_list args;
180.1517 @@ -1642,10 +1548,10 @@
180.1518  
180.1519  // Writes full header
180.1520  static
180.1521 -void WriteHeader(LPIT8 it8, LPSAVESTREAM fp)
180.1522 +void WriteHeader(cmsIT8* it8, SAVESTREAM* fp)
180.1523  {
180.1524 -    LPKEYVALUE p;
180.1525 -    LPTABLE t = GetTable(it8);
180.1526 +    KEYVALUE* p;
180.1527 +    TABLE* t = GetTable(it8);
180.1528  
180.1529  
180.1530      for (p = t->HeaderList; (p != NULL); p = p->Next)
180.1531 @@ -1672,14 +1578,13 @@
180.1532  
180.1533          if (!IsAvailableOnList(it8-> ValidKeywords, p->Keyword, NULL, NULL)) {
180.1534  
180.1535 -#ifdef STRICT_CGATS
180.1536 +#ifdef CMS_STRICT_CGATS
180.1537              WriteStr(fp, "KEYWORD\t\"");
180.1538              WriteStr(fp, p->Keyword);
180.1539              WriteStr(fp, "\"\n");
180.1540  #endif
180.1541  
180.1542              AddAvailableProperty(it8, p->Keyword, WRITE_UNCOOKED);
180.1543 -
180.1544          }
180.1545  
180.1546          WriteStr(fp, p->Keyword);
180.1547 @@ -1720,10 +1625,10 @@
180.1548  
180.1549  // Writes the data format
180.1550  static
180.1551 -void WriteDataFormat(LPSAVESTREAM fp, LPIT8 it8)
180.1552 +void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8)
180.1553  {
180.1554      int i, nSamples;
180.1555 -    LPTABLE t = GetTable(it8);
180.1556 +    TABLE* t = GetTable(it8);
180.1557  
180.1558      if (!t -> DataFormat) return;
180.1559  
180.1560 @@ -1743,10 +1648,10 @@
180.1561  
180.1562  // Writes data array
180.1563  static
180.1564 -void WriteData(LPSAVESTREAM fp, LPIT8 it8)
180.1565 +void WriteData(SAVESTREAM* fp, cmsIT8* it8)
180.1566  {
180.1567         int  i, j;
180.1568 -       LPTABLE t = GetTable(it8);
180.1569 +       TABLE* t = GetTable(it8);
180.1570  
180.1571         if (!t->Data) return;
180.1572  
180.1573 @@ -1785,13 +1690,13 @@
180.1574  
180.1575  
180.1576  // Saves whole file
180.1577 -LCMSBOOL LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE hIT8, const char* cFileName)
180.1578 +cmsBool CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName)
180.1579  {
180.1580      SAVESTREAM sd;
180.1581 -    int i;
180.1582 -    LPIT8 it8 = (LPIT8) hIT8;
180.1583 -
180.1584 -    ZeroMemory(&sd, sizeof(SAVESTREAM));
180.1585 +    cmsUInt32Number i;
180.1586 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1587 +
180.1588 +    memset(&sd, 0, sizeof(sd));
180.1589  
180.1590      sd.stream = fopen(cFileName, "wt");
180.1591      if (!sd.stream) return FALSE;
180.1592 @@ -1806,23 +1711,23 @@
180.1593              WriteData(&sd, it8);
180.1594      }
180.1595  
180.1596 -    fclose(sd.stream);
180.1597 +    if (fclose(sd.stream) != 0) return FALSE;
180.1598  
180.1599      return TRUE;
180.1600  }
180.1601  
180.1602  
180.1603  // Saves to memory
180.1604 -LCMSBOOL LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded)
180.1605 +cmsBool CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded)
180.1606  {
180.1607      SAVESTREAM sd;
180.1608 -    int i;
180.1609 -    LPIT8 it8 = (LPIT8) hIT8;
180.1610 -
180.1611 -    ZeroMemory(&sd, sizeof(SAVESTREAM));
180.1612 +    cmsUInt32Number i;
180.1613 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1614 +
180.1615 +    memset(&sd, 0, sizeof(sd));
180.1616  
180.1617      sd.stream = NULL;
180.1618 -    sd.Base   = (LPBYTE) MemPtr;
180.1619 +    sd.Base   = (cmsUInt8Number*)  MemPtr;
180.1620      sd.Ptr    = sd.Base;
180.1621  
180.1622      sd.Used = 0;
180.1623 @@ -1856,10 +1761,10 @@
180.1624  // -------------------------------------------------------------- Higer level parsing
180.1625  
180.1626  static
180.1627 -LCMSBOOL DataFormatSection(LPIT8 it8)
180.1628 +cmsBool DataFormatSection(cmsIT8* it8)
180.1629  {
180.1630      int iField = 0;
180.1631 -    LPTABLE t = GetTable(it8);
180.1632 +    TABLE* t = GetTable(it8);
180.1633  
180.1634      InSymbol(it8);   // Eats "BEGIN_DATA_FORMAT"
180.1635      CheckEOLN(it8);
180.1636 @@ -1897,12 +1802,12 @@
180.1637  
180.1638  
180.1639  static
180.1640 -LCMSBOOL DataSection (LPIT8 it8)
180.1641 +cmsBool DataSection (cmsIT8* it8)
180.1642  {
180.1643      int  iField = 0;
180.1644      int  iSet   = 0;
180.1645 -    char Buffer[MAXSTR];
180.1646 -    LPTABLE t = GetTable(it8);
180.1647 +    char Buffer[256];
180.1648 +    TABLE* t = GetTable(it8);
180.1649  
180.1650      InSymbol(it8);   // Eats "BEGIN_DATA"
180.1651      CheckEOLN(it8);
180.1652 @@ -1949,11 +1854,11 @@
180.1653  
180.1654  
180.1655  static
180.1656 -LCMSBOOL HeaderSection(LPIT8 it8)
180.1657 +cmsBool HeaderSection(cmsIT8* it8)
180.1658  {
180.1659      char VarName[MAXID];
180.1660      char Buffer[MAXSTR];
180.1661 -    LPKEYVALUE Key;
180.1662 +    KEYVALUE* Key;
180.1663  
180.1664          while (it8->sy != SEOF &&
180.1665                 it8->sy != SSYNERROR &&
180.1666 @@ -1985,7 +1890,7 @@
180.1667  
180.1668                  if (!IsAvailableOnList(it8-> ValidKeywords, VarName, NULL, &Key)) {
180.1669  
180.1670 -#ifdef STRICT_CGATS
180.1671 +#ifdef CMS_STRICT_CGATS
180.1672                   return SynError(it8, "Undefined keyword '%s'", VarName);
180.1673  #else
180.1674                      Key = AddAvailableProperty(it8, VarName, WRITE_UNCOOKED);
180.1675 @@ -2007,7 +1912,7 @@
180.1676                          return SynError(it8, "Invalid value '%s' for property '%s'.", Buffer, VarName);
180.1677  
180.1678                      // chop the string as a list of "subkey, value" pairs, using ';' as a separator
180.1679 -                    for(Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
180.1680 +                    for (Subkey = Buffer; Subkey != NULL; Subkey = Nextkey)
180.1681                      {
180.1682                          char *Value, *temp;
180.1683  
180.1684 @@ -2058,7 +1963,7 @@
180.1685  
180.1686  
180.1687  static
180.1688 -LCMSBOOL ParseIT8(LPIT8 it8, LCMSBOOL nosheet)
180.1689 +cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
180.1690  {
180.1691      char* SheetTypePtr = it8 ->SheetType;
180.1692  
180.1693 @@ -2119,33 +2024,32 @@
180.1694  // Init usefull pointers
180.1695  
180.1696  static
180.1697 -void CookPointers(LPIT8 it8)
180.1698 +void CookPointers(cmsIT8* it8)
180.1699  {
180.1700      int idField, i;
180.1701      char* Fld;
180.1702 -    int j;
180.1703 -    int nOldTable = it8 ->nTable;
180.1704 +    cmsUInt32Number j;
180.1705 +    cmsUInt32Number nOldTable = it8 ->nTable;
180.1706  
180.1707      for (j=0; j < it8 ->TablesCount; j++) {
180.1708  
180.1709 -    LPTABLE t = it8 ->Tab + j;
180.1710 +    TABLE* t = it8 ->Tab + j;
180.1711  
180.1712      t -> SampleID = 0;
180.1713      it8 ->nTable = j;
180.1714  
180.1715      for (idField = 0; idField < t -> nSamples; idField++)
180.1716      {
180.1717 -        if (t ->DataFormat == NULL) {
180.1718 -             SynError(it8, "Undefined DATA_FORMAT");
180.1719 -             return;
180.1720 -
180.1721 +        if (t ->DataFormat == NULL){
180.1722 +            SynError(it8, "Undefined DATA_FORMAT");
180.1723 +            return;
180.1724          }
180.1725  
180.1726          Fld = t->DataFormat[idField];
180.1727          if (!Fld) continue;
180.1728  
180.1729  
180.1730 -        if (stricmp(Fld, "SAMPLE_ID") == 0) {
180.1731 +        if (cmsstrcasecmp(Fld, "SAMPLE_ID") == 0) {
180.1732  
180.1733                      t -> SampleID = idField;
180.1734  
180.1735 @@ -2170,7 +2074,7 @@
180.1736  
180.1737          // "LABEL" is an extension. It keeps references to forward tables
180.1738  
180.1739 -        if ((stricmp(Fld, "LABEL") == 0) || Fld[0] == '$' ) {
180.1740 +        if ((cmsstrcasecmp(Fld, "LABEL") == 0) || Fld[0] == '$' ) {
180.1741  
180.1742                      // Search for table references...
180.1743                      for (i=0; i < t -> nPatches; i++) {
180.1744 @@ -2179,15 +2083,15 @@
180.1745  
180.1746                              if (Label) {
180.1747  
180.1748 -                                int k;
180.1749 +                                cmsUInt32Number k;
180.1750  
180.1751                                  // This is the label, search for a table containing
180.1752                                  // this property
180.1753  
180.1754                                  for (k=0; k < it8 ->TablesCount; k++) {
180.1755  
180.1756 -                                    LPTABLE Table = it8 ->Tab + k;
180.1757 -                                    LPKEYVALUE p;
180.1758 +                                    TABLE* Table = it8 ->Tab + k;
180.1759 +                                    KEYVALUE* p;
180.1760  
180.1761                                      if (IsAvailableOnList(Table->HeaderList, Label, NULL, &p)) {
180.1762  
180.1763 @@ -2221,10 +2125,10 @@
180.1764  // that should be something like some printable characters plus a \n
180.1765  
180.1766  static
180.1767 -int IsMyBlock(LPBYTE Buffer, size_t n)
180.1768 +int IsMyBlock(cmsUInt8Number* Buffer, int n)
180.1769  {
180.1770      int cols = 1, space = 0, quot = 0;
180.1771 -    size_t i;
180.1772 +    int i;
180.1773  
180.1774      if (n < 10) return FALSE;   // Too small
180.1775  
180.1776 @@ -2261,20 +2165,22 @@
180.1777  
180.1778  
180.1779  static
180.1780 -int IsMyFile(const char* FileName)
180.1781 +cmsBool IsMyFile(const char* FileName)
180.1782  {
180.1783     FILE *fp;
180.1784 -   size_t Size;
180.1785 -   BYTE Ptr[133];
180.1786 +   cmsUInt32Number Size;
180.1787 +   cmsUInt8Number Ptr[133];
180.1788  
180.1789     fp = fopen(FileName, "rt");
180.1790     if (!fp) {
180.1791 -       cmsSignalError(LCMS_ERRC_ABORTED, "File '%s' not found", FileName);
180.1792 +       cmsSignalError(0, cmsERROR_FILE, "File '%s' not found", FileName);
180.1793         return FALSE;
180.1794     }
180.1795  
180.1796 -   Size = fread(Ptr, 1, 132, fp);
180.1797 -   fclose(fp);
180.1798 +   Size = (cmsUInt32Number) fread(Ptr, 1, 132, fp);
180.1799 +
180.1800 +   if (fclose(fp) != 0)
180.1801 +       return FALSE;
180.1802  
180.1803     Ptr[Size] = '\0';
180.1804  
180.1805 @@ -2284,24 +2190,28 @@
180.1806  // ---------------------------------------------------------- Exported routines
180.1807  
180.1808  
180.1809 -LCMSHANDLE LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len)
180.1810 +cmsHANDLE  CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len)
180.1811  {
180.1812 -    LCMSHANDLE hIT8;
180.1813 -    LPIT8  it8;
180.1814 -
180.1815 -    int type = IsMyBlock((LPBYTE) Ptr, len);
180.1816 +    cmsHANDLE hIT8;
180.1817 +    cmsIT8*  it8;
180.1818 +    int type;
180.1819 +
180.1820 +    _cmsAssert(Ptr != NULL);
180.1821 +    _cmsAssert(len != 0);
180.1822 +
180.1823 +    type = IsMyBlock((cmsUInt8Number*)Ptr, len);
180.1824      if (type == 0) return NULL;
180.1825  
180.1826 -    hIT8 = cmsIT8Alloc();
180.1827 +    hIT8 = cmsIT8Alloc(ContextID);
180.1828      if (!hIT8) return NULL;
180.1829  
180.1830 -    it8 = (LPIT8) hIT8;
180.1831 -    it8 ->MemoryBlock = (char*) _cmsMalloc(len + 1);
180.1832 +    it8 = (cmsIT8*) hIT8;
180.1833 +    it8 ->MemoryBlock = (char*) _cmsMalloc(ContextID, len + 1);
180.1834  
180.1835      strncpy(it8 ->MemoryBlock, (const char*) Ptr, len);
180.1836      it8 ->MemoryBlock[len] = 0;
180.1837  
180.1838 -    strncpy(it8->FileStack[0]->FileName, "", MAX_PATH-1);
180.1839 +    strncpy(it8->FileStack[0]->FileName, "", cmsMAX_PATH-1);
180.1840      it8-> Source = it8 -> MemoryBlock;
180.1841  
180.1842      if (!ParseIT8(it8, type-1)) {
180.1843 @@ -2313,7 +2223,7 @@
180.1844      CookPointers(it8);
180.1845      it8 ->nTable = 0;
180.1846  
180.1847 -     _cmsFree(it8->MemoryBlock);
180.1848 +    _cmsFree(ContextID, it8->MemoryBlock);
180.1849      it8 -> MemoryBlock = NULL;
180.1850  
180.1851      return hIT8;
180.1852 @@ -2322,17 +2232,20 @@
180.1853  }
180.1854  
180.1855  
180.1856 -LCMSHANDLE LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName)
180.1857 +cmsHANDLE  CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName)
180.1858  {
180.1859  
180.1860 -     LCMSHANDLE hIT8;
180.1861 -     LPIT8  it8;
180.1862 -
180.1863 -     int type = IsMyFile(cFileName);
180.1864 +     cmsHANDLE hIT8;
180.1865 +     cmsIT8*  it8;
180.1866 +     int type;
180.1867 +
180.1868 +     _cmsAssert(cFileName != NULL);
180.1869 +
180.1870 +     type = IsMyFile(cFileName);
180.1871       if (type == 0) return NULL;
180.1872  
180.1873 -     hIT8 = cmsIT8Alloc();
180.1874 -     it8 = (LPIT8) hIT8;
180.1875 +     hIT8 = cmsIT8Alloc(ContextID);
180.1876 +     it8 = (cmsIT8*) hIT8;
180.1877       if (!hIT8) return NULL;
180.1878  
180.1879  
180.1880 @@ -2344,8 +2257,8 @@
180.1881       }
180.1882  
180.1883  
180.1884 -    strncpy(it8->FileStack[0]->FileName, cFileName, MAX_PATH-1);
180.1885 -    it8->FileStack[0]->FileName[MAX_PATH-1] = 0;
180.1886 +    strncpy(it8->FileStack[0]->FileName, cFileName, cmsMAX_PATH-1);
180.1887 +    it8->FileStack[0]->FileName[cmsMAX_PATH-1] = 0;
180.1888  
180.1889      if (!ParseIT8(it8, type-1)) {
180.1890  
180.1891 @@ -2357,28 +2270,41 @@
180.1892      CookPointers(it8);
180.1893      it8 ->nTable = 0;
180.1894  
180.1895 -    fclose(it8 ->FileStack[0]->Stream);
180.1896 +    if (fclose(it8 ->FileStack[0]->Stream)!= 0) {
180.1897 +        cmsIT8Free(hIT8);
180.1898 +            return NULL;
180.1899 +    }
180.1900 +
180.1901      return hIT8;
180.1902  
180.1903  }
180.1904  
180.1905 -int LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE hIT8, char ***SampleNames)
180.1906 +int CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames)
180.1907  {
180.1908 -        LPIT8 it8 = (LPIT8) hIT8;
180.1909 -        LPTABLE t = GetTable(it8);
180.1910 -
180.1911 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1912 +    TABLE* t;
180.1913 +
180.1914 +    _cmsAssert(hIT8 != NULL);
180.1915 +
180.1916 +    t = GetTable(it8);
180.1917 +
180.1918 +    if (SampleNames)
180.1919          *SampleNames = t -> DataFormat;
180.1920 -        return t -> nSamples;
180.1921 +    return t -> nSamples;
180.1922  }
180.1923  
180.1924  
180.1925 -int LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames)
180.1926 +cmsUInt32Number CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyNames)
180.1927  {
180.1928 -    LPIT8 it8 = (LPIT8) hIT8;
180.1929 -    LPKEYVALUE p;
180.1930 -    int n;
180.1931 -    const char **Props;
180.1932 -    LPTABLE t = GetTable(it8);
180.1933 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1934 +    KEYVALUE* p;
180.1935 +    cmsUInt32Number n;
180.1936 +    char **Props;
180.1937 +    TABLE* t;
180.1938 +
180.1939 +    _cmsAssert(hIT8 != NULL);
180.1940 +
180.1941 +    t = GetTable(it8);
180.1942  
180.1943      // Pass#1 - count properties
180.1944  
180.1945 @@ -2388,7 +2314,7 @@
180.1946      }
180.1947  
180.1948  
180.1949 -    Props = (const char **) AllocChunk(it8, sizeof(char *) * n);
180.1950 +    Props = (char **) AllocChunk(it8, sizeof(char *) * n);
180.1951  
180.1952      // Pass#2 - Fill pointers
180.1953      n = 0;
180.1954 @@ -2400,13 +2326,18 @@
180.1955      return n;
180.1956  }
180.1957  
180.1958 -int LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
180.1959 +cmsUInt32Number CMSEXPORT cmsIT8EnumPropertyMulti(cmsHANDLE hIT8, const char* cProp, const char ***SubpropertyNames)
180.1960  {
180.1961 -    LPIT8 it8 = (LPIT8) hIT8;
180.1962 -    LPKEYVALUE p, tmp;
180.1963 -    int n;
180.1964 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.1965 +    KEYVALUE *p, *tmp;
180.1966 +    cmsUInt32Number n;
180.1967      const char **Props;
180.1968 -    LPTABLE t = GetTable(it8);
180.1969 +    TABLE* t;
180.1970 +
180.1971 +    _cmsAssert(hIT8 != NULL);
180.1972 +
180.1973 +
180.1974 +    t = GetTable(it8);
180.1975  
180.1976      if(!IsAvailableOnList(t->HeaderList, cProp, NULL, &p)) {
180.1977          *SubpropertyNames = 0;
180.1978 @@ -2436,11 +2367,11 @@
180.1979  }
180.1980  
180.1981  static
180.1982 -int LocatePatch(LPIT8 it8, const char* cPatch)
180.1983 +int LocatePatch(cmsIT8* it8, const char* cPatch)
180.1984  {
180.1985      int i;
180.1986      const char *data;
180.1987 -    LPTABLE t = GetTable(it8);
180.1988 +    TABLE* t = GetTable(it8);
180.1989  
180.1990      for (i=0; i < t-> nPatches; i++) {
180.1991  
180.1992 @@ -2448,7 +2379,7 @@
180.1993  
180.1994          if (data != NULL) {
180.1995  
180.1996 -                if (stricmp(data, cPatch) == 0)
180.1997 +                if (cmsstrcasecmp(data, cPatch) == 0)
180.1998                          return i;
180.1999                  }
180.2000          }
180.2001 @@ -2459,62 +2390,65 @@
180.2002  
180.2003  
180.2004  static
180.2005 -int LocateEmptyPatch(LPIT8 it8)
180.2006 +int LocateEmptyPatch(cmsIT8* it8)
180.2007  {
180.2008      int i;
180.2009      const char *data;
180.2010 -    LPTABLE t = GetTable(it8);
180.2011 +    TABLE* t = GetTable(it8);
180.2012  
180.2013      for (i=0; i < t-> nPatches; i++) {
180.2014  
180.2015          data = GetData(it8, i, t->SampleID);
180.2016  
180.2017          if (data == NULL)
180.2018 -                    return i;
180.2019 -
180.2020 -        }
180.2021 -
180.2022 -        return -1;
180.2023 +            return i;
180.2024 +
180.2025 +    }
180.2026 +
180.2027 +    return -1;
180.2028  }
180.2029  
180.2030  static
180.2031 -int LocateSample(LPIT8 it8, const char* cSample)
180.2032 +int LocateSample(cmsIT8* it8, const char* cSample)
180.2033  {
180.2034      int i;
180.2035      const char *fld;
180.2036 -    LPTABLE t = GetTable(it8);
180.2037 +    TABLE* t = GetTable(it8);
180.2038  
180.2039      for (i=0; i < t->nSamples; i++) {
180.2040  
180.2041          fld = GetDataFormat(it8, i);
180.2042 -        if (stricmp(fld, cSample) == 0)
180.2043 +        if (cmsstrcasecmp(fld, cSample) == 0)
180.2044              return i;
180.2045      }
180.2046  
180.2047 -
180.2048 -    // SynError(it8, "Couldn't find data field %s\n", cSample);
180.2049      return -1;
180.2050  
180.2051  }
180.2052  
180.2053  
180.2054 -int LCMSEXPORT cmsIT8GetDataFormat(LCMSHANDLE hIT8, const char* cSample)
180.2055 +int CMSEXPORT cmsIT8FindDataFormat(cmsHANDLE hIT8, const char* cSample)
180.2056  {
180.2057 -    LPIT8 it8 = (LPIT8) hIT8;
180.2058 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2059 +
180.2060 +    _cmsAssert(hIT8 != NULL);
180.2061 +
180.2062      return LocateSample(it8, cSample);
180.2063  }
180.2064  
180.2065  
180.2066  
180.2067 -const char* LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE hIT8, int row, int col)
180.2068 +const char* CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col)
180.2069  {
180.2070 -    LPIT8 it8 = (LPIT8) hIT8;
180.2071 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2072 +
180.2073 +    _cmsAssert(hIT8 != NULL);
180.2074  
180.2075      return GetData(it8, row, col);
180.2076  }
180.2077  
180.2078  
180.2079 -double LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE hIT8, int row, int col)
180.2080 +cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int col)
180.2081  {
180.2082      const char* Buffer;
180.2083  
180.2084 @@ -2530,19 +2464,23 @@
180.2085  }
180.2086  
180.2087  
180.2088 -LCMSBOOL LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col, const char* Val)
180.2089 +cmsBool CMSEXPORT cmsIT8SetDataRowCol(cmsHANDLE hIT8, int row, int col, const char* Val)
180.2090  {
180.2091 -    LPIT8 it8 = (LPIT8) hIT8;
180.2092 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2093 +
180.2094 +    _cmsAssert(hIT8 != NULL);
180.2095  
180.2096      return SetData(it8, row, col, Val);
180.2097  }
180.2098  
180.2099  
180.2100 -LCMSBOOL LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col, double Val)
180.2101 +cmsBool CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col, cmsFloat64Number Val)
180.2102  {
180.2103 -    LPIT8 it8 = (LPIT8) hIT8;
180.2104 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2105      char Buff[256];
180.2106  
180.2107 +    _cmsAssert(hIT8 != NULL);
180.2108 +
180.2109      sprintf(Buff, it8->DoubleFormatter, Val);
180.2110  
180.2111      return SetData(it8, row, col, Buff);
180.2112 @@ -2550,18 +2488,18 @@
180.2113  
180.2114  
180.2115  
180.2116 -const char* LCMSEXPORT cmsIT8GetData(LCMSHANDLE hIT8, const char* cPatch, const char* cSample)
180.2117 +const char* CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample)
180.2118  {
180.2119 -    LPIT8 it8 = (LPIT8) hIT8;
180.2120 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2121      int iField, iSet;
180.2122  
180.2123 +    _cmsAssert(hIT8 != NULL);
180.2124  
180.2125      iField = LocateSample(it8, cSample);
180.2126      if (iField < 0) {
180.2127          return NULL;
180.2128      }
180.2129  
180.2130 -
180.2131      iSet = LocatePatch(it8, cPatch);
180.2132      if (iSet < 0) {
180.2133              return NULL;
180.2134 @@ -2571,7 +2509,7 @@
180.2135  }
180.2136  
180.2137  
180.2138 -double LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE it8, const char* cPatch, const char* cSample)
180.2139 +cmsFloat64Number CMSEXPORT cmsIT8GetDataDbl(cmsHANDLE  it8, const char* cPatch, const char* cSample)
180.2140  {
180.2141      const char* Buffer;
180.2142  
180.2143 @@ -2589,100 +2527,109 @@
180.2144  
180.2145  
180.2146  
180.2147 -LCMSBOOL LCMSEXPORT cmsIT8SetData(LCMSHANDLE hIT8, const char* cPatch,
180.2148 -                        const char* cSample,
180.2149 -                        const char *Val)
180.2150 +cmsBool CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample, const char *Val)
180.2151  {
180.2152 -    LPIT8 it8 = (LPIT8) hIT8;
180.2153 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2154      int iField, iSet;
180.2155 -    LPTABLE t = GetTable(it8);
180.2156 -
180.2157 +    TABLE* t;
180.2158 +
180.2159 +    _cmsAssert(hIT8 != NULL);
180.2160 +
180.2161 +    t = GetTable(it8);
180.2162  
180.2163      iField = LocateSample(it8, cSample);
180.2164  
180.2165      if (iField < 0)
180.2166          return FALSE;
180.2167  
180.2168 -
180.2169 -
180.2170 -        if (t-> nPatches == 0) {
180.2171 -
180.2172 -                AllocateDataFormat(it8);
180.2173 -                AllocateDataSet(it8);
180.2174 -                CookPointers(it8);
180.2175 +    if (t-> nPatches == 0) {
180.2176 +
180.2177 +        AllocateDataFormat(it8);
180.2178 +        AllocateDataSet(it8);
180.2179 +        CookPointers(it8);
180.2180 +    }
180.2181 +
180.2182 +    if (cmsstrcasecmp(cSample, "SAMPLE_ID") == 0) {
180.2183 +
180.2184 +        iSet   = LocateEmptyPatch(it8);
180.2185 +        if (iSet < 0) {
180.2186 +            return SynError(it8, "Couldn't add more patches '%s'\n", cPatch);
180.2187          }
180.2188  
180.2189 -
180.2190 -        if (stricmp(cSample, "SAMPLE_ID") == 0)
180.2191 -        {
180.2192 -
180.2193 -                iSet   = LocateEmptyPatch(it8);
180.2194 -                if (iSet < 0) {
180.2195 -                        return SynError(it8, "Couldn't add more patches '%s'\n", cPatch);
180.2196 -                }
180.2197 -
180.2198 -                iField = t -> SampleID;
180.2199 +        iField = t -> SampleID;
180.2200 +    }
180.2201 +    else {
180.2202 +        iSet = LocatePatch(it8, cPatch);
180.2203 +        if (iSet < 0) {
180.2204 +            return FALSE;
180.2205          }
180.2206 -        else {
180.2207 -                iSet = LocatePatch(it8, cPatch);
180.2208 -                if (iSet < 0) {
180.2209 -                    return FALSE;
180.2210 -            }
180.2211 -        }
180.2212 -
180.2213 -        return SetData(it8, iSet, iField, Val);
180.2214 +    }
180.2215 +
180.2216 +    return SetData(it8, iSet, iField, Val);
180.2217  }
180.2218  
180.2219  
180.2220 -LCMSBOOL LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
180.2221 -                        const char* cSample,
180.2222 -                        double Val)
180.2223 +cmsBool CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch,
180.2224 +                                   const char* cSample,
180.2225 +                                   cmsFloat64Number Val)
180.2226  {
180.2227 -    LPIT8 it8 = (LPIT8) hIT8;
180.2228 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2229      char Buff[256];
180.2230  
180.2231 -        snprintf(Buff, 255, it8->DoubleFormatter, Val);
180.2232 -        return cmsIT8SetData(hIT8, cPatch, cSample, Buff);
180.2233 -
180.2234 +    _cmsAssert(hIT8 != NULL);
180.2235 +
180.2236 +    snprintf(Buff, 255, it8->DoubleFormatter, Val);
180.2237 +    return cmsIT8SetData(hIT8, cPatch, cSample, Buff);
180.2238  }
180.2239  
180.2240  // Buffer should get MAXSTR at least
180.2241  
180.2242 -const char* LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer)
180.2243 +const char* CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer)
180.2244  {
180.2245 -        LPIT8 it8 = (LPIT8) hIT8;
180.2246 -        LPTABLE t = GetTable(it8);
180.2247 -        char* Data = GetData(it8, nPatch, t->SampleID);
180.2248 -
180.2249 -        if (!Data) return NULL;
180.2250 -        if (!buffer) return Data;
180.2251 -
180.2252 -        strncpy(buffer, Data, MAXSTR-1);
180.2253 -        buffer[MAXSTR-1] = 0;
180.2254 -        return buffer;
180.2255 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2256 +    TABLE* t;
180.2257 +    char* Data;
180.2258 +
180.2259 +    _cmsAssert(hIT8 != NULL);
180.2260 +
180.2261 +    t = GetTable(it8);
180.2262 +    Data = GetData(it8, nPatch, t->SampleID);
180.2263 +
180.2264 +    if (!Data) return NULL;
180.2265 +    if (!buffer) return Data;
180.2266 +
180.2267 +    strncpy(buffer, Data, MAXSTR-1);
180.2268 +    buffer[MAXSTR-1] = 0;
180.2269 +    return buffer;
180.2270  }
180.2271  
180.2272 -int LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cPatch)
180.2273 +int CMSEXPORT cmsIT8GetPatchByName(cmsHANDLE hIT8, const char *cPatch)
180.2274  {
180.2275 -    return LocatePatch((LPIT8)hIT8, cPatch);
180.2276 +    _cmsAssert(hIT8 != NULL);
180.2277 +
180.2278 +    return LocatePatch((cmsIT8*)hIT8, cPatch);
180.2279  }
180.2280  
180.2281 -int LCMSEXPORT cmsIT8TableCount(LCMSHANDLE hIT8)
180.2282 +cmsUInt32Number CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8)
180.2283  {
180.2284 -        LPIT8 it8 = (LPIT8) hIT8;
180.2285 -
180.2286 -        return it8 ->TablesCount;
180.2287 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2288 +
180.2289 +    _cmsAssert(hIT8 != NULL);
180.2290 +
180.2291 +    return it8 ->TablesCount;
180.2292  }
180.2293  
180.2294  // This handles the "LABEL" extension.
180.2295  // Label, nTable, Type
180.2296  
180.2297 -int LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType)
180.2298 +int CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType)
180.2299  {
180.2300      const char* cLabelFld;
180.2301      char Type[256], Label[256];
180.2302      int nTable;
180.2303  
180.2304 +    _cmsAssert(hIT8 != NULL);
180.2305 +
180.2306      if (cField != NULL && *cField == 0)
180.2307              cField = "LABEL";
180.2308  
180.2309 @@ -2700,18 +2647,21 @@
180.2310  
180.2311      if (ExpectedType) {
180.2312  
180.2313 -        if (stricmp(Type, ExpectedType) != 0) return -1;
180.2314 +        if (cmsstrcasecmp(Type, ExpectedType) != 0) return -1;
180.2315      }
180.2316  
180.2317      return cmsIT8SetTable(hIT8, nTable);
180.2318  }
180.2319  
180.2320  
180.2321 -LCMSBOOL LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample)
180.2322 +cmsBool CMSEXPORT cmsIT8SetIndexColumn(cmsHANDLE hIT8, const char* cSample)
180.2323  {
180.2324 -    LPIT8 it8 = (LPIT8) hIT8;
180.2325 -
180.2326 -    int pos = LocateSample(it8, cSample);
180.2327 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2328 +    int pos;
180.2329 +
180.2330 +    _cmsAssert(hIT8 != NULL);
180.2331 +
180.2332 +    pos = LocateSample(it8, cSample);
180.2333      if(pos == -1)
180.2334          return FALSE;
180.2335  
180.2336 @@ -2720,9 +2670,11 @@
180.2337  }
180.2338  
180.2339  
180.2340 -void LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE hIT8, const char* Formatter)
180.2341 +void CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter)
180.2342  {
180.2343 -    LPIT8 it8 = (LPIT8) hIT8;
180.2344 +    cmsIT8* it8 = (cmsIT8*) hIT8;
180.2345 +
180.2346 +    _cmsAssert(hIT8 != NULL);
180.2347  
180.2348      if (Formatter == NULL)
180.2349          strcpy(it8->DoubleFormatter, DEFAULT_DBL_FORMAT);
   181.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c	Thu Sep 23 17:33:40 2010 -0700
   181.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmscnvrt.c	Fri Sep 24 16:41:32 2010 -0700
   181.3 @@ -27,9 +27,10 @@
   181.4  // However, the following notice accompanied the original version of this
   181.5  // file:
   181.6  //
   181.7 +//---------------------------------------------------------------------------------
   181.8  //
   181.9 -//  Little cms
  181.10 -//  Copyright (C) 1998-2007 Marti Maria
  181.11 +//  Little Color Management System
  181.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  181.13  //
  181.14  // Permission is hereby granted, free of charge, to any person obtaining
  181.15  // a copy of this software and associated documentation files (the "Software"),
  181.16 @@ -48,178 +49,117 @@
  181.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  181.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  181.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  181.20 +//
  181.21 +//---------------------------------------------------------------------------------
  181.22 +//
  181.23  
  181.24 -#include "lcms.h"
  181.25 +#include "lcms2_internal.h"
  181.26  
  181.27  
  181.28 +// Link several profiles to obtain a single LUT modelling the whole color transform. Intents, Black point
  181.29 +// compensation and Adaptation parameters may vary across profiles. BPC and Adaptation refers to the PCS
  181.30 +// after the profile. I.e, BPC[0] refers to connexion between profile(0) and profile(1)
  181.31 +cmsPipeline* _cmsLinkProfiles(cmsContext     ContextID,
  181.32 +                              cmsUInt32Number nProfiles,
  181.33 +                              cmsUInt32Number Intents[],
  181.34 +                              cmsHPROFILE     hProfiles[],
  181.35 +                              cmsBool         BPC[],
  181.36 +                              cmsFloat64Number AdaptationStates[],
  181.37 +                              cmsUInt32Number dwFlags);
  181.38  
  181.39 +//---------------------------------------------------------------------------------
  181.40  
  181.41 -/*
  181.42 -       This module provides conversion stages for handling intents.
  181.43 +// This is the default routine for ICC-style intents. A user may decide to override it by using a plugin.
  181.44 +// Supported intents are perceptual, relative colorimetric, saturation and ICC-absolute colorimetric
  181.45 +static
  181.46 +cmsPipeline* DefaultICCintents(cmsContext     ContextID,
  181.47 +                               cmsUInt32Number nProfiles,
  181.48 +                               cmsUInt32Number Intents[],
  181.49 +                               cmsHPROFILE     hProfiles[],
  181.50 +                               cmsBool         BPC[],
  181.51 +                               cmsFloat64Number AdaptationStates[],
  181.52 +                               cmsUInt32Number dwFlags);
  181.53  
  181.54 -The chain of evaluation in a transform is:
  181.55 +//---------------------------------------------------------------------------------
  181.56  
  181.57 -                PCS1            PCS2                    PCS3          PCS4
  181.58 +// This is the entry for black-preserving K-only intents, which are non-ICC. Last profile have to be a output profile
  181.59 +// to do the trick (no devicelinks allowed at that position)
  181.60 +static
  181.61 +cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,
  181.62 +                                          cmsUInt32Number nProfiles,
  181.63 +                                          cmsUInt32Number Intents[],
  181.64 +                                          cmsHPROFILE     hProfiles[],
  181.65 +                                          cmsBool         BPC[],
  181.66 +                                          cmsFloat64Number AdaptationStates[],
  181.67 +                                          cmsUInt32Number dwFlags);
  181.68  
  181.69 -|From |  |From  |  |Conversion |  |Preview |  |Gamut   |  |Conversion |  |To    |  |To     |
  181.70 -|Input|->|Device|->|Stage 1    |->|handling|->|Checking|->|Stage 2    |->|Device|->|output |
  181.71 +//---------------------------------------------------------------------------------
  181.72  
  181.73 ---------  -------  -------------   ---------  ----------  -------------   -------  ---------
  181.74 +// This is the entry for black-plane preserving, which are non-ICC. Again, Last profile have to be a output profile
  181.75 +// to do the trick (no devicelinks allowed at that position)
  181.76 +static
  181.77 +cmsPipeline*  BlackPreservingKPlaneIntents(cmsContext     ContextID,
  181.78 +                                           cmsUInt32Number nProfiles,
  181.79 +                                           cmsUInt32Number Intents[],
  181.80 +                                           cmsHPROFILE     hProfiles[],
  181.81 +                                           cmsBool         BPC[],
  181.82 +                                           cmsFloat64Number AdaptationStates[],
  181.83 +                                           cmsUInt32Number dwFlags);
  181.84  
  181.85 -          AToB0                     prew0       gamut                     BToA0
  181.86 -Formatting LUT      Adjusting        LUT         LUT       Adjusting       LUT      Formatting
  181.87 -          Intent     Intent 1       intent      intent      Intent 2      Intent
  181.88 +//---------------------------------------------------------------------------------
  181.89  
  181.90  
  181.91 -Some of these LUT may be missing
  181.92 +// This is a structure holding implementations for all supported intents.
  181.93 +typedef struct _cms_intents_list {
  181.94  
  181.95 -There are two intents involved here, the intent of the transform itself, and the
  181.96 -intent the proof is being done, if is the case. Since the first intent is to be
  181.97 -applied to preview, is the proofing intent. The second intent  identifies the
  181.98 -transform intent. Input data of any stage is taked as relative colorimetric
  181.99 -always.
 181.100 +    cmsUInt32Number Intent;
 181.101 +    char            Description[256];
 181.102 +    cmsIntentFn     Link;
 181.103 +    struct _cms_intents_list*  Next;
 181.104  
 181.105 +} cmsIntentsList;
 181.106  
 181.107 -NOTES: V4 states than perceptual & saturation intents between mixed v2 & v4 profiles should
 181.108 -scale PCS from a black point equal to ZERO in v2 profiles to the reference media black of
 181.109 -perceptual v4 PCS. Since I found many v2 profiles to be using a perceptual intent with black
 181.110 -point not zero at all, I'm implementing that as a black point compensation from whatever
 181.111 -black from perceptal intent to the reference media black for v4 profiles.
 181.112  
 181.113 -*/
 181.114 +// Built-in intents
 181.115 +static cmsIntentsList DefaultIntents[] = {
 181.116  
 181.117 +    { INTENT_PERCEPTUAL,                            "Perceptual",                                   DefaultICCintents,            &DefaultIntents[1] },
 181.118 +    { INTENT_RELATIVE_COLORIMETRIC,                 "Relative colorimetric",                        DefaultICCintents,            &DefaultIntents[2] },
 181.119 +    { INTENT_SATURATION,                            "Saturation",                                   DefaultICCintents,            &DefaultIntents[3] },
 181.120 +    { INTENT_ABSOLUTE_COLORIMETRIC,                 "Absolute colorimetric",                        DefaultICCintents,            &DefaultIntents[4] },
 181.121 +    { INTENT_PRESERVE_K_ONLY_PERCEPTUAL,            "Perceptual preserving black ink",              BlackPreservingKOnlyIntents,  &DefaultIntents[5] },
 181.122 +    { INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC, "Relative colorimetric preserving black ink",   BlackPreservingKOnlyIntents,  &DefaultIntents[6] },
 181.123 +    { INTENT_PRESERVE_K_ONLY_SATURATION,            "Saturation preserving black ink",              BlackPreservingKOnlyIntents,  &DefaultIntents[7] },
 181.124 +    { INTENT_PRESERVE_K_PLANE_PERCEPTUAL,           "Perceptual preserving black plane",            BlackPreservingKPlaneIntents, &DefaultIntents[8] },
 181.125 +    { INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC,"Relative colorimetric preserving black plane", BlackPreservingKPlaneIntents, &DefaultIntents[9] },
 181.126 +    { INTENT_PRESERVE_K_PLANE_SATURATION,           "Saturation preserving black plane",            BlackPreservingKPlaneIntents, NULL }
 181.127 +};
 181.128  
 181.129  
 181.130 +// A pointer to the begining of the list
 181.131 +static cmsIntentsList *Intents = DefaultIntents;
 181.132  
 181.133 -int cdecl cmsChooseCnvrt(int Absolute,
 181.134 -                 int Phase1, LPcmsCIEXYZ BlackPointIn,
 181.135 -                             LPcmsCIEXYZ WhitePointIn,
 181.136 -                             LPcmsCIEXYZ IlluminantIn,
 181.137 -                             LPMAT3 ChromaticAdaptationMatrixIn,
 181.138 +// Search the list for a suitable intent. Returns NULL if not found
 181.139 +static
 181.140 +cmsIntentsList* SearchIntent(cmsUInt32Number Intent)
 181.141 +{
 181.142 +    cmsIntentsList* pt;
 181.143  
 181.144 -                 int Phase2, LPcmsCIEXYZ BlackPointOut,
 181.145 -                             LPcmsCIEXYZ WhitePointOut,
 181.146 -                             LPcmsCIEXYZ IlluminantOut,
 181.147 -                             LPMAT3 ChromaticAdaptationMatrixOut,
 181.148 +    for (pt = Intents; pt != NULL; pt = pt -> Next)
 181.149 +        if (pt ->Intent == Intent) return pt;
 181.150  
 181.151 -                int DoBlackPointCompensation,
 181.152 -                double AdaptationState,
 181.153 -                 _cmsADJFN *fn1,
 181.154 -                 LPWMAT3 wm, LPWVEC3 wof);
 181.155 -
 181.156 -
 181.157 -// -------------------------------------------------------------------------
 181.158 -
 181.159 -// D50 - Widely used
 181.160 -
 181.161 -LCMSAPI LPcmsCIEXYZ LCMSEXPORT cmsD50_XYZ(void)
 181.162 -{
 181.163 -    static cmsCIEXYZ D50XYZ = {D50X, D50Y, D50Z};
 181.164 -
 181.165 -    return &D50XYZ;
 181.166 +    return NULL;
 181.167  }
 181.168  
 181.169 -LCMSAPI LPcmsCIExyY LCMSEXPORT cmsD50_xyY(void)
 181.170 +// Black point compensation. Implemented as a linear scaling in XYZ. Black points
 181.171 +// should come relative to the white point. Fills an matrix/offset element m
 181.172 +// which is organized as a 4x4 matrix.
 181.173 +static
 181.174 +void ComputeBlackPointCompensation(const cmsCIEXYZ* BlackPointIn,
 181.175 +                                   const cmsCIEXYZ* BlackPointOut,
 181.176 +                                   cmsMAT3* m, cmsVEC3* off)
 181.177  {
 181.178 -    static cmsCIExyY D50xyY;
 181.179 -    cmsXYZ2xyY(&D50xyY, cmsD50_XYZ());
 181.180 -
 181.181 -    return &D50xyY;
 181.182 -}
 181.183 -
 181.184 -
 181.185 -// ---------------- From LUT to LUT --------------------------
 181.186 -
 181.187 -
 181.188 -// Calculate m, offset Relativ -> Absolute undoing any chromatic
 181.189 -// adaptation done by the profile.
 181.190 -
 181.191 -#ifdef _MSC_VER
 181.192 -#pragma warning(disable : 4100 4505)
 181.193 -#endif
 181.194 -
 181.195 -
 181.196 -
 181.197 -// join scalings to obtain:
 181.198 -//     relative input to absolute and then to relative output
 181.199 -
 181.200 -static
 181.201 -void Rel2RelStepAbsCoefs(double AdaptationState,
 181.202 -
 181.203 -                         LPcmsCIEXYZ BlackPointIn,
 181.204 -                         LPcmsCIEXYZ WhitePointIn,
 181.205 -                         LPcmsCIEXYZ IlluminantIn,
 181.206 -                         LPMAT3 ChromaticAdaptationMatrixIn,
 181.207 -
 181.208 -                         LPcmsCIEXYZ BlackPointOut,
 181.209 -                         LPcmsCIEXYZ WhitePointOut,
 181.210 -                         LPcmsCIEXYZ IlluminantOut,
 181.211 -                         LPMAT3 ChromaticAdaptationMatrixOut,
 181.212 -
 181.213 -                         LPMAT3 m, LPVEC3 of)
 181.214 -{
 181.215 -
 181.216 -       VEC3 WtPtIn, WtPtInAdapted;
 181.217 -       VEC3 WtPtOut, WtPtOutAdapted;
 181.218 -       MAT3 Scale, m1, m2, m3;
 181.219 -
 181.220 -       VEC3init(&WtPtIn, WhitePointIn->X, WhitePointIn->Y, WhitePointIn->Z);
 181.221 -       MAT3eval(&WtPtInAdapted, ChromaticAdaptationMatrixIn, &WtPtIn);
 181.222 -
 181.223 -       VEC3init(&WtPtOut, WhitePointOut->X, WhitePointOut->Y, WhitePointOut->Z);
 181.224 -       MAT3eval(&WtPtOutAdapted, ChromaticAdaptationMatrixOut, &WtPtOut);
 181.225 -
 181.226 -       VEC3init(&Scale.v[0], WtPtInAdapted.n[0] / WtPtOutAdapted.n[0], 0, 0);
 181.227 -       VEC3init(&Scale.v[1], 0, WtPtInAdapted.n[1] / WtPtOutAdapted.n[1], 0);
 181.228 -       VEC3init(&Scale.v[2], 0, 0, WtPtInAdapted.n[2] / WtPtOutAdapted.n[2]);
 181.229 -
 181.230 -
 181.231 -       // Adaptation state
 181.232 -
 181.233 -       if (AdaptationState == 1.0) {
 181.234 -
 181.235 -           // Observer is fully adapted. Keep chromatic adaptation
 181.236 -
 181.237 -           CopyMemory(m, &Scale, sizeof(MAT3));
 181.238 -
 181.239 -       }
 181.240 -       else {
 181.241 -
 181.242 -            // Observer is not adapted, undo the chromatic adaptation
 181.243 -            m1 = *ChromaticAdaptationMatrixIn;
 181.244 -            MAT3inverse(&m1, &m2);
 181.245 -
 181.246 -            MAT3per(&m3, &m2, &Scale);
 181.247 -            MAT3per(m, &m3, ChromaticAdaptationMatrixOut);
 181.248 -       }
 181.249 -
 181.250 -
 181.251 -       VEC3init(of, 0.0, 0.0, 0.0);
 181.252 -
 181.253 -}
 181.254 -
 181.255 -
 181.256 -// The (in)famous black point compensation. Right now implemented as
 181.257 -// a linear scaling in XYZ
 181.258 -
 181.259 -static
 181.260 -void ComputeBlackPointCompensationFactors(LPcmsCIEXYZ BlackPointIn,
 181.261 -                      LPcmsCIEXYZ WhitePointIn,
 181.262 -                      LPcmsCIEXYZ IlluminantIn,
 181.263 -                      LPcmsCIEXYZ BlackPointOut,
 181.264 -                      LPcmsCIEXYZ WhitePointOut,
 181.265 -                      LPcmsCIEXYZ IlluminantOut,
 181.266 -                      LPMAT3 m, LPVEC3 of)
 181.267 -{
 181.268 -
 181.269 -
 181.270 -   cmsCIEXYZ RelativeBlackPointIn, RelativeBlackPointOut;
 181.271 -   double ax, ay, az, bx, by, bz, tx, ty, tz;
 181.272 -
 181.273 -   // At first, convert both black points to relative.
 181.274 -
 181.275 -   cmsAdaptToIlluminant(&RelativeBlackPointIn,  WhitePointIn, IlluminantIn, BlackPointIn);
 181.276 -   cmsAdaptToIlluminant(&RelativeBlackPointOut, WhitePointOut, IlluminantOut, BlackPointOut);
 181.277 +  cmsFloat64Number ax, ay, az, bx, by, bz, tx, ty, tz;
 181.278  
 181.279     // Now we need to compute a matrix plus an offset m and of such of
 181.280     // [m]*bpin + off = bpout
 181.281 @@ -229,438 +169,900 @@
 181.282     // a = (bpout - D50) / (bpin - D50)
 181.283     // b = - D50* (bpout - bpin) / (bpin - D50)
 181.284  
 181.285 +   tx = BlackPointIn->X - cmsD50_XYZ()->X;
 181.286 +   ty = BlackPointIn->Y - cmsD50_XYZ()->Y;
 181.287 +   tz = BlackPointIn->Z - cmsD50_XYZ()->Z;
 181.288  
 181.289 -   tx = RelativeBlackPointIn.X - IlluminantIn ->X;
 181.290 -   ty = RelativeBlackPointIn.Y - IlluminantIn ->Y;
 181.291 -   tz = RelativeBlackPointIn.Z - IlluminantIn ->Z;
 181.292 +   ax = (BlackPointOut->X - cmsD50_XYZ()->X) / tx;
 181.293 +   ay = (BlackPointOut->Y - cmsD50_XYZ()->Y) / ty;
 181.294 +   az = (BlackPointOut->Z - cmsD50_XYZ()->Z) / tz;
 181.295  
 181.296 -   ax = (RelativeBlackPointOut.X - IlluminantOut ->X) / tx;
 181.297 -   ay = (RelativeBlackPointOut.Y - IlluminantOut ->Y) / ty;
 181.298 -   az = (RelativeBlackPointOut.Z - IlluminantOut ->Z) / tz;
 181.299 +   bx = - cmsD50_XYZ()-> X * (BlackPointOut->X - BlackPointIn->X) / tx;
 181.300 +   by = - cmsD50_XYZ()-> Y * (BlackPointOut->Y - BlackPointIn->Y) / ty;
 181.301 +   bz = - cmsD50_XYZ()-> Z * (BlackPointOut->Z - BlackPointIn->Z) / tz;
 181.302  
 181.303 -   bx = - IlluminantOut -> X * (RelativeBlackPointOut.X - RelativeBlackPointIn.X) / tx;
 181.304 -   by = - IlluminantOut -> Y * (RelativeBlackPointOut.Y - RelativeBlackPointIn.Y) / ty;
 181.305 -   bz = - IlluminantOut -> Z * (RelativeBlackPointOut.Z - RelativeBlackPointIn.Z) / tz;
 181.306 -
 181.307 -
 181.308 -   MAT3identity(m);
 181.309 -
 181.310 -   m->v[VX].n[0] = ax;
 181.311 -   m->v[VY].n[1] = ay;
 181.312 -   m->v[VZ].n[2] = az;
 181.313 -
 181.314 -   VEC3init(of, bx, by, bz);
 181.315 +   _cmsVEC3init(&m ->v[0], ax, 0,  0);
 181.316 +   _cmsVEC3init(&m ->v[1], 0, ay,  0);
 181.317 +   _cmsVEC3init(&m ->v[2], 0,  0,  az);
 181.318 +   _cmsVEC3init(off, bx, by, bz);
 181.319  
 181.320  }
 181.321  
 181.322 -// Return TRUE if both m and of are empy -- "m" being identity and "of" being 0
 181.323  
 181.324 +// Approximate a blackbody illuminant based on CHAD information
 181.325  static
 181.326 -LCMSBOOL IdentityParameters(LPWMAT3 m, LPWVEC3 of)
 181.327 +cmsFloat64Number CHAD2Temp(const cmsMAT3* Chad)
 181.328  {
 181.329 -    WVEC3 wv0;
 181.330 +    // Convert D50 across CHAD to get the absolute white point
 181.331 +     cmsVEC3 d, s;
 181.332 +     cmsCIEXYZ Dest;
 181.333 +     cmsCIExyY DestChromaticity;
 181.334 +     cmsFloat64Number TempK;
 181.335  
 181.336 -    VEC3initF(&wv0, 0, 0, 0);
 181.337 +    s.n[VX] = cmsD50_XYZ() -> X;
 181.338 +    s.n[VY] = cmsD50_XYZ() -> Y;
 181.339 +    s.n[VZ] = cmsD50_XYZ() -> Z;
 181.340  
 181.341 -    if (!MAT3isIdentity(m, 0.00001)) return FALSE;
 181.342 -    if (!VEC3equal(of, &wv0, 0.00001)) return FALSE;
 181.343 +    _cmsMAT3eval(&d, Chad, &s);
 181.344 +
 181.345 +    Dest.X = d.n[VX];
 181.346 +    Dest.Y = d.n[VY];
 181.347 +    Dest.Z = d.n[VZ];
 181.348 +
 181.349 +    cmsXYZ2xyY(&DestChromaticity, &Dest);
 181.350 +
 181.351 +    if (!cmsTempFromWhitePoint(&TempK, &DestChromaticity))
 181.352 +        return -1.0;
 181.353 +
 181.354 +    return TempK;
 181.355 +}
 181.356 +
 181.357 +// Compute a CHAD based on a given temperature
 181.358 +static
 181.359 +void Temp2CHAD(cmsMAT3* Chad, cmsFloat64Number Temp)
 181.360 +{
 181.361 +    cmsCIEXYZ White;
 181.362 +    cmsCIExyY ChromaticityOfWhite;
 181.363 +
 181.364 +    cmsWhitePointFromTemp(&ChromaticityOfWhite, Temp);
 181.365 +    cmsxyY2XYZ(&White, &ChromaticityOfWhite);
 181.366 +    _cmsAdaptationMatrix(Chad, NULL, cmsD50_XYZ(), &White);
 181.367 +
 181.368 +}
 181.369 +
 181.370 +// Join scalings to obtain relative input to absolute and then to relative output.
 181.371 +// Result is stored in a 3x3 matrix
 181.372 +static
 181.373 +cmsBool  ComputeAbsoluteIntent(cmsFloat64Number AdaptationState,
 181.374 +                               const cmsCIEXYZ* WhitePointIn,
 181.375 +                               const cmsMAT3* ChromaticAdaptationMatrixIn,
 181.376 +                               const cmsCIEXYZ* WhitePointOut,
 181.377 +                               const cmsMAT3* ChromaticAdaptationMatrixOut,
 181.378 +                               cmsMAT3* m)
 181.379 +{
 181.380 +    cmsMAT3 Scale, m1, m2, m3;
 181.381 +
 181.382 +    // Adaptation state
 181.383 +    if (AdaptationState == 1.0) {
 181.384 +
 181.385 +        // Observer is fully adapted. Keep chromatic adaptation.
 181.386 +        // That is the standard V4 behaviour
 181.387 +        _cmsVEC3init(&m->v[0], WhitePointIn->X / WhitePointOut->X, 0, 0);
 181.388 +        _cmsVEC3init(&m->v[1], 0, WhitePointIn->Y / WhitePointOut->Y, 0);
 181.389 +        _cmsVEC3init(&m->v[2], 0, 0, WhitePointIn->Z / WhitePointOut->Z);
 181.390 +
 181.391 +    }
 181.392 +    else  {
 181.393 +
 181.394 +        // Incomplete adaptation. This is an advanced feature.
 181.395 +        _cmsVEC3init(&Scale.v[0], WhitePointIn->X / WhitePointOut->X, 0, 0);
 181.396 +        _cmsVEC3init(&Scale.v[1], 0,  WhitePointIn->Y / WhitePointOut->Y, 0);
 181.397 +        _cmsVEC3init(&Scale.v[2], 0, 0,  WhitePointIn->Z / WhitePointOut->Z);
 181.398 +
 181.399 +        m1 = *ChromaticAdaptationMatrixIn;
 181.400 +        if (!_cmsMAT3inverse(&m1, &m2)) return FALSE;
 181.401 +        _cmsMAT3per(&m3, &m2, &Scale);
 181.402 +
 181.403 +        // m3 holds CHAD from input white to D50 times abs. col. scaling
 181.404 +        if (AdaptationState == 0.0) {
 181.405 +
 181.406 +            // Observer is not adapted, undo the chromatic adaptation
 181.407 +            _cmsMAT3per(m, &m3, ChromaticAdaptationMatrixOut);
 181.408 +
 181.409 +        } else {
 181.410 +
 181.411 +            cmsMAT3 MixedCHAD;
 181.412 +            cmsFloat64Number TempSrc, TempDest, Temp;
 181.413 +
 181.414 +            TempSrc  = CHAD2Temp(ChromaticAdaptationMatrixIn);  // K for source white
 181.415 +            TempDest = CHAD2Temp(ChromaticAdaptationMatrixOut); // K for dest white
 181.416 +
 181.417 +            if (TempSrc < 0.0 || TempDest < 0.0) return FALSE; // Something went wrong
 181.418 +
 181.419 +            if (_cmsMAT3isIdentity(&Scale) && fabs(TempSrc - TempDest) < 0.01) {
 181.420 +
 181.421 +                _cmsMAT3identity(m);
 181.422 +                return TRUE;
 181.423 +            }
 181.424 +
 181.425 +            Temp = AdaptationState * TempSrc + (1.0 - AdaptationState) * TempDest;
 181.426 +
 181.427 +            // Get a CHAD from D50 to whatever output temperature. This replaces output CHAD
 181.428 +            Temp2CHAD(&MixedCHAD, Temp);
 181.429 +
 181.430 +            _cmsMAT3per(m, &m3, &MixedCHAD);
 181.431 +        }
 181.432 +
 181.433 +    }
 181.434 +    return TRUE;
 181.435 +
 181.436 +}
 181.437 +
 181.438 +// Just to see if m matrix should be applied
 181.439 +static
 181.440 +cmsBool IsEmptyLayer(cmsMAT3* m, cmsVEC3* off)
 181.441 +{
 181.442 +    cmsFloat64Number diff = 0;
 181.443 +    cmsMAT3 Ident;
 181.444 +    int i;
 181.445 +
 181.446 +    if (m == NULL && off == NULL) return TRUE;  // NULL is allowed as an empty layer
 181.447 +    if (m == NULL && off != NULL) return FALSE; // This is an internal error
 181.448 +
 181.449 +    _cmsMAT3identity(&Ident);
 181.450 +
 181.451 +    for (i=0; i < 3*3; i++)
 181.452 +        diff += fabs(((cmsFloat64Number*)m)[i] - ((cmsFloat64Number*)&Ident)[i]);
 181.453 +
 181.454 +    for (i=0; i < 3; i++)
 181.455 +        diff += fabs(((cmsFloat64Number*)off)[i]);
 181.456 +
 181.457 +
 181.458 +    return (diff < 0.002);
 181.459 +}
 181.460 +
 181.461 +
 181.462 +// Compute the conversion layer
 181.463 +static
 181.464 +cmsBool ComputeConversion(int i, cmsHPROFILE hProfiles[],
 181.465 +                                 cmsUInt32Number Intent,
 181.466 +                                 cmsBool BPC,
 181.467 +                                 cmsFloat64Number AdaptationState,
 181.468 +                                 cmsMAT3* m, cmsVEC3* off)
 181.469 +{
 181.470 +
 181.471 +    int k;
 181.472 +
 181.473 +    // m  and off are set to identity and this is detected latter on
 181.474 +    _cmsMAT3identity(m);
 181.475 +    _cmsVEC3init(off, 0, 0, 0);
 181.476 +
 181.477 +    // If intent is abs. colorimetric,
 181.478 +    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) {
 181.479 +
 181.480 +        cmsCIEXYZ WhitePointIn, WhitePointOut;
 181.481 +        cmsMAT3 ChromaticAdaptationMatrixIn, ChromaticAdaptationMatrixOut;
 181.482 +
 181.483 +        _cmsReadMediaWhitePoint(&WhitePointIn,  hProfiles[i-1]);
 181.484 +        _cmsReadCHAD(&ChromaticAdaptationMatrixIn, hProfiles[i-1]);
 181.485 +
 181.486 +        _cmsReadMediaWhitePoint(&WhitePointOut,  hProfiles[i]);
 181.487 +        _cmsReadCHAD(&ChromaticAdaptationMatrixOut, hProfiles[i]);
 181.488 +
 181.489 +        if (!ComputeAbsoluteIntent(AdaptationState,
 181.490 +                                  &WhitePointIn,  &ChromaticAdaptationMatrixIn,
 181.491 +                                  &WhitePointOut, &ChromaticAdaptationMatrixOut, m)) return FALSE;
 181.492 +
 181.493 +    }
 181.494 +    else {
 181.495 +        // Rest of intents may apply BPC.
 181.496 +
 181.497 +        if (BPC) {
 181.498 +
 181.499 +            cmsCIEXYZ BlackPointIn, BlackPointOut;
 181.500 +
 181.501 +            cmsDetectBlackPoint(&BlackPointIn,  hProfiles[i-1], Intent, 0);
 181.502 +            cmsDetectBlackPoint(&BlackPointOut, hProfiles[i], Intent, 0);
 181.503 +
 181.504 +            // If black points are equal, then do nothing
 181.505 +            if (BlackPointIn.X != BlackPointOut.X ||
 181.506 +                BlackPointIn.Y != BlackPointOut.Y ||
 181.507 +                BlackPointIn.Z != BlackPointOut.Z)
 181.508 +                    ComputeBlackPointCompensation(&BlackPointIn, &BlackPointOut, m, off);
 181.509 +        }
 181.510 +    }
 181.511 +
 181.512 +    // Offset should be adjusted because the encoding. We encode XYZ normalized to 0..1.0,
 181.513 +    // to do that, we divide by MAX_ENCODEABLE_XZY. The conversion stage goes XYZ -> XYZ so
 181.514 +    // we have first to convert from encoded to XYZ and then convert back to encoded.
 181.515 +    // y = Mx + Off
 181.516 +    // x = x'c
 181.517 +    // y = M x'c + Off
 181.518 +    // y = y'c; y' = y / c
 181.519 +    // y' = (Mx'c + Off) /c = Mx' + (Off / c)
 181.520 +
 181.521 +    for (k=0; k < 3; k++) {
 181.522 +        off ->n[k] /= MAX_ENCODEABLE_XYZ;
 181.523 +    }
 181.524  
 181.525      return TRUE;
 181.526  }
 181.527  
 181.528  
 181.529 +// Add a conversion stage if needed. If a matrix/offset m is given, it applies to XYZ space
 181.530 +static
 181.531 +cmsBool AddConversion(cmsPipeline* Result, cmsColorSpaceSignature InPCS, cmsColorSpaceSignature OutPCS, cmsMAT3* m, cmsVEC3* off)
 181.532 +{
 181.533 +    cmsFloat64Number* m_as_dbl = (cmsFloat64Number*) m;
 181.534 +    cmsFloat64Number* off_as_dbl = (cmsFloat64Number*) off;
 181.535  
 181.536 +    // Handle PCS mismatches. A specialized stage is added to the LUT in such case
 181.537 +    switch (InPCS) {
 181.538  
 181.539 -// ----------------------------------------- Inter PCS conversions
 181.540 +        case cmsSigXYZData: // Input profile operates in XYZ
 181.541  
 181.542 -// XYZ to XYZ linear scaling. Aso used on Black point compensation
 181.543 +            switch (OutPCS) {
 181.544  
 181.545 -static
 181.546 -void XYZ2XYZ(WORD In[], WORD Out[], LPWMAT3 m, LPWVEC3 of)
 181.547 -{
 181.548 +            case cmsSigXYZData:  // XYZ -> XYZ
 181.549 +                if (!IsEmptyLayer(m, off))
 181.550 +                    cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
 181.551 +                break;
 181.552  
 181.553 -    WVEC3 a, r;
 181.554 +            case cmsSigLabData:  // XYZ -> Lab
 181.555 +                if (!IsEmptyLayer(m, off))
 181.556 +                    cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
 181.557 +                cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID));
 181.558 +                break;
 181.559  
 181.560 -    a.n[0] = In[0] << 1;
 181.561 -    a.n[1] = In[1] << 1;
 181.562 -    a.n[2] = In[2] << 1;
 181.563 +            default:
 181.564 +                return FALSE;   // Colorspace mismatch
 181.565 +                }
 181.566 +                break;
 181.567  
 181.568 -    MAT3evalW(&r, m, &a);
 181.569  
 181.570 -    Out[0] = _cmsClampWord((r.n[VX] + of->n[VX]) >> 1);
 181.571 -    Out[1] = _cmsClampWord((r.n[VY] + of->n[VY]) >> 1);
 181.572 -    Out[2] = _cmsClampWord((r.n[VZ] + of->n[VZ]) >> 1);
 181.573 +        case cmsSigLabData: // Input profile operates in Lab
 181.574 +
 181.575 +            switch (OutPCS) {
 181.576 +
 181.577 +            case cmsSigXYZData:  // Lab -> XYZ
 181.578 +
 181.579 +                cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID));
 181.580 +                if (!IsEmptyLayer(m, off))
 181.581 +                    cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
 181.582 +                break;
 181.583 +
 181.584 +            case cmsSigLabData:  // Lab -> Lab
 181.585 +
 181.586 +                if (!IsEmptyLayer(m, off)) {
 181.587 +                    cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocLab2XYZ(Result ->ContextID));
 181.588 +                    cmsPipelineInsertStage(Result, cmsAT_END, cmsStageAllocMatrix(Result ->ContextID, 3, 3, m_as_dbl, off_as_dbl));
 181.589 +                    cmsPipelineInsertStage(Result, cmsAT_END, _cmsStageAllocXYZ2Lab(Result ->ContextID));
 181.590 +                }
 181.591 +                break;
 181.592 +
 181.593 +            default:
 181.594 +                return FALSE;  // Mismatch
 181.595 +            }
 181.596 +            break;
 181.597 +
 181.598 +
 181.599 +            // On colorspaces other than PCS, check for same space
 181.600 +        default:
 181.601 +            if (InPCS != OutPCS) return FALSE;
 181.602 +            break;
 181.603 +    }
 181.604 +
 181.605 +    return TRUE;
 181.606  }
 181.607  
 181.608  
 181.609 -// XYZ to Lab, scaling first
 181.610 +// Is a given space compatible with another?
 181.611 +static
 181.612 +cmsBool ColorSpaceIsCompatible(cmsColorSpaceSignature a, cmsColorSpaceSignature b)
 181.613 +{
 181.614 +    // If they are same, they are compatible.
 181.615 +    if (a == b) return TRUE;
 181.616  
 181.617 -static
 181.618 -void XYZ2Lab(WORD In[], WORD Out[], LPWMAT3 m, LPWVEC3 of)
 181.619 -{
 181.620 -  WORD XYZ[3];
 181.621 +    // Check for XYZ/Lab. Those spaces are interchangeable as they can be computed one from other.
 181.622 +    if ((a == cmsSigXYZData) && (b == cmsSigLabData)) return TRUE;
 181.623 +    if ((a == cmsSigLabData) && (b == cmsSigXYZData)) return TRUE;
 181.624  
 181.625 -  XYZ2XYZ(In, XYZ, m, of);
 181.626 -  cmsXYZ2LabEncoded(XYZ, Out);
 181.627 +    return FALSE;
 181.628  }
 181.629  
 181.630 -// Lab to XYZ, then scalling
 181.631  
 181.632 +// Default handler for ICC-style intents
 181.633  static
 181.634 -void Lab2XYZ(WORD In[], WORD Out[], LPWMAT3 m, LPWVEC3 of)
 181.635 +cmsPipeline* DefaultICCintents(cmsContext       ContextID,
 181.636 +                               cmsUInt32Number  nProfiles,
 181.637 +                               cmsUInt32Number  TheIntents[],
 181.638 +                               cmsHPROFILE      hProfiles[],
 181.639 +                               cmsBool          BPC[],
 181.640 +                               cmsFloat64Number AdaptationStates[],
 181.641 +                               cmsUInt32Number  dwFlags)
 181.642  {
 181.643 -       WORD XYZ[3];
 181.644 +    cmsPipeline* Lut, *Result;
 181.645 +    cmsHPROFILE hProfile;
 181.646 +    cmsMAT3 m;
 181.647 +    cmsVEC3 off;
 181.648 +    cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut, CurrentColorSpace;
 181.649 +    cmsProfileClassSignature ClassSig;
 181.650 +    cmsUInt32Number  i, Intent;
 181.651  
 181.652 -       cmsLab2XYZEncoded(In, XYZ);
 181.653 -       XYZ2XYZ(XYZ, Out, m, of);
 181.654 +    // For safety
 181.655 +    if (nProfiles == 0) return NULL;
 181.656 +
 181.657 +    // Allocate an empty LUT for holding the result. 0 as channel count means 'undefined'
 181.658 +    Result = cmsPipelineAlloc(ContextID, 0, 0);
 181.659 +    if (Result == NULL) return NULL;
 181.660 +
 181.661 +    CurrentColorSpace = cmsGetColorSpace(hProfiles[0]);
 181.662 +
 181.663 +    for (i=0; i < nProfiles; i++) {
 181.664 +
 181.665 +        cmsBool  lIsDeviceLink, lIsInput;
 181.666 +
 181.667 +        hProfile      = hProfiles[i];
 181.668 +        ClassSig      = cmsGetDeviceClass(hProfile);
 181.669 +        lIsDeviceLink = (ClassSig == cmsSigLinkClass || ClassSig == cmsSigAbstractClass );
 181.670 +
 181.671 +        // First profile is used as input unless devicelink or abstract
 181.672 +        if ((i == 0) && !lIsDeviceLink) {
 181.673 +            lIsInput = TRUE;
 181.674 +        }
 181.675 +        else {
 181.676 +            // Else use profile in the input direction if current space is not PCS
 181.677 +        lIsInput      = (CurrentColorSpace != cmsSigXYZData) &&
 181.678 +                        (CurrentColorSpace != cmsSigLabData);
 181.679 +        }
 181.680 +
 181.681 +        Intent        = TheIntents[i];
 181.682 +
 181.683 +        if (lIsInput || lIsDeviceLink) {
 181.684 +
 181.685 +            ColorSpaceIn    = cmsGetColorSpace(hProfile);
 181.686 +            ColorSpaceOut   = cmsGetPCS(hProfile);
 181.687 +        }
 181.688 +        else {
 181.689 +
 181.690 +            ColorSpaceIn    = cmsGetPCS(hProfile);
 181.691 +            ColorSpaceOut   = cmsGetColorSpace(hProfile);
 181.692 +        }
 181.693 +
 181.694 +        if (!ColorSpaceIsCompatible(ColorSpaceIn, CurrentColorSpace)) {
 181.695 +
 181.696 +            cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "ColorSpace mismatch");
 181.697 +            goto Error;
 181.698 +        }
 181.699 +
 181.700 +        // If devicelink is found, then no custom intent is allowed and we can
 181.701 +        // read the LUT to be applied. Settings don't apply here.
 181.702 +        if (lIsDeviceLink) {
 181.703 +
 181.704 +            // Get the involved LUT from the profile
 181.705 +            Lut = _cmsReadDevicelinkLUT(hProfile, Intent);
 181.706 +            if (Lut == NULL) goto Error;
 181.707 +
 181.708 +            // What about abstract profiles?
 181.709 +             if (ClassSig == cmsSigAbstractClass && i > 0) {
 181.710 +                if (!ComputeConversion(i, hProfiles, Intent, BPC[i], AdaptationStates[i], &m, &off)) goto Error;
 181.711 +             }
 181.712 +             else {
 181.713 +                _cmsMAT3identity(&m);
 181.714 +                _cmsVEC3init(&off, 0, 0, 0);
 181.715 +             }
 181.716 +
 181.717 +
 181.718 +            if (!AddConversion(Result, CurrentColorSpace, ColorSpaceIn, &m, &off)) goto Error;
 181.719 +
 181.720 +        }
 181.721 +        else {
 181.722 +
 181.723 +            if (lIsInput) {
 181.724 +                // Input direction means non-pcs connection, so proceed like devicelinks
 181.725 +                Lut = _cmsReadInputLUT(hProfile, Intent);
 181.726 +                if (Lut == NULL) goto Error;
 181.727 +            }
 181.728 +            else {
 181.729 +
 181.730 +                // Output direction means PCS connection. Intent may apply here
 181.731 +                Lut = _cmsReadOutputLUT(hProfile, Intent);
 181.732 +                if (Lut == NULL) goto Error;
 181.733 +
 181.734 +
 181.735 +                if (!ComputeConversion(i, hProfiles, Intent, BPC[i], AdaptationStates[i], &m, &off)) goto Error;
 181.736 +                if (!AddConversion(Result, CurrentColorSpace, ColorSpaceIn, &m, &off)) goto Error;
 181.737 +
 181.738 +            }
 181.739 +        }
 181.740 +
 181.741 +        // Concatenate to the output LUT
 181.742 +        cmsPipelineCat(Result, Lut);
 181.743 +        cmsPipelineFree(Lut);
 181.744 +
 181.745 +        // Update current space
 181.746 +        CurrentColorSpace = ColorSpaceOut;
 181.747 +    }
 181.748 +
 181.749 +    return Result;
 181.750 +
 181.751 +Error:
 181.752 +
 181.753 +    if (Result != NULL) cmsPipelineFree(Result);
 181.754 +    return NULL;
 181.755 +
 181.756 +    cmsUNUSED_PARAMETER(dwFlags);
 181.757  }
 181.758  
 181.759 -// Lab to XYZ, scalling and then, back to Lab
 181.760  
 181.761 -static
 181.762 -void Lab2XYZ2Lab(WORD In[], WORD Out[], LPWMAT3 m, LPWVEC3 of)
 181.763 +// Wrapper for DLL calling convention
 181.764 +cmsPipeline*  CMSEXPORT _cmsDefaultICCintents(cmsContext     ContextID,
 181.765 +                                              cmsUInt32Number nProfiles,
 181.766 +                                              cmsUInt32Number TheIntents[],
 181.767 +                                              cmsHPROFILE     hProfiles[],
 181.768 +                                              cmsBool         BPC[],
 181.769 +                                              cmsFloat64Number AdaptationStates[],
 181.770 +                                              cmsUInt32Number dwFlags)
 181.771  {
 181.772 -       WORD XYZ[3], XYZ2[3];
 181.773 -
 181.774 -       cmsLab2XYZEncoded(In, XYZ);
 181.775 -       XYZ2XYZ(XYZ, XYZ2, m, of);
 181.776 -       cmsXYZ2LabEncoded(XYZ2, Out);
 181.777 +    return DefaultICCintents(ContextID, nProfiles, TheIntents, hProfiles, BPC, AdaptationStates, dwFlags);
 181.778  }
 181.779  
 181.780 -// ------------------------------------------------------------------
 181.781 +// Black preserving intents ---------------------------------------------------------------------------------------------
 181.782  
 181.783 -// Dispatcher for XYZ Relative LUT
 181.784 +// Translate black-preserving intents to ICC ones
 181.785 +static
 181.786 +int TranslateNonICCIntents(int Intent)
 181.787 +{
 181.788 +    switch (Intent) {
 181.789 +        case INTENT_PRESERVE_K_ONLY_PERCEPTUAL:
 181.790 +        case INTENT_PRESERVE_K_PLANE_PERCEPTUAL:
 181.791 +            return INTENT_PERCEPTUAL;
 181.792  
 181.793 -static
 181.794 -int FromXYZRelLUT(int Absolute,
 181.795 -                             LPcmsCIEXYZ BlackPointIn,
 181.796 -                             LPcmsCIEXYZ WhitePointIn,
 181.797 -                             LPcmsCIEXYZ IlluminantIn,
 181.798 -                             LPMAT3 ChromaticAdaptationMatrixIn,
 181.799 +        case INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC:
 181.800 +        case INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC:
 181.801 +            return INTENT_RELATIVE_COLORIMETRIC;
 181.802  
 181.803 -                 int Phase2, LPcmsCIEXYZ BlackPointOut,
 181.804 -                             LPcmsCIEXYZ WhitePointOut,
 181.805 -                             LPcmsCIEXYZ IlluminantOut,
 181.806 -                             LPMAT3 ChromaticAdaptationMatrixOut,
 181.807 +        case INTENT_PRESERVE_K_ONLY_SATURATION:
 181.808 +        case INTENT_PRESERVE_K_PLANE_SATURATION:
 181.809 +            return INTENT_SATURATION;
 181.810  
 181.811 -                 int DoBlackPointCompensation,
 181.812 -                 double AdaptationState,
 181.813 -                 _cmsADJFN *fn1,
 181.814 -                 LPMAT3 m, LPVEC3 of)
 181.815 -
 181.816 -{
 181.817 -              switch (Phase2) {
 181.818 -
 181.819 -                     // From relative XYZ to Relative XYZ.
 181.820 -
 181.821 -                     case XYZRel:
 181.822 -
 181.823 -                            if (Absolute)
 181.824 -                            {
 181.825 -                                   // From input relative to absolute, and then
 181.826 -                                   // back to output relative
 181.827 -
 181.828 -                                   Rel2RelStepAbsCoefs(AdaptationState,
 181.829 -                                                       BlackPointIn,
 181.830 -                                                       WhitePointIn,
 181.831 -                                                       IlluminantIn,
 181.832 -                                                       ChromaticAdaptationMatrixIn,
 181.833 -                                                       BlackPointOut,
 181.834 -                                                       WhitePointOut,
 181.835 -                                                       IlluminantOut,
 181.836 -                                                       ChromaticAdaptationMatrixOut,
 181.837 -                                                       m, of);
 181.838 -                                   *fn1 = XYZ2XYZ;
 181.839 -
 181.840 -                            }
 181.841 -                            else
 181.842 -                            {
 181.843 -                                   // XYZ Relative to XYZ relative, no op required
 181.844 -                                   *fn1 = NULL;
 181.845 -                                   if (DoBlackPointCompensation) {
 181.846 -
 181.847 -                                      *fn1 = XYZ2XYZ;
 181.848 -                                      ComputeBlackPointCompensationFactors(BlackPointIn,
 181.849 -                                                                      WhitePointIn,
 181.850 -                                                                      IlluminantIn,
 181.851 -                                                                      BlackPointOut,
 181.852 -                                                                      WhitePointOut,
 181.853 -                                                                      IlluminantOut,
 181.854 -                                                                      m, of);
 181.855 -
 181.856 -                                   }
 181.857 -                            }
 181.858 -                            break;
 181.859 -
 181.860 -
 181.861 -                     // From relative XYZ to Relative Lab
 181.862 -
 181.863 -                     case LabRel:
 181.864 -
 181.865 -                            // First pass XYZ to absolute, then to relative and
 181.866 -                            // finally to Lab. I use here D50 for output in order
 181.867 -                            // to prepare the "to Lab" conversion.
 181.868 -
 181.869 -                            if (Absolute)
 181.870 -                            {
 181.871 -
 181.872 -                                Rel2RelStepAbsCoefs(AdaptationState,
 181.873 -                                                    BlackPointIn,
 181.874 -                                                    WhitePointIn,
 181.875 -                                                    IlluminantIn,
 181.876 -                                                    ChromaticAdaptationMatrixIn,
 181.877 -                                                    BlackPointOut,
 181.878 -                                                    WhitePointOut,
 181.879 -                                                    IlluminantOut,
 181.880 -                                                    ChromaticAdaptationMatrixOut,
 181.881 -                                                    m, of);
 181.882 -
 181.883 -                                *fn1 = XYZ2Lab;
 181.884 -
 181.885 -                            }
 181.886 -                            else
 181.887 -                            {
 181.888 -                                   // Just Convert to Lab
 181.889 -
 181.890 -                                   MAT3identity(m);
 181.891 -                                   VEC3init(of, 0, 0, 0);
 181.892 -                                   *fn1 = XYZ2Lab;
 181.893 -
 181.894 -                                   if (DoBlackPointCompensation) {
 181.895 -
 181.896 -                                    ComputeBlackPointCompensationFactors(BlackPointIn,
 181.897 -                                                                          WhitePointIn,
 181.898 -                                                                          IlluminantIn,
 181.899 -                                                                          BlackPointOut,
 181.900 -                                                                          WhitePointOut,
 181.901 -                                                                          IlluminantOut,
 181.902 -                                                                          m, of);
 181.903 -                                   }
 181.904 -                            }
 181.905 -                            break;
 181.906 -
 181.907 -
 181.908 -                     default: return FALSE;
 181.909 -                     }
 181.910 -
 181.911 -              return TRUE;
 181.912 +        default: return Intent;
 181.913 +    }
 181.914  }
 181.915  
 181.916 +// Sampler for Black-only preserving CMYK->CMYK transforms
 181.917  
 181.918 +typedef struct {
 181.919 +    cmsPipeline*    cmyk2cmyk;      // The original transform
 181.920 +    cmsToneCurve*   KTone;          // Black-to-black tone curve
 181.921  
 181.922 +} GrayOnlyParams;
 181.923  
 181.924 -// From Lab Relative type LUT
 181.925  
 181.926 +// Preserve black only if that is the only ink used
 181.927  static
 181.928 -int FromLabRelLUT(int Absolute,
 181.929 -                             LPcmsCIEXYZ BlackPointIn,
 181.930 -                             LPcmsCIEXYZ WhitePointIn,
 181.931 -                             LPcmsCIEXYZ IlluminantIn,
 181.932 -                             LPMAT3 ChromaticAdaptationMatrixIn,
 181.933 +int BlackPreservingGrayOnlySampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
 181.934 +{
 181.935 +    GrayOnlyParams* bp = (GrayOnlyParams*) Cargo;
 181.936  
 181.937 -                 int Phase2, LPcmsCIEXYZ BlackPointOut,
 181.938 -                             LPcmsCIEXYZ WhitePointOut,
 181.939 -                             LPcmsCIEXYZ IlluminantOut,
 181.940 -                             LPMAT3 ChromaticAdaptationMatrixOut,
 181.941 +    // If going across black only, keep black only
 181.942 +    if (In[0] == 0 && In[1] == 0 && In[2] == 0) {
 181.943  
 181.944 -                int DoBlackPointCompensation,
 181.945 -                double AdaptationState,
 181.946 +        // TAC does not apply because it is black ink!
 181.947 +        Out[0] = Out[1] = Out[2] = 0;
 181.948 +        Out[3] = cmsEvalToneCurve16(bp->KTone, In[3]);
 181.949 +        return TRUE;
 181.950 +    }
 181.951  
 181.952 -                 _cmsADJFN *fn1,
 181.953 -                 LPMAT3 m, LPVEC3 of)
 181.954 -{
 181.955 -
 181.956 -          switch (Phase2) {
 181.957 -
 181.958 -              // From Lab Relative to XYZ Relative, very usual case
 181.959 -
 181.960 -              case XYZRel:
 181.961 -
 181.962 -                  if (Absolute) {  // Absolute intent
 181.963 -
 181.964 -                            // From lab relative, to XYZ absolute, and then,
 181.965 -                            // back to XYZ relative
 181.966 -
 181.967 -                            Rel2RelStepAbsCoefs(AdaptationState,
 181.968 -                                                BlackPointIn,
 181.969 -                                                WhitePointIn,
 181.970 -                                                cmsD50_XYZ(),
 181.971 -                                                ChromaticAdaptationMatrixIn,
 181.972 -                                                BlackPointOut,
 181.973 -                                                WhitePointOut,
 181.974 -                                                IlluminantOut,
 181.975 -                                                ChromaticAdaptationMatrixOut,
 181.976 -                                                m, of);
 181.977 -
 181.978 -                            *fn1 = Lab2XYZ;
 181.979 -
 181.980 -                     }
 181.981 -                     else
 181.982 -                     {
 181.983 -                            // From Lab relative, to XYZ relative.
 181.984 -
 181.985 -                            *fn1 = Lab2XYZ;
 181.986 -                            if (DoBlackPointCompensation) {
 181.987 -
 181.988 -                                 ComputeBlackPointCompensationFactors(BlackPointIn,
 181.989 -                                                                      WhitePointIn,
 181.990 -                                                                      IlluminantIn,
 181.991 -                                                                      BlackPointOut,
 181.992 -                                                                      WhitePointOut,
 181.993 -                                                                      IlluminantOut,
 181.994 -                                                                      m, of);
 181.995 -
 181.996 -                            }
 181.997 -                     }
 181.998 -                     break;
 181.999 -
181.1000 -
181.1001 -
181.1002 -              case LabRel:
181.1003 -
181.1004 -                     if (Absolute) {
181.1005 -
181.1006 -                             // First pass to XYZ using the input illuminant
181.1007 -                             // * InIlluminant / D50, then to absolute. Then
181.1008 -                             // to relative, but for input
181.1009 -
181.1010 -                             Rel2RelStepAbsCoefs(AdaptationState,
181.1011 -                                                 BlackPointIn,
181.1012 -                                                 WhitePointIn, IlluminantIn,
181.1013 -                                                 ChromaticAdaptationMatrixIn,
181.1014 -                                                 BlackPointOut,
181.1015 -                                                 WhitePointOut, cmsD50_XYZ(),
181.1016 -                                                 ChromaticAdaptationMatrixOut,
181.1017 -                                                 m, of);
181.1018 -                             *fn1 = Lab2XYZ2Lab;
181.1019 -                     }
181.1020 -                     else
181.1021 -                     {      // Lab -> Lab relative don't need any adjust unless
181.1022 -                            // black point compensation
181.1023 -
181.1024 -                            *fn1 = NULL;
181.1025 -                             if (DoBlackPointCompensation) {
181.1026 -
181.1027 -                                 *fn1 = Lab2XYZ2Lab;
181.1028 -                                 ComputeBlackPointCompensationFactors(BlackPointIn,
181.1029 -                                                                      WhitePointIn,
181.1030 -                                                                      IlluminantIn,
181.1031 -                                                                      BlackPointOut,
181.1032 -                                                                      WhitePointOut,
181.1033 -                                                                      IlluminantOut,
181.1034 -                                                                      m, of);
181.1035 -
181.1036 -
181.1037 -                            }
181.1038 -                     }
181.1039 -                     break;
181.1040 -
181.1041 -
181.1042 -              default: return FALSE;
181.1043 -              }
181.1044 -
181.1045 -   return TRUE;
181.1046 +    // Keep normal transform for other colors
181.1047 +    bp ->cmyk2cmyk ->Eval16Fn(In, Out, bp ->cmyk2cmyk->Data);
181.1048 +    return TRUE;
181.1049  }
181.1050  
181.1051 +// This is the entry for black-preserving K-only intents, which are non-ICC
181.1052 +static
181.1053 +cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,
181.1054 +                                          cmsUInt32Number nProfiles,
181.1055 +                                          cmsUInt32Number TheIntents[],
181.1056 +                                          cmsHPROFILE     hProfiles[],
181.1057 +                                          cmsBool         BPC[],
181.1058 +                                          cmsFloat64Number AdaptationStates[],
181.1059 +                                          cmsUInt32Number dwFlags)
181.1060 +{
181.1061 +    GrayOnlyParams  bp;
181.1062 +    cmsPipeline*    Result;
181.1063 +    cmsUInt32Number ICCIntents[256];
181.1064 +    cmsStage*         CLUT;
181.1065 +    cmsUInt32Number i, nGridPoints;
181.1066  
181.1067 -// This function does calculate the necessary conversion operations
181.1068 -// needed from transpassing data from a LUT to a LUT. The conversion
181.1069 -// is modeled as a pointer of function and two coefficients, a and b
181.1070 -// The function is actually called only if not null pointer is provided,
181.1071 -// and the two paramaters are passed in. There are several types of
181.1072 -// conversions, but basically they do a linear scalling and a interchange
181.1073  
181.1074 +    // Sanity check
181.1075 +    if (nProfiles < 1 || nProfiles > 255) return NULL;
181.1076  
181.1077 +    // Translate black-preserving intents to ICC ones
181.1078 +    for (i=0; i < nProfiles; i++)
181.1079 +        ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]);
181.1080  
181.1081 -// Main dispatcher
181.1082 +    // Check for non-cmyk profiles
181.1083 +    if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
181.1084 +        cmsGetColorSpace(hProfiles[nProfiles-1]) != cmsSigCmykData)
181.1085 +           return DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags);
181.1086  
181.1087 -int cmsChooseCnvrt(int Absolute,
181.1088 -                  int Phase1, LPcmsCIEXYZ BlackPointIn,
181.1089 -                              LPcmsCIEXYZ WhitePointIn,
181.1090 -                              LPcmsCIEXYZ IlluminantIn,
181.1091 -                              LPMAT3 ChromaticAdaptationMatrixIn,
181.1092 +    memset(&bp, 0, sizeof(bp));
181.1093  
181.1094 -                  int Phase2, LPcmsCIEXYZ BlackPointOut,
181.1095 -                              LPcmsCIEXYZ WhitePointOut,
181.1096 -                              LPcmsCIEXYZ IlluminantOut,
181.1097 -                              LPMAT3 ChromaticAdaptationMatrixOut,
181.1098 +    // Allocate an empty LUT for holding the result
181.1099 +    Result = cmsPipelineAlloc(ContextID, 4, 4);
181.1100 +    if (Result == NULL) return NULL;
181.1101  
181.1102 -                  int DoBlackPointCompensation,
181.1103 -                  double AdaptationState,
181.1104 -                  _cmsADJFN *fn1,
181.1105 -                  LPWMAT3 wm, LPWVEC3 wof)
181.1106 -{
181.1107 +    // Create a LUT holding normal ICC transform
181.1108 +    bp.cmyk2cmyk = DefaultICCintents(ContextID,
181.1109 +        nProfiles,
181.1110 +        ICCIntents,
181.1111 +        hProfiles,
181.1112 +        BPC,
181.1113 +        AdaptationStates,
181.1114 +        dwFlags);
181.1115  
181.1116 -       int rc;
181.1117 -       MAT3 m;
181.1118 -       VEC3 of;
181.1119 +    if (bp.cmyk2cmyk == NULL) goto Error;
181.1120  
181.1121 +    // Now, compute the tone curve
181.1122 +    bp.KTone = _cmsBuildKToneCurve(ContextID,
181.1123 +        4096,
181.1124 +        nProfiles,
181.1125 +        ICCIntents,
181.1126 +        hProfiles,
181.1127 +        BPC,
181.1128 +        AdaptationStates,
181.1129 +        dwFlags);
181.1130  
181.1131 -       MAT3identity(&m);
181.1132 -       VEC3init(&of, 0, 0, 0);
181.1133 +    if (bp.KTone == NULL) goto Error;
181.1134  
181.1135 -       switch (Phase1) {
181.1136  
181.1137 -       // Input LUT is giving XYZ relative values.
181.1138 +    // How many gridpoints are we going to use?
181.1139 +    nGridPoints = _cmsReasonableGridpointsByColorspace(cmsSigCmykData, dwFlags);
181.1140  
181.1141 -       case XYZRel:  rc = FromXYZRelLUT(Absolute,
181.1142 -                                          BlackPointIn,
181.1143 -                                          WhitePointIn,
181.1144 -                                          IlluminantIn,
181.1145 -                                          ChromaticAdaptationMatrixIn,
181.1146 -                                          Phase2,
181.1147 -                                          BlackPointOut,
181.1148 -                                          WhitePointOut,
181.1149 -                                          IlluminantOut,
181.1150 -                                          ChromaticAdaptationMatrixOut,
181.1151 -                                          DoBlackPointCompensation,
181.1152 -                                          AdaptationState,
181.1153 -                                          fn1, &m, &of);
181.1154 -                     break;
181.1155 +    // Create the CLUT. 16 bits
181.1156 +    CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL);
181.1157 +    if (CLUT == NULL) goto Error;
181.1158  
181.1159 +    // This is the one and only MPE in this LUT
181.1160 +    cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT);
181.1161  
181.1162 +    // Sample it. We cannot afford pre/post linearization this time.
181.1163 +    if (!cmsStageSampleCLut16bit(CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0))
181.1164 +        goto Error;
181.1165  
181.1166 -       // Input LUT is giving Lab relative values
181.1167 +    // Get rid of xform and tone curve
181.1168 +    cmsPipelineFree(bp.cmyk2cmyk);
181.1169 +    cmsFreeToneCurve(bp.KTone);
181.1170  
181.1171 -       case LabRel:  rc =  FromLabRelLUT(Absolute,
181.1172 -                                          BlackPointIn,
181.1173 -                                          WhitePointIn,
181.1174 -                                          IlluminantIn,
181.1175 -                                          ChromaticAdaptationMatrixIn,
181.1176 -                                          Phase2,
181.1177 -                                          BlackPointOut,
181.1178 -                                          WhitePointOut,
181.1179 -                                          IlluminantOut,
181.1180 -                                          ChromaticAdaptationMatrixOut,
181.1181 -                                          DoBlackPointCompensation,
181.1182 -                                          AdaptationState,
181.1183 -                                          fn1, &m, &of);
181.1184 -                     break;
181.1185 +    return Result;
181.1186  
181.1187 +Error:
181.1188  
181.1189 +    if (bp.cmyk2cmyk != NULL) cmsPipelineFree(bp.cmyk2cmyk);
181.1190 +    if (bp.KTone != NULL)  cmsFreeToneCurve(bp.KTone);
181.1191 +    if (Result != NULL) cmsPipelineFree(Result);
181.1192 +    return NULL;
181.1193  
181.1194 -
181.1195 -       // Unrecognized combination
181.1196 -
181.1197 -       default:    cmsSignalError(LCMS_ERRC_ABORTED, "(internal) Phase error");
181.1198 -                   return FALSE;
181.1199 -
181.1200 -       }
181.1201 -
181.1202 -       MAT3toFix(wm, &m);
181.1203 -       VEC3toFix(wof, &of);
181.1204 -
181.1205 -       // Do some optimization -- discard conversion if identity parameters.
181.1206 -
181.1207 -       if (*fn1 == XYZ2XYZ || *fn1 == Lab2XYZ2Lab) {
181.1208 -
181.1209 -           if (IdentityParameters(wm, wof))
181.1210 -               *fn1 = NULL;
181.1211 -       }
181.1212 -
181.1213 -
181.1214 -       return rc;
181.1215  }
181.1216  
181.1217 +// K Plane-preserving CMYK to CMYK ------------------------------------------------------------------------------------
181.1218  
181.1219 +typedef struct {
181.1220  
181.1221 +    cmsPipeline*     cmyk2cmyk;     // The original transform
181.1222 +    cmsHTRANSFORM    hProofOutput;  // Output CMYK to Lab (last profile)
181.1223 +    cmsHTRANSFORM    cmyk2Lab;      // The input chain
181.1224 +    cmsToneCurve*    KTone;         // Black-to-black tone curve
181.1225 +    cmsPipeline*     LabK2cmyk;     // The output profile
181.1226 +    cmsFloat64Number MaxError;
181.1227 +
181.1228 +    cmsHTRANSFORM    hRoundTrip;
181.1229 +    cmsFloat64Number MaxTAC;
181.1230 +
181.1231 +
181.1232 +} PreserveKPlaneParams;
181.1233 +
181.1234 +
181.1235 +// The CLUT will be stored at 16 bits, but calculations are performed at cmsFloat32Number precision
181.1236 +static
181.1237 +int BlackPreservingSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
181.1238 +{
181.1239 +    int i;
181.1240 +    cmsFloat32Number Inf[4], Outf[4];
181.1241 +    cmsFloat32Number LabK[4];
181.1242 +    cmsFloat64Number SumCMY, SumCMYK, Error, Ratio;
181.1243 +    cmsCIELab ColorimetricLab, BlackPreservingLab;
181.1244 +    PreserveKPlaneParams* bp = (PreserveKPlaneParams*) Cargo;
181.1245 +
181.1246 +    // Convert from 16 bits to floating point
181.1247 +    for (i=0; i < 4; i++)
181.1248 +        Inf[i] = (cmsFloat32Number) (In[i] / 65535.0);
181.1249 +
181.1250 +    // Get the K across Tone curve
181.1251 +    LabK[3] = cmsEvalToneCurveFloat(bp ->KTone, Inf[3]);
181.1252 +
181.1253 +    // If going across black only, keep black only
181.1254 +    if (In[0] == 0 && In[1] == 0 && In[2] == 0) {
181.1255 +
181.1256 +        Out[0] = Out[1] = Out[2] = 0;
181.1257 +        Out[3] = _cmsQuickSaturateWord(LabK[3] * 65535.0);
181.1258 +        return TRUE;
181.1259 +    }
181.1260 +
181.1261 +    // Try the original transform,
181.1262 +    cmsPipelineEvalFloat( Inf, Outf, bp ->cmyk2cmyk);
181.1263 +
181.1264 +    // Store a copy of the floating point result into 16-bit
181.1265 +    for (i=0; i < 4; i++)
181.1266 +            Out[i] = _cmsQuickSaturateWord(Outf[i] * 65535.0);
181.1267 +
181.1268 +    // Maybe K is already ok (mostly on K=0)
181.1269 +    if ( fabs(Outf[3] - LabK[3]) < (3.0 / 65535.0) ) {
181.1270 +        return TRUE;
181.1271 +    }
181.1272 +
181.1273 +    // K differ, mesure and keep Lab measurement for further usage
181.1274 +    // this is done in relative colorimetric intent
181.1275 +    cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1);
181.1276 +
181.1277 +    // Is not black only and the transform doesn't keep black.
181.1278 +    // Obtain the Lab of output CMYK. After that we have Lab + K
181.1279 +    cmsDoTransform(bp ->cmyk2Lab, Outf, LabK, 1);
181.1280 +
181.1281 +    // Obtain the corresponding CMY using reverse interpolation
181.1282 +    // (K is fixed in LabK[3])
181.1283 +    if (!cmsPipelineEvalReverseFloat(LabK, Outf, Outf, bp ->LabK2cmyk)) {
181.1284 +
181.1285 +        // Cannot find a suitable value, so use colorimetric xform
181.1286 +        // which is already stored in Out[]
181.1287 +        return TRUE;
181.1288 +    }
181.1289 +
181.1290 +    // Make sure to pass thru K (which now is fixed)
181.1291 +    Outf[3] = LabK[3];
181.1292 +
181.1293 +    // Apply TAC if needed
181.1294 +    SumCMY   = Outf[0]  + Outf[1] + Outf[2];
181.1295 +    SumCMYK  = SumCMY + Outf[3];
181.1296 +
181.1297 +    if (SumCMYK > bp ->MaxTAC) {
181.1298 +
181.1299 +        Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY);
181.1300 +        if (Ratio < 0)
181.1301 +            Ratio = 0;
181.1302 +    }
181.1303 +    else
181.1304 +       Ratio = 1.0;
181.1305 +
181.1306 +    Out[0] = _cmsQuickSaturateWord(Outf[0] * Ratio * 65535.0);     // C
181.1307 +    Out[1] = _cmsQuickSaturateWord(Outf[1] * Ratio * 65535.0);     // M
181.1308 +    Out[2] = _cmsQuickSaturateWord(Outf[2] * Ratio * 65535.0);     // Y
181.1309 +    Out[3] = _cmsQuickSaturateWord(Outf[3] * 65535.0);
181.1310 +
181.1311 +    // Estimate the error (this goes 16 bits to Lab DBL)
181.1312 +    cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1);
181.1313 +    Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab);
181.1314 +    if (Error > bp -> MaxError)
181.1315 +        bp->MaxError = Error;
181.1316 +
181.1317 +    return TRUE;
181.1318 +}
181.1319 +
181.1320 +// This is the entry for black-plane preserving, which are non-ICC
181.1321 +static
181.1322 +cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
181.1323 +                                          cmsUInt32Number nProfiles,
181.1324 +                                          cmsUInt32Number TheIntents[],
181.1325 +                                          cmsHPROFILE     hProfiles[],
181.1326 +                                          cmsBool         BPC[],
181.1327 +                                          cmsFloat64Number AdaptationStates[],
181.1328 +                                          cmsUInt32Number dwFlags)
181.1329 +{
181.1330 +    PreserveKPlaneParams bp;
181.1331 +    cmsPipeline*    Result = NULL;
181.1332 +    cmsUInt32Number ICCIntents[256];
181.1333 +    cmsStage*         CLUT;
181.1334 +    cmsUInt32Number i, nGridPoints;
181.1335 +    cmsHPROFILE hLab;
181.1336 +
181.1337 +    // Sanity check
181.1338 +    if (nProfiles < 1 || nProfiles > 255) return NULL;
181.1339 +
181.1340 +    // Translate black-preserving intents to ICC ones
181.1341 +    for (i=0; i < nProfiles; i++)
181.1342 +        ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]);
181.1343 +
181.1344 +    // Check for non-cmyk profiles
181.1345 +    if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
181.1346 +        cmsGetColorSpace(hProfiles[nProfiles-1]) != cmsSigCmykData)
181.1347 +           return  DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags);
181.1348 +
181.1349 +    // Allocate an empty LUT for holding the result
181.1350 +    Result = cmsPipelineAlloc(ContextID, 4, 4);
181.1351 +    if (Result == NULL) return NULL;
181.1352 +
181.1353 +
181.1354 +    memset(&bp, 0, sizeof(bp));
181.1355 +
181.1356 +    // We need the input LUT of the last profile, assuming this one is responsible of
181.1357 +    // black generation. This LUT will be seached in inverse order.
181.1358 +    bp.LabK2cmyk = _cmsReadInputLUT(hProfiles[nProfiles-1], INTENT_RELATIVE_COLORIMETRIC);
181.1359 +    if (bp.LabK2cmyk == NULL) goto Cleanup;
181.1360 +
181.1361 +    // Get total area coverage (in 0..1 domain)
181.1362 +    bp.MaxTAC = cmsDetectTAC(hProfiles[nProfiles-1]) / 100.0;
181.1363 +
181.1364 +    // Create a LUT holding normal ICC transform
181.1365 +    bp.cmyk2cmyk = DefaultICCintents(ContextID,
181.1366 +                                         nProfiles,
181.1367 +                                         ICCIntents,
181.1368 +                                         hProfiles,
181.1369 +                                         BPC,
181.1370 +                                         AdaptationStates,
181.1371 +                                         dwFlags);
181.1372 +
181.1373 +    // Now the tone curve
181.1374 +    bp.KTone = _cmsBuildKToneCurve(ContextID, 4096, nProfiles,
181.1375 +                                   ICCIntents,
181.1376 +                                   hProfiles,
181.1377 +                                   BPC,
181.1378 +                                   AdaptationStates,
181.1379 +                                   dwFlags);
181.1380 +
181.1381 +
181.1382 +    // To measure the output, Last profile to Lab
181.1383 +    hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
181.1384 +    bp.hProofOutput = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
181.1385 +                                         CHANNELS_SH(4)|BYTES_SH(2), hLab, TYPE_Lab_DBL,
181.1386 +                                         INTENT_RELATIVE_COLORIMETRIC,
181.1387 +                                         cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
181.1388 +
181.1389 +    // Same as anterior, but lab in the 0..1 range
181.1390 +    bp.cmyk2Lab = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
181.1391 +                                         FLOAT_SH(1)|CHANNELS_SH(4)|BYTES_SH(4), hLab,
181.1392 +                                         FLOAT_SH(1)|CHANNELS_SH(3)|BYTES_SH(4),
181.1393 +                                         INTENT_RELATIVE_COLORIMETRIC,
181.1394 +                                         cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
181.1395 +    cmsCloseProfile(hLab);
181.1396 +
181.1397 +    // Error estimation (for debug only)
181.1398 +    bp.MaxError = 0;
181.1399 +
181.1400 +    // How many gridpoints are we going to use?
181.1401 +    nGridPoints = _cmsReasonableGridpointsByColorspace(cmsSigCmykData, dwFlags);
181.1402 +
181.1403 +
181.1404 +    CLUT = cmsStageAllocCLut16bit(ContextID, nGridPoints, 4, 4, NULL);
181.1405 +    if (CLUT == NULL) goto Cleanup;
181.1406 +
181.1407 +    cmsPipelineInsertStage(Result, cmsAT_BEGIN, CLUT);
181.1408 +
181.1409 +    cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0);
181.1410 +
181.1411 +Cleanup:
181.1412 +
181.1413 +    if (bp.cmyk2cmyk) cmsPipelineFree(bp.cmyk2cmyk);
181.1414 +    if (bp.cmyk2Lab) cmsDeleteTransform(bp.cmyk2Lab);
181.1415 +    if (bp.hProofOutput) cmsDeleteTransform(bp.hProofOutput);
181.1416 +
181.1417 +    if (bp.KTone) cmsFreeToneCurve(bp.KTone);
181.1418 +    if (bp.LabK2cmyk) cmsPipelineFree(bp.LabK2cmyk);
181.1419 +
181.1420 +    return Result;
181.1421 +}
181.1422 +
181.1423 +// Link routines ------------------------------------------------------------------------------------------------------
181.1424 +
181.1425 +// Chain several profiles into a single LUT. It just checks the parameters and then calls the handler
181.1426 +// for the first intent in chain. The handler may be user-defined. Is up to the handler to deal with the
181.1427 +// rest of intents in chain. A maximum of 255 profiles at time are supported, which is pretty reasonable.
181.1428 +cmsPipeline* _cmsLinkProfiles(cmsContext     ContextID,
181.1429 +                              cmsUInt32Number nProfiles,
181.1430 +                              cmsUInt32Number TheIntents[],
181.1431 +                              cmsHPROFILE     hProfiles[],
181.1432 +                              cmsBool         BPC[],
181.1433 +                              cmsFloat64Number AdaptationStates[],
181.1434 +                              cmsUInt32Number dwFlags)
181.1435 +{
181.1436 +    cmsUInt32Number i;
181.1437 +    cmsIntentsList* Intent;
181.1438 +
181.1439 +    // Make sure a reasonable number of profiles is provided
181.1440 +    if (nProfiles <= 0 || nProfiles > 255) {
181.1441 +         cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't link '%d' profiles", nProfiles);
181.1442 +        return NULL;
181.1443 +    }
181.1444 +
181.1445 +    for (i=0; i < nProfiles; i++) {
181.1446 +
181.1447 +        // Check if black point is really needed or allowed. Note that
181.1448 +        // following Adobe's document:
181.1449 +        // BPC does not apply to devicelink profiles, nor to abs colorimetric,
181.1450 +        // and applies always on V4 perceptual and saturation.
181.1451 +
181.1452 +        if (TheIntents[i] == INTENT_ABSOLUTE_COLORIMETRIC)
181.1453 +            BPC[i] = FALSE;
181.1454 +
181.1455 +        if (TheIntents[i] == INTENT_PERCEPTUAL || TheIntents[i] == INTENT_SATURATION) {
181.1456 +
181.1457 +            // Force BPC for V4 profiles in perceptual and saturation
181.1458 +            if (cmsGetProfileVersion(hProfiles[i]) >= 4.0)
181.1459 +                BPC[i] = TRUE;
181.1460 +        }
181.1461 +    }
181.1462 +
181.1463 +    // Search for a handler. The first intent in the chain defines the handler. That would
181.1464 +    // prevent using multiple custom intents in a multiintent chain, but the behaviour of
181.1465 +    // this case would present some issues if the custom intent tries to do things like
181.1466 +    // preserve primaries. This solution is not perfect, but works well on most cases.
181.1467 +
181.1468 +    Intent = SearchIntent(TheIntents[0]);
181.1469 +    if (Intent == NULL) {
181.1470 +        cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported intent '%d'", TheIntents[0]);
181.1471 +        return NULL;
181.1472 +    }
181.1473 +
181.1474 +    // Call the handler
181.1475 +    return Intent ->Link(ContextID, nProfiles, TheIntents, hProfiles, BPC, AdaptationStates, dwFlags);
181.1476 +}
181.1477 +
181.1478 +// -------------------------------------------------------------------------------------------------
181.1479 +
181.1480 +// Get information about available intents. nMax is the maximum space for the supplied "Codes"
181.1481 +// and "Descriptions" the function returns the total number of intents, which may be greater
181.1482 +// than nMax, although the matrices are not populated beyond this level.
181.1483 +cmsUInt32Number CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions)
181.1484 +{
181.1485 +    cmsIntentsList* pt;
181.1486 +    cmsUInt32Number nIntents;
181.1487 +
181.1488 +    for (nIntents=0, pt = Intents; pt != NULL; pt = pt -> Next)
181.1489 +    {
181.1490 +        if (nIntents < nMax) {
181.1491 +            if (Codes != NULL)
181.1492 +                Codes[nIntents] = pt ->Intent;
181.1493 +
181.1494 +            if (Descriptions != NULL)
181.1495 +                Descriptions[nIntents] = pt ->Description;
181.1496 +        }
181.1497 +
181.1498 +        nIntents++;
181.1499 +    }
181.1500 +
181.1501 +    return nIntents;
181.1502 +}
181.1503 +
181.1504 +// The plug-in registration. User can add new intents or override default routines
181.1505 +cmsBool  _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Data)
181.1506 +{
181.1507 +    cmsPluginRenderingIntent* Plugin = (cmsPluginRenderingIntent*) Data;
181.1508 +    cmsIntentsList* fl;
181.1509 +
181.1510 +    // Do we have to reset the intents?
181.1511 +    if (Data == NULL) {
181.1512 +
181.1513 +       Intents = DefaultIntents;
181.1514 +       return TRUE;
181.1515 +    }
181.1516 +
181.1517 +    fl = SearchIntent(Plugin ->Intent);
181.1518 +
181.1519 +    if (fl == NULL) {
181.1520 +        fl = (cmsIntentsList*) _cmsPluginMalloc(sizeof(cmsIntentsList));
181.1521 +        if (fl == NULL) return FALSE;
181.1522 +    }
181.1523 +
181.1524 +    fl ->Intent  = Plugin ->Intent;
181.1525 +    strncpy(fl ->Description, Plugin ->Description, 255);
181.1526 +    fl ->Description[255] = 0;
181.1527 +
181.1528 +    fl ->Link    = Plugin ->Link;
181.1529 +
181.1530 +    fl ->Next = Intents;
181.1531 +    Intents = fl;
181.1532 +
181.1533 +    return TRUE;
181.1534 +}
181.1535 +
   182.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmserr.c	Thu Sep 23 17:33:40 2010 -0700
   182.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmserr.c	Fri Sep 24 16:41:32 2010 -0700
   182.3 @@ -27,9 +27,10 @@
   182.4  // However, the following notice accompanied the original version of this
   182.5  // file:
   182.6  //
   182.7 +//---------------------------------------------------------------------------------
   182.8  //
   182.9 -//  Little cms
  182.10 -//  Copyright (C) 1998-2007 Marti Maria
  182.11 +//  Little Color Management System
  182.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  182.13  //
  182.14  // Permission is hereby granted, free of charge, to any person obtaining
  182.15  // a copy of this software and associated documentation files (the "Software"),
  182.16 @@ -48,92 +49,399 @@
  182.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  182.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  182.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  182.20 +//
  182.21 +//---------------------------------------------------------------------------------
  182.22  
  182.23 +#include "lcms2_internal.h"
  182.24  
  182.25 -#include "lcms.h"
  182.26 +// I am so tired about incompatibilities on those functions that here are some replacements
  182.27 +// that hopefully would be fully portable.
  182.28  
  182.29 +// compare two strings ignoring case
  182.30 +int CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2)
  182.31 +{
  182.32 +         register const unsigned char *us1 = (const unsigned char *)s1,
  182.33 +                                      *us2 = (const unsigned char *)s2;
  182.34  
  182.35 -// As a rule, only the functions visible from API can signal
  182.36 -// errors.
  182.37 -
  182.38 -void cdecl cmsSignalError(int ErrorCode, const char *ErrorText, ...);
  182.39 -
  182.40 -int  LCMSEXPORT cmsErrorAction(int lAbort);
  182.41 -void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn);
  182.42 -
  182.43 -
  182.44 -// ******************************************************************
  182.45 -
  182.46 -static int nDoAbort = LCMS_ERROR_ABORT;
  182.47 -static cmsErrorHandlerFunction UserErrorHandler = (cmsErrorHandlerFunction) NULL;
  182.48 -
  182.49 -
  182.50 -int LCMSEXPORT cmsErrorAction(int nAction)
  182.51 -{
  182.52 -       int nOld = nDoAbort;
  182.53 -       nDoAbort = nAction;
  182.54 -
  182.55 -       return nOld;
  182.56 +        while (toupper(*us1) == toupper(*us2++))
  182.57 +                if (*us1++ == '\0')
  182.58 +                        return (0);
  182.59 +        return (toupper(*us1) - toupper(*--us2));
  182.60  }
  182.61  
  182.62 -void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn)
  182.63 +// long int because C99 specifies ftell in such way (7.19.9.2)
  182.64 +long int CMSEXPORT cmsfilelength(FILE* f)
  182.65  {
  182.66 -       UserErrorHandler = Fn;
  182.67 +    long int n;
  182.68 +
  182.69 +    if (fseek(f, 0, SEEK_END) != 0) {
  182.70 +        return -1;
  182.71 +    }
  182.72 +    n = ftell(f);
  182.73 +    fseek(f, 0, SEEK_SET);
  182.74 +
  182.75 +    return n;
  182.76  }
  182.77  
  182.78 +// Memory handling ------------------------------------------------------------------
  182.79 +//
  182.80 +// This is the interface to low-level memory management routines. By default a simple
  182.81 +// wrapping to malloc/free/realloc is provided, although there is a limit on the max
  182.82 +// amount of memoy that can be reclaimed. This is mostly as a safety feature to
  182.83 +// prevent bogus or malintentionated code to allocate huge blocks that otherwise lcms
  182.84 +// would never need.
  182.85  
  182.86 -// Default error handler
  182.87 +#define MAX_MEMORY_FOR_ALLOC  ((cmsUInt32Number)(1024U*1024U*512U))
  182.88  
  182.89 +// User may override this behaviour by using a memory plug-in, which basically replaces
  182.90 +// the default memory management functions. In this case, no check is performed and it
  182.91 +// is up to the plug-in writter to keep in the safe side. There are only three functions
  182.92 +// required to be implemented: malloc, realloc and free, although the user may want to
  182.93 +// replace the optional mallocZero, calloc and dup as well.
  182.94  
  182.95 -void cmsSignalError(int ErrorCode, const char *ErrorText, ...)
  182.96 +cmsBool   _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
  182.97 +
  182.98 +// *********************************************************************************
  182.99 +
 182.100 +// This is the default memory allocation function. It does a very coarse
 182.101 +// check of amout of memory, just to prevent exploits
 182.102 +static
 182.103 +void* _cmsMallocDefaultFn(cmsContext ContextID, cmsUInt32Number size)
 182.104  {
 182.105 -       va_list args;
 182.106 +    if (size > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never allow over maximum
 182.107  
 182.108 -       if (nDoAbort == LCMS_ERROR_IGNORE) return;
 182.109 +    return (void*) malloc(size);
 182.110  
 182.111 -        va_start(args, ErrorText);
 182.112 +    cmsUNUSED_PARAMETER(ContextID);
 182.113 +}
 182.114  
 182.115 -        if (UserErrorHandler != NULL) {
 182.116 +// Generic allocate & zero
 182.117 +static
 182.118 +void* _cmsMallocZeroDefaultFn(cmsContext ContextID, cmsUInt32Number size)
 182.119 +{
 182.120 +    void *pt = _cmsMalloc(ContextID, size);
 182.121 +    if (pt == NULL) return NULL;
 182.122  
 182.123 -            char Buffer[1024];
 182.124 +    memset(pt, 0, size);
 182.125 +    return pt;
 182.126 +}
 182.127  
 182.128 -            vsnprintf(Buffer, 1023, ErrorText, args);
 182.129 -            va_end(args);
 182.130  
 182.131 -            if (UserErrorHandler(ErrorCode, Buffer)) {
 182.132 +// The default free function. The only check proformed is against NULL pointers
 182.133 +static
 182.134 +void _cmsFreeDefaultFn(cmsContext ContextID, void *Ptr)
 182.135 +{
 182.136 +    // free(NULL) is defined a no-op by C99, therefore it is safe to
 182.137 +    // avoid the check, but it is here just in case...
 182.138  
 182.139 -                return;
 182.140 -                }
 182.141 -         }
 182.142 +    if (Ptr) free(Ptr);
 182.143  
 182.144 -#if defined( __CONSOLE__ ) || defined( NON_WINDOWS )
 182.145 +    cmsUNUSED_PARAMETER(ContextID);
 182.146 +}
 182.147  
 182.148 -              fprintf(stderr, "lcms: Error #%d; ", ErrorCode);
 182.149 -              vfprintf(stderr, ErrorText, args);
 182.150 -              fprintf(stderr, "\n");
 182.151 -              va_end(args);
 182.152 +// The default realloc function. Again it check for exploits. If Ptr is NULL,
 182.153 +// realloc behaves the same way as malloc and allocates a new block of size bytes.
 182.154 +static
 182.155 +void* _cmsReallocDefaultFn(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
 182.156 +{
 182.157  
 182.158 -              if (nDoAbort == LCMS_ERROR_ABORT) exit(1);
 182.159 -#else
 182.160 -              {
 182.161 -              char Buffer1[1024];
 182.162 -              char Buffer2[256];
 182.163 +    if (size > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never realloc over 512Mb
 182.164  
 182.165 -              snprintf(Buffer1,  767, "Error #%x; ", ErrorCode);
 182.166 -              vsnprintf(Buffer2, 255, ErrorText, args);
 182.167 -              strcat(Buffer1, Buffer2);
 182.168 -              MessageBox(NULL, Buffer1, "Little cms",
 182.169 -                                          MB_OK|MB_ICONSTOP|MB_TASKMODAL);
 182.170 -              va_end(args);
 182.171 +    return realloc(Ptr, size);
 182.172  
 182.173 -              if (nDoAbort == LCMS_ERROR_ABORT) {
 182.174 +    cmsUNUSED_PARAMETER(ContextID);
 182.175 +}
 182.176  
 182.177 -#ifdef __BORLANDC__
 182.178 -                    _cexit();
 182.179 -#endif
 182.180  
 182.181 -                  FatalAppExit(0, "lcms is terminating application");
 182.182 -              }
 182.183 -              }
 182.184 -#endif
 182.185 +// The default calloc function. Allocates an array of num elements, each one of size bytes
 182.186 +// all memory is initialized to zero.
 182.187 +static
 182.188 +void* _cmsCallocDefaultFn(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
 182.189 +{
 182.190 +    cmsUInt32Number Total = num * size;
 182.191 +
 182.192 +    // Check for overflow
 182.193 +    if (Total < num || Total < size) {
 182.194 +        return NULL;
 182.195 +    }
 182.196 +
 182.197 +    if (Total > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never alloc over 512Mb
 182.198 +
 182.199 +    return _cmsMallocZero(ContextID, Total);
 182.200  }
 182.201 +
 182.202 +// Generic block duplication
 182.203 +static
 182.204 +void* _cmsDupDefaultFn(cmsContext ContextID, const void* Org, cmsUInt32Number size)
 182.205 +{
 182.206 +    void* mem;
 182.207 +
 182.208 +    if (size > MAX_MEMORY_FOR_ALLOC) return NULL;  // Never dup over 512Mb
 182.209 +
 182.210 +    mem = _cmsMalloc(ContextID, size);
 182.211 +
 182.212 +    if (mem != NULL && Org != NULL)
 182.213 +        memmove(mem, Org, size);
 182.214 +
 182.215 +    return mem;
 182.216 +}
 182.217 +
 182.218 +// Pointers to malloc and _cmsFree functions in current environment
 182.219 +static void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size)                     = _cmsMallocDefaultFn;
 182.220 +static void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size)                 = _cmsMallocZeroDefaultFn;
 182.221 +static void   (* FreePtr)(cmsContext ContextID, void *Ptr)                                  = _cmsFreeDefaultFn;
 182.222 +static void * (* ReallocPtr)(cmsContext ContextID, void *Ptr, cmsUInt32Number NewSize)      = _cmsReallocDefaultFn;
 182.223 +static void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)= _cmsCallocDefaultFn;
 182.224 +static void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size)       = _cmsDupDefaultFn;
 182.225 +
 182.226 +// Plug-in replacement entry
 182.227 +cmsBool  _cmsRegisterMemHandlerPlugin(cmsPluginBase *Data)
 182.228 +{
 182.229 +    cmsPluginMemHandler* Plugin = (cmsPluginMemHandler*) Data;
 182.230 +
 182.231 +    // NULL forces to reset to defaults
 182.232 +    if (Data == NULL) {
 182.233 +
 182.234 +        MallocPtr    = _cmsMallocDefaultFn;
 182.235 +        MallocZeroPtr= _cmsMallocZeroDefaultFn;
 182.236 +        FreePtr      = _cmsFreeDefaultFn;
 182.237 +        ReallocPtr   = _cmsReallocDefaultFn;
 182.238 +        CallocPtr    = _cmsCallocDefaultFn;
 182.239 +        DupPtr       = _cmsDupDefaultFn;
 182.240 +        return TRUE;
 182.241 +    }
 182.242 +
 182.243 +    // Check for required callbacks
 182.244 +    if (Plugin -> MallocPtr == NULL ||
 182.245 +        Plugin -> FreePtr == NULL ||
 182.246 +        Plugin -> ReallocPtr == NULL) return FALSE;
 182.247 +
 182.248 +    // Set replacement functions
 182.249 +    MallocPtr  = Plugin -> MallocPtr;
 182.250 +    FreePtr    = Plugin -> FreePtr;
 182.251 +    ReallocPtr = Plugin -> ReallocPtr;
 182.252 +
 182.253 +    if (Plugin ->MallocZeroPtr != NULL) MallocZeroPtr = Plugin ->MallocZeroPtr;
 182.254 +    if (Plugin ->CallocPtr != NULL)     CallocPtr     = Plugin -> CallocPtr;
 182.255 +    if (Plugin ->DupPtr != NULL)        DupPtr        = Plugin -> DupPtr;
 182.256 +
 182.257 +    return TRUE;
 182.258 +}
 182.259 +
 182.260 +// Generic allocate
 182.261 +void* CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size)
 182.262 +{
 182.263 +    return MallocPtr(ContextID, size);
 182.264 +}
 182.265 +
 182.266 +// Generic allocate & zero
 182.267 +void* CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size)
 182.268 +{
 182.269 +    return MallocZeroPtr(ContextID, size);
 182.270 +}
 182.271 +
 182.272 +// Generic calloc
 182.273 +void* CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size)
 182.274 +{
 182.275 +    return CallocPtr(ContextID, num, size);
 182.276 +}
 182.277 +
 182.278 +// Generic reallocate
 182.279 +void* CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number size)
 182.280 +{
 182.281 +    return ReallocPtr(ContextID, Ptr, size);
 182.282 +}
 182.283 +
 182.284 +// Generic free memory
 182.285 +void CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr)
 182.286 +{
 182.287 +    if (Ptr != NULL) FreePtr(ContextID, Ptr);
 182.288 +}
 182.289 +
 182.290 +// Generic block duplication
 182.291 +void* CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size)
 182.292 +{
 182.293 +    return DupPtr(ContextID, Org, size);
 182.294 +}
 182.295 +
 182.296 +// ********************************************************************************************
 182.297 +
 182.298 +// Sub allocation takes care of many pointers of small size. The memory allocated in
 182.299 +// this way have be freed at once. Next function allocates a single chunk for linked list
 182.300 +// I prefer this method over realloc due to the big inpact on xput realloc may have if
 182.301 +// memory is being swapped to disk. This approach is safer (although thats not true on any platform)
 182.302 +static
 182.303 +_cmsSubAllocator_chunk* _cmsCreateSubAllocChunk(cmsContext ContextID, cmsUInt32Number Initial)
 182.304 +{
 182.305 +    _cmsSubAllocator_chunk* chunk;
 182.306 +
 182.307 +    // Create the container
 182.308 +    chunk = (_cmsSubAllocator_chunk*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator_chunk));
 182.309 +    if (chunk == NULL) return NULL;
 182.310 +
 182.311 +    // Initialize values
 182.312 +    chunk ->Block     = (cmsUInt8Number*) _cmsMalloc(ContextID, Initial);
 182.313 +    if (chunk ->Block == NULL) {
 182.314 +
 182.315 +        // Something went wrong
 182.316 +        _cmsFree(ContextID, chunk);
 182.317 +        return NULL;
 182.318 +    }
 182.319 +
 182.320 +    // 20K by default
 182.321 +    if (Initial == 0)
 182.322 +        Initial = 20*1024;
 182.323 +
 182.324 +    chunk ->BlockSize = Initial;
 182.325 +    chunk ->Used      = 0;
 182.326 +    chunk ->next      = NULL;
 182.327 +
 182.328 +    return chunk;
 182.329 +}
 182.330 +
 182.331 +// The suballocated is nothing but a pointer to the first element in the list. We also keep
 182.332 +// the thread ID in this structure.
 182.333 +_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial)
 182.334 +{
 182.335 +    _cmsSubAllocator* sub;
 182.336 +
 182.337 +    // Create the container
 182.338 +    sub = (_cmsSubAllocator*) _cmsMallocZero(ContextID, sizeof(_cmsSubAllocator));
 182.339 +    if (sub == NULL) return NULL;
 182.340 +
 182.341 +    sub ->ContextID = ContextID;
 182.342 +
 182.343 +    sub ->h = _cmsCreateSubAllocChunk(ContextID, Initial);
 182.344 +    if (sub ->h == NULL) {
 182.345 +        _cmsFree(ContextID, sub);
 182.346 +        return NULL;
 182.347 +    }
 182.348 +
 182.349 +    return sub;
 182.350 +}
 182.351 +
 182.352 +
 182.353 +// Get rid of whole linked list
 182.354 +void _cmsSubAllocDestroy(_cmsSubAllocator* sub)
 182.355 +{
 182.356 +    _cmsSubAllocator_chunk *chunk, *n;
 182.357 +
 182.358 +    for (chunk = sub ->h; chunk != NULL; chunk = n) {
 182.359 +
 182.360 +        n = chunk->next;
 182.361 +        if (chunk->Block != NULL) _cmsFree(sub ->ContextID, chunk->Block);
 182.362 +        _cmsFree(sub ->ContextID, chunk);
 182.363 +    }
 182.364 +
 182.365 +    // Free the header
 182.366 +    _cmsFree(sub ->ContextID, sub);
 182.367 +}
 182.368 +
 182.369 +
 182.370 +// Get a pointer to small memory block.
 182.371 +void*  _cmsSubAlloc(_cmsSubAllocator* sub, cmsUInt32Number size)
 182.372 +{
 182.373 +    cmsUInt32Number Free = sub -> h ->BlockSize - sub -> h -> Used;
 182.374 +    cmsUInt8Number* ptr;
 182.375 +
 182.376 +    size = _cmsALIGNLONG(size);
 182.377 +
 182.378 +    // Check for memory. If there is no room, allocate a new chunk of double memory size.
 182.379 +    if (size > Free) {
 182.380 +
 182.381 +        _cmsSubAllocator_chunk* chunk;
 182.382 +        cmsUInt32Number newSize;
 182.383 +
 182.384 +        newSize = sub -> h ->BlockSize * 2;
 182.385 +        if (newSize < size) newSize = size;
 182.386 +
 182.387 +        chunk = _cmsCreateSubAllocChunk(sub -> ContextID, newSize);
 182.388 +        if (chunk == NULL) return NULL;
 182.389 +
 182.390 +        // Link list
 182.391 +        chunk ->next = sub ->h;
 182.392 +        sub ->h    = chunk;
 182.393 +
 182.394 +    }
 182.395 +
 182.396 +    ptr =  sub -> h ->Block + sub -> h ->Used;
 182.397 +    sub -> h -> Used += size;
 182.398 +
 182.399 +    return (void*) ptr;
 182.400 +}
 182.401 +
 182.402 +// Error logging ******************************************************************
 182.403 +
 182.404 +// There is no error handling at all. When a funtion fails, it returns proper value.
 182.405 +// For example, all create functions does return NULL on failure. Other return FALSE
 182.406 +// It may be interesting, for the developer, to know why the function is failing.
 182.407 +// for that reason, lcms2 does offer a logging function. This function does recive
 182.408 +// a ENGLISH string with some clues on what is going wrong. You can show this
 182.409 +// info to the end user, or just create some sort of log.
 182.410 +// The logging function should NOT terminate the program, as this obviously can leave
 182.411 +// resources. It is the programmer's responsability to check each function return code
 182.412 +// to make sure it didn't fail.
 182.413 +
 182.414 +// Error messages are limited to MAX_ERROR_MESSAGE_LEN
 182.415 +
 182.416 +#define MAX_ERROR_MESSAGE_LEN   1024
 182.417 +
 182.418 +// ---------------------------------------------------------------------------------------------------------
 182.419 +
 182.420 +// This is our default log error
 182.421 +static void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text);
 182.422 +
 182.423 +// The current handler in actual environment
 182.424 +static cmsLogErrorHandlerFunction LogErrorHandler   = DefaultLogErrorHandlerFunction;
 182.425 +
 182.426 +// The default error logger does nothing.
 182.427 +static
 182.428 +void DefaultLogErrorHandlerFunction(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text)
 182.429 +{
 182.430 +    // fprintf(stderr, "[lcms]: %s\n", Text);
 182.431 +    // fflush(stderr);
 182.432 +
 182.433 +     cmsUNUSED_PARAMETER(ContextID);
 182.434 +     cmsUNUSED_PARAMETER(ErrorCode);
 182.435 +     cmsUNUSED_PARAMETER(Text);
 182.436 +}
 182.437 +
 182.438 +// Change log error
 182.439 +void CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn)
 182.440 +{
 182.441 +    if (Fn == NULL)
 182.442 +        LogErrorHandler = DefaultLogErrorHandlerFunction;
 182.443 +    else
 182.444 +        LogErrorHandler = Fn;
 182.445 +}
 182.446 +
 182.447 +// Log an error
 182.448 +// ErrorText is a text holding an english description of error.
 182.449 +void CMSEXPORT cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...)
 182.450 +{
 182.451 +    va_list args;
 182.452 +    char Buffer[MAX_ERROR_MESSAGE_LEN];
 182.453 +
 182.454 +    va_start(args, ErrorText);
 182.455 +    vsnprintf(Buffer, MAX_ERROR_MESSAGE_LEN-1, ErrorText, args);
 182.456 +    va_end(args);
 182.457 +
 182.458 +    // Call handler
 182.459 +    LogErrorHandler(ContextID, ErrorCode, Buffer);
 182.460 +}
 182.461 +
 182.462 +// Utility function to print signatures
 182.463 +void _cmsTagSignature2String(char String[5], cmsTagSignature sig)
 182.464 +{
 182.465 +    cmsUInt32Number be;
 182.466 +
 182.467 +    // Convert to big endian
 182.468 +    be = _cmsAdjustEndianess32((cmsUInt32Number) sig);
 182.469 +
 182.470 +    // Move chars
 182.471 +    memmove(String, &be, 4);
 182.472 +
 182.473 +    // Make sure of terminator
 182.474 +    String[4] = 0;
 182.475 +}
 182.476 +
   183.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c	Thu Sep 23 17:33:40 2010 -0700
   183.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsgamma.c	Fri Sep 24 16:41:32 2010 -0700
   183.3 @@ -27,9 +27,10 @@
   183.4  // However, the following notice accompanied the original version of this
   183.5  // file:
   183.6  //
   183.7 +//---------------------------------------------------------------------------------
   183.8  //
   183.9 -//  Little cms
  183.10 -//  Copyright (C) 1998-2007 Marti Maria
  183.11 +//  Little Color Management System
  183.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  183.13  //
  183.14  // Permission is hereby granted, free of charge, to any person obtaining
  183.15  // a copy of this software and associated documentation files (the "Software"),
  183.16 @@ -48,447 +49,850 @@
  183.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  183.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  183.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  183.20 +//
  183.21 +//---------------------------------------------------------------------------------
  183.22 +//
  183.23 +#include "lcms2_internal.h"
  183.24  
  183.25 +// Tone curves are powerful constructs that can contain curves specified in diverse ways.
  183.26 +// The curve is stored in segments, where each segment can be sampled or specified by parameters.
  183.27 +// a 16.bit simplification of the *whole* curve is kept for optimization purposes. For float operation,
  183.28 +// each segment is evaluated separately. Plug-ins may be used to define new parametric schemes,
  183.29 +// each plug-in may define up to MAX_TYPES_IN_LCMS_PLUGIN functions types. For defining a function,
  183.30 +// the plug-in should provide the type id, how many parameters each type has, and a pointer to
  183.31 +// a procedure that evaluates the function. In the case of reverse evaluation, the evaluator will
  183.32 +// be called with the type id as a negative value, and a sampled version of the reversed curve
  183.33 +// will be built.
  183.34  
  183.35 -#include "lcms.h"
  183.36 +// ----------------------------------------------------------------- Implementation
  183.37 +// Maxim number of nodes
  183.38 +#define MAX_NODES_IN_CURVE   4097
  183.39 +#define MINUS_INF            (-1E22F)
  183.40 +#define PLUS_INF             (+1E22F)
  183.41  
  183.42 -// Gamma handling.
  183.43 +// The list of supported parametric curves
  183.44 +typedef struct _cmsParametricCurvesCollection_st {
  183.45  
  183.46 -LPGAMMATABLE LCMSEXPORT cmsAllocGamma(int nEntries);
  183.47 -void         LCMSEXPORT cmsFreeGamma(LPGAMMATABLE Gamma);
  183.48 -void         LCMSEXPORT cmsFreeGammaTriple(LPGAMMATABLE Gamma[3]);
  183.49 -LPGAMMATABLE LCMSEXPORT cmsBuildGamma(int nEntries, double Gamma);
  183.50 -LPGAMMATABLE LCMSEXPORT cmsDupGamma(LPGAMMATABLE Src);
  183.51 -LPGAMMATABLE LCMSEXPORT cmsReverseGamma(int nResultSamples, LPGAMMATABLE InGamma);
  183.52 -LPGAMMATABLE LCMSEXPORT cmsBuildParametricGamma(int nEntries, int Type, double Params[]);
  183.53 -LPGAMMATABLE LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma);
  183.54 -LPGAMMATABLE LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma, LPGAMMATABLE OutGamma, int nPoints);
  183.55 -LCMSBOOL         LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
  183.56 +    int nFunctions;                                     // Number of supported functions in this chunk
  183.57 +    int FunctionTypes[MAX_TYPES_IN_LCMS_PLUGIN];        // The identification types
  183.58 +    int ParameterCount[MAX_TYPES_IN_LCMS_PLUGIN];       // Number of parameters for each function
  183.59 +    cmsParametricCurveEvaluator    Evaluator;           // The evaluator
  183.60  
  183.61 -LCMSBOOL         cdecl _cmsSmoothEndpoints(LPWORD Table, int nPoints);
  183.62 +    struct _cmsParametricCurvesCollection_st* Next; // Next in list
  183.63  
  183.64 +} _cmsParametricCurvesCollection;
  183.65  
  183.66 -// Sampled curves
  183.67  
  183.68 -LPSAMPLEDCURVE cdecl cmsAllocSampledCurve(int nItems);
  183.69 -void           cdecl cmsFreeSampledCurve(LPSAMPLEDCURVE p);
  183.70 -void           cdecl cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max);
  183.71 -void           cdecl cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max);
  183.72 -LCMSBOOL       cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
  183.73 -void           cdecl cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints);
  183.74 +// This is the default (built-in) evaluator
  183.75 +static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R);
  183.76  
  183.77 -LPSAMPLEDCURVE cdecl cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints);
  183.78 +// The built-in list
  183.79 +static _cmsParametricCurvesCollection DefaultCurves = {
  183.80 +    9,                                  // # of curve types
  183.81 +    { 1, 2, 3, 4, 5, 6, 7, 8, 108 },    // Parametric curve ID
  183.82 +    { 1, 3, 4, 5, 7, 4, 5, 5, 1 },      // Parameters by type
  183.83 +    DefaultEvalParametricFn,            // Evaluator
  183.84 +    NULL                                // Next in chain
  183.85 +};
  183.86  
  183.87 -double LCMSEXPORT cmsEstimateGamma(LPGAMMATABLE t);
  183.88 -double LCMSEXPORT cmsEstimateGammaEx(LPWORD GammaTable, int nEntries, double Thereshold);
  183.89 +// The linked list head
  183.90 +static _cmsParametricCurvesCollection* ParametricCurves = &DefaultCurves;
  183.91  
  183.92 -// ----------------------------------------------------------------------------------------
  183.93 +// As a way to install new parametric curves
  183.94 +cmsBool _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Data)
  183.95 +{
  183.96 +    cmsPluginParametricCurves* Plugin = (cmsPluginParametricCurves*) Data;
  183.97 +    _cmsParametricCurvesCollection* fl;
  183.98  
  183.99 +    if (Data == NULL) {
 183.100  
 183.101 -#define MAX_KNOTS   4096
 183.102 -typedef float vec[MAX_KNOTS+1];
 183.103 +          ParametricCurves =  &DefaultCurves;
 183.104 +          return TRUE;
 183.105 +    }
 183.106  
 183.107 +    fl = (_cmsParametricCurvesCollection*) _cmsPluginMalloc(sizeof(_cmsParametricCurvesCollection));
 183.108 +    if (fl == NULL) return FALSE;
 183.109  
 183.110 -// Ciclic-redundant-check for assuring table is a true representation of parametric curve
 183.111 +    // Copy the parameters
 183.112 +    fl ->Evaluator  = Plugin ->Evaluator;
 183.113 +    fl ->nFunctions = Plugin ->nFunctions;
 183.114  
 183.115 -// The usual polynomial, which is used for AAL5, FDDI, and probably Ethernet
 183.116 -#define QUOTIENT 0x04c11db7
 183.117 +    // Make sure no mem overwrites
 183.118 +    if (fl ->nFunctions > MAX_TYPES_IN_LCMS_PLUGIN)
 183.119 +        fl ->nFunctions = MAX_TYPES_IN_LCMS_PLUGIN;
 183.120  
 183.121 +    // Copy the data
 183.122 +    memmove(fl->FunctionTypes,  Plugin ->FunctionTypes,   fl->nFunctions * sizeof(cmsUInt32Number));
 183.123 +    memmove(fl->ParameterCount, Plugin ->ParameterCount,  fl->nFunctions * sizeof(cmsUInt32Number));
 183.124 +
 183.125 +    // Keep linked list
 183.126 +    fl ->Next = ParametricCurves;
 183.127 +    ParametricCurves = fl;
 183.128 +
 183.129 +    // All is ok
 183.130 +    return TRUE;
 183.131 +}
 183.132 +
 183.133 +
 183.134 +// Search in type list, return position or -1 if not found
 183.135  static
 183.136 -unsigned int Crc32(unsigned int result, LPVOID ptr, int len)
 183.137 +int IsInSet(int Type, _cmsParametricCurvesCollection* c)
 183.138  {
 183.139 -    int          i,j;
 183.140 -    BYTE         octet;
 183.141 -    LPBYTE       data = (LPBYTE) ptr;
 183.142 +    int i;
 183.143  
 183.144 -    for (i=0; i < len; i++) {
 183.145 +    for (i=0; i < c ->nFunctions; i++)
 183.146 +        if (abs(Type) == c ->FunctionTypes[i]) return i;
 183.147  
 183.148 -        octet = *data++;
 183.149 +    return -1;
 183.150 +}
 183.151  
 183.152 -        for (j=0; j < 8; j++) {
 183.153  
 183.154 -            if (result & 0x80000000) {
 183.155 +// Search for the collection which contains a specific type
 183.156 +static
 183.157 +_cmsParametricCurvesCollection *GetParametricCurveByType(int Type, int* index)
 183.158 +{
 183.159 +    _cmsParametricCurvesCollection* c;
 183.160 +    int Position;
 183.161  
 183.162 -                result = (result << 1) ^ QUOTIENT ^ (octet >> 7);
 183.163 -            }
 183.164 -            else
 183.165 -            {
 183.166 -                result = (result << 1) ^ (octet >> 7);
 183.167 -            }
 183.168 -            octet <<= 1;
 183.169 +    for (c = ParametricCurves; c != NULL; c = c ->Next) {
 183.170 +
 183.171 +        Position = IsInSet(Type, c);
 183.172 +
 183.173 +        if (Position != -1) {
 183.174 +            if (index != NULL)
 183.175 +                *index = Position;
 183.176 +            return c;
 183.177          }
 183.178      }
 183.179  
 183.180 -    return result;
 183.181 +    return NULL;
 183.182  }
 183.183  
 183.184 -// Get CRC of gamma table
 183.185 +// Low level allocate, which takes care of memory details. nEntries may be zero, and in this case
 183.186 +// no optimation curve is computed. nSegments may also be zero in the inverse case, where only the
 183.187 +// optimization curve is given. Both features simultaneously is an error
 183.188 +static
 183.189 +cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsInt32Number nEntries,
 183.190 +                                      cmsInt32Number nSegments, const cmsCurveSegment* Segments,
 183.191 +                                      const cmsUInt16Number* Values)
 183.192 +{
 183.193 +    cmsToneCurve* p;
 183.194 +    int i;
 183.195  
 183.196 -unsigned int _cmsCrc32OfGammaTable(LPGAMMATABLE Table)
 183.197 -{
 183.198 -    unsigned int crc = ~0U;
 183.199 +    // We allow huge tables, which are then restricted for smoothing operations
 183.200 +    if (nEntries > 65530 || nEntries < 0) {
 183.201 +        cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't create tone curve of more than 65530 entries");
 183.202 +        return NULL;
 183.203 +    }
 183.204  
 183.205 -    crc = Crc32(crc, &Table -> Seed.Type,  sizeof(int));
 183.206 -    crc = Crc32(crc, Table ->Seed.Params,  sizeof(double)*10);
 183.207 -    crc = Crc32(crc, &Table ->nEntries,    sizeof(int));
 183.208 -    crc = Crc32(crc, Table ->GammaTable,   sizeof(WORD) * Table -> nEntries);
 183.209 +    if (nEntries <= 0 && nSegments <= 0) {
 183.210 +        cmsSignalError(ContextID, cmsERROR_RANGE, "Couldn't create tone curve with zero segments and no table");
 183.211 +        return NULL;
 183.212 +    }
 183.213  
 183.214 -    return ~crc;
 183.215 +    // Allocate all required pointers, etc.
 183.216 +    p = (cmsToneCurve*) _cmsMallocZero(ContextID, sizeof(cmsToneCurve));
 183.217 +    if (!p) return NULL;
 183.218  
 183.219 +    // In this case, there are no segments
 183.220 +    if (nSegments <= 0) {
 183.221 +        p ->Segments = NULL;
 183.222 +        p ->Evals = NULL;
 183.223 +    }
 183.224 +    else {
 183.225 +        p ->Segments = (cmsCurveSegment*) _cmsCalloc(ContextID, nSegments, sizeof(cmsCurveSegment));
 183.226 +        if (p ->Segments == NULL) goto Error;
 183.227 +
 183.228 +        p ->Evals    = (cmsParametricCurveEvaluator*) _cmsCalloc(ContextID, nSegments, sizeof(cmsParametricCurveEvaluator));
 183.229 +        if (p ->Evals == NULL) goto Error;
 183.230 +    }
 183.231 +
 183.232 +    p -> nSegments = nSegments;
 183.233 +
 183.234 +    // This 16-bit table contains a limited precision representation of the whole curve and is kept for
 183.235 +    // increasing xput on certain operations.
 183.236 +    if (nEntries <= 0) {
 183.237 +        p ->Table16 = NULL;
 183.238 +    }
 183.239 +    else {
 183.240 +       p ->Table16 = (cmsUInt16Number*)  _cmsCalloc(ContextID, nEntries, sizeof(cmsUInt16Number));
 183.241 +       if (p ->Table16 == NULL) goto Error;
 183.242 +    }
 183.243 +
 183.244 +    p -> nEntries  = nEntries;
 183.245 +
 183.246 +    // Initialize members if requested
 183.247 +    if (Values != NULL && (nEntries > 0)) {
 183.248 +
 183.249 +        for (i=0; i < nEntries; i++)
 183.250 +            p ->Table16[i] = Values[i];
 183.251 +    }
 183.252 +
 183.253 +    // Initialize the segments stuff. The evaluator for each segment is located and a pointer to it
 183.254 +    // is placed in advance to maximize performance.
 183.255 +    if (Segments != NULL && (nSegments > 0)) {
 183.256 +
 183.257 +        _cmsParametricCurvesCollection *c;
 183.258 +
 183.259 +        p ->SegInterp = (cmsInterpParams**) _cmsCalloc(ContextID, nSegments, sizeof(cmsInterpParams*));
 183.260 +        if (p ->SegInterp == NULL) goto Error;
 183.261 +
 183.262 +        for (i=0; i< nSegments; i++) {
 183.263 +
 183.264 +            // Type 0 is a special marker for table-based curves
 183.265 +            if (Segments[i].Type == 0)
 183.266 +                p ->SegInterp[i] = _cmsComputeInterpParams(ContextID, Segments[i].nGridPoints, 1, 1, NULL, CMS_LERP_FLAGS_FLOAT);
 183.267 +
 183.268 +            memmove(&p ->Segments[i], &Segments[i], sizeof(cmsCurveSegment));
 183.269 +
 183.270 +            if (Segments[i].Type == 0 && Segments[i].SampledPoints != NULL)
 183.271 +                p ->Segments[i].SampledPoints = (cmsFloat32Number*) _cmsDupMem(ContextID, Segments[i].SampledPoints, sizeof(cmsFloat32Number) * Segments[i].nGridPoints);
 183.272 +            else
 183.273 +                p ->Segments[i].SampledPoints = NULL;
 183.274 +
 183.275 +
 183.276 +            c = GetParametricCurveByType(Segments[i].Type, NULL);
 183.277 +            if (c != NULL)
 183.278 +                    p ->Evals[i] = c ->Evaluator;
 183.279 +        }
 183.280 +    }
 183.281 +
 183.282 +    p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS);
 183.283 +    return p;
 183.284 +
 183.285 +Error:
 183.286 +    if (p -> Segments) _cmsFree(ContextID, p ->Segments);
 183.287 +    if (p -> Evals) _cmsFree(ContextID, p -> Evals);
 183.288 +    if (p ->Table16) _cmsFree(ContextID, p ->Table16);
 183.289 +    _cmsFree(ContextID, p);
 183.290 +    return NULL;
 183.291  }
 183.292  
 183.293  
 183.294 -LPGAMMATABLE LCMSEXPORT cmsAllocGamma(int nEntries)
 183.295 +// Parametric Fn using floating point
 183.296 +static
 183.297 +cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R)
 183.298  {
 183.299 -       LPGAMMATABLE p;
 183.300 -       size_t size;
 183.301 +    cmsFloat64Number e, Val, disc;
 183.302  
 183.303 -       if (nEntries > 65530 || nEntries <= 0) {
 183.304 -                cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't create gammatable of more than 65530 entries");
 183.305 -                return NULL;
 183.306 -       }
 183.307 +    switch (Type) {
 183.308  
 183.309 -       size = sizeof(GAMMATABLE) + (sizeof(WORD) * (nEntries-1));
 183.310 +    // X = Y ^ Gamma
 183.311 +    case 1:
 183.312 +        if (R < 0)
 183.313 +            Val = 0;
 183.314 +        else
 183.315 +            Val = pow(R, Params[0]);
 183.316 +        break;
 183.317  
 183.318 -       p = (LPGAMMATABLE) _cmsMalloc(size);
 183.319 -       if (!p) return NULL;
 183.320 +    // Type 1 Reversed: X = Y ^1/gamma
 183.321 +    case -1:
 183.322 +        if (R < 0)
 183.323 +            Val = 0;
 183.324 +        else
 183.325 +            Val = pow(R, 1/Params[0]);
 183.326 +        break;
 183.327  
 183.328 -       ZeroMemory(p, size);
 183.329 +    // CIE 122-1966
 183.330 +    // Y = (aX + b)^Gamma  | X >= -b/a
 183.331 +    // Y = 0               | else
 183.332 +    case 2:
 183.333 +        disc = -Params[2] / Params[1];
 183.334  
 183.335 -       p -> Seed.Type     = 0;
 183.336 -       p -> nEntries = nEntries;
 183.337 +        if (R >= disc ) {
 183.338  
 183.339 -       return p;
 183.340 +            e = Params[1]*R + Params[2];
 183.341 +
 183.342 +            if (e > 0)
 183.343 +                Val = pow(e, Params[0]);
 183.344 +            else
 183.345 +                Val = 0;
 183.346 +        }
 183.347 +        else
 183.348 +            Val = 0;
 183.349 +        break;
 183.350 +
 183.351 +     // Type 2 Reversed
 183.352 +     // X = (Y ^1/g  - b) / a
 183.353 +     case -2:
 183.354 +         if (R < 0)
 183.355 +             Val = 0;
 183.356 +         else
 183.357 +             Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1];
 183.358 +
 183.359 +         if (Val < 0)
 183.360 +              Val = 0;
 183.361 +         break;
 183.362 +
 183.363 +
 183.364 +    // IEC 61966-3
 183.365 +    // Y = (aX + b)^Gamma | X <= -b/a
 183.366 +    // Y = c              | else
 183.367 +    case 3:
 183.368 +        disc = -Params[2] / Params[1];
 183.369 +        if (disc < 0)
 183.370 +            disc = 0;
 183.371 +
 183.372 +        if (R >= disc) {
 183.373 +
 183.374 +            e = Params[1]*R + Params[2];
 183.375 +
 183.376 +            if (e > 0)
 183.377 +                Val = pow(e, Params[0]) + Params[3];
 183.378 +            else
 183.379 +                Val = 0;
 183.380 +        }
 183.381 +        else
 183.382 +            Val = Params[3];
 183.383 +        break;
 183.384 +
 183.385 +
 183.386 +    // Type 3 reversed
 183.387 +    // X=((Y-c)^1/g - b)/a      | (Y>=c)
 183.388 +    // X=-b/a                   | (Y<c)
 183.389 +    case -3:
 183.390 +        if (R >= Params[3])  {
 183.391 +
 183.392 +            e = R - Params[3];
 183.393 +
 183.394 +            if (e > 0)
 183.395 +                Val = (pow(e, 1/Params[0]) - Params[2]) / Params[1];
 183.396 +            else
 183.397 +                Val = 0;
 183.398 +        }
 183.399 +        else {
 183.400 +            Val = -Params[2] / Params[1];
 183.401 +        }
 183.402 +        break;
 183.403 +
 183.404 +
 183.405 +    // IEC 61966-2.1 (sRGB)
 183.406 +    // Y = (aX + b)^Gamma | X >= d
 183.407 +    // Y = cX             | X < d
 183.408 +    case 4:
 183.409 +        if (R >= Params[4]) {
 183.410 +
 183.411 +            e = Params[1]*R + Params[2];
 183.412 +
 183.413 +            if (e > 0)
 183.414 +                Val = pow(e, Params[0]);
 183.415 +            else
 183.416 +                Val = 0;
 183.417 +        }
 183.418 +        else
 183.419 +            Val = R * Params[3];
 183.420 +        break;
 183.421 +
 183.422 +    // Type 4 reversed
 183.423 +    // X=((Y^1/g-b)/a)    | Y >= (ad+b)^g
 183.424 +    // X=Y/c              | Y< (ad+b)^g
 183.425 +    case -4:
 183.426 +        e = Params[1] * Params[4] + Params[2];
 183.427 +        if (e < 0)
 183.428 +            disc = 0;
 183.429 +        else
 183.430 +            disc = pow(e, Params[0]);
 183.431 +
 183.432 +        if (R >= disc) {
 183.433 +
 183.434 +            Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1];
 183.435 +        }
 183.436 +        else {
 183.437 +            Val = R / Params[3];
 183.438 +        }
 183.439 +        break;
 183.440 +
 183.441 +
 183.442 +    // Y = (aX + b)^Gamma + e | X >= d
 183.443 +    // Y = cX + f             | X < d
 183.444 +    case 5:
 183.445 +        if (R >= Params[4]) {
 183.446 +
 183.447 +            e = Params[1]*R + Params[2];
 183.448 +
 183.449 +            if (e > 0)
 183.450 +                Val = pow(e, Params[0]) + Params[5];
 183.451 +            else
 183.452 +                Val = 0;
 183.453 +        }
 183.454 +        else
 183.455 +            Val = R*Params[3] + Params[6];
 183.456 +        break;
 183.457 +
 183.458 +
 183.459 +    // Reversed type 5
 183.460 +    // X=((Y-e)1/g-b)/a   | Y >=(ad+b)^g+e), cd+f
 183.461 +    // X=(Y-f)/c          | else
 183.462 +    case -5:
 183.463 +
 183.464 +        disc = Params[3] * Params[4] + Params[6];
 183.465 +        if (R >= disc) {
 183.466 +
 183.467 +            e = R - Params[5];
 183.468 +            if (e < 0)
 183.469 +                Val = 0;
 183.470 +            else
 183.471 +                Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1];
 183.472 +        }
 183.473 +        else {
 183.474 +            Val = (R - Params[6]) / Params[3];
 183.475 +        }
 183.476 +        break;
 183.477 +
 183.478 +
 183.479 +    // Types 6,7,8 comes from segmented curves as described in ICCSpecRevision_02_11_06_Float.pdf
 183.480 +    // Type 6 is basically identical to type 5 without d
 183.481 +
 183.482 +    // Y = (a * X + b) ^ Gamma + c
 183.483 +    case 6:
 183.484 +        e = Params[1]*R + Params[2];
 183.485 +
 183.486 +        if (e < 0)
 183.487 +            Val = 0;
 183.488 +        else
 183.489 +            Val = pow(e, Params[0]) + Params[3];
 183.490 +        break;
 183.491 +
 183.492 +    // ((Y - c) ^1/Gamma - b) / a
 183.493 +    case -6:
 183.494 +        e = R - Params[3];
 183.495 +        if (e < 0)
 183.496 +            Val = 0;
 183.497 +        else
 183.498 +        Val = (pow(e, 1.0/Params[0]) - Params[2]) / Params[1];
 183.499 +        break;
 183.500 +
 183.501 +
 183.502 +    // Y = a * log (b * X^Gamma + c) + d
 183.503 +    case 7:
 183.504 +
 183.505 +       e = Params[2] * pow(R, Params[0]) + Params[3];
 183.506 +       if (e <= 0)
 183.507 +           Val = 0;
 183.508 +       else
 183.509 +           Val = Params[1]*log10(e) + Params[4];
 183.510 +       break;
 183.511 +
 183.512 +    // (Y - d) / a = log(b * X ^Gamma + c)
 183.513 +    // pow(10, (Y-d) / a) = b * X ^Gamma + c
 183.514 +    // pow((pow(10, (Y-d) / a) - c) / b, 1/g) = X
 183.515 +    case -7:
 183.516 +       Val = pow((pow(10.0, (R-Params[4]) / Params[1]) - Params[3]) / Params[2], 1.0 / Params[0]);
 183.517 +       break;
 183.518 +
 183.519 +
 183.520 +   //Y = a * b^(c*X+d) + e
 183.521 +   case 8:
 183.522 +       Val = (Params[0] * pow(Params[1], Params[2] * R + Params[3]) + Params[4]);
 183.523 +       break;
 183.524 +
 183.525 +
 183.526 +   // Y = (log((y-e) / a) / log(b) - d ) / c
 183.527 +   // a=0, b=1, c=2, d=3, e=4,
 183.528 +   case -8:
 183.529 +
 183.530 +       disc = R - Params[4];
 183.531 +       if (disc < 0) Val = 0;
 183.532 +       else
 183.533 +           Val = (log(disc / Params[0]) / log(Params[1]) - Params[3]) / Params[2];
 183.534 +       break;
 183.535 +
 183.536 +   // S-Shaped: (1 - (1-x)^1/g)^1/g
 183.537 +   case 108:
 183.538 +      Val = pow(1.0 - pow(1 - R, 1/Params[0]), 1/Params[0]);
 183.539 +      break;
 183.540 +
 183.541 +    // y = (1 - (1-x)^1/g)^1/g
 183.542 +    // y^g = (1 - (1-x)^1/g)
 183.543 +    // 1 - y^g = (1-x)^1/g
 183.544 +    // (1 - y^g)^g = 1 - x
 183.545 +    // 1 - (1 - y^g)^g
 183.546 +    case -108:
 183.547 +        Val = 1 - pow(1 - pow(R, Params[0]), Params[0]);
 183.548 +        break;
 183.549 +
 183.550 +    default:
 183.551 +        // Unsupported parametric curve. Should never reach here
 183.552 +        return 0;
 183.553 +    }
 183.554 +
 183.555 +    return Val;
 183.556  }
 183.557  
 183.558 -void LCMSEXPORT cmsFreeGamma(LPGAMMATABLE Gamma)
 183.559 +// Evaluate a segmented funtion for a single value. Return -1 if no valid segment found .
 183.560 +// If fn type is 0, perform an interpolation on the table
 183.561 +static
 183.562 +cmsFloat64Number EvalSegmentedFn(const cmsToneCurve *g, cmsFloat64Number R)
 183.563  {
 183.564 -       if (Gamma)  _cmsFree(Gamma);
 183.565 +    int i;
 183.566 +
 183.567 +    for (i = g ->nSegments-1; i >= 0 ; --i) {
 183.568 +
 183.569 +        // Check for domain
 183.570 +        if ((R > g ->Segments[i].x0) && (R <= g ->Segments[i].x1)) {
 183.571 +
 183.572 +            // Type == 0 means segment is sampled
 183.573 +            if (g ->Segments[i].Type == 0) {
 183.574 +
 183.575 +                cmsFloat32Number R1 = (cmsFloat32Number) (R - g ->Segments[i].x0);
 183.576 +                cmsFloat32Number Out;
 183.577 +
 183.578 +                // Setup the table (TODO: clean that)
 183.579 +                g ->SegInterp[i]-> Table = g ->Segments[i].SampledPoints;
 183.580 +
 183.581 +                g ->SegInterp[i] -> Interpolation.LerpFloat(&R1, &Out, g ->SegInterp[i]);
 183.582 +
 183.583 +                return Out;
 183.584 +            }
 183.585 +            else
 183.586 +                return g ->Evals[i](g->Segments[i].Type, g ->Segments[i].Params, R);
 183.587 +        }
 183.588 +    }
 183.589 +
 183.590 +    return MINUS_INF;
 183.591  }
 183.592  
 183.593  
 183.594 -
 183.595 -void LCMSEXPORT cmsFreeGammaTriple(LPGAMMATABLE Gamma[3])
 183.596 +// Create an empty gamma curve, by using tables. This specifies only the limited-precision part, and leaves the
 183.597 +// floating point description empty.
 183.598 +cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsInt32Number nEntries, const cmsUInt16Number Values[])
 183.599  {
 183.600 -    cmsFreeGamma(Gamma[0]);
 183.601 -    cmsFreeGamma(Gamma[1]);
 183.602 -    cmsFreeGamma(Gamma[2]);
 183.603 -    Gamma[0] = Gamma[1] = Gamma[2] = NULL;
 183.604 +    return AllocateToneCurveStruct(ContextID, nEntries, 0, NULL, Values);
 183.605  }
 183.606  
 183.607 -
 183.608 -
 183.609 -// Duplicate a gamma table
 183.610 -
 183.611 -LPGAMMATABLE  LCMSEXPORT cmsDupGamma(LPGAMMATABLE In)
 183.612 +static
 183.613 +int EntriesByGamma(cmsFloat64Number Gamma)
 183.614  {
 183.615 -       LPGAMMATABLE Ptr;
 183.616 -       size_t size;
 183.617 -
 183.618 -       Ptr = cmsAllocGamma(In -> nEntries);
 183.619 -       if (Ptr == NULL) return NULL;
 183.620 -
 183.621 -       size = sizeof(GAMMATABLE) + (sizeof(WORD) * (In -> nEntries-1));
 183.622 -
 183.623 -       CopyMemory(Ptr, In, size);
 183.624 -       return Ptr;
 183.625 +    if (fabs(Gamma - 1.0) < 0.001) return 2;
 183.626 +    return 4096;
 183.627  }
 183.628  
 183.629  
 183.630 -// Handle gamma using interpolation tables. The resulting curves can become
 183.631 -// very stange, but are pleasent to eye.
 183.632 +// Create a segmented gamma, fill the table
 183.633 +cmsToneCurve* CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID,
 183.634 +                                                   cmsInt32Number nSegments, const cmsCurveSegment Segments[])
 183.635 +{
 183.636 +    int i;
 183.637 +    cmsFloat64Number R, Val;
 183.638 +    cmsToneCurve* g;
 183.639 +    int nGridPoints = 4096;
 183.640  
 183.641 -LPGAMMATABLE LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma,
 183.642 -                          LPGAMMATABLE OutGamma)
 183.643 -{
 183.644 -       register int i;
 183.645 -       L16PARAMS L16In, L16Out;
 183.646 -       LPWORD InPtr, OutPtr;
 183.647 -       LPGAMMATABLE p;
 183.648 +    _cmsAssert(Segments != NULL);
 183.649  
 183.650 -       p = cmsAllocGamma(256);
 183.651 -       if (!p) return NULL;
 183.652 +    // Optimizatin for identity curves.
 183.653 +    if (nSegments == 1 && Segments[0].Type == 1) {
 183.654  
 183.655 -       cmsCalcL16Params(InGamma -> nEntries, &L16In);
 183.656 -       InPtr  = InGamma -> GammaTable;
 183.657 +        nGridPoints = EntriesByGamma(Segments[0].Params[0]);
 183.658 +    }
 183.659  
 183.660 -       cmsCalcL16Params(OutGamma -> nEntries, &L16Out);
 183.661 -       OutPtr = OutGamma-> GammaTable;
 183.662 +    g = AllocateToneCurveStruct(ContextID, nGridPoints, nSegments, Segments, NULL);
 183.663 +    if (g == NULL) return NULL;
 183.664  
 183.665 -       for (i=0; i < 256; i++)
 183.666 -       {
 183.667 -              WORD wValIn, wValOut;
 183.668 +    // Once we have the floating point version, we can approximate a 16 bit table of 4096 entries
 183.669 +    // for performance reasons. This table would normally not be used except on 8/16 bits transforms.
 183.670 +    for (i=0; i < nGridPoints; i++) {
 183.671  
 183.672 -              wValIn  = cmsLinearInterpLUT16(RGB_8_TO_16(i), InPtr, &L16In);
 183.673 -              wValOut = cmsReverseLinearInterpLUT16(wValIn, OutPtr, &L16Out);
 183.674 +        R   = (cmsFloat64Number) i / (nGridPoints-1);
 183.675  
 183.676 -              p -> GammaTable[i] = wValOut;
 183.677 -       }
 183.678 +        Val = EvalSegmentedFn(g, R);
 183.679  
 183.680 -       return p;
 183.681 +        // Round and saturate
 183.682 +        g ->Table16[i] = _cmsQuickSaturateWord(Val * 65535.0);
 183.683 +    }
 183.684 +
 183.685 +    return g;
 183.686  }
 183.687  
 183.688 +// Use a segmented curve to store the floating point table
 183.689 +cmsToneCurve* CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[])
 183.690 +{
 183.691 +    cmsCurveSegment Seg[2];
 183.692  
 183.693 +    // Initialize segmented curve part up to 0
 183.694 +    Seg[0].x0 = -1;
 183.695 +    Seg[0].x1 = 0;
 183.696 +    Seg[0].Type = 6;
 183.697  
 183.698 -// New method, using smoothed parametric curves. This works FAR better.
 183.699 -// We want to get
 183.700 -//
 183.701 -//      y = f(g^-1(x))      ; f = ingamma, g = outgamma
 183.702 -//
 183.703 -// And this can be parametrized as
 183.704 -//
 183.705 -//      y = f(t)
 183.706 -//      x = g(t)
 183.707 +    Seg[0].Params[0] = 1;
 183.708 +    Seg[0].Params[1] = 0;
 183.709 +    Seg[0].Params[2] = 0;
 183.710 +    Seg[0].Params[3] = 0;
 183.711 +    Seg[0].Params[4] = 0;
 183.712  
 183.713 +    // From zero to any
 183.714 +    Seg[1].x0 = 0;
 183.715 +    Seg[1].x1 = 1.0;
 183.716 +    Seg[1].Type = 0;
 183.717  
 183.718 -LPGAMMATABLE LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma,
 183.719 -                                       LPGAMMATABLE OutGamma, int nPoints)
 183.720 -{
 183.721 +    Seg[1].nGridPoints = nEntries;
 183.722 +    Seg[1].SampledPoints = (cmsFloat32Number*) values;
 183.723  
 183.724 -    LPSAMPLEDCURVE x, y, r;
 183.725 -    LPGAMMATABLE res;
 183.726 -
 183.727 -    x = cmsConvertGammaToSampledCurve(InGamma,  nPoints);
 183.728 -    y = cmsConvertGammaToSampledCurve(OutGamma, nPoints);
 183.729 -    r = cmsJoinSampledCurves(y, x, nPoints);
 183.730 -
 183.731 -    // Does clean "hair"
 183.732 -    cmsSmoothSampledCurve(r, 0.001);
 183.733 -
 183.734 -    cmsClampSampledCurve(r, 0.0, 65535.0);
 183.735 -
 183.736 -    cmsFreeSampledCurve(x);
 183.737 -    cmsFreeSampledCurve(y);
 183.738 -
 183.739 -    res = cmsConvertSampledCurveToGamma(r, 65535.0);
 183.740 -    cmsFreeSampledCurve(r);
 183.741 -
 183.742 -    return res;
 183.743 +    return cmsBuildSegmentedToneCurve(ContextID, 2, Seg);
 183.744  }
 183.745  
 183.746 -
 183.747 -
 183.748 -// Reverse a gamma table
 183.749 -
 183.750 -LPGAMMATABLE LCMSEXPORT cmsReverseGamma(int nResultSamples, LPGAMMATABLE InGamma)
 183.751 -{
 183.752 -       register int i;
 183.753 -       L16PARAMS L16In;
 183.754 -       LPWORD InPtr;
 183.755 -       LPGAMMATABLE p;
 183.756 -
 183.757 -       // Try to reverse it analytically whatever possible
 183.758 -       if (InGamma -> Seed.Type > 0 && InGamma -> Seed.Type <= 5 &&
 183.759 -            _cmsCrc32OfGammaTable(InGamma) == InGamma -> Seed.Crc32) {
 183.760 -
 183.761 -                return cmsBuildParametricGamma(nResultSamples, -(InGamma -> Seed.Type), InGamma ->Seed.Params);
 183.762 -       }
 183.763 -
 183.764 -
 183.765 -       // Nope, reverse the table
 183.766 -       p = cmsAllocGamma(nResultSamples);
 183.767 -       if (!p) return NULL;
 183.768 -
 183.769 -       cmsCalcL16Params(InGamma -> nEntries, &L16In);
 183.770 -       InPtr  = InGamma -> GammaTable;
 183.771 -
 183.772 -       for (i=0; i < nResultSamples; i++)
 183.773 -       {
 183.774 -              WORD wValIn, wValOut;
 183.775 -
 183.776 -              wValIn = _cmsQuantizeVal(i, nResultSamples);
 183.777 -              wValOut = cmsReverseLinearInterpLUT16(wValIn, InPtr, &L16In);
 183.778 -              p -> GammaTable[i] = wValOut;
 183.779 -       }
 183.780 -
 183.781 -
 183.782 -       return p;
 183.783 -}
 183.784 -
 183.785 -
 183.786 -
 183.787  // Parametric curves
 183.788  //
 183.789 -// Parameters goes as: Gamma, a, b, c, d, e, f
 183.790 +// Parameters goes as: Curve, a, b, c, d, e, f
 183.791  // Type is the ICC type +1
 183.792  // if type is negative, then the curve is analyticaly inverted
 183.793 +cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[])
 183.794 +{
 183.795 +    cmsCurveSegment Seg0;
 183.796 +    int Pos = 0;
 183.797 +    cmsUInt32Number size;
 183.798 +    _cmsParametricCurvesCollection* c = GetParametricCurveByType(Type, &Pos);
 183.799  
 183.800 -LPGAMMATABLE LCMSEXPORT cmsBuildParametricGamma(int nEntries, int Type, double Params[])
 183.801 +    _cmsAssert(Params != NULL);
 183.802 +
 183.803 +    if (c == NULL) {
 183.804 +         cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
 183.805 +        return NULL;
 183.806 +    }
 183.807 +
 183.808 +    memset(&Seg0, 0, sizeof(Seg0));
 183.809 +
 183.810 +    Seg0.x0   = MINUS_INF;
 183.811 +    Seg0.x1   = PLUS_INF;
 183.812 +    Seg0.Type = Type;
 183.813 +
 183.814 +    size = c->ParameterCount[Pos] * sizeof(cmsFloat64Number);
 183.815 +    memmove(Seg0.Params, Params, size);
 183.816 +
 183.817 +    return cmsBuildSegmentedToneCurve(ContextID, 1, &Seg0);
 183.818 +}
 183.819 +
 183.820 +
 183.821 +
 183.822 +// Build a gamma table based on gamma constant
 183.823 +cmsToneCurve* CMSEXPORT cmsBuildGamma(cmsContext ContextID, cmsFloat64Number Gamma)
 183.824  {
 183.825 -        LPGAMMATABLE Table;
 183.826 -        double R, Val, dval, e;
 183.827 -        int i;
 183.828 -        int ParamsByType[] = { 0, 1, 3, 4, 5, 7 };
 183.829 +    return cmsBuildParametricToneCurve(ContextID, 1, &Gamma);
 183.830 +}
 183.831  
 183.832 -        Table = cmsAllocGamma(nEntries);
 183.833 -        if (NULL == Table) return NULL;
 183.834  
 183.835 -        Table -> Seed.Type = Type;
 183.836 +// Free all memory taken by the gamma curve
 183.837 +void CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve)
 183.838 +{
 183.839 +    cmsContext ContextID;
 183.840  
 183.841 -        CopyMemory(Table ->Seed.Params, Params, ParamsByType[abs(Type)] * sizeof(double));
 183.842 +    if (Curve == NULL) return;
 183.843  
 183.844 +    ContextID = Curve ->InterpParams->ContextID;
 183.845  
 183.846 -        for (i=0; i < nEntries; i++) {
 183.847 +    _cmsFreeInterpParams(Curve ->InterpParams);
 183.848  
 183.849 -                R   = (double) i / (nEntries-1);
 183.850 +    if (Curve -> Table16)
 183.851 +        _cmsFree(ContextID, Curve ->Table16);
 183.852  
 183.853 -                switch (Type) {
 183.854 +    if (Curve ->Segments) {
 183.855  
 183.856 -                // X = Y ^ Gamma
 183.857 -                case 1:
 183.858 -                      Val = pow(R, Params[0]);
 183.859 -                      break;
 183.860 +        cmsUInt32Number i;
 183.861  
 183.862 -                // Type 1 Reversed: X = Y ^1/gamma
 183.863 -                case -1:
 183.864 -                      Val = pow(R, 1/Params[0]);
 183.865 -                      break;
 183.866 +        for (i=0; i < Curve ->nSegments; i++) {
 183.867  
 183.868 -                // CIE 122-1966
 183.869 -                // Y = (aX + b)^Gamma  | X >= -b/a
 183.870 -                // Y = 0               | else
 183.871 -                case 2:
 183.872 -                    if (R >= -Params[2] / Params[1]) {
 183.873 +            if (Curve ->Segments[i].SampledPoints) {
 183.874 +                _cmsFree(ContextID, Curve ->Segments[i].SampledPoints);
 183.875 +            }
 183.876  
 183.877 -                              e = Params[1]*R + Params[2];
 183.878 -
 183.879 -                              if (e > 0)
 183.880 -                                Val = pow(e, Params[0]);
 183.881 -                              else
 183.882 -                                Val = 0;
 183.883 -                    }
 183.884 -                    else
 183.885 -                              Val = 0;
 183.886 -                      break;
 183.887 -
 183.888 -                // Type 2 Reversed
 183.889 -                // X = (Y ^1/g  - b) / a
 183.890 -                case -2:
 183.891 -
 183.892 -                    Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1];
 183.893 -                    if (Val < 0)
 183.894 -                            Val = 0;
 183.895 -                    break;
 183.896 -
 183.897 -
 183.898 -                // IEC 61966-3
 183.899 -                // Y = (aX + b)^Gamma | X <= -b/a
 183.900 -                // Y = c              | else
 183.901 -                case 3:
 183.902 -                    if (R >= -Params[2] / Params[1]) {
 183.903 -
 183.904 -                      e = Params[1]*R + Params[2];
 183.905 -                      Val = pow(e, Params[0]) + Params[3];
 183.906 -                    }
 183.907 -                    else
 183.908 -                      Val = Params[3];
 183.909 -                    break;
 183.910 -
 183.911 -
 183.912 -                // Type 3 reversed
 183.913 -                // X=((Y-c)^1/g - b)/a      | (Y>=c)
 183.914 -                // X=-b/a                   | (Y<c)
 183.915 -
 183.916 -                case -3:
 183.917 -                    if (R >= Params[3])  {
 183.918 -                        e = R - Params[3];
 183.919 -                        Val = (pow(e, 1/Params[0]) - Params[2]) / Params[1];
 183.920 -                        if (Val < 0) Val = 0;
 183.921 -                    }
 183.922 -                    else {
 183.923 -                        Val = -Params[2] / Params[1];
 183.924 -                    }
 183.925 -                    break;
 183.926 -
 183.927 -
 183.928 -                // IEC 61966-2.1 (sRGB)
 183.929 -                // Y = (aX + b)^Gamma | X >= d
 183.930 -                // Y = cX             | X < d
 183.931 -                case 4:
 183.932 -                    if (R >= Params[4]) {
 183.933 -
 183.934 -                              e = Params[1]*R + Params[2];
 183.935 -                              if (e > 0)
 183.936 -                                Val = pow(e, Params[0]);
 183.937 -                              else
 183.938 -                                Val = 0;
 183.939 -                    }
 183.940 -                      else
 183.941 -                              Val = R * Params[3];
 183.942 -                      break;
 183.943 -
 183.944 -                // Type 4 reversed
 183.945 -                // X=((Y^1/g-b)/a)    | Y >= (ad+b)^g
 183.946 -                // X=Y/c              | Y< (ad+b)^g
 183.947 -
 183.948 -                case -4:
 183.949 -                    if (R >= pow(Params[1] * Params[4] + Params[2], Params[0])) {
 183.950 -
 183.951 -                        Val = (pow(R, 1.0/Params[0]) - Params[2]) / Params[1];
 183.952 -                    }
 183.953 -                    else {
 183.954 -                        Val = R / Params[3];
 183.955 -                    }
 183.956 -                    break;
 183.957 -
 183.958 -
 183.959 -
 183.960 -                // Y = (aX + b)^Gamma + e | X <= d
 183.961 -                // Y = cX + f             | else
 183.962 -                case 5:
 183.963 -                    if (R >= Params[4]) {
 183.964 -
 183.965 -                        e = Params[1]*R + Params[2];
 183.966 -                        Val = pow(e, Params[0]) + Params[5];
 183.967 -                    }
 183.968 -                    else
 183.969 -                        Val = R*Params[3] + Params[6];
 183.970 -                    break;
 183.971 -
 183.972 -
 183.973 -                // Reversed type 5
 183.974 -                // X=((Y-e)1/g-b)/a   | Y >=(ad+b)^g+e)
 183.975 -                // X=(Y-f)/c          | else
 183.976 -                case -5:
 183.977 -
 183.978 -                if (R >= pow(Params[1] * Params[4], Params[0]) + Params[5]) {
 183.979 -
 183.980 -                    Val = pow(R - Params[5], 1/Params[0]) - Params[2] / Params[1];
 183.981 -                }
 183.982 -                else {
 183.983 -                    Val = (R - Params[6]) / Params[3];
 183.984 -                }
 183.985 -                break;
 183.986 -
 183.987 -                default:
 183.988 -                        cmsSignalError(LCMS_ERRC_ABORTED, "Unsupported parametric curve type=%d", abs(Type)-1);
 183.989 -                        cmsFreeGamma(Table);
 183.990 -                        return NULL;
 183.991 -                }
 183.992 -
 183.993 -
 183.994 -        // Saturate
 183.995 -
 183.996 -        dval = Val * 65535.0 + .5;
 183.997 -        if (dval > 65535.) dval = 65535.0;
 183.998 -        if (dval < 0) dval = 0;
 183.999 -
183.1000 -        Table->GammaTable[i] = (WORD) floor(dval);
183.1001 +            if (Curve ->SegInterp[i] != 0)
183.1002 +                _cmsFreeInterpParams(Curve->SegInterp[i]);
183.1003          }
183.1004  
183.1005 -        Table -> Seed.Crc32 = _cmsCrc32OfGammaTable(Table);
183.1006 +        _cmsFree(ContextID, Curve ->Segments);
183.1007 +        _cmsFree(ContextID, Curve ->SegInterp);
183.1008 +    }
183.1009  
183.1010 -        return Table;
183.1011 +    if (Curve -> Evals)
183.1012 +        _cmsFree(ContextID, Curve -> Evals);
183.1013 +
183.1014 +    if (Curve) _cmsFree(ContextID, Curve);
183.1015  }
183.1016  
183.1017 -// Build a gamma table based on gamma constant
183.1018 +// Utility function, free 3 gamma tables
183.1019 +void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3])
183.1020 +{
183.1021  
183.1022 -LPGAMMATABLE LCMSEXPORT cmsBuildGamma(int nEntries, double Gamma)
183.1023 -{
183.1024 -    return cmsBuildParametricGamma(nEntries, 1, &Gamma);
183.1025 +    _cmsAssert(Curve != NULL);
183.1026 +
183.1027 +    if (Curve[0] != NULL) cmsFreeToneCurve(Curve[0]);
183.1028 +    if (Curve[1] != NULL) cmsFreeToneCurve(Curve[1]);
183.1029 +    if (Curve[2] != NULL) cmsFreeToneCurve(Curve[2]);
183.1030 +
183.1031 +    Curve[0] = Curve[1] = Curve[2] = NULL;
183.1032  }
183.1033  
183.1034  
183.1035 +// Duplicate a gamma table
183.1036 +cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* In)
183.1037 +{
183.1038 +    if (In == NULL) return NULL;
183.1039 +
183.1040 +    return  AllocateToneCurveStruct(In ->InterpParams ->ContextID, In ->nEntries, In ->nSegments, In ->Segments, In ->Table16);
183.1041 +}
183.1042 +
183.1043 +// Joins two curves for X and Y. Curves should be monotonic.
183.1044 +// We want to get
183.1045 +//
183.1046 +//      y = Y^-1(X(t))
183.1047 +//
183.1048 +cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID,
183.1049 +                                      const cmsToneCurve* X,
183.1050 +                                      const cmsToneCurve* Y, cmsUInt32Number nResultingPoints)
183.1051 +{
183.1052 +    cmsToneCurve* out = NULL;
183.1053 +    cmsToneCurve* Yreversed = NULL;
183.1054 +    cmsFloat32Number t, x;
183.1055 +    cmsFloat32Number* Res = NULL;
183.1056 +    cmsUInt32Number i;
183.1057 +
183.1058 +
183.1059 +    _cmsAssert(X != NULL);
183.1060 +    _cmsAssert(Y != NULL);
183.1061 +
183.1062 +    Yreversed = cmsReverseToneCurveEx(nResultingPoints, Y);
183.1063 +    if (Yreversed == NULL) goto Error;
183.1064 +
183.1065 +    Res = (cmsFloat32Number*) _cmsCalloc(ContextID, nResultingPoints, sizeof(cmsFloat32Number));
183.1066 +    if (Res == NULL) goto Error;
183.1067 +
183.1068 +    //Iterate
183.1069 +    for (i=0; i <  nResultingPoints; i++) {
183.1070 +
183.1071 +        t = (cmsFloat32Number) i / (nResultingPoints-1);
183.1072 +        x = cmsEvalToneCurveFloat(X,  t);
183.1073 +        Res[i] = cmsEvalToneCurveFloat(Yreversed, x);
183.1074 +    }
183.1075 +
183.1076 +    // Allocate space for output
183.1077 +    out = cmsBuildTabulatedToneCurveFloat(ContextID, nResultingPoints, Res);
183.1078 +
183.1079 +Error:
183.1080 +
183.1081 +    if (Res != NULL) _cmsFree(ContextID, Res);
183.1082 +    if (Yreversed != NULL) cmsFreeToneCurve(Yreversed);
183.1083 +
183.1084 +    return out;
183.1085 +}
183.1086 +
183.1087 +
183.1088 +
183.1089 +// Get the surrounding nodes. This is tricky on non-monotonic tables
183.1090 +static
183.1091 +int GetInterval(cmsFloat64Number In, const cmsUInt16Number LutTable[], const struct _cms_interp_struc* p)
183.1092 +{
183.1093 +    int i;
183.1094 +    int y0, y1;
183.1095 +
183.1096 +    // A 1 point table is not allowed
183.1097 +    if (p -> Domain[0] < 1) return -1;
183.1098 +
183.1099 +    // Let's see if ascending or descending.
183.1100 +    if (LutTable[0] < LutTable[p ->Domain[0]]) {
183.1101 +
183.1102 +        // Table is overall ascending
183.1103 +        for (i=p->Domain[0]-1; i >=0; --i) {
183.1104 +
183.1105 +            y0 = LutTable[i];
183.1106 +            y1 = LutTable[i+1];
183.1107 +
183.1108 +            if (y0 <= y1) { // Increasing
183.1109 +                if (In >= y0 && In <= y1) return i;
183.1110 +            }
183.1111 +            else
183.1112 +                if (y1 < y0) { // Decreasing
183.1113 +                    if (In >= y1 && In <= y0) return i;
183.1114 +                }
183.1115 +        }
183.1116 +    }
183.1117 +    else {
183.1118 +        // Table is overall descending
183.1119 +        for (i=0; i < (int) p -> Domain[0]; i++) {
183.1120 +
183.1121 +            y0 = LutTable[i];
183.1122 +            y1 = LutTable[i+1];
183.1123 +
183.1124 +            if (y0 <= y1) { // Increasing
183.1125 +                if (In >= y0 && In <= y1) return i;
183.1126 +            }
183.1127 +            else
183.1128 +                if (y1 < y0) { // Decreasing
183.1129 +                    if (In >= y1 && In <= y0) return i;
183.1130 +                }
183.1131 +        }
183.1132 +    }
183.1133 +
183.1134 +    return -1;
183.1135 +}
183.1136 +
183.1137 +// Reverse a gamma table
183.1138 +cmsToneCurve* CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InCurve)
183.1139 +{
183.1140 +    cmsToneCurve *out;
183.1141 +    cmsFloat64Number a = 1, b = 0, y, x1, y1, x2, y2;
183.1142 +    int i, j;
183.1143 +    int Ascending;
183.1144 +
183.1145 +    _cmsAssert(InCurve != NULL);
183.1146 +
183.1147 +    // Try to reverse it analytically whatever possible
183.1148 +    if (InCurve ->nSegments == 1 && InCurve ->Segments[0].Type > 0 && InCurve -> Segments[0].Type <= 5) {
183.1149 +
183.1150 +        return cmsBuildParametricToneCurve(InCurve ->InterpParams->ContextID,
183.1151 +                                       -(InCurve -> Segments[0].Type),
183.1152 +                                       InCurve -> Segments[0].Params);
183.1153 +    }
183.1154 +
183.1155 +    // Nope, reverse the table.
183.1156 +    out = cmsBuildTabulatedToneCurve16(InCurve ->InterpParams->ContextID, nResultSamples, NULL);
183.1157 +    if (out == NULL)
183.1158 +        return NULL;
183.1159 +
183.1160 +    // We want to know if this is an ascending or descending table
183.1161 +    Ascending = !cmsIsToneCurveDescending(InCurve);
183.1162 +
183.1163 +    // Iterate across Y axis
183.1164 +    for (i=0; i <  nResultSamples; i++) {
183.1165 +
183.1166 +        y = (cmsFloat64Number) i * 65535.0 / (nResultSamples - 1);
183.1167 +
183.1168 +        // Find interval in which y is within.
183.1169 +        j = GetInterval(y, InCurve->Table16, InCurve->InterpParams);
183.1170 +        if (j >= 0) {
183.1171 +
183.1172 +            // Get limits of interval
183.1173 +            x1 = InCurve ->Table16[j];
183.1174 +            x2 = InCurve ->Table16[j+1];
183.1175 +
183.1176 +            y1 = (cmsFloat64Number) (j * 65535.0) / (InCurve ->nEntries - 1);
183.1177 +            y2 = (cmsFloat64Number) ((j+1) * 65535.0 ) / (InCurve ->nEntries - 1);
183.1178 +
183.1179 +            // If collapsed, then use any
183.1180 +            if (x1 == x2) {
183.1181 +
183.1182 +                out ->Table16[i] = _cmsQuickSaturateWord(Ascending ? y2 : y1);
183.1183 +                continue;
183.1184 +
183.1185 +            } else {
183.1186 +
183.1187 +                // Interpolate
183.1188 +                a = (y2 - y1) / (x2 - x1);
183.1189 +                b = y2 - a * x2;
183.1190 +            }
183.1191 +        }
183.1192 +
183.1193 +        out ->Table16[i] = _cmsQuickSaturateWord(a* y + b);
183.1194 +    }
183.1195 +
183.1196 +    return out;
183.1197 +}
183.1198 +
183.1199 +// Reverse a gamma table
183.1200 +cmsToneCurve* CMSEXPORT cmsReverseToneCurve(const cmsToneCurve* InGamma)
183.1201 +{
183.1202 +    _cmsAssert(InGamma != NULL);
183.1203 +
183.1204 +    return cmsReverseToneCurveEx(InGamma -> nEntries, InGamma);
183.1205 +}
183.1206  
183.1207  // From: Eilers, P.H.C. (1994) Smoothing and interpolation with finite
183.1208  // differences. in: Graphic Gems IV, Heckbert, P.S. (ed.), Academic press.
183.1209 @@ -499,485 +903,264 @@
183.1210  //   Input:  smoothing parameter (lambda), length (m).
183.1211  //   Output: smoothed vector (z): vector from 1 to m.
183.1212  
183.1213 +static
183.1214 +cmsBool smooth2(cmsContext ContextID, cmsFloat32Number w[], cmsFloat32Number y[], cmsFloat32Number z[], cmsFloat32Number lambda, int m)
183.1215 +{
183.1216 +    int i, i1, i2;
183.1217 +    cmsFloat32Number *c, *d, *e;
183.1218 +    cmsBool st;
183.1219  
183.1220 -static
183.1221 -void smooth2(vec w, vec y, vec z, float lambda, int m)
183.1222 -{
183.1223 -  int i, i1, i2;
183.1224 -  vec c, d, e;
183.1225 -  d[1] = w[1] + lambda;
183.1226 -  c[1] = -2 * lambda / d[1];
183.1227 -  e[1] = lambda /d[1];
183.1228 -  z[1] = w[1] * y[1];
183.1229 -  d[2] = w[2] + 5 * lambda - d[1] * c[1] *  c[1];
183.1230 -  c[2] = (-4 * lambda - d[1] * c[1] * e[1]) / d[2];
183.1231 -  e[2] = lambda / d[2];
183.1232 -  z[2] = w[2] * y[2] - c[1] * z[1];
183.1233 -  for (i = 3; i < m - 1; i++) {
183.1234 -    i1 = i - 1; i2 = i - 2;
183.1235 -    d[i]= w[i] + 6 * lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
183.1236 -    c[i] = (-4 * lambda -d[i1] * c[i1] * e[i1])/ d[i];
183.1237 -    e[i] = lambda / d[i];
183.1238 -    z[i] = w[i] * y[i] - c[i1] * z[i1] - e[i2] * z[i2];
183.1239 -  }
183.1240 -  i1 = m - 2; i2 = m - 3;
183.1241 -  d[m - 1] = w[m - 1] + 5 * lambda -c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
183.1242 -  c[m - 1] = (-2 * lambda - d[i1] * c[i1] * e[i1]) / d[m - 1];
183.1243 -  z[m - 1] = w[m - 1] * y[m - 1] - c[i1] * z[i1] - e[i2] * z[i2];
183.1244 -  i1 = m - 1; i2 = m - 2;
183.1245 -  d[m] = w[m] + lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
183.1246 -  z[m] = (w[m] * y[m] - c[i1] * z[i1] - e[i2] * z[i2]) / d[m];
183.1247 -  z[m - 1] = z[m - 1] / d[m - 1] - c[m - 1] * z[m];
183.1248 -  for (i = m - 2; 1<= i; i--)
183.1249 -     z[i] = z[i] / d[i] - c[i] * z[i + 1] - e[i] * z[i + 2];
183.1250 +
183.1251 +    c = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number));
183.1252 +    d = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number));
183.1253 +    e = (cmsFloat32Number*) _cmsCalloc(ContextID, MAX_NODES_IN_CURVE, sizeof(cmsFloat32Number));
183.1254 +
183.1255 +    if (c != NULL && d != NULL && e != NULL) {
183.1256 +
183.1257 +
183.1258 +    d[1] = w[1] + lambda;
183.1259 +    c[1] = -2 * lambda / d[1];
183.1260 +    e[1] = lambda /d[1];
183.1261 +    z[1] = w[1] * y[1];
183.1262 +    d[2] = w[2] + 5 * lambda - d[1] * c[1] *  c[1];
183.1263 +    c[2] = (-4 * lambda - d[1] * c[1] * e[1]) / d[2];
183.1264 +    e[2] = lambda / d[2];
183.1265 +    z[2] = w[2] * y[2] - c[1] * z[1];
183.1266 +
183.1267 +    for (i = 3; i < m - 1; i++) {
183.1268 +        i1 = i - 1; i2 = i - 2;
183.1269 +        d[i]= w[i] + 6 * lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
183.1270 +        c[i] = (-4 * lambda -d[i1] * c[i1] * e[i1])/ d[i];
183.1271 +        e[i] = lambda / d[i];
183.1272 +        z[i] = w[i] * y[i] - c[i1] * z[i1] - e[i2] * z[i2];
183.1273 +    }
183.1274 +
183.1275 +    i1 = m - 2; i2 = m - 3;
183.1276 +
183.1277 +    d[m - 1] = w[m - 1] + 5 * lambda -c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
183.1278 +    c[m - 1] = (-2 * lambda - d[i1] * c[i1] * e[i1]) / d[m - 1];
183.1279 +    z[m - 1] = w[m - 1] * y[m - 1] - c[i1] * z[i1] - e[i2] * z[i2];
183.1280 +    i1 = m - 1; i2 = m - 2;
183.1281 +
183.1282 +    d[m] = w[m] + lambda - c[i1] * c[i1] * d[i1] - e[i2] * e[i2] * d[i2];
183.1283 +    z[m] = (w[m] * y[m] - c[i1] * z[i1] - e[i2] * z[i2]) / d[m];
183.1284 +    z[m - 1] = z[m - 1] / d[m - 1] - c[m - 1] * z[m];
183.1285 +
183.1286 +    for (i = m - 2; 1<= i; i--)
183.1287 +        z[i] = z[i] / d[i] - c[i] * z[i + 1] - e[i] * z[i + 2];
183.1288 +
183.1289 +      st = TRUE;
183.1290 +    }
183.1291 +    else st = FALSE;
183.1292 +
183.1293 +    if (c != NULL) _cmsFree(ContextID, c);
183.1294 +    if (d != NULL) _cmsFree(ContextID, d);
183.1295 +    if (e != NULL) _cmsFree(ContextID, e);
183.1296 +
183.1297 +    return st;
183.1298  }
183.1299  
183.1300 -
183.1301 -
183.1302 -// Smooths a curve sampled at regular intervals
183.1303 -
183.1304 -LCMSBOOL LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda)
183.1305 -
183.1306 +// Smooths a curve sampled at regular intervals.
183.1307 +cmsBool  CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda)
183.1308  {
183.1309 -    vec w, y, z;
183.1310 +    cmsFloat32Number w[MAX_NODES_IN_CURVE], y[MAX_NODES_IN_CURVE], z[MAX_NODES_IN_CURVE];
183.1311      int i, nItems, Zeros, Poles;
183.1312  
183.1313 +    if (Tab == NULL) return FALSE;
183.1314  
183.1315 -    if (cmsIsLinear(Tab->GammaTable, Tab->nEntries)) return FALSE; // Nothing to do
183.1316 +    if (cmsIsToneCurveLinear(Tab)) return FALSE; // Nothing to do
183.1317  
183.1318      nItems = Tab -> nEntries;
183.1319  
183.1320 -    if (nItems > MAX_KNOTS) {
183.1321 -                cmsSignalError(LCMS_ERRC_ABORTED, "cmsSmoothGamma: too many points.");
183.1322 -                return FALSE;
183.1323 -                }
183.1324 +    if (nItems >= MAX_NODES_IN_CURVE) {
183.1325 +        cmsSignalError(Tab ->InterpParams->ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: too many points.");
183.1326 +        return FALSE;
183.1327 +    }
183.1328  
183.1329 -    ZeroMemory(w, nItems * sizeof(float));
183.1330 -    ZeroMemory(y, nItems * sizeof(float));
183.1331 -    ZeroMemory(z, nItems * sizeof(float));
183.1332 +    memset(w, 0, nItems * sizeof(cmsFloat32Number));
183.1333 +    memset(y, 0, nItems * sizeof(cmsFloat32Number));
183.1334 +    memset(z, 0, nItems * sizeof(cmsFloat32Number));
183.1335  
183.1336      for (i=0; i < nItems; i++)
183.1337      {
183.1338 -        y[i+1] = (float) Tab -> GammaTable[i];
183.1339 +        y[i+1] = (cmsFloat32Number) Tab -> Table16[i];
183.1340          w[i+1] = 1.0;
183.1341      }
183.1342  
183.1343 -    smooth2(w, y, z, (float) lambda, nItems);
183.1344 +    if (!smooth2(Tab ->InterpParams->ContextID, w, y, z, (cmsFloat32Number) lambda, nItems)) return FALSE;
183.1345  
183.1346      // Do some reality - checking...
183.1347      Zeros = Poles = 0;
183.1348      for (i=nItems; i > 1; --i) {
183.1349  
183.1350 -            if (z[i] == 0.) Zeros++;
183.1351 -            if (z[i] >= 65535.) Poles++;
183.1352 -            if (z[i] < z[i-1]) return FALSE; // Non-Monotonic
183.1353 +        if (z[i] == 0.) Zeros++;
183.1354 +        if (z[i] >= 65535.) Poles++;
183.1355 +        if (z[i] < z[i-1]) return FALSE; // Non-Monotonic
183.1356      }
183.1357  
183.1358      if (Zeros > (nItems / 3)) return FALSE;  // Degenerated, mostly zeros
183.1359      if (Poles > (nItems / 3)) return FALSE;  // Degenerated, mostly poles
183.1360  
183.1361      // Seems ok
183.1362 -
183.1363      for (i=0; i < nItems; i++) {
183.1364  
183.1365 -        // Clamp to WORD
183.1366 -
183.1367 -        float v = z[i+1];
183.1368 -
183.1369 -        if (v < 0) v = 0;
183.1370 -        if (v > 65535.) v = 65535.;
183.1371 -
183.1372 -        Tab -> GammaTable[i] = (WORD) floor(v + .5);
183.1373 -        }
183.1374 +        // Clamp to cmsUInt16Number
183.1375 +        Tab -> Table16[i] = _cmsQuickSaturateWord(z[i+1]);
183.1376 +    }
183.1377  
183.1378      return TRUE;
183.1379  }
183.1380  
183.1381 +// Is a table linear? Do not use parametric since we cannot guarantee some weird parameters resulting
183.1382 +// in a linear table. This way assures it is linear in 12 bits, which should be enought in most cases.
183.1383 +cmsBool CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve)
183.1384 +{
183.1385 +    cmsUInt32Number i;
183.1386 +    int diff;
183.1387  
183.1388 -// Check if curve is exponential, return gamma if so.
183.1389 +    _cmsAssert(Curve != NULL);
183.1390  
183.1391 -double LCMSEXPORT cmsEstimateGammaEx(LPWORD GammaTable, int nEntries, double Thereshold)
183.1392 +    for (i=0; i < Curve ->nEntries; i++) {
183.1393 +
183.1394 +        diff = abs((int) Curve->Table16[i] - (int) _cmsQuantizeVal(i, Curve ->nEntries));
183.1395 +        if (diff > 0x0f)
183.1396 +            return FALSE;
183.1397 +    }
183.1398 +
183.1399 +    return TRUE;
183.1400 +}
183.1401 +
183.1402 +// Same, but for monotonicity
183.1403 +cmsBool  CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t)
183.1404  {
183.1405 -    double gamma, sum, sum2;
183.1406 -    double n, x, y, Std;
183.1407 -    int i;
183.1408 +    int n;
183.1409 +    int i, last;
183.1410 +
183.1411 +    _cmsAssert(t != NULL);
183.1412 +
183.1413 +    n    = t ->nEntries;
183.1414 +    last = t ->Table16[n-1];
183.1415 +
183.1416 +    for (i = n-2; i >= 0; --i) {
183.1417 +
183.1418 +        if (t ->Table16[i] > last)
183.1419 +
183.1420 +            return FALSE;
183.1421 +        else
183.1422 +            last = t ->Table16[i];
183.1423 +
183.1424 +    }
183.1425 +
183.1426 +    return TRUE;
183.1427 +}
183.1428 +
183.1429 +// Same, but for descending tables
183.1430 +cmsBool  CMSEXPORT cmsIsToneCurveDescending(const cmsToneCurve* t)
183.1431 +{
183.1432 +    _cmsAssert(t != NULL);
183.1433 +
183.1434 +    return t ->Table16[0] > t ->Table16[t ->nEntries-1];
183.1435 +}
183.1436 +
183.1437 +
183.1438 +// Another info fn: is out gamma table multisegment?
183.1439 +cmsBool  CMSEXPORT cmsIsToneCurveMultisegment(const cmsToneCurve* t)
183.1440 +{
183.1441 +    _cmsAssert(t != NULL);
183.1442 +
183.1443 +    return t -> nSegments > 1;
183.1444 +}
183.1445 +
183.1446 +cmsInt32Number  CMSEXPORT cmsGetToneCurveParametricType(const cmsToneCurve* t)
183.1447 +{
183.1448 +    _cmsAssert(t != NULL);
183.1449 +
183.1450 +    if (t -> nSegments != 1) return 0;
183.1451 +    return t ->Segments[0].Type;
183.1452 +}
183.1453 +
183.1454 +// We need accuracy this time
183.1455 +cmsFloat32Number CMSEXPORT cmsEvalToneCurveFloat(const cmsToneCurve* Curve, cmsFloat32Number v)
183.1456 +{
183.1457 +    _cmsAssert(Curve != NULL);
183.1458 +
183.1459 +    // Check for 16 bits table. If so, this is a limited-precision tone curve
183.1460 +    if (Curve ->nSegments == 0) {
183.1461 +
183.1462 +        cmsUInt16Number In, Out;
183.1463 +
183.1464 +        In = (cmsUInt16Number) _cmsQuickSaturateWord(v * 65535.0);
183.1465 +        Out = cmsEvalToneCurve16(Curve, In);
183.1466 +
183.1467 +        return (cmsFloat32Number) (Out / 65535.0);
183.1468 +    }
183.1469 +
183.1470 +    return (cmsFloat32Number) EvalSegmentedFn(Curve, v);
183.1471 +}
183.1472 +
183.1473 +// We need xput over here
183.1474 +cmsUInt16Number CMSEXPORT cmsEvalToneCurve16(const cmsToneCurve* Curve, cmsUInt16Number v)
183.1475 +{
183.1476 +    cmsUInt16Number out;
183.1477 +
183.1478 +    _cmsAssert(Curve != NULL);
183.1479 +
183.1480 +    Curve ->InterpParams ->Interpolation.Lerp16(&v, &out, Curve ->InterpParams);
183.1481 +    return out;
183.1482 +}
183.1483 +
183.1484 +
183.1485 +// Least squares fitting.
183.1486 +// A mathematical procedure for finding the best-fitting curve to a given set of points by
183.1487 +// minimizing the sum of the squares of the offsets ("the residuals") of the points from the curve.
183.1488 +// The sum of the squares of the offsets is used instead of the offset absolute values because
183.1489 +// this allows the residuals to be treated as a continuous differentiable quantity.
183.1490 +//
183.1491 +// y = f(x) = x ^ g
183.1492 +//
183.1493 +// R  = (yi - (xi^g))
183.1494 +// R2 = (yi - (xi^g))2
183.1495 +// SUM R2 = SUM (yi - (xi^g))2
183.1496 +//
183.1497 +// dR2/dg = -2 SUM x^g log(x)(y - x^g)
183.1498 +// solving for dR2/dg = 0
183.1499 +//
183.1500 +// g = 1/n * SUM(log(y) / log(x))
183.1501 +
183.1502 +cmsFloat64Number CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Number Precision)
183.1503 +{
183.1504 +    cmsFloat64Number gamma, sum, sum2;
183.1505 +    cmsFloat64Number n, x, y, Std;
183.1506 +    cmsUInt32Number i;
183.1507 +
183.1508 +    _cmsAssert(t != NULL);
183.1509  
183.1510      sum = sum2 = n = 0;
183.1511  
183.1512 -    // Does exclude endpoints
183.1513 -    for (i=1; i < nEntries - 1; i++) {
183.1514 +    // Excluding endpoints
183.1515 +    for (i=1; i < (MAX_NODES_IN_CURVE-1); i++) {
183.1516  
183.1517 -            x = (double) i / (nEntries - 1);
183.1518 -            y = (double) GammaTable[i] / 65535.;
183.1519 +        x = (cmsFloat64Number) i / (MAX_NODES_IN_CURVE-1);
183.1520 +        y = (cmsFloat64Number) cmsEvalToneCurveFloat(t, (cmsFloat32Number) x);
183.1521  
183.1522 -            // Avoid 7% on lower part to prevent
183.1523 -            // artifacts due to linear ramps
183.1524 +        // Avoid 7% on lower part to prevent
183.1525 +        // artifacts due to linear ramps
183.1526  
183.1527 -            if (y > 0. && y < 1. && x > 0.07) {
183.1528 +        if (y > 0. && y < 1. && x > 0.07) {
183.1529  
183.1530              gamma = log(y) / log(x);
183.1531              sum  += gamma;
183.1532              sum2 += gamma * gamma;
183.1533              n++;
183.1534 -            }
183.1535 -
183.1536 +        }
183.1537      }
183.1538  
183.1539      // Take a look on SD to see if gamma isn't exponential at all
183.1540      Std = sqrt((n * sum2 - sum * sum) / (n*(n-1)));
183.1541  
183.1542 -
183.1543 -    if (Std > Thereshold)
183.1544 +    if (Std > Precision)
183.1545          return -1.0;
183.1546  
183.1547      return (sum / n);   // The mean
183.1548  }
183.1549  
183.1550 -
183.1551 -double LCMSEXPORT cmsEstimateGamma(LPGAMMATABLE t)
183.1552 -{
183.1553 -        return cmsEstimateGammaEx(t->GammaTable, t->nEntries, 0.7);
183.1554 -}
183.1555 -
183.1556 -
183.1557 -// -----------------------------------------------------------------Sampled curves
183.1558 -
183.1559 -// Allocate a empty curve
183.1560 -
183.1561 -LPSAMPLEDCURVE cmsAllocSampledCurve(int nItems)
183.1562 -{
183.1563 -    LPSAMPLEDCURVE pOut;
183.1564 -
183.1565 -    pOut = (LPSAMPLEDCURVE) _cmsMalloc(sizeof(SAMPLEDCURVE));
183.1566 -    if (pOut == NULL)
183.1567 -            return NULL;
183.1568 -
183.1569 -    if((pOut->Values = (double *) _cmsMalloc(nItems * sizeof(double))) == NULL)
183.1570 -    {
183.1571 -         _cmsFree(pOut);
183.1572 -        return NULL;
183.1573 -    }
183.1574 -
183.1575 -    pOut->nItems = nItems;
183.1576 -    ZeroMemory(pOut->Values, nItems * sizeof(double));
183.1577 -
183.1578 -    return pOut;
183.1579 -}
183.1580 -
183.1581 -
183.1582 -void cmsFreeSampledCurve(LPSAMPLEDCURVE p)
183.1583 -{
183.1584 -     _cmsFree((LPVOID) p -> Values);
183.1585 -     _cmsFree((LPVOID) p);
183.1586 -}
183.1587 -
183.1588 -
183.1589 -
183.1590 -// Does duplicate a sampled curve
183.1591 -
183.1592 -LPSAMPLEDCURVE cmsDupSampledCurve(LPSAMPLEDCURVE p)
183.1593 -{
183.1594 -    LPSAMPLEDCURVE out;
183.1595 -
183.1596 -    out = cmsAllocSampledCurve(p -> nItems);
183.1597 -    if (!out) return NULL;
183.1598 -
183.1599 -    CopyMemory(out ->Values, p ->Values, p->nItems * sizeof(double));
183.1600 -
183.1601 -    return out;
183.1602 -}
183.1603 -
183.1604 -
183.1605 -// Take min, max of curve
183.1606 -
183.1607 -void cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max)
183.1608 -{
183.1609 -        int i;
183.1610 -
183.1611 -        *Min = 65536.;
183.1612 -        *Max = 0.;
183.1613 -
183.1614 -        for (i=0; i < p -> nItems; i++) {
183.1615 -
183.1616 -                double v = p -> Values[i];
183.1617 -
183.1618 -                if (v < *Min)
183.1619 -                        *Min = v;
183.1620 -
183.1621 -                if (v > *Max)
183.1622 -                        *Max = v;
183.1623 -        }
183.1624 -
183.1625 -        if (*Min < 0) *Min = 0;
183.1626 -        if (*Max > 65535.0) *Max = 65535.0;
183.1627 -}
183.1628 -
183.1629 -// Clamps to Min, Max
183.1630 -
183.1631 -void cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max)
183.1632 -{
183.1633 -
183.1634 -        int i;
183.1635 -
183.1636 -        for (i=0; i < p -> nItems; i++) {
183.1637 -
183.1638 -                double v = p -> Values[i];
183.1639 -
183.1640 -                if (v < Min)
183.1641 -                        v = Min;
183.1642 -
183.1643 -                if (v > Max)
183.1644 -                        v = Max;
183.1645 -
183.1646 -                p -> Values[i] = v;
183.1647 -
183.1648 -        }
183.1649 -
183.1650 -}
183.1651 -
183.1652 -
183.1653 -
183.1654 -// Smooths a curve sampled at regular intervals
183.1655 -
183.1656 -LCMSBOOL cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double lambda)
183.1657 -{
183.1658 -    vec w, y, z;
183.1659 -    int i, nItems;
183.1660 -
183.1661 -    nItems = Tab -> nItems;
183.1662 -
183.1663 -    if (nItems > MAX_KNOTS) {
183.1664 -                cmsSignalError(LCMS_ERRC_ABORTED, "cmsSmoothSampledCurve: too many points.");
183.1665 -                return FALSE;
183.1666 -                }
183.1667 -
183.1668 -    ZeroMemory(w, nItems * sizeof(float));
183.1669 -    ZeroMemory(y, nItems * sizeof(float));
183.1670 -    ZeroMemory(z, nItems * sizeof(float));
183.1671 -
183.1672 -    for (i=0; i < nItems; i++)
183.1673 -    {
183.1674 -        float value = (float) Tab -> Values[i];
183.1675 -
183.1676 -        y[i+1] = value;
183.1677 -        w[i+1] = (float) ((value < 0.0) ?  0 : 1);
183.1678 -    }
183.1679 -
183.1680 -
183.1681 -    smooth2(w, y, z, (float) lambda, nItems);
183.1682 -
183.1683 -    for (i=0; i < nItems; i++) {
183.1684 -
183.1685 -        Tab -> Values[i] = z[i+1];;
183.1686 -     }
183.1687 -
183.1688 -    return TRUE;
183.1689 -
183.1690 -}
183.1691 -
183.1692 -
183.1693 -// Scale a value v, within domain Min .. Max
183.1694 -// to a domain 0..(nPoints-1)
183.1695 -
183.1696 -static
183.1697 -double ScaleVal(double v, double Min, double Max, int nPoints)
183.1698 -{
183.1699 -
183.1700 -        double a, b;
183.1701 -
183.1702 -        if (v <= Min) return 0;
183.1703 -        if (v >= Max) return (nPoints-1);
183.1704 -
183.1705 -        a = (double) (nPoints - 1) / (Max - Min);
183.1706 -        b = a * Min;
183.1707 -
183.1708 -        return (a * v) - b;
183.1709 -
183.1710 -}
183.1711 -
183.1712 -
183.1713 -// Does rescale a sampled curve to fit in a 0..(nPoints-1) domain
183.1714 -
183.1715 -void cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints)
183.1716 -{
183.1717 -
183.1718 -        int i;
183.1719 -
183.1720 -        for (i=0; i < p -> nItems; i++) {
183.1721 -
183.1722 -                double v = p -> Values[i];
183.1723 -
183.1724 -                p -> Values[i] = ScaleVal(v, Min, Max, nPoints);
183.1725 -        }
183.1726 -
183.1727 -}
183.1728 -
183.1729 -
183.1730 -// Joins two sampled curves for X and Y. Curves should be sorted.
183.1731 -
183.1732 -LPSAMPLEDCURVE cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints)
183.1733 -{
183.1734 -    int i, j;
183.1735 -    LPSAMPLEDCURVE out;
183.1736 -    double MinX, MinY, MaxX, MaxY;
183.1737 -    double x, y, x1, y1, x2, y2, a, b;
183.1738 -
183.1739 -    out = cmsAllocSampledCurve(nResultingPoints);
183.1740 -    if (out == NULL)
183.1741 -        return NULL;
183.1742 -
183.1743 -    if (X -> nItems != Y -> nItems) {
183.1744 -
183.1745 -        cmsSignalError(LCMS_ERRC_ABORTED, "cmsJoinSampledCurves: invalid curve.");
183.1746 -        cmsFreeSampledCurve(out);
183.1747 -        return NULL;
183.1748 -    }
183.1749 -
183.1750 -    // Get endpoints of sampled curves
183.1751 -    cmsEndpointsOfSampledCurve(X, &MinX, &MaxX);
183.1752 -    cmsEndpointsOfSampledCurve(Y, &MinY, &MaxY);
183.1753 -
183.1754 -
183.1755 -    // Set our points
183.1756 -    out ->Values[0] = MinY;
183.1757 -    for (i=1; i < nResultingPoints; i++) {
183.1758 -
183.1759 -        // Scale t to x domain
183.1760 -        x = (i * (MaxX - MinX) / (nResultingPoints-1)) + MinX;
183.1761 -
183.1762 -        // Find interval in which j is within (always up,
183.1763 -        // since fn should be monotonic at all)
183.1764 -
183.1765 -        j = 1;
183.1766 -        while ((j < X ->nItems - 1) && X ->Values[j] < x)
183.1767 -            j++;
183.1768 -
183.1769 -        // Now x is within X[j-1], X[j]
183.1770 -        x1 = X ->Values[j-1]; x2 = X ->Values[j];
183.1771 -        y1 = Y ->Values[j-1]; y2 = Y ->Values[j];
183.1772 -
183.1773 -        // Interpolate  the value
183.1774 -        a = (y1 - y2) / (x1 - x2);
183.1775 -        b = y1 - a * x1;
183.1776 -        y = a* x + b;
183.1777 -
183.1778 -        out ->Values[i] = y;
183.1779 -    }
183.1780 -
183.1781 -
183.1782 -    cmsClampSampledCurve(out, MinY, MaxY);
183.1783 -    return out;
183.1784 -}
183.1785 -
183.1786 -
183.1787 -
183.1788 -// Convert between curve types
183.1789 -
183.1790 -LPGAMMATABLE cmsConvertSampledCurveToGamma(LPSAMPLEDCURVE Sampled, double Max)
183.1791 -{
183.1792 -    LPGAMMATABLE Gamma;
183.1793 -    int i, nPoints;
183.1794 -
183.1795 -
183.1796 -    nPoints = Sampled ->nItems;
183.1797 -
183.1798 -    Gamma = cmsAllocGamma(nPoints);
183.1799 -    for (i=0; i < nPoints; i++) {
183.1800 -
183.1801 -        Gamma->GammaTable[i] = (WORD) floor(ScaleVal(Sampled ->Values[i], 0, Max, 65536) + .5);
183.1802 -    }
183.1803 -
183.1804 -    return Gamma;
183.1805 -
183.1806 -}
183.1807 -
183.1808 -// Inverse of anterior
183.1809 -
183.1810 -LPSAMPLEDCURVE cmsConvertGammaToSampledCurve(LPGAMMATABLE Gamma, int nPoints)
183.1811 -{
183.1812 -    LPSAMPLEDCURVE Sampled;
183.1813 -    L16PARAMS L16;
183.1814 -    int i;
183.1815 -    WORD wQuant, wValIn;
183.1816 -
183.1817 -    if (nPoints > 4096) {
183.1818 -
183.1819 -        cmsSignalError(LCMS_ERRC_ABORTED, "cmsConvertGammaToSampledCurve: too many points (max=4096)");
183.1820 -        return NULL;
183.1821 -    }
183.1822 -
183.1823 -    cmsCalcL16Params(Gamma -> nEntries, &L16);
183.1824 -
183.1825 -    Sampled = cmsAllocSampledCurve(nPoints);
183.1826 -    for (i=0; i < nPoints; i++) {
183.1827 -            wQuant  = _cmsQuantizeVal(i, nPoints);
183.1828 -            wValIn  = cmsLinearInterpLUT16(wQuant, Gamma ->GammaTable, &L16);
183.1829 -            Sampled ->Values[i] = (float) wValIn;
183.1830 -    }
183.1831 -
183.1832 -    return Sampled;
183.1833 -}
183.1834 -
183.1835 -
183.1836 -
183.1837 -
183.1838 -// Smooth endpoints (used in Black/White compensation)
183.1839 -
183.1840 -LCMSBOOL _cmsSmoothEndpoints(LPWORD Table, int nEntries)
183.1841 -{
183.1842 -    vec w, y, z;
183.1843 -    int i, Zeros, Poles;
183.1844 -
183.1845 -
183.1846 -
183.1847 -    if (cmsIsLinear(Table, nEntries)) return FALSE; // Nothing to do
183.1848 -
183.1849 -
183.1850 -    if (nEntries > MAX_KNOTS) {
183.1851 -                cmsSignalError(LCMS_ERRC_ABORTED, "_cmsSmoothEndpoints: too many points.");
183.1852 -                return FALSE;
183.1853 -                }
183.1854 -
183.1855 -    ZeroMemory(w, nEntries * sizeof(float));
183.1856 -    ZeroMemory(y, nEntries * sizeof(float));
183.1857 -    ZeroMemory(z, nEntries * sizeof(float));
183.1858 -
183.1859 -    for (i=0; i < nEntries; i++)
183.1860 -    {
183.1861 -        y[i+1] = (float) Table[i];
183.1862 -        w[i+1] = 1.0;
183.1863 -    }
183.1864 -
183.1865 -    w[1]        = 65535.0;
183.1866 -    w[nEntries] = 65535.0;
183.1867 -
183.1868 -    smooth2(w, y, z, (float) nEntries, nEntries);
183.1869 -
183.1870 -    // Do some reality - checking...
183.1871 -    Zeros = Poles = 0;
183.1872 -    for (i=nEntries; i > 1; --i) {
183.1873 -
183.1874 -            if (z[i] == 0.) Zeros++;
183.1875 -            if (z[i] >= 65535.) Poles++;
183.1876 -            if (z[i] < z[i-1]) return FALSE; // Non-Monotonic
183.1877 -    }
183.1878 -
183.1879 -    if (Zeros > (nEntries / 3)) return FALSE;  // Degenerated, mostly zeros
183.1880 -    if (Poles > (nEntries / 3)) return FALSE;    // Degenerated, mostly poles
183.1881 -
183.1882 -    // Seems ok
183.1883 -
183.1884 -    for (i=0; i < nEntries; i++) {
183.1885 -
183.1886 -        // Clamp to WORD
183.1887 -
183.1888 -        float v = z[i+1];
183.1889 -
183.1890 -        if (v < 0) v = 0;
183.1891 -        if (v > 65535.) v = 65535.;
183.1892 -
183.1893 -        Table[i] = (WORD) floor(v + .5);
183.1894 -        }
183.1895 -
183.1896 -    return TRUE;
183.1897 -}
   184.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c	Thu Sep 23 17:33:40 2010 -0700
   184.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsgmt.c	Fri Sep 24 16:41:32 2010 -0700
   184.3 @@ -27,9 +27,10 @@
   184.4  // However, the following notice accompanied the original version of this
   184.5  // file:
   184.6  //
   184.7 +//---------------------------------------------------------------------------------
   184.8  //
   184.9 -//  Little cms
  184.10 -//  Copyright (C) 1998-2007 Marti Maria
  184.11 +//  Little Color Management System
  184.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  184.13  //
  184.14  // Permission is hereby granted, free of charge, to any person obtaining
  184.15  // a copy of this software and associated documentation files (the "Software"),
  184.16 @@ -48,871 +49,383 @@
  184.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  184.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  184.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  184.20 +//
  184.21 +//---------------------------------------------------------------------------------
  184.22 +//
  184.23  
  184.24 +#include "lcms2_internal.h"
  184.25  
  184.26 -#include "lcms.h"
  184.27  
  184.28 -/*
  184.29 -Gamut check by default is a catching of 0xFFFF/0xFFFF/0xFFFF PCS values, used
  184.30 -internally by lcms to hold invalid values. Matrix LUT's, operates in a way that
  184.31 -unencodeable values are marked as this combination, if PCS is XYZ, this is a very
  184.32 -high value since encoding is a 1.15 fixed point, something like 1.9997, 1.9997, 1.9997
  184.33 -not a very common color after all. Lab PCS is not to be a problem, since L>100 are truely
  184.34 -undefined. There is a posibility than ICC comitee defines L>100 as a valid means
  184.35 -to use highlights, then it will be lost.
  184.36 +// Auxiliar: append a Lab identity after the given sequence of profiles
  184.37 +// and return the transform. Lab profile is closed, rest of profiles are kept open.
  184.38 +cmsHTRANSFORM _cmsChain2Lab(cmsContext            ContextID,
  184.39 +                            cmsUInt32Number        nProfiles,
  184.40 +                            cmsUInt32Number        InputFormat,
  184.41 +                            cmsUInt32Number        OutputFormat,
  184.42 +                            const cmsUInt32Number  Intents[],
  184.43 +                            const cmsHPROFILE      hProfiles[],
  184.44 +                            const cmsBool          BPC[],
  184.45 +                            const cmsFloat64Number AdaptationStates[],
  184.46 +                            cmsUInt32Number        dwFlags)
  184.47 +{
  184.48 +    cmsHTRANSFORM xform;
  184.49 +    cmsHPROFILE   hLab;
  184.50 +    cmsHPROFILE   ProfileList[256];
  184.51 +    cmsBool       BPCList[256];
  184.52 +    cmsFloat64Number AdaptationList[256];
  184.53 +    cmsUInt32Number IntentList[256];
  184.54 +    cmsUInt32Number i;
  184.55  
  184.56 -(1.10 - Actually ICC did it, so this should be checked for full ICC 4.0 support)
  184.57 +    // This is a rather big number and there is no need of dynamic memory
  184.58 +    // since we are adding a profile, 254 + 1 = 255 and this is the limit
  184.59 +    if (nProfiles > 254) return NULL;
  184.60  
  184.61 -*/
  184.62 +    // The output space
  184.63 +    hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
  184.64 +    if (hLab == NULL) return NULL;
  184.65  
  184.66 +    // Create a copy of parameters
  184.67 +    for (i=0; i < nProfiles; i++) {
  184.68  
  184.69 -LCMSBOOL _cmsEndPointsBySpace(icColorSpaceSignature Space, WORD **White, WORD **Black,
  184.70 -                            int *nOutputs)
  184.71 -{
  184.72 -       // Only most common spaces
  184.73 +        ProfileList[i]    = hProfiles[i];
  184.74 +        BPCList[i]        = BPC[i];
  184.75 +        AdaptationList[i] = AdaptationStates[i];
  184.76 +        IntentList[i]     = Intents[i];
  184.77 +    }
  184.78  
  184.79 -       static WORD RGBblack[4]  = { 0, 0, 0 };
  184.80 -       static WORD RGBwhite[4]  = { 0xffff, 0xffff, 0xffff };
  184.81 -       static WORD CMYKblack[4] = { 0xffff, 0xffff, 0xffff, 0xffff };   // 400% of ink
  184.82 -       static WORD CMYKwhite[4] = { 0, 0, 0, 0 };
  184.83 -       static WORD LABblack[4]  = { 0, 0x8000, 0x8000 };
  184.84 -       static WORD LABwhite[4]  = { 0xFF00, 0x8000, 0x8000 };
  184.85 -       static WORD CMYblack[4]  = { 0xffff, 0xffff, 0xffff };
  184.86 -       static WORD CMYwhite[4]  = { 0, 0, 0 };
  184.87 -       static WORD Grayblack[4] = { 0 };
  184.88 -       static WORD GrayWhite[4] = { 0xffff };
  184.89 +    // Place Lab identity at chain's end.
  184.90 +    ProfileList[nProfiles]    = hLab;
  184.91 +    BPCList[nProfiles]        = 0;
  184.92 +    AdaptationList[nProfiles] = 1.0;
  184.93 +    IntentList[nProfiles]     = INTENT_RELATIVE_COLORIMETRIC;
  184.94  
  184.95 -       switch (Space) {
  184.96 +    // Create the transform
  184.97 +    xform = cmsCreateExtendedTransform(ContextID, nProfiles + 1, ProfileList,
  184.98 +                                       BPCList,
  184.99 +                                       IntentList,
 184.100 +                                       AdaptationList,
 184.101 +                                       NULL, 0,
 184.102 +                                       InputFormat,
 184.103 +                                       OutputFormat,
 184.104 +                                       dwFlags);
 184.105  
 184.106 -       case icSigGrayData: if (White)    *White = GrayWhite;
 184.107 -                           if (Black)    *Black = Grayblack;
 184.108 -                           if (nOutputs) *nOutputs = 1;
 184.109 -                           return TRUE;
 184.110 +    cmsCloseProfile(hLab);
 184.111  
 184.112 -       case icSigRgbData:  if (White)    *White = RGBwhite;
 184.113 -                           if (Black)    *Black = RGBblack;
 184.114 -                           if (nOutputs) *nOutputs = 3;
 184.115 -                           return TRUE;
 184.116 -
 184.117 -       case icSigLabData:  if (White)    *White = LABwhite;
 184.118 -                           if (Black)    *Black = LABblack;
 184.119 -                           if (nOutputs) *nOutputs = 3;
 184.120 -                           return TRUE;
 184.121 -
 184.122 -       case icSigCmykData: if (White)    *White = CMYKwhite;
 184.123 -                           if (Black)    *Black = CMYKblack;
 184.124 -                           if (nOutputs) *nOutputs = 4;
 184.125 -                           return TRUE;
 184.126 -
 184.127 -       case icSigCmyData:  if (White)    *White = CMYwhite;
 184.128 -                           if (Black)    *Black = CMYblack;
 184.129 -                           if (nOutputs) *nOutputs = 3;
 184.130 -                           return TRUE;
 184.131 -
 184.132 -       default:;
 184.133 -       }
 184.134 -
 184.135 -  return FALSE;
 184.136 +    return xform;
 184.137  }
 184.138  
 184.139  
 184.140 -WORD *_cmsWhiteBySpace(icColorSpaceSignature Space)
 184.141 +// Compute K -> L* relationship. Flags may include black point compensation. In this case,
 184.142 +// the relationship is assumed from the profile with BPC to a black point zero.
 184.143 +static
 184.144 +cmsToneCurve* ComputeKToLstar(cmsContext            ContextID,
 184.145 +                               cmsUInt32Number       nPoints,
 184.146 +                               cmsUInt32Number       nProfiles,
 184.147 +                               const cmsUInt32Number Intents[],
 184.148 +                               const cmsHPROFILE     hProfiles[],
 184.149 +                               const cmsBool         BPC[],
 184.150 +                               const cmsFloat64Number AdaptationStates[],
 184.151 +                               cmsUInt32Number dwFlags)
 184.152  {
 184.153 -       WORD *White= NULL, *Black = NULL;
 184.154 -       int Dummy;
 184.155 -       static WORD Default[MAXCHANNELS];
 184.156 +    cmsToneCurve* out = NULL;
 184.157 +    cmsUInt32Number i;
 184.158 +    cmsHTRANSFORM xform;
 184.159 +    cmsCIELab Lab;
 184.160 +    cmsFloat32Number cmyk[4];
 184.161 +    cmsFloat32Number* SampledPoints;
 184.162  
 184.163 -       if (_cmsEndPointsBySpace(Space, &White, &Black, &Dummy))
 184.164 -              return White;
 184.165 +    xform = _cmsChain2Lab(ContextID, nProfiles, TYPE_CMYK_FLT, TYPE_Lab_DBL, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
 184.166 +    if (xform == NULL) return NULL;
 184.167  
 184.168 -       return Default;
 184.169 +    SampledPoints = (cmsFloat32Number*) _cmsCalloc(ContextID, nPoints, sizeof(cmsFloat32Number));
 184.170 +    if (SampledPoints  == NULL) goto Error;
 184.171  
 184.172 +    for (i=0; i < nPoints; i++) {
 184.173 +
 184.174 +        cmyk[0] = 0;
 184.175 +        cmyk[1] = 0;
 184.176 +        cmyk[2] = 0;
 184.177 +        cmyk[3] = (cmsFloat32Number) ((i * 100.0) / (nPoints-1));
 184.178 +
 184.179 +        cmsDoTransform(xform, cmyk, &Lab, 1);
 184.180 +        SampledPoints[i]= (cmsFloat32Number) (1.0 - Lab.L / 100.0); // Negate K for easier operation
 184.181 +    }
 184.182 +
 184.183 +    out = cmsBuildTabulatedToneCurveFloat(ContextID, nPoints, SampledPoints);
 184.184 +
 184.185 +Error:
 184.186 +
 184.187 +    cmsDeleteTransform(xform);
 184.188 +    if (SampledPoints) _cmsFree(ContextID, SampledPoints);
 184.189 +
 184.190 +    return out;
 184.191  }
 184.192  
 184.193  
 184.194 +// Compute Black tone curve on a CMYK -> CMYK transform. This is done by
 184.195 +// using the proof direction on both profiles to find K->L* relationship
 184.196 +// then joining both curves. dwFlags may include black point compensation.
 184.197 +cmsToneCurve* _cmsBuildKToneCurve(cmsContext        ContextID,
 184.198 +                                   cmsUInt32Number   nPoints,
 184.199 +                                   cmsUInt32Number   nProfiles,
 184.200 +                                   const cmsUInt32Number Intents[],
 184.201 +                                   const cmsHPROFILE hProfiles[],
 184.202 +                                   const cmsBool     BPC[],
 184.203 +                                   const cmsFloat64Number AdaptationStates[],
 184.204 +                                   cmsUInt32Number   dwFlags)
 184.205 +{
 184.206 +    cmsToneCurve *in, *out, *KTone;
 184.207  
 184.208 +    // Make sure CMYK -> CMYK
 184.209 +    if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
 184.210 +        cmsGetColorSpace(hProfiles[nProfiles-1])!= cmsSigCmykData) return NULL;
 184.211  
 184.212 -WORD Clamp_L(Fixed32 in)
 184.213 -{
 184.214 -       if (in == 0xFFFF) return 0xFFFFU;  // Marker
 184.215  
 184.216 -       if (in > 0xFF00) return 0xFF00U;  // L* = 100.0
 184.217 -       return (WORD) in;
 184.218 +    // Make sure last is an output profile
 184.219 +    if (cmsGetDeviceClass(hProfiles[nProfiles - 1]) != cmsSigOutputClass) return NULL;
 184.220 +
 184.221 +    // Create individual curves. BPC works also as each K to L* is
 184.222 +    // computed as a BPC to zero black point in case of L*
 184.223 +    in  = ComputeKToLstar(ContextID, nPoints, nProfiles - 1, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
 184.224 +    if (in == NULL) return NULL;
 184.225 +
 184.226 +    out = ComputeKToLstar(ContextID, nPoints, 1,
 184.227 +                            Intents + (nProfiles - 1),
 184.228 +                            hProfiles + (nProfiles - 1),
 184.229 +                            BPC + (nProfiles - 1),
 184.230 +                            AdaptationStates + (nProfiles - 1),
 184.231 +                            dwFlags);
 184.232 +    if (out == NULL) {
 184.233 +        cmsFreeToneCurve(in);
 184.234 +        return NULL;
 184.235 +    }
 184.236 +
 184.237 +    // Build the relationship. This effectively limits the maximum accuracy to 16 bits, but
 184.238 +    // since this is used on black-preserving LUTs, we are not loosing  accuracy in any case
 184.239 +    KTone = cmsJoinToneCurve(ContextID, in, out, nPoints);
 184.240 +
 184.241 +    // Get rid of components
 184.242 +    cmsFreeToneCurve(in); cmsFreeToneCurve(out);
 184.243 +
 184.244 +    // Something went wrong...
 184.245 +    if (KTone == NULL) return NULL;
 184.246 +
 184.247 +    // Make sure it is monotonic
 184.248 +    if (!cmsIsToneCurveMonotonic(KTone)) {
 184.249 +
 184.250 +        cmsFreeToneCurve(KTone);
 184.251 +        return NULL;
 184.252 +    }
 184.253 +
 184.254 +    return KTone;
 184.255  }
 184.256  
 184.257  
 184.258 -#define ENCODE_AB(x) (WORD) (((x) + 128.0) * 256.0 + 0.5)
 184.259 -
 184.260 -WORD Clamp_ab(Fixed32 in)
 184.261 -{
 184.262 -       if (in == 0xFFFF) return 0xFFFFU;             // Marker
 184.263 -
 184.264 -       if (in < 0) return ENCODE_AB(-128.0);         // Max negative number
 184.265 -       if (in > 0xFFFF) return ENCODE_AB(+127.9961); // Max positive number
 184.266 -       return (WORD) in;
 184.267 -}
 184.268 -
 184.269 -
 184.270 -
 184.271 -// Returns dE on two Lab values
 184.272 -
 184.273 -double LCMSEXPORT cmsDeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2)
 184.274 -{
 184.275 -        double dL, da, db;
 184.276 -
 184.277 -        if (Lab1 -> L < 0 ||
 184.278 -            Lab2 -> L < 0) return 65536.;
 184.279 -
 184.280 -        if (Lab1 -> a < -200 || Lab1 -> a > 200) return 65536.;
 184.281 -        if (Lab1 -> b < -200 || Lab1 -> b > 200) return 65536.;
 184.282 -
 184.283 -        if (Lab2 -> a < -200 || Lab2 -> a > 200) return 65536.;
 184.284 -        if (Lab2 -> b < -200 || Lab2 -> b > 200) return 65536.;
 184.285 -
 184.286 -        if (Lab1 ->L == 0 && Lab2 ->L == 0) return 0;
 184.287 -
 184.288 -        dL = fabs(Lab1 -> L - Lab2 -> L);
 184.289 -        da = fabs(Lab1 -> a - Lab2 -> a);
 184.290 -        db = fabs(Lab1 -> b - Lab2 -> b);
 184.291 -
 184.292 -        return pow(dL*dL + da * da + db * db, 0.5);
 184.293 -
 184.294 -}
 184.295 -
 184.296 -
 184.297 -// Square
 184.298 -static
 184.299 -double Sqr(double v)
 184.300 -{
 184.301 -    return v *  v;
 184.302 -}
 184.303 -
 184.304 -// Return the CIE94 Delta E
 184.305 -double LCMSEXPORT cmsCIE94DeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2)
 184.306 -{
 184.307 -    cmsCIELCh LCh1, LCh2;
 184.308 -    double dE, dL, dC, dh, dhsq;
 184.309 -    double c12, sc, sh;
 184.310 -
 184.311 -    if (Lab1 ->L == 0 && Lab2 ->L == 0) return 0;
 184.312 -
 184.313 -    dL = fabs(Lab1 ->L - Lab2 ->L);
 184.314 -
 184.315 -    cmsLab2LCh(&LCh1, Lab1);
 184.316 -    cmsLab2LCh(&LCh2, Lab2);
 184.317 -
 184.318 -    dC  = fabs(LCh1.C - LCh2.C);
 184.319 -    dE  = cmsDeltaE(Lab1, Lab2);
 184.320 -
 184.321 -    dhsq = Sqr(dE) - Sqr(dL) - Sqr(dC);
 184.322 -    if (dhsq < 0)
 184.323 -        dh = 0;
 184.324 -    else
 184.325 -        dh = pow(dhsq, 0.5);
 184.326 -
 184.327 -    c12 = sqrt(LCh1.C * LCh2.C);
 184.328 -
 184.329 -    sc = 1.0 + (0.048 * c12);
 184.330 -    sh = 1.0 + (0.014 * c12);
 184.331 -
 184.332 -    return sqrt(Sqr(dL)  + Sqr(dC) / Sqr(sc) + Sqr(dh) / Sqr(sh));
 184.333 -}
 184.334 -
 184.335 -
 184.336 -// Auxiliary
 184.337 -
 184.338 -static
 184.339 -double ComputeLBFD(LPcmsCIELab Lab)
 184.340 -{
 184.341 -  double yt;
 184.342 -
 184.343 -  if (Lab->L > 7.996969)
 184.344 -        yt = (Sqr((Lab->L+16)/116)*((Lab->L+16)/116))*100;
 184.345 -  else
 184.346 -        yt = 100 * (Lab->L / 903.3);
 184.347 -
 184.348 -  return (54.6 * (LOGE * (log(yt + 1.5))) - 9.6);
 184.349 -}
 184.350 -
 184.351 -
 184.352 -
 184.353 -// bfd - gets BFD(1:1) difference between Lab1, Lab2
 184.354 -double LCMSEXPORT cmsBFDdeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2)
 184.355 -{
 184.356 -    double lbfd1,lbfd2,AveC,Aveh,dE,deltaL,
 184.357 -        deltaC,deltah,dc,t,g,dh,rh,rc,rt,bfd;
 184.358 -    cmsCIELCh LCh1, LCh2;
 184.359 -
 184.360 -
 184.361 -    if (Lab1 ->L == 0 && Lab2 ->L == 0) return 0;
 184.362 -
 184.363 -    lbfd1 = ComputeLBFD(Lab1);
 184.364 -    lbfd2 = ComputeLBFD(Lab2);
 184.365 -    deltaL = lbfd2 - lbfd1;
 184.366 -
 184.367 -    cmsLab2LCh(&LCh1, Lab1);
 184.368 -    cmsLab2LCh(&LCh2, Lab2);
 184.369 -
 184.370 -    deltaC = LCh2.C - LCh1.C;
 184.371 -    AveC = (LCh1.C+LCh2.C)/2;
 184.372 -    Aveh = (LCh1.h+LCh2.h)/2;
 184.373 -
 184.374 -    dE = cmsDeltaE(Lab1, Lab2);
 184.375 -
 184.376 -    if (Sqr(dE)>(Sqr(Lab2->L-Lab1->L)+Sqr(deltaC)))
 184.377 -        deltah = sqrt(Sqr(dE)-Sqr(Lab2->L-Lab1->L)-Sqr(deltaC));
 184.378 -    else
 184.379 -        deltah =0;
 184.380 -
 184.381 -
 184.382 -    dc   = 0.035 * AveC / (1 + 0.00365 * AveC)+0.521;
 184.383 -    g    = sqrt(Sqr(Sqr(AveC))/(Sqr(Sqr(AveC))+14000));
 184.384 -    t    = 0.627+(0.055*cos((Aveh-254)/(180/M_PI))-
 184.385 -        0.040*cos((2*Aveh-136)/(180/M_PI))+
 184.386 -        0.070*cos((3*Aveh-31)/(180/M_PI))+
 184.387 -        0.049*cos((4*Aveh+114)/(180/M_PI))-
 184.388 -        0.015*cos((5*Aveh-103)/(180/M_PI)));
 184.389 -
 184.390 -    dh    = dc*(g*t+1-g);
 184.391 -    rh    = -0.260*cos((Aveh-308)/(180/M_PI))-
 184.392 -        0.379*cos((2*Aveh-160)/(180/M_PI))-
 184.393 -        0.636*cos((3*Aveh+254)/(180/M_PI))+
 184.394 -        0.226*cos((4*Aveh+140)/(180/M_PI))-
 184.395 -        0.194*cos((5*Aveh+280)/(180/M_PI));
 184.396 -
 184.397 -    rc = sqrt((AveC*AveC*AveC*AveC*AveC*AveC)/((AveC*AveC*AveC*AveC*AveC*AveC)+70000000));
 184.398 -    rt = rh*rc;
 184.399 -
 184.400 -    bfd = sqrt(Sqr(deltaL)+Sqr(deltaC/dc)+Sqr(deltah/dh)+(rt*(deltaC/dc)*(deltah/dh)));
 184.401 -
 184.402 -    return bfd;
 184.403 -}
 184.404 -
 184.405 -
 184.406 -//  cmc - CMC(1:1) difference between Lab1, Lab2
 184.407 -double LCMSEXPORT cmsCMCdeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2)
 184.408 -{
 184.409 -  double dE,dL,dC,dh,sl,sc,sh,t,f,cmc;
 184.410 -  cmsCIELCh LCh1, LCh2;
 184.411 -
 184.412 -  if (Lab1 ->L == 0 && Lab2 ->L == 0) return 0;
 184.413 -
 184.414 -  cmsLab2LCh(&LCh1, Lab1);
 184.415 -  cmsLab2LCh(&LCh2, Lab2);
 184.416 -
 184.417 -
 184.418 -  dL = Lab2->L-Lab1->L;
 184.419 -  dC = LCh2.C-LCh1.C;
 184.420 -
 184.421 -  dE = cmsDeltaE(Lab1, Lab2);
 184.422 -  if (Sqr(dE)>(Sqr(dL)+Sqr(dC)))
 184.423 -            dh = sqrt(Sqr(dE)-Sqr(dL)-Sqr(dC));
 184.424 -  else
 184.425 -            dh =0;
 184.426 -
 184.427 -  if ((LCh1.h > 164) && (LCh1.h<345))
 184.428 -      t = 0.56 + fabs(0.2 * cos(((LCh1.h + 168)/(180/M_PI))));
 184.429 -  else
 184.430 -      t = 0.36 + fabs(0.4 * cos(((LCh1.h + 35 )/(180/M_PI))));
 184.431 -
 184.432 -   sc  = 0.0638   * LCh1.C / (1 + 0.0131  * LCh1.C) + 0.638;
 184.433 -   sl  = 0.040975 * Lab1->L /(1 + 0.01765 * Lab1->L);
 184.434 -
 184.435 -   if (Lab1->L<16)
 184.436 -         sl = 0.511;
 184.437 -
 184.438 -   f   = sqrt((LCh1.C * LCh1.C * LCh1.C * LCh1.C)/((LCh1.C * LCh1.C * LCh1.C * LCh1.C)+1900));
 184.439 -   sh  = sc*(t*f+1-f);
 184.440 -   cmc = sqrt(Sqr(dL/sl)+Sqr(dC/sc)+Sqr(dh/sh));
 184.441 -
 184.442 -   return cmc;
 184.443 -}
 184.444 -
 184.445 -
 184.446 -
 184.447 -static
 184.448 -double atan2deg(double b, double a)
 184.449 -{
 184.450 -   double h;
 184.451 -
 184.452 -   if (a == 0 && b == 0)
 184.453 -            h   = 0;
 184.454 -    else
 184.455 -            h = atan2(a, b);
 184.456 -
 184.457 -    h *= (180. / M_PI);
 184.458 -
 184.459 -    while (h > 360.)
 184.460 -        h -= 360.;
 184.461 -
 184.462 -    while ( h < 0)
 184.463 -        h += 360.;
 184.464 -
 184.465 -    return h;
 184.466 -
 184.467 -}
 184.468 -
 184.469 -
 184.470 -static
 184.471 -double RADIANES(double deg)
 184.472 -{
 184.473 -    return (deg * M_PI) / 180.;
 184.474 -}
 184.475 -
 184.476 -
 184.477 -// dE2000 The weightings KL, KC and KH can be modified to reflect the relative
 184.478 -// importance of lightness, chroma and hue in different industrial applications
 184.479 -
 184.480 -double LCMSEXPORT cmsCIE2000DeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2,
 184.481 -                                  double Kl, double Kc, double Kh)
 184.482 -{
 184.483 -    double L1  = Lab1->L;
 184.484 -    double a1  = Lab1->a;
 184.485 -    double b1  = Lab1->b;
 184.486 -    double C   = sqrt( Sqr(a1) + Sqr(b1) );
 184.487 -
 184.488 -    double Ls = Lab2 ->L;
 184.489 -    double as = Lab2 ->a;
 184.490 -    double bs = Lab2 ->b;
 184.491 -    double Cs = sqrt( Sqr(as) + Sqr(bs) );
 184.492 -
 184.493 -    double G = 0.5 * ( 1 - sqrt(pow((C + Cs) / 2 , 7.0) / (pow((C + Cs) / 2, 7.0) + pow(25.0, 7.0) ) ));
 184.494 -
 184.495 -    double a_p = (1 + G ) * a1;
 184.496 -    double b_p = b1;
 184.497 -    double C_p = sqrt( Sqr(a_p) + Sqr(b_p));
 184.498 -    double h_p = atan2deg(a_p, b_p);
 184.499 -
 184.500 -
 184.501 -    double a_ps = (1 + G) * as;
 184.502 -    double b_ps = bs;
 184.503 -    double C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps));
 184.504 -    double h_ps = atan2deg(a_ps, b_ps);
 184.505 -
 184.506 -    double meanC_p =(C_p + C_ps) / 2;
 184.507 -
 184.508 -    double hps_plus_hp  = h_ps + h_p;
 184.509 -    double hps_minus_hp = h_ps - h_p;
 184.510 -
 184.511 -    double meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
 184.512 -                            (hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
 184.513 -                                                 (hps_plus_hp - 360)/2;
 184.514 -
 184.515 -    double delta_h = (hps_minus_hp) <= -180.000001 ?  (hps_minus_hp + 360) :
 184.516 -                            (hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
 184.517 -                                                    (hps_minus_hp);
 184.518 -    double delta_L = (Ls - L1);
 184.519 -    double delta_C = (C_ps - C_p );
 184.520 -
 184.521 -
 184.522 -    double delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANES(delta_h) / 2);
 184.523 -
 184.524 -    double T = 1 - 0.17 * cos(RADIANES(meanh_p-30))
 184.525 -                 + 0.24 * cos(RADIANES(2*meanh_p))
 184.526 -                 + 0.32 * cos(RADIANES(3*meanh_p + 6))
 184.527 -                 - 0.2  * cos(RADIANES(4*meanh_p - 63));
 184.528 -
 184.529 -    double Sl = 1 + (0.015 * Sqr((Ls + L1) /2- 50) )/ sqrt(20 + Sqr( (Ls+L1)/2 - 50) );
 184.530 -
 184.531 -    double Sc = 1 + 0.045 * (C_p + C_ps)/2;
 184.532 -    double Sh = 1 + 0.015 * ((C_ps + C_p)/2) * T;
 184.533 -
 184.534 -    double delta_ro = 30 * exp( -Sqr(((meanh_p - 275 ) / 25)));
 184.535 -
 184.536 -    double Rc = 2 * sqrt(( pow(meanC_p, 7.0) )/( pow(meanC_p, 7.0) + pow(25.0, 7.0)));
 184.537 -
 184.538 -    double Rt = -sin(2 * RADIANES(delta_ro)) * Rc;
 184.539 -
 184.540 -    double deltaE00 = sqrt( Sqr(delta_L /(Sl * Kl)) +
 184.541 -                            Sqr(delta_C/(Sc * Kc))  +
 184.542 -                            Sqr(delta_H/(Sh * Kh))  +
 184.543 -                            Rt*(delta_C/(Sc * Kc)) * (delta_H / (Sh * Kh)));
 184.544 -
 184.545 -    return deltaE00;
 184.546 -}
 184.547 -
 184.548 -
 184.549 -
 184.550 -// Carefully,  clamp on CIELab space.
 184.551 -
 184.552 -void LCMSEXPORT cmsClampLab(LPcmsCIELab Lab, double amax, double amin,
 184.553 -                                   double bmax, double bmin)
 184.554 -{
 184.555 -
 184.556 -            // Whole Luma surface to zero
 184.557 -
 184.558 -        if (Lab -> L < 0) {
 184.559 -
 184.560 -                Lab-> L = Lab->a = Lab-> b = 0.0;
 184.561 -                return;
 184.562 -            }
 184.563 -
 184.564 -            // Clamp white, DISCARD HIGHLIGHTS. This is done
 184.565 -            // in such way because icc spec doesn't allow the
 184.566 -            // use of L>100 as a highlight means.
 184.567 -
 184.568 -            if (Lab->L > 100)
 184.569 -                        Lab -> L = 100;
 184.570 -
 184.571 -            // Check out gamut prism, on a, b faces
 184.572 -
 184.573 -            if (Lab -> a < amin || Lab->a > amax||
 184.574 -                Lab -> b < bmin || Lab->b > bmax) {
 184.575 -
 184.576 -                 cmsCIELCh LCh;
 184.577 -                 double h, slope;
 184.578 -
 184.579 -                 // Falls outside a, b limits. Transports to LCh space,
 184.580 -                 // and then do the clipping
 184.581 -
 184.582 -
 184.583 -                 if (Lab -> a == 0.0) { // Is hue exactly 90?
 184.584 -
 184.585 -                        // atan will not work, so clamp here
 184.586 -                        Lab -> b = Lab->b < 0 ? bmin : bmax;
 184.587 -                        return;
 184.588 -                 }
 184.589 -
 184.590 -                 cmsLab2LCh(&LCh, Lab);
 184.591 -
 184.592 -                 slope = Lab -> b / Lab -> a;
 184.593 -                 h = LCh.h;
 184.594 -
 184.595 -                 // There are 4 zones
 184.596 -
 184.597 -                 if ((h >= 0. && h < 45.) ||
 184.598 -                     (h >= 315 && h <= 360.)) {
 184.599 -
 184.600 -                     // clip by amax
 184.601 -                     Lab -> a = amax;
 184.602 -                     Lab -> b = amax * slope;
 184.603 -                 }
 184.604 -                 else
 184.605 -                 if (h >= 45. && h < 135)
 184.606 -                 {
 184.607 -                        // clip by bmax
 184.608 -                        Lab -> b = bmax;
 184.609 -                        Lab -> a = bmax / slope;
 184.610 -                 }
 184.611 -                 else
 184.612 -                 if (h >= 135 && h < 225) {
 184.613 -                        // clip by amin
 184.614 -                        Lab -> a = amin;
 184.615 -                        Lab -> b = amin * slope;
 184.616 -
 184.617 -                 }
 184.618 -                 else
 184.619 -                 if (h >= 225 && h < 315) {
 184.620 -                        // clip by bmin
 184.621 -                        Lab -> b = bmin;
 184.622 -                        Lab -> a = bmin / slope;
 184.623 -                 }
 184.624 -                 else
 184.625 -                        cmsSignalError(LCMS_ERRC_ABORTED, "Invalid angle");
 184.626 -
 184.627 -        }
 184.628 -}
 184.629 -
 184.630 -// Several utilities -------------------------------------------------------
 184.631 -
 184.632 -// Translate from our colorspace to ICC representation
 184.633 -
 184.634 -icColorSpaceSignature LCMSEXPORT _cmsICCcolorSpace(int OurNotation)
 184.635 -{
 184.636 -       switch (OurNotation) {
 184.637 -
 184.638 -       case 1:
 184.639 -       case PT_GRAY: return  icSigGrayData;
 184.640 -
 184.641 -       case 2:
 184.642 -       case PT_RGB:  return  icSigRgbData;
 184.643 -
 184.644 -       case PT_CMY:  return  icSigCmyData;
 184.645 -       case PT_CMYK: return  icSigCmykData;
 184.646 -       case PT_YCbCr:return  icSigYCbCrData;
 184.647 -       case PT_YUV:  return  icSigLuvData;
 184.648 -       case PT_XYZ:  return  icSigXYZData;
 184.649 -       case PT_Lab:  return  icSigLabData;
 184.650 -       case PT_YUVK: return  icSigLuvKData;
 184.651 -       case PT_HSV:  return  icSigHsvData;
 184.652 -       case PT_HLS:  return  icSigHlsData;
 184.653 -       case PT_Yxy:  return  icSigYxyData;
 184.654 -       case PT_HiFi: return  icSigHexachromeData;
 184.655 -       case PT_HiFi7: return icSigHeptachromeData;
 184.656 -       case PT_HiFi8: return icSigOctachromeData;
 184.657 -
 184.658 -       case PT_HiFi9:  return icSigMCH9Data;
 184.659 -       case PT_HiFi10: return icSigMCHAData;
 184.660 -       case PT_HiFi11: return icSigMCHBData;
 184.661 -       case PT_HiFi12: return icSigMCHCData;
 184.662 -       case PT_HiFi13: return icSigMCHDData;
 184.663 -       case PT_HiFi14: return icSigMCHEData;
 184.664 -       case PT_HiFi15: return icSigMCHFData;
 184.665 -
 184.666 -       default:  return icMaxEnumData;
 184.667 -       }
 184.668 -}
 184.669 -
 184.670 -
 184.671 -int LCMSEXPORT _cmsLCMScolorSpace(icColorSpaceSignature ProfileSpace)
 184.672 -{
 184.673 -    switch (ProfileSpace) {
 184.674 -
 184.675 -    case icSigGrayData: return  PT_GRAY;
 184.676 -    case icSigRgbData:  return  PT_RGB;
 184.677 -    case icSigCmyData:  return  PT_CMY;
 184.678 -    case icSigCmykData: return  PT_CMYK;
 184.679 -    case icSigYCbCrData:return  PT_YCbCr;
 184.680 -    case icSigLuvData:  return  PT_YUV;
 184.681 -    case icSigXYZData:  return  PT_XYZ;
 184.682 -    case icSigLabData:  return  PT_Lab;
 184.683 -    case icSigLuvKData: return  PT_YUVK;
 184.684 -    case icSigHsvData:  return  PT_HSV;
 184.685 -    case icSigHlsData:  return  PT_HLS;
 184.686 -    case icSigYxyData:  return  PT_Yxy;
 184.687 -
 184.688 -    case icSig6colorData:
 184.689 -    case icSigHexachromeData: return PT_HiFi;
 184.690 -
 184.691 -    case icSigHeptachromeData:
 184.692 -    case icSig7colorData:     return PT_HiFi7;
 184.693 -
 184.694 -    case icSigOctachromeData:
 184.695 -    case icSig8colorData:     return PT_HiFi8;
 184.696 -
 184.697 -    case icSigMCH9Data:
 184.698 -    case icSig9colorData:     return PT_HiFi9;
 184.699 -
 184.700 -    case icSigMCHAData:
 184.701 -    case icSig10colorData:     return PT_HiFi10;
 184.702 -
 184.703 -    case icSigMCHBData:
 184.704 -    case icSig11colorData:     return PT_HiFi11;
 184.705 -
 184.706 -    case icSigMCHCData:
 184.707 -    case icSig12colorData:     return PT_HiFi12;
 184.708 -
 184.709 -    case icSigMCHDData:
 184.710 -    case icSig13colorData:     return PT_HiFi13;
 184.711 -
 184.712 -    case icSigMCHEData:
 184.713 -    case icSig14colorData:     return PT_HiFi14;
 184.714 -
 184.715 -    case icSigMCHFData:
 184.716 -    case icSig15colorData:     return PT_HiFi15;
 184.717 -
 184.718 -    default:  return icMaxEnumData;
 184.719 -    }
 184.720 -}
 184.721 -
 184.722 -
 184.723 -int LCMSEXPORT _cmsChannelsOf(icColorSpaceSignature ColorSpace)
 184.724 -{
 184.725 -
 184.726 -    switch (ColorSpace) {
 184.727 -
 184.728 -    case icSigGrayData: return 1;
 184.729 -
 184.730 -    case icSig2colorData:  return 2;
 184.731 -
 184.732 -    case icSigXYZData:
 184.733 -    case icSigLabData:
 184.734 -    case icSigLuvData:
 184.735 -    case icSigYCbCrData:
 184.736 -    case icSigYxyData:
 184.737 -    case icSigRgbData:
 184.738 -    case icSigHsvData:
 184.739 -    case icSigHlsData:
 184.740 -    case icSigCmyData:
 184.741 -    case icSig3colorData:  return 3;
 184.742 -
 184.743 -    case icSigLuvKData:
 184.744 -    case icSigCmykData:
 184.745 -    case icSig4colorData:  return 4;
 184.746 -
 184.747 -    case icSigMCH5Data:
 184.748 -    case icSig5colorData:  return 5;
 184.749 -
 184.750 -    case icSigHexachromeData:
 184.751 -    case icSig6colorData:  return 6;
 184.752 -
 184.753 -    case icSigHeptachromeData:
 184.754 -    case icSig7colorData:  return  7;
 184.755 -
 184.756 -    case icSigOctachromeData:
 184.757 -    case icSig8colorData:  return  8;
 184.758 -
 184.759 -    case icSigMCH9Data:
 184.760 -    case icSig9colorData:  return  9;
 184.761 -
 184.762 -    case icSigMCHAData:
 184.763 -    case icSig10colorData: return 10;
 184.764 -
 184.765 -    case icSigMCHBData:
 184.766 -    case icSig11colorData: return 11;
 184.767 -
 184.768 -    case icSigMCHCData:
 184.769 -    case icSig12colorData: return 12;
 184.770 -
 184.771 -    case icSigMCHDData:
 184.772 -    case icSig13colorData: return 13;
 184.773 -
 184.774 -    case icSigMCHEData:
 184.775 -    case icSig14colorData: return 14;
 184.776 -
 184.777 -    case icSigMCHFData:
 184.778 -    case icSig15colorData: return 15;
 184.779 -
 184.780 -    default: return 3;
 184.781 -    }
 184.782 -
 184.783 -}
 184.784 -
 184.785 -
 184.786 -// v2 L=100 is supposed to be placed on 0xFF00. There is no reasonable
 184.787 -// number of gridpoints that would make exact match. However, a
 184.788 -// prelinearization of 258 entries, would map 0xFF00 on entry 257.
 184.789 -// This is almost what we need, unfortunately, the rest of entries
 184.790 -// should be scaled by (255*257/256) and this is not exact.
 184.791 -//
 184.792 -// An intermediate solution would be to use 257 entries. This does not
 184.793 -// map 0xFF00 exactly on a node, but so close that the dE induced is
 184.794 -// negligible. AND the rest of curve is exact.
 184.795 -
 184.796 -static
 184.797 -void CreateLabPrelinearization(LPGAMMATABLE LabTable[])
 184.798 -{
 184.799 -    int i;
 184.800 -
 184.801 -    LabTable[0] = cmsAllocGamma(257);
 184.802 -    LabTable[1] = cmsBuildGamma(257, 1.0);
 184.803 -    LabTable[2] = cmsBuildGamma(257, 1.0);
 184.804 -
 184.805 -    // L* uses 257 entries. Entry 256 holds 0xFFFF, so, the effective range
 184.806 -    // is 0..0xFF00. Last entry (257) is also collapsed to 0xFFFF
 184.807 -
 184.808 -    // From 0 to 0xFF00
 184.809 -    for (i=0; i < 256; i++)
 184.810 -        LabTable[0]->GammaTable[i] = RGB_8_TO_16(i);
 184.811 -
 184.812 -    // Repeat last for 0xFFFF
 184.813 -    LabTable[0] ->GammaTable[256] = 0xFFFF;
 184.814 -}
 184.815 -
 184.816 +// Gamut LUT Creation -----------------------------------------------------------------------------------------
 184.817  
 184.818  // Used by gamut & softproofing
 184.819  
 184.820  typedef struct {
 184.821  
 184.822 -    cmsHTRANSFORM hInput;               // From whatever input color space. NULL for Lab
 184.823 +    cmsHTRANSFORM hInput;               // From whatever input color space. 16 bits to DBL
 184.824      cmsHTRANSFORM hForward, hReverse;   // Transforms going from Lab to colorant and back
 184.825 -    double Thereshold;                  // The thereshold after which is considered out of gamut
 184.826 +    cmsFloat64Number Thereshold;        // The thereshold after which is considered out of gamut
 184.827  
 184.828 -    } GAMUTCHAIN,FAR* LPGAMUTCHAIN;
 184.829 +    } GAMUTCHAIN;
 184.830  
 184.831  // This sampler does compute gamut boundaries by comparing original
 184.832  // values with a transform going back and forth. Values above ERR_THERESHOLD
 184.833  // of maximum are considered out of gamut.
 184.834  
 184.835 -
 184.836  #define ERR_THERESHOLD      5
 184.837  
 184.838  
 184.839  static
 184.840 -int GamutSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
 184.841 +int GamutSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
 184.842  {
 184.843 -    LPGAMUTCHAIN t = (LPGAMUTCHAIN) Cargo;
 184.844 -    WORD Proof[MAXCHANNELS], Check[MAXCHANNELS];
 184.845 -    WORD Proof2[MAXCHANNELS], Check2[MAXCHANNELS];
 184.846 +    GAMUTCHAIN*  t = (GAMUTCHAIN* ) Cargo;
 184.847      cmsCIELab LabIn1, LabOut1;
 184.848      cmsCIELab LabIn2, LabOut2;
 184.849 -    double dE1, dE2, ErrorRatio;
 184.850 +    cmsFloat32Number Proof[cmsMAXCHANNELS], Proof2[cmsMAXCHANNELS];
 184.851 +    cmsFloat64Number dE1, dE2, ErrorRatio;
 184.852  
 184.853      // Assume in-gamut by default.
 184.854      dE1 = 0.;
 184.855      dE2 = 0;
 184.856      ErrorRatio = 1.0;
 184.857  
 184.858 -
 184.859 -    // Any input space? I can use In[] no matter channels
 184.860 -    // because is just one pixel
 184.861 -
 184.862 -    if (t -> hInput != NULL) cmsDoTransform(t -> hInput, In, In, 1);
 184.863 +    // Convert input to Lab
 184.864 +    if (t -> hInput != NULL)
 184.865 +        cmsDoTransform(t -> hInput, In, &LabIn1, 1);
 184.866  
 184.867      // converts from PCS to colorant. This always
 184.868      // does return in-gamut values,
 184.869 -    cmsDoTransform(t -> hForward, In, Proof, 1);
 184.870 +    cmsDoTransform(t -> hForward, &LabIn1, Proof, 1);
 184.871  
 184.872      // Now, do the inverse, from colorant to PCS.
 184.873 -    cmsDoTransform(t -> hReverse, Proof, Check, 1);
 184.874 +    cmsDoTransform(t -> hReverse, Proof, &LabOut1, 1);
 184.875  
 184.876 +    memmove(&LabIn2, &LabOut1, sizeof(cmsCIELab));
 184.877  
 184.878      // Try again, but this time taking Check as input
 184.879 -    cmsDoTransform(t -> hForward, Check, Proof2,  1);
 184.880 -    cmsDoTransform(t -> hReverse, Proof2, Check2, 1);
 184.881 +    cmsDoTransform(t -> hForward, &LabOut1, Proof2,  1);
 184.882 +    cmsDoTransform(t -> hReverse, Proof2, &LabOut2, 1);
 184.883  
 184.884 +    // Take difference of direct value
 184.885 +    dE1 = cmsDeltaE(&LabIn1, &LabOut1);
 184.886  
 184.887 +    // Take difference of converted value
 184.888 +    dE2 = cmsDeltaE(&LabIn2, &LabOut2);
 184.889  
 184.890 -    // Does the transform returns out-of-gamut?
 184.891 -    if (Check[0] == 0xFFFF &&
 184.892 -        Check[1] == 0xFFFF &&
 184.893 -        Check[2] == 0xFFFF)
 184.894  
 184.895 -        Out[0] = 0xFF00;            // Out of gamut!
 184.896 +    // if dE1 is small and dE2 is small, value is likely to be in gamut
 184.897 +    if (dE1 < t->Thereshold && dE2 < t->Thereshold)
 184.898 +        Out[0] = 0;
 184.899      else {
 184.900  
 184.901 -        // Transport encoded values
 184.902 -        cmsLabEncoded2Float(&LabIn1,  In);
 184.903 -        cmsLabEncoded2Float(&LabOut1, Check);
 184.904 -
 184.905 -        // Take difference of direct value
 184.906 -        dE1 = cmsDeltaE(&LabIn1, &LabOut1);
 184.907 -
 184.908 -        cmsLabEncoded2Float(&LabIn2,  Check);
 184.909 -        cmsLabEncoded2Float(&LabOut2, Check2);
 184.910 -
 184.911 -        // Take difference of converted value
 184.912 -        dE2 = cmsDeltaE(&LabIn2, &LabOut2);
 184.913 -
 184.914 -
 184.915 -        // if dE1 is small and dE2 is small, value is likely to be in gamut
 184.916 -        if (dE1 < t->Thereshold && dE2 < t->Thereshold)
 184.917 +        // if dE1 is small and dE2 is big, undefined. Assume in gamut
 184.918 +        if (dE1 < t->Thereshold && dE2 > t->Thereshold)
 184.919              Out[0] = 0;
 184.920          else
 184.921 -            // if dE1 is small and dE2 is big, undefined. Assume in gamut
 184.922 -            if (dE1 < t->Thereshold && dE2 > t->Thereshold)
 184.923 -                Out[0] = 0;
 184.924 -            else
 184.925 -                // dE1 is big and dE2 is small, clearly out of gamut
 184.926 -                if (dE1 > t->Thereshold && dE2 < t->Thereshold)
 184.927 -                    Out[0] = (WORD) _cmsQuickFloor((dE1 - t->Thereshold) + .5);
 184.928 -                else  {
 184.929 +            // dE1 is big and dE2 is small, clearly out of gamut
 184.930 +            if (dE1 > t->Thereshold && dE2 < t->Thereshold)
 184.931 +                Out[0] = (cmsUInt16Number) _cmsQuickFloor((dE1 - t->Thereshold) + .5);
 184.932 +            else  {
 184.933  
 184.934 -                    // dE1 is big and dE2 is also big, could be due to perceptual mapping
 184.935 -                    // so take error ratio
 184.936 -                    if (dE2 == 0.0)
 184.937 -                        ErrorRatio = dE1;
 184.938 -                    else
 184.939 -                        ErrorRatio = dE1 / dE2;
 184.940 +                // dE1 is big and dE2 is also big, could be due to perceptual mapping
 184.941 +                // so take error ratio
 184.942 +                if (dE2 == 0.0)
 184.943 +                    ErrorRatio = dE1;
 184.944 +                else
 184.945 +                    ErrorRatio = dE1 / dE2;
 184.946  
 184.947 -                    if (ErrorRatio > t->Thereshold)
 184.948 -                        Out[0] = (WORD)  _cmsQuickFloor((ErrorRatio - t->Thereshold) + .5);
 184.949 -                    else
 184.950 -                        Out[0] = 0;
 184.951 -                }
 184.952 +                if (ErrorRatio > t->Thereshold)
 184.953 +                    Out[0] = (cmsUInt16Number)  _cmsQuickFloor((ErrorRatio - t->Thereshold) + .5);
 184.954 +                else
 184.955 +                    Out[0] = 0;
 184.956 +            }
 184.957 +    }
 184.958  
 184.959 -    }
 184.960  
 184.961      return TRUE;
 184.962  }
 184.963  
 184.964 +// Does compute a gamut LUT going back and forth across pcs -> relativ. colorimetric intent -> pcs
 184.965 +// the dE obtained is then annotated on the LUT. Values truely out of gamut are clipped to dE = 0xFFFE
 184.966 +// and values changed are supposed to be handled by any gamut remapping, so, are out of gamut as well.
 184.967 +//
 184.968 +// **WARNING: This algorithm does assume that gamut remapping algorithms does NOT move in-gamut colors,
 184.969 +// of course, many perceptual and saturation intents does not work in such way, but relativ. ones should.
 184.970  
 184.971 -// Does compute a gamut LUT going back and forth across
 184.972 -// pcs -> relativ. colorimetric intent -> pcs
 184.973 -// the dE obtained is then annotated on the LUT.
 184.974 -// values truely out of gamut, are clipped to dE = 0xFFFE
 184.975 -// and values changed are supposed to be handled by
 184.976 -// any gamut remapping, so, are out of gamut as well.
 184.977 -//
 184.978 -// **WARNING: This algorithm does assume that gamut
 184.979 -// remapping algorithms does NOT move in-gamut colors,
 184.980 -// of course, many perceptual and saturation intents does
 184.981 -// not work in such way, but relativ. ones should.
 184.982 -
 184.983 -static
 184.984 -LPLUT ComputeGamutWithInput(cmsHPROFILE hInput, cmsHPROFILE hProfile, int Intent)
 184.985 +cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
 184.986 +                                          cmsHPROFILE hProfiles[],
 184.987 +                                          cmsBool  BPC[],
 184.988 +                                          cmsUInt32Number Intents[],
 184.989 +                                          cmsFloat64Number AdaptationStates[],
 184.990 +                                          cmsUInt32Number nGamutPCSposition,
 184.991 +                                          cmsHPROFILE hGamut)
 184.992  {
 184.993      cmsHPROFILE hLab;
 184.994 -    LPLUT Gamut;
 184.995 -    DWORD dwFormat;
 184.996 +    cmsPipeline* Gamut;
 184.997 +    cmsStage* CLUT;
 184.998 +    cmsUInt32Number dwFormat;
 184.999      GAMUTCHAIN Chain;
184.1000 -    int nErrState, nChannels, nGridpoints;
184.1001 -    LPGAMMATABLE Trans[3];
184.1002 -    icColorSpaceSignature ColorSpace;
184.1003 +    int nChannels, nGridpoints;
184.1004 +    cmsColorSpaceSignature ColorSpace;
184.1005 +    cmsUInt32Number i;
184.1006 +    cmsHPROFILE ProfileList[256];
184.1007 +    cmsBool     BPCList[256];
184.1008 +    cmsFloat64Number AdaptationList[256];
184.1009 +    cmsUInt32Number IntentList[256];
184.1010  
184.1011 +    memset(&Chain, 0, sizeof(GAMUTCHAIN));
184.1012  
184.1013 -    ZeroMemory(&Chain, sizeof(GAMUTCHAIN));
184.1014  
184.1015 -    hLab = cmsCreateLabProfile(NULL);
184.1016 +    if (nGamutPCSposition <= 0 || nGamutPCSposition > 255) {
184.1017 +        cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong position of PCS. 1..255 expected, %d found.", nGamutPCSposition);
184.1018 +        return NULL;
184.1019 +    }
184.1020  
184.1021 -    // Safeguard against early abortion
184.1022 -    nErrState = cmsErrorAction(LCMS_ERROR_IGNORE);
184.1023 +    hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
184.1024 +    if (hLab == NULL) return NULL;
184.1025 +
184.1026  
184.1027      // The figure of merit. On matrix-shaper profiles, should be almost zero as
184.1028      // the conversion is pretty exact. On LUT based profiles, different resolutions
184.1029      // of input and output CLUT may result in differences.
184.1030  
184.1031 -    if (!cmsIsIntentSupported(hProfile, Intent, LCMS_USED_AS_INPUT) &&
184.1032 -        !cmsIsIntentSupported(hProfile, Intent, LCMS_USED_AS_OUTPUT))
184.1033 +    if (cmsIsMatrixShaper(hGamut)) {
184.1034  
184.1035          Chain.Thereshold = 1.0;
184.1036 -    else
184.1037 +    }
184.1038 +    else {
184.1039          Chain.Thereshold = ERR_THERESHOLD;
184.1040 -
184.1041 -    ColorSpace  = cmsGetColorSpace(hProfile);
184.1042 -
184.1043 -    // If input profile specified, create a transform from such profile to Lab
184.1044 -    if (hInput != NULL) {
184.1045 -
184.1046 -        nChannels   = _cmsChannelsOf(ColorSpace);
184.1047 -        nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
184.1048 -        dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));
184.1049 -
184.1050 -        Chain.hInput = cmsCreateTransform(hInput, dwFormat,
184.1051 -                                          hLab,   TYPE_Lab_16,
184.1052 -                                          Intent,
184.1053 -                                          cmsFLAGS_NOTPRECALC);
184.1054 -    }
184.1055 -    else  {
184.1056 -        // Input transform=NULL (Lab) Used to compute the gamut tag
184.1057 -        // This table will take 53 points to give some accurancy,
184.1058 -        // 53 * 53 * 53 * 2 = 291K
184.1059 -
184.1060 -        nChannels    = 3;      // For Lab
184.1061 -        nGridpoints  = 53;
184.1062 -        Chain.hInput = NULL;
184.1063 -        dwFormat = (CHANNELS_SH(_cmsChannelsOf(ColorSpace))|BYTES_SH(2));
184.1064      }
184.1065  
184.1066  
184.1067 -    // Does create the forward step
184.1068 -    Chain.hForward = cmsCreateTransform(hLab, TYPE_Lab_16,
184.1069 -                                        hProfile, dwFormat,
184.1070 -                                        INTENT_RELATIVE_COLORIMETRIC,
184.1071 -                                        cmsFLAGS_NOTPRECALC);
184.1072 +    // Create a copy of parameters
184.1073 +    for (i=0; i < nGamutPCSposition; i++) {
184.1074 +        ProfileList[i]    = hProfiles[i];
184.1075 +        BPCList[i]        = BPC[i];
184.1076 +        AdaptationList[i] = AdaptationStates[i];
184.1077 +        IntentList[i]     = Intents[i];
184.1078 +    }
184.1079 +
184.1080 +    // Fill Lab identity
184.1081 +    ProfileList[nGamutPCSposition] = hLab;
184.1082 +    BPCList[nGamutPCSposition] = 0;
184.1083 +    AdaptationList[nGamutPCSposition] = 1.0;
184.1084 +    Intents[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
184.1085 +
184.1086 +
184.1087 +    ColorSpace  = cmsGetColorSpace(hGamut);
184.1088 +
184.1089 +    nChannels   = cmsChannelsOf(ColorSpace);
184.1090 +    nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
184.1091 +    dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));
184.1092 +
184.1093 +    // 16 bits to Lab double
184.1094 +    Chain.hInput = cmsCreateExtendedTransform(ContextID,
184.1095 +                                              nGamutPCSposition + 1,
184.1096 +                                              ProfileList,
184.1097 +                                              BPCList,
184.1098 +                                              Intents,
184.1099 +                                              AdaptationList,
184.1100 +                                              NULL, 0,
184.1101 +                                              dwFormat, TYPE_Lab_DBL,
184.1102 +                                              cmsFLAGS_NOCACHE);
184.1103 +
184.1104 +
184.1105 +    // Does create the forward step. Lab double to cmsFloat32Number
184.1106 +    dwFormat    = (FLOAT_SH(1)|CHANNELS_SH(nChannels)|BYTES_SH(4));
184.1107 +    Chain.hForward = cmsCreateTransformTHR(ContextID,
184.1108 +                                           hLab, TYPE_Lab_DBL,
184.1109 +                                           hGamut, dwFormat,
184.1110 +                                           INTENT_RELATIVE_COLORIMETRIC,
184.1111 +                                           cmsFLAGS_NOCACHE);
184.1112  
184.1113      // Does create the backwards step
184.1114 -    Chain.hReverse = cmsCreateTransform(hProfile, dwFormat,
184.1115 -                                        hLab, TYPE_Lab_16,
184.1116 -                                        INTENT_RELATIVE_COLORIMETRIC,
184.1117 -                                        cmsFLAGS_NOTPRECALC);
184.1118 -
184.1119 -    // Restores error handler previous state
184.1120 -    cmsErrorAction(nErrState);
184.1121 +    Chain.hReverse = cmsCreateTransformTHR(ContextID, hGamut, dwFormat,
184.1122 +                                           hLab, TYPE_Lab_DBL,
184.1123 +                                           INTENT_RELATIVE_COLORIMETRIC,
184.1124 +                                           cmsFLAGS_NOCACHE);
184.1125  
184.1126  
184.1127      // All ok?
184.1128      if (Chain.hForward && Chain.hReverse) {
184.1129  
184.1130 -    // Go on, try to compute gamut LUT from PCS.
184.1131 -    // This consist on a single channel containing
184.1132 -    // dE when doing a transform back and forth on
184.1133 -    // the colorimetric intent.
184.1134 +        // Go on, try to compute gamut LUT from PCS. This consist on a single channel containing
184.1135 +        // dE when doing a transform back and forth on the colorimetric intent.
184.1136  
184.1137 -    Gamut = cmsAllocLUT();
184.1138 -    Gamut = cmsAlloc3DGrid(Gamut, nGridpoints, nChannels, 1);
184.1139 +        Gamut = cmsPipelineAlloc(ContextID, 3, 1);
184.1140  
184.1141 -    // If no input, then this is a gamut tag operated by Lab,
184.1142 -    // so include pertinent prelinearization
184.1143 -    if (hInput == NULL) {
184.1144 +        if (Gamut != NULL) {
184.1145  
184.1146 -        CreateLabPrelinearization(Trans);
184.1147 -        cmsAllocLinearTable(Gamut, Trans, 1);
184.1148 -        cmsFreeGammaTriple(Trans);
184.1149 -    }
184.1150 +            CLUT = cmsStageAllocCLut16bit(ContextID, nGridpoints, nChannels, 1, NULL);
184.1151 +            cmsPipelineInsertStage(Gamut, cmsAT_BEGIN, CLUT);
184.1152  
184.1153 -
184.1154 -    cmsSample3DGrid(Gamut, GamutSampler, (LPVOID) &Chain, Gamut ->wFlags);
184.1155 +            cmsStageSampleCLut16bit(CLUT, GamutSampler, (void*) &Chain, 0);
184.1156 +        }
184.1157      }
184.1158      else
184.1159          Gamut = NULL;   // Didn't work...
184.1160 @@ -921,352 +434,187 @@
184.1161      if (Chain.hInput)   cmsDeleteTransform(Chain.hInput);
184.1162      if (Chain.hForward) cmsDeleteTransform(Chain.hForward);
184.1163      if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse);
184.1164 -
184.1165 -    cmsCloseProfile(hLab);
184.1166 +    if (hLab) cmsCloseProfile(hLab);
184.1167  
184.1168      // And return computed hull
184.1169      return Gamut;
184.1170  }
184.1171  
184.1172 +// Total Area Coverage estimation ----------------------------------------------------------------
184.1173  
184.1174 -// Wrapper
184.1175 +typedef struct {
184.1176 +    cmsUInt32Number  nOutputChans;
184.1177 +    cmsHTRANSFORM    hRoundTrip;
184.1178 +    cmsFloat32Number MaxTAC;
184.1179 +    cmsFloat32Number MaxInput[cmsMAXCHANNELS];
184.1180  
184.1181 -LPLUT _cmsComputeGamutLUT(cmsHPROFILE hProfile, int Intent)
184.1182 +} cmsTACestimator;
184.1183 +
184.1184 +
184.1185 +// This callback just accounts the maximum ink dropped in the given node. It does not populate any
184.1186 +// memory, as the destination table is NULL. Its only purpose it to know the global maximum.
184.1187 +static
184.1188 +int EstimateTAC(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo)
184.1189  {
184.1190 -    return ComputeGamutWithInput(NULL, hProfile, Intent);
184.1191 +    cmsTACestimator* bp = (cmsTACestimator*) Cargo;
184.1192 +    cmsFloat32Number RoundTrip[cmsMAXCHANNELS];
184.1193 +    cmsUInt32Number i;
184.1194 +    cmsFloat32Number Sum;
184.1195 +
184.1196 +
184.1197 +    // Evaluate the xform
184.1198 +    cmsDoTransform(bp->hRoundTrip, In, RoundTrip, 1);
184.1199 +
184.1200 +    // All all amounts of ink
184.1201 +    for (Sum=0, i=0; i < bp ->nOutputChans; i++)
184.1202 +            Sum += RoundTrip[i];
184.1203 +
184.1204 +    // If above maximum, keep track of input values
184.1205 +    if (Sum > bp ->MaxTAC) {
184.1206 +
184.1207 +            bp ->MaxTAC = Sum;
184.1208 +
184.1209 +            for (i=0; i < bp ->nOutputChans; i++) {
184.1210 +                bp ->MaxInput[i] = In[i];
184.1211 +            }
184.1212 +    }
184.1213 +
184.1214 +    return TRUE;
184.1215 +
184.1216 +    cmsUNUSED_PARAMETER(Out);
184.1217  }
184.1218  
184.1219  
184.1220 -// This routine does compute the gamut check CLUT. This CLUT goes from whatever
184.1221 -// input space to the 0 or != 0 gamut check.
184.1222 +// Detect Total area coverage of the profile
184.1223 +cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile)
184.1224 +{
184.1225 +    cmsTACestimator bp;
184.1226 +    cmsUInt32Number dwFormatter;
184.1227 +    cmsUInt32Number GridPoints[MAX_INPUT_DIMENSIONS];
184.1228 +    cmsHPROFILE hLab;
184.1229 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
184.1230  
184.1231 -LPLUT _cmsPrecalculateGamutCheck(cmsHTRANSFORM h)
184.1232 -{
184.1233 -       _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) h;
184.1234 +    // TAC only works on output profiles
184.1235 +    if (cmsGetDeviceClass(hProfile) != cmsSigOutputClass) {
184.1236 +        return 0;
184.1237 +    }
184.1238  
184.1239 -       return ComputeGamutWithInput(p->InputProfile, p ->PreviewProfile, p->Intent);
184.1240 +    // Create a fake formatter for result
184.1241 +    dwFormatter = cmsFormatterForColorspaceOfProfile(hProfile, 4, TRUE);
184.1242 +
184.1243 +    bp.nOutputChans = T_CHANNELS(dwFormatter);
184.1244 +    bp.MaxTAC = 0;    // Initial TAC is 0
184.1245 +
184.1246 +    //  for safety
184.1247 +    if (bp.nOutputChans >= cmsMAXCHANNELS) return 0;
184.1248 +
184.1249 +    hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
184.1250 +    if (hLab == NULL) return 0;
184.1251 +    // Setup a roundtrip on perceptual intent in output profile for TAC estimation
184.1252 +    bp.hRoundTrip = cmsCreateTransformTHR(ContextID, hLab, TYPE_Lab_16,
184.1253 +                                          hProfile, dwFormatter, INTENT_PERCEPTUAL, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE);
184.1254 +
184.1255 +    cmsCloseProfile(hLab);
184.1256 +    if (bp.hRoundTrip == NULL) return 0;
184.1257 +
184.1258 +    // For L* we only need black and white. For C* we need many points
184.1259 +    GridPoints[0] = 6;
184.1260 +    GridPoints[1] = 74;
184.1261 +    GridPoints[2] = 74;
184.1262 +
184.1263 +
184.1264 +    if (!cmsSliceSpace16(3, GridPoints, EstimateTAC, &bp)) {
184.1265 +        bp.MaxTAC = 0;
184.1266 +    }
184.1267 +
184.1268 +    cmsDeleteTransform(bp.hRoundTrip);
184.1269 +
184.1270 +    // Results in %
184.1271 +    return bp.MaxTAC;
184.1272  }
184.1273  
184.1274  
184.1275 -// SoftProofing. Convert from Lab to device, then back to Lab,
184.1276 -// any gamut remapping is applied
184.1277 +// Carefully,  clamp on CIELab space.
184.1278  
184.1279 -static
184.1280 -int SoftProofSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
184.1281 +cmsBool CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab,
184.1282 +                                   double amax, double amin,
184.1283 +                                   double bmax, double bmin)
184.1284  {
184.1285 -        LPGAMUTCHAIN t = (LPGAMUTCHAIN) Cargo;
184.1286 -        WORD Colorant[MAXCHANNELS];
184.1287  
184.1288 -        // From pcs to colorant
184.1289 -        cmsDoTransform(t -> hForward, In, Colorant, 1);
184.1290 +    // Whole Luma surface to zero
184.1291  
184.1292 -        // Now, do the inverse, from colorant to pcs.
184.1293 -        cmsDoTransform(t -> hReverse, Colorant, Out, 1);
184.1294 +    if (Lab -> L < 0) {
184.1295  
184.1296 -        return TRUE;
184.1297 -}
184.1298 +        Lab-> L = Lab->a = Lab-> b = 0.0;
184.1299 +        return FALSE;
184.1300 +    }
184.1301  
184.1302 -// Does return Softproofing LUT on desired intent
184.1303 +    // Clamp white, DISCARD HIGHLIGHTS. This is done
184.1304 +    // in such way because icc spec doesn't allow the
184.1305 +    // use of L>100 as a highlight means.
184.1306  
184.1307 -LPLUT _cmsComputeSoftProofLUT(cmsHPROFILE hProfile, int nIntent)
184.1308 -{
184.1309 -    cmsHPROFILE hLab;
184.1310 -    LPLUT SoftProof;
184.1311 -    DWORD dwFormat;
184.1312 -    GAMUTCHAIN Chain;
184.1313 -    int nErrState;
184.1314 -    LPGAMMATABLE Trans[3];
184.1315 +    if (Lab->L > 100)
184.1316 +        Lab -> L = 100;
184.1317  
184.1318 +    // Check out gamut prism, on a, b faces
184.1319  
184.1320 -    // LUTs are never abs. colorimetric, is the transform who
184.1321 -    // is responsible of generating white point displacement
184.1322 -    if (nIntent == INTENT_ABSOLUTE_COLORIMETRIC)
184.1323 -        nIntent = INTENT_RELATIVE_COLORIMETRIC;
184.1324 +    if (Lab -> a < amin || Lab->a > amax||
184.1325 +        Lab -> b < bmin || Lab->b > bmax) {
184.1326  
184.1327 -    ZeroMemory(&Chain, sizeof(GAMUTCHAIN));
184.1328 +            cmsCIELCh LCh;
184.1329 +            double h, slope;
184.1330  
184.1331 -    hLab = cmsCreateLabProfile(NULL);
184.1332 +            // Falls outside a, b limits. Transports to LCh space,
184.1333 +            // and then do the clipping
184.1334  
184.1335 -    // ONLY 4 channels
184.1336 -    dwFormat = (CHANNELS_SH(4)|BYTES_SH(2));
184.1337  
184.1338 -    // Safeguard against early abortion
184.1339 -    nErrState = cmsErrorAction(LCMS_ERROR_IGNORE);
184.1340 +            if (Lab -> a == 0.0) { // Is hue exactly 90?
184.1341  
184.1342 -    // Does create the first step
184.1343 -    Chain.hForward = cmsCreateTransform(hLab, TYPE_Lab_16,
184.1344 -                                        hProfile, dwFormat,
184.1345 -                                        nIntent,
184.1346 -                                        cmsFLAGS_NOTPRECALC);
184.1347 +                // atan will not work, so clamp here
184.1348 +                Lab -> b = Lab->b < 0 ? bmin : bmax;
184.1349 +                return TRUE;
184.1350 +            }
184.1351  
184.1352 -    // Does create the last step
184.1353 -    Chain.hReverse = cmsCreateTransform(hProfile, dwFormat,
184.1354 -                                        hLab, TYPE_Lab_16,
184.1355 -                                        INTENT_RELATIVE_COLORIMETRIC,
184.1356 -                                        cmsFLAGS_NOTPRECALC);
184.1357 +            cmsLab2LCh(&LCh, Lab);
184.1358  
184.1359 -    // Restores error handler previous state
184.1360 -    cmsErrorAction(nErrState);
184.1361 +            slope = Lab -> b / Lab -> a;
184.1362 +            h = LCh.h;
184.1363  
184.1364 -    // All ok?
184.1365 -    if (Chain.hForward && Chain.hReverse) {
184.1366 +            // There are 4 zones
184.1367  
184.1368 -    // This is Lab -> Lab, so 33 point should hold anything
184.1369 -    SoftProof = cmsAllocLUT();
184.1370 -    SoftProof = cmsAlloc3DGrid(SoftProof, 33, 3, 3);
184.1371 +            if ((h >= 0. && h < 45.) ||
184.1372 +                (h >= 315 && h <= 360.)) {
184.1373  
184.1374 -    CreateLabPrelinearization(Trans);
184.1375 -    cmsAllocLinearTable(SoftProof, Trans, 1);
184.1376 -    cmsFreeGammaTriple(Trans);
184.1377 +                    // clip by amax
184.1378 +                    Lab -> a = amax;
184.1379 +                    Lab -> b = amax * slope;
184.1380 +            }
184.1381 +            else
184.1382 +                if (h >= 45. && h < 135.)
184.1383 +                {
184.1384 +                    // clip by bmax
184.1385 +                    Lab -> b = bmax;
184.1386 +                    Lab -> a = bmax / slope;
184.1387 +                }
184.1388 +                else
184.1389 +                    if (h >= 135. && h < 225.) {
184.1390 +                        // clip by amin
184.1391 +                        Lab -> a = amin;
184.1392 +                        Lab -> b = amin * slope;
184.1393  
184.1394 -    cmsSample3DGrid(SoftProof, SoftProofSampler, (LPVOID) &Chain, SoftProof->wFlags);
184.1395 -    }
184.1396 -    else
184.1397 -        SoftProof = NULL;   // Didn't work...
184.1398 -
184.1399 -    // Free all needed stuff.
184.1400 -    if (Chain.hForward) cmsDeleteTransform(Chain.hForward);
184.1401 -    if (Chain.hReverse) cmsDeleteTransform(Chain.hReverse);
184.1402 -
184.1403 -    cmsCloseProfile(hLab);
184.1404 -
184.1405 -    return SoftProof;
184.1406 -}
184.1407 -
184.1408 -
184.1409 -static
184.1410 -int MostlyLinear(WORD Table[], int nEntries)
184.1411 -{
184.1412 -       register int i;
184.1413 -       int diff;
184.1414 -
184.1415 -       for (i=5; i < nEntries; i++) {
184.1416 -
184.1417 -           diff = abs((int) Table[i] - (int) _cmsQuantizeVal(i, nEntries));
184.1418 -           if (diff > 0x0300)
184.1419 -                     return 0;
184.1420 -       }
184.1421 -
184.1422 -       return 1;
184.1423 -}
184.1424 -
184.1425 -
184.1426 -static
184.1427 -void SlopeLimiting(WORD Table[], int nEntries)
184.1428 -{
184.1429 -    int At = (int) floor((double) nEntries * 0.02 + 0.5);   // Cutoff at 2%
184.1430 -    double Val, Slope;
184.1431 -    int i;
184.1432 -
184.1433 -    Val   = Table[At];
184.1434 -    Slope = Val / At;
184.1435 -
184.1436 -    for (i=0; i < At; i++)
184.1437 -        Table[i] = (WORD) floor(i * Slope + 0.5);
184.1438 -
184.1439 -}
184.1440 -
184.1441 -
184.1442 -// Check for monotonicity.
184.1443 -
184.1444 -static
184.1445 -LCMSBOOL IsMonotonic(LPGAMMATABLE t)
184.1446 -{
184.1447 -    int n = t -> nEntries;
184.1448 -    int i, last;
184.1449 -
184.1450 -    last = t ->GammaTable[n-1];
184.1451 -
184.1452 -    for (i = n-2; i >= 0; --i) {
184.1453 -
184.1454 -        if (t ->GammaTable[i] > last)
184.1455 -
184.1456 -               return FALSE;
184.1457 -        else
184.1458 -                last = t ->GammaTable[i];
184.1459 +                    }
184.1460 +                    else
184.1461 +                        if (h >= 225. && h < 315.) {
184.1462 +                            // clip by bmin
184.1463 +                            Lab -> b = bmin;
184.1464 +                            Lab -> a = bmin / slope;
184.1465 +                        }
184.1466 +                        else  {
184.1467 +                            cmsSignalError(0, cmsERROR_RANGE, "Invalid angle");
184.1468 +                            return FALSE;
184.1469 +                        }
184.1470  
184.1471      }
184.1472  
184.1473      return TRUE;
184.1474  }
184.1475 -
184.1476 -// Check for endpoints
184.1477 -
184.1478 -static
184.1479 -LCMSBOOL HasProperEndpoints(LPGAMMATABLE t)
184.1480 -{
184.1481 -    if (t ->GammaTable[0] != 0) return FALSE;
184.1482 -    if (t ->GammaTable[t ->nEntries-1] != 0xFFFF) return FALSE;
184.1483 -
184.1484 -    return TRUE;
184.1485 -}
184.1486 -
184.1487 -
184.1488 -
184.1489 -#define PRELINEARIZATION_POINTS 4096
184.1490 -
184.1491 -// Fixes the gamma balancing of transform. Thanks to Mike Chaney
184.1492 -// for pointing this subtle bug.
184.1493 -
184.1494 -void _cmsComputePrelinearizationTablesFromXFORM(cmsHTRANSFORM h[], int nTransforms, LPLUT Grid)
184.1495 -{
184.1496 -    LPGAMMATABLE Trans[MAXCHANNELS];
184.1497 -    unsigned int t, i, v;
184.1498 -    int j;
184.1499 -    WORD In[MAXCHANNELS], Out[MAXCHANNELS];
184.1500 -    LCMSBOOL lIsSuitable;
184.1501 -    _LPcmsTRANSFORM InputXForm   = (_LPcmsTRANSFORM) h[0];
184.1502 -    _LPcmsTRANSFORM OutputXForm  = (_LPcmsTRANSFORM) h[nTransforms-1];
184.1503 -
184.1504 -
184.1505 -    // First space is *Lab, use our specialized curves for v2 Lab
184.1506 -
184.1507 -    if (InputXForm ->EntryColorSpace == icSigLabData &&
184.1508 -        OutputXForm->ExitColorSpace != icSigLabData) {
184.1509 -
184.1510 -                CreateLabPrelinearization(Trans);
184.1511 -                cmsAllocLinearTable(Grid, Trans, 1);
184.1512 -                cmsFreeGammaTriple(Trans);
184.1513 -                return;
184.1514 -    }
184.1515 -
184.1516 -
184.1517 -    // Do nothing on all but Gray/RGB to Gray/RGB transforms
184.1518 -
184.1519 -    if (((InputXForm ->EntryColorSpace != icSigRgbData) && (InputXForm ->EntryColorSpace != icSigGrayData)) ||
184.1520 -        ((OutputXForm->ExitColorSpace  != icSigRgbData) && (OutputXForm->ExitColorSpace  != icSigGrayData))) return;
184.1521 -
184.1522 -
184.1523 -    for (t = 0; t < Grid -> InputChan; t++)
184.1524 -            Trans[t] = cmsAllocGamma(PRELINEARIZATION_POINTS);
184.1525 -
184.1526 -    for (i=0; i < PRELINEARIZATION_POINTS; i++) {
184.1527 -
184.1528 -                v = _cmsQuantizeVal(i, PRELINEARIZATION_POINTS);
184.1529 -
184.1530 -                for (t=0; t < Grid -> InputChan; t++)
184.1531 -                        In[t] = (WORD) v;
184.1532 -
184.1533 -                cmsDoTransform(h[0], In, Out, 1);
184.1534 -                for (j=1; j < nTransforms; j++)
184.1535 -                        cmsDoTransform(h[j], Out, Out, 1);
184.1536 -
184.1537 -                for (t=0; t < Grid -> InputChan; t++)
184.1538 -                        Trans[t] ->GammaTable[i] = Out[t];
184.1539 -
184.1540 -    }
184.1541 -
184.1542 -
184.1543 -    // Check transfer curves
184.1544 -    lIsSuitable = TRUE;
184.1545 -    for (t=0; (lIsSuitable && (t < Grid->InputChan)); t++) {
184.1546 -
184.1547 -
184.1548 -        // Exclude if already linear
184.1549 -        if (MostlyLinear(Trans[t]->GammaTable, PRELINEARIZATION_POINTS))
184.1550 -                    lIsSuitable = FALSE;
184.1551 -
184.1552 -        // Exclude if non-monotonic
184.1553 -        if (!IsMonotonic(Trans[t]))
184.1554 -                    lIsSuitable = FALSE;
184.1555 -
184.1556 -        // Exclude if weird endpoints
184.1557 -        if (!HasProperEndpoints(Trans[t]))
184.1558 -                    lIsSuitable = FALSE;
184.1559 -
184.1560 -        /*
184.1561 -        // Exclude if transfer function is not smooth enough
184.1562 -        // to be modelled as a gamma function, or the gamma is reversed
184.1563 -
184.1564 -        if (cmsEstimateGamma(Trans[t]) < 1.0)
184.1565 -                    lIsSuitable = FALSE;
184.1566 -        */
184.1567 -
184.1568 -    }
184.1569 -
184.1570 -    if (lIsSuitable) {
184.1571 -
184.1572 -            for (t = 0; t < Grid ->InputChan; t++)
184.1573 -                SlopeLimiting(Trans[t]->GammaTable, Trans[t]->nEntries);
184.1574 -    }
184.1575 -
184.1576 -    if (lIsSuitable) cmsAllocLinearTable(Grid, Trans, 1);
184.1577 -
184.1578 -
184.1579 -    for (t = 0; t < Grid ->InputChan; t++)
184.1580 -                        cmsFreeGamma(Trans[t]);
184.1581 -
184.1582 -
184.1583 -}
184.1584 -
184.1585 -
184.1586 -// Compute K -> L* relationship. Flags may include black point compensation. In this case,
184.1587 -// the relationship is assumed from the profile with BPC to a black point zero.
184.1588 -static
184.1589 -LPGAMMATABLE ComputeKToLstar(cmsHPROFILE hProfile, int nPoints, int Intent, DWORD dwFlags)
184.1590 -{
184.1591 -    LPGAMMATABLE out;
184.1592 -    int i;
184.1593 -    WORD cmyk[4], wLab[3];
184.1594 -    cmsHPROFILE   hLab  = cmsCreateLabProfile(NULL);
184.1595 -    cmsHTRANSFORM xform = cmsCreateTransform(hProfile, TYPE_CMYK_16,
184.1596 -                                             hLab, TYPE_Lab_16,
184.1597 -                                             Intent, (dwFlags|cmsFLAGS_NOTPRECALC));
184.1598 -
184.1599 -
184.1600 -    out = cmsAllocGamma(nPoints);
184.1601 -    for (i=0; i < nPoints; i++) {
184.1602 -
184.1603 -        cmyk[0] = 0;
184.1604 -        cmyk[1] = 0;
184.1605 -        cmyk[2] = 0;
184.1606 -        cmyk[3] = _cmsQuantizeVal(i, nPoints);
184.1607 -
184.1608 -        cmsDoTransform(xform, cmyk, wLab, 1);
184.1609 -        out->GammaTable[i] = (WORD) (0xFFFF - wLab[0]);
184.1610 -    }
184.1611 -
184.1612 -    cmsDeleteTransform(xform);
184.1613 -    cmsCloseProfile(hLab);
184.1614 -
184.1615 -    return out;
184.1616 -}
184.1617 -
184.1618 -
184.1619 -
184.1620 -// Compute Black tone curve on a CMYK -> CMYK transform. This is done by
184.1621 -// using the proof direction on both profiles to find K->L* relationship
184.1622 -// then joining both curves. dwFlags may include black point compensation.
184.1623 -
184.1624 -LPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints)
184.1625 -{
184.1626 -    LPGAMMATABLE in, out;
184.1627 -    LPGAMMATABLE KTone;
184.1628 -    _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) hCMYK2CMYK;
184.1629 -
184.1630 -
184.1631 -    // Make sure CMYK -> CMYK
184.1632 -    if (p -> EntryColorSpace != icSigCmykData ||
184.1633 -        p -> ExitColorSpace  != icSigCmykData) return NULL;
184.1634 -
184.1635 -    // Create individual curves. BPC works also as each K to L* is
184.1636 -    // computed as a BPC to zero black point in case of L*
184.1637 -    in  = ComputeKToLstar(p ->InputProfile,  nPoints, p->Intent, p -> dwOriginalFlags);
184.1638 -    out = ComputeKToLstar(p ->OutputProfile, nPoints, p->Intent, p -> dwOriginalFlags);
184.1639 -
184.1640 -    // Build the relationship
184.1641 -    KTone = cmsJoinGamma(in, out);
184.1642 -
184.1643 -    cmsFreeGamma(in); cmsFreeGamma(out);
184.1644 -
184.1645 -    // Make sure it is monotonic
184.1646 -
184.1647 -    if (!IsMonotonic(KTone)) {
184.1648 -
184.1649 -        cmsFreeGamma(KTone);
184.1650 -        return NULL;
184.1651 -    }
184.1652 -
184.1653 -
184.1654 -    return KTone;
184.1655 -}
   185.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c	Thu Sep 23 17:33:40 2010 -0700
   185.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c	Fri Sep 24 16:41:32 2010 -0700
   185.3 @@ -27,9 +27,10 @@
   185.4  // However, the following notice accompanied the original version of this
   185.5  // file:
   185.6  //
   185.7 +//---------------------------------------------------------------------------------
   185.8  //
   185.9 -//  Little cms
  185.10 -//  Copyright (C) 1998-2007 Marti Maria
  185.11 +//  Little Color Management System
  185.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  185.13  //
  185.14  // Permission is hereby granted, free of charge, to any person obtaining
  185.15  // a copy of this software and associated documentation files (the "Software"),
  185.16 @@ -48,731 +49,318 @@
  185.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  185.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  185.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  185.20 +//
  185.21 +//---------------------------------------------------------------------------------
  185.22 +//
  185.23  
  185.24 -// Interpolation
  185.25 +#include "lcms2_internal.h"
  185.26  
  185.27 -#include "lcms.h"
  185.28 +// This module incorporates several interpolation routines, for 1, 3, 4, 5, 6, 7 and 8 channels on input and
  185.29 +// up to 65535 channels on output. The user may change those by using the interpolation plug-in
  185.30  
  185.31 -void cmsCalcL16Params(int nSamples, LPL16PARAMS p)
  185.32 +// Interpolation routines by default
  185.33 +static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
  185.34 +
  185.35 +// This is the default factory
  185.36 +static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory;
  185.37 +
  185.38 +
  185.39 +// Main plug-in entry
  185.40 +cmsBool  _cmsRegisterInterpPlugin(cmsPluginBase* Data)
  185.41  {
  185.42 -       p -> nSamples = nSamples;
  185.43 -       p -> Domain   = (WORD) (nSamples - 1);
  185.44 -       p -> nInputs = p -> nOutputs = 1;
  185.45 +    cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
  185.46  
  185.47 +    if (Data == NULL) {
  185.48 +
  185.49 +        Interpolators = DefaultInterpolatorsFactory;
  185.50 +        return TRUE;
  185.51 +    }
  185.52 +
  185.53 +    // Set replacement functions
  185.54 +    Interpolators = Plugin ->InterpolatorsFactory;
  185.55 +    return TRUE;
  185.56  }
  185.57  
  185.58  
  185.59 +// Set the interpolation method
  185.60 +static
  185.61 +cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
  185.62 +{
  185.63 +    // Invoke factory, possibly in the Plug-in
  185.64 +    p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
  185.65  
  185.66 -// Eval gray LUT having only one input channel
  185.67 +    // If unsupported by the plug-in, go for the LittleCMS default.
  185.68 +    // If happens only if an extern plug-in is being used
  185.69 +    if (p ->Interpolation.Lerp16 == NULL)
  185.70 +        p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags);
  185.71  
  185.72 -static
  185.73 -void Eval1Input(WORD StageABC[], WORD StageLMN[], WORD LutTable[], LPL16PARAMS p16)
  185.74 -{
  185.75 -       Fixed32 fk;
  185.76 -       Fixed32 k0, k1, rk, K0, K1;
  185.77 -       int OutChan;
  185.78 -
  185.79 -       fk = ToFixedDomain((Fixed32) StageABC[0] * p16 -> Domain);
  185.80 -       k0 = FIXED_TO_INT(fk);
  185.81 -       rk = (WORD) FIXED_REST_TO_INT(fk);
  185.82 -
  185.83 -       k1 = k0 + (StageABC[0] != 0xFFFFU ? 1 : 0);
  185.84 -
  185.85 -       K0 = p16 -> opta1 * k0;
  185.86 -       K1 = p16 -> opta1 * k1;
  185.87 -
  185.88 -       for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
  185.89 -
  185.90 -           StageLMN[OutChan] = (WORD) FixedLERP(rk, LutTable[K0+OutChan],
  185.91 -                                                    LutTable[K1+OutChan]);
  185.92 -       }
  185.93 +    // Check for valid interpolator (we just check one member of the union)
  185.94 +    if (p ->Interpolation.Lerp16 == NULL) {
  185.95 +            return FALSE;
  185.96 +    }
  185.97 +    return TRUE;
  185.98  }
  185.99  
 185.100  
 185.101 +// This function precalculates as many parameters as possible to speed up the interpolation.
 185.102 +cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
 185.103 +                                           const cmsUInt32Number nSamples[],
 185.104 +                                           int InputChan, int OutputChan,
 185.105 +                                           const void *Table,
 185.106 +                                           cmsUInt32Number dwFlags)
 185.107 +{
 185.108 +    cmsInterpParams* p;
 185.109 +    int i;
 185.110  
 185.111 -// For more that 3 inputs (i.e., CMYK)
 185.112 -// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
 185.113 +    // Check for maximum inputs
 185.114 +    if (InputChan > MAX_INPUT_DIMENSIONS) {
 185.115 +             cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS);
 185.116 +            return NULL;
 185.117 +    }
 185.118 +
 185.119 +    // Creates an empty object
 185.120 +    p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
 185.121 +    if (p == NULL) return NULL;
 185.122 +
 185.123 +    // Keep original parameters
 185.124 +    p -> dwFlags  = dwFlags;
 185.125 +    p -> nInputs  = InputChan;
 185.126 +    p -> nOutputs = OutputChan;
 185.127 +    p ->Table     = Table;
 185.128 +    p ->ContextID  = ContextID;
 185.129 +
 185.130 +    // Fill samples per input direction and domain (which is number of nodes minus one)
 185.131 +    for (i=0; i < InputChan; i++) {
 185.132 +
 185.133 +        p -> nSamples[i] = nSamples[i];
 185.134 +        p -> Domain[i]   = nSamples[i] - 1;
 185.135 +    }
 185.136 +
 185.137 +    // Compute factors to apply to each component to index the grid array
 185.138 +    p -> opta[0] = p -> nOutputs;
 185.139 +    for (i=1; i < InputChan; i++)
 185.140 +        p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
 185.141 +
 185.142 +
 185.143 +    if (!_cmsSetInterpolationRoutine(p)) {
 185.144 +         cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
 185.145 +        _cmsFree(ContextID, p);
 185.146 +        return NULL;
 185.147 +    }
 185.148 +
 185.149 +    // All seems ok
 185.150 +    return p;
 185.151 +}
 185.152 +
 185.153 +
 185.154 +// This one is a wrapper on the anterior, but assuming all directions have same number of nodes
 185.155 +cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags)
 185.156 +{
 185.157 +    int i;
 185.158 +    cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
 185.159 +
 185.160 +    // Fill the auxiliar array
 185.161 +    for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
 185.162 +        Samples[i] = nSamples;
 185.163 +
 185.164 +    // Call the extended function
 185.165 +    return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
 185.166 +}
 185.167 +
 185.168 +
 185.169 +// Free all associated memory
 185.170 +void _cmsFreeInterpParams(cmsInterpParams* p)
 185.171 +{
 185.172 +    if (p != NULL) _cmsFree(p ->ContextID, p);
 185.173 +}
 185.174 +
 185.175 +
 185.176 +// Inline fixed point interpolation
 185.177 +cmsINLINE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h)
 185.178 +{
 185.179 +    cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000;
 185.180 +    dif = (dif >> 16) + l;
 185.181 +    return (cmsUInt16Number) (dif);
 185.182 +}
 185.183 +
 185.184 +
 185.185 +//  Linear interpolation (Fixed-point optimized)
 185.186  static
 185.187 -void Eval4Inputs(WORD StageABC[], WORD StageLMN[], WORD LutTable[], LPL16PARAMS p16)
 185.188 +void LinLerp1D(register const cmsUInt16Number Value[],
 185.189 +               register cmsUInt16Number Output[],
 185.190 +               register const cmsInterpParams* p)
 185.191  {
 185.192 -       Fixed32 fk;
 185.193 -       Fixed32 k0, rk;
 185.194 -       int K0, K1;
 185.195 -       LPWORD T;
 185.196 -       int i;
 185.197 -       WORD Tmp1[MAXCHANNELS], Tmp2[MAXCHANNELS];
 185.198 +    cmsUInt16Number y1, y0;
 185.199 +    int cell0, rest;
 185.200 +    int val3;
 185.201 +    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
 185.202  
 185.203 +    // if last value...
 185.204 +    if (Value[0] == 0xffff) {
 185.205  
 185.206 -       fk = ToFixedDomain((Fixed32) StageABC[0] * p16 -> Domain);
 185.207 -       k0 = FIXED_TO_INT(fk);
 185.208 -       rk = FIXED_REST_TO_INT(fk);
 185.209 +        Output[0] = LutTable[p -> Domain[0]];
 185.210 +        return;
 185.211 +    }
 185.212  
 185.213 -       K0 = p16 -> opta4 * k0;
 185.214 -       K1 = p16 -> opta4 * (k0 + (StageABC[0] != 0xFFFFU ? 1 : 0));
 185.215 +    val3 = p -> Domain[0] * Value[0];
 185.216 +    val3 = _cmsToFixedDomain(val3);    // To fixed 15.16
 185.217  
 185.218 -       p16 -> nInputs = 3;
 185.219 +    cell0 = FIXED_TO_INT(val3);             // Cell is 16 MSB bits
 185.220 +    rest  = FIXED_REST_TO_INT(val3);        // Rest is 16 LSB bits
 185.221  
 185.222 -       T = LutTable + K0;
 185.223 +    y0 = LutTable[cell0];
 185.224 +    y1 = LutTable[cell0+1];
 185.225  
 185.226 -       cmsTetrahedralInterp16(StageABC + 1,  Tmp1, T, p16);
 185.227  
 185.228 +    Output[0] = LinearInterp(rest, y0, y1);
 185.229 +}
 185.230  
 185.231 -       T = LutTable + K1;
 185.232  
 185.233 -       cmsTetrahedralInterp16(StageABC + 1,  Tmp2, T, p16);
 185.234 +// Floating-point version of 1D interpolation
 185.235 +static
 185.236 +void LinLerp1Dfloat(const cmsFloat32Number Value[],
 185.237 +                    cmsFloat32Number Output[],
 185.238 +                    const cmsInterpParams* p)
 185.239 +{
 185.240 +       cmsFloat32Number y1, y0;
 185.241 +       cmsFloat32Number val2, rest;
 185.242 +       int cell0, cell1;
 185.243 +       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
 185.244  
 185.245 -
 185.246 -       p16 -> nInputs = 4;
 185.247 -       for (i=0; i < p16 -> nOutputs; i++)
 185.248 -       {
 185.249 -              StageLMN[i] = (WORD) FixedLERP(rk, Tmp1[i], Tmp2[i]);
 185.250 -
 185.251 +       // if last value...
 185.252 +       if (Value[0] == 1.0) {
 185.253 +           Output[0] = LutTable[p -> Domain[0]];
 185.254 +           return;
 185.255         }
 185.256  
 185.257 -}
 185.258 -
 185.259 -
 185.260 -static
 185.261 -void Eval5Inputs(WORD StageABC[], WORD StageLMN[], WORD LutTable[], LPL16PARAMS p16)
 185.262 -{
 185.263 -       Fixed32 fk;
 185.264 -       Fixed32 k0, rk;
 185.265 -       int K0, K1;
 185.266 -       LPWORD T;
 185.267 -       int i;
 185.268 -       WORD Tmp1[MAXCHANNELS], Tmp2[MAXCHANNELS];
 185.269 -
 185.270 -
 185.271 -       fk = ToFixedDomain((Fixed32) StageABC[0] * p16 -> Domain);
 185.272 -       k0 = FIXED_TO_INT(fk);
 185.273 -       rk = FIXED_REST_TO_INT(fk);
 185.274 -
 185.275 -       K0 = p16 -> opta5 * k0;
 185.276 -       K1 = p16 -> opta5 * (k0 + (StageABC[0] != 0xFFFFU ? 1 : 0));
 185.277 -
 185.278 -       p16 -> nInputs = 4;
 185.279 -
 185.280 -       T = LutTable + K0;
 185.281 -
 185.282 -       Eval4Inputs(StageABC + 1, Tmp1, T, p16);
 185.283 -
 185.284 -       T = LutTable + K1;
 185.285 -
 185.286 -       Eval4Inputs(StageABC + 1, Tmp2, T, p16);
 185.287 -
 185.288 -       p16 -> nInputs = 5;
 185.289 -       for (i=0; i < p16 -> nOutputs; i++)
 185.290 -       {
 185.291 -              StageLMN[i] = (WORD) FixedLERP(rk, Tmp1[i], Tmp2[i]);
 185.292 -
 185.293 -       }
 185.294 -
 185.295 -}
 185.296 -
 185.297 -
 185.298 -static
 185.299 -void Eval6Inputs(WORD StageABC[], WORD StageLMN[], WORD LutTable[], LPL16PARAMS p16)
 185.300 -{
 185.301 -       Fixed32 fk;
 185.302 -       Fixed32 k0, rk;
 185.303 -       int K0, K1;
 185.304 -       LPWORD T;
 185.305 -       int i;
 185.306 -       WORD Tmp1[MAXCHANNELS], Tmp2[MAXCHANNELS];
 185.307 -
 185.308 -
 185.309 -       fk = ToFixedDomain((Fixed32) StageABC[0] * p16 -> Domain);
 185.310 -       k0 = FIXED_TO_INT(fk);
 185.311 -       rk = FIXED_REST_TO_INT(fk);
 185.312 -
 185.313 -       K0 = p16 -> opta6 * k0;
 185.314 -       K1 = p16 -> opta6 * (k0 + (StageABC[0] != 0xFFFFU ? 1 : 0));
 185.315 -
 185.316 -       p16 -> nInputs = 5;
 185.317 -
 185.318 -       T = LutTable + K0;
 185.319 -
 185.320 -       Eval5Inputs(StageABC + 1, Tmp1, T, p16);
 185.321 -
 185.322 -       T = LutTable + K1;
 185.323 -
 185.324 -       Eval5Inputs(StageABC + 1, Tmp2, T, p16);
 185.325 -
 185.326 -       p16 -> nInputs = 6;
 185.327 -       for (i=0; i < p16 -> nOutputs; i++)
 185.328 -       {
 185.329 -              StageLMN[i] = (WORD) FixedLERP(rk, Tmp1[i], Tmp2[i]);
 185.330 -       }
 185.331 -
 185.332 -}
 185.333 -
 185.334 -static
 185.335 -void Eval7Inputs(WORD StageABC[], WORD StageLMN[], WORD LutTable[], LPL16PARAMS p16)
 185.336 -{
 185.337 -       Fixed32 fk;
 185.338 -       Fixed32 k0, rk;
 185.339 -       int K0, K1;
 185.340 -       LPWORD T;
 185.341 -       int i;
 185.342 -       WORD Tmp1[MAXCHANNELS], Tmp2[MAXCHANNELS];
 185.343 -
 185.344 -
 185.345 -       fk = ToFixedDomain((Fixed32) StageABC[0] * p16 -> Domain);
 185.346 -       k0 = FIXED_TO_INT(fk);
 185.347 -       rk = FIXED_REST_TO_INT(fk);
 185.348 -
 185.349 -       K0 = p16 -> opta7 * k0;
 185.350 -       K1 = p16 -> opta7 * (k0 + (StageABC[0] != 0xFFFFU ? 1 : 0));
 185.351 -
 185.352 -       p16 -> nInputs = 6;
 185.353 -
 185.354 -       T = LutTable + K0;
 185.355 -
 185.356 -       Eval6Inputs(StageABC + 1, Tmp1, T, p16);
 185.357 -
 185.358 -       T = LutTable + K1;
 185.359 -
 185.360 -       Eval6Inputs(StageABC + 1, Tmp2, T, p16);
 185.361 -
 185.362 -       p16 -> nInputs = 7;
 185.363 -       for (i=0; i < p16 -> nOutputs; i++)
 185.364 -       {
 185.365 -              StageLMN[i] = (WORD) FixedLERP(rk, Tmp1[i], Tmp2[i]);
 185.366 -       }
 185.367 -
 185.368 -}
 185.369 -
 185.370 -static
 185.371 -void Eval8Inputs(WORD StageABC[], WORD StageLMN[], WORD LutTable[], LPL16PARAMS p16)
 185.372 -{
 185.373 -       Fixed32 fk;
 185.374 -       Fixed32 k0, rk;
 185.375 -       int K0, K1;
 185.376 -       LPWORD T;
 185.377 -       int i;
 185.378 -       WORD Tmp1[MAXCHANNELS], Tmp2[MAXCHANNELS];
 185.379 -
 185.380 -
 185.381 -       fk = ToFixedDomain((Fixed32) StageABC[0] * p16 -> Domain);
 185.382 -       k0 = FIXED_TO_INT(fk);
 185.383 -       rk = FIXED_REST_TO_INT(fk);
 185.384 -
 185.385 -       K0 = p16 -> opta8 * k0;
 185.386 -       K1 = p16 -> opta8 * (k0 + (StageABC[0] != 0xFFFFU ? 1 : 0));
 185.387 -
 185.388 -       p16 -> nInputs = 7;
 185.389 -
 185.390 -       T = LutTable + K0;
 185.391 -
 185.392 -       Eval7Inputs(StageABC + 1, Tmp1, T, p16);
 185.393 -
 185.394 -       T = LutTable + K1;
 185.395 -
 185.396 -       Eval7Inputs(StageABC + 1, Tmp2, T, p16);
 185.397 -
 185.398 -       p16 -> nInputs = 8;
 185.399 -       for (i=0; i < p16 -> nOutputs; i++)
 185.400 -       {
 185.401 -              StageLMN[i] = (WORD) FixedLERP(rk, Tmp1[i], Tmp2[i]);
 185.402 -       }
 185.403 -
 185.404 -}
 185.405 -
 185.406 -
 185.407 -// Fills optimization parameters
 185.408 -
 185.409 -void cmsCalcCLUT16ParamsEx(int nSamples, int InputChan, int OutputChan,
 185.410 -                                            LCMSBOOL lUseTetrahedral, LPL16PARAMS p)
 185.411 -{
 185.412 -       int clutPoints;
 185.413 -
 185.414 -       cmsCalcL16Params(nSamples, p);
 185.415 -
 185.416 -       p -> nInputs  = InputChan;
 185.417 -       p -> nOutputs = OutputChan;
 185.418 -
 185.419 -       clutPoints = p -> Domain + 1;
 185.420 -
 185.421 -       p -> opta1 = p -> nOutputs;              // Z
 185.422 -       p -> opta2 = p -> opta1 * clutPoints;    // Y
 185.423 -       p -> opta3 = p -> opta2 * clutPoints;    // X
 185.424 -       p -> opta4 = p -> opta3 * clutPoints;    // Used only in 4 inputs LUT
 185.425 -       p -> opta5 = p -> opta4 * clutPoints;    // Used only in 5 inputs LUT
 185.426 -       p -> opta6 = p -> opta5 * clutPoints;    // Used only on 6 inputs LUT
 185.427 -       p -> opta7 = p -> opta6 * clutPoints;    // Used only on 7 inputs LUT
 185.428 -       p -> opta8 = p -> opta7 * clutPoints;    // Used only on 8 inputs LUT
 185.429 -
 185.430 -
 185.431 -       switch (InputChan) {
 185.432 -
 185.433 -
 185.434 -           case 1: // Gray LUT
 185.435 -
 185.436 -               p ->Interp3D = Eval1Input;
 185.437 -               break;
 185.438 -
 185.439 -           case 3:  // RGB et al
 185.440 -               if (lUseTetrahedral) {
 185.441 -                   p ->Interp3D = cmsTetrahedralInterp16;
 185.442 -               }
 185.443 -               else
 185.444 -                   p ->Interp3D = cmsTrilinearInterp16;
 185.445 -               break;
 185.446 -
 185.447 -           case 4:  // CMYK LUT
 185.448 -                p ->Interp3D = Eval4Inputs;
 185.449 -                break;
 185.450 -
 185.451 -           case 5: // 5 Inks
 185.452 -                p ->Interp3D = Eval5Inputs;
 185.453 -                break;
 185.454 -
 185.455 -           case 6: // 6 Inks
 185.456 -                p -> Interp3D = Eval6Inputs;
 185.457 -                break;
 185.458 -
 185.459 -            case 7: // 7 inks
 185.460 -                p ->Interp3D = Eval7Inputs;
 185.461 -                break;
 185.462 -
 185.463 -           case 8: // 8 inks
 185.464 -                p ->Interp3D = Eval8Inputs;
 185.465 -                break;
 185.466 -
 185.467 -           default:
 185.468 -                cmsSignalError(LCMS_ERRC_ABORTED, "Unsupported restoration (%d channels)", InputChan);
 185.469 -           }
 185.470 -
 185.471 -}
 185.472 -
 185.473 -
 185.474 -void cmsCalcCLUT16Params(int nSamples, int InputChan, int OutputChan, LPL16PARAMS p)
 185.475 -{
 185.476 -    cmsCalcCLUT16ParamsEx(nSamples, InputChan, OutputChan, FALSE, p);
 185.477 -}
 185.478 -
 185.479 -
 185.480 -
 185.481 -#ifdef USE_FLOAT
 185.482 -
 185.483 -
 185.484 -// Floating-point version
 185.485 -
 185.486 -WORD cmsLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p)
 185.487 -{
 185.488 -       double y1, y0;
 185.489 -       double y;
 185.490 -       double val2, rest;
 185.491 -       int cell0, cell1;
 185.492 -
 185.493 -       // if last value...
 185.494 -
 185.495 -       if (Value == 0xffff) return LutTable[p -> Domain];
 185.496 -
 185.497 -       val2 = p -> Domain * ((double) Value / 65535.0);
 185.498 +       val2 = p -> Domain[0] * Value[0];
 185.499  
 185.500         cell0 = (int) floor(val2);
 185.501         cell1 = (int) ceil(val2);
 185.502  
 185.503         // Rest is 16 LSB bits
 185.504 -
 185.505         rest = val2 - cell0;
 185.506  
 185.507         y0 = LutTable[cell0] ;
 185.508         y1 = LutTable[cell1] ;
 185.509  
 185.510 -       y = y0 + (y1 - y0) * rest;
 185.511 -
 185.512 -
 185.513 -       return (WORD) floor(y+.5);
 185.514 +       Output[0] = y0 + (y1 - y0) * rest;
 185.515  }
 185.516  
 185.517 -#endif
 185.518  
 185.519  
 185.520 -//
 185.521 -//  Linear interpolation (Fixed-point optimized, but C source)
 185.522 -//
 185.523 +// Eval gray LUT having only one input channel
 185.524 +static
 185.525 +void Eval1Input(register const cmsUInt16Number Input[],
 185.526 +                register cmsUInt16Number Output[],
 185.527 +                register const cmsInterpParams* p16)
 185.528 +{
 185.529 +       cmsS15Fixed16Number fk;
 185.530 +       cmsS15Fixed16Number k0, k1, rk, K0, K1;
 185.531 +       int v;
 185.532 +       cmsUInt32Number OutChan;
 185.533 +       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
 185.534  
 185.535 +       v = Input[0] * p16 -> Domain[0];
 185.536 +       fk = _cmsToFixedDomain(v);
 185.537  
 185.538 -#ifdef USE_C
 185.539 +       k0 = FIXED_TO_INT(fk);
 185.540 +       rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
 185.541  
 185.542 -WORD cmsLinearInterpLUT16(WORD Value1, WORD LutTable[], LPL16PARAMS p)
 185.543 +       k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
 185.544 +
 185.545 +       K0 = p16 -> opta[0] * k0;
 185.546 +       K1 = p16 -> opta[0] * k1;
 185.547 +
 185.548 +       for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
 185.549 +
 185.550 +           Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
 185.551 +       }
 185.552 +}
 185.553 +
 185.554 +
 185.555 +
 185.556 +// Eval gray LUT having only one input channel
 185.557 +static
 185.558 +void Eval1InputFloat(const cmsFloat32Number Value[],
 185.559 +                     cmsFloat32Number Output[],
 185.560 +                     const cmsInterpParams* p)
 185.561  {
 185.562 -       WORD y1, y0;
 185.563 -       WORD y;
 185.564 -       int dif, a1;
 185.565 -       int cell0, rest;
 185.566 -       int val3, Value;
 185.567 +    cmsFloat32Number y1, y0;
 185.568 +    cmsFloat32Number val2, rest;
 185.569 +    int cell0, cell1;
 185.570 +    cmsUInt32Number OutChan;
 185.571 +    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
 185.572  
 185.573 -       // if last value...
 185.574 -
 185.575 -
 185.576 -       Value = Value1;
 185.577 -       if (Value == 0xffff) return LutTable[p -> Domain];
 185.578 -
 185.579 -       val3 = p -> Domain * Value;
 185.580 -       val3 = ToFixedDomain(val3);              // To fixed 15.16
 185.581 -
 185.582 -       cell0 = FIXED_TO_INT(val3);             // Cell is 16 MSB bits
 185.583 -       rest  = FIXED_REST_TO_INT(val3);        // Rest is 16 LSB bits
 185.584 -
 185.585 -       y0 = LutTable[cell0] ;
 185.586 -       y1 = LutTable[cell0+1] ;
 185.587 -
 185.588 -       dif = (int) y1 - y0;        // dif is in domain -ffff ... ffff
 185.589 -
 185.590 -       if (dif >= 0)
 185.591 -       {
 185.592 -       a1 = ToFixedDomain(dif * rest);
 185.593 -       a1 += 0x8000;
 185.594 -       }
 185.595 -       else
 185.596 -       {
 185.597 -              a1 = ToFixedDomain((- dif) * rest);
 185.598 -              a1 -= 0x8000;
 185.599 -              a1 = -a1;
 185.600 +        // if last value...
 185.601 +       if (Value[0] == 1.0) {
 185.602 +           Output[0] = LutTable[p -> Domain[0]];
 185.603 +           return;
 185.604         }
 185.605  
 185.606 -       y = (WORD) (y0 + FIXED_TO_INT(a1));
 185.607 +       val2 = p -> Domain[0] * Value[0];
 185.608  
 185.609 -       return y;
 185.610 +       cell0 = (int) floor(val2);
 185.611 +       cell1 = (int) ceil(val2);
 185.612 +
 185.613 +       // Rest is 16 LSB bits
 185.614 +       rest = val2 - cell0;
 185.615 +
 185.616 +       cell0 *= p -> opta[0];
 185.617 +       cell1 *= p -> opta[0];
 185.618 +
 185.619 +       for (OutChan=0; OutChan < p->nOutputs; OutChan++) {
 185.620 +
 185.621 +            y0 = LutTable[cell0 + OutChan] ;
 185.622 +            y1 = LutTable[cell1 + OutChan] ;
 185.623 +
 185.624 +            Output[OutChan] = y0 + (y1 - y0) * rest;
 185.625 +       }
 185.626  }
 185.627  
 185.628 -#endif
 185.629  
 185.630 -// Linear interpolation (asm by hand optimized)
 185.631  
 185.632 -#ifdef USE_ASSEMBLER
 185.633 -
 185.634 -#ifdef _MSC_VER
 185.635 -#pragma warning(disable : 4033)
 185.636 -#pragma warning(disable : 4035)
 185.637 -#endif
 185.638 -
 185.639 -WORD cmsLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p)
 185.640 -{
 185.641 -       int xDomain = p -> Domain;
 185.642 -
 185.643 -
 185.644 -       if (Value == 0xffff) return LutTable[p -> Domain];
 185.645 -       else
 185.646 -       ASM {
 185.647 -              xor       eax, eax
 185.648 -              mov       ax, word ptr ss:Value
 185.649 -              mov       edx, ss:xDomain
 185.650 -              mul       edx                         //  val3 = p -> Domain * Value;
 185.651 -              shld      edx, eax, 16                // Convert it to fixed 15.16
 185.652 -              shl       eax, 16                     // * 65536 / 65535
 185.653 -              mov       ebx, 0x0000ffff
 185.654 -              div       ebx
 185.655 -              mov       ecx, eax
 185.656 -              sar       ecx, 16                        // ecx = cell0
 185.657 -              mov       edx, eax                       // rest = (val2 & 0xFFFFU)
 185.658 -              and       edx, 0x0000ffff                // edx = rest
 185.659 -              mov       ebx, ss:LutTable
 185.660 -              lea       eax, dword ptr [ebx+2*ecx]     // Ptr to LUT
 185.661 -              xor       ebx, ebx
 185.662 -              mov        bx, word  ptr [eax]           // EBX = y0
 185.663 -              movzx     eax, word  ptr [eax+2]         // EAX = y1
 185.664 -              sub       eax, ebx                       // EAX = y1-y0
 185.665 -              js        IsNegative
 185.666 -              mul       edx                            // EAX = EAX * rest
 185.667 -              shld      edx, eax, 16                   // Pass it to fixed
 185.668 -              sal       eax, 16                        // * 65536 / 65535
 185.669 -              mov       ecx, 0x0000ffff
 185.670 -              div       ecx
 185.671 -              add       eax, 0x8000                    // Rounding
 185.672 -              sar       eax, 16
 185.673 -              add       eax, ebx                       // Done!
 185.674 -              }
 185.675 -
 185.676 -              RET((WORD) _EAX);
 185.677 -
 185.678 -       IsNegative:
 185.679 -
 185.680 -              ASM {
 185.681 -              neg       eax
 185.682 -              mul       edx                            // EAX = EAX * rest
 185.683 -              shld      edx, eax, 16                   // Pass it to fixed
 185.684 -              sal       eax, 16                        // * 65536 / 65535
 185.685 -              mov       ecx, 0x0000ffff
 185.686 -              div       ecx
 185.687 -              sub       eax, 0x8000
 185.688 -              neg       eax
 185.689 -              sar       eax, 16
 185.690 -              add       eax, ebx                       // Done!
 185.691 -              }
 185.692 -
 185.693 -              RET((WORD) _EAX);
 185.694 -}
 185.695 -
 185.696 -#ifdef _MSC_VER
 185.697 -#pragma warning(default : 4033)
 185.698 -#pragma warning(default : 4035)
 185.699 -#endif
 185.700 -
 185.701 -#endif
 185.702 -
 185.703 -Fixed32 cmsLinearInterpFixed(WORD Value1, WORD LutTable[], LPL16PARAMS p)
 185.704 -{
 185.705 -       Fixed32 y1, y0;
 185.706 -       int cell0;
 185.707 -       int val3, Value;
 185.708 -
 185.709 -       // if last value...
 185.710 -
 185.711 -
 185.712 -       Value = Value1;
 185.713 -       if (Value == 0xffffU) return LutTable[p -> Domain];
 185.714 -
 185.715 -       val3 = p -> Domain * Value;
 185.716 -       val3 = ToFixedDomain(val3);              // To fixed 15.16
 185.717 -
 185.718 -       cell0 = FIXED_TO_INT(val3);             // Cell is 16 MSB bits
 185.719 -
 185.720 -       y0 = LutTable[cell0] ;
 185.721 -       y1 = LutTable[cell0+1] ;
 185.722 -
 185.723 -
 185.724 -       return y0 + FixedMul((y1 - y0), (val3 & 0xFFFFL));
 185.725 -}
 185.726 -
 185.727 -
 185.728 -// Reverse Lineal interpolation (16 bits)
 185.729 -// Im using a sort of binary search here, this is not a time-critical function
 185.730 -
 185.731 -WORD cmsReverseLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p)
 185.732 -{
 185.733 -        register int l = 1;
 185.734 -        register int r = 0x10000;
 185.735 -        register int x = 0, res;       // 'int' Give spacing for negative values
 185.736 -        int NumZeroes, NumPoles;
 185.737 -        int cell0, cell1;
 185.738 -        double val2;
 185.739 -        double y0, y1, x0, x1;
 185.740 -        double a, b, f;
 185.741 -
 185.742 -        // July/27 2001 - Expanded to handle degenerated curves with an arbitrary
 185.743 -        // number of elements containing 0 at the begining of the table (Zeroes)
 185.744 -        // and another arbitrary number of poles (FFFFh) at the end.
 185.745 -        // First the zero and pole extents are computed, then value is compared.
 185.746 -
 185.747 -        NumZeroes = 0;
 185.748 -        while (LutTable[NumZeroes] == 0 && NumZeroes < p -> Domain)
 185.749 -                        NumZeroes++;
 185.750 -
 185.751 -        // There are no zeros at the beginning and we are trying to find a zero, so
 185.752 -        // return anything. It seems zero would be the less destructive choice
 185.753 -
 185.754 -        if (NumZeroes == 0 && Value == 0)
 185.755 -            return 0;
 185.756 -
 185.757 -        NumPoles = 0;
 185.758 -        while (LutTable[p -> Domain - NumPoles] == 0xFFFF && NumPoles < p -> Domain)
 185.759 -                        NumPoles++;
 185.760 -
 185.761 -        // Does the curve belong to this case?
 185.762 -        if (NumZeroes > 1 || NumPoles > 1)
 185.763 -        {
 185.764 -                int a, b;
 185.765 -
 185.766 -                // Identify if value fall downto 0 or FFFF zone
 185.767 -                if (Value == 0) return 0;
 185.768 -               // if (Value == 0xFFFF) return 0xFFFF;
 185.769 -
 185.770 -                // else restrict to valid zone
 185.771 -
 185.772 -                a = ((NumZeroes-1) * 0xFFFF) / p->Domain;
 185.773 -                b = ((p -> Domain - NumPoles) * 0xFFFF) / p ->Domain;
 185.774 -
 185.775 -                l = a - 1;
 185.776 -                r = b + 1;
 185.777 -        }
 185.778 -
 185.779 -
 185.780 -        // Seems not a degenerated case... apply binary search
 185.781 -
 185.782 -        while (r > l) {
 185.783 -
 185.784 -                x = (l + r) / 2;
 185.785 -
 185.786 -                res = (int) cmsLinearInterpLUT16((WORD) (x - 1), LutTable, p);
 185.787 -
 185.788 -                if (res == Value) {
 185.789 -
 185.790 -                    // Found exact match.
 185.791 -
 185.792 -                    return (WORD) (x - 1);
 185.793 -                }
 185.794 -
 185.795 -                if (res > Value) r = x - 1;
 185.796 -                else l = x + 1;
 185.797 -        }
 185.798 -
 185.799 -        // Not found, should we interpolate?
 185.800 -
 185.801 -
 185.802 -        // Get surrounding nodes
 185.803 -
 185.804 -        val2 = p -> Domain * ((double) (x - 1) / 65535.0);
 185.805 -
 185.806 -        cell0 = (int) floor(val2);
 185.807 -        cell1 = (int) ceil(val2);
 185.808 -
 185.809 -        if (cell0 == cell1) return (WORD) x;
 185.810 -
 185.811 -        y0 = LutTable[cell0] ;
 185.812 -        x0 = (65535.0 * cell0) / p ->Domain;
 185.813 -
 185.814 -        y1 = LutTable[cell1] ;
 185.815 -        x1 = (65535.0 * cell1) / p ->Domain;
 185.816 -
 185.817 -        a = (y1 - y0) / (x1 - x0);
 185.818 -        b = y0 - a * x0;
 185.819 -
 185.820 -        if (fabs(a) < 0.01) return (WORD) x;
 185.821 -
 185.822 -        f = ((Value - b) / a);
 185.823 -
 185.824 -        if (f < 0.0) return (WORD) 0;
 185.825 -        if (f >= 65535.0) return (WORD) 0xFFFF;
 185.826 -
 185.827 -        return (WORD) floor(f + 0.5);
 185.828 -
 185.829 -}
 185.830 -
 185.831 -
 185.832 -
 185.833 -
 185.834 -// Trilinear interpolation (16 bits) - float version
 185.835 -
 185.836 -#ifdef USE_FLOAT
 185.837 -void cmsTrilinearInterp16(WORD Input[], WORD Output[],
 185.838 -                            WORD LutTable[], LPL16PARAMS p)
 185.839 +// Trilinear interpolation (16 bits) - cmsFloat32Number version
 185.840 +static
 185.841 +void TrilinearInterpFloat(const cmsFloat32Number Input[],
 185.842 +                          cmsFloat32Number Output[],
 185.843 +                          const cmsInterpParams* p)
 185.844  
 185.845  {
 185.846 -#   define LERP(a,l,h)  (double) ((l)+(((h)-(l))*(a)))
 185.847 -#   define DENS(X, Y, Z)    (double) (LutTable[TotalOut*((Z)+clutPoints*((Y)+clutPoints*(X)))+OutChan])
 185.848 +#   define LERP(a,l,h)      (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
 185.849 +#   define DENS(i,j,k)      (LutTable[(i)+(j)+(k)+OutChan])
 185.850  
 185.851 -
 185.852 -
 185.853 -    double     px, py, pz;
 185.854 +    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
 185.855 +    cmsFloat32Number      px, py, pz;
 185.856      int        x0, y0, z0,
 185.857 -               x1, y1, z1;
 185.858 -               int clutPoints, TotalOut, OutChan;
 185.859 -    double     fx, fy, fz,
 185.860 -               d000, d001, d010, d011,
 185.861 -               d100, d101, d110, d111,
 185.862 -               dx00, dx01, dx10, dx11,
 185.863 -               dxy0, dxy1, dxyz;
 185.864 -
 185.865 -
 185.866 -    clutPoints = p -> Domain + 1;
 185.867 -    TotalOut   = p -> nOutputs;
 185.868 -
 185.869 -    px = ((double) Input[0] * (p->Domain)) / 65535.0;
 185.870 -    py = ((double) Input[1] * (p->Domain)) / 65535.0;
 185.871 -    pz = ((double) Input[2] * (p->Domain)) / 65535.0;
 185.872 -
 185.873 -    x0 = (int) _cmsQuickFloor(px); fx = px - (double) x0;
 185.874 -    y0 = (int) _cmsQuickFloor(py); fy = py - (double) y0;
 185.875 -    z0 = (int) _cmsQuickFloor(pz); fz = pz - (double) z0;
 185.876 -
 185.877 -    x1 = x0 + (Input[0] != 0xFFFFU ? 1 : 0);
 185.878 -    y1 = y0 + (Input[1] != 0xFFFFU ? 1 : 0);
 185.879 -    z1 = z0 + (Input[2] != 0xFFFFU ? 1 : 0);
 185.880 -
 185.881 -
 185.882 -    for (OutChan = 0; OutChan < TotalOut; OutChan++)
 185.883 -    {
 185.884 -
 185.885 -        d000 = DENS(x0, y0, z0);
 185.886 -        d001 = DENS(x0, y0, z1);
 185.887 -        d010 = DENS(x0, y1, z0);
 185.888 -        d011 = DENS(x0, y1, z1);
 185.889 -
 185.890 -        d100 = DENS(x1, y0, z0);
 185.891 -        d101 = DENS(x1, y0, z1);
 185.892 -        d110 = DENS(x1, y1, z0);
 185.893 -        d111 = DENS(x1, y1, z1);
 185.894 -
 185.895 -
 185.896 -    dx00 = LERP(fx, d000, d100);
 185.897 -    dx01 = LERP(fx, d001, d101);
 185.898 -    dx10 = LERP(fx, d010, d110);
 185.899 -    dx11 = LERP(fx, d011, d111);
 185.900 -
 185.901 -    dxy0 = LERP(fy, dx00, dx10);
 185.902 -    dxy1 = LERP(fy, dx01, dx11);
 185.903 -
 185.904 -    dxyz = LERP(fz, dxy0, dxy1);
 185.905 -
 185.906 -    Output[OutChan] = (WORD) floor(dxyz + .5);
 185.907 -    }
 185.908 -
 185.909 -
 185.910 -#   undef LERP
 185.911 -#   undef DENS
 185.912 -}
 185.913 -
 185.914 -
 185.915 -#endif
 185.916 -
 185.917 -
 185.918 -#ifndef USE_FLOAT
 185.919 -
 185.920 -// Trilinear interpolation (16 bits) - optimized version
 185.921 -
 185.922 -void cmsTrilinearInterp16(WORD Input[], WORD Output[],
 185.923 -                            WORD LutTable[], LPL16PARAMS p)
 185.924 -
 185.925 -{
 185.926 -#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
 185.927 -#define LERP(a,l,h)     (WORD) (l+ ROUND_FIXED_TO_INT(((h-l)*a)))
 185.928 -
 185.929 -
 185.930 -           int        OutChan, TotalOut;
 185.931 -           Fixed32    fx, fy, fz;
 185.932 -  register int        rx, ry, rz;
 185.933 -           int        x0, y0, z0;
 185.934 -  register int        X0, X1, Y0, Y1, Z0, Z1;
 185.935 -           int        d000, d001, d010, d011,
 185.936 -                      d100, d101, d110, d111,
 185.937 -                      dx00, dx01, dx10, dx11,
 185.938 -                      dxy0, dxy1, dxyz;
 185.939 -
 185.940 +               X0, Y0, Z0, X1, Y1, Z1;
 185.941 +    int        TotalOut, OutChan;
 185.942 +    cmsFloat32Number      fx, fy, fz,
 185.943 +        d000, d001, d010, d011,
 185.944 +        d100, d101, d110, d111,
 185.945 +        dx00, dx01, dx10, dx11,
 185.946 +        dxy0, dxy1, dxyz;
 185.947  
 185.948      TotalOut   = p -> nOutputs;
 185.949  
 185.950 -    fx = ToFixedDomain((int) Input[0] * p -> Domain);
 185.951 -    x0  = FIXED_TO_INT(fx);
 185.952 -    rx  = FIXED_REST_TO_INT(fx);    // Rest in 0..1.0 domain
 185.953 +    px = Input[0] * p->Domain[0];
 185.954 +    py = Input[1] * p->Domain[1];
 185.955 +    pz = Input[2] * p->Domain[2];
 185.956  
 185.957 +    x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
 185.958 +    y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
 185.959 +    z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0;
 185.960  
 185.961 -    fy = ToFixedDomain((int) Input[1] * p -> Domain);
 185.962 -    y0  = FIXED_TO_INT(fy);
 185.963 -    ry  = FIXED_REST_TO_INT(fy);
 185.964 +    X0 = p -> opta[2] * x0;
 185.965 +    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
 185.966  
 185.967 -    fz = ToFixedDomain((int) Input[2] * p -> Domain);
 185.968 -    z0 = FIXED_TO_INT(fz);
 185.969 -    rz = FIXED_REST_TO_INT(fz);
 185.970 +    Y0 = p -> opta[1] * y0;
 185.971 +    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
 185.972  
 185.973 +    Z0 = p -> opta[0] * z0;
 185.974 +    Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
 185.975  
 185.976 -
 185.977 -    X0 = p -> opta3 * x0;
 185.978 -    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta3);
 185.979 -
 185.980 -    Y0 = p -> opta2 * y0;
 185.981 -    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta2);
 185.982 -
 185.983 -    Z0 = p -> opta1 * z0;
 185.984 -    Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta1);
 185.985 -
 185.986 -
 185.987 -
 185.988 -    for (OutChan = 0; OutChan < TotalOut; OutChan++)
 185.989 -    {
 185.990 +    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
 185.991  
 185.992          d000 = DENS(X0, Y0, Z0);
 185.993          d001 = DENS(X0, Y0, Z1);
 185.994 @@ -785,6 +373,83 @@
 185.995          d111 = DENS(X1, Y1, Z1);
 185.996  
 185.997  
 185.998 +        dx00 = LERP(fx, d000, d100);
 185.999 +        dx01 = LERP(fx, d001, d101);
185.1000 +        dx10 = LERP(fx, d010, d110);
185.1001 +        dx11 = LERP(fx, d011, d111);
185.1002 +
185.1003 +        dxy0 = LERP(fy, dx00, dx10);
185.1004 +        dxy1 = LERP(fy, dx01, dx11);
185.1005 +
185.1006 +        dxyz = LERP(fz, dxy0, dxy1);
185.1007 +
185.1008 +        Output[OutChan] = dxyz;
185.1009 +    }
185.1010 +
185.1011 +
185.1012 +#   undef LERP
185.1013 +#   undef DENS
185.1014 +}
185.1015 +
185.1016 +// Trilinear interpolation (16 bits) - optimized version
185.1017 +static
185.1018 +void TrilinearInterp16(register const cmsUInt16Number Input[],
185.1019 +                       register cmsUInt16Number Output[],
185.1020 +                       register const cmsInterpParams* p)
185.1021 +
185.1022 +{
185.1023 +#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
185.1024 +#define LERP(a,l,h)     (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
185.1025 +
185.1026 +           const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
185.1027 +           int        OutChan, TotalOut;
185.1028 +           cmsS15Fixed16Number    fx, fy, fz;
185.1029 +  register int        rx, ry, rz;
185.1030 +           int        x0, y0, z0;
185.1031 +  register int        X0, X1, Y0, Y1, Z0, Z1;
185.1032 +           int        d000, d001, d010, d011,
185.1033 +                      d100, d101, d110, d111,
185.1034 +                      dx00, dx01, dx10, dx11,
185.1035 +                      dxy0, dxy1, dxyz;
185.1036 +
185.1037 +    TotalOut   = p -> nOutputs;
185.1038 +
185.1039 +    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
185.1040 +    x0  = FIXED_TO_INT(fx);
185.1041 +    rx  = FIXED_REST_TO_INT(fx);    // Rest in 0..1.0 domain
185.1042 +
185.1043 +
185.1044 +    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
185.1045 +    y0  = FIXED_TO_INT(fy);
185.1046 +    ry  = FIXED_REST_TO_INT(fy);
185.1047 +
185.1048 +    fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
185.1049 +    z0 = FIXED_TO_INT(fz);
185.1050 +    rz = FIXED_REST_TO_INT(fz);
185.1051 +
185.1052 +
185.1053 +    X0 = p -> opta[2] * x0;
185.1054 +    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
185.1055 +
185.1056 +    Y0 = p -> opta[1] * y0;
185.1057 +    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
185.1058 +
185.1059 +    Z0 = p -> opta[0] * z0;
185.1060 +    Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
185.1061 +
185.1062 +    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
185.1063 +
185.1064 +        d000 = DENS(X0, Y0, Z0);
185.1065 +        d001 = DENS(X0, Y0, Z1);
185.1066 +        d010 = DENS(X0, Y1, Z0);
185.1067 +        d011 = DENS(X0, Y1, Z1);
185.1068 +
185.1069 +        d100 = DENS(X1, Y0, Z0);
185.1070 +        d101 = DENS(X1, Y0, Z1);
185.1071 +        d110 = DENS(X1, Y1, Z0);
185.1072 +        d111 = DENS(X1, Y1, Z1);
185.1073 +
185.1074 +
185.1075          dx00 = LERP(rx, d000, d100);
185.1076          dx01 = LERP(rx, d001, d101);
185.1077          dx10 = LERP(rx, d010, d110);
185.1078 @@ -795,7 +460,7 @@
185.1079  
185.1080          dxyz = LERP(rz, dxy0, dxy1);
185.1081  
185.1082 -        Output[OutChan] = (WORD) dxyz;
185.1083 +        Output[OutChan] = (cmsUInt16Number) dxyz;
185.1084      }
185.1085  
185.1086  
185.1087 @@ -803,133 +468,128 @@
185.1088  #   undef DENS
185.1089  }
185.1090  
185.1091 -#endif
185.1092 -
185.1093 -
185.1094 -#ifdef USE_FLOAT
185.1095 -
185.1096 -#define DENS(X, Y, Z)    (double) (LutTable[TotalOut*((Z)+clutPoints*((Y)+clutPoints*(X)))+OutChan])
185.1097 -
185.1098  
185.1099  // Tetrahedral interpolation, using Sakamoto algorithm.
185.1100 +#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
185.1101 +static
185.1102 +void TetrahedralInterpFloat(const cmsFloat32Number Input[],
185.1103 +                            cmsFloat32Number Output[],
185.1104 +                            const cmsInterpParams* p)
185.1105 +{
185.1106 +    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
185.1107 +    cmsFloat32Number     px, py, pz;
185.1108 +    int        x0, y0, z0,
185.1109 +               X0, Y0, Z0, X1, Y1, Z1;
185.1110 +    cmsFloat32Number     rx, ry, rz;
185.1111 +    cmsFloat32Number     c0, c1=0, c2=0, c3=0;
185.1112 +    int                  OutChan, TotalOut;
185.1113  
185.1114 -void cmsTetrahedralInterp16(WORD Input[],
185.1115 -                            WORD Output[],
185.1116 -                            WORD LutTable[],
185.1117 -                            LPL16PARAMS p)
185.1118 -{
185.1119 -    double     px, py, pz;
185.1120 -    int        x0, y0, z0,
185.1121 -               x1, y1, z1;
185.1122 -    double     fx, fy, fz;
185.1123 -    double     c1=0, c2=0, c3=0;
185.1124 -    int        clutPoints, OutChan, TotalOut;
185.1125 -
185.1126 -
185.1127 -    clutPoints = p -> Domain + 1;
185.1128      TotalOut   = p -> nOutputs;
185.1129  
185.1130 +    px = Input[0] * p->Domain[0];
185.1131 +    py = Input[1] * p->Domain[1];
185.1132 +    pz = Input[2] * p->Domain[2];
185.1133  
185.1134 -    px = ((double) Input[0] * p->Domain) / 65535.0;
185.1135 -    py = ((double) Input[1] * p->Domain) / 65535.0;
185.1136 -    pz = ((double) Input[2] * p->Domain) / 65535.0;
185.1137 +    x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
185.1138 +    y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
185.1139 +    z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0);
185.1140  
185.1141 -    x0 = (int) _cmsQuickFloor(px); fx = (px - (double) x0);
185.1142 -    y0 = (int) _cmsQuickFloor(py); fy = (py - (double) y0);
185.1143 -    z0 = (int) _cmsQuickFloor(pz); fz = (pz - (double) z0);
185.1144  
185.1145 +    X0 = p -> opta[2] * x0;
185.1146 +    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
185.1147  
185.1148 -    x1 = x0 + (Input[0] != 0xFFFFU ? 1 : 0);
185.1149 -    y1 = y0 + (Input[1] != 0xFFFFU ? 1 : 0);
185.1150 -    z1 = z0 + (Input[2] != 0xFFFFU ? 1 : 0);
185.1151 +    Y0 = p -> opta[1] * y0;
185.1152 +    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
185.1153  
185.1154 +    Z0 = p -> opta[0] * z0;
185.1155 +    Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
185.1156  
185.1157 -    for (OutChan=0; OutChan < TotalOut; OutChan++)
185.1158 -    {
185.1159 +    for (OutChan=0; OutChan < TotalOut; OutChan++) {
185.1160  
185.1161         // These are the 6 Tetrahedral
185.1162  
185.1163 -       if (fx >= fy && fy >= fz)
185.1164 -       {
185.1165 -              c1 = DENS(x1, y0, z0) - DENS(x0, y0, z0);
185.1166 -              c2 = DENS(x1, y1, z0) - DENS(x1, y0, z0);
185.1167 -              c3 = DENS(x1, y1, z1) - DENS(x1, y1, z0);
185.1168 -       }
185.1169 -       else
185.1170 -       if (fx >= fz && fz >= fy)
185.1171 -       {
185.1172 -              c1 = DENS(x1, y0, z0) - DENS(x0, y0, z0);
185.1173 -              c2 = DENS(x1, y1, z1) - DENS(x1, y0, z1);
185.1174 -              c3 = DENS(x1, y0, z1) - DENS(x1, y0, z0);
185.1175 -       }
185.1176 -       else
185.1177 -       if (fz >= fx && fx >= fy)
185.1178 -       {
185.1179 -              c1 = DENS(x1, y0, z1) - DENS(x0, y0, z1);
185.1180 -              c2 = DENS(x1, y1, z1) - DENS(x1, y0, z1);
185.1181 -              c3 = DENS(x0, y0, z1) - DENS(x0, y0, z0);
185.1182 -       }
185.1183 -       else
185.1184 -       if (fy >= fx && fx >= fz)
185.1185 -       {
185.1186 -              c1 = DENS(x1, y1, z0) - DENS(x0, y1, z0);
185.1187 -              c2 = DENS(x0, y1, z0) - DENS(x0, y0, z0);
185.1188 -              c3 = DENS(x1, y1, z1) - DENS(x1, y1, z0);
185.1189 +        c0 = DENS(X0, Y0, Z0);
185.1190  
185.1191 -       }
185.1192 -       else
185.1193 -       if (fy >= fz && fz >= fx)
185.1194 -       {
185.1195 -              c1 = DENS(x1, y1, z1) - DENS(x0, y1, z1);
185.1196 -              c2 = DENS(x0, y1, z0) - DENS(x0, y0, z0);
185.1197 -              c3 = DENS(x0, y1, z1) - DENS(x0, y1, z0);
185.1198 -       }
185.1199 -       else
185.1200 -       if (fz >= fy && fy >= fx)
185.1201 -       {
185.1202 -              c1 = DENS(x1, y1, z1) - DENS(x0, y1, z1);
185.1203 -              c2 = DENS(x0, y1, z1) - DENS(x0, y0, z1);
185.1204 -              c3 = DENS(x0, y0, z1) - DENS(x0, y0, z0);
185.1205 -       }
185.1206 -       else
185.1207 -       {
185.1208 -         c1 = c2 = c3 = 0;
185.1209 -       //  assert(FALSE);
185.1210 -       }
185.1211 +        if (rx >= ry && ry >= rz) {
185.1212  
185.1213 +            c1 = DENS(X1, Y0, Z0) - c0;
185.1214 +            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
185.1215 +            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1216  
185.1217 -       Output[OutChan] = (WORD) floor((double) DENS(x0,y0,z0) + c1 * fx + c2 * fy + c3 * fz + .5);
185.1218 +        }
185.1219 +        else
185.1220 +            if (rx >= rz && rz >= ry) {
185.1221 +
185.1222 +                c1 = DENS(X1, Y0, Z0) - c0;
185.1223 +                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1224 +                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
185.1225 +
185.1226 +            }
185.1227 +            else
185.1228 +                if (rz >= rx && rx >= ry) {
185.1229 +
185.1230 +                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
185.1231 +                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1232 +                    c3 = DENS(X0, Y0, Z1) - c0;
185.1233 +
185.1234 +                }
185.1235 +                else
185.1236 +                    if (ry >= rx && rx >= rz) {
185.1237 +
185.1238 +                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
185.1239 +                        c2 = DENS(X0, Y1, Z0) - c0;
185.1240 +                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1241 +
185.1242 +                    }
185.1243 +                    else
185.1244 +                        if (ry >= rz && rz >= rx) {
185.1245 +
185.1246 +                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1247 +                            c2 = DENS(X0, Y1, Z0) - c0;
185.1248 +                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
185.1249 +
185.1250 +                        }
185.1251 +                        else
185.1252 +                            if (rz >= ry && ry >= rx) {
185.1253 +
185.1254 +                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1255 +                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
185.1256 +                                c3 = DENS(X0, Y0, Z1) - c0;
185.1257 +
185.1258 +                            }
185.1259 +                            else  {
185.1260 +                                c1 = c2 = c3 = 0;
185.1261 +                            }
185.1262 +
185.1263 +       Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
185.1264         }
185.1265  
185.1266  }
185.1267  
185.1268  #undef DENS
185.1269  
185.1270 -#else
185.1271 +
185.1272  
185.1273  #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
185.1274  
185.1275 +static
185.1276 +void TetrahedralInterp16(register const cmsUInt16Number Input[],
185.1277 +                         register cmsUInt16Number Output[],
185.1278 +                         register const cmsInterpParams* p)
185.1279 +{
185.1280 +    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
185.1281 +    cmsS15Fixed16Number    fx, fy, fz;
185.1282 +    cmsS15Fixed16Number    rx, ry, rz;
185.1283 +    int                    x0, y0, z0;
185.1284 +    cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
185.1285 +    cmsUInt32Number        OutChan;
185.1286 +    cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
185.1287 +    cmsUInt32Number        TotalOut = p -> nOutputs;
185.1288  
185.1289 -void cmsTetrahedralInterp16(WORD Input[],
185.1290 -                            WORD Output[],
185.1291 -                            WORD LutTable1[],
185.1292 -                            LPL16PARAMS p)
185.1293 -{
185.1294  
185.1295 -       Fixed32    fx, fy, fz;
185.1296 -       Fixed32    rx, ry, rz;
185.1297 -       int        x0, y0, z0;
185.1298 -       Fixed32    c0, c1, c2, c3, Rest;
185.1299 -       int        OutChan;
185.1300 -       Fixed32    X0, X1, Y0, Y1, Z0, Z1;
185.1301 -       int        TotalOut = p -> nOutputs;
185.1302 -       register   LPWORD LutTable = LutTable1;
185.1303 -
185.1304 -
185.1305 -
185.1306 -    fx  = ToFixedDomain((int) Input[0] * p -> Domain);
185.1307 -    fy  = ToFixedDomain((int) Input[1] * p -> Domain);
185.1308 -    fz  = ToFixedDomain((int) Input[2] * p -> Domain);
185.1309 +    fx  = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
185.1310 +    fy  = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
185.1311 +    fz  = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
185.1312  
185.1313      x0  = FIXED_TO_INT(fx);
185.1314      y0  = FIXED_TO_INT(fy);
185.1315 @@ -939,196 +599,754 @@
185.1316      ry  = FIXED_REST_TO_INT(fy);
185.1317      rz  = FIXED_REST_TO_INT(fz);
185.1318  
185.1319 -    X0 = p -> opta3 * x0;
185.1320 -    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta3);
185.1321 +    X0 = p -> opta[2] * x0;
185.1322 +    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
185.1323  
185.1324 -    Y0 = p -> opta2 * y0;
185.1325 -    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta2);
185.1326 +    Y0 = p -> opta[1] * y0;
185.1327 +    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
185.1328  
185.1329 -    Z0 = p -> opta1 * z0;
185.1330 -    Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta1);
185.1331 -
185.1332 -
185.1333 +    Z0 = p -> opta[0] * z0;
185.1334 +    Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
185.1335  
185.1336      // These are the 6 Tetrahedral
185.1337      for (OutChan=0; OutChan < TotalOut; OutChan++) {
185.1338  
185.1339 -       c0 = DENS(X0, Y0, Z0);
185.1340 +        c0 = DENS(X0, Y0, Z0);
185.1341  
185.1342 -       if (rx >= ry && ry >= rz) {
185.1343 +        if (rx >= ry && ry >= rz) {
185.1344  
185.1345 -              c1 = DENS(X1, Y0, Z0) - c0;
185.1346 -              c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
185.1347 -              c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1348 +            c1 = DENS(X1, Y0, Z0) - c0;
185.1349 +            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
185.1350 +            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1351  
185.1352 -       }
185.1353 -       else
185.1354 -       if (rx >= rz && rz >= ry) {
185.1355 +        }
185.1356 +        else
185.1357 +            if (rx >= rz && rz >= ry) {
185.1358  
185.1359 -              c1 = DENS(X1, Y0, Z0) - c0;
185.1360 -              c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1361 -              c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
185.1362 +                c1 = DENS(X1, Y0, Z0) - c0;
185.1363 +                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1364 +                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
185.1365  
185.1366 -       }
185.1367 -       else
185.1368 -       if (rz >= rx && rx >= ry) {
185.1369 +            }
185.1370 +            else
185.1371 +                if (rz >= rx && rx >= ry) {
185.1372  
185.1373 -              c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
185.1374 -              c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1375 -              c3 = DENS(X0, Y0, Z1) - c0;
185.1376 +                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
185.1377 +                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1378 +                    c3 = DENS(X0, Y0, Z1) - c0;
185.1379  
185.1380 -       }
185.1381 -       else
185.1382 -       if (ry >= rx && rx >= rz) {
185.1383 +                }
185.1384 +                else
185.1385 +                    if (ry >= rx && rx >= rz) {
185.1386  
185.1387 -              c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
185.1388 -              c2 = DENS(X0, Y1, Z0) - c0;
185.1389 -              c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1390 +                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
185.1391 +                        c2 = DENS(X0, Y1, Z0) - c0;
185.1392 +                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1393  
185.1394 -       }
185.1395 -       else
185.1396 -       if (ry >= rz && rz >= rx) {
185.1397 +                    }
185.1398 +                    else
185.1399 +                        if (ry >= rz && rz >= rx) {
185.1400  
185.1401 -              c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1402 -              c2 = DENS(X0, Y1, Z0) - c0;
185.1403 -              c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
185.1404 +                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1405 +                            c2 = DENS(X0, Y1, Z0) - c0;
185.1406 +                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
185.1407  
185.1408 -       }
185.1409 -       else
185.1410 -       if (rz >= ry && ry >= rx) {
185.1411 +                        }
185.1412 +                        else
185.1413 +                            if (rz >= ry && ry >= rx) {
185.1414  
185.1415 -              c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1416 -              c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
185.1417 -              c3 = DENS(X0, Y0, Z1) - c0;
185.1418 +                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1419 +                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
185.1420 +                                c3 = DENS(X0, Y0, Z1) - c0;
185.1421  
185.1422 -       }
185.1423 -       else  {
185.1424 -              c1 = c2 = c3 = 0;
185.1425 -              // assert(FALSE);
185.1426 -       }
185.1427 +                            }
185.1428 +                            else  {
185.1429 +                                c1 = c2 = c3 = 0;
185.1430 +                            }
185.1431  
185.1432 -        Rest = c1 * rx + c2 * ry + c3 * rz;
185.1433 +                            Rest = c1 * rx + c2 * ry + c3 * rz;
185.1434  
185.1435 -        // There is a lot of math hidden in this expression. The rest is in fixed domain
185.1436 -        // and the result in 0..ffff domain. So the complete expression should be
185.1437 -        // ROUND_FIXED_TO_INT(ToFixedDomain(Rest)) But that can be optimized as (Rest + 0x7FFF) / 0xFFFF
185.1438 -
185.1439 -        Output[OutChan] = (WORD) (c0 + ((Rest + 0x7FFF) / 0xFFFF));
185.1440 -
185.1441 +                            Output[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
185.1442      }
185.1443  
185.1444  }
185.1445 -
185.1446 -
185.1447 -
185.1448  #undef DENS
185.1449  
185.1450 -#endif
185.1451 -
185.1452 -
185.1453 -// A optimized interpolation for 8-bit input.
185.1454  
185.1455  #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
185.1456 +static
185.1457 +void Eval4Inputs(register const cmsUInt16Number Input[],
185.1458 +                     register cmsUInt16Number Output[],
185.1459 +                     register const cmsInterpParams* p16)
185.1460 +{
185.1461 +    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
185.1462 +    cmsS15Fixed16Number fk;
185.1463 +    cmsS15Fixed16Number k0, rk;
185.1464 +    int K0, K1;
185.1465 +    cmsS15Fixed16Number    fx, fy, fz;
185.1466 +    cmsS15Fixed16Number    rx, ry, rz;
185.1467 +    int                    x0, y0, z0;
185.1468 +    cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
185.1469 +    cmsUInt32Number i;
185.1470 +    cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
185.1471 +    cmsUInt32Number        OutChan;
185.1472 +    cmsUInt16Number        Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.1473  
185.1474 -void cmsTetrahedralInterp8(WORD Input[],
185.1475 -                           WORD Output[],
185.1476 -                           WORD LutTable[],
185.1477 -                           LPL16PARAMS p)
185.1478 +
185.1479 +    fk  = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
185.1480 +    fx  = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
185.1481 +    fy  = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
185.1482 +    fz  = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);
185.1483 +
185.1484 +    k0  = FIXED_TO_INT(fk);
185.1485 +    x0  = FIXED_TO_INT(fx);
185.1486 +    y0  = FIXED_TO_INT(fy);
185.1487 +    z0  = FIXED_TO_INT(fz);
185.1488 +
185.1489 +    rk  = FIXED_REST_TO_INT(fk);
185.1490 +    rx  = FIXED_REST_TO_INT(fx);
185.1491 +    ry  = FIXED_REST_TO_INT(fy);
185.1492 +    rz  = FIXED_REST_TO_INT(fz);
185.1493 +
185.1494 +    K0 = p16 -> opta[3] * k0;
185.1495 +    K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
185.1496 +
185.1497 +    X0 = p16 -> opta[2] * x0;
185.1498 +    X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
185.1499 +
185.1500 +    Y0 = p16 -> opta[1] * y0;
185.1501 +    Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
185.1502 +
185.1503 +    Z0 = p16 -> opta[0] * z0;
185.1504 +    Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
185.1505 +
185.1506 +    LutTable = (cmsUInt16Number*) p16 -> Table;
185.1507 +    LutTable += K0;
185.1508 +
185.1509 +    for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
185.1510 +
185.1511 +        c0 = DENS(X0, Y0, Z0);
185.1512 +
185.1513 +        if (rx >= ry && ry >= rz) {
185.1514 +
185.1515 +            c1 = DENS(X1, Y0, Z0) - c0;
185.1516 +            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
185.1517 +            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1518 +
185.1519 +        }
185.1520 +        else
185.1521 +            if (rx >= rz && rz >= ry) {
185.1522 +
185.1523 +                c1 = DENS(X1, Y0, Z0) - c0;
185.1524 +                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1525 +                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
185.1526 +
185.1527 +            }
185.1528 +            else
185.1529 +                if (rz >= rx && rx >= ry) {
185.1530 +
185.1531 +                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
185.1532 +                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1533 +                    c3 = DENS(X0, Y0, Z1) - c0;
185.1534 +
185.1535 +                }
185.1536 +                else
185.1537 +                    if (ry >= rx && rx >= rz) {
185.1538 +
185.1539 +                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
185.1540 +                        c2 = DENS(X0, Y1, Z0) - c0;
185.1541 +                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1542 +
185.1543 +                    }
185.1544 +                    else
185.1545 +                        if (ry >= rz && rz >= rx) {
185.1546 +
185.1547 +                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1548 +                            c2 = DENS(X0, Y1, Z0) - c0;
185.1549 +                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
185.1550 +
185.1551 +                        }
185.1552 +                        else
185.1553 +                            if (rz >= ry && ry >= rx) {
185.1554 +
185.1555 +                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1556 +                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
185.1557 +                                c3 = DENS(X0, Y0, Z1) - c0;
185.1558 +
185.1559 +                            }
185.1560 +                            else  {
185.1561 +                                c1 = c2 = c3 = 0;
185.1562 +                            }
185.1563 +
185.1564 +                            Rest = c1 * rx + c2 * ry + c3 * rz;
185.1565 +
185.1566 +                            Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
185.1567 +    }
185.1568 +
185.1569 +
185.1570 +    LutTable = (cmsUInt16Number*) p16 -> Table;
185.1571 +    LutTable += K1;
185.1572 +
185.1573 +    for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
185.1574 +
185.1575 +        c0 = DENS(X0, Y0, Z0);
185.1576 +
185.1577 +        if (rx >= ry && ry >= rz) {
185.1578 +
185.1579 +            c1 = DENS(X1, Y0, Z0) - c0;
185.1580 +            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
185.1581 +            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1582 +
185.1583 +        }
185.1584 +        else
185.1585 +            if (rx >= rz && rz >= ry) {
185.1586 +
185.1587 +                c1 = DENS(X1, Y0, Z0) - c0;
185.1588 +                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1589 +                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
185.1590 +
185.1591 +            }
185.1592 +            else
185.1593 +                if (rz >= rx && rx >= ry) {
185.1594 +
185.1595 +                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
185.1596 +                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1597 +                    c3 = DENS(X0, Y0, Z1) - c0;
185.1598 +
185.1599 +                }
185.1600 +                else
185.1601 +                    if (ry >= rx && rx >= rz) {
185.1602 +
185.1603 +                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
185.1604 +                        c2 = DENS(X0, Y1, Z0) - c0;
185.1605 +                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1606 +
185.1607 +                    }
185.1608 +                    else
185.1609 +                        if (ry >= rz && rz >= rx) {
185.1610 +
185.1611 +                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1612 +                            c2 = DENS(X0, Y1, Z0) - c0;
185.1613 +                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
185.1614 +
185.1615 +                        }
185.1616 +                        else
185.1617 +                            if (rz >= ry && ry >= rx) {
185.1618 +
185.1619 +                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1620 +                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
185.1621 +                                c3 = DENS(X0, Y0, Z1) - c0;
185.1622 +
185.1623 +                            }
185.1624 +                            else  {
185.1625 +                                c1 = c2 = c3 = 0;
185.1626 +                            }
185.1627 +
185.1628 +                            Rest = c1 * rx + c2 * ry + c3 * rz;
185.1629 +
185.1630 +                            Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
185.1631 +    }
185.1632 +
185.1633 +
185.1634 +
185.1635 +    for (i=0; i < p16 -> nOutputs; i++) {
185.1636 +        Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
185.1637 +    }
185.1638 +}
185.1639 +#undef DENS
185.1640 +
185.1641 +
185.1642 +// For more that 3 inputs (i.e., CMYK)
185.1643 +// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
185.1644 +
185.1645 +
185.1646 +static
185.1647 +void Eval4InputsFloat(const cmsFloat32Number Input[],
185.1648 +                      cmsFloat32Number Output[],
185.1649 +                      const cmsInterpParams* p)
185.1650  {
185.1651 +       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
185.1652 +       cmsFloat32Number rest;
185.1653 +       cmsFloat32Number pk;
185.1654 +       int k0, K0, K1;
185.1655 +       const cmsFloat32Number* T;
185.1656 +       cmsUInt32Number i;
185.1657 +       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.1658 +       cmsInterpParams p1;
185.1659  
185.1660 -       int        r, g, b;
185.1661 -       Fixed32    rx, ry, rz;
185.1662 -       Fixed32    c1, c2, c3, Rest;
185.1663 -       int        OutChan;
185.1664 -       register   Fixed32    X0, X1, Y0, Y1, Z0, Z1;
185.1665 -       int        TotalOut = p -> nOutputs;
185.1666 -       register   LPL8PARAMS p8 = p ->p8;
185.1667  
185.1668 +       pk = Input[0] * p->Domain[0];
185.1669 +       k0 = _cmsQuickFloor(pk);
185.1670 +       rest = pk - (cmsFloat32Number) k0;
185.1671  
185.1672 +       K0 = p -> opta[3] * k0;
185.1673 +       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]);
185.1674  
185.1675 -    r = Input[0] >> 8;
185.1676 -    g = Input[1] >> 8;
185.1677 -    b = Input[2] >> 8;
185.1678 +       p1 = *p;
185.1679 +       memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
185.1680  
185.1681 -    X0 = X1 = p8->X0[r];
185.1682 -    Y0 = Y1 = p8->Y0[g];
185.1683 -    Z0 = Z1 = p8->Z0[b];
185.1684 +       T = LutTable + K0;
185.1685 +       p1.Table = T;
185.1686  
185.1687 -    X1 += (r == 255) ? 0 : p ->opta3;
185.1688 -    Y1 += (g == 255) ? 0 : p ->opta2;
185.1689 -    Z1 += (b == 255) ? 0 : p ->opta1;
185.1690 +       TetrahedralInterpFloat(Input + 1,  Tmp1, &p1);
185.1691  
185.1692 -    rx = p8 ->rx[r];
185.1693 -    ry = p8 ->ry[g];
185.1694 -    rz = p8 ->rz[b];
185.1695 +       T = LutTable + K1;
185.1696 +       p1.Table = T;
185.1697 +       TetrahedralInterpFloat(Input + 1,  Tmp2, &p1);
185.1698  
185.1699 +       for (i=0; i < p -> nOutputs; i++)
185.1700 +       {
185.1701 +              cmsFloat32Number y0 = Tmp1[i];
185.1702 +              cmsFloat32Number y1 = Tmp2[i];
185.1703  
185.1704 -    // These are the 6 Tetrahedral
185.1705 -    for (OutChan=0; OutChan < TotalOut; OutChan++) {
185.1706 +              Output[i] = y0 + (y1 - y0) * rest;
185.1707 +       }
185.1708 +}
185.1709  
185.1710 -       if (rx >= ry && ry >= rz)
185.1711 -       {
185.1712  
185.1713 -              c1 = DENS(X1, Y0, Z0) - DENS(X0, Y0, Z0);
185.1714 -              c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
185.1715 -              c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1716 +static
185.1717 +void Eval5Inputs(register const cmsUInt16Number Input[],
185.1718 +                 register cmsUInt16Number Output[],
185.1719  
185.1720 +                 register const cmsInterpParams* p16)
185.1721 +{
185.1722 +       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
185.1723 +       cmsS15Fixed16Number fk;
185.1724 +       cmsS15Fixed16Number k0, rk;
185.1725 +       int K0, K1;
185.1726 +       const cmsUInt16Number* T;
185.1727 +       cmsUInt32Number i;
185.1728 +       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.1729 +       cmsInterpParams p1;
185.1730 +
185.1731 +
185.1732 +       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
185.1733 +       k0 = FIXED_TO_INT(fk);
185.1734 +       rk = FIXED_REST_TO_INT(fk);
185.1735 +
185.1736 +       K0 = p16 -> opta[4] * k0;
185.1737 +       K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
185.1738 +
185.1739 +       p1 = *p16;
185.1740 +       memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
185.1741 +
185.1742 +       T = LutTable + K0;
185.1743 +       p1.Table = T;
185.1744 +
185.1745 +       Eval4Inputs(Input + 1, Tmp1, &p1);
185.1746 +
185.1747 +       T = LutTable + K1;
185.1748 +       p1.Table = T;
185.1749 +
185.1750 +       Eval4Inputs(Input + 1, Tmp2, &p1);
185.1751 +
185.1752 +       for (i=0; i < p16 -> nOutputs; i++) {
185.1753 +
185.1754 +              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
185.1755         }
185.1756 -       else
185.1757 -       if (rx >= rz && rz >= ry)
185.1758 -       {
185.1759 -              c1 = DENS(X1, Y0, Z0) - DENS(X0, Y0, Z0);
185.1760 -              c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1761 -              c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
185.1762 -
185.1763 -       }
185.1764 -       else
185.1765 -       if (rz >= rx && rx >= ry)
185.1766 -       {
185.1767 -
185.1768 -              c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
185.1769 -              c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
185.1770 -              c3 = DENS(X0, Y0, Z1) - DENS(X0, Y0, Z0);
185.1771 -
185.1772 -       }
185.1773 -       else
185.1774 -       if (ry >= rx && rx >= rz)
185.1775 -       {
185.1776 -
185.1777 -              c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
185.1778 -              c2 = DENS(X0, Y1, Z0) - DENS(X0, Y0, Z0);
185.1779 -              c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
185.1780 -
185.1781 -       }
185.1782 -       else
185.1783 -       if (ry >= rz && rz >= rx)
185.1784 -       {
185.1785 -
185.1786 -              c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1787 -              c2 = DENS(X0, Y1, Z0) - DENS(X0, Y0, Z0);
185.1788 -              c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
185.1789 -
185.1790 -       }
185.1791 -       else
185.1792 -       if (rz >= ry && ry >= rx)
185.1793 -       {
185.1794 -              c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
185.1795 -              c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
185.1796 -              c3 = DENS(X0, Y0, Z1) - DENS(X0, Y0, Z0);
185.1797 -
185.1798 -       }
185.1799 -       else  {
185.1800 -              c1 = c2 = c3 = 0;
185.1801 -              // assert(FALSE);
185.1802 -       }
185.1803 -
185.1804 -
185.1805 -        Rest = c1 * rx + c2 * ry + c3 * rz;
185.1806 -
185.1807 -        Output[OutChan] = (WORD) (DENS(X0,Y0,Z0) + ((Rest + 0x7FFF) / 0xFFFF));
185.1808 -    }
185.1809  
185.1810  }
185.1811  
185.1812 -#undef DENS
185.1813  
185.1814 +static
185.1815 +void Eval5InputsFloat(const cmsFloat32Number Input[],
185.1816 +                      cmsFloat32Number Output[],
185.1817 +                      const cmsInterpParams* p)
185.1818 +{
185.1819 +       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
185.1820 +       cmsFloat32Number rest;
185.1821 +       cmsFloat32Number pk;
185.1822 +       int k0, K0, K1;
185.1823 +       const cmsFloat32Number* T;
185.1824 +       cmsUInt32Number i;
185.1825 +       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.1826 +       cmsInterpParams p1;
185.1827 +
185.1828 +       pk = Input[0] * p->Domain[0];
185.1829 +       k0 = _cmsQuickFloor(pk);
185.1830 +       rest = pk - (cmsFloat32Number) k0;
185.1831 +
185.1832 +       K0 = p -> opta[4] * k0;
185.1833 +       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]);
185.1834 +
185.1835 +       p1 = *p;
185.1836 +       memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
185.1837 +
185.1838 +       T = LutTable + K0;
185.1839 +       p1.Table = T;
185.1840 +
185.1841 +       Eval4InputsFloat(Input + 1,  Tmp1, &p1);
185.1842 +
185.1843 +       T = LutTable + K1;
185.1844 +       p1.Table = T;
185.1845 +
185.1846 +       Eval4InputsFloat(Input + 1,  Tmp2, &p1);
185.1847 +
185.1848 +       for (i=0; i < p -> nOutputs; i++) {
185.1849 +
185.1850 +              cmsFloat32Number y0 = Tmp1[i];
185.1851 +              cmsFloat32Number y1 = Tmp2[i];
185.1852 +
185.1853 +              Output[i] = y0 + (y1 - y0) * rest;
185.1854 +       }
185.1855 +}
185.1856 +
185.1857 +
185.1858 +
185.1859 +static
185.1860 +void Eval6Inputs(register const cmsUInt16Number Input[],
185.1861 +                 register cmsUInt16Number Output[],
185.1862 +                 register const cmsInterpParams* p16)
185.1863 +{
185.1864 +       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
185.1865 +       cmsS15Fixed16Number fk;
185.1866 +       cmsS15Fixed16Number k0, rk;
185.1867 +       int K0, K1;
185.1868 +       const cmsUInt16Number* T;
185.1869 +       cmsUInt32Number i;
185.1870 +       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.1871 +       cmsInterpParams p1;
185.1872 +
185.1873 +       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
185.1874 +       k0 = FIXED_TO_INT(fk);
185.1875 +       rk = FIXED_REST_TO_INT(fk);
185.1876 +
185.1877 +       K0 = p16 -> opta[5] * k0;
185.1878 +       K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
185.1879 +
185.1880 +       p1 = *p16;
185.1881 +       memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
185.1882 +
185.1883 +       T = LutTable + K0;
185.1884 +       p1.Table = T;
185.1885 +
185.1886 +       Eval5Inputs(Input + 1, Tmp1, &p1);
185.1887 +
185.1888 +       T = LutTable + K1;
185.1889 +       p1.Table = T;
185.1890 +
185.1891 +       Eval5Inputs(Input + 1, Tmp2, &p1);
185.1892 +
185.1893 +       for (i=0; i < p16 -> nOutputs; i++) {
185.1894 +
185.1895 +              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
185.1896 +       }
185.1897 +
185.1898 +}
185.1899 +
185.1900 +
185.1901 +static
185.1902 +void Eval6InputsFloat(const cmsFloat32Number Input[],
185.1903 +                      cmsFloat32Number Output[],
185.1904 +                      const cmsInterpParams* p)
185.1905 +{
185.1906 +       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
185.1907 +       cmsFloat32Number rest;
185.1908 +       cmsFloat32Number pk;
185.1909 +       int k0, K0, K1;
185.1910 +       const cmsFloat32Number* T;
185.1911 +       cmsUInt32Number i;
185.1912 +       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.1913 +       cmsInterpParams p1;
185.1914 +
185.1915 +       pk = Input[0] * p->Domain[0];
185.1916 +       k0 = _cmsQuickFloor(pk);
185.1917 +       rest = pk - (cmsFloat32Number) k0;
185.1918 +
185.1919 +       K0 = p -> opta[5] * k0;
185.1920 +       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]);
185.1921 +
185.1922 +       p1 = *p;
185.1923 +       memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
185.1924 +
185.1925 +       T = LutTable + K0;
185.1926 +       p1.Table = T;
185.1927 +
185.1928 +       Eval5InputsFloat(Input + 1,  Tmp1, &p1);
185.1929 +
185.1930 +       T = LutTable + K1;
185.1931 +       p1.Table = T;
185.1932 +
185.1933 +       Eval5InputsFloat(Input + 1,  Tmp2, &p1);
185.1934 +
185.1935 +       for (i=0; i < p -> nOutputs; i++) {
185.1936 +
185.1937 +              cmsFloat32Number y0 = Tmp1[i];
185.1938 +              cmsFloat32Number y1 = Tmp2[i];
185.1939 +
185.1940 +              Output[i] = y0 + (y1 - y0) * rest;
185.1941 +       }
185.1942 +}
185.1943 +
185.1944 +
185.1945 +static
185.1946 +void Eval7Inputs(register const cmsUInt16Number Input[],
185.1947 +                 register cmsUInt16Number Output[],
185.1948 +                 register const cmsInterpParams* p16)
185.1949 +{
185.1950 +       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
185.1951 +       cmsS15Fixed16Number fk;
185.1952 +       cmsS15Fixed16Number k0, rk;
185.1953 +       int K0, K1;
185.1954 +       const cmsUInt16Number* T;
185.1955 +       cmsUInt32Number i;
185.1956 +       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.1957 +       cmsInterpParams p1;
185.1958 +
185.1959 +
185.1960 +       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
185.1961 +       k0 = FIXED_TO_INT(fk);
185.1962 +       rk = FIXED_REST_TO_INT(fk);
185.1963 +
185.1964 +       K0 = p16 -> opta[6] * k0;
185.1965 +       K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
185.1966 +
185.1967 +       p1 = *p16;
185.1968 +       memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
185.1969 +
185.1970 +       T = LutTable + K0;
185.1971 +       p1.Table = T;
185.1972 +
185.1973 +       Eval6Inputs(Input + 1, Tmp1, &p1);
185.1974 +
185.1975 +       T = LutTable + K1;
185.1976 +       p1.Table = T;
185.1977 +
185.1978 +       Eval6Inputs(Input + 1, Tmp2, &p1);
185.1979 +
185.1980 +       for (i=0; i < p16 -> nOutputs; i++) {
185.1981 +              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
185.1982 +       }
185.1983 +}
185.1984 +
185.1985 +
185.1986 +static
185.1987 +void Eval7InputsFloat(const cmsFloat32Number Input[],
185.1988 +                      cmsFloat32Number Output[],
185.1989 +                      const cmsInterpParams* p)
185.1990 +{
185.1991 +       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
185.1992 +       cmsFloat32Number rest;
185.1993 +       cmsFloat32Number pk;
185.1994 +       int k0, K0, K1;
185.1995 +       const cmsFloat32Number* T;
185.1996 +       cmsUInt32Number i;
185.1997 +       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.1998 +       cmsInterpParams p1;
185.1999 +
185.2000 +       pk = Input[0] * p->Domain[0];
185.2001 +       k0 = _cmsQuickFloor(pk);
185.2002 +       rest = pk - (cmsFloat32Number) k0;
185.2003 +
185.2004 +       K0 = p -> opta[6] * k0;
185.2005 +       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]);
185.2006 +
185.2007 +       p1 = *p;
185.2008 +       memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
185.2009 +
185.2010 +       T = LutTable + K0;
185.2011 +       p1.Table = T;
185.2012 +
185.2013 +       Eval6InputsFloat(Input + 1,  Tmp1, &p1);
185.2014 +
185.2015 +       T = LutTable + K1;
185.2016 +       p1.Table = T;
185.2017 +
185.2018 +       Eval6InputsFloat(Input + 1,  Tmp2, &p1);
185.2019 +
185.2020 +
185.2021 +       for (i=0; i < p -> nOutputs; i++) {
185.2022 +
185.2023 +              cmsFloat32Number y0 = Tmp1[i];
185.2024 +              cmsFloat32Number y1 = Tmp2[i];
185.2025 +
185.2026 +              Output[i] = y0 + (y1 - y0) * rest;
185.2027 +
185.2028 +       }
185.2029 +}
185.2030 +
185.2031 +static
185.2032 +void Eval8Inputs(register const cmsUInt16Number Input[],
185.2033 +                 register cmsUInt16Number Output[],
185.2034 +                 register const cmsInterpParams* p16)
185.2035 +{
185.2036 +       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
185.2037 +       cmsS15Fixed16Number fk;
185.2038 +       cmsS15Fixed16Number k0, rk;
185.2039 +       int K0, K1;
185.2040 +       const cmsUInt16Number* T;
185.2041 +       cmsUInt32Number i;
185.2042 +       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.2043 +       cmsInterpParams p1;
185.2044 +
185.2045 +       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
185.2046 +       k0 = FIXED_TO_INT(fk);
185.2047 +       rk = FIXED_REST_TO_INT(fk);
185.2048 +
185.2049 +       K0 = p16 -> opta[7] * k0;
185.2050 +       K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
185.2051 +
185.2052 +       p1 = *p16;
185.2053 +       memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
185.2054 +
185.2055 +       T = LutTable + K0;
185.2056 +       p1.Table = T;
185.2057 +
185.2058 +       Eval7Inputs(Input + 1, Tmp1, &p1);
185.2059 +
185.2060 +       T = LutTable + K1;
185.2061 +       p1.Table = T;
185.2062 +       Eval7Inputs(Input + 1, Tmp2, &p1);
185.2063 +
185.2064 +       for (i=0; i < p16 -> nOutputs; i++) {
185.2065 +              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
185.2066 +       }
185.2067 +}
185.2068 +
185.2069 +
185.2070 +
185.2071 +static
185.2072 +void Eval8InputsFloat(const cmsFloat32Number Input[],
185.2073 +                      cmsFloat32Number Output[],
185.2074 +                      const cmsInterpParams* p)
185.2075 +{
185.2076 +       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
185.2077 +       cmsFloat32Number rest;
185.2078 +       cmsFloat32Number pk;
185.2079 +       int k0, K0, K1;
185.2080 +       const cmsFloat32Number* T;
185.2081 +       cmsUInt32Number i;
185.2082 +       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
185.2083 +       cmsInterpParams p1;
185.2084 +
185.2085 +       pk = Input[0] * p->Domain[0];
185.2086 +       k0 = _cmsQuickFloor(pk);
185.2087 +       rest = pk - (cmsFloat32Number) k0;
185.2088 +
185.2089 +       K0 = p -> opta[7] * k0;
185.2090 +       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]);
185.2091 +
185.2092 +       p1 = *p;
185.2093 +       memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
185.2094 +
185.2095 +       T = LutTable + K0;
185.2096 +       p1.Table = T;
185.2097 +
185.2098 +       Eval7InputsFloat(Input + 1,  Tmp1, &p1);
185.2099 +
185.2100 +       T = LutTable + K1;
185.2101 +       p1.Table = T;
185.2102 +
185.2103 +       Eval7InputsFloat(Input + 1,  Tmp2, &p1);
185.2104 +
185.2105 +
185.2106 +       for (i=0; i < p -> nOutputs; i++) {
185.2107 +
185.2108 +              cmsFloat32Number y0 = Tmp1[i];
185.2109 +              cmsFloat32Number y1 = Tmp2[i];
185.2110 +
185.2111 +              Output[i] = y0 + (y1 - y0) * rest;
185.2112 +       }
185.2113 +}
185.2114 +
185.2115 +// The default factory
185.2116 +static
185.2117 +cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
185.2118 +{
185.2119 +
185.2120 +    cmsInterpFunction Interpolation;
185.2121 +    cmsBool  IsFloat     = (dwFlags & CMS_LERP_FLAGS_FLOAT);
185.2122 +    cmsBool  IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
185.2123 +
185.2124 +    memset(&Interpolation, 0, sizeof(Interpolation));
185.2125 +
185.2126 +    // Safety check
185.2127 +    if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
185.2128 +        return Interpolation;
185.2129 +
185.2130 +    switch (nInputChannels) {
185.2131 +
185.2132 +           case 1: // Gray LUT / linear
185.2133 +
185.2134 +               if (nOutputChannels == 1) {
185.2135 +
185.2136 +                   if (IsFloat)
185.2137 +                       Interpolation.LerpFloat = LinLerp1Dfloat;
185.2138 +                   else
185.2139 +                       Interpolation.Lerp16 = LinLerp1D;
185.2140 +
185.2141 +               }
185.2142 +               else {
185.2143 +
185.2144 +                   if (IsFloat)
185.2145 +                       Interpolation.LerpFloat = Eval1InputFloat;
185.2146 +                   else
185.2147 +                       Interpolation.Lerp16 = Eval1Input;
185.2148 +               }
185.2149 +               break;
185.2150 +
185.2151 +
185.2152 +           case 3:  // RGB et al
185.2153 +
185.2154 +               if (IsTrilinear) {
185.2155 +
185.2156 +                   if (IsFloat)
185.2157 +                       Interpolation.LerpFloat = TrilinearInterpFloat;
185.2158 +                   else
185.2159 +                       Interpolation.Lerp16 = TrilinearInterp16;
185.2160 +               }
185.2161 +               else {
185.2162 +
185.2163 +                   if (IsFloat)
185.2164 +                       Interpolation.LerpFloat = TetrahedralInterpFloat;
185.2165 +                   else {
185.2166 +
185.2167 +                       Interpolation.Lerp16 = TetrahedralInterp16;
185.2168 +                   }
185.2169 +               }
185.2170 +               break;
185.2171 +
185.2172 +           case 4:  // CMYK lut
185.2173 +
185.2174 +               if (IsFloat)
185.2175 +                   Interpolation.LerpFloat =  Eval4InputsFloat;
185.2176 +               else
185.2177 +                   Interpolation.Lerp16    =  Eval4Inputs;
185.2178 +               break;
185.2179 +
185.2180 +           case 5: // 5 Inks
185.2181 +               if (IsFloat)
185.2182 +                   Interpolation.LerpFloat =  Eval5InputsFloat;
185.2183 +               else
185.2184 +                   Interpolation.Lerp16    =  Eval5Inputs;
185.2185 +               break;
185.2186 +
185.2187 +           case 6: // 6 Inks
185.2188 +               if (IsFloat)
185.2189 +                   Interpolation.LerpFloat =  Eval6InputsFloat;
185.2190 +               else
185.2191 +                   Interpolation.Lerp16    =  Eval6Inputs;
185.2192 +               break;
185.2193 +
185.2194 +           case 7: // 7 inks
185.2195 +               if (IsFloat)
185.2196 +                   Interpolation.LerpFloat =  Eval7InputsFloat;
185.2197 +               else
185.2198 +                   Interpolation.Lerp16    =  Eval7Inputs;
185.2199 +               break;
185.2200 +
185.2201 +           case 8: // 8 inks
185.2202 +               if (IsFloat)
185.2203 +                   Interpolation.LerpFloat =  Eval8InputsFloat;
185.2204 +               else
185.2205 +                   Interpolation.Lerp16    =  Eval8Inputs;
185.2206 +               break;
185.2207 +
185.2208 +               break;
185.2209 +
185.2210 +           default:
185.2211 +               Interpolation.Lerp16 = NULL;
185.2212 +    }
185.2213 +
185.2214 +    return Interpolation;
185.2215 +}
   186.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsio0.c	Thu Sep 23 17:33:40 2010 -0700
   186.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsio0.c	Fri Sep 24 16:41:32 2010 -0700
   186.3 @@ -27,9 +27,10 @@
   186.4  // However, the following notice accompanied the original version of this
   186.5  // file:
   186.6  //
   186.7 +//---------------------------------------------------------------------------------
   186.8  //
   186.9 -//  Little cms
  186.10 -//  Copyright (C) 1998-2007 Marti Maria
  186.11 +//  Little Color Management System
  186.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  186.13  //
  186.14  // Permission is hereby granted, free of charge, to any person obtaining
  186.15  // a copy of this software and associated documentation files (the "Software"),
  186.16 @@ -49,748 +50,1640 @@
  186.17  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  186.18  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  186.19  //
  186.20 +//---------------------------------------------------------------------------------
  186.21 +//
  186.22 +
  186.23 +#include "lcms2_internal.h"
  186.24  
  186.25  // Generic I/O, tag dictionary management, profile struct
  186.26  
  186.27 +// IOhandlers are abstractions used by littleCMS to read from whatever file, stream,
  186.28 +// memory block or any storage. Each IOhandler provides implementations for read,
  186.29 +// write, seek and tell functions. LittleCMS code deals with IO across those objects.
  186.30 +// In this way, is easier to add support for new storage media.
  186.31  
  186.32 +// NULL stream, for taking care of used space -------------------------------------
  186.33  
  186.34 -#include "lcms.h"
  186.35 -
  186.36 -
  186.37 -// Memory-based stream ---------------------------------------------------
  186.38 +// NULL IOhandler basically does nothing but keep track on how many bytes have been
  186.39 +// written. This is handy when creating profiles, where the file size is needed in the
  186.40 +// header. Then, whole profile is serialized across NULL IOhandler and a second pass
  186.41 +// writes the bytes to the pertinent IOhandler.
  186.42  
  186.43  typedef struct {
  186.44 -                LPBYTE Block;           // Points to allocated memory
  186.45 -                size_t Size;            // Size of allocated memory
  186.46 -                size_t Pointer;         // Points to current location
  186.47 -                int FreeBlockOnClose;   // As title
  186.48 -
  186.49 -                } FILEMEM;
  186.50 +    cmsUInt32Number Pointer;         // Points to current location
  186.51 +} FILENULL;
  186.52  
  186.53  static
  186.54 -LPVOID MemoryOpen(LPBYTE Block, size_t Size, char Mode)
  186.55 +cmsUInt32Number NULLRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count)
  186.56  {
  186.57 -    FILEMEM* fm = (FILEMEM*) _cmsMalloc(sizeof(FILEMEM));
  186.58 -    if (fm == NULL) return NULL;
  186.59 +    FILENULL* ResData = (FILENULL*) iohandler ->stream;
  186.60  
  186.61 -    ZeroMemory(fm, sizeof(FILEMEM));
  186.62 +    cmsUInt32Number len = size * count;
  186.63 +    ResData -> Pointer += len;
  186.64 +    return count;
  186.65  
  186.66 -    if (Mode == 'r') {
  186.67 +    cmsUNUSED_PARAMETER(Buffer);
  186.68 +}
  186.69  
  186.70 -        fm ->Block   = (LPBYTE) _cmsMalloc(Size);
  186.71 -        if (fm ->Block == NULL) {
  186.72 -             _cmsFree(fm);
  186.73 -            return NULL;
  186.74 -        }
  186.75 +static
  186.76 +cmsBool  NULLSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset)
  186.77 +{
  186.78 +    FILENULL* ResData = (FILENULL*) iohandler ->stream;
  186.79  
  186.80 -        CopyMemory(fm->Block, Block, Size);
  186.81 -        fm ->FreeBlockOnClose = TRUE;
  186.82 -    }
  186.83 -    else {
  186.84 -        fm ->Block = Block;
  186.85 -        fm ->FreeBlockOnClose = FALSE;
  186.86 -    }
  186.87 +    ResData ->Pointer = offset;
  186.88 +    return TRUE;
  186.89 +}
  186.90  
  186.91 -    fm ->Size    = Size;
  186.92 +static
  186.93 +cmsUInt32Number NULLTell(cmsIOHANDLER* iohandler)
  186.94 +{
  186.95 +    FILENULL* ResData = (FILENULL*) iohandler ->stream;
  186.96 +    return ResData -> Pointer;
  186.97 +}
  186.98 +
  186.99 +static
 186.100 +cmsBool  NULLWrite(cmsIOHANDLER* iohandler, cmsUInt32Number size, const void *Ptr)
 186.101 +{
 186.102 +    FILENULL* ResData = (FILENULL*) iohandler ->stream;
 186.103 +
 186.104 +    ResData ->Pointer += size;
 186.105 +    if (ResData ->Pointer > iohandler->UsedSpace)
 186.106 +        iohandler->UsedSpace = ResData ->Pointer;
 186.107 +
 186.108 +    return TRUE;
 186.109 +
 186.110 +    cmsUNUSED_PARAMETER(Ptr);
 186.111 +}
 186.112 +
 186.113 +static
 186.114 +cmsBool  NULLClose(cmsIOHANDLER* iohandler)
 186.115 +{
 186.116 +    FILENULL* ResData = (FILENULL*) iohandler ->stream;
 186.117 +
 186.118 +    _cmsFree(iohandler ->ContextID, ResData);
 186.119 +    _cmsFree(iohandler ->ContextID, iohandler);
 186.120 +    return TRUE;
 186.121 +}
 186.122 +
 186.123 +// The NULL IOhandler creator
 186.124 +cmsIOHANDLER*  CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID)
 186.125 +{
 186.126 +    struct _cms_io_handler* iohandler = NULL;
 186.127 +    FILENULL* fm = NULL;
 186.128 +
 186.129 +    iohandler = (struct _cms_io_handler*) _cmsMallocZero(ContextID, sizeof(struct _cms_io_handler));
 186.130 +    if (iohandler == NULL) return NULL;
 186.131 +
 186.132 +    fm = (FILENULL*) _cmsMallocZero(ContextID, sizeof(FILENULL));
 186.133 +    if (fm == NULL) goto Error;
 186.134 +
 186.135      fm ->Pointer = 0;
 186.136  
 186.137 -    return (LPVOID) fm;
 186.138 +    iohandler ->ContextID = ContextID;
 186.139 +    iohandler ->stream  = (void*) fm;
 186.140 +    iohandler ->UsedSpace = 0;
 186.141 +    iohandler ->PhysicalFile[0] = 0;
 186.142 +
 186.143 +    iohandler ->Read    = NULLRead;
 186.144 +    iohandler ->Seek    = NULLSeek;
 186.145 +    iohandler ->Close   = NULLClose;
 186.146 +    iohandler ->Tell    = NULLTell;
 186.147 +    iohandler ->Write   = NULLWrite;
 186.148 +
 186.149 +    return iohandler;
 186.150 +
 186.151 +Error:
 186.152 +    if (fm) _cmsFree(ContextID, fm);
 186.153 +    if (iohandler) _cmsFree(ContextID, iohandler);
 186.154 +    return NULL;
 186.155 +
 186.156  }
 186.157  
 186.158  
 186.159 +// Memory-based stream --------------------------------------------------------------
 186.160 +
 186.161 +// Those functions implements an iohandler which takes a block of memory as storage medium.
 186.162 +
 186.163 +typedef struct {
 186.164 +    cmsUInt8Number* Block;    // Points to allocated memory
 186.165 +    cmsUInt32Number Size;     // Size of allocated memory
 186.166 +    cmsUInt32Number Pointer;  // Points to current location
 186.167 +    int FreeBlockOnClose;     // As title
 186.168 +
 186.169 +} FILEMEM;
 186.170 +
 186.171  static
 186.172 -size_t MemoryRead(LPVOID buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc)
 186.173 +cmsUInt32Number MemoryRead(struct _cms_io_handler* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count)
 186.174  {
 186.175 -     FILEMEM* ResData = (FILEMEM*) Icc ->stream;
 186.176 -     LPBYTE Ptr;
 186.177 -     size_t len = size * count;
 186.178 -     size_t extent = ResData -> Pointer + len;
 186.179 +    FILEMEM* ResData = (FILEMEM*) iohandler ->stream;
 186.180 +    cmsUInt8Number* Ptr;
 186.181 +    cmsUInt32Number len = size * count;
 186.182  
 186.183 -        if (len == 0) {
 186.184 -                return 0;
 186.185 -        }
 186.186 +    if (ResData -> Pointer + len > ResData -> Size){
 186.187  
 186.188 -        if (len / size != count) {
 186.189 -          cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with count / size.");
 186.190 -          return 0;
 186.191 -      }
 186.192 -
 186.193 -      if (extent < len || extent < ResData -> Pointer) {
 186.194 -          cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Integer overflow with len.");
 186.195 -          return 0;
 186.196 -      }
 186.197 -
 186.198 -      if (ResData -> Pointer + len > ResData -> Size) {
 186.199 -
 186.200 -         len = (ResData -> Size - ResData -> Pointer);
 186.201 -         cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size);
 186.202 -         return 0;
 186.203 -     }
 186.204 +        len = (ResData -> Size - ResData -> Pointer);
 186.205 +        cmsSignalError(iohandler ->ContextID, cmsERROR_READ, "Read from memory error. Got %d bytes, block should be of %d bytes", len, count * size);
 186.206 +        return 0;
 186.207 +    }
 186.208  
 186.209      Ptr  = ResData -> Block;
 186.210      Ptr += ResData -> Pointer;
 186.211 -    CopyMemory(buffer, Ptr, len);
 186.212 -    ResData -> Pointer += (int) len;
 186.213 +    memmove(Buffer, Ptr, len);
 186.214 +    ResData -> Pointer += len;
 186.215  
 186.216      return count;
 186.217  }
 186.218  
 186.219  // SEEK_CUR is assumed
 186.220 -
 186.221  static
 186.222 -LCMSBOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
 186.223 +cmsBool  MemorySeek(struct _cms_io_handler* iohandler, cmsUInt32Number offset)
 186.224  {
 186.225 -    FILEMEM* ResData = (FILEMEM*) Icc ->stream;
 186.226 +    FILEMEM* ResData = (FILEMEM*) iohandler ->stream;
 186.227  
 186.228      if (offset > ResData ->Size) {
 186.229 -         cmsSignalError(LCMS_ERRC_ABORTED,  "Pointer error; probably corrupted file");
 186.230 -         return TRUE;
 186.231 +        cmsSignalError(iohandler ->ContextID, cmsERROR_SEEK,  "Too few data; probably corrupted profile");
 186.232 +        return FALSE;
 186.233      }
 186.234  
 186.235 -    ResData ->Pointer = (DWORD) offset;
 186.236 -    return FALSE;
 186.237 +    ResData ->Pointer = offset;
 186.238 +    return TRUE;
 186.239  }
 186.240  
 186.241 -// FTell
 186.242 +// Tell for memory
 186.243 +static
 186.244 +cmsUInt32Number MemoryTell(struct _cms_io_handler* iohandler)
 186.245 +{
 186.246 +    FILEMEM* ResData = (FILEMEM*) iohandler ->stream;
 186.247  
 186.248 -static
 186.249 -size_t MemoryTell(struct _lcms_iccprofile_struct* Icc)
 186.250 -{
 186.251 -    FILEMEM* ResData = (FILEMEM*) Icc ->stream;
 186.252 -
 186.253 +    if (ResData == NULL) return 0;
 186.254      return ResData -> Pointer;
 186.255  }
 186.256  
 186.257  
 186.258 -// Writes data to memory, also keeps used space for further reference. NO CHECK IS PERFORMED
 186.259 +// Writes data to memory, also keeps used space for further reference.
 186.260 +static
 186.261 +cmsBool  MemoryWrite(struct _cms_io_handler* iohandler, cmsUInt32Number size, const void *Ptr)
 186.262 +{
 186.263 +    FILEMEM* ResData = (FILEMEM*) iohandler ->stream;
 186.264  
 186.265 -static
 186.266 -LCMSBOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr)
 186.267 -{
 186.268 -        FILEMEM* ResData = (FILEMEM*) Icc ->stream;
 186.269 +    if (ResData == NULL) return FALSE; // Housekeeping
 186.270  
 186.271 -       if (size == 0) return TRUE;
 186.272 +    if (size == 0) return TRUE;     // Write zero bytes is ok, but does nothing
 186.273  
 186.274 -       if (ResData != NULL)
 186.275 -           CopyMemory(ResData ->Block + ResData ->Pointer, Ptr, size);
 186.276 +    memmove(ResData ->Block + ResData ->Pointer, Ptr, size);
 186.277 +    ResData ->Pointer += size;
 186.278  
 186.279 -       ResData->Pointer += size;
 186.280 -       Icc->UsedSpace += size;
 186.281 +    if (ResData ->Pointer > iohandler->UsedSpace)
 186.282 +        iohandler->UsedSpace = ResData ->Pointer;
 186.283  
 186.284 -       return TRUE;
 186.285 -}
 186.286  
 186.287 +    iohandler->UsedSpace += size;
 186.288  
 186.289 -static
 186.290 -LCMSBOOL MemoryGrow(struct _lcms_iccprofile_struct* Icc, size_t size)
 186.291 -{
 186.292 -    FILEMEM* ResData = (FILEMEM*) Icc->stream;
 186.293 -
 186.294 -    void* newBlock = NULL;
 186.295 -
 186.296 -    /* Follow same policies as functions in lcms.h  */
 186.297 -    if (ResData->Size + size < 0) return NULL;
 186.298 -    if (ResData->Size + size > ((size_t)1024*1024*500)) return NULL;
 186.299 -
 186.300 -    newBlock = realloc(ResData->Block, ResData->Size + size);
 186.301 -
 186.302 -    if (!newBlock) {
 186.303 -        return FALSE;
 186.304 -    }
 186.305 -    ResData->Block = newBlock;
 186.306 -    ResData->Size += size;
 186.307      return TRUE;
 186.308  }
 186.309  
 186.310  
 186.311  static
 186.312 -LCMSBOOL MemoryClose(struct _lcms_iccprofile_struct* Icc)
 186.313 +cmsBool  MemoryClose(struct _cms_io_handler* iohandler)
 186.314  {
 186.315 -    FILEMEM* ResData = (FILEMEM*) Icc ->stream;
 186.316 +    FILEMEM* ResData = (FILEMEM*) iohandler ->stream;
 186.317  
 186.318      if (ResData ->FreeBlockOnClose) {
 186.319  
 186.320 -        if (ResData ->Block)  _cmsFree(ResData ->Block);
 186.321 +        if (ResData ->Block) _cmsFree(iohandler ->ContextID, ResData ->Block);
 186.322      }
 186.323 -     _cmsFree(ResData);
 186.324 -    return 0;
 186.325 +
 186.326 +    _cmsFree(iohandler ->ContextID, ResData);
 186.327 +    _cmsFree(iohandler ->ContextID, iohandler);
 186.328 +
 186.329 +    return TRUE;
 186.330  }
 186.331  
 186.332 +// Create a iohandler for memory block. AccessMode=='r' assumes the iohandler is going to read, and makes
 186.333 +// a copy of the memory block for letting user to free the memory after invoking open profile. In write
 186.334 +// mode ("w"), Buffere points to the begin of memory block to be written.
 186.335 +cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode)
 186.336 +{
 186.337 +    cmsIOHANDLER* iohandler = NULL;
 186.338 +    FILEMEM* fm = NULL;
 186.339 +
 186.340 +    _cmsAssert(AccessMode != NULL);
 186.341 +
 186.342 +    iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER));
 186.343 +    if (iohandler == NULL) return NULL;
 186.344 +
 186.345 +    switch (*AccessMode) {
 186.346 +
 186.347 +    case 'r':
 186.348 +        fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM));
 186.349 +        if (fm == NULL) goto Error;
 186.350 +
 186.351 +        if (Buffer == NULL) {
 186.352 +            cmsSignalError(ContextID, cmsERROR_READ, "Couldn't read profile from NULL pointer");
 186.353 +            goto Error;
 186.354 +        }
 186.355 +
 186.356 +        fm ->Block = (cmsUInt8Number*) _cmsMalloc(ContextID, size);
 186.357 +        if (fm ->Block == NULL) {
 186.358 +
 186.359 +            _cmsFree(ContextID, fm);
 186.360 +            _cmsFree(ContextID, iohandler);
 186.361 +            cmsSignalError(ContextID, cmsERROR_READ, "Couldn't allocate %ld bytes for profile", size);
 186.362 +            return NULL;
 186.363 +        }
 186.364 +
 186.365 +
 186.366 +        memmove(fm->Block, Buffer, size);
 186.367 +        fm ->FreeBlockOnClose = TRUE;
 186.368 +        fm ->Size    = size;
 186.369 +        fm ->Pointer = 0;
 186.370 +        break;
 186.371 +
 186.372 +    case 'w':
 186.373 +        fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM));
 186.374 +        if (fm == NULL) goto Error;
 186.375 +
 186.376 +        fm ->Block = (cmsUInt8Number*) Buffer;
 186.377 +        fm ->FreeBlockOnClose = FALSE;
 186.378 +        fm ->Size    = size;
 186.379 +        fm ->Pointer = 0;
 186.380 +        break;
 186.381 +
 186.382 +    default:
 186.383 +        cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknow access mode '%c'", *AccessMode);
 186.384 +        return NULL;
 186.385 +    }
 186.386 +
 186.387 +    iohandler ->ContextID = ContextID;
 186.388 +    iohandler ->stream  = (void*) fm;
 186.389 +    iohandler ->UsedSpace = 0;
 186.390 +    iohandler ->PhysicalFile[0] = 0;
 186.391 +
 186.392 +    iohandler ->Read    = MemoryRead;
 186.393 +    iohandler ->Seek    = MemorySeek;
 186.394 +    iohandler ->Close   = MemoryClose;
 186.395 +    iohandler ->Tell    = MemoryTell;
 186.396 +    iohandler ->Write   = MemoryWrite;
 186.397 +
 186.398 +    return iohandler;
 186.399 +
 186.400 +Error:
 186.401 +    if (fm) _cmsFree(ContextID, fm);
 186.402 +    if (iohandler) _cmsFree(ContextID, iohandler);
 186.403 +    return NULL;
 186.404 +}
 186.405  
 186.406  // File-based stream -------------------------------------------------------
 186.407  
 186.408 +// Read count elements of size bytes each. Return number of elements read
 186.409  static
 186.410 -LPVOID FileOpen(const char* filename)
 186.411 +cmsUInt32Number FileRead(cmsIOHANDLER* iohandler, void *Buffer, cmsUInt32Number size, cmsUInt32Number count)
 186.412  {
 186.413 -    return (void*) fopen(filename, "rb");
 186.414 -}
 186.415 +    cmsUInt32Number nReaded = (cmsUInt32Number) fread(Buffer, size, count, (FILE*) iohandler->stream);
 186.416  
 186.417 -static
 186.418 -size_t FileRead(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc)
 186.419 -{
 186.420 -    size_t nReaded = fread(buffer, size, count, (FILE*) Icc->stream);
 186.421      if (nReaded != count) {
 186.422 -            cmsSignalError(LCMS_ERRC_ABORTED, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size);
 186.423 +            cmsSignalError(iohandler ->ContextID, cmsERROR_FILE, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size);
 186.424              return 0;
 186.425      }
 186.426  
 186.427      return nReaded;
 186.428  }
 186.429  
 186.430 +// Postion file pointer in the file
 186.431 +static
 186.432 +cmsBool  FileSeek(cmsIOHANDLER* iohandler, cmsUInt32Number offset)
 186.433 +{
 186.434 +    if (fseek((FILE*) iohandler ->stream, (long) offset, SEEK_SET) != 0) {
 186.435 +
 186.436 +       cmsSignalError(iohandler ->ContextID, cmsERROR_FILE, "Seek error; probably corrupted file");
 186.437 +       return FALSE;
 186.438 +    }
 186.439 +
 186.440 +    return TRUE;
 186.441 +}
 186.442 +
 186.443 +// Returns file pointer position
 186.444 +static
 186.445 +cmsUInt32Number FileTell(cmsIOHANDLER* iohandler)
 186.446 +{
 186.447 +    return ftell((FILE*)iohandler ->stream);
 186.448 +}
 186.449 +
 186.450 +// Writes data to stream, also keeps used space for further reference. Returns TRUE on success, FALSE on error
 186.451 +static
 186.452 +cmsBool  FileWrite(cmsIOHANDLER* iohandler, cmsUInt32Number size, const void* Buffer)
 186.453 +{
 186.454 +       if (size == 0) return TRUE;  // We allow to write 0 bytes, but nothing is written
 186.455 +
 186.456 +       iohandler->UsedSpace += size;
 186.457 +       return (fwrite(Buffer, size, 1, (FILE*) iohandler->stream) == 1);
 186.458 +}
 186.459 +
 186.460 +// Closes the file
 186.461 +static
 186.462 +cmsBool  FileClose(cmsIOHANDLER* iohandler)
 186.463 +{
 186.464 +    if (fclose((FILE*) iohandler ->stream) != 0) return FALSE;
 186.465 +    _cmsFree(iohandler ->ContextID, iohandler);
 186.466 +    return TRUE;
 186.467 +}
 186.468 +
 186.469 +// Create a iohandler for disk based files. if FileName is NULL, then 'stream' member is also set
 186.470 +// to NULL and no real writting is performed. This only happens in writting access mode
 186.471 +cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode)
 186.472 +{
 186.473 +    cmsIOHANDLER* iohandler = NULL;
 186.474 +    FILE* fm = NULL;
 186.475 +
 186.476 +    iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER));
 186.477 +    if (iohandler == NULL) return NULL;
 186.478 +
 186.479 +    switch (*AccessMode) {
 186.480 +
 186.481 +    case 'r':
 186.482 +        fm = fopen(FileName, "rb");
 186.483 +        if (fm == NULL) {
 186.484 +            _cmsFree(ContextID, iohandler);
 186.485 +             cmsSignalError(ContextID, cmsERROR_FILE, "File '%s' not found", FileName);
 186.486 +            return NULL;
 186.487 +        }
 186.488 +        break;
 186.489 +
 186.490 +    case 'w':
 186.491 +        fm = fopen(FileName, "wb");
 186.492 +        if (fm == NULL) {
 186.493 +            _cmsFree(ContextID, iohandler);
 186.494 +             cmsSignalError(ContextID, cmsERROR_FILE, "Couldn't create '%s'", FileName);
 186.495 +            return NULL;
 186.496 +        }
 186.497 +        break;
 186.498 +
 186.499 +    default:
 186.500 +        _cmsFree(ContextID, iohandler);
 186.501 +         cmsSignalError(ContextID, cmsERROR_FILE, "Unknow access mode '%c'", *AccessMode);
 186.502 +        return NULL;
 186.503 +    }
 186.504 +
 186.505 +    iohandler ->ContextID = ContextID;
 186.506 +    iohandler ->stream = (void*) fm;
 186.507 +    iohandler ->UsedSpace = 0;
 186.508 +
 186.509 +    // Keep track of the original file
 186.510 +    if (FileName != NULL)  {
 186.511 +
 186.512 +        strncpy(iohandler -> PhysicalFile, FileName, sizeof(iohandler -> PhysicalFile)-1);
 186.513 +        iohandler -> PhysicalFile[sizeof(iohandler -> PhysicalFile)-1] = 0;
 186.514 +    }
 186.515 +
 186.516 +    iohandler ->Read    = FileRead;
 186.517 +    iohandler ->Seek    = FileSeek;
 186.518 +    iohandler ->Close   = FileClose;
 186.519 +    iohandler ->Tell    = FileTell;
 186.520 +    iohandler ->Write   = FileWrite;
 186.521 +
 186.522 +    return iohandler;
 186.523 +}
 186.524 +
 186.525 +// Create a iohandler for stream based files
 186.526 +cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream)
 186.527 +{
 186.528 +    cmsIOHANDLER* iohandler = NULL;
 186.529 +
 186.530 +    iohandler = (cmsIOHANDLER*) _cmsMallocZero(ContextID, sizeof(cmsIOHANDLER));
 186.531 +    if (iohandler == NULL) return NULL;
 186.532 +
 186.533 +    iohandler -> ContextID = ContextID;
 186.534 +    iohandler -> stream = (void*) Stream;
 186.535 +    iohandler -> UsedSpace = 0;
 186.536 +    iohandler -> PhysicalFile[0] = 0;
 186.537 +
 186.538 +    iohandler ->Read    = FileRead;
 186.539 +    iohandler ->Seek    = FileSeek;
 186.540 +    iohandler ->Close   = FileClose;
 186.541 +    iohandler ->Tell    = FileTell;
 186.542 +    iohandler ->Write   = FileWrite;
 186.543 +
 186.544 +    return iohandler;
 186.545 +}
 186.546 +
 186.547 +
 186.548 +
 186.549 +// Close an open IO handler
 186.550 +cmsBool CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io)
 186.551 +{
 186.552 +    return io -> Close(io);
 186.553 +}
 186.554 +
 186.555 +// -------------------------------------------------------------------------------------------------------
 186.556 +
 186.557 +// Creates an empty structure holding all required parameters
 186.558 +cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID)
 186.559 +{
 186.560 +    time_t now = time(NULL);
 186.561 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) _cmsMallocZero(ContextID, sizeof(_cmsICCPROFILE));
 186.562 +    if (Icc == NULL) return NULL;
 186.563 +
 186.564 +    Icc ->ContextID = ContextID;
 186.565 +
 186.566 +    // Set it to empty
 186.567 +    Icc -> TagCount   = 0;
 186.568 +
 186.569 +    // Set default version
 186.570 +    Icc ->Version =  0x02100000;
 186.571 +
 186.572 +    // Set creation date/time
 186.573 +    memmove(&Icc ->Created, gmtime(&now), sizeof(Icc ->Created));
 186.574 +
 186.575 +    // Return the handle
 186.576 +    return (cmsHPROFILE) Icc;
 186.577 +}
 186.578 +
 186.579 +cmsContext CMSEXPORT cmsGetProfileContextID(cmsHPROFILE hProfile)
 186.580 +{
 186.581 +     _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
 186.582 +
 186.583 +    if (Icc == NULL) return NULL;
 186.584 +    return Icc -> ContextID;
 186.585 +}
 186.586 +
 186.587 +
 186.588 +// Return the number of tags
 186.589 +cmsInt32Number CMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile)
 186.590 +{
 186.591 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
 186.592 +    if (Icc == NULL) return -1;
 186.593 +
 186.594 +    return  Icc->TagCount;
 186.595 +}
 186.596 +
 186.597 +// Return the tag signature of a given tag number
 186.598 +cmsTagSignature CMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, cmsUInt32Number n)
 186.599 +{
 186.600 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
 186.601 +
 186.602 +    if (n > Icc->TagCount) return (cmsTagSignature) 0;  // Mark as not available
 186.603 +    if (n >= MAX_TABLE_TAG) return (cmsTagSignature) 0; // As double check
 186.604 +
 186.605 +    return Icc ->TagNames[n];
 186.606 +}
 186.607 +
 186.608  
 186.609  static
 186.610 -LCMSBOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
 186.611 +int SearchOneTag(_cmsICCPROFILE* Profile, cmsTagSignature sig)
 186.612  {
 186.613 -    if (fseek((FILE*) Icc ->stream, (long) offset, SEEK_SET) != 0) {
 186.614 +    cmsUInt32Number i;
 186.615  
 186.616 -       cmsSignalError(LCMS_ERRC_ABORTED, "Seek error; probably corrupted file");
 186.617 -       return TRUE;
 186.618 +    for (i=0; i < Profile -> TagCount; i++) {
 186.619 +
 186.620 +        if (sig == Profile -> TagNames[i])
 186.621 +            return i;
 186.622 +    }
 186.623 +
 186.624 +    return -1;
 186.625 +}
 186.626 +
 186.627 +// Search for a specific tag in tag dictionary. Returns position or -1 if tag not found.
 186.628 +// If followlinks is turned on, then the position of the linked tag is returned
 186.629 +int _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks)
 186.630 +{
 186.631 +    int n;
 186.632 +    cmsTagSignature LinkedSig;
 186.633 +
 186.634 +    do {
 186.635 +
 186.636 +        // Search for given tag in ICC profile directory
 186.637 +        n = SearchOneTag(Icc, sig);
 186.638 +        if (n < 0)
 186.639 +            return -1;        // Not found
 186.640 +
 186.641 +        if (!lFollowLinks)
 186.642 +            return n;         // Found, don't follow links
 186.643 +
 186.644 +        // Is this a linked tag?
 186.645 +        LinkedSig = Icc ->TagLinked[n];
 186.646 +
 186.647 +        // Yes, follow link
 186.648 +        if (LinkedSig != (cmsTagSignature) 0) {
 186.649 +            sig = LinkedSig;
 186.650 +        }
 186.651 +
 186.652 +    } while (LinkedSig != (cmsTagSignature) 0);
 186.653 +
 186.654 +    return n;
 186.655 +}
 186.656 +
 186.657 +
 186.658 +// Create a new tag entry
 186.659 +
 186.660 +static
 186.661 +cmsBool _cmsNewTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, int* NewPos)
 186.662 +{
 186.663 +    int i;
 186.664 +
 186.665 +    // Search for the tag
 186.666 +    i = _cmsSearchTag(Icc, sig, FALSE);
 186.667 +
 186.668 +    // Now let's do it easy. If the tag has been already written, that's an error
 186.669 +    if (i >= 0) {
 186.670 +        cmsSignalError(Icc ->ContextID, cmsERROR_ALREADY_DEFINED, "Tag '%x' already exists", sig);
 186.671 +        return FALSE;
 186.672 +    }
 186.673 +    else  {
 186.674 +
 186.675 +        // New one
 186.676 +
 186.677 +        if (Icc -> TagCount >= MAX_TABLE_TAG) {
 186.678 +            cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG);
 186.679 +            return FALSE;
 186.680 +        }
 186.681 +
 186.682 +        *NewPos = Icc ->TagCount;
 186.683 +        Icc -> TagCount++;
 186.684 +    }
 186.685 +
 186.686 +    return TRUE;
 186.687 +}
 186.688 +
 186.689 +
 186.690 +// Check existance
 186.691 +cmsBool CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig)
 186.692 +{
 186.693 +       _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) (void*) hProfile;
 186.694 +       return _cmsSearchTag(Icc, sig, FALSE) >= 0;
 186.695 +}
 186.696 +
 186.697 +
 186.698 +// Read profile header and validate it
 186.699 +cmsBool _cmsReadHeader(_cmsICCPROFILE* Icc)
 186.700 +{
 186.701 +    cmsTagEntry Tag;
 186.702 +    cmsICCHeader Header;
 186.703 +    cmsUInt32Number i, j;
 186.704 +    cmsUInt32Number HeaderSize;
 186.705 +    cmsIOHANDLER* io = Icc ->IOhandler;
 186.706 +    cmsUInt32Number TagCount;
 186.707 +
 186.708 +
 186.709 +    // Read the header
 186.710 +    if (io -> Read(io, &Header, sizeof(cmsICCHeader), 1) != 1) {
 186.711 +        return FALSE;
 186.712 +    }
 186.713 +
 186.714 +    // Validate file as an ICC profile
 186.715 +    if (_cmsAdjustEndianess32(Header.magic) != cmsMagicNumber) {
 186.716 +        cmsSignalError(Icc ->ContextID, cmsERROR_BAD_SIGNATURE, "not an ICC profile, invalid signature");
 186.717 +        return FALSE;
 186.718 +    }
 186.719 +
 186.720 +    // Adjust endianess of the used parameters
 186.721 +    Icc -> DeviceClass     = (cmsProfileClassSignature) _cmsAdjustEndianess32(Header.deviceClass);
 186.722 +    Icc -> ColorSpace      = (cmsColorSpaceSignature)   _cmsAdjustEndianess32(Header.colorSpace);
 186.723 +    Icc -> PCS             = (cmsColorSpaceSignature)   _cmsAdjustEndianess32(Header.pcs);
 186.724 +    Icc -> RenderingIntent = _cmsAdjustEndianess32(Header.renderingIntent);
 186.725 +    Icc -> flags           = _cmsAdjustEndianess32(Header.flags);
 186.726 +    Icc -> manufacturer    = _cmsAdjustEndianess32(Header.manufacturer);
 186.727 +    Icc -> model           = _cmsAdjustEndianess32(Header.model);
 186.728 +    _cmsAdjustEndianess64(&Icc -> attributes, Header.attributes);
 186.729 +    Icc -> Version         = _cmsAdjustEndianess32(Header.version);
 186.730 +
 186.731 +    // Get size as reported in header
 186.732 +    HeaderSize = _cmsAdjustEndianess32(Header.size);
 186.733 +
 186.734 +    // Get creation date/time
 186.735 +    _cmsDecodeDateTimeNumber(&Header.date, &Icc ->Created);
 186.736 +
 186.737 +    // The profile ID are 32 raw bytes
 186.738 +    memmove(Icc ->ProfileID.ID32, Header.profileID.ID32, 16);
 186.739 +
 186.740 +
 186.741 +    // Read tag directory
 186.742 +    if (!_cmsReadUInt32Number(io, &TagCount)) return FALSE;
 186.743 +    if (TagCount > MAX_TABLE_TAG) {
 186.744 +
 186.745 +        cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", TagCount);
 186.746 +        return FALSE;
 186.747 +    }
 186.748 +
 186.749 +    // Read tag directory
 186.750 +    Icc -> TagCount = 0;
 186.751 +    for (i=0; i < TagCount; i++) {
 186.752 +
 186.753 +        if (!_cmsReadUInt32Number(io, (cmsUInt32Number *) &Tag.sig)) return FALSE;
 186.754 +        if (!_cmsReadUInt32Number(io, &Tag.offset)) return FALSE;
 186.755 +        if (!_cmsReadUInt32Number(io, &Tag.size)) return FALSE;
 186.756 +
 186.757 +        // Perform some sanity check. Offset + size should fall inside file.
 186.758 +        if (Tag.offset + Tag.size > HeaderSize)
 186.759 +                  continue;
 186.760 +
 186.761 +        Icc -> TagNames[Icc ->TagCount]   = Tag.sig;
 186.762 +        Icc -> TagOffsets[Icc ->TagCount] = Tag.offset;
 186.763 +        Icc -> TagSizes[Icc ->TagCount]   = Tag.size;
 186.764 +
 186.765 +       // Search for links
 186.766 +        for (j=0; j < Icc ->TagCount; j++) {
 186.767 +
 186.768 +            if ((Icc ->TagOffsets[j] == Tag.offset) &&
 186.769 +                (Icc ->TagSizes[j]   == Tag.size)) {
 186.770 +
 186.771 +                Icc ->TagLinked[Icc ->TagCount] = Icc ->TagNames[j];
 186.772 +            }
 186.773 +
 186.774 +        }
 186.775 +
 186.776 +        Icc ->TagCount++;
 186.777 +    }
 186.778 +
 186.779 +    return TRUE;
 186.780 +}
 186.781 +
 186.782 +// Saves profile header
 186.783 +cmsBool _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace)
 186.784 +{
 186.785 +    cmsICCHeader Header;
 186.786 +    cmsUInt32Number i;
 186.787 +    cmsTagEntry Tag;
 186.788 +    cmsInt32Number Count = 0;
 186.789 +
 186.790 +    Header.size        = _cmsAdjustEndianess32(UsedSpace);
 186.791 +    Header.cmmId       = _cmsAdjustEndianess32(lcmsSignature);
 186.792 +    Header.version     = _cmsAdjustEndianess32(Icc ->Version);
 186.793 +
 186.794 +    Header.deviceClass = (cmsProfileClassSignature) _cmsAdjustEndianess32(Icc -> DeviceClass);
 186.795 +    Header.colorSpace  = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Icc -> ColorSpace);
 186.796 +    Header.pcs         = (cmsColorSpaceSignature) _cmsAdjustEndianess32(Icc -> PCS);
 186.797 +
 186.798 +    //   NOTE: in v4 Timestamp must be in UTC rather than in local time
 186.799 +    _cmsEncodeDateTimeNumber(&Header.date, &Icc ->Created);
 186.800 +
 186.801 +    Header.magic       = _cmsAdjustEndianess32(cmsMagicNumber);
 186.802 +
 186.803 +#ifdef CMS_IS_WINDOWS_
 186.804 +    Header.platform    = (cmsPlatformSignature) _cmsAdjustEndianess32(cmsSigMicrosoft);
 186.805 +#else
 186.806 +    Header.platform    = (cmsPlatformSignature) _cmsAdjustEndianess32(cmsSigMacintosh);
 186.807 +#endif
 186.808 +
 186.809 +    Header.flags        = _cmsAdjustEndianess32(Icc -> flags);
 186.810 +    Header.manufacturer = _cmsAdjustEndianess32(Icc -> manufacturer);
 186.811 +    Header.model        = _cmsAdjustEndianess32(Icc -> model);
 186.812 +
 186.813 +    _cmsAdjustEndianess64(&Header.attributes, Icc -> attributes);
 186.814 +
 186.815 +    // Rendering intent in the header (for embedded profiles)
 186.816 +    Header.renderingIntent = _cmsAdjustEndianess32(Icc -> RenderingIntent);
 186.817 +
 186.818 +    // Illuminant is always D50
 186.819 +    Header.illuminant.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->X));
 186.820 +    Header.illuminant.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Y));
 186.821 +    Header.illuminant.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(cmsD50_XYZ()->Z));
 186.822 +
 186.823 +    // Created by LittleCMS (that's me!)
 186.824 +    Header.creator      = _cmsAdjustEndianess32(lcmsSignature);
 186.825 +
 186.826 +    memset(&Header.reserved, 0, sizeof(Header.reserved));
 186.827 +
 186.828 +    // Set profile ID. Endianess is always big endian
 186.829 +    memmove(&Header.profileID, &Icc ->ProfileID, 16);
 186.830 +
 186.831 +    // Dump the header
 186.832 +    if (!Icc -> IOhandler->Write(Icc->IOhandler, sizeof(cmsICCHeader), &Header)) return FALSE;
 186.833 +
 186.834 +    // Saves Tag directory
 186.835 +
 186.836 +    // Get true count
 186.837 +    for (i=0;  i < Icc -> TagCount; i++) {
 186.838 +        if (Icc ->TagNames[i] != 0)
 186.839 +            Count++;
 186.840 +    }
 186.841 +
 186.842 +    // Store number of tags
 186.843 +    if (!_cmsWriteUInt32Number(Icc ->IOhandler, Count)) return FALSE;
 186.844 +
 186.845 +    for (i=0; i < Icc -> TagCount; i++) {
 186.846 +
 186.847 +        if (Icc ->TagNames[i] == 0) continue;   // It is just a placeholder
 186.848 +
 186.849 +        Tag.sig    = (cmsTagSignature) _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagNames[i]);
 186.850 +        Tag.offset = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagOffsets[i]);
 186.851 +        Tag.size   = _cmsAdjustEndianess32((cmsInt32Number) Icc -> TagSizes[i]);
 186.852 +
 186.853 +        if (!Icc ->IOhandler -> Write(Icc-> IOhandler, sizeof(cmsTagEntry), &Tag)) return FALSE;
 186.854 +    }
 186.855 +
 186.856 +    return TRUE;
 186.857 +}
 186.858 +
 186.859 +// ----------------------------------------------------------------------- Set/Get several struct members
 186.860 +
 186.861 +
 186.862 +cmsUInt32Number CMSEXPORT cmsGetHeaderRenderingIntent(cmsHPROFILE hProfile)
 186.863 +{
 186.864 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.865 +    return Icc -> RenderingIntent;
 186.866 +}
 186.867 +
 186.868 +void CMSEXPORT cmsSetHeaderRenderingIntent(cmsHPROFILE hProfile, cmsUInt32Number RenderingIntent)
 186.869 +{
 186.870 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.871 +    Icc -> RenderingIntent = RenderingIntent;
 186.872 +}
 186.873 +
 186.874 +cmsUInt32Number CMSEXPORT cmsGetHeaderFlags(cmsHPROFILE hProfile)
 186.875 +{
 186.876 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.877 +    return (cmsUInt32Number) Icc -> flags;
 186.878 +}
 186.879 +
 186.880 +void CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags)
 186.881 +{
 186.882 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.883 +    Icc -> flags = (cmsUInt32Number) Flags;
 186.884 +}
 186.885 +
 186.886 +cmsUInt32Number CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile)
 186.887 +{
 186.888 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.889 +    return (cmsUInt32Number) Icc ->manufacturer;
 186.890 +}
 186.891 +
 186.892 +void CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer)
 186.893 +{
 186.894 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.895 +    Icc -> manufacturer = (cmsUInt32Number) manufacturer;
 186.896 +}
 186.897 +
 186.898 +cmsUInt32Number CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile)
 186.899 +{
 186.900 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.901 +    return (cmsUInt32Number) Icc ->model;
 186.902 +}
 186.903 +
 186.904 +void CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model)
 186.905 +{
 186.906 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.907 +    Icc -> manufacturer = (cmsUInt32Number) model;
 186.908 +}
 186.909 +
 186.910 +
 186.911 +void CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags)
 186.912 +{
 186.913 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.914 +    memmove(Flags, &Icc -> attributes, sizeof(cmsUInt64Number));
 186.915 +}
 186.916 +
 186.917 +void CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags)
 186.918 +{
 186.919 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.920 +    memmove(&Icc -> attributes, &Flags, sizeof(cmsUInt64Number));
 186.921 +}
 186.922 +
 186.923 +void CMSEXPORT cmsGetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID)
 186.924 +{
 186.925 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.926 +    memmove(ProfileID, Icc ->ProfileID.ID8, 16);
 186.927 +}
 186.928 +
 186.929 +void CMSEXPORT cmsSetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID)
 186.930 +{
 186.931 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.932 +    memmove(&Icc -> ProfileID, ProfileID, 16);
 186.933 +}
 186.934 +
 186.935 +cmsBool  CMSEXPORT cmsGetHeaderCreationDateTime(cmsHPROFILE hProfile, struct tm *Dest)
 186.936 +{
 186.937 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.938 +    memmove(Dest, &Icc ->Created, sizeof(struct tm));
 186.939 +    return TRUE;
 186.940 +}
 186.941 +
 186.942 +cmsColorSpaceSignature CMSEXPORT cmsGetPCS(cmsHPROFILE hProfile)
 186.943 +{
 186.944 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.945 +    return Icc -> PCS;
 186.946 +}
 186.947 +
 186.948 +void CMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, cmsColorSpaceSignature pcs)
 186.949 +{
 186.950 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.951 +    Icc -> PCS = pcs;
 186.952 +}
 186.953 +
 186.954 +cmsColorSpaceSignature CMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile)
 186.955 +{
 186.956 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.957 +    return Icc -> ColorSpace;
 186.958 +}
 186.959 +
 186.960 +void CMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, cmsColorSpaceSignature sig)
 186.961 +{
 186.962 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.963 +    Icc -> ColorSpace = sig;
 186.964 +}
 186.965 +
 186.966 +cmsProfileClassSignature CMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile)
 186.967 +{
 186.968 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.969 +    return Icc -> DeviceClass;
 186.970 +}
 186.971 +
 186.972 +void CMSEXPORT cmsSetDeviceClass(cmsHPROFILE hProfile, cmsProfileClassSignature sig)
 186.973 +{
 186.974 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.975 +    Icc -> DeviceClass = sig;
 186.976 +}
 186.977 +
 186.978 +cmsUInt32Number CMSEXPORT cmsGetEncodedICCversion(cmsHPROFILE hProfile)
 186.979 +{
 186.980 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.981 +    return Icc -> Version;
 186.982 +}
 186.983 +
 186.984 +void CMSEXPORT cmsSetEncodedICCversion(cmsHPROFILE hProfile, cmsUInt32Number Version)
 186.985 +{
 186.986 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
 186.987 +    Icc -> Version = Version;
 186.988 +}
 186.989 +
 186.990 +// Get an hexadecimal number with same digits as v
 186.991 +static
 186.992 +cmsUInt32Number BaseToBase(cmsUInt32Number in, int BaseIn, int BaseOut)
 186.993 +{
 186.994 +    char Buff[100];
 186.995 +    int i, len;
 186.996 +    cmsUInt32Number out;
 186.997 +
 186.998 +    for (len=0; in > 0 && len < 100; len++) {
 186.999 +
186.1000 +        Buff[len] = (char) (in % BaseIn);
186.1001 +        in /= BaseIn;
186.1002 +    }
186.1003 +
186.1004 +    for (i=len-1, out=0; i >= 0; --i) {
186.1005 +        out = out * BaseOut + Buff[i];
186.1006 +    }
186.1007 +
186.1008 +    return out;
186.1009 +}
186.1010 +
186.1011 +void  CMSEXPORT cmsSetProfileVersion(cmsHPROFILE hProfile, cmsFloat64Number Version)
186.1012 +{
186.1013 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
186.1014 +
186.1015 +    // 4.2 -> 0x4200000
186.1016 +
186.1017 +    Icc -> Version = BaseToBase((cmsUInt32Number) floor(Version * 100.0), 10, 16) << 16;
186.1018 +}
186.1019 +
186.1020 +cmsFloat64Number CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile)
186.1021 +{
186.1022 +    _cmsICCPROFILE*  Icc = (_cmsICCPROFILE*) hProfile;
186.1023 +    cmsUInt32Number n = Icc -> Version >> 16;
186.1024 +
186.1025 +    return BaseToBase(n, 16, 10) / 100.0;
186.1026 +}
186.1027 +// --------------------------------------------------------------------------------------------------------------
186.1028 +
186.1029 +
186.1030 +// Create profile from IOhandler
186.1031 +cmsHPROFILE CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io)
186.1032 +{
186.1033 +    _cmsICCPROFILE* NewIcc;
186.1034 +    cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID);
186.1035 +
186.1036 +    if (hEmpty == NULL) return NULL;
186.1037 +
186.1038 +    NewIcc = (_cmsICCPROFILE*) hEmpty;
186.1039 +
186.1040 +    NewIcc ->IOhandler = io;
186.1041 +    if (!_cmsReadHeader(NewIcc)) goto Error;
186.1042 +    return hEmpty;
186.1043 +
186.1044 +Error:
186.1045 +    cmsCloseProfile(hEmpty);
186.1046 +    return NULL;
186.1047 +}
186.1048 +
186.1049 +// Create profile from disk file
186.1050 +cmsHPROFILE CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *lpFileName, const char *sAccess)
186.1051 +{
186.1052 +    _cmsICCPROFILE* NewIcc;
186.1053 +    cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID);
186.1054 +
186.1055 +    if (hEmpty == NULL) return NULL;
186.1056 +
186.1057 +    NewIcc = (_cmsICCPROFILE*) hEmpty;
186.1058 +
186.1059 +    NewIcc ->IOhandler = cmsOpenIOhandlerFromFile(ContextID, lpFileName, sAccess);
186.1060 +    if (NewIcc ->IOhandler == NULL) goto Error;
186.1061 +
186.1062 +    if (*sAccess == 'W' || *sAccess == 'w') {
186.1063 +
186.1064 +        NewIcc -> IsWrite = TRUE;
186.1065 +
186.1066 +        return hEmpty;
186.1067 +    }
186.1068 +
186.1069 +    if (!_cmsReadHeader(NewIcc)) goto Error;
186.1070 +    return hEmpty;
186.1071 +
186.1072 +Error:
186.1073 +    cmsCloseProfile(hEmpty);
186.1074 +    return NULL;
186.1075 +}
186.1076 +
186.1077 +
186.1078 +cmsHPROFILE CMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess)
186.1079 +{
186.1080 +    return cmsOpenProfileFromFileTHR(NULL, ICCProfile, sAccess);
186.1081 +}
186.1082 +
186.1083 +
186.1084 +cmsHPROFILE  CMSEXPORT cmsOpenProfileFromStreamTHR(cmsContext ContextID, FILE* ICCProfile, const char *sAccess)
186.1085 +{
186.1086 +    _cmsICCPROFILE* NewIcc;
186.1087 +    cmsHPROFILE hEmpty = cmsCreateProfilePlaceholder(ContextID);
186.1088 +
186.1089 +    if (hEmpty == NULL) return NULL;
186.1090 +
186.1091 +    NewIcc = (_cmsICCPROFILE*) hEmpty;
186.1092 +
186.1093 +    NewIcc ->IOhandler = cmsOpenIOhandlerFromStream(ContextID, ICCProfile);
186.1094 +    if (NewIcc ->IOhandler == NULL) goto Error;
186.1095 +
186.1096 +    if (*sAccess == 'w') {
186.1097 +
186.1098 +        NewIcc -> IsWrite = TRUE;
186.1099 +        return hEmpty;
186.1100 +    }
186.1101 +
186.1102 +    if (!_cmsReadHeader(NewIcc)) goto Error;
186.1103 +    return hEmpty;
186.1104 +
186.1105 +Error:
186.1106 +    cmsCloseProfile(hEmpty);
186.1107 +    return NULL;
186.1108 +
186.1109 +}
186.1110 +
186.1111 +cmsHPROFILE  CMSEXPORT cmsOpenProfileFromStream(FILE* ICCProfile, const char *sAccess)
186.1112 +{
186.1113 +    return cmsOpenProfileFromStreamTHR(NULL, ICCProfile, sAccess);
186.1114 +}
186.1115 +
186.1116 +
186.1117 +// Open from memory block
186.1118 +cmsHPROFILE CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void* MemPtr, cmsUInt32Number dwSize)
186.1119 +{
186.1120 +    _cmsICCPROFILE* NewIcc;
186.1121 +    cmsHPROFILE hEmpty;
186.1122 +
186.1123 +    hEmpty = cmsCreateProfilePlaceholder(ContextID);
186.1124 +    if (hEmpty == NULL) return NULL;
186.1125 +
186.1126 +    NewIcc = (_cmsICCPROFILE*) hEmpty;
186.1127 +
186.1128 +    // Ok, in this case const void* is casted to void* just because open IO handler
186.1129 +    // shares read and writting modes. Don't abuse this feature!
186.1130 +    NewIcc ->IOhandler = cmsOpenIOhandlerFromMem(ContextID, (void*) MemPtr, dwSize, "r");
186.1131 +    if (NewIcc ->IOhandler == NULL) goto Error;
186.1132 +
186.1133 +    if (!_cmsReadHeader(NewIcc)) goto Error;
186.1134 +
186.1135 +    return hEmpty;
186.1136 +
186.1137 +Error:
186.1138 +    cmsCloseProfile(hEmpty);
186.1139 +    return NULL;
186.1140 +}
186.1141 +
186.1142 +cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number dwSize)
186.1143 +{
186.1144 +    return cmsOpenProfileFromMemTHR(NULL, MemPtr, dwSize);
186.1145 +}
186.1146 +
186.1147 +
186.1148 +
186.1149 +// Dump tag contents. If the profile is being modified, untouched tags are copied from FileOrig
186.1150 +static
186.1151 +cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
186.1152 +{
186.1153 +    cmsUInt8Number* Data;
186.1154 +    cmsUInt32Number i;
186.1155 +    cmsUInt32Number Begin;
186.1156 +    cmsIOHANDLER* io = Icc ->IOhandler;
186.1157 +    cmsTagDescriptor* TagDescriptor;
186.1158 +    cmsTagTypeSignature TypeBase;
186.1159 +    cmsTagTypeHandler* TypeHandler;
186.1160 +
186.1161 +
186.1162 +    for (i=0; i < Icc -> TagCount; i++) {
186.1163 +
186.1164 +
186.1165 +        if (Icc ->TagNames[i] == 0) continue;
186.1166 +
186.1167 +        // Linked tags are not written
186.1168 +        if (Icc ->TagLinked[i] != (cmsTagSignature) 0) continue;
186.1169 +
186.1170 +        Icc -> TagOffsets[i] = Begin = io ->UsedSpace;
186.1171 +
186.1172 +        Data = (cmsUInt8Number*)  Icc -> TagPtrs[i];
186.1173 +
186.1174 +        if (!Data) {
186.1175 +
186.1176 +            // Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user.
186.1177 +            // In this case a blind copy of the block data is performed
186.1178 +            if (FileOrig != NULL && Icc -> TagOffsets[i]) {
186.1179 +
186.1180 +                cmsUInt32Number TagSize   = FileOrig -> TagSizes[i];
186.1181 +                cmsUInt32Number TagOffset = FileOrig -> TagOffsets[i];
186.1182 +                void* Mem;
186.1183 +
186.1184 +                if (!FileOrig ->IOhandler->Seek(FileOrig ->IOhandler, TagOffset)) return FALSE;
186.1185 +
186.1186 +                Mem = _cmsMalloc(Icc ->ContextID, TagSize);
186.1187 +                if (Mem == NULL) return FALSE;
186.1188 +
186.1189 +                if (FileOrig ->IOhandler->Read(FileOrig->IOhandler, Mem, TagSize, 1) != 1) return FALSE;
186.1190 +                if (!io ->Write(io, TagSize, Mem)) return FALSE;
186.1191 +                _cmsFree(Icc ->ContextID, Mem);
186.1192 +
186.1193 +                Icc -> TagSizes[i] = (io ->UsedSpace - Begin);
186.1194 +
186.1195 +
186.1196 +                // Align to 32 bit boundary.
186.1197 +                if (! _cmsWriteAlignment(io))
186.1198 +                    return FALSE;
186.1199 +            }
186.1200 +
186.1201 +            continue;
186.1202 +        }
186.1203 +
186.1204 +
186.1205 +        // Should this tag be saved as RAW? If so, tagsizes should be specified in advance (no further cooking is done)
186.1206 +        if (Icc ->TagSaveAsRaw[i]) {
186.1207 +
186.1208 +            if (io -> Write(io, Icc ->TagSizes[i], Data) != 1) return FALSE;
186.1209 +        }
186.1210 +        else {
186.1211 +
186.1212 +            // Search for support on this tag
186.1213 +            TagDescriptor = _cmsGetTagDescriptor(Icc -> TagNames[i]);
186.1214 +            if (TagDescriptor == NULL) continue;                        // Unsupported, ignore it
186.1215 +
186.1216 +            TypeHandler = Icc ->TagTypeHandlers[i];
186.1217 +
186.1218 +            if (TypeHandler == NULL) {
186.1219 +                cmsSignalError(Icc ->ContextID, cmsERROR_INTERNAL, "(Internal) no handler for tag %x", Icc -> TagNames[i]);
186.1220 +                continue;
186.1221 +            }
186.1222 +
186.1223 +            TypeBase    = TypeHandler ->Signature;
186.1224 +            if (!_cmsWriteTypeBase(io, TypeBase))
186.1225 +                return FALSE;
186.1226 +
186.1227 +            if (!TypeHandler ->WritePtr(TypeHandler, io, Data, TagDescriptor ->ElemCount)) {
186.1228 +
186.1229 +                char String[5];
186.1230 +
186.1231 +                _cmsTagSignature2String(String, (cmsTagSignature) TypeBase);
186.1232 +                cmsSignalError(Icc ->ContextID, cmsERROR_WRITE, "Couldn't write type '%s'", String);
186.1233 +                return FALSE;
186.1234 +            }
186.1235 +        }
186.1236 +
186.1237 +
186.1238 +        Icc -> TagSizes[i] = (io ->UsedSpace - Begin);
186.1239 +
186.1240 +        // Align to 32 bit boundary.
186.1241 +        if (! _cmsWriteAlignment(io))
186.1242 +            return FALSE;
186.1243 +    }
186.1244 +
186.1245 +
186.1246 +    return TRUE;
186.1247 +}
186.1248 +
186.1249 +
186.1250 +// Fill the offset and size fields for all linked tags
186.1251 +static
186.1252 +cmsBool SetLinks( _cmsICCPROFILE* Icc)
186.1253 +{
186.1254 +    cmsUInt32Number i;
186.1255 +
186.1256 +    for (i=0; i < Icc -> TagCount; i++) {
186.1257 +
186.1258 +        cmsTagSignature lnk = Icc ->TagLinked[i];
186.1259 +        if (lnk != (cmsTagSignature) 0) {
186.1260 +
186.1261 +            int j = _cmsSearchTag(Icc, lnk, FALSE);
186.1262 +            if (j >= 0) {
186.1263 +
186.1264 +                Icc ->TagOffsets[i] = Icc ->TagOffsets[j];
186.1265 +                Icc ->TagSizes[i]   = Icc ->TagSizes[j];
186.1266 +            }
186.1267 +
186.1268 +        }
186.1269 +    }
186.1270 +
186.1271 +    return TRUE;
186.1272 +}
186.1273 +
186.1274 +// Low-level save to IOHANDLER. It returns the number of bytes used to
186.1275 +// store the profile, or zero on error. io may be NULL and in this case
186.1276 +// no data is written--only sizes are calculated
186.1277 +cmsUInt32Number CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOHANDLER* io)
186.1278 +{
186.1279 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
186.1280 +    _cmsICCPROFILE Keep;
186.1281 +    cmsIOHANDLER* PrevIO;
186.1282 +    cmsUInt32Number UsedSpace;
186.1283 +    cmsContext ContextID;
186.1284 +
186.1285 +    memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
186.1286 +
186.1287 +    ContextID = cmsGetProfileContextID(hProfile);
186.1288 +    PrevIO = Icc ->IOhandler = cmsOpenIOhandlerFromNULL(ContextID);
186.1289 +    if (PrevIO == NULL) return 0;
186.1290 +
186.1291 +    // Pass #1 does compute offsets
186.1292 +
186.1293 +    if (!_cmsWriteHeader(Icc, 0)) return 0;
186.1294 +    if (!SaveTags(Icc, &Keep)) return 0;
186.1295 +
186.1296 +    UsedSpace = PrevIO ->UsedSpace;
186.1297 +
186.1298 +    // Pass #2 does save to iohandler
186.1299 +
186.1300 +    if (io != NULL) {
186.1301 +        Icc ->IOhandler = io;
186.1302 +        if (!SetLinks(Icc)) goto CleanUp;
186.1303 +        if (!_cmsWriteHeader(Icc, UsedSpace)) goto CleanUp;
186.1304 +        if (!SaveTags(Icc, &Keep)) goto CleanUp;
186.1305 +    }
186.1306 +
186.1307 +    memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
186.1308 +    if (!cmsCloseIOhandler(PrevIO)) return 0;
186.1309 +
186.1310 +    return UsedSpace;
186.1311 +
186.1312 +
186.1313 +CleanUp:
186.1314 +    cmsCloseIOhandler(PrevIO);
186.1315 +    memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
186.1316 +    return 0;
186.1317 +}
186.1318 +
186.1319 +
186.1320 +// Low-level save to disk.
186.1321 +cmsBool  CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName)
186.1322 +{
186.1323 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
186.1324 +    cmsIOHANDLER* io = cmsOpenIOhandlerFromFile(ContextID, FileName, "w");
186.1325 +    cmsBool rc;
186.1326 +
186.1327 +    if (io == NULL) return FALSE;
186.1328 +
186.1329 +    rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0);
186.1330 +    rc &= cmsCloseIOhandler(io);
186.1331 +
186.1332 +    if (rc == FALSE) {          // remove() is C99 per 7.19.4.1
186.1333 +            remove(FileName);   // We have to IGNORE return value in this case
186.1334 +    }
186.1335 +    return rc;
186.1336 +}
186.1337 +
186.1338 +// Same as anterior, but for streams
186.1339 +cmsBool CMSEXPORT cmsSaveProfileToStream(cmsHPROFILE hProfile, FILE* Stream)
186.1340 +{
186.1341 +    cmsBool rc;
186.1342 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
186.1343 +    cmsIOHANDLER* io = cmsOpenIOhandlerFromStream(ContextID, Stream);
186.1344 +
186.1345 +    if (io == NULL) return FALSE;
186.1346 +
186.1347 +    rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0);
186.1348 +    rc &= cmsCloseIOhandler(io);
186.1349 +
186.1350 +    return rc;
186.1351 +}
186.1352 +
186.1353 +
186.1354 +// Same as anterior, but for memory blocks. In this case, a NULL as MemPtr means calculate needed space only
186.1355 +cmsBool CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUInt32Number* BytesNeeded)
186.1356 +{
186.1357 +    cmsBool rc;
186.1358 +    cmsIOHANDLER* io;
186.1359 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
186.1360 +
186.1361 +    // Should we just calculate the needed space?
186.1362 +    if (MemPtr == NULL) {
186.1363 +
186.1364 +           *BytesNeeded =  cmsSaveProfileToIOhandler(hProfile, NULL);
186.1365 +            return TRUE;
186.1366 +    }
186.1367 +
186.1368 +    // That is a real write operation
186.1369 +    io =  cmsOpenIOhandlerFromMem(ContextID, MemPtr, *BytesNeeded, "w");
186.1370 +    if (io == NULL) return FALSE;
186.1371 +
186.1372 +    rc = (cmsSaveProfileToIOhandler(hProfile, io) != 0);
186.1373 +    rc &= cmsCloseIOhandler(io);
186.1374 +
186.1375 +    return rc;
186.1376 +}
186.1377 +
186.1378 +
186.1379 +
186.1380 +// Closes a profile freeing any involved resources
186.1381 +cmsBool  CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
186.1382 +{
186.1383 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
186.1384 +    cmsBool  rc = TRUE;
186.1385 +    cmsUInt32Number i;
186.1386 +
186.1387 +    if (!Icc) return FALSE;
186.1388 +
186.1389 +    // Was open in write mode?
186.1390 +    if (Icc ->IsWrite) {
186.1391 +
186.1392 +        Icc ->IsWrite = FALSE;      // Assure no further writting
186.1393 +        rc &= cmsSaveProfileToFile(hProfile, Icc ->IOhandler->PhysicalFile);
186.1394 +    }
186.1395 +
186.1396 +    for (i=0; i < Icc -> TagCount; i++) {
186.1397 +
186.1398 +        if (Icc -> TagPtrs[i]) {
186.1399 +
186.1400 +            cmsTagTypeHandler* TypeHandler = Icc ->TagTypeHandlers[i];
186.1401 +
186.1402 +            if (TypeHandler != NULL)
186.1403 +                TypeHandler ->FreePtr(TypeHandler, Icc -> TagPtrs[i]);
186.1404 +            else
186.1405 +                _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
186.1406 +        }
186.1407 +    }
186.1408 +
186.1409 +    if (Icc ->IOhandler != NULL) {
186.1410 +        rc &= cmsCloseIOhandler(Icc->IOhandler);
186.1411 +    }
186.1412 +
186.1413 +    _cmsFree(Icc ->ContextID, Icc);   // Free placeholder memory
186.1414 +
186.1415 +    return rc;
186.1416 +}
186.1417 +
186.1418 +
186.1419 +// -------------------------------------------------------------------------------------------------------------------
186.1420 +
186.1421 +
186.1422 +// Returns TRUE if a given tag is supported by a plug-in
186.1423 +static
186.1424 +cmsBool IsTypeSupported(cmsTagDescriptor* TagDescriptor, cmsTagTypeSignature Type)
186.1425 +{
186.1426 +    cmsUInt32Number i, nMaxTypes;
186.1427 +
186.1428 +    nMaxTypes = TagDescriptor->nSupportedTypes;
186.1429 +    if (nMaxTypes >= MAX_TYPES_IN_LCMS_PLUGIN)
186.1430 +        nMaxTypes = MAX_TYPES_IN_LCMS_PLUGIN;
186.1431 +
186.1432 +    for (i=0; i < nMaxTypes; i++) {
186.1433 +        if (Type == TagDescriptor ->SupportedTypes[i]) return TRUE;
186.1434      }
186.1435  
186.1436      return FALSE;
186.1437  }
186.1438  
186.1439  
186.1440 -static
186.1441 -size_t FileTell(struct _lcms_iccprofile_struct* Icc)
186.1442 +// That's the main read function
186.1443 +void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
186.1444  {
186.1445 -    return ftell((FILE*) Icc ->stream);
186.1446 -}
186.1447 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
186.1448 +    cmsIOHANDLER* io = Icc ->IOhandler;
186.1449 +    cmsTagTypeHandler* TypeHandler;
186.1450 +    cmsTagDescriptor*  TagDescriptor;
186.1451 +    cmsTagTypeSignature BaseType;
186.1452 +    cmsUInt32Number Offset, TagSize;
186.1453 +    cmsUInt32Number ElemCount;
186.1454 +    int n;
186.1455  
186.1456 -// Writes data to stream, also keeps used space for further reference
186.1457 +    n = _cmsSearchTag(Icc, sig, TRUE);
186.1458 +    if (n < 0) return NULL;                 // Not found, return NULL
186.1459  
186.1460  
186.1461 -static
186.1462 -LCMSBOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr)
186.1463 -{
186.1464 -       if (size == 0) return TRUE;
186.1465  
186.1466 -       Icc->UsedSpace += size;
186.1467 +    // If the element is already in memory, return the pointer
186.1468 +    if (Icc -> TagPtrs[n]) {
186.1469  
186.1470 -       if (Icc->stream == NULL) {
186.1471 -
186.1472 -              return TRUE;
186.1473 -       }
186.1474 -
186.1475 -       return (fwrite(Ptr, size, 1, (FILE*) Icc->stream) == 1);
186.1476 -}
186.1477 -
186.1478 -
186.1479 -static
186.1480 -LCMSBOOL FileGrow(struct _lcms_iccprofile_struct* Icc, size_t size)
186.1481 -{
186.1482 -  return TRUE;
186.1483 -}
186.1484 -
186.1485 -
186.1486 -static
186.1487 -LCMSBOOL FileClose(struct _lcms_iccprofile_struct* Icc)
186.1488 -{
186.1489 -    return fclose((FILE*) Icc ->stream);
186.1490 -}
186.1491 -
186.1492 -// ----------------------------------------------------------------------------------------------------
186.1493 -
186.1494 -
186.1495 -// Creates an empty structure holding all required parameters
186.1496 -
186.1497 -cmsHPROFILE _cmsCreateProfilePlaceholder(void)
186.1498 -{
186.1499 -
186.1500 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) _cmsMalloc(sizeof(LCMSICCPROFILE));
186.1501 -    if (Icc == NULL) return NULL;
186.1502 -
186.1503 -    // Empty values
186.1504 -    ZeroMemory(Icc, sizeof(LCMSICCPROFILE));
186.1505 -
186.1506 -    // Make sure illuminant is correct
186.1507 -    Icc ->Illuminant = *cmsD50_XYZ();
186.1508 -
186.1509 -    // Set it to empty
186.1510 -    Icc -> TagCount   = 0;
186.1511 -
186.1512 -    // Return the handle
186.1513 -    return (cmsHPROFILE) Icc;
186.1514 -}
186.1515 -
186.1516 -
186.1517 -// Return the number of tags
186.1518 -icInt32Number LCMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile)
186.1519 -{
186.1520 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
186.1521 -    return  Icc->TagCount;
186.1522 -}
186.1523 -
186.1524 -// Return the tag signature of a given tag number
186.1525 -icTagSignature LCMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, icInt32Number n)
186.1526 -{
186.1527 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
186.1528 -
186.1529 -    if (n < 0 || n > Icc->TagCount) return (icTagSignature) 0;  // Mark as not available
186.1530 -
186.1531 -    return Icc ->TagNames[n];
186.1532 -}
186.1533 -
186.1534 -
186.1535 -// Search for a specific tag in tag dictionary
186.1536 -// Returns position or -1 if tag not found
186.1537 -
186.1538 -icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError)
186.1539 -{
186.1540 -       icInt32Number i;
186.1541 -
186.1542 -       if (sig == 0) return -1;     // 0 identifies a special tag holding raw memory.
186.1543 -
186.1544 -       for (i=0; i < Profile -> TagCount; i++) {
186.1545 -
186.1546 -              if (sig == Profile -> TagNames[i])
186.1547 -                            return i;
186.1548 -       }
186.1549 -
186.1550 -       if (lSignalError)
186.1551 -            cmsSignalError(LCMS_ERRC_ABORTED, "Tag '%lx' not found", sig);
186.1552 -
186.1553 -       return -1;
186.1554 -}
186.1555 -
186.1556 -
186.1557 -// Check existance
186.1558 -
186.1559 -LCMSBOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig)
186.1560 -{
186.1561 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.1562 -       return _cmsSearchTag(Icc, sig, FALSE) >= 0;
186.1563 -}
186.1564 -
186.1565 -
186.1566 -
186.1567 -// Search for a particular tag, replace if found or add new one else
186.1568 -
186.1569 -LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const void* Init)
186.1570 -{
186.1571 -    LPVOID Ptr;
186.1572 -    icInt32Number i;
186.1573 -
186.1574 -    i = _cmsSearchTag(Icc, sig, FALSE);
186.1575 -
186.1576 -    if (i >=0) {
186.1577 -
186.1578 -        if (Icc -> TagPtrs[i]) _cmsFree(Icc -> TagPtrs[i]);
186.1579 -    }
186.1580 -    else  {
186.1581 -
186.1582 -        i = Icc -> TagCount;
186.1583 -        Icc -> TagCount++;
186.1584 -
186.1585 -        if (Icc ->TagCount >= MAX_TABLE_TAG) {
186.1586 -
186.1587 -            cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", MAX_TABLE_TAG);
186.1588 -            Icc ->TagCount = MAX_TABLE_TAG-1;
186.1589 -            return NULL;
186.1590 -        }
186.1591 +        if (Icc ->TagSaveAsRaw[n]) return NULL;  // We don't support read raw tags as cooked
186.1592 +        return Icc -> TagPtrs[n];
186.1593      }
186.1594  
186.1595 +    // We need to read it. Get the offset and size to the file
186.1596 +    Offset    = Icc -> TagOffsets[n];
186.1597 +    TagSize   = Icc -> TagSizes[n];
186.1598  
186.1599 -    Ptr = _cmsMalloc(size);
186.1600 -    if (Ptr == NULL) return NULL;
186.1601 +    // Seek to its location
186.1602 +    if (!io -> Seek(io, Offset))
186.1603 +            return NULL;
186.1604  
186.1605 -    CopyMemory(Ptr, Init, size);
186.1606 +    // Search for support on this tag
186.1607 +    TagDescriptor = _cmsGetTagDescriptor(sig);
186.1608 +    if (TagDescriptor == NULL) return NULL;     // Unsupported.
186.1609  
186.1610 -    Icc ->TagNames[i] = sig;
186.1611 -    Icc ->TagSizes[i] = size;
186.1612 -    Icc ->TagPtrs[i]  = Ptr;
186.1613 +    // if supported, get type and check if in list
186.1614 +    BaseType = _cmsReadTypeBase(io);
186.1615 +    if (BaseType == 0) return NULL;
186.1616  
186.1617 -    return Ptr;
186.1618 -}
186.1619 +    if (!IsTypeSupported(TagDescriptor, BaseType)) return NULL;
186.1620  
186.1621 +    TagSize  -= 8;                      // Alredy read by the type base logic
186.1622  
186.1623 +    // Get type handler
186.1624 +    TypeHandler = _cmsGetTagTypeHandler(BaseType);
186.1625 +    if (TypeHandler == NULL) return NULL;
186.1626  
186.1627  
186.1628 +    // Read the tag
186.1629 +    Icc -> TagTypeHandlers[n] = TypeHandler;
186.1630 +    Icc -> TagPtrs[n] = TypeHandler ->ReadPtr(TypeHandler, io, &ElemCount, TagSize);
186.1631  
186.1632 -// Creates a profile from file read placeholder
186.1633 +    // The tag type is supported, but something wrong happend and we cannot read the tag.
186.1634 +    // let know the user about this (although it is just a warning)
186.1635 +    if (Icc -> TagPtrs[n] == NULL) {
186.1636  
186.1637 -LPLCMSICCPROFILE _cmsCreateProfileFromFilePlaceholder(const char* FileName)
186.1638 -{
186.1639 -    LPLCMSICCPROFILE NewIcc;
186.1640 -    LPVOID ICCfile = FileOpen(FileName);
186.1641 +        char String[5];
186.1642  
186.1643 -    if (ICCfile == NULL) {
186.1644 -
186.1645 -              cmsSignalError(LCMS_ERRC_ABORTED, "File '%s' not found", FileName);
186.1646 -              return NULL;
186.1647 -    }
186.1648 -
186.1649 -    NewIcc = (LPLCMSICCPROFILE) _cmsCreateProfilePlaceholder();
186.1650 -    if (NewIcc == NULL) return NULL;
186.1651 -
186.1652 -    strncpy(NewIcc -> PhysicalFile, FileName, MAX_PATH-1);
186.1653 -    NewIcc -> PhysicalFile[MAX_PATH-1] = 0;
186.1654 -
186.1655 -    NewIcc ->stream = ICCfile;
186.1656 -
186.1657 -    NewIcc ->Read  = FileRead;
186.1658 -    NewIcc ->Seek  = FileSeek;
186.1659 -    NewIcc ->Tell  = FileTell;
186.1660 -    NewIcc ->Close = FileClose;
186.1661 -    NewIcc ->Grow  = FileGrow;
186.1662 -    NewIcc ->Write = NULL;
186.1663 -
186.1664 -    NewIcc ->IsWrite = FALSE;
186.1665 -
186.1666 -
186.1667 -
186.1668 -
186.1669 -    return NewIcc;
186.1670 -}
186.1671 -
186.1672 -
186.1673 -// Creates a profile from memory read placeholder
186.1674 -
186.1675 -LPLCMSICCPROFILE _cmsCreateProfileFromMemPlaceholder(LPVOID MemPtr, DWORD dwSize)
186.1676 -{
186.1677 -
186.1678 -    LPLCMSICCPROFILE NewIcc;
186.1679 -    LPVOID ICCfile = MemoryOpen((LPBYTE) MemPtr, (size_t) dwSize, 'r');
186.1680 -
186.1681 -
186.1682 -    if (ICCfile == NULL) {
186.1683 -
186.1684 -        cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't allocate %ld bytes for profile", dwSize);
186.1685 +        _cmsTagSignature2String(String, sig);
186.1686 +        cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted tag '%s'", String);
186.1687          return NULL;
186.1688      }
186.1689  
186.1690 +    // This is a weird error that may be a symptom of something more serious, the number of
186.1691 +    // stored item is actually less than the number of required elements.
186.1692 +    if (ElemCount < TagDescriptor ->ElemCount) {
186.1693  
186.1694 -    NewIcc = (LPLCMSICCPROFILE) _cmsCreateProfilePlaceholder();
186.1695 -    if (NewIcc == NULL) return NULL;
186.1696 +        char String[5];
186.1697  
186.1698 -    NewIcc -> PhysicalFile[0] = 0;
186.1699 -    NewIcc ->stream = ICCfile;
186.1700 +        _cmsTagSignature2String(String, sig);
186.1701 +        cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "'%s' Inconsistent number of items: expected %d, got %d",
186.1702 +                                                             String, TagDescriptor ->ElemCount, ElemCount);
186.1703 +    }
186.1704  
186.1705 -    NewIcc ->Read  = MemoryRead;
186.1706 -    NewIcc ->Seek  = MemorySeek;
186.1707 -    NewIcc ->Tell  = MemoryTell;
186.1708 -    NewIcc ->Close = MemoryClose;
186.1709 -    NewIcc ->Grow  = MemoryGrow;
186.1710 -    NewIcc ->Write = MemoryWrite;
186.1711  
186.1712 -    NewIcc ->IsWrite = FALSE;
186.1713 -
186.1714 -
186.1715 -    return NewIcc;
186.1716 +    // Return the data
186.1717 +    return Icc -> TagPtrs[n];
186.1718  }
186.1719  
186.1720  
186.1721 -// Turn a placeholder into file writter
186.1722 +// Get true type of data
186.1723 +cmsTagTypeSignature _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig)
186.1724 +{
186.1725 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
186.1726 +    cmsTagTypeHandler* TypeHandler;
186.1727 +    int n;
186.1728  
186.1729 -void _cmsSetSaveToDisk(LPLCMSICCPROFILE Icc, const char* FileName)
186.1730 +    // Search for given tag in ICC profile directory
186.1731 +    n = _cmsSearchTag(Icc, sig, TRUE);
186.1732 +    if (n < 0) return (cmsTagTypeSignature) 0;                // Not found, return NULL
186.1733 +
186.1734 +    // Get the handler. The true type is there
186.1735 +    TypeHandler =  Icc -> TagTypeHandlers[n];
186.1736 +    return TypeHandler ->Signature;
186.1737 +}
186.1738 +
186.1739 +
186.1740 +// Write a single tag. This just keeps track of the tak into a list of "to be written". If the tag is already
186.1741 +// in that list, the previous version is deleted.
186.1742 +cmsBool CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data)
186.1743  {
186.1744 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
186.1745 +    cmsTagTypeHandler* TypeHandler = NULL;
186.1746 +    cmsTagDescriptor* TagDescriptor = NULL;
186.1747 +    cmsTagTypeSignature Type;
186.1748 +    int i;
186.1749 +    cmsFloat64Number Version;
186.1750  
186.1751 -    if (FileName == NULL) {
186.1752  
186.1753 -          Icc ->stream = NULL;
186.1754 +    if (data == NULL) {
186.1755 +
186.1756 +         cmsSignalError(cmsGetProfileContextID(hProfile), cmsERROR_NULL, "couldn't wite NULL to tag");
186.1757 +         return FALSE;
186.1758 +    }
186.1759 +
186.1760 +    i = _cmsSearchTag(Icc, sig, FALSE);
186.1761 +    if (i >=0) {
186.1762 +
186.1763 +        if (Icc -> TagPtrs[i] != NULL) {
186.1764 +
186.1765 +            // Already exists. Free previous version
186.1766 +            if (Icc ->TagSaveAsRaw[i]) {
186.1767 +                _cmsFree(Icc ->ContextID, Icc ->TagPtrs[i]);
186.1768 +            }
186.1769 +            else {
186.1770 +                TypeHandler = Icc ->TagTypeHandlers[i];
186.1771 +                TypeHandler->FreePtr(TypeHandler, Icc -> TagPtrs[i]);
186.1772 +            }
186.1773 +        }
186.1774 +    }
186.1775 +    else  {
186.1776 +        // New one
186.1777 +        i = Icc -> TagCount;
186.1778 +
186.1779 +        if (i >= MAX_TABLE_TAG) {
186.1780 +            cmsSignalError(Icc ->ContextID, cmsERROR_RANGE, "Too many tags (%d)", MAX_TABLE_TAG);
186.1781 +            return FALSE;
186.1782 +        }
186.1783 +
186.1784 +        Icc -> TagCount++;
186.1785 +    }
186.1786 +
186.1787 +    // This is not raw
186.1788 +    Icc ->TagSaveAsRaw[i] = FALSE;
186.1789 +
186.1790 +    // This is not a link
186.1791 +    Icc ->TagLinked[i] = (cmsTagSignature) 0;
186.1792 +
186.1793 +    // Get information about the TAG.
186.1794 +    TagDescriptor = _cmsGetTagDescriptor(sig);
186.1795 +    if (TagDescriptor == NULL){
186.1796 +         cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag '%x'", sig);
186.1797 +        return FALSE;
186.1798 +    }
186.1799 +
186.1800 +
186.1801 +    // Now we need to know which type to use. It depends on the version.
186.1802 +    Version = cmsGetProfileVersion(hProfile);
186.1803 +    if (TagDescriptor ->DecideType != NULL) {
186.1804 +
186.1805 +        // Let the tag descriptor to decide the type base on depending on
186.1806 +        // the data. This is useful for example on parametric curves, where
186.1807 +        // curves specified by a table cannot be saved as parametric and needs
186.1808 +        // to be revented to single v2-curves, even on v4 profiles.
186.1809 +
186.1810 +        Type = TagDescriptor ->DecideType(Version, data);
186.1811      }
186.1812      else {
186.1813  
186.1814 -          Icc ->stream = fopen(FileName, "wb");
186.1815 -          if (Icc ->stream == NULL)
186.1816 -                cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't write to file '%s'", FileName);
186.1817 +        Type = TagDescriptor ->SupportedTypes[0];
186.1818      }
186.1819  
186.1820 -    Icc ->Write = FileWrite;   // Save to disk
186.1821 -    Icc ->Close = FileClose;
186.1822 -}
186.1823 -
186.1824 -
186.1825 -
186.1826 -// Turn a  placeholder into memory writter
186.1827 -
186.1828 -void _cmsSetSaveToMemory(LPLCMSICCPROFILE Icc, LPVOID MemPtr, size_t dwSize)
186.1829 -{
186.1830 -
186.1831 -    if (MemPtr == NULL) {
186.1832 -
186.1833 -        Icc ->stream = NULL;
186.1834 -    }
186.1835 -    else {
186.1836 -
186.1837 -        Icc ->stream = (FILEMEM*) MemoryOpen((LPBYTE) MemPtr, dwSize, 'w');
186.1838 -        if (Icc ->stream == NULL)
186.1839 -                cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't write to memory");
186.1840 +    // Does the tag support this type?
186.1841 +    if (!IsTypeSupported(TagDescriptor, Type)) {
186.1842 +        cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%x' for tag '%x'", Type, sig);
186.1843 +        return FALSE;
186.1844      }
186.1845  
186.1846 -    Icc ->Write = MemoryWrite;
186.1847 -    Icc ->Close = MemoryClose;
186.1848 -}
186.1849 +    // Does we have a handler for this type?
186.1850 +    TypeHandler =  _cmsGetTagTypeHandler(Type);
186.1851 +    if (TypeHandler == NULL) {
186.1852 +        cmsSignalError(Icc ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported type '%x' for tag '%x'", Type, sig);
186.1853 +        return FALSE;           // Should never happen
186.1854 +    }
186.1855  
186.1856 +    // Fill fields on icc structure
186.1857 +    Icc ->TagTypeHandlers[i]  = TypeHandler;
186.1858 +    Icc ->TagNames[i]         = sig;
186.1859 +    Icc ->TagSizes[i]         = 0;
186.1860 +    Icc ->TagOffsets[i]       = 0;
186.1861 +    Icc ->TagPtrs[i]          = TypeHandler ->DupPtr(TypeHandler, data, TagDescriptor ->ElemCount);
186.1862  
186.1863 -// ----------------------------------------------------------------------- Set/Get several struct members
186.1864 +    if (Icc ->TagPtrs[i] == NULL)  {
186.1865  
186.1866 +        TypeHandler ->DupPtr(TypeHandler, data, TagDescriptor ->ElemCount);
186.1867 +        cmsSignalError(Icc ->ContextID, cmsERROR_CORRUPTION_DETECTED, "Malformed struct in type '%x' for tag '%x'", Type, sig);
186.1868  
186.1869 +        return FALSE;
186.1870 +    }
186.1871  
186.1872 -
186.1873 -LCMSBOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
186.1874 -{
186.1875 -     LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) hProfile;
186.1876 -     *Dest = Icc -> MediaWhitePoint;
186.1877 -     return TRUE;
186.1878 -}
186.1879 -
186.1880 -
186.1881 -LCMSBOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
186.1882 -{
186.1883 -      LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) hProfile;
186.1884 -      *Dest = Icc -> MediaBlackPoint;
186.1885 -      return TRUE;
186.1886 -}
186.1887 -
186.1888 -LCMSBOOL  LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
186.1889 -{
186.1890 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1891 -       *Dest = Icc -> Illuminant;
186.1892 -       return TRUE;
186.1893 -}
186.1894 -
186.1895 -int LCMSEXPORT cmsTakeRenderingIntent(cmsHPROFILE hProfile)
186.1896 -{
186.1897 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1898 -       return (int) Icc -> RenderingIntent;
186.1899 -}
186.1900 -
186.1901 -void LCMSEXPORT cmsSetRenderingIntent(cmsHPROFILE hProfile, int RenderingIntent)
186.1902 -{
186.1903 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1904 -    Icc -> RenderingIntent = (icRenderingIntent) RenderingIntent;
186.1905 -}
186.1906 -
186.1907 -
186.1908 -DWORD LCMSEXPORT cmsTakeHeaderFlags(cmsHPROFILE hProfile)
186.1909 -{
186.1910 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1911 -       return (DWORD) Icc -> flags;
186.1912 -}
186.1913 -
186.1914 -void LCMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, DWORD Flags)
186.1915 -{
186.1916 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1917 -    Icc -> flags = (icUInt32Number) Flags;
186.1918 -}
186.1919 -
186.1920 -DWORD LCMSEXPORT cmsTakeHeaderAttributes(cmsHPROFILE hProfile)
186.1921 -{
186.1922 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1923 -       return (DWORD) Icc -> attributes;
186.1924 -}
186.1925 -
186.1926 -void LCMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, DWORD Flags)
186.1927 -{
186.1928 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1929 -    Icc -> attributes = (icUInt32Number) Flags;
186.1930 -}
186.1931 -
186.1932 -
186.1933 -const BYTE* LCMSEXPORT cmsTakeProfileID(cmsHPROFILE hProfile)
186.1934 -{
186.1935 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1936 -    return Icc ->ProfileID;
186.1937 -}
186.1938 -
186.1939 -void LCMSEXPORT cmsSetProfileID(cmsHPROFILE hProfile, LPBYTE ProfileID)
186.1940 -{
186.1941 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1942 -    CopyMemory(Icc -> ProfileID, ProfileID, 16);
186.1943 -}
186.1944 -
186.1945 -
186.1946 -LCMSBOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
186.1947 -{
186.1948 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.1949 -    CopyMemory(Dest, &Icc ->Created, sizeof(struct tm));
186.1950      return TRUE;
186.1951  }
186.1952  
186.1953 +// Read and write raw data. The only way those function would work and keep consistence with normal read and write
186.1954 +// is to do an additional step of serialization. That means, readRaw would issue a normal read and then convert the obtained
186.1955 +// data to raw bytes by using the "write" serialization logic. And vice-versa. I know this may end in situations where
186.1956 +// raw data written does not exactly correspond with the raw data proposed to cmsWriteRaw data, but this approach allows
186.1957 +// to write a tag as raw data and the read it as handled.
186.1958  
186.1959 -icColorSpaceSignature LCMSEXPORT cmsGetPCS(cmsHPROFILE hProfile)
186.1960 +cmsInt32Number CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* data, cmsUInt32Number BufferSize)
186.1961  {
186.1962 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.1963 -       return Icc -> PCS;
186.1964 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
186.1965 +    void *Object;
186.1966 +    int i;
186.1967 +    cmsIOHANDLER* MemIO;
186.1968 +    cmsTagTypeHandler* TypeHandler = NULL;
186.1969 +    cmsTagDescriptor* TagDescriptor = NULL;
186.1970 +    cmsUInt32Number rc;
186.1971 +    cmsUInt32Number Offset, TagSize;
186.1972 +
186.1973 +    // Search for given tag in ICC profile directory
186.1974 +    i = _cmsSearchTag(Icc, sig, TRUE);
186.1975 +    if (i < 0) return 0;                 // Not found, return 0
186.1976 +
186.1977 +    // It is already read?
186.1978 +    if (Icc -> TagPtrs[i] == NULL) {
186.1979 +
186.1980 +        // No yet, get original position
186.1981 +        Offset   = Icc ->TagOffsets[i];
186.1982 +        TagSize  = Icc ->TagSizes[i];
186.1983 +
186.1984 +
186.1985 +        // read the data directly, don't keep copy
186.1986 +        if (data != NULL) {
186.1987 +
186.1988 +            if (BufferSize < TagSize)
186.1989 +                 TagSize = BufferSize;
186.1990 +
186.1991 +            if (!Icc ->IOhandler ->Seek(Icc ->IOhandler, Offset)) return 0;
186.1992 +            if (!Icc ->IOhandler ->Read(Icc ->IOhandler, data, 1, TagSize)) return 0;
186.1993 +        }
186.1994 +
186.1995 +        return Icc ->TagSizes[i];
186.1996 +    }
186.1997 +
186.1998 +    // The data has been already read, or written. But wait!, maybe the user choosed to save as
186.1999 +    // raw data. In this case, return the raw data directly
186.2000 +    if (Icc ->TagSaveAsRaw[i]) {
186.2001 +
186.2002 +        if (data != NULL)  {
186.2003 +
186.2004 +            TagSize  = Icc ->TagSizes[i];
186.2005 +            if (BufferSize < TagSize)
186.2006 +                       TagSize = BufferSize;
186.2007 +
186.2008 +            memmove(data, Icc ->TagPtrs[i], TagSize);
186.2009 +        }
186.2010 +
186.2011 +        return Icc ->TagSizes[i];
186.2012 +    }
186.2013 +
186.2014 +    // Already readed, or previously set by cmsWriteTag(). We need to serialize that
186.2015 +    // data to raw in order to maintain consistency.
186.2016 +    Object = cmsReadTag(hProfile, sig);
186.2017 +    if (Object == NULL) return 0;
186.2018 +
186.2019 +    // Now we need to serialize to a memory block: just use a memory iohandler
186.2020 +
186.2021 +    if (data == NULL) {
186.2022 +        MemIO = cmsOpenIOhandlerFromNULL(cmsGetProfileContextID(hProfile));
186.2023 +    } else{
186.2024 +          MemIO = cmsOpenIOhandlerFromMem(cmsGetProfileContextID(hProfile), data, BufferSize, "w");
186.2025 +    }
186.2026 +    if (MemIO == NULL) return 0;
186.2027 +
186.2028 +    // Obtain type handling for the tag
186.2029 +    TypeHandler = Icc ->TagTypeHandlers[i];
186.2030 +    TagDescriptor = _cmsGetTagDescriptor(sig);
186.2031 +
186.2032 +    // Serialize
186.2033 +    if (!TypeHandler ->WritePtr(TypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) return 0;
186.2034 +
186.2035 +    // Get Size and close
186.2036 +    rc = MemIO ->Tell(MemIO);
186.2037 +    cmsCloseIOhandler(MemIO);      // Ignore return code this time
186.2038 +
186.2039 +    return rc;
186.2040  }
186.2041  
186.2042 +// Similar to the anterior. This function allows to write directly to the ICC profile any data, without
186.2043 +// checking anything. As a rule, mixing Raw with cooked doesn't work, so writting a tag as raw and then reading
186.2044 +// it as cooked without serializing does result into an error. If that is wha you want, you will need to dump
186.2045 +// the profile to memry or disk and then reopen it.
186.2046 +cmsBool CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size)
186.2047 +{
186.2048 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
186.2049 +    int i;
186.2050  
186.2051 -void LCMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, icColorSpaceSignature pcs)
186.2052 -{
186.2053 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.2054 -       Icc -> PCS = pcs;
186.2055 -}
186.2056 +    if (!_cmsNewTag(Icc, sig, &i)) return FALSE;
186.2057  
186.2058 -icColorSpaceSignature LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile)
186.2059 -{
186.2060 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.2061 -       return Icc -> ColorSpace;
186.2062 -}
186.2063 +    // Mark the tag as being written as RAW
186.2064 +    Icc ->TagSaveAsRaw[i] = TRUE;
186.2065 +    Icc ->TagNames[i]     = sig;
186.2066 +    Icc ->TagLinked[i]    = (cmsTagSignature) 0;
186.2067  
186.2068 -void LCMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, icColorSpaceSignature sig)
186.2069 -{
186.2070 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.2071 -       Icc -> ColorSpace = sig;
186.2072 -}
186.2073 +    // Keep a copy of the block
186.2074 +    Icc ->TagPtrs[i]  = _cmsDupMem(Icc ->ContextID, data, Size);
186.2075 +    Icc ->TagSizes[i] = Size;
186.2076  
186.2077 -icProfileClassSignature LCMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile)
186.2078 -{
186.2079 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.2080 -       return Icc -> DeviceClass;
186.2081 -}
186.2082 -
186.2083 -DWORD LCMSEXPORT cmsGetProfileICCversion(cmsHPROFILE hProfile)
186.2084 -{
186.2085 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.2086 -       return (DWORD) Icc -> Version;
186.2087 -}
186.2088 -
186.2089 -void LCMSEXPORT cmsSetProfileICCversion(cmsHPROFILE hProfile, DWORD Version)
186.2090 -{
186.2091 -   LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.2092 -   Icc -> Version = Version;
186.2093 -}
186.2094 -
186.2095 -
186.2096 -void LCMSEXPORT cmsSetDeviceClass(cmsHPROFILE hProfile, icProfileClassSignature sig)
186.2097 -{
186.2098 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) hProfile;
186.2099 -       Icc -> DeviceClass = sig;
186.2100 -}
186.2101 -
186.2102 -
186.2103 -// --------------------------------------------------------------------------------------------------------------
186.2104 -
186.2105 -
186.2106 -static
186.2107 -int SizeOfGammaTab(LPGAMMATABLE In)
186.2108 -{
186.2109 -       return sizeof(GAMMATABLE) + (In -> nEntries - 1)*sizeof(WORD);
186.2110 -}
186.2111 -
186.2112 -
186.2113 -// Creates a phantom tag holding a memory block
186.2114 -
186.2115 -static
186.2116 -LPVOID DupBlock(LPLCMSICCPROFILE Icc, LPVOID Block, size_t size)
186.2117 -{
186.2118 -    if (Block != NULL && size > 0)
186.2119 -        return _cmsInitTag(Icc, (icTagSignature) 0, size, Block);
186.2120 -    else
186.2121 -        return NULL;
186.2122 -
186.2123 -}
186.2124 -
186.2125 -// This is tricky, since LUT structs does have pointers
186.2126 -
186.2127 -LCMSBOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut)
186.2128 -{
186.2129 -       LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2130 -       LPLUT Orig, Stored;
186.2131 -       unsigned int i;
186.2132 -
186.2133 -       // The struct itself
186.2134 -
186.2135 -       Orig   = (LPLUT) lut;
186.2136 -       Stored = (LPLUT) _cmsInitTag(Icc, (icTagSignature) sig, sizeof(LUT), lut);
186.2137 -
186.2138 -       // dup' the memory blocks
186.2139 -       for (i=0; i < Orig ->InputChan; i++)
186.2140 -            Stored -> L1[i] = (LPWORD) DupBlock(Icc, (LPWORD) Orig ->L1[i],
186.2141 -                                            sizeof(WORD) * Orig ->In16params.nSamples);
186.2142 -
186.2143 -       for (i=0; i < Orig ->OutputChan; i++)
186.2144 -            Stored -> L2[i] = (LPWORD) DupBlock(Icc, (LPWORD) Orig ->L2[i],
186.2145 -                                            sizeof(WORD) * Orig ->Out16params.nSamples);
186.2146 -
186.2147 -       Stored -> T     = (LPWORD) DupBlock(Icc, (LPWORD) Orig ->T, Orig -> Tsize);
186.2148 -
186.2149 -       // Zero any additional pointer
186.2150 -       Stored ->CLut16params.p8 = NULL;
186.2151 -       return TRUE;
186.2152 -}
186.2153 -
186.2154 -
186.2155 -LCMSBOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ)
186.2156 -{
186.2157 -       LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2158 -
186.2159 -       _cmsInitTag(Icc, sig, sizeof(cmsCIEXYZ), XYZ);
186.2160 -       return TRUE;
186.2161 -}
186.2162 -
186.2163 -
186.2164 -LCMSBOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text)
186.2165 -{
186.2166 -       LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2167 -
186.2168 -       _cmsInitTag(Icc, sig, strlen(Text)+1, (LPVOID) Text);
186.2169 -       return TRUE;
186.2170 -}
186.2171 -
186.2172 -LCMSBOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction)
186.2173 -{
186.2174 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2175 -
186.2176 -    _cmsInitTag(Icc, sig, SizeOfGammaTab(TransferFunction), TransferFunction);
186.2177      return TRUE;
186.2178  }
186.2179  
186.2180 +// Using this function you can collapse several tag entries to the same block in the profile
186.2181 +cmsBool CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSignature dest)
186.2182 +{
186.2183 +     _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
186.2184 +    int i;
186.2185  
186.2186 -LCMSBOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm)
186.2187 -{
186.2188 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2189 +    if (!_cmsNewTag(Icc, sig, &i)) return FALSE;
186.2190  
186.2191 -    _cmsInitTag(Icc, sig, sizeof(cmsCIExyYTRIPLE), Chrm);
186.2192 +    // Keep necessary information
186.2193 +    Icc ->TagSaveAsRaw[i] = FALSE;
186.2194 +    Icc ->TagNames[i]     = sig;
186.2195 +    Icc ->TagLinked[i]    = dest;
186.2196 +
186.2197 +    Icc ->TagPtrs[i]    = NULL;
186.2198 +    Icc ->TagSizes[i]   = 0;
186.2199 +    Icc ->TagOffsets[i] = 0;
186.2200 +
186.2201      return TRUE;
186.2202  }
186.2203 -
186.2204 -
186.2205 -LCMSBOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ pseq)
186.2206 -{
186.2207 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2208 -
186.2209 -    _cmsInitTag(Icc, sig, sizeof(int) + pseq -> n * sizeof(cmsPSEQDESC), pseq);
186.2210 -    return TRUE;
186.2211 -
186.2212 -}
186.2213 -
186.2214 -
186.2215 -LCMSBOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
186.2216 -{
186.2217 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2218 -
186.2219 -    _cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc);
186.2220 -    return TRUE;
186.2221 -}
186.2222 -
186.2223 -
186.2224 -LCMSBOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime)
186.2225 -{
186.2226 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2227 -
186.2228 -    _cmsInitTag(Icc, sig, sizeof(struct tm), DateTime);
186.2229 -    return TRUE;
186.2230 -}
186.2231 -
186.2232 -
186.2233 -LCMSBOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
186.2234 -{
186.2235 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2236 -
186.2237 -    _cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc);
186.2238 -    return TRUE;
186.2239 -}
186.2240 -
186.2241 -
186.2242 -LCMSBOOL LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat)
186.2243 -{
186.2244 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
186.2245 -
186.2246 -    _cmsInitTag(Icc, sig, 3*sizeof(cmsCIEXYZ), mat);
186.2247 -    return TRUE;
186.2248 -
186.2249 -}
186.2250 -
186.2251 -
   187.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsio1.c	Thu Sep 23 17:33:40 2010 -0700
   187.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsio1.c	Fri Sep 24 16:41:32 2010 -0700
   187.3 @@ -27,9 +27,10 @@
   187.4  // However, the following notice accompanied the original version of this
   187.5  // file:
   187.6  //
   187.7 +//---------------------------------------------------------------------------------
   187.8  //
   187.9 -//  Little cms
  187.10 -//  Copyright (C) 1998-2007 Marti Maria
  187.11 +//  Little Color Management System
  187.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  187.13  //
  187.14  // Permission is hereby granted, free of charge, to any person obtaining
  187.15  // a copy of this software and associated documentation files (the "Software"),
  187.16 @@ -48,1860 +49,108 @@
  187.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  187.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  187.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  187.20 -
  187.21 -// ICC profile serialization
  187.22 -
  187.23 -
  187.24 -#include "lcms.h"
  187.25 -
  187.26 -// ----------------------------------------------------------------- Tag Serialization
  187.27 -
  187.28 -// Alignment of ICC file format uses 4 bytes DWORD
  187.29 -
  187.30 -#define ALIGNLONG(x) (((x)+3) & ~(3))         // Aligns to DWORD boundary
  187.31 -
  187.32 -
  187.33 -static int GlobalLanguageCode;   // Language & country descriptors, for ICC 4.0 support
  187.34 -static int GlobalCountryCode;
  187.35 -
  187.36 -
  187.37 -#ifdef __BEOS__
  187.38 -#       define USE_CUSTOM_SWAB  1
  187.39 -#endif
  187.40 -
  187.41 -
  187.42 -#ifdef USE_CUSTOM_SWAB
  187.43 -
  187.44 -// Replacement to swab function, thanks to YNOP
  187.45 -// for providing the BeOS port
  187.46  //
  187.47 -// from: @(#)swab.c       5.10 (Berkeley)  3/6/91
  187.48 -
  187.49 -static
  187.50 -void xswab(const void *from, void *to, size_t len)
  187.51 -{
  187.52 -         register unsigned long temp;
  187.53 -         register int n;
  187.54 -         register char *fp, *tp;
  187.55 -
  187.56 -         n = (len >> 1) + 1;
  187.57 -         fp = (char *)from;
  187.58 -         tp = (char *)to;
  187.59 -#define STEP    temp = *fp++,*tp++ = *fp++,*tp++ = temp
  187.60 -         /* round to multiple of 8 */
  187.61 -         while ((--n) & 07)
  187.62 -                 STEP;
  187.63 -         n >>= 3;
  187.64 -         while (--n >= 0) {
  187.65 -
  187.66 -                 STEP; STEP; STEP; STEP;
  187.67 -                 STEP; STEP; STEP; STEP;
  187.68 -         }
  187.69 -#undef STEP
  187.70 -}
  187.71 -#else
  187.72 -#define xswab swab
  187.73 -#endif
  187.74 -
  187.75 -
  187.76 -//
  187.77 -//      Little-Endian to Big-Endian
  187.78 +//---------------------------------------------------------------------------------
  187.79  //
  187.80  
  187.81 -#ifdef USE_BIG_ENDIAN
  187.82 -#define AdjustEndianess16(a)
  187.83 -#define AdjustEndianess32(a)
  187.84 -#define AdjustEndianessArray16(a, b)
  187.85 -#else
  187.86 +#include "lcms2_internal.h"
  187.87  
  187.88 -static
  187.89 -void AdjustEndianess16(LPBYTE pByte)
  187.90 +// Read tags using low-level functions, provides necessary glue code to adapt versions, etc.
  187.91 +
  187.92 +// LUT tags
  187.93 +static const cmsTagSignature Device2PCS16[]   =  {cmsSigAToB0Tag,     // Perceptual
  187.94 +                                                  cmsSigAToB1Tag,     // Relative colorimetric
  187.95 +                                                  cmsSigAToB2Tag,     // Saturation
  187.96 +                                                  cmsSigAToB1Tag };   // Absolute colorimetric
  187.97 +
  187.98 +static const cmsTagSignature Device2PCSFloat[] = {cmsSigDToB0Tag,     // Perceptual
  187.99 +                                                  cmsSigDToB1Tag,     // Relative colorimetric
 187.100 +                                                  cmsSigDToB2Tag,     // Saturation
 187.101 +                                                  cmsSigDToB3Tag };   // Absolute colorimetric
 187.102 +
 187.103 +static const cmsTagSignature PCS2Device16[]    = {cmsSigBToA0Tag,     // Perceptual
 187.104 +                                                  cmsSigBToA1Tag,     // Relative colorimetric
 187.105 +                                                  cmsSigBToA2Tag,     // Saturation
 187.106 +                                                  cmsSigBToA1Tag };   // Absolute colorimetric
 187.107 +
 187.108 +static const cmsTagSignature PCS2DeviceFloat[] = {cmsSigBToD0Tag,     // Perceptual
 187.109 +                                                  cmsSigBToD1Tag,     // Relative colorimetric
 187.110 +                                                  cmsSigBToD2Tag,     // Saturation
 187.111 +                                                  cmsSigBToD3Tag };   // Absolute colorimetric
 187.112 +
 187.113 +
 187.114 +// Factors to convert from 1.15 fixed point to 0..1.0 range and vice-versa
 187.115 +#define InpAdj   (1.0/MAX_ENCODEABLE_XYZ)     // (65536.0/(65535.0*2.0))
 187.116 +#define OutpAdj  (MAX_ENCODEABLE_XYZ)         // ((2.0*65535.0)/65536.0)
 187.117 +
 187.118 +// Several resources for gray conversions.
 187.119 +static const cmsFloat64Number GrayInputMatrix[] = { (InpAdj*cmsD50X),  (InpAdj*cmsD50Y),  (InpAdj*cmsD50Z) };
 187.120 +static const cmsFloat64Number OneToThreeInputMatrix[] = { 1, 1, 1 };
 187.121 +static const cmsFloat64Number PickYMatrix[] = { 0, (OutpAdj*cmsD50Y), 0 };
 187.122 +static const cmsFloat64Number PickLstarMatrix[] = { 1, 0, 0 };
 187.123 +
 187.124 +// Get a media white point fixing some issues found in certain old profiles
 187.125 +cmsBool  _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile)
 187.126  {
 187.127 -       BYTE tmp;
 187.128 +    cmsCIEXYZ* Tag;
 187.129  
 187.130 -       tmp = pByte[0];
 187.131 -       pByte[0] = pByte[1];
 187.132 -       pByte[1] = tmp;
 187.133 -}
 187.134 +    _cmsAssert(Dest != NULL);
 187.135  
 187.136 -static
 187.137 -void AdjustEndianess32(LPBYTE pByte)
 187.138 -{
 187.139 -        BYTE temp1;
 187.140 -        BYTE temp2;
 187.141 +    Tag = (cmsCIEXYZ*) cmsReadTag(hProfile, cmsSigMediaWhitePointTag);
 187.142  
 187.143 -        temp1 = *pByte++;
 187.144 -        temp2 = *pByte++;
 187.145 -        *(pByte-1) = *pByte;
 187.146 -        *pByte++ = temp2;
 187.147 -        *(pByte-3) = *pByte;
 187.148 -        *pByte = temp1;
 187.149 -}
 187.150 -
 187.151 -
 187.152 -// swap bytes in a array of words
 187.153 -
 187.154 -static
 187.155 -void AdjustEndianessArray16(LPWORD p, size_t num_words)
 187.156 -{
 187.157 -       xswab((char*) p, (char*)p, (int) num_words * sizeof(WORD));
 187.158 -}
 187.159 -
 187.160 -#endif
 187.161 -
 187.162 -
 187.163 -// Transports to properly encoded values - note that icc profiles does use
 187.164 -// big endian notation.
 187.165 -
 187.166 -static
 187.167 -icInt32Number TransportValue32(icInt32Number Value)
 187.168 -{
 187.169 -       icInt32Number Temp = Value;
 187.170 -
 187.171 -       AdjustEndianess32((LPBYTE) &Temp);
 187.172 -       return Temp;
 187.173 -}
 187.174 -
 187.175 -static
 187.176 -WORD TransportValue16(WORD Value)
 187.177 -{
 187.178 -       WORD Temp = Value;
 187.179 -
 187.180 -       AdjustEndianess16((LPBYTE) &Temp);
 187.181 -       return Temp;
 187.182 -}
 187.183 -
 187.184 -
 187.185 -// from Fixed point 8.8 to double
 187.186 -
 187.187 -static
 187.188 -double Convert8Fixed8(WORD fixed8)
 187.189 -{
 187.190 -       BYTE msb, lsb;
 187.191 -
 187.192 -       lsb = (BYTE) (fixed8 & 0xff);
 187.193 -       msb = (BYTE) (((WORD) fixed8 >> 8) & 0xff);
 187.194 -
 187.195 -       return (double) ((double) msb + ((double) lsb / 256.0));
 187.196 -}
 187.197 -
 187.198 -
 187.199 -// from Fixed point 15.16 to double
 187.200 -static
 187.201 -double Convert15Fixed16(icS15Fixed16Number fix32)
 187.202 -{
 187.203 -    double floater, sign, mid, hack;
 187.204 -    int Whole, FracPart;
 187.205 -
 187.206 -
 187.207 -    AdjustEndianess32((LPBYTE) &fix32);
 187.208 -
 187.209 -    sign  = (fix32 < 0 ? -1 : 1);
 187.210 -    fix32 = abs(fix32);
 187.211 -
 187.212 -    Whole = LOWORD(fix32 >> 16);
 187.213 -    FracPart  = LOWORD(fix32 & 0x0000ffffL);
 187.214 -
 187.215 -    hack    = 65536.0;
 187.216 -    mid     = (double) FracPart / hack;
 187.217 -    floater = (double) Whole + mid;
 187.218 -
 187.219 -    return sign * floater;
 187.220 -}
 187.221 -
 187.222 -
 187.223 -// Auxiliar-- read base and return type
 187.224 -
 187.225 -static
 187.226 -icTagTypeSignature ReadBase(LPLCMSICCPROFILE Icc)
 187.227 -{
 187.228 -    icTagBase Base;
 187.229 -
 187.230 -    if (Icc -> Read(&Base, sizeof(icTagBase), 1, Icc) != 1)
 187.231 -                return (icTagTypeSignature) 0;
 187.232 -    AdjustEndianess32((LPBYTE) &Base.sig);
 187.233 -
 187.234 -    return Base.sig;
 187.235 -}
 187.236 -
 187.237 -
 187.238 -static
 187.239 -void DecodeDateTimeNumber(const icDateTimeNumber *Source, struct tm *Dest)
 187.240 -{
 187.241 -    Dest->tm_sec   = TransportValue16(Source->seconds);
 187.242 -    Dest->tm_min   = TransportValue16(Source->minutes);
 187.243 -    Dest->tm_hour  = TransportValue16(Source->hours);
 187.244 -    Dest->tm_mday  = TransportValue16(Source->day);
 187.245 -    Dest->tm_mon   = TransportValue16(Source->month) - 1;
 187.246 -    Dest->tm_year  = TransportValue16(Source->year) - 1900;
 187.247 -    Dest->tm_wday  = -1;
 187.248 -    Dest->tm_yday  = -1;
 187.249 -    Dest->tm_isdst = 0;
 187.250 -}
 187.251 -
 187.252 -static
 187.253 -void EncodeDateTimeNumber(icDateTimeNumber *Dest, const struct tm *Source)
 187.254 -{
 187.255 -    Dest->seconds = TransportValue16((WORD) Source->tm_sec);
 187.256 -    Dest->minutes = TransportValue16((WORD) Source->tm_min);
 187.257 -    Dest->hours   = TransportValue16((WORD) Source->tm_hour);
 187.258 -    Dest->day     = TransportValue16((WORD) Source->tm_mday);
 187.259 -    Dest->month   = TransportValue16((WORD) (Source->tm_mon + 1));
 187.260 -    Dest->year    = TransportValue16((WORD) (Source->tm_year + 1900));
 187.261 -}
 187.262 -
 187.263 -
 187.264 -// Jun-21-2000: Some profiles (those that comes with W2K) comes
 187.265 -// with the media white (media black?) x 100. Add a sanity check
 187.266 -
 187.267 -static
 187.268 -void NormalizeXYZ(LPcmsCIEXYZ Dest)
 187.269 -{
 187.270 -    while (Dest -> X > 2. &&
 187.271 -           Dest -> Y > 2. &&
 187.272 -           Dest -> Z > 2.) {
 187.273 -
 187.274 -               Dest -> X /= 10.;
 187.275 -               Dest -> Y /= 10.;
 187.276 -               Dest -> Z /= 10.;
 187.277 -       }
 187.278 -}
 187.279 -
 187.280 -// Evaluates a XYZ tristimulous across chromatic adaptation matrix
 187.281 -
 187.282 -static
 187.283 -void EvalCHRM(LPcmsCIEXYZ Dest, LPMAT3 Chrm, LPcmsCIEXYZ Src)
 187.284 -{
 187.285 -    VEC3 d, s;
 187.286 -
 187.287 -    s.n[VX] = Src -> X;
 187.288 -    s.n[VY] = Src -> Y;
 187.289 -    s.n[VZ] = Src -> Z;
 187.290 -
 187.291 -    MAT3eval(&d, Chrm, &s);
 187.292 -
 187.293 -    Dest ->X = d.n[VX];
 187.294 -    Dest ->Y = d.n[VY];
 187.295 -    Dest ->Z = d.n[VZ];
 187.296 -
 187.297 -}
 187.298 -
 187.299 -
 187.300 -// Read profile header and validate it
 187.301 -
 187.302 -static
 187.303 -LPLCMSICCPROFILE ReadHeader(LPLCMSICCPROFILE Icc, LCMSBOOL lIsFromMemory)
 187.304 -{
 187.305 -     icTag Tag;
 187.306 -     icHeader Header;
 187.307 -     icInt32Number TagCount, i;
 187.308 -     icUInt32Number extent;
 187.309 -
 187.310 -       if (Icc -> Read(&Header, sizeof(icHeader), 1, Icc) != 1)
 187.311 -                      goto ErrorCleanup;
 187.312 -
 187.313 -       // Convert endian
 187.314 -
 187.315 -       AdjustEndianess32((LPBYTE) &Header.size);
 187.316 -       AdjustEndianess32((LPBYTE) &Header.cmmId);
 187.317 -       AdjustEndianess32((LPBYTE) &Header.version);
 187.318 -       AdjustEndianess32((LPBYTE) &Header.deviceClass);
 187.319 -       AdjustEndianess32((LPBYTE) &Header.colorSpace);
 187.320 -       AdjustEndianess32((LPBYTE) &Header.pcs);
 187.321 -       AdjustEndianess32((LPBYTE) &Header.magic);
 187.322 -       AdjustEndianess32((LPBYTE) &Header.flags);
 187.323 -       AdjustEndianess32((LPBYTE) &Header.attributes[0]);
 187.324 -       AdjustEndianess32((LPBYTE) &Header.renderingIntent);
 187.325 -
 187.326 -       // Validate it
 187.327 -
 187.328 -       if (Header.magic != icMagicNumber) goto ErrorCleanup;
 187.329 -
 187.330 -       if (Icc ->Read(&TagCount, sizeof(icInt32Number), 1, Icc) != 1)
 187.331 -                     goto ErrorCleanup;
 187.332 -
 187.333 -       AdjustEndianess32((LPBYTE) &TagCount);
 187.334 -
 187.335 -       Icc -> DeviceClass     = Header.deviceClass;
 187.336 -       Icc -> ColorSpace      = Header.colorSpace;
 187.337 -       Icc -> PCS             = Header.pcs;
 187.338 -       Icc -> RenderingIntent = (icRenderingIntent) Header.renderingIntent;
 187.339 -       Icc -> flags           = Header.flags;
 187.340 -       Icc -> attributes      = Header.attributes[0];
 187.341 -       Icc -> Illuminant.X    = Convert15Fixed16(Header.illuminant.X);
 187.342 -       Icc -> Illuminant.Y    = Convert15Fixed16(Header.illuminant.Y);
 187.343 -       Icc -> Illuminant.Z    = Convert15Fixed16(Header.illuminant.Z);
 187.344 -       Icc -> Version         = Header.version;
 187.345 -
 187.346 -       // Get creation date/time
 187.347 -
 187.348 -       DecodeDateTimeNumber(&Header.date, &Icc ->Created);
 187.349 -
 187.350 -       // Fix illuminant, some profiles are broken in this field!
 187.351 -
 187.352 -       Icc ->Illuminant = *cmsD50_XYZ();
 187.353 -
 187.354 -       // The profile ID are 16 raw bytes
 187.355 -
 187.356 -       CopyMemory(Icc ->ProfileID, Header.reserved, 16);
 187.357 -
 187.358 -       // Get rid of possible wrong profiles
 187.359 -
 187.360 -       NormalizeXYZ(&Icc  -> Illuminant);
 187.361 -
 187.362 -       // Read tag directory
 187.363 -
 187.364 -       if (TagCount > MAX_TABLE_TAG || TagCount < 0) {
 187.365 -
 187.366 -           cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", TagCount);
 187.367 -           goto ErrorCleanup;
 187.368 -       }
 187.369 -
 187.370 -       Icc -> TagCount = TagCount;
 187.371 -       for (i=0; i < TagCount; i++) {
 187.372 -
 187.373 -              if (Icc ->Read(&Tag, sizeof(icTag), 1, Icc) != 1)
 187.374 -                  goto ErrorCleanup;
 187.375 -
 187.376 -              AdjustEndianess32((LPBYTE) &Tag.offset);
 187.377 -              AdjustEndianess32((LPBYTE) &Tag.size);
 187.378 -              AdjustEndianess32((LPBYTE) &Tag.sig);            // Signature
 187.379 -
 187.380 -              // Perform some sanity check. Offset + size should fall inside file.
 187.381 -              extent = Tag.offset + Tag.size;
 187.382 -              if (extent > Header.size || extent < Tag.offset)
 187.383 -                  goto ErrorCleanup;
 187.384 -
 187.385 -              Icc -> TagNames[i]   = Tag.sig;
 187.386 -              Icc -> TagOffsets[i] = Tag.offset;
 187.387 -              Icc -> TagSizes[i]   = Tag.size;
 187.388 -       }
 187.389 -
 187.390 -       return Icc;
 187.391 -
 187.392 -
 187.393 -ErrorCleanup:
 187.394 -
 187.395 -       Icc ->Close(Icc);
 187.396 -
 187.397 -       if (lIsFromMemory)
 187.398 -             cmsSignalError(LCMS_ERRC_ABORTED, "Corrupted memory profile");
 187.399 -       else
 187.400 -             cmsSignalError(LCMS_ERRC_ABORTED, "Corrupted profile: '%s'", Icc->PhysicalFile);
 187.401 -
 187.402 -
 187.403 -        _cmsFree(Icc);
 187.404 -       return NULL;
 187.405 -}
 187.406 -
 187.407 -static
 187.408 -unsigned int uipow(unsigned int a, unsigned int b) {
 187.409 -        unsigned int rv = 1;
 187.410 -        for (; b > 0; b--)
 187.411 -                rv *= a;
 187.412 -        return rv;
 187.413 -}
 187.414 -
 187.415 -
 187.416 -
 187.417 -// Convert between notations.
 187.418 -
 187.419 -#define TO16_TAB(x)      (WORD) (((x) << 8) | (x))
 187.420 -
 187.421 -
 187.422 -// LUT8 can come only in Lab space. There is a fatal flaw in
 187.423 -// converting from Lut8 to Lut16. Due to particular encoding
 187.424 -// of Lab, different actions should be taken from input and
 187.425 -// output Lab8 LUTS. For input, is as easy as applying a << 8,
 187.426 -// since numbers comes in fixed point. However, for output LUT
 187.427 -// things goes a bit more complex.... LUT 16 is supposed to
 187.428 -// have a domain of 0..ff00, so we should remap the LUT in order
 187.429 -// to get things working. Affected signatures are B2Axx tags,
 187.430 -// preview and gamut.
 187.431 -
 187.432 -// I do solve it by multiplying input matrix by:
 187.433 -//
 187.434 -//  | 0xffff/0xff00   0                0              |
 187.435 -//  |       0         0xffff/0xff00    0              |
 187.436 -//  |       0         0                0xffff/0xff00  |
 187.437 -//
 187.438 -// The input values got then remapped to adequate domain
 187.439 -
 187.440 -static
 187.441 -void FixLUT8(LPLUT Lut, icTagSignature sig, size_t nTabSize)
 187.442 -{
 187.443 -    MAT3 Fixup, Original, Result;
 187.444 -    LPWORD PtrW;
 187.445 -    size_t i;
 187.446 -
 187.447 -    switch (sig) {
 187.448 -
 187.449 -
 187.450 -       case icSigBToA0Tag:
 187.451 -       case icSigBToA1Tag:
 187.452 -       case icSigBToA2Tag:
 187.453 -       case icSigGamutTag:
 187.454 -       case icSigPreview0Tag:
 187.455 -       case icSigPreview1Tag:
 187.456 -       case icSigPreview2Tag:
 187.457 -
 187.458 -
 187.459 -                VEC3init(&Fixup.v[0], (double) 0xFFFF/0xFF00, 0, 0);
 187.460 -                VEC3init(&Fixup.v[1], 0, (double) 0xFFFF/0xFF00, 0);
 187.461 -                VEC3init(&Fixup.v[2], 0, 0, (double) 0xFFFF/0xFF00);
 187.462 -
 187.463 -
 187.464 -                MAT3fromFix(&Original, &Lut->Matrix);
 187.465 -                MAT3per(&Result, &Original, &Fixup);
 187.466 -                MAT3toFix(&Lut->Matrix, &Result);
 187.467 -
 187.468 -                Lut -> wFlags |= LUT_HASMATRIX;
 187.469 -                break;
 187.470 -
 187.471 -       // For input, clear low part since this has to be
 187.472 -       // Lab in fixed point
 187.473 -
 187.474 -       default:
 187.475 -
 187.476 -                PtrW = Lut -> T;
 187.477 -                for (i = 0; i < nTabSize; i++) {
 187.478 -
 187.479 -                             *PtrW++ &= 0xFF00;
 187.480 -                }
 187.481 +    // If no wp, take D50
 187.482 +    if (Tag == NULL) {
 187.483 +        *Dest = *cmsD50_XYZ();
 187.484 +        return TRUE;
 187.485      }
 187.486  
 187.487 -}
 187.488 +    // V2 display profiles should give D50
 187.489 +    if (cmsGetEncodedICCversion(hProfile) < 0x4000000) {
 187.490  
 187.491 -// On Lab -> Lab abstract or Lab identities, fix both sides of LUT
 187.492 -
 187.493 -static
 187.494 -void FixLUT8bothSides(LPLUT Lut, size_t nTabSize)
 187.495 -{
 187.496 -    MAT3 Fixup, Original, Result;
 187.497 -    LPWORD PtrW;
 187.498 -    size_t i;
 187.499 -
 187.500 -        VEC3init(&Fixup.v[0], (double) 0xFFFF/0xFF00, 0, 0);
 187.501 -        VEC3init(&Fixup.v[1], 0, (double) 0xFFFF/0xFF00, 0);
 187.502 -        VEC3init(&Fixup.v[2], 0, 0, (double) 0xFFFF/0xFF00);
 187.503 -
 187.504 -        MAT3fromFix(&Original, &Lut->Matrix);
 187.505 -        MAT3per(&Result, &Original, &Fixup);
 187.506 -        MAT3toFix(&Lut->Matrix, &Result);
 187.507 -
 187.508 -        Lut -> wFlags |= LUT_HASMATRIX;
 187.509 -
 187.510 -        PtrW = Lut -> T;
 187.511 -        for (i = 0; i < nTabSize; i++) {
 187.512 -
 187.513 -                     *PtrW++ &= 0xFF00;
 187.514 +        if (cmsGetDeviceClass(hProfile) == cmsSigDisplayClass) {
 187.515 +            *Dest = *cmsD50_XYZ();
 187.516 +            return TRUE;
 187.517          }
 187.518 -
 187.519 -}
 187.520 -
 187.521 -
 187.522 -// The infamous LUT 8
 187.523 -
 187.524 -static
 187.525 -LCMSBOOL ReadLUT8(LPLCMSICCPROFILE Icc, LPLUT NewLUT, icTagSignature sig)
 187.526 -{
 187.527 -    icLut8 LUT8;
 187.528 -    LPBYTE Temp;
 187.529 -    size_t nTabSize;
 187.530 -    unsigned int i, j;
 187.531 -    unsigned int AllLinear;
 187.532 -    LPWORD PtrW;
 187.533 -
 187.534 -       if (Icc ->Read(&LUT8, sizeof(icLut8) - SIZEOF_UINT8_ALIGNED, 1, Icc) != 1) return FALSE;
 187.535 -
 187.536 -       NewLUT -> wFlags        = LUT_HASTL1|LUT_HASTL2|LUT_HAS3DGRID;
 187.537 -       NewLUT -> cLutPoints    = LUT8.clutPoints;
 187.538 -       NewLUT -> InputChan     = LUT8.inputChan;
 187.539 -       NewLUT -> OutputChan    = LUT8.outputChan;
 187.540 -       NewLUT -> InputEntries  = 256;
 187.541 -       NewLUT -> OutputEntries = 256;
 187.542 -
 187.543 -       // Do some checking
 187.544 -       if (!_cmsValidateLUT(NewLUT)) {
 187.545 -          return FALSE;
 187.546 -       }
 187.547 -
 187.548 -       AdjustEndianess32((LPBYTE) &LUT8.e00);
 187.549 -       AdjustEndianess32((LPBYTE) &LUT8.e01);
 187.550 -       AdjustEndianess32((LPBYTE) &LUT8.e02);
 187.551 -       AdjustEndianess32((LPBYTE) &LUT8.e10);
 187.552 -       AdjustEndianess32((LPBYTE) &LUT8.e11);
 187.553 -       AdjustEndianess32((LPBYTE) &LUT8.e12);
 187.554 -       AdjustEndianess32((LPBYTE) &LUT8.e20);
 187.555 -       AdjustEndianess32((LPBYTE) &LUT8.e21);
 187.556 -       AdjustEndianess32((LPBYTE) &LUT8.e22);
 187.557 -
 187.558 -
 187.559 -       // Matrix handling
 187.560 -
 187.561 -       NewLUT -> Matrix.v[0].n[0] = (Fixed32) LUT8.e00;
 187.562 -       NewLUT -> Matrix.v[0].n[1] = (Fixed32) LUT8.e01;
 187.563 -       NewLUT -> Matrix.v[0].n[2] = (Fixed32) LUT8.e02;
 187.564 -       NewLUT -> Matrix.v[1].n[0] = (Fixed32) LUT8.e10;
 187.565 -       NewLUT -> Matrix.v[1].n[1] = (Fixed32) LUT8.e11;
 187.566 -       NewLUT -> Matrix.v[1].n[2] = (Fixed32) LUT8.e12;
 187.567 -       NewLUT -> Matrix.v[2].n[0] = (Fixed32) LUT8.e20;
 187.568 -       NewLUT -> Matrix.v[2].n[1] = (Fixed32) LUT8.e21;
 187.569 -       NewLUT -> Matrix.v[2].n[2] = (Fixed32) LUT8.e22;
 187.570 -
 187.571 -
 187.572 -       // Only operates if not identity...
 187.573 -
 187.574 -       if ((NewLUT -> InputChan == 3) && !MAT3isIdentity(&NewLUT -> Matrix, 0.0001)) {
 187.575 -
 187.576 -              NewLUT -> wFlags |= LUT_HASMATRIX;
 187.577 -       }
 187.578 -
 187.579 -
 187.580 -       // Copy input tables
 187.581 -
 187.582 -       Temp = (LPBYTE) _cmsMalloc(256);
 187.583 -       if (Temp == NULL) return FALSE;
 187.584 -
 187.585 -       AllLinear = 0;
 187.586 -       for (i=0; i < NewLUT -> InputChan; i++) {
 187.587 -
 187.588 -              PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256);
 187.589 -              if (PtrW == NULL) {
 187.590 -                   _cmsFree(Temp);
 187.591 -                  return FALSE;
 187.592 -                  }
 187.593 -
 187.594 -              NewLUT -> L1[i] = PtrW;
 187.595 -              if (Icc ->Read(Temp, 1, 256, Icc) != 256) {
 187.596 -                   _cmsFree(Temp);
 187.597 -                  return FALSE;
 187.598 -                  }
 187.599 -
 187.600 -              for (j=0; j < 256; j++)
 187.601 -                     PtrW[j] = TO16_TAB(Temp[j]);
 187.602 -                     AllLinear += cmsIsLinear(NewLUT -> L1[i], NewLUT -> InputEntries);
 187.603 -              }
 187.604 -
 187.605 -       // Linear input, so ignore full step
 187.606 -
 187.607 -       if (AllLinear == NewLUT -> InputChan) {
 187.608 -
 187.609 -              NewLUT -> wFlags &= ~LUT_HASTL1;
 187.610 -       }
 187.611 -
 187.612 -        _cmsFree(Temp);
 187.613 -
 187.614 -       // Copy 3D CLUT
 187.615 -
 187.616 -       nTabSize = (NewLUT -> OutputChan * uipow(NewLUT->cLutPoints,
 187.617 -                                                NewLUT->InputChan));
 187.618 -
 187.619 -       if (nTabSize > 0) {
 187.620 -
 187.621 -            PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
 187.622 -            if (PtrW == NULL) return FALSE;
 187.623 -
 187.624 -            Temp = (LPBYTE) _cmsMalloc(nTabSize);
 187.625 -            if (Temp == NULL) {
 187.626 -                 _cmsFree(PtrW);
 187.627 -                return FALSE;
 187.628 -                }
 187.629 -
 187.630 -            if (Icc ->Read(Temp, 1, nTabSize, Icc) != nTabSize) {
 187.631 -                 _cmsFree(Temp);
 187.632 -                _cmsFree(PtrW);
 187.633 -                return FALSE;
 187.634 -                }
 187.635 -
 187.636 -            NewLUT -> T = PtrW;
 187.637 -            NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD));
 187.638 -
 187.639 -            for (i = 0; i < nTabSize; i++) {
 187.640 -
 187.641 -                     *PtrW++ = TO16_TAB(Temp[i]);
 187.642 -            }
 187.643 -            _cmsFree(Temp);
 187.644 -       }
 187.645 -       else {
 187.646 -           NewLUT ->T = NULL;
 187.647 -           NewLUT ->Tsize = 0;
 187.648 -           NewLUT ->wFlags &= ~LUT_HAS3DGRID;
 187.649 -       }
 187.650 -
 187.651 -
 187.652 -       // Copy output tables
 187.653 -
 187.654 -       Temp = (LPBYTE) _cmsMalloc(256);
 187.655 -       if (Temp == NULL) {
 187.656 -           return FALSE;
 187.657 -           }
 187.658 -
 187.659 -       AllLinear = 0;
 187.660 -       for (i=0; i < NewLUT -> OutputChan; i++) {
 187.661 -
 187.662 -              PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * 256);
 187.663 -              if (PtrW == NULL) {
 187.664 -                  _cmsFree(Temp);
 187.665 -                  return FALSE;
 187.666 -                  }
 187.667 -
 187.668 -              NewLUT -> L2[i] = PtrW;
 187.669 -              if (Icc ->Read(Temp, 1, 256, Icc) != 256) {
 187.670 -                  _cmsFree(Temp);
 187.671 -                  return FALSE;
 187.672 -                  }
 187.673 -
 187.674 -              for (j=0; j < 256; j++)
 187.675 -                     PtrW[j] = TO16_TAB(Temp[j]);
 187.676 -                     AllLinear += cmsIsLinear(NewLUT -> L2[i], 256);
 187.677 -              }
 187.678 -
 187.679 -       // Linear input, so ignore full step
 187.680 -
 187.681 -       if (AllLinear == NewLUT -> OutputChan) {
 187.682 -
 187.683 -              NewLUT -> wFlags &= ~LUT_HASTL2;
 187.684 -       }
 187.685 -
 187.686 -
 187.687 -       _cmsFree(Temp);
 187.688 -
 187.689 -       cmsCalcL16Params(NewLUT -> InputEntries,  &NewLUT -> In16params);
 187.690 -       cmsCalcL16Params(NewLUT -> OutputEntries, &NewLUT -> Out16params);
 187.691 -       cmsCalcCLUT16Params(NewLUT -> cLutPoints,  NewLUT -> InputChan,
 187.692 -                                                  NewLUT -> OutputChan,
 187.693 -                                                 &NewLUT -> CLut16params);
 187.694 -       // Fixup
 187.695 -
 187.696 -       if (Icc ->PCS == icSigLabData) {
 187.697 -
 187.698 -           // Abstract or Lab identity
 187.699 -
 187.700 -           if (Icc -> ColorSpace == icSigLabData)
 187.701 -
 187.702 -                FixLUT8bothSides(NewLUT, nTabSize);
 187.703 -           else
 187.704 -                FixLUT8(NewLUT, sig, nTabSize);
 187.705 -
 187.706 -
 187.707 -           // Now some additional fixup. Lab encoding on 8 bit makes
 187.708 -           // impossible to place gray axis on a exact node. However,
 187.709 -           // some profiles does claim to do that. Poor lcms will try
 187.710 -           // to detect such condition and fix up "on the fly".
 187.711 -
 187.712 -           switch (sig) {
 187.713 -
 187.714 -            case icSigBToA0Tag:
 187.715 -            case icSigBToA1Tag:
 187.716 -            case icSigBToA2Tag:
 187.717 -            case icSigGamutTag:
 187.718 -            case icSigPreview0Tag:
 187.719 -            case icSigPreview1Tag:
 187.720 -            case icSigPreview2Tag:
 187.721 -           {
 187.722 -               LPWORD WhiteLab, ExpectedWhite;
 187.723 -               WORD WhiteFixed[MAXCHANNELS], WhiteUnfixed[MAXCHANNELS];
 187.724 -               int j, nChannels;
 187.725 -               double Dist, DistFixed, DistUnfixed;
 187.726 -
 187.727 -               _cmsEndPointsBySpace(icSigLabData, &WhiteLab, NULL, NULL);
 187.728 -
 187.729 -               if (_cmsEndPointsBySpace(Icc -> ColorSpace,
 187.730 -                                &ExpectedWhite, NULL, &nChannels)) {
 187.731 -
 187.732 -                   // 1.- Find white obtained by both combinations
 187.733 -
 187.734 -                   NewLUT -> FixGrayAxes = FALSE;
 187.735 -                   cmsEvalLUT(NewLUT, WhiteLab, WhiteUnfixed);
 187.736 -
 187.737 -                   NewLUT -> FixGrayAxes = TRUE;
 187.738 -                   cmsEvalLUT(NewLUT, WhiteLab, WhiteFixed);
 187.739 -
 187.740 -                   // 2.- Which method gives closer white?
 187.741 -
 187.742 -                   DistFixed = DistUnfixed = 0;
 187.743 -                   for (j=0; j < nChannels; j++) {
 187.744 -
 187.745 -                       Dist = ExpectedWhite[j] - WhiteFixed[j];
 187.746 -                       DistFixed += Dist*Dist;
 187.747 -                       Dist = ExpectedWhite[j] - WhiteUnfixed[j];
 187.748 -                       DistUnfixed += Dist*Dist;
 187.749 -                   }
 187.750 -
 187.751 -                   // 3.- Decide method
 187.752 -
 187.753 -                   if (sqrt(DistFixed) < sqrt(DistUnfixed))
 187.754 -                       NewLUT -> FixGrayAxes = TRUE;
 187.755 -                   else
 187.756 -                       NewLUT -> FixGrayAxes = FALSE;
 187.757 -               }
 187.758 -
 187.759 -           }
 187.760 -           break;
 187.761 -
 187.762 -        default:;
 187.763 -        }
 187.764 -       }
 187.765 -
 187.766 -       return TRUE;
 187.767 -}
 187.768 -
 187.769 -
 187.770 -
 187.771 -
 187.772 -// Case LUT 16
 187.773 -
 187.774 -static
 187.775 -LCMSBOOL ReadLUT16(LPLCMSICCPROFILE Icc, LPLUT NewLUT)
 187.776 -{
 187.777 -    icLut16 LUT16;
 187.778 -    size_t nTabSize;
 187.779 -    unsigned int i;
 187.780 -    unsigned int AllLinear;
 187.781 -    LPWORD PtrW;
 187.782 -
 187.783 -
 187.784 -       if (Icc ->Read(&LUT16, sizeof(icLut16)- SIZEOF_UINT16_ALIGNED, 1, Icc) != 1)
 187.785 -            return FALSE;
 187.786 -
 187.787 -       NewLUT -> wFlags        = LUT_HASTL1 | LUT_HASTL2 | LUT_HAS3DGRID;
 187.788 -       NewLUT -> cLutPoints    = LUT16.clutPoints;
 187.789 -       NewLUT -> InputChan     = LUT16.inputChan;
 187.790 -       NewLUT -> OutputChan    = LUT16.outputChan;
 187.791 -
 187.792 -       AdjustEndianess16((LPBYTE) &LUT16.inputEnt);
 187.793 -       AdjustEndianess16((LPBYTE) &LUT16.outputEnt);
 187.794 -
 187.795 -       NewLUT -> InputEntries  = LUT16.inputEnt;
 187.796 -       NewLUT -> OutputEntries = LUT16.outputEnt;
 187.797 -
 187.798 -       if (!_cmsValidateLUT(NewLUT)) {
 187.799 -         return FALSE;
 187.800 -       }
 187.801 -
 187.802 -       // Matrix handling
 187.803 -
 187.804 -       AdjustEndianess32((LPBYTE) &LUT16.e00);
 187.805 -       AdjustEndianess32((LPBYTE) &LUT16.e01);
 187.806 -       AdjustEndianess32((LPBYTE) &LUT16.e02);
 187.807 -       AdjustEndianess32((LPBYTE) &LUT16.e10);
 187.808 -       AdjustEndianess32((LPBYTE) &LUT16.e11);
 187.809 -       AdjustEndianess32((LPBYTE) &LUT16.e12);
 187.810 -       AdjustEndianess32((LPBYTE) &LUT16.e20);
 187.811 -       AdjustEndianess32((LPBYTE) &LUT16.e21);
 187.812 -       AdjustEndianess32((LPBYTE) &LUT16.e22);
 187.813 -
 187.814 -       NewLUT -> Matrix.v[0].n[0] = (Fixed32) LUT16.e00;
 187.815 -       NewLUT -> Matrix.v[0].n[1] = (Fixed32) LUT16.e01;
 187.816 -       NewLUT -> Matrix.v[0].n[2] = (Fixed32) LUT16.e02;
 187.817 -       NewLUT -> Matrix.v[1].n[0] = (Fixed32) LUT16.e10;
 187.818 -       NewLUT -> Matrix.v[1].n[1] = (Fixed32) LUT16.e11;
 187.819 -       NewLUT -> Matrix.v[1].n[2] = (Fixed32) LUT16.e12;
 187.820 -       NewLUT -> Matrix.v[2].n[0] = (Fixed32) LUT16.e20;
 187.821 -       NewLUT -> Matrix.v[2].n[1] = (Fixed32) LUT16.e21;
 187.822 -       NewLUT -> Matrix.v[2].n[2] = (Fixed32) LUT16.e22;
 187.823 -
 187.824 -       // Only operates if not identity...
 187.825 -
 187.826 -       if ((NewLUT -> InputChan == 3) && !MAT3isIdentity(&NewLUT -> Matrix, 0.0001)) {
 187.827 -
 187.828 -              NewLUT -> wFlags |= LUT_HASMATRIX;
 187.829 -       }
 187.830 -
 187.831 -
 187.832 -       // Copy input tables
 187.833 -
 187.834 -       AllLinear = 0;
 187.835 -       for (i=0; i < NewLUT -> InputChan; i++) {
 187.836 -
 187.837 -              PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries);
 187.838 -              if (PtrW == NULL) return FALSE;
 187.839 -
 187.840 -              NewLUT -> L1[i] = PtrW;
 187.841 -              if (Icc ->Read(PtrW, sizeof(WORD), NewLUT -> InputEntries, Icc) != NewLUT -> InputEntries) {
 187.842 -                  return FALSE;
 187.843 -                  }
 187.844 -
 187.845 -              AdjustEndianessArray16(PtrW, NewLUT -> InputEntries);
 187.846 -              AllLinear += cmsIsLinear(NewLUT -> L1[i], NewLUT -> InputEntries);
 187.847 -              }
 187.848 -
 187.849 -       // Linear input, so ignore full step
 187.850 -
 187.851 -       if (AllLinear == NewLUT -> InputChan) {
 187.852 -
 187.853 -              NewLUT -> wFlags &= ~LUT_HASTL1;
 187.854 -       }
 187.855 -
 187.856 -
 187.857 -       // Copy 3D CLUT
 187.858 -
 187.859 -       nTabSize = (NewLUT -> OutputChan * uipow(NewLUT->cLutPoints,
 187.860 -                                                NewLUT->InputChan));
 187.861 -       if (nTabSize > 0) {
 187.862 -
 187.863 -           PtrW = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
 187.864 -           if (PtrW == NULL)
 187.865 -               return FALSE;
 187.866 -
 187.867 -           NewLUT -> T = PtrW;
 187.868 -           NewLUT -> Tsize = (unsigned int) (nTabSize * sizeof(WORD));
 187.869 -
 187.870 -           if (Icc -> Read(PtrW, sizeof(WORD), nTabSize, Icc) != nTabSize) {
 187.871 -               return FALSE;
 187.872 -           }
 187.873 -
 187.874 -           AdjustEndianessArray16(NewLUT -> T, nTabSize);
 187.875 -       }
 187.876 -       else {
 187.877 -           NewLUT ->T = NULL;
 187.878 -           NewLUT ->Tsize = 0;
 187.879 -           NewLUT -> wFlags &= ~LUT_HAS3DGRID;
 187.880 -       }
 187.881 -
 187.882 -       // Copy output tables
 187.883 -
 187.884 -       AllLinear = 0;
 187.885 -       for (i=0; i < NewLUT -> OutputChan; i++) {
 187.886 -
 187.887 -              PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries);
 187.888 -              if (PtrW == NULL) {
 187.889 -                  return FALSE;
 187.890 -                  }
 187.891 -
 187.892 -              NewLUT -> L2[i] = PtrW;
 187.893 -              if (Icc ->Read(PtrW, sizeof(WORD), NewLUT -> OutputEntries, Icc) != NewLUT -> OutputEntries) {
 187.894 -                  return FALSE;
 187.895 -                  }
 187.896 -
 187.897 -              AdjustEndianessArray16(PtrW, NewLUT -> OutputEntries);
 187.898 -              AllLinear += cmsIsLinear(NewLUT -> L2[i], NewLUT -> OutputEntries);
 187.899 -              }
 187.900 -
 187.901 -       // Linear output, ignore step
 187.902 -
 187.903 -       if (AllLinear == NewLUT -> OutputChan)
 187.904 -       {
 187.905 -              NewLUT -> wFlags &= ~LUT_HASTL2;
 187.906 -       }
 187.907 -
 187.908 -
 187.909 -       cmsCalcL16Params(NewLUT -> InputEntries,  &NewLUT -> In16params);
 187.910 -       cmsCalcL16Params(NewLUT -> OutputEntries, &NewLUT -> Out16params);
 187.911 -       cmsCalcCLUT16Params(NewLUT -> cLutPoints,  NewLUT -> InputChan,
 187.912 -                                                  NewLUT -> OutputChan,
 187.913 -                                                  &NewLUT -> CLut16params);
 187.914 -
 187.915 -       return TRUE;
 187.916 -}
 187.917 -
 187.918 -
 187.919 -// This is a shared routine for reading curves. It can handle v2 curves
 187.920 -// as linear, single gamma and table-based as well as v4 parametric curves.
 187.921 -
 187.922 -static
 187.923 -LPGAMMATABLE ReadCurve(LPLCMSICCPROFILE  Icc)
 187.924 -{
 187.925 -    icUInt32Number      Count;
 187.926 -    LPGAMMATABLE        NewGamma;
 187.927 -    icTagTypeSignature  BaseType;
 187.928 -    int                 n;
 187.929 -
 187.930 -
 187.931 -       BaseType = ReadBase(Icc);
 187.932 -       switch (BaseType) {
 187.933 -
 187.934 -
 187.935 -       case ((icTagTypeSignature) 0x9478ee00):    // Monaco 2 profiler is BROKEN!
 187.936 -       case icSigCurveType:
 187.937 -
 187.938 -           if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
 187.939 -           AdjustEndianess32((LPBYTE) &Count);
 187.940 -
 187.941 -           switch (Count) {
 187.942 -
 187.943 -           case 0:   // Linear.
 187.944 -
 187.945 -                     NewGamma = cmsAllocGamma(2);
 187.946 -                     if (!NewGamma) return NULL;
 187.947 -                     NewGamma -> GammaTable[0] = 0;
 187.948 -                     NewGamma -> GammaTable[1] = 0xFFFF;
 187.949 -                     return NewGamma;
 187.950 -
 187.951 -           case 1:  // Specified as the exponent of gamma function
 187.952 -                    {
 187.953 -                     WORD SingleGammaFixed;
 187.954 -
 187.955 -                     if (Icc ->Read(&SingleGammaFixed, sizeof(WORD), 1, Icc) != 1) return NULL;
 187.956 -                     AdjustEndianess16((LPBYTE) &SingleGammaFixed);
 187.957 -                     return cmsBuildGamma(4096, Convert8Fixed8(SingleGammaFixed));
 187.958 -                     }
 187.959 -
 187.960 -           default: { // Curve
 187.961 -
 187.962 -                     NewGamma = cmsAllocGamma(Count);
 187.963 -                     if (!NewGamma) return NULL;
 187.964 -
 187.965 -                     if (Icc ->Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc) != Count)
 187.966 -                         return NULL;
 187.967 -                     AdjustEndianessArray16(NewGamma -> GammaTable, Count);
 187.968 -                     return NewGamma;
 187.969 -                    }
 187.970 -              }
 187.971 -              break;
 187.972 -
 187.973 -
 187.974 -       // Parametric curves
 187.975 -       case icSigParametricCurveType: {
 187.976 -
 187.977 -           int ParamsByType[] = { 1, 3, 4, 5, 7 };
 187.978 -           double Params[10];
 187.979 -           icS15Fixed16Number Num;
 187.980 -           icUInt32Number Reserved;
 187.981 -           icUInt16Number   Type;
 187.982 -           int i;
 187.983 -
 187.984 -           if (Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
 187.985 -           if (Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
 187.986 -
 187.987 -           AdjustEndianess16((LPBYTE) &Type);
 187.988 -           if (Type > 4) {
 187.989 -
 187.990 -                cmsSignalError(LCMS_ERRC_ABORTED, "Unknown parametric curve type '%d' found.", Type);
 187.991 -                return NULL;
 187.992 -           }
 187.993 -
 187.994 -          ZeroMemory(Params, 10* sizeof(double));
 187.995 -          n = ParamsByType[Type];
 187.996 -
 187.997 -          for (i=0; i < n; i++) {
 187.998 -                Num = 0;
 187.999 -                if (Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc) != 1) return NULL;
187.1000 -                Params[i] = Convert15Fixed16(Num);
187.1001 -          }
187.1002 -
187.1003 -
187.1004 -           NewGamma = cmsBuildParametricGamma(4096, Type+1, Params);
187.1005 -           return NewGamma;
187.1006 -          }
187.1007 -
187.1008 -
187.1009 -       default:
187.1010 -              cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature '%lx' found.", BaseType);
187.1011 -              return NULL;
187.1012 -       }
187.1013 -
187.1014 -}
187.1015 -
187.1016 -
187.1017 -// Similar to anterior, but curve is reversed
187.1018 -
187.1019 -static
187.1020 -LPGAMMATABLE ReadCurveReversed(LPLCMSICCPROFILE Icc)
187.1021 -{
187.1022 -
187.1023 -     icTagTypeSignature BaseType;
187.1024 -     LPGAMMATABLE       NewGamma, ReturnGamma;
187.1025 -     icUInt32Number     Count;
187.1026 -     int                n;
187.1027 -
187.1028 -
187.1029 -       BaseType = ReadBase(Icc);
187.1030 -
187.1031 -       switch (BaseType) {
187.1032 -
187.1033 -
187.1034 -       case 0x9478ee00L:    // Monaco 2 profiler is BROKEN!
187.1035 -       case icSigCurveType:
187.1036 -
187.1037 -           if (Icc -> Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
187.1038 -           AdjustEndianess32((LPBYTE) &Count);
187.1039 -
187.1040 -
187.1041 -           switch (Count) {
187.1042 -
187.1043 -           case 0:   // Linear, reverse is same.
187.1044 -
187.1045 -                     NewGamma = cmsAllocGamma(2);
187.1046 -                     if (!NewGamma) return NULL;
187.1047 -
187.1048 -                     NewGamma -> GammaTable[0] = 0;
187.1049 -                     NewGamma -> GammaTable[1] = 0xFFFF;
187.1050 -                     return NewGamma;
187.1051 -
187.1052 -           case 1:  {
187.1053 -                     WORD SingleGammaFixed;
187.1054 -
187.1055 -                     if (Icc -> Read(&SingleGammaFixed, sizeof(WORD), 1, Icc) != 1) return NULL;
187.1056 -                     AdjustEndianess16((LPBYTE) &SingleGammaFixed);
187.1057 -                     return cmsBuildGamma(4096, 1./Convert8Fixed8(SingleGammaFixed));
187.1058 -                     }
187.1059 -
187.1060 -           default: { // Curve. Do our best to trying to reverse the curve
187.1061 -
187.1062 -                     NewGamma = cmsAllocGamma(Count);
187.1063 -                     if (!NewGamma) return NULL;
187.1064 -
187.1065 -                     if (Icc -> Read(NewGamma -> GammaTable, sizeof(WORD), Count, Icc) != Count)
187.1066 -                         return NULL;
187.1067 -
187.1068 -                     AdjustEndianessArray16(NewGamma -> GammaTable, Count);
187.1069 -
187.1070 -                     if (Count < 256)
187.1071 -                         Count = 256;      // Reverse of simple curve has not necesarely to be simple
187.1072 -
187.1073 -                     ReturnGamma = cmsReverseGamma(Count, NewGamma);
187.1074 -                     cmsFreeGamma(NewGamma);
187.1075 -
187.1076 -                     return ReturnGamma;
187.1077 -                    }
187.1078 -              }
187.1079 -              break;
187.1080 -
187.1081 -
187.1082 -       // Parametric curves
187.1083 -       case icSigParametricCurveType: {
187.1084 -
187.1085 -           int ParamsByType[] = { 1, 3, 4, 5, 7 };
187.1086 -           double Params[10];
187.1087 -           icS15Fixed16Number Num;
187.1088 -           icUInt32Number Reserved;
187.1089 -           icUInt16Number   Type;
187.1090 -           int i;
187.1091 -
187.1092 -
187.1093 -           if (Icc -> Read(&Type, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
187.1094 -           if (Icc -> Read(&Reserved, sizeof(icUInt16Number), 1, Icc) != 1) return NULL;
187.1095 -
187.1096 -           AdjustEndianess16((LPBYTE) &Type);
187.1097 -           if (Type > 4) {
187.1098 -
187.1099 -                cmsSignalError(LCMS_ERRC_ABORTED, "Unknown parametric curve type '%d' found.", Type);
187.1100 -                return NULL;
187.1101 -           }
187.1102 -
187.1103 -          ZeroMemory(Params, 10* sizeof(double));
187.1104 -          n = ParamsByType[Type];
187.1105 -
187.1106 -          for (i=0; i < n; i++) {
187.1107 -                if (Icc -> Read(&Num, sizeof(icS15Fixed16Number), 1, Icc) != 1) return NULL;
187.1108 -                Params[i] = Convert15Fixed16(Num);
187.1109 -          }
187.1110 -
187.1111 -
187.1112 -           // Negative type as a mark of reversed curve
187.1113 -           NewGamma = cmsBuildParametricGamma(4096, -(Type+1), Params);
187.1114 -           return NewGamma;
187.1115 -          }
187.1116 -
187.1117 -
187.1118 -       default:
187.1119 -              cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature '%lx' found.", BaseType);
187.1120 -              return NULL;
187.1121 -       }
187.1122 -
187.1123 -}
187.1124 -
187.1125 -
187.1126 -// V4 stuff. Read matrix for LutAtoB and LutBtoA
187.1127 -
187.1128 -static
187.1129 -LCMSBOOL ReadMatrixOffset(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, DWORD dwFlags)
187.1130 -{
187.1131 -
187.1132 -    icS15Fixed16Number All[12];
187.1133 -    int i;
187.1134 -    MAT3 m;
187.1135 -    VEC3 o;
187.1136 -
187.1137 -    if (Icc -> Seek(Icc, Offset)) return FALSE;
187.1138 -
187.1139 -    if (Icc ->Read(All, sizeof(icS15Fixed16Number), 12, Icc) != 12)
187.1140 -        return FALSE;
187.1141 -
187.1142 -    for (i=0; i < 12;  i++)
187.1143 -              AdjustEndianess32((LPBYTE) &All[i]);
187.1144 -
187.1145 -
187.1146 -       m.v[0].n[0] = FIXED_TO_DOUBLE((Fixed32) All[0]);
187.1147 -       m.v[0].n[1] = FIXED_TO_DOUBLE((Fixed32) All[1]);
187.1148 -       m.v[0].n[2] = FIXED_TO_DOUBLE((Fixed32) All[2]);
187.1149 -       m.v[1].n[0] = FIXED_TO_DOUBLE((Fixed32) All[3]);
187.1150 -       m.v[1].n[1] = FIXED_TO_DOUBLE((Fixed32) All[4]);
187.1151 -       m.v[1].n[2] = FIXED_TO_DOUBLE((Fixed32) All[5]);
187.1152 -       m.v[2].n[0] = FIXED_TO_DOUBLE((Fixed32) All[6]);
187.1153 -       m.v[2].n[1] = FIXED_TO_DOUBLE((Fixed32) All[7]);
187.1154 -       m.v[2].n[2] = FIXED_TO_DOUBLE((Fixed32) All[8]);
187.1155 -
187.1156 -       o.n[0] = FIXED_TO_DOUBLE((Fixed32) All[9]);
187.1157 -       o.n[1] = FIXED_TO_DOUBLE((Fixed32) All[10]);
187.1158 -       o.n[2] = FIXED_TO_DOUBLE((Fixed32) All[11]);
187.1159 -
187.1160 -       cmsSetMatrixLUT4(NewLUT, &m, &o, dwFlags);
187.1161 -
187.1162 -       return TRUE;
187.1163 -}
187.1164 -
187.1165 -
187.1166 -//  V4 stuff. Read CLUT part for LutAtoB and LutBtoA
187.1167 -
187.1168 -static
187.1169 -LCMSBOOL ReadCLUT(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT)
187.1170 -{
187.1171 -    unsigned int j;
187.1172 -    icCLutStruct CLUT;
187.1173 -
187.1174 -    if (Icc -> Seek(Icc, Offset)) return FALSE;
187.1175 -    if (Icc ->Read(&CLUT, sizeof(icCLutStruct), 1, Icc) != 1) return FALSE;
187.1176 -
187.1177 -
187.1178 -    for (j=1; j < NewLUT ->InputChan; j++) {
187.1179 -        if (CLUT.gridPoints[0] != CLUT.gridPoints[j]) {
187.1180 -            cmsSignalError(LCMS_ERRC_ABORTED, "CLUT with different granulatity is currently unsupported.");
187.1181 -            return FALSE;
187.1182 -        }
187.1183 -
187.1184 -
187.1185      }
187.1186  
187.1187 -    if (cmsAlloc3DGrid(NewLUT, CLUT.gridPoints[0], NewLUT ->InputChan,
187.1188 -                                               NewLUT ->OutputChan) == NULL) return FALSE;
187.1189 -
187.1190 -    // Precission can be 1 or 2 bytes
187.1191 -
187.1192 -    if (CLUT.prec == 1) {
187.1193 -
187.1194 -        BYTE v;
187.1195 -        unsigned int i;
187.1196 -
187.1197 -        for (i=0; i < NewLUT->Tsize / sizeof(WORD); i++) {
187.1198 -                if (Icc ->Read(&v, sizeof(BYTE), 1, Icc) != 1) return FALSE;
187.1199 -                NewLUT->T[i] = TO16_TAB(v);
187.1200 -        }
187.1201 -
187.1202 -    }
187.1203 -    else
187.1204 -        if (CLUT.prec == 2) {
187.1205 -
187.1206 -         size_t n = NewLUT->Tsize / sizeof(WORD);
187.1207 -
187.1208 -         if (Icc ->Read(NewLUT ->T, sizeof(WORD), n, Icc) != n) return FALSE;
187.1209 -         AdjustEndianessArray16(NewLUT ->T, NewLUT->Tsize / sizeof(WORD));
187.1210 -    }
187.1211 -    else {
187.1212 -        cmsSignalError(LCMS_ERRC_ABORTED, "Unknow precission of '%d'", CLUT.prec);
187.1213 -        return FALSE;
187.1214 -    }
187.1215 -
187.1216 +    // All seems ok
187.1217 +    *Dest = *Tag;
187.1218      return TRUE;
187.1219  }
187.1220  
187.1221  
187.1222 -static
187.1223 -void ResampleCurves(LPGAMMATABLE Curves[], int nCurves)
187.1224 +// Chromatic adaptation matrix. Fix some issues as well
187.1225 +cmsBool  _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile)
187.1226  {
187.1227 -    int i;
187.1228 -    LPSAMPLEDCURVE sc;
187.1229 +    cmsMAT3* Tag;
187.1230  
187.1231 -    for (i=0; i < nCurves; i++) {
187.1232 -        sc = cmsConvertGammaToSampledCurve(Curves[i], 4096);
187.1233 -        cmsFreeGamma(Curves[i]);
187.1234 -        Curves[i] = cmsConvertSampledCurveToGamma(sc, 0xFFFF);
187.1235 -        cmsFreeSampledCurve(sc);
187.1236 +    _cmsAssert(Dest != NULL);
187.1237 +
187.1238 +    Tag = (cmsMAT3*) cmsReadTag(hProfile, cmsSigChromaticAdaptationTag);
187.1239 +
187.1240 +    if (Tag != NULL) {
187.1241 +
187.1242 +        *Dest = *Tag;
187.1243 +        return TRUE;
187.1244      }
187.1245  
187.1246 -}
187.1247 +    // No CHAD available, default it to identity
187.1248 +    _cmsMAT3identity(Dest);
187.1249  
187.1250 +    // V2 display profiles should give D50
187.1251 +    if (cmsGetEncodedICCversion(hProfile) < 0x4000000) {
187.1252  
187.1253 -static
187.1254 -void SkipAlignment(LPLCMSICCPROFILE Icc)
187.1255 -{
187.1256 -    BYTE Buffer[4];
187.1257 -    size_t At = Icc ->Tell(Icc);
187.1258 -    int BytesToNextAlignedPos = (int) (At % 4);
187.1259 +        if (cmsGetDeviceClass(hProfile) == cmsSigDisplayClass) {
187.1260  
187.1261 -    Icc ->Read(Buffer, 1, BytesToNextAlignedPos, Icc);
187.1262 -}
187.1263 +            cmsCIEXYZ* White = (cmsCIEXYZ*) cmsReadTag(hProfile, cmsSigMediaWhitePointTag);
187.1264  
187.1265 -// Read a set of curves from specific offset
187.1266 -static
187.1267 -LCMSBOOL ReadSetOfCurves(LPLCMSICCPROFILE Icc, size_t Offset, LPLUT NewLUT, int nLocation)
187.1268 -{
187.1269 -    LPGAMMATABLE Curves[MAXCHANNELS];
187.1270 -    unsigned int i, nCurves;
187.1271 +            if (White == NULL) {
187.1272  
187.1273 -    if (Icc -> Seek(Icc, Offset)) return FALSE;
187.1274 -
187.1275 -    if (nLocation == 1 ||  nLocation == 3)
187.1276 -
187.1277 -        nCurves = NewLUT ->InputChan;
187.1278 -    else
187.1279 -        nCurves = NewLUT ->OutputChan;
187.1280 -
187.1281 -    ZeroMemory(Curves, sizeof(Curves));
187.1282 -    for (i=0; i < nCurves; i++) {
187.1283 -
187.1284 -        Curves[i] = ReadCurve(Icc);
187.1285 -        if (Curves[i] == NULL) goto Error;
187.1286 -        SkipAlignment(Icc);
187.1287 -    }
187.1288 -
187.1289 -    // March-26'08: some V4 profiles may have different sampling
187.1290 -    // rates, in this case resample all curves to maximum
187.1291 -
187.1292 -    for (i=1; i < nCurves; i++) {
187.1293 -        if (Curves[i]->nEntries != Curves[0]->nEntries) {
187.1294 -            ResampleCurves(Curves, nCurves);
187.1295 -        break;
187.1296 -        }
187.1297 -    }
187.1298 -
187.1299 -    NewLUT = cmsAllocLinearTable(NewLUT, Curves, nLocation);
187.1300 -    if (NewLUT == NULL) goto Error;
187.1301 -
187.1302 -    for (i=0; i < nCurves; i++)
187.1303 -        cmsFreeGamma(Curves[i]);
187.1304 -
187.1305 -    return TRUE;
187.1306 -
187.1307 -Error:
187.1308 -
187.1309 -    for (i=0; i < nCurves; i++)
187.1310 -        if (Curves[i])
187.1311 -            cmsFreeGamma(Curves[i]);
187.1312 -
187.1313 -    return FALSE;
187.1314 -
187.1315 -
187.1316 -}
187.1317 -
187.1318 -// V4 stuff. LutAtoB type
187.1319 -//
187.1320 -//  [L1] -> [CLUT] -> [L4] -> [Mat4] -> [Ofs4] -> [L2]
187.1321 -//
187.1322 -//  Mat, Mat3, Ofs3, L3 are missing
187.1323 -//   L1 = A curves
187.1324 -//   L4 = M curves
187.1325 -//   L2 = B curves
187.1326 -
187.1327 -static
187.1328 -LCMSBOOL ReadLUT_A2B(LPLCMSICCPROFILE Icc, LPLUT NewLUT, size_t BaseOffset, icTagSignature sig)
187.1329 -{
187.1330 -    icLutAtoB LUT16;
187.1331 -
187.1332 -       if (Icc ->Read(&LUT16, sizeof(icLutAtoB), 1, Icc) != 1) return FALSE;
187.1333 -
187.1334 -       NewLUT -> InputChan     = LUT16.inputChan;
187.1335 -       NewLUT -> OutputChan    = LUT16.outputChan;
187.1336 -
187.1337 -       // Validate the NewLUT here to avoid excessive number of channels
187.1338 -       // (leading to stack-based buffer overflow in ReadSetOfCurves).
187.1339 -       // Needs revalidation after table size is filled in.
187.1340 -       if (!_cmsValidateLUT(NewLUT)) {
187.1341 -           return FALSE;
187.1342 -       }
187.1343 -
187.1344 -       AdjustEndianess32((LPBYTE) &LUT16.offsetB);
187.1345 -       AdjustEndianess32((LPBYTE) &LUT16.offsetMat);
187.1346 -       AdjustEndianess32((LPBYTE) &LUT16.offsetM);
187.1347 -       AdjustEndianess32((LPBYTE) &LUT16.offsetC);
187.1348 -       AdjustEndianess32((LPBYTE) &LUT16.offsetA);
187.1349 -
187.1350 -       if (LUT16.offsetB != 0)
187.1351 -                ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetB, NewLUT, 2);
187.1352 -
187.1353 -       if (LUT16.offsetMat != 0)
187.1354 -            ReadMatrixOffset(Icc, BaseOffset + LUT16.offsetMat, NewLUT, LUT_HASMATRIX4);
187.1355 -
187.1356 -
187.1357 -       if (LUT16.offsetM != 0)
187.1358 -                ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetM, NewLUT, 4);
187.1359 -
187.1360 -       if (LUT16.offsetC != 0)
187.1361 -           ReadCLUT(Icc, BaseOffset + LUT16.offsetC, NewLUT);
187.1362 -
187.1363 -       if (LUT16.offsetA!= 0)
187.1364 -                ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetA, NewLUT, 1);
187.1365 -
187.1366 -        // Convert to v2 PCS
187.1367 -
187.1368 -       if (Icc ->PCS == icSigLabData) {
187.1369 -
187.1370 -       switch (sig) {
187.1371 -
187.1372 -       case icSigAToB0Tag:
187.1373 -       case icSigAToB1Tag:
187.1374 -       case icSigAToB2Tag:
187.1375 -       case icSigGamutTag:
187.1376 -       case icSigPreview0Tag:
187.1377 -       case icSigPreview1Tag:
187.1378 -       case icSigPreview2Tag:
187.1379 -
187.1380 -               NewLUT ->wFlags |= LUT_V4_INPUT_EMULATE_V2;
187.1381 -               break;
187.1382 -
187.1383 -       default:;
187.1384 -       }
187.1385 -       }
187.1386 -
187.1387 -
187.1388 -       return TRUE;
187.1389 -}
187.1390 -
187.1391 -// V4 stuff. LutBtoA type
187.1392 -
187.1393 -static
187.1394 -LCMSBOOL ReadLUT_B2A(LPLCMSICCPROFILE Icc, LPLUT NewLUT,  size_t BaseOffset, icTagSignature sig)
187.1395 -{
187.1396 -  icLutBtoA LUT16;
187.1397 -
187.1398 -       if (Icc ->Read(&LUT16, sizeof(icLutBtoA), 1, Icc) != 1) return FALSE;
187.1399 -
187.1400 -       NewLUT -> InputChan     = LUT16.inputChan;
187.1401 -       NewLUT -> OutputChan    = LUT16.outputChan;
187.1402 -
187.1403 -       // Validate the NewLUT here to avoid excessive number of channels
187.1404 -       // (leading to stack-based buffer overflow in ReadSetOfCurves).
187.1405 -       // Needs revalidation after table size is filled in.
187.1406 -       if (!_cmsValidateLUT(NewLUT)) {
187.1407 -           return FALSE;
187.1408 -       }
187.1409 -
187.1410 -       AdjustEndianess32((LPBYTE) &LUT16.offsetB);
187.1411 -       AdjustEndianess32((LPBYTE) &LUT16.offsetMat);
187.1412 -       AdjustEndianess32((LPBYTE) &LUT16.offsetM);
187.1413 -       AdjustEndianess32((LPBYTE) &LUT16.offsetC);
187.1414 -       AdjustEndianess32((LPBYTE) &LUT16.offsetA);
187.1415 -
187.1416 -
187.1417 -       if (LUT16.offsetB != 0)
187.1418 -                ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetB, NewLUT, 1);
187.1419 -
187.1420 -       if (LUT16.offsetMat != 0)
187.1421 -            ReadMatrixOffset(Icc, BaseOffset + LUT16.offsetMat, NewLUT, LUT_HASMATRIX3);
187.1422 -
187.1423 -       if (LUT16.offsetM != 0)
187.1424 -                ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetM, NewLUT, 3);
187.1425 -
187.1426 -       if (LUT16.offsetC != 0)
187.1427 -           ReadCLUT(Icc, BaseOffset + LUT16.offsetC, NewLUT);
187.1428 -
187.1429 -       if (LUT16.offsetA!= 0)
187.1430 -                ReadSetOfCurves(Icc, BaseOffset + LUT16.offsetA, NewLUT, 2);
187.1431 -
187.1432 -
187.1433 -       // Convert to v2 PCS
187.1434 -
187.1435 -       if (Icc ->PCS == icSigLabData) {
187.1436 -
187.1437 -       switch (sig) {
187.1438 -
187.1439 -       case icSigBToA0Tag:
187.1440 -       case icSigBToA1Tag:
187.1441 -       case icSigBToA2Tag:
187.1442 -       case icSigGamutTag:
187.1443 -       case icSigPreview0Tag:
187.1444 -       case icSigPreview1Tag:
187.1445 -       case icSigPreview2Tag:
187.1446 -
187.1447 -               NewLUT ->wFlags |= LUT_V4_OUTPUT_EMULATE_V2;
187.1448 -               break;
187.1449 -
187.1450 -       default:;
187.1451 -       }
187.1452 -       }
187.1453 -
187.1454 -       return TRUE;
187.1455 -}
187.1456 -
187.1457 -// CLUT main reader
187.1458 -
187.1459 -LPLUT LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig)
187.1460 -{
187.1461 -
187.1462 -    LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.1463 -    icTagTypeSignature  BaseType;
187.1464 -    int                 n;
187.1465 -    size_t              offset;
187.1466 -    LPLUT               NewLUT;
187.1467 -
187.1468 -    n = _cmsSearchTag(Icc, sig, TRUE);
187.1469 -    if (n < 0)
187.1470 -        return NULL;
187.1471 -
187.1472 -
187.1473 -    // If is in memory, the LUT is already there, so throw a copy
187.1474 -    if (Icc -> TagPtrs[n]) {
187.1475 -        if (!_cmsValidateLUT((LPLUT) Icc ->TagPtrs[n])) {
187.1476 -            return NULL;
187.1477 -        }
187.1478 -
187.1479 -        return cmsDupLUT((LPLUT) Icc ->TagPtrs[n]);
187.1480 -    }
187.1481 -
187.1482 -    offset = Icc -> TagOffsets[n];
187.1483 -
187.1484 -    if (Icc -> Seek(Icc, offset))
187.1485 -            return NULL;
187.1486 -
187.1487 -    BaseType = ReadBase(Icc);
187.1488 -
187.1489 -
187.1490 -    NewLUT = cmsAllocLUT();
187.1491 -    if (!NewLUT) {
187.1492 -
187.1493 -       cmsSignalError(LCMS_ERRC_ABORTED, "cmsAllocLUT() failed");
187.1494 -       return NULL;
187.1495 -    }
187.1496 -
187.1497 -
187.1498 -    switch (BaseType) {
187.1499 -
187.1500 -    case icSigLut8Type:    if (!ReadLUT8(Icc, NewLUT, sig)) {
187.1501 -                                cmsFreeLUT(NewLUT);
187.1502 -                                return NULL;
187.1503 -                           }
187.1504 -                           break;
187.1505 -
187.1506 -    case icSigLut16Type:   if (!ReadLUT16(Icc, NewLUT)) {
187.1507 -                                cmsFreeLUT(NewLUT);
187.1508 -                                return NULL;
187.1509 -                           }
187.1510 -                           break;
187.1511 -
187.1512 -    case icSiglutAtoBType: if (!ReadLUT_A2B(Icc, NewLUT, offset, sig)) {
187.1513 -                                cmsFreeLUT(NewLUT);
187.1514 -                                return NULL;
187.1515 -                           }
187.1516 -                           break;
187.1517 -
187.1518 -    case icSiglutBtoAType: if (!ReadLUT_B2A(Icc, NewLUT, offset, sig)) {
187.1519 -                                cmsFreeLUT(NewLUT);
187.1520 -                                return NULL;
187.1521 -                           }
187.1522 -                           break;
187.1523 -
187.1524 -    default:  cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature %lx found.", BaseType);
187.1525 -              cmsFreeLUT(NewLUT);
187.1526 -              return NULL;
187.1527 -    }
187.1528 -
187.1529 -
187.1530 -    return NewLUT;
187.1531 -}
187.1532 -
187.1533 -
187.1534 -// Sets the language & country preferences. Used only in ICC 4.0 profiles
187.1535 -
187.1536 -void LCMSEXPORT cmsSetLanguage(const char LanguageCode[4], const char CountryCode[4])
187.1537 -{
187.1538 -
187.1539 -    int LanguageCodeInt = *(int *) LanguageCode;
187.1540 -    int CountryCodeInt  = *(int *) CountryCode;
187.1541 -
187.1542 -    AdjustEndianess32((LPBYTE) &LanguageCodeInt);
187.1543 -    AdjustEndianess32((LPBYTE) &CountryCodeInt);
187.1544 -
187.1545 -    GlobalLanguageCode = LanguageCodeInt;
187.1546 -    GlobalCountryCode  = CountryCodeInt;
187.1547 -}
187.1548 -
187.1549 -
187.1550 -
187.1551 -// Some tags (e.g, 'pseq') can have text tags embedded. This function
187.1552 -// handles such special case. Returns -1 on error, or the number of bytes left on success.
187.1553 -
187.1554 -static
187.1555 -int ReadEmbeddedTextTag(LPLCMSICCPROFILE Icc, size_t size, char* Name, size_t size_max)
187.1556 -{
187.1557 -    icTagTypeSignature  BaseType;
187.1558 -
187.1559 -
187.1560 -    BaseType = ReadBase(Icc);
187.1561 -    size -= sizeof(icTagBase);
187.1562 -
187.1563 -    switch (BaseType) {
187.1564 -
187.1565 -    case icSigTextDescriptionType: {
187.1566 -
187.1567 -           icUInt32Number  AsciiCount;
187.1568 -           icUInt32Number  i, UnicodeCode, UnicodeCount;
187.1569 -           icUInt16Number  ScriptCodeCode, Dummy;
187.1570 -           icUInt8Number   ScriptCodeCount;
187.1571 -
187.1572 -           if (Icc ->Read(&AsciiCount, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
187.1573 -
187.1574 -           if (size < sizeof(icUInt32Number)) return (int) size;
187.1575 -           size -= sizeof(icUInt32Number);
187.1576 -
187.1577 -           AdjustEndianess32((LPBYTE) &AsciiCount);
187.1578 -           Icc ->Read(Name, 1,
187.1579 -                (AsciiCount >= size_max) ? (size_max-1) : AsciiCount, Icc);
187.1580 -
187.1581 -           if (size < AsciiCount) return (int) size;
187.1582 -           size -= AsciiCount;
187.1583 -
187.1584 -           // Skip Unicode code
187.1585 -
187.1586 -           if (Icc ->Read(&UnicodeCode,  sizeof(icUInt32Number), 1, Icc) != 1) return -1;
187.1587 -           if (size < sizeof(icUInt32Number)) return (int) size;
187.1588 -           size -= sizeof(icUInt32Number);
187.1589 -
187.1590 -           if (Icc ->Read(&UnicodeCount, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
187.1591 -           if (size < sizeof(icUInt32Number)) return (int) size;
187.1592 -           size -= sizeof(icUInt32Number);
187.1593 -
187.1594 -           AdjustEndianess32((LPBYTE) &UnicodeCount);
187.1595 -
187.1596 -           if (UnicodeCount > size) return (int) size;
187.1597 -
187.1598 -           for (i=0; i < UnicodeCount; i++) {
187.1599 -                size_t nread = Icc ->Read(&Dummy, sizeof(icUInt16Number), 1, Icc);
187.1600 -                if (nread != 1) return (int) size;
187.1601 -                size -= sizeof(icUInt16Number);
187.1602 -           }
187.1603 -
187.1604 -          // Skip ScriptCode code
187.1605 -
187.1606 -           if (Icc ->Read(&ScriptCodeCode,  sizeof(icUInt16Number), 1, Icc) != 1) return -1;
187.1607 -           size -= sizeof(icUInt16Number);
187.1608 -           if (Icc ->Read(&ScriptCodeCount, sizeof(icUInt8Number), 1, Icc) != 1) return -1;
187.1609 -           size -= sizeof(icUInt8Number);
187.1610 -
187.1611 -           // Should remain 67 bytes as filler
187.1612 -
187.1613 -           if (size < 67) return (int) size;
187.1614 -
187.1615 -           for (i=0; i < 67; i++) {
187.1616 -                size_t nread = Icc ->Read(&Dummy, sizeof(icUInt8Number), 1, Icc);
187.1617 -                if (nread != 1) return (int) size;
187.1618 -                size --;
187.1619 -               }
187.1620 -           }
187.1621 -           break;
187.1622 -
187.1623 -
187.1624 -    case icSigCopyrightTag:   // Broken profiles from agfa does store copyright info in such type
187.1625 -    case icSigTextType:
187.1626 -         {
187.1627 -         char Dummy;
187.1628 -         size_t i, Missing = 0;
187.1629 -
187.1630 -         if (size >= size_max) {
187.1631 -
187.1632 -             Missing = size - size_max + 1;
187.1633 -             size = size_max - 1;
187.1634 -         }
187.1635 -
187.1636 -         if (Icc -> Read(Name, 1, size, Icc) != size) return -1;
187.1637 -
187.1638 -         for (i=0; i < Missing; i++)
187.1639 -             Icc -> Read(&Dummy, 1, 1, Icc);
187.1640 -         }
187.1641 -         break;
187.1642 -
187.1643 -    // MultiLocalizedUnicodeType, V4 only
187.1644 -
187.1645 -    case icSigMultiLocalizedUnicodeType: {
187.1646 -
187.1647 -        icUInt32Number Count, RecLen;
187.1648 -        icUInt16Number Language, Country;
187.1649 -        icUInt32Number ThisLen, ThisOffset;
187.1650 -        size_t         Offset = 0;
187.1651 -        size_t         Len    = 0;
187.1652 -        size_t         i;
187.1653 -        wchar_t*       wchar  = L"";
187.1654 -
187.1655 -
187.1656 -            if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
187.1657 -            AdjustEndianess32((LPBYTE) &Count);
187.1658 -            if (Icc ->Read(&RecLen, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
187.1659 -            AdjustEndianess32((LPBYTE) &RecLen);
187.1660 -
187.1661 -            if (RecLen != 12) {
187.1662 -
187.1663 -                    cmsSignalError(LCMS_ERRC_ABORTED, "multiLocalizedUnicodeType of len != 12 is not supported.");
187.1664 -                    return -1;
187.1665 +                _cmsMAT3identity(Dest);
187.1666 +                return TRUE;
187.1667              }
187.1668  
187.1669 -            for (i=0; i < Count; i++) {
187.1670 -
187.1671 -                if (Icc ->Read(&Language, sizeof(icUInt16Number), 1, Icc) != 1) return -1;
187.1672 -                AdjustEndianess16((LPBYTE) &Language);
187.1673 -                if (Icc ->Read(&Country, sizeof(icUInt16Number), 1, Icc) != 1) return -1;
187.1674 -                AdjustEndianess16((LPBYTE) &Country);
187.1675 -
187.1676 -                if (Icc ->Read(&ThisLen, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
187.1677 -                AdjustEndianess32((LPBYTE) &ThisLen);
187.1678 -
187.1679 -                if (Icc ->Read(&ThisOffset, sizeof(icUInt32Number), 1, Icc) != 1) return -1;
187.1680 -                AdjustEndianess32((LPBYTE) &ThisOffset);
187.1681 -
187.1682 -                if (Language == GlobalLanguageCode || Offset == 0) {
187.1683 -
187.1684 -                    Len = ThisLen; Offset = ThisOffset;
187.1685 -                    if (Country == GlobalCountryCode)
187.1686 -                                    break;              // Found
187.1687 -                }
187.1688 -
187.1689 -            }
187.1690 -
187.1691 -
187.1692 -            if (Offset == 0) {
187.1693 -
187.1694 -                    strcpy(Name, "(no info)");
187.1695 -                    break;
187.1696 -            }
187.1697 -
187.1698 -            // Compute true offset
187.1699 -            Offset -= 12 * Count + 8 + sizeof(icTagBase);
187.1700 -
187.1701 -            // Skip unused bytes
187.1702 -            for (i=0; i < Offset; i++) {
187.1703 -
187.1704 -                    char Discard;
187.1705 -                    if (Icc ->Read(&Discard, 1, 1, Icc) != 1) return -1;
187.1706 -            }
187.1707 -
187.1708 -
187.1709 -            // Bound len
187.1710 -            if (Len < 0) Len = 0;
187.1711 -            if (Len > 20*1024) Len = 20 * 1024;
187.1712 -
187.1713 -            wchar = (wchar_t*) _cmsMalloc(Len*sizeof(wchar_t)+2);
187.1714 -            if (!wchar) return -1;
187.1715 -
187.1716 -            if (Icc ->Read(wchar, 1, Len, Icc) != Len) return -1;
187.1717 -            AdjustEndianessArray16((LPWORD) wchar, Len / 2);
187.1718 -
187.1719 -            wchar[Len / 2] = L'\0';
187.1720 -            i = wcstombs(Name, wchar, size_max );
187.1721 -            if (i == ((size_t) -1)) {
187.1722 -
187.1723 -                Name[0] = 0;    // Error
187.1724 -            }
187.1725 -
187.1726 -            _cmsFree((void*) wchar);
187.1727 -            }
187.1728 -            break;
187.1729 -
187.1730 -    default:
187.1731 -            cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature %lx found.", BaseType);
187.1732 -            return -1;
187.1733 -    }
187.1734 -
187.1735 -    return (int) size;
187.1736 -}
187.1737 -
187.1738 -
187.1739 -// Take an ASCII item. Takes at most size_max bytes
187.1740 -
187.1741 -int LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *Name, size_t size_max)
187.1742 -{
187.1743 -    LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.1744 -    size_t              offset, size;
187.1745 -    int                 n;
187.1746 -
187.1747 -    n = _cmsSearchTag(Icc, sig, TRUE);
187.1748 -    if (n < 0)
187.1749 -        return -1;
187.1750 -
187.1751 -     size   = Icc -> TagSizes[n];
187.1752 -
187.1753 -    if (Icc -> TagPtrs[n]) {
187.1754 -
187.1755 -        if (size > size_max)
187.1756 -            size = size_max;
187.1757 -
187.1758 -        CopyMemory(Name, Icc -> TagPtrs[n], size);
187.1759 -
187.1760 -        return (int) Icc -> TagSizes[n];
187.1761 -    }
187.1762 -
187.1763 -    offset = Icc -> TagOffsets[n];
187.1764 -
187.1765 -
187.1766 -    if (Icc -> Seek(Icc, offset))
187.1767 -            return -1;
187.1768 -
187.1769 -    if (ReadEmbeddedTextTag(Icc, size, Name, size_max) < 0) return -1;
187.1770 -
187.1771 -        return size;
187.1772 -}
187.1773 -
187.1774 -// Keep compatibility with older versions
187.1775 -
187.1776 -int LCMSEXPORT cmsReadICCText(cmsHPROFILE hProfile, icTagSignature sig, char *Text)
187.1777 -{
187.1778 -    return cmsReadICCTextEx(hProfile, sig, Text, LCMS_DESC_MAX);
187.1779 -}
187.1780 -
187.1781 -
187.1782 -// Take an XYZ item
187.1783 -
187.1784 -static
187.1785 -int ReadICCXYZ(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIEXYZ Value, LCMSBOOL lIsFatal)
187.1786 -{
187.1787 -    LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.1788 -    icTagTypeSignature  BaseType;
187.1789 -    size_t              offset;
187.1790 -    int                 n;
187.1791 -    icXYZNumber         XYZ;
187.1792 -
187.1793 -    n = _cmsSearchTag(Icc, sig, FALSE);
187.1794 -    if (n < 0)
187.1795 -            return -1;
187.1796 -
187.1797 -    if (Icc -> TagPtrs[n]) {
187.1798 -
187.1799 -         CopyMemory(Value, Icc -> TagPtrs[n], Icc -> TagSizes[n]);
187.1800 -         return (int) Icc -> TagSizes[n];
187.1801 -    }
187.1802 -
187.1803 -    offset = Icc -> TagOffsets[n];
187.1804 -
187.1805 -    if (Icc -> Seek(Icc, offset))
187.1806 -            return -1;
187.1807 -
187.1808 -
187.1809 -    BaseType = ReadBase(Icc);
187.1810 -
187.1811 -    switch (BaseType) {
187.1812 -
187.1813 -
187.1814 -    case 0x7c3b10cL:    // Some apple broken embedded profiles does not have correct type
187.1815 -    case icSigXYZType:
187.1816 -
187.1817 -           Icc ->Read(&XYZ, sizeof(icXYZNumber), 1, Icc);
187.1818 -           Value -> X = Convert15Fixed16(XYZ.X);
187.1819 -           Value -> Y = Convert15Fixed16(XYZ.Y);
187.1820 -           Value -> Z = Convert15Fixed16(XYZ.Z);
187.1821 -           break;
187.1822 -
187.1823 -    // Aug/21-2001 - Monaco 2 does have WRONG values.
187.1824 -
187.1825 -    default:
187.1826 -           if (lIsFatal)
187.1827 -                cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature %lx found.", BaseType);
187.1828 -           return -1;
187.1829 -    }
187.1830 -
187.1831 -    return 1;
187.1832 -}
187.1833 -
187.1834 -
187.1835 -// Read a icSigS15Fixed16ArrayType (currently only a 3x3 matrix)
187.1836 -
187.1837 -static
187.1838 -int ReadICCXYZArray(cmsHPROFILE hProfile, icTagSignature sig, LPMAT3 v)
187.1839 -{
187.1840 -    LPLCMSICCPROFILE    Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.1841 -    icTagTypeSignature  BaseType;
187.1842 -    size_t              offset, sz;
187.1843 -    int                 i, n;
187.1844 -    icXYZNumber         XYZ[3];
187.1845 -    cmsCIEXYZ           XYZdbl[3];
187.1846 -
187.1847 -
187.1848 -    n = _cmsSearchTag(Icc, sig, FALSE);
187.1849 -    if (n < 0)
187.1850 -            return -1; // Not found
187.1851 -
187.1852 -    if (Icc -> TagPtrs[n]) {
187.1853 -
187.1854 -            CopyMemory(v, Icc -> TagPtrs[n], Icc -> TagSizes[n]);
187.1855 -            return (int) Icc -> TagSizes[n];
187.1856 -    }
187.1857 -
187.1858 -    offset = Icc -> TagOffsets[n];
187.1859 -
187.1860 -    if (Icc -> Seek(Icc, offset))
187.1861 -            return -1;
187.1862 -
187.1863 -    BaseType = ReadBase(Icc);
187.1864 -
187.1865 -    switch (BaseType) {
187.1866 -
187.1867 -    case icSigS15Fixed16ArrayType:
187.1868 -
187.1869 -         sz = Icc ->TagSizes[n] / sizeof(icXYZNumber);
187.1870 -
187.1871 -         if (sz != 3) {
187.1872 -             cmsSignalError(LCMS_ERRC_ABORTED, "Bad array size of %d entries.", sz);
187.1873 -             return -1;
187.1874 -         }
187.1875 -
187.1876 -         Icc ->Read(XYZ, sizeof(icXYZNumber), 3, Icc);
187.1877 -
187.1878 -         for (i=0; i < 3; i++) {
187.1879 -
187.1880 -            XYZdbl[i].X = Convert15Fixed16(XYZ[i].X);
187.1881 -            XYZdbl[i].Y = Convert15Fixed16(XYZ[i].Y);
187.1882 -            XYZdbl[i].Z = Convert15Fixed16(XYZ[i].Z);
187.1883 -         }
187.1884 -
187.1885 -         CopyMemory(v, XYZdbl, 3*sizeof(cmsCIEXYZ));
187.1886 -         break;
187.1887 -
187.1888 -    default:
187.1889 -         cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature %lx found.", BaseType);
187.1890 -         return -1;
187.1891 -
187.1892 -    }
187.1893 -
187.1894 -   return sizeof(MAT3);
187.1895 -}
187.1896 -
187.1897 -
187.1898 -
187.1899 -// Primaries are to be in xyY notation
187.1900 -
187.1901 -LCMSBOOL LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile)
187.1902 -{
187.1903 -       if (ReadICCXYZ(hProfile, icSigRedColorantTag, &Dest -> Red, TRUE) < 0) return FALSE;
187.1904 -       if (ReadICCXYZ(hProfile, icSigGreenColorantTag, &Dest -> Green, TRUE) < 0) return FALSE;
187.1905 -       if (ReadICCXYZ(hProfile, icSigBlueColorantTag, &Dest -> Blue, TRUE) < 0) return FALSE;
187.1906 -
187.1907 -       return TRUE;
187.1908 -}
187.1909 -
187.1910 -
187.1911 -LCMSBOOL cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile)
187.1912 -{
187.1913 -       cmsCIEXYZTRIPLE Primaries;
187.1914 -
187.1915 -       if (!cmsTakeColorants(&Primaries, hProfile)) return FALSE;
187.1916 -
187.1917 -       VEC3init(&r -> v[0], Primaries.Red.X, Primaries.Green.X,  Primaries.Blue.X);
187.1918 -       VEC3init(&r -> v[1], Primaries.Red.Y, Primaries.Green.Y,  Primaries.Blue.Y);
187.1919 -       VEC3init(&r -> v[2], Primaries.Red.Z, Primaries.Green.Z,  Primaries.Blue.Z);
187.1920 -
187.1921 -       return TRUE;
187.1922 -
187.1923 -}
187.1924 -
187.1925 -
187.1926 -// Always return a suitable matrix
187.1927 -
187.1928 -LCMSBOOL cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile)
187.1929 -{
187.1930 -
187.1931 -    if (ReadICCXYZArray(hProfile, icSigChromaticAdaptationTag, r) < 0) {
187.1932 -
187.1933 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.1934 -
187.1935 -       // For display profiles, revert to bradford. Else take identity.
187.1936 -
187.1937 -       MAT3identity(r);
187.1938 -
187.1939 -       // Emissive devices have non-identity chad
187.1940 -
187.1941 -       if ((cmsGetDeviceClass(hProfile) == icSigDisplayClass) ||
187.1942 -           cmsTakeHeaderFlags(hProfile) & icTransparency) {
187.1943 -
187.1944 -            // NULL for cone defaults to Bradford, from media to D50
187.1945 -            cmsAdaptationMatrix(r, NULL, &Icc ->MediaWhitePoint, &Icc ->Illuminant);
187.1946 +            return _cmsAdaptationMatrix(Dest, NULL, cmsD50_XYZ(), White);
187.1947          }
187.1948      }
187.1949  
187.1950 @@ -1909,1850 +158,599 @@
187.1951  }
187.1952  
187.1953  
187.1954 +// Auxiliar, read colorants as a MAT3 structure. Used by any function that needs a matrix-shaper
187.1955 +static
187.1956 +cmsBool ReadICCMatrixRGB2XYZ(cmsMAT3* r, cmsHPROFILE hProfile)
187.1957 +{
187.1958 +    cmsCIEXYZ *PtrRed, *PtrGreen, *PtrBlue;
187.1959  
187.1960 -LPGAMMATABLE LCMSEXPORT cmsReadICCGamma(cmsHPROFILE hProfile, icTagSignature sig)
187.1961 -{
187.1962 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.1963 -       size_t         offset;
187.1964 -       int            n;
187.1965 +    _cmsAssert(r != NULL);
187.1966  
187.1967 +    PtrRed   = (cmsCIEXYZ *) cmsReadTag(hProfile, cmsSigRedColorantTag);
187.1968 +    PtrGreen = (cmsCIEXYZ *) cmsReadTag(hProfile, cmsSigGreenColorantTag);
187.1969 +    PtrBlue  = (cmsCIEXYZ *) cmsReadTag(hProfile, cmsSigBlueColorantTag);
187.1970  
187.1971 -       n = _cmsSearchTag(Icc, sig, TRUE);
187.1972 -       if (n < 0)
187.1973 -           return NULL;
187.1974 -
187.1975 -       if (Icc -> TagPtrs[n]) {
187.1976 -
187.1977 -            return cmsDupGamma((LPGAMMATABLE) Icc -> TagPtrs[n]);
187.1978 -       }
187.1979 -
187.1980 -       offset = Icc -> TagOffsets[n];
187.1981 -
187.1982 -       if (Icc -> Seek(Icc, offset))
187.1983 -            return NULL;
187.1984 -
187.1985 -       return ReadCurve(Icc);
187.1986 -
187.1987 -}
187.1988 -
187.1989 -
187.1990 -// Some ways have analytical revese. This function accounts for that
187.1991 -
187.1992 -LPGAMMATABLE LCMSEXPORT cmsReadICCGammaReversed(cmsHPROFILE hProfile, icTagSignature sig)
187.1993 -{
187.1994 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.1995 -       size_t         offset;
187.1996 -       int            n;
187.1997 -
187.1998 -
187.1999 -       n = _cmsSearchTag(Icc, sig, TRUE);
187.2000 -       if (n < 0)
187.2001 -            return NULL;
187.2002 -
187.2003 -       if (Icc -> TagPtrs[n]) {
187.2004 -
187.2005 -            return cmsReverseGamma(256, (LPGAMMATABLE) Icc -> TagPtrs[n]);
187.2006 -       }
187.2007 -
187.2008 -       offset = Icc -> TagOffsets[n];
187.2009 -
187.2010 -       if (Icc -> Seek(Icc, offset))
187.2011 -            return NULL;
187.2012 -
187.2013 -       return ReadCurveReversed(Icc);
187.2014 -}
187.2015 -
187.2016 -// Check Named color header
187.2017 -
187.2018 -static
187.2019 -LCMSBOOL CheckHeader(LPcmsNAMEDCOLORLIST v, icNamedColor2* nc2)
187.2020 -{
187.2021 -    if (v ->Prefix[0] == 0 && v ->Suffix[0] == 0 && v ->ColorantCount == 0) return TRUE;
187.2022 -
187.2023 -    if (stricmp(v ->Prefix, (const char*) nc2 ->prefix) != 0) return FALSE;
187.2024 -    if (stricmp(v ->Suffix, (const char*) nc2 ->suffix) != 0) return FALSE;
187.2025 -
187.2026 -    return ((int) v ->ColorantCount == (int) nc2 ->nDeviceCoords);
187.2027 -}
187.2028 -
187.2029 -// Read named color list
187.2030 -
187.2031 -int cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSignature sig)
187.2032 -{
187.2033 -       _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
187.2034 -       LPLCMSICCPROFILE   Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.2035 -       int                n;
187.2036 -       icTagTypeSignature BaseType;
187.2037 -       size_t             offset;
187.2038 -
187.2039 -       n = _cmsSearchTag(Icc, sig, TRUE);
187.2040 -       if (n < 0)
187.2041 -            return 0;
187.2042 -
187.2043 -       if (Icc -> TagPtrs[n]) {
187.2044 -
187.2045 -            // This replaces actual named color list.
187.2046 -            size_t size   = Icc -> TagSizes[n];
187.2047 -
187.2048 -            if (v ->NamedColorList) cmsFreeNamedColorList(v ->NamedColorList);
187.2049 -            v -> NamedColorList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
187.2050 -            CopyMemory(v -> NamedColorList, Icc ->TagPtrs[n], size);
187.2051 -            return v ->NamedColorList->nColors;
187.2052 -       }
187.2053 -
187.2054 -       offset = Icc -> TagOffsets[n];
187.2055 -
187.2056 -       if (Icc -> Seek(Icc, offset))
187.2057 -            return 0;
187.2058 -
187.2059 -       BaseType = ReadBase(Icc);
187.2060 -
187.2061 -       switch (BaseType) {
187.2062 -
187.2063 -        // I never have seen one of these. Probably is not worth of implementing.
187.2064 -
187.2065 -       case icSigNamedColorType: {
187.2066 -
187.2067 -              cmsSignalError(LCMS_ERRC_WARNING, "Ancient named color profiles are not supported.");
187.2068 -              return 0;
187.2069 -            }
187.2070 -
187.2071 -        // The named color struct
187.2072 -
187.2073 -       case icSigNamedColor2Type: {
187.2074 -
187.2075 -                icNamedColor2 nc2;
187.2076 -                unsigned int i, j;
187.2077 -
187.2078 -                if (Icc -> Read(&nc2, sizeof(icNamedColor2) - SIZEOF_UINT8_ALIGNED, 1, Icc) != 1) return 0;
187.2079 -                AdjustEndianess32((LPBYTE) &nc2.vendorFlag);
187.2080 -                AdjustEndianess32((LPBYTE) &nc2.count);
187.2081 -                AdjustEndianess32((LPBYTE) &nc2.nDeviceCoords);
187.2082 -
187.2083 -                if (!CheckHeader(v->NamedColorList, &nc2)) {
187.2084 -                     cmsSignalError(LCMS_ERRC_WARNING, "prefix/suffix/device for named color profiles mismatch.");
187.2085 -                     return 0;
187.2086 -                }
187.2087 -
187.2088 -                if (nc2.nDeviceCoords > MAXCHANNELS) {
187.2089 -                          cmsSignalError(LCMS_ERRC_WARNING, "Too many device coordinates.");
187.2090 -                          return 0;
187.2091 -                }
187.2092 -
187.2093 -                strncpy(v ->NamedColorList->Prefix, (const char*) nc2.prefix, 32);
187.2094 -                strncpy(v ->NamedColorList->Suffix, (const char*) nc2.suffix, 32);
187.2095 -                v ->NamedColorList->Prefix[32] = v->NamedColorList->Suffix[32] = 0;
187.2096 -
187.2097 -                v ->NamedColorList ->ColorantCount = nc2.nDeviceCoords;
187.2098 -
187.2099 -                for (i=0; i < nc2.count; i++) {
187.2100 -
187.2101 -                    WORD PCS[3];
187.2102 -                    WORD Colorant[MAXCHANNELS];
187.2103 -                    char Root[33];
187.2104 -
187.2105 -                    ZeroMemory(Colorant, sizeof(WORD) * MAXCHANNELS);
187.2106 -                    Icc -> Read(Root, 1, 32, Icc);
187.2107 -                    Icc -> Read(PCS,  3, sizeof(WORD), Icc);
187.2108 -
187.2109 -                    for (j=0; j < 3; j++)
187.2110 -                        AdjustEndianess16((LPBYTE) &PCS[j]);
187.2111 -
187.2112 -                    Icc -> Read(Colorant, sizeof(WORD), nc2.nDeviceCoords, Icc);
187.2113 -
187.2114 -                    for (j=0; j < nc2.nDeviceCoords; j++)
187.2115 -                            AdjustEndianess16((LPBYTE) &Colorant[j]);
187.2116 -
187.2117 -                    cmsAppendNamedColor(v, Root, PCS, Colorant);
187.2118 -                }
187.2119 -
187.2120 -            return v ->NamedColorList->nColors;
187.2121 -            }
187.2122 -            break;
187.2123 -
187.2124 -       default:
187.2125 -              cmsSignalError(LCMS_ERRC_WARNING, "Bad tag signature '%lx' found.", BaseType);
187.2126 -              return 0;
187.2127 -       }
187.2128 -
187.2129 -       // It would never reach here
187.2130 -       // return 0;
187.2131 -}
187.2132 -
187.2133 -
187.2134 -
187.2135 -// Read colorant tables
187.2136 -
187.2137 -LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile, icTagSignature sig)
187.2138 -{
187.2139 -    icInt32Number n;
187.2140 -    icUInt32Number Count, i;
187.2141 -    size_t offset;
187.2142 -    icTagTypeSignature  BaseType;
187.2143 -    LPLCMSICCPROFILE   Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.2144 -    LPcmsNAMEDCOLORLIST List;
187.2145 -
187.2146 -    n = _cmsSearchTag(Icc, sig, FALSE);
187.2147 -    if (n < 0)
187.2148 -            return NULL; // Not found
187.2149 -
187.2150 -    if (Icc -> TagPtrs[n]) {
187.2151 -
187.2152 -            size_t size   = Icc -> TagSizes[n];
187.2153 -            void* v = _cmsMalloc(size);
187.2154 -
187.2155 -            if (v == NULL) return NULL;
187.2156 -            CopyMemory(v, Icc -> TagPtrs[n], size);
187.2157 -            return (LPcmsNAMEDCOLORLIST) v;
187.2158 -    }
187.2159 -
187.2160 -
187.2161 -    offset = Icc -> TagOffsets[n];
187.2162 -
187.2163 -    if (Icc -> Seek(Icc, offset))
187.2164 -            return NULL;
187.2165 -
187.2166 -    BaseType = ReadBase(Icc);
187.2167 -
187.2168 -    if (BaseType != icSigColorantTableType) {
187.2169 -            cmsSignalError(LCMS_ERRC_ABORTED, "Bad tag signature '%lx' found.", BaseType);
187.2170 -            return NULL;
187.2171 -    }
187.2172 -
187.2173 -
187.2174 -    if (Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc) != 1) return NULL;
187.2175 -    AdjustEndianess32((LPBYTE) &Count);
187.2176 -
187.2177 -    if (Count > MAXCHANNELS) {
187.2178 -        cmsSignalError(LCMS_ERRC_ABORTED, "Too many colorants '%lx'", Count);
187.2179 -        return NULL;
187.2180 -    }
187.2181 -
187.2182 -    List = cmsAllocNamedColorList(Count);
187.2183 -    for (i=0; i < Count; i++) {
187.2184 -
187.2185 -        if (!Icc ->Read(List->List[i].Name, 1, 32 , Icc)) goto Error;
187.2186 -        if (!Icc ->Read(List->List[i].PCS, sizeof(icUInt16Number), 3, Icc)) goto Error;
187.2187 -        AdjustEndianessArray16(List->List[i].PCS, 3);
187.2188 -    }
187.2189 -
187.2190 -    return List;
187.2191 -
187.2192 -Error:
187.2193 -    cmsFreeNamedColorList(List);
187.2194 -    return NULL;
187.2195 -
187.2196 -}
187.2197 -
187.2198 -
187.2199 -
187.2200 -// Uncooked manufacturer
187.2201 -
187.2202 -const char* LCMSEXPORT cmsTakeManufacturer(cmsHPROFILE hProfile)
187.2203 -{
187.2204 -
187.2205 -    static char Manufacturer[LCMS_DESC_MAX] = "";
187.2206 -
187.2207 -       Manufacturer[0] = 0;
187.2208 -
187.2209 -       if (cmsIsTag(hProfile, icSigDeviceMfgDescTag)) {
187.2210 -
187.2211 -            cmsReadICCTextEx(hProfile, icSigDeviceMfgDescTag, Manufacturer, LCMS_DESC_MAX);
187.2212 -       }
187.2213 -
187.2214 -    return Manufacturer;
187.2215 -}
187.2216 -
187.2217 -// Uncooked model
187.2218 -
187.2219 -const char* LCMSEXPORT cmsTakeModel(cmsHPROFILE hProfile)
187.2220 -{
187.2221 -
187.2222 -    static char Model[LCMS_DESC_MAX] = "";
187.2223 -
187.2224 -       Model[0] = 0;
187.2225 -
187.2226 -       if (cmsIsTag(hProfile, icSigDeviceModelDescTag)) {
187.2227 -
187.2228 -            cmsReadICCTextEx(hProfile, icSigDeviceModelDescTag, Model, LCMS_DESC_MAX);
187.2229 -       }
187.2230 -
187.2231 -    return Model;
187.2232 -}
187.2233 -
187.2234 -
187.2235 -const char* LCMSEXPORT cmsTakeCopyright(cmsHPROFILE hProfile)
187.2236 -{
187.2237 -
187.2238 -    static char Copyright[LCMS_DESC_MAX] = "";
187.2239 -
187.2240 -       Copyright[0] = 0;
187.2241 -       if (cmsIsTag(hProfile, icSigCopyrightTag)) {
187.2242 -
187.2243 -            cmsReadICCTextEx(hProfile, icSigCopyrightTag, Copyright, LCMS_DESC_MAX);
187.2244 -       }
187.2245 -
187.2246 -    return Copyright;
187.2247 -}
187.2248 -
187.2249 -
187.2250 -// We compute name with model - manufacturer
187.2251 -
187.2252 -const char*  LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile)
187.2253 -{
187.2254 -    static char Name[LCMS_DESC_MAX*2+4];
187.2255 -    char Manufacturer[LCMS_DESC_MAX], Model[LCMS_DESC_MAX];
187.2256 -
187.2257 -    Name[0] = '\0';
187.2258 -    Manufacturer[0] = Model[0] = '\0';
187.2259 -
187.2260 -    if (cmsIsTag(hProfile, icSigDeviceMfgDescTag)) {
187.2261 -
187.2262 -        cmsReadICCTextEx(hProfile, icSigDeviceMfgDescTag, Manufacturer, LCMS_DESC_MAX);
187.2263 -    }
187.2264 -
187.2265 -    if (cmsIsTag(hProfile, icSigDeviceModelDescTag)) {
187.2266 -
187.2267 -        cmsReadICCTextEx(hProfile, icSigDeviceModelDescTag, Model, LCMS_DESC_MAX);
187.2268 -    }
187.2269 -
187.2270 -    if (!Manufacturer[0] && !Model[0]) {
187.2271 -
187.2272 -        if (cmsIsTag(hProfile, icSigProfileDescriptionTag)) {
187.2273 -
187.2274 -            cmsReadICCTextEx(hProfile, icSigProfileDescriptionTag, Name, LCMS_DESC_MAX);
187.2275 -            return Name;
187.2276 -        }
187.2277 -        else return "{no name}";
187.2278 -    }
187.2279 -
187.2280 -
187.2281 -    if (!Manufacturer[0] ||
187.2282 -            strncmp(Model, Manufacturer, 8) == 0 || strlen(Model) > 30)
187.2283 -        strcpy(Name, Model);
187.2284 -    else
187.2285 -        sprintf(Name, "%s - %s", Model, Manufacturer);
187.2286 -
187.2287 -    return Name;
187.2288 -
187.2289 -}
187.2290 -
187.2291 -
187.2292 -// We compute desc with manufacturer - model
187.2293 -
187.2294 -const char*  LCMSEXPORT cmsTakeProductDesc(cmsHPROFILE hProfile)
187.2295 -{
187.2296 -       static char Name[2048];
187.2297 -
187.2298 -       if (cmsIsTag(hProfile, icSigProfileDescriptionTag)) {
187.2299 -
187.2300 -              cmsReadICCText(hProfile, icSigProfileDescriptionTag, Name);
187.2301 -       }
187.2302 -       else return cmsTakeProductName(hProfile);
187.2303 -
187.2304 -       if (strncmp(Name, "Copyrig", 7) == 0)
187.2305 -              return cmsTakeProductName(hProfile);
187.2306 -
187.2307 -       return Name;
187.2308 -}
187.2309 -
187.2310 -
187.2311 -const char*  LCMSEXPORT cmsTakeProductInfo(cmsHPROFILE hProfile)
187.2312 -{
187.2313 -       LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.2314 -
187.2315 -       static char Info[4096];
187.2316 -
187.2317 -       Info[0] = '\0';
187.2318 -
187.2319 -       if (cmsIsTag(hProfile, icSigProfileDescriptionTag))
187.2320 -       {
187.2321 -       char Desc[1024];
187.2322 -
187.2323 -       cmsReadICCText(hProfile, icSigProfileDescriptionTag, Desc);
187.2324 -       strcat(Info, Desc);
187.2325 -       strcat(Info, "\r\n\r\n");
187.2326 -       }
187.2327 -
187.2328 -
187.2329 -       if (cmsIsTag(hProfile, icSigCopyrightTag))
187.2330 -       {
187.2331 -       char Copyright[LCMS_DESC_MAX];
187.2332 -
187.2333 -       cmsReadICCText(hProfile, icSigCopyrightTag, Copyright);
187.2334 -       strcat(Info, Copyright);
187.2335 -       strcat(Info, "\r\n\r\n");
187.2336 -       }
187.2337 -
187.2338 -
187.2339 -
187.2340 -// KODAK private tag... But very useful
187.2341 -
187.2342 -#define K007         (icTagSignature)0x4B303037
187.2343 -
187.2344 -       // MonCal
187.2345 -
187.2346 -       if (cmsIsTag(hProfile, K007))
187.2347 -       {
187.2348 -       char MonCal[LCMS_DESC_MAX];
187.2349 -
187.2350 -       cmsReadICCText(hProfile, K007, MonCal);
187.2351 -       strcat(Info, MonCal);
187.2352 -       strcat(Info, "\r\n\r\n");
187.2353 -       }
187.2354 -       else
187.2355 -       {
187.2356 -       cmsCIEXYZ WhitePt;
187.2357 -       char WhiteStr[1024];
187.2358 -
187.2359 -       cmsTakeMediaWhitePoint(&WhitePt, hProfile);
187.2360 -       _cmsIdentifyWhitePoint(WhiteStr, &WhitePt);
187.2361 -       strcat(WhiteStr, "\r\n\r\n");
187.2362 -       strcat(Info, WhiteStr);
187.2363 -       }
187.2364 -
187.2365 -
187.2366 -       if (Icc -> stream) {
187.2367 -              strcat(Info, Icc -> PhysicalFile);
187.2368 -       }
187.2369 -       return Info;
187.2370 -}
187.2371 -
187.2372 -// Extract the target data as a big string. Does not signal if tag is not present.
187.2373 -
187.2374 -LCMSBOOL LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len)
187.2375 -{
187.2376 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.2377 -    int n;
187.2378 -
187.2379 -    *Data = NULL;
187.2380 -    *len  = 0;
187.2381 -
187.2382 -    n = _cmsSearchTag(Icc, icSigCharTargetTag, FALSE);
187.2383 -    if (n < 0) return FALSE;
187.2384 -
187.2385 -
187.2386 -    *len =  Icc -> TagSizes[n];
187.2387 -
187.2388 -    // Make sure that is reasonable (600K)
187.2389 -    if (*len > 600*1024) *len = 600*1024;
187.2390 -
187.2391 -    *Data = (char*) _cmsMalloc(*len + 1);  // Plus zero marker
187.2392 -
187.2393 -    if (!*Data) {
187.2394 -
187.2395 -        cmsSignalError(LCMS_ERRC_ABORTED, "Out of memory allocating CharTarget space!");
187.2396 -        return FALSE;
187.2397 -    }
187.2398 -
187.2399 -    if (cmsReadICCTextEx(hProfile, icSigCharTargetTag, *Data, *len) < 0)
187.2400 +    if (PtrRed == NULL || PtrGreen == NULL || PtrBlue == NULL)
187.2401          return FALSE;
187.2402  
187.2403 -    (*Data)[*len] = 0;  // Force a zero marker. Shouldn't be needed, but is
187.2404 -                        // here to simplify things.
187.2405 +    _cmsVEC3init(&r -> v[0], PtrRed -> X, PtrGreen -> X,  PtrBlue -> X);
187.2406 +    _cmsVEC3init(&r -> v[1], PtrRed -> Y, PtrGreen -> Y,  PtrBlue -> Y);
187.2407 +    _cmsVEC3init(&r -> v[2], PtrRed -> Z, PtrGreen -> Z,  PtrBlue -> Z);
187.2408  
187.2409      return TRUE;
187.2410  }
187.2411  
187.2412  
187.2413 +// Gray input pipeline
187.2414 +static
187.2415 +cmsPipeline* BuildGrayInputMatrixPipeline(cmsHPROFILE hProfile)
187.2416 +{
187.2417 +    cmsToneCurve *GrayTRC;
187.2418 +    cmsPipeline* Lut;
187.2419 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
187.2420  
187.2421 +    GrayTRC = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGrayTRCTag);
187.2422 +    if (GrayTRC == NULL) return NULL;
187.2423  
187.2424 -LCMSBOOL LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
187.2425 -{
187.2426 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.2427 -    int n;
187.2428 +    Lut = cmsPipelineAlloc(ContextID, 1, 3);
187.2429 +    if (Lut == NULL) return NULL;
187.2430  
187.2431 -    n = _cmsSearchTag(Icc, icSigCalibrationDateTimeTag, FALSE);
187.2432 -    if (n < 0) return FALSE;
187.2433 +    if (cmsGetPCS(hProfile) == cmsSigLabData) {
187.2434  
187.2435 -    if (Icc ->TagPtrs[n]) {
187.2436 +        // In this case we implement the profile as an  identity matrix plus 3 tone curves
187.2437 +        cmsUInt16Number Zero[2] = { 0x8080, 0x8080 };
187.2438 +        cmsToneCurve* EmptyTab;
187.2439 +        cmsToneCurve* LabCurves[3];
187.2440  
187.2441 -        CopyMemory(Dest, Icc ->TagPtrs[n],  sizeof(struct tm));
187.2442 +        EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
187.2443 +
187.2444 +        if (EmptyTab == NULL) {
187.2445 +
187.2446 +                 cmsPipelineFree(Lut);
187.2447 +                 return NULL;
187.2448 +        }
187.2449 +
187.2450 +        LabCurves[0] = GrayTRC;
187.2451 +        LabCurves[1] = EmptyTab;
187.2452 +        LabCurves[2] = EmptyTab;
187.2453 +
187.2454 +        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3,  1, OneToThreeInputMatrix, NULL));
187.2455 +        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, LabCurves));
187.2456 +
187.2457 +        cmsFreeToneCurve(EmptyTab);
187.2458 +
187.2459      }
187.2460 -    else
187.2461 -    {
187.2462 -        icDateTimeNumber timestamp;
187.2463 -
187.2464 -        if (Icc -> Seek(Icc, Icc -> TagOffsets[n] + sizeof(icTagBase)))
187.2465 -            return FALSE;
187.2466 -
187.2467 -        if (Icc ->Read(&timestamp, 1, sizeof(icDateTimeNumber), Icc) != sizeof(icDateTimeNumber))
187.2468 -            return FALSE;
187.2469 -
187.2470 -        DecodeDateTimeNumber(&timestamp, Dest);
187.2471 +    else  {
187.2472 +       cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &GrayTRC));
187.2473 +       cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3,  1, GrayInputMatrix, NULL));
187.2474      }
187.2475  
187.2476 -
187.2477 -    return TRUE;
187.2478 +    return Lut;
187.2479  }
187.2480  
187.2481 +// RGB Matrix shaper
187.2482 +static
187.2483 +cmsPipeline* BuildRGBInputMatrixShaper(cmsHPROFILE hProfile)
187.2484 +{
187.2485 +    cmsPipeline* Lut;
187.2486 +    cmsMAT3 Mat;
187.2487 +    cmsToneCurve *Shapes[3];
187.2488 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
187.2489 +    int i, j;
187.2490  
187.2491 +    if (!ReadICCMatrixRGB2XYZ(&Mat, hProfile)) return NULL;
187.2492  
187.2493 -// PSEQ Tag, used in devicelink profiles
187.2494 +    // XYZ PCS in encoded in 1.15 format, and the matrix output comes in 0..0xffff range, so
187.2495 +    // we need to adjust the output by a factor of (0x10000/0xffff) to put data in
187.2496 +    // a 1.16 range, and then a >> 1 to obtain 1.15. The total factor is (65536.0)/(65535.0*2)
187.2497  
187.2498 -LPcmsSEQ LCMSEXPORT cmsReadProfileSequenceDescription(cmsHPROFILE hProfile)
187.2499 -{
187.2500 -    LPLCMSICCPROFILE  Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.2501 -    int n;
187.2502 -    icUInt32Number     i, Count;
187.2503 -    icDescStruct       DescStruct;
187.2504 -    icTagTypeSignature BaseType;
187.2505 -    size_t             size, offset;
187.2506 -    LPcmsSEQ           OutSeq;
187.2507 +    for (i=0; i < 3; i++)
187.2508 +        for (j=0; j < 3; j++)
187.2509 +            Mat.v[i].n[j] *= InpAdj;
187.2510  
187.2511  
187.2512 -    n = _cmsSearchTag(Icc, icSigProfileSequenceDescTag, FALSE);
187.2513 -    if (n < 0) return NULL;
187.2514 +    Shapes[0] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigRedTRCTag);
187.2515 +    Shapes[1] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGreenTRCTag);
187.2516 +    Shapes[2] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigBlueTRCTag);
187.2517  
187.2518 -    size   = Icc -> TagSizes[n];
187.2519 -    if (size < 12)  return NULL;
187.2520 +    if (!Shapes[0] || !Shapes[1] || !Shapes[2])
187.2521 +        return NULL;
187.2522  
187.2523 -    if (Icc -> TagPtrs[n]) {
187.2524 +    Lut = cmsPipelineAlloc(ContextID, 3, 3);
187.2525 +    if (Lut != NULL) {
187.2526  
187.2527 -            OutSeq = (LPcmsSEQ) _cmsMalloc(size);
187.2528 -            if (OutSeq == NULL) return NULL;
187.2529 -            CopyMemory(OutSeq, Icc ->TagPtrs[n], size);
187.2530 -            return OutSeq;
187.2531 +        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, Shapes));
187.2532 +        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Mat, NULL));
187.2533      }
187.2534  
187.2535 -    offset = Icc -> TagOffsets[n];
187.2536 +    return Lut;
187.2537 +}
187.2538  
187.2539 -    if (Icc -> Seek(Icc, offset))
187.2540 -            return NULL;
187.2541 +// Read and create a BRAND NEW MPE LUT from a given profile. All stuff dependent of version, etc
187.2542 +// is adjusted here in order to create a LUT that takes care of all those details
187.2543 +cmsPipeline* _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent)
187.2544 +{
187.2545 +    cmsTagTypeSignature OriginalType;
187.2546 +    cmsTagSignature tag16    = Device2PCS16[Intent];
187.2547 +    cmsTagSignature tagFloat = Device2PCSFloat[Intent];
187.2548 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
187.2549  
187.2550 -    BaseType = ReadBase(Icc);
187.2551 +    if (cmsIsTag(hProfile, tagFloat)) {  // Float tag takes precedence
187.2552  
187.2553 -    if (BaseType != icSigProfileSequenceDescType) return NULL;
187.2554 -
187.2555 -    Icc ->Read(&Count, sizeof(icUInt32Number), 1, Icc);
187.2556 -    AdjustEndianess32((LPBYTE) &Count);
187.2557 -
187.2558 -    if (Count > 1000) {
187.2559 -         return NULL;
187.2560 +        // Floating point LUT are always V4, so no adjustment is required
187.2561 +        return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
187.2562      }
187.2563  
187.2564 -    size = sizeof(int) + Count * sizeof(cmsPSEQDESC);
187.2565 -    OutSeq = (LPcmsSEQ) _cmsMalloc(size);
187.2566 -    if (OutSeq == NULL) return NULL;
187.2567 -
187.2568 -    OutSeq ->n = Count;
187.2569 -
187.2570 -    // Get structures as well
187.2571 -
187.2572 -    for (i=0; i < Count; i++) {
187.2573 -
187.2574 -        LPcmsPSEQDESC sec = &OutSeq -> seq[i];
187.2575 -
187.2576 -        Icc -> Read(&DescStruct, sizeof(icDescStruct) - SIZEOF_UINT8_ALIGNED, 1, Icc);
187.2577 -
187.2578 -        AdjustEndianess32((LPBYTE) &DescStruct.deviceMfg);
187.2579 -        AdjustEndianess32((LPBYTE) &DescStruct.deviceModel);
187.2580 -        AdjustEndianess32((LPBYTE) &DescStruct.technology);
187.2581 -        AdjustEndianess32((LPBYTE) &DescStruct.attributes[0]);
187.2582 -        AdjustEndianess32((LPBYTE) &DescStruct.attributes[1]);
187.2583 -
187.2584 -        sec ->attributes[0] = DescStruct.attributes[0];
187.2585 -        sec ->attributes[1] = DescStruct.attributes[1];
187.2586 -        sec ->deviceMfg     = DescStruct.deviceMfg;
187.2587 -        sec ->deviceModel   = DescStruct.deviceModel;
187.2588 -        sec ->technology    = DescStruct.technology;
187.2589 -
187.2590 -        if (ReadEmbeddedTextTag(Icc, size, sec ->Manufacturer, LCMS_DESC_MAX) < 0) return NULL;
187.2591 -        if (ReadEmbeddedTextTag(Icc, size, sec ->Model, LCMS_DESC_MAX) < 0) return NULL;
187.2592 -
187.2593 +    // Revert to perceptual if no tag is found
187.2594 +    if (!cmsIsTag(hProfile, tag16)) {
187.2595 +        tag16 = Device2PCS16[0];
187.2596      }
187.2597  
187.2598 -    return OutSeq;
187.2599 +    if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
187.2600 +
187.2601 +        // Check profile version and LUT type. Do the necessary adjustments if needed
187.2602 +
187.2603 +        // First read the tag
187.2604 +        cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
187.2605 +        if (Lut == NULL) return NULL;
187.2606 +
187.2607 +        // After reading it, we have now info about the original type
187.2608 +        OriginalType =  _cmsGetTagTrueType(hProfile, tag16);
187.2609 +
187.2610 +        // The profile owns the Lut, so we need to copy it
187.2611 +        Lut = cmsPipelineDup(Lut);
187.2612 +
187.2613 +        // We need to adjust data only for Lab16 on output
187.2614 +        if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
187.2615 +            return Lut;
187.2616 +
187.2617 +        // Add a matrix for conversion V2 to V4 Lab PCS
187.2618 +        cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
187.2619 +        return Lut;
187.2620 +    }
187.2621 +
187.2622 +    // Lut was not found, try to create a matrix-shaper
187.2623 +
187.2624 +    // Check if this is a grayscale profile.
187.2625 +    if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
187.2626 +
187.2627 +        // if so, build appropiate conversion tables.
187.2628 +        // The tables are the PCS iluminant, scaled across GrayTRC
187.2629 +        return BuildGrayInputMatrixPipeline(hProfile);
187.2630 +    }
187.2631 +
187.2632 +    // Not gray, create a normal matrix-shaper
187.2633 +    return BuildRGBInputMatrixShaper(hProfile);
187.2634  }
187.2635  
187.2636 +// ---------------------------------------------------------------------------------------------------------------
187.2637  
187.2638 -void LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq)
187.2639 +// Gray output pipeline.
187.2640 +// XYZ -> Gray or Lab -> Gray. Since we only know the GrayTRC, we need to do some assumptions. Gray component will be
187.2641 +// given by Y on XYZ PCS and by L* on Lab PCS, Both across inverse TRC curve.
187.2642 +// The complete pipeline on XYZ is Matrix[3:1] -> Tone curve and in Lab Matrix[3:1] -> Tone Curve as well.
187.2643 +
187.2644 +static
187.2645 +cmsPipeline* BuildGrayOutputPipeline(cmsHPROFILE hProfile)
187.2646  {
187.2647 -    if (pseq)
187.2648 -        _cmsFree(pseq);
187.2649 +    cmsToneCurve *GrayTRC, *RevGrayTRC;
187.2650 +    cmsPipeline* Lut;
187.2651 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
187.2652 +
187.2653 +    GrayTRC = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGrayTRCTag);
187.2654 +    if (GrayTRC == NULL) return NULL;
187.2655 +
187.2656 +    RevGrayTRC = cmsReverseToneCurve(GrayTRC);
187.2657 +    if (RevGrayTRC == NULL) return NULL;
187.2658 +
187.2659 +    Lut = cmsPipelineAlloc(ContextID, 3, 1);
187.2660 +    if (Lut == NULL) {
187.2661 +        cmsFreeToneCurve(RevGrayTRC);
187.2662 +        return NULL;
187.2663 +    }
187.2664 +
187.2665 +    if (cmsGetPCS(hProfile) == cmsSigLabData) {
187.2666 +
187.2667 +        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1,  3, PickLstarMatrix, NULL));
187.2668 +    }
187.2669 +    else  {
187.2670 +        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 1,  3, PickYMatrix, NULL));
187.2671 +    }
187.2672 +
187.2673 +    cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 1, &RevGrayTRC));
187.2674 +    cmsFreeToneCurve(RevGrayTRC);
187.2675 +
187.2676 +    return Lut;
187.2677  }
187.2678  
187.2679  
187.2680  
187.2681  
187.2682 +static
187.2683 +cmsPipeline* BuildRGBOutputMatrixShaper(cmsHPROFILE hProfile)
187.2684 +{
187.2685 +    cmsPipeline* Lut;
187.2686 +    cmsToneCurve *Shapes[3], *InvShapes[3];
187.2687 +    cmsMAT3 Mat, Inv;
187.2688 +    int i, j;
187.2689 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
187.2690  
187.2691 -// Read a few tags that are hardly required
187.2692 +    if (!ReadICCMatrixRGB2XYZ(&Mat, hProfile))
187.2693 +        return NULL;
187.2694  
187.2695 +    if (!_cmsMAT3inverse(&Mat, &Inv))
187.2696 +        return NULL;
187.2697  
187.2698 -static
187.2699 -void ReadCriticalTags(LPLCMSICCPROFILE Icc)
187.2700 +    // XYZ PCS in encoded in 1.15 format, and the matrix input should come in 0..0xffff range, so
187.2701 +    // we need to adjust the input by a << 1 to obtain a 1.16 fixed and then by a factor of
187.2702 +    // (0xffff/0x10000) to put data in 0..0xffff range. Total factor is (2.0*65535.0)/65536.0;
187.2703 +
187.2704 +    for (i=0; i < 3; i++)
187.2705 +        for (j=0; j < 3; j++)
187.2706 +            Inv.v[i].n[j] *= OutpAdj;
187.2707 +
187.2708 +    Shapes[0] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigRedTRCTag);
187.2709 +    Shapes[1] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigGreenTRCTag);
187.2710 +    Shapes[2] = (cmsToneCurve *) cmsReadTag(hProfile, cmsSigBlueTRCTag);
187.2711 +
187.2712 +    if (!Shapes[0] || !Shapes[1] || !Shapes[2])
187.2713 +        return NULL;
187.2714 +
187.2715 +    InvShapes[0] = cmsReverseToneCurve(Shapes[0]);
187.2716 +    InvShapes[1] = cmsReverseToneCurve(Shapes[1]);
187.2717 +    InvShapes[2] = cmsReverseToneCurve(Shapes[2]);
187.2718 +
187.2719 +    if (!InvShapes[0] || !InvShapes[1] || !InvShapes[2]) {
187.2720 +        return NULL;
187.2721 +    }
187.2722 +
187.2723 +    Lut = cmsPipelineAlloc(ContextID, 3, 3);
187.2724 +    if (Lut != NULL) {
187.2725 +
187.2726 +        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocMatrix(ContextID, 3, 3, (cmsFloat64Number*) &Inv, NULL));
187.2727 +        cmsPipelineInsertStage(Lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, 3, InvShapes));
187.2728 +    }
187.2729 +
187.2730 +    cmsFreeToneCurveTriple(InvShapes);
187.2731 +    return Lut;
187.2732 +}
187.2733 +
187.2734 +// Create an output MPE LUT from agiven profile. Version mismatches are handled here
187.2735 +cmsPipeline* _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent)
187.2736  {
187.2737 -    cmsHPROFILE hProfile = (cmsHPROFILE) Icc;
187.2738 +    cmsTagTypeSignature OriginalType;
187.2739 +    cmsTagSignature tag16    = PCS2Device16[Intent];
187.2740 +    cmsTagSignature tagFloat = PCS2DeviceFloat[Intent];
187.2741 +    cmsContext ContextID     = cmsGetProfileContextID(hProfile);
187.2742  
187.2743 -    if (Icc ->Version >= 0x4000000) {
187.2744 +    if (cmsIsTag(hProfile, tagFloat)) {  // Float tag takes precedence
187.2745  
187.2746 -        // v4 profiles
187.2747 +        // Floating point LUT are always V4, so no adjustment is required
187.2748 +        return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
187.2749 +    }
187.2750  
187.2751 -        MAT3 ChrmCanonical;
187.2752 +    // Revert to perceptual if no tag is found
187.2753 +    if (!cmsIsTag(hProfile, tag16)) {
187.2754 +        tag16 = PCS2Device16[0];
187.2755 +    }
187.2756  
187.2757 -         if (ReadICCXYZ(hProfile,
187.2758 -                      icSigMediaWhitePointTag,
187.2759 -                      &Icc ->MediaWhitePoint, FALSE) < 0) {
187.2760 +    if (cmsIsTag(hProfile, tag16)) { // Is there any LUT-Based table?
187.2761  
187.2762 -              Icc ->MediaWhitePoint = *cmsD50_XYZ();
187.2763 -       }
187.2764 +        // Check profile version and LUT type. Do the necessary adjustments if needed
187.2765  
187.2766 -       // Read media black
187.2767 +        // First read the tag
187.2768 +        cmsPipeline* Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
187.2769 +        if (Lut == NULL) return NULL;
187.2770  
187.2771 -       if (ReadICCXYZ(hProfile,
187.2772 -                      icSigMediaBlackPointTag,
187.2773 -                      &Icc ->MediaBlackPoint, FALSE) < 0) {
187.2774 +        // After reading it, we have info about the original type
187.2775 +        OriginalType =  _cmsGetTagTrueType(hProfile, tag16);
187.2776  
187.2777 -              Icc ->MediaBlackPoint.X = 0;
187.2778 -              Icc ->MediaBlackPoint.Y = 0;
187.2779 -              Icc ->MediaBlackPoint.X = 0;
187.2780 +        // The profile owns the Lut, so we need to copy it
187.2781 +        Lut = cmsPipelineDup(Lut);
187.2782  
187.2783 -       }
187.2784 +        // We need to adjust data only for Lab and Lut16 type
187.2785 +        if (OriginalType != cmsSigLut16Type || cmsGetPCS(hProfile) != cmsSigLabData)
187.2786 +            return Lut;
187.2787  
187.2788 -       NormalizeXYZ(&Icc ->MediaWhitePoint);
187.2789 -       NormalizeXYZ(&Icc ->MediaBlackPoint);
187.2790 +        // Add a matrix for conversion V4 to V2 Lab PCS
187.2791 +        cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
187.2792 +        return Lut;
187.2793 +    }
187.2794  
187.2795 -      if (ReadICCXYZArray(hProfile,
187.2796 -                                icSigChromaticAdaptationTag,
187.2797 -                                &ChrmCanonical) > 0) {
187.2798 +    // Lut not found, try to create a matrix-shaper
187.2799  
187.2800 -                MAT3inverse(&ChrmCanonical, &Icc ->ChromaticAdaptation);
187.2801 +    // Check if this is a grayscale profile.
187.2802 +     if (cmsGetColorSpace(hProfile) == cmsSigGrayData) {
187.2803  
187.2804 -      }
187.2805 -      else {
187.2806 +              // if so, build appropiate conversion tables.
187.2807 +              // The tables are the PCS iluminant, scaled across GrayTRC
187.2808 +              return BuildGrayOutputPipeline(hProfile);
187.2809 +    }
187.2810  
187.2811 -                MAT3identity(&Icc ->ChromaticAdaptation);
187.2812 -      }
187.2813 +    // Not gray, create a normal matrix-shaper
187.2814 +    return BuildRGBOutputMatrixShaper(hProfile);
187.2815 +}
187.2816  
187.2817 +// ---------------------------------------------------------------------------------------------------------------
187.2818  
187.2819 -      // Convert media white, black to absolute under original illuminant
187.2820 +// This one includes abstract profiles as well. Matrix-shaper cannot be obtained on that device class. The
187.2821 +// tag name here may default to AToB0
187.2822 +cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent)
187.2823 +{
187.2824 +    cmsPipeline* Lut;
187.2825 +    cmsTagTypeSignature OriginalType;
187.2826 +    cmsTagSignature tag16    = Device2PCS16[Intent];
187.2827 +    cmsTagSignature tagFloat = Device2PCSFloat[Intent];
187.2828 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
187.2829  
187.2830 -      EvalCHRM(&Icc ->MediaWhitePoint, &Icc ->ChromaticAdaptation, &Icc ->MediaWhitePoint);
187.2831 -      EvalCHRM(&Icc ->MediaBlackPoint, &Icc ->ChromaticAdaptation, &Icc ->MediaBlackPoint);
187.2832 +    if (cmsIsTag(hProfile, tagFloat)) {  // Float tag takes precedence
187.2833  
187.2834 +        // Floating point LUT are always V4, no adjustment is required
187.2835 +        return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
187.2836 +    }
187.2837  
187.2838 +    tagFloat = Device2PCSFloat[0];
187.2839 +    if (cmsIsTag(hProfile, tagFloat)) {
187.2840 +
187.2841 +        return cmsPipelineDup((cmsPipeline*) cmsReadTag(hProfile, tagFloat));
187.2842      }
187.2843 -    else {
187.2844  
187.2845 -        // v2 profiles
187.2846 +    if (!cmsIsTag(hProfile, tag16)) {  // Is there any LUT-Based table?
187.2847  
187.2848 -       // Read media white
187.2849 +        tag16    = Device2PCS16[0];
187.2850 +        if (!cmsIsTag(hProfile, tag16)) return NULL;
187.2851 +    }
187.2852  
187.2853 -       if (ReadICCXYZ(hProfile,
187.2854 -                      icSigMediaWhitePointTag,
187.2855 -                      &Icc ->MediaWhitePoint, FALSE) < 0) {
187.2856 +    // Check profile version and LUT type. Do the necessary adjustments if needed
187.2857  
187.2858 -              Icc ->MediaWhitePoint = *cmsD50_XYZ();
187.2859 -       }
187.2860 +    // Read the tag
187.2861 +    Lut = (cmsPipeline*) cmsReadTag(hProfile, tag16);
187.2862 +    if (Lut == NULL) return NULL;
187.2863  
187.2864 -       // Read media black
187.2865 +    // The profile owns the Lut, so we need to copy it
187.2866 +    Lut = cmsPipelineDup(Lut);
187.2867  
187.2868 -       if (ReadICCXYZ(hProfile,
187.2869 -                      icSigMediaBlackPointTag,
187.2870 -                      &Icc ->MediaBlackPoint, FALSE) < 0) {
187.2871 +    // After reading it, we have info about the original type
187.2872 +    OriginalType =  _cmsGetTagTrueType(hProfile, tag16);
187.2873  
187.2874 -              Icc ->MediaBlackPoint.X = 0;
187.2875 -              Icc ->MediaBlackPoint.Y = 0;
187.2876 -              Icc ->MediaBlackPoint.X = 0;
187.2877 +    // We need to adjust data for Lab16 on output
187.2878 +    if (OriginalType != cmsSigLut16Type) return Lut;
187.2879  
187.2880 -       }
187.2881 +    // Here it is possible to get Lab on both sides
187.2882  
187.2883 -       NormalizeXYZ(&Icc ->MediaWhitePoint);
187.2884 -       NormalizeXYZ(&Icc ->MediaBlackPoint);
187.2885 +    if (cmsGetPCS(hProfile) == cmsSigLabData) {
187.2886 +            cmsPipelineInsertStage(Lut, cmsAT_BEGIN, _cmsStageAllocLabV4ToV2(ContextID));
187.2887 +    }
187.2888  
187.2889 +    if (cmsGetColorSpace(hProfile) == cmsSigLabData) {
187.2890 +            cmsPipelineInsertStage(Lut, cmsAT_END, _cmsStageAllocLabV2ToV4(ContextID));
187.2891 +    }
187.2892  
187.2893 -       // Take Bradford as default for Display profiles only.
187.2894 +    return Lut;
187.2895  
187.2896 -       if (cmsGetDeviceClass(hProfile) == icSigDisplayClass) {
187.2897 -
187.2898 -
187.2899 -            cmsAdaptationMatrix(&Icc -> ChromaticAdaptation,
187.2900 -                                NULL,
187.2901 -                                &Icc -> Illuminant,
187.2902 -                                &Icc -> MediaWhitePoint);
187.2903 -       }
187.2904 -       else
187.2905 -            MAT3identity(&Icc ->ChromaticAdaptation);
187.2906 -
187.2907 -    }
187.2908  
187.2909  }
187.2910  
187.2911 +// ---------------------------------------------------------------------------------------------------------------
187.2912  
187.2913 -// Create profile from disk file
187.2914 +// Returns TRUE if the profile is implemented as matrix-shaper
187.2915 +cmsBool  CMSEXPORT cmsIsMatrixShaper(cmsHPROFILE hProfile)
187.2916 +{
187.2917 +    switch (cmsGetColorSpace(hProfile)) {
187.2918  
187.2919 -cmsHPROFILE LCMSEXPORT cmsOpenProfileFromFile(const char *lpFileName, const char *sAccess)
187.2920 -{
187.2921 -       LPLCMSICCPROFILE NewIcc;
187.2922 -       cmsHPROFILE hEmpty;
187.2923 +    case cmsSigGrayData:
187.2924  
187.2925 +        return cmsIsTag(hProfile, cmsSigGrayTRCTag);
187.2926  
187.2927 -       // Open for write means an empty profile
187.2928 +    case cmsSigRgbData:
187.2929  
187.2930 -       if (*sAccess == 'W' || *sAccess == 'w') {
187.2931 +        return (cmsIsTag(hProfile, cmsSigRedColorantTag) &&
187.2932 +                cmsIsTag(hProfile, cmsSigGreenColorantTag) &&
187.2933 +                cmsIsTag(hProfile, cmsSigBlueColorantTag) &&
187.2934 +                cmsIsTag(hProfile, cmsSigRedTRCTag) &&
187.2935 +                cmsIsTag(hProfile, cmsSigGreenTRCTag) &&
187.2936 +                cmsIsTag(hProfile, cmsSigBlueTRCTag));
187.2937  
187.2938 -           hEmpty = _cmsCreateProfilePlaceholder();
187.2939 -           NewIcc = (LPLCMSICCPROFILE) (LPSTR) hEmpty;
187.2940 -           NewIcc -> IsWrite = TRUE;
187.2941 -           strncpy(NewIcc ->PhysicalFile, lpFileName, MAX_PATH-1);
187.2942 -           NewIcc ->PhysicalFile[MAX_PATH-1] = 0;
187.2943 +    default:
187.2944  
187.2945 -           // Save LUT as 8 bit
187.2946 -
187.2947 -           sAccess++;
187.2948 -           if (*sAccess == '8') NewIcc ->SaveAs8Bits = TRUE;
187.2949 -
187.2950 -           return hEmpty;
187.2951 -       }
187.2952 -
187.2953 -
187.2954 -       // Open for read means a file placeholder
187.2955 -
187.2956 -       NewIcc = _cmsCreateProfileFromFilePlaceholder(lpFileName);
187.2957 -        if (!NewIcc) return NULL;
187.2958 -
187.2959 -       if (!ReadHeader(NewIcc, FALSE)) return NULL;
187.2960 -
187.2961 -       ReadCriticalTags(NewIcc);
187.2962 -
187.2963 -       return (cmsHPROFILE) (LPSTR) NewIcc;
187.2964 +        return FALSE;
187.2965 +    }
187.2966  }
187.2967  
187.2968 +// Returns TRUE if the intent is implemented as CLUT
187.2969 +cmsBool  CMSEXPORT cmsIsCLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent, int UsedDirection)
187.2970 +{
187.2971 +    const cmsTagSignature* TagTable;
187.2972  
187.2973 +    // For devicelinks, the supported intent is that one stated in the header
187.2974 +    if (cmsGetDeviceClass(hProfile) == cmsSigLinkClass) {
187.2975 +            return (cmsGetHeaderRenderingIntent(hProfile) == Intent);
187.2976 +    }
187.2977  
187.2978 +    switch (UsedDirection) {
187.2979  
187.2980 -// Open from memory block
187.2981 +       case LCMS_USED_AS_INPUT: TagTable = Device2PCS16; break;
187.2982 +       case LCMS_USED_AS_OUTPUT:TagTable = PCS2Device16; break;
187.2983  
187.2984 -cmsHPROFILE LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize)
187.2985 -{
187.2986 -       LPLCMSICCPROFILE NewIcc;
187.2987 +       // For proofing, we need rel. colorimetric in output. Let's do some recursion
187.2988 +       case LCMS_USED_AS_PROOF:
187.2989 +           return cmsIsIntentSupported(hProfile, Intent, LCMS_USED_AS_INPUT) &&
187.2990 +                  cmsIsIntentSupported(hProfile, INTENT_RELATIVE_COLORIMETRIC, LCMS_USED_AS_OUTPUT);
187.2991  
187.2992 +       default:
187.2993 +           cmsSignalError(cmsGetProfileContextID(hProfile), cmsERROR_RANGE, "Unexpected direction (%d)", UsedDirection);
187.2994 +           return FALSE;
187.2995 +    }
187.2996  
187.2997 -       NewIcc = _cmsCreateProfileFromMemPlaceholder(MemPtr, dwSize);
187.2998 -       if (!NewIcc) return NULL;
187.2999 -
187.3000 -       if (!ReadHeader(NewIcc, TRUE)) return NULL;
187.3001 -
187.3002 -       ReadCriticalTags(NewIcc);
187.3003 -
187.3004 -       return (cmsHPROFILE) (LPSTR) NewIcc;
187.3005 +    return cmsIsTag(hProfile, TagTable[Intent]);
187.3006  
187.3007  }
187.3008  
187.3009  
187.3010 +// Return info about supported intents
187.3011 +cmsBool  CMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
187.3012 +                                        cmsUInt32Number Intent, int UsedDirection)
187.3013 +{
187.3014  
187.3015 -LCMSBOOL LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile)
187.3016 -{
187.3017 -       LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.3018 -       LCMSBOOL rc = TRUE;
187.3019 -       icInt32Number i;
187.3020 +    if (cmsIsCLUT(hProfile, Intent, UsedDirection)) return TRUE;
187.3021  
187.3022 -       if (!Icc) return FALSE;
187.3023 +    // Is there any matrix-shaper? If so, the intent is supported. This is a bit odd, since V2 matrix shaper
187.3024 +    // does not fully support relative colorimetric because they cannot deal with non-zero black points, but
187.3025 +    // many profiles claims that, and this is certainly not true for V4 profiles. Lets answer "yes" no matter
187.3026 +    // the accuracy would be less than optimal in rel.col and v2 case.
187.3027  
187.3028 -       // Was open in write mode?
187.3029 -       if (Icc ->IsWrite) {
187.3030 -
187.3031 -           Icc ->IsWrite = FALSE;      // Assure no further writting
187.3032 -           rc = _cmsSaveProfile(hProfile, Icc ->PhysicalFile);
187.3033 -       }
187.3034 -
187.3035 -       for (i=0; i < Icc -> TagCount; i++) {
187.3036 -
187.3037 -                  if (Icc -> TagPtrs[i])
187.3038 -                            free(Icc -> TagPtrs[i]);
187.3039 -       }
187.3040 -
187.3041 -       if (Icc -> stream != NULL) {     // Was a memory (i.e. not serialized) profile?
187.3042 -                 Icc -> Close(Icc);     // No, close the stream
187.3043 -       }
187.3044 -
187.3045 -       free(Icc);   // Free placeholder memory
187.3046 -
187.3047 -       return rc;
187.3048 +    return cmsIsMatrixShaper(hProfile);
187.3049  }
187.3050  
187.3051  
187.3052 +// ---------------------------------------------------------------------------------------------------------------
187.3053  
187.3054 -// Write profile ------------------------------------------------------------
187.3055 +// Read both, profile sequence description and profile sequence id if present. Then combine both to
187.3056 +// create qa unique structure holding both. Shame on ICC to store things in such complicated way.
187.3057  
187.3058 +cmsSEQ* _cmsReadProfileSequence(cmsHPROFILE hProfile)
187.3059 +{
187.3060 +    cmsSEQ* ProfileSeq;
187.3061 +    cmsSEQ* ProfileId;
187.3062 +    cmsSEQ* NewSeq;
187.3063 +    cmsUInt32Number i;
187.3064  
187.3065 +    // Take profile sequence description first
187.3066 +    ProfileSeq = (cmsSEQ*) cmsReadTag(hProfile, cmsSigProfileSequenceDescTag);
187.3067  
187.3068 -static
187.3069 -LCMSBOOL SaveWordsTable(int nEntries, LPWORD Tab, LPLCMSICCPROFILE Icc)
187.3070 -{
187.3071 -   size_t nTabSize = sizeof(WORD) * nEntries;
187.3072 -   LPWORD PtrW = (LPWORD) _cmsMalloc(nTabSize);
187.3073 -   LCMSBOOL rc;
187.3074 +    // Take profile sequence ID
187.3075 +    ProfileId  = (cmsSEQ*) cmsReadTag(hProfile, cmsSigProfileSequenceIdTag);
187.3076  
187.3077 -   if (!PtrW) return FALSE;
187.3078 -   CopyMemory(PtrW, Tab, nTabSize);
187.3079 -   AdjustEndianessArray16(PtrW, nEntries);
187.3080 -   rc = Icc ->Write(Icc, nTabSize, PtrW);
187.3081 -   free(PtrW);
187.3082 +    if (ProfileSeq == NULL && ProfileId == NULL) return NULL;
187.3083  
187.3084 -   return rc;
187.3085 +    if (ProfileSeq == NULL) return cmsDupProfileSequenceDescription(ProfileId);
187.3086 +    if (ProfileId  == NULL) return cmsDupProfileSequenceDescription(ProfileSeq);
187.3087 +
187.3088 +    // We have to mix both together. For that they must agree
187.3089 +    if (ProfileSeq ->n != ProfileId ->n) return cmsDupProfileSequenceDescription(ProfileSeq);
187.3090 +
187.3091 +    NewSeq = cmsDupProfileSequenceDescription(ProfileSeq);
187.3092 +
187.3093 +    // Ok, proceed to the mixing
187.3094 +    for (i=0; i < ProfileSeq ->n; i++) {
187.3095 +
187.3096 +        memmove(&NewSeq ->seq[i].ProfileID, &ProfileId ->seq[i].ProfileID, sizeof(cmsProfileID));
187.3097 +        NewSeq ->seq[i].Description = cmsMLUdup(ProfileId ->seq[i].Description);
187.3098 +    }
187.3099 +
187.3100 +    return NewSeq;
187.3101  }
187.3102  
187.3103 +// Dump the contents of profile sequence in both tags (if v4 available)
187.3104 +cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq)
187.3105 +{
187.3106 +    if (!cmsWriteTag(hProfile, cmsSigProfileSequenceDescTag, seq)) return FALSE;
187.3107  
187.3108 +    if (cmsGetProfileVersion(hProfile) >= 4.0) {
187.3109  
187.3110 -// Saves profile header
187.3111 -
187.3112 -static
187.3113 -LCMSBOOL SaveHeader(LPLCMSICCPROFILE Icc)
187.3114 -{
187.3115 -  icHeader Header;
187.3116 -  time_t now = time(NULL);
187.3117 -
187.3118 -       Header.size        = TransportValue32((icInt32Number) Icc ->UsedSpace);
187.3119 -       Header.cmmId       = TransportValue32(lcmsSignature);
187.3120 -       Header.version     = TransportValue32((icInt32Number) 0x02300000);
187.3121 -       Header.deviceClass = (icProfileClassSignature) TransportValue32(Icc -> DeviceClass);
187.3122 -       Header.colorSpace  = (icColorSpaceSignature) TransportValue32(Icc -> ColorSpace);
187.3123 -       Header.pcs         = (icColorSpaceSignature) TransportValue32(Icc -> PCS);
187.3124 -
187.3125 -       //   NOTE: in v4 Timestamp must be in UTC rather than in local time
187.3126 -       EncodeDateTimeNumber(&Header.date, gmtime(&now));
187.3127 -
187.3128 -       Header.magic       = TransportValue32(icMagicNumber);
187.3129 -
187.3130 -#ifdef NON_WINDOWS
187.3131 -       Header.platform    = (icPlatformSignature)TransportValue32(icSigMacintosh);
187.3132 -#else
187.3133 -       Header.platform    = (icPlatformSignature)TransportValue32(icSigMicrosoft);
187.3134 -#endif
187.3135 -
187.3136 -       Header.flags        = TransportValue32(Icc -> flags);
187.3137 -       Header.manufacturer = TransportValue32(lcmsSignature);
187.3138 -       Header.model        = TransportValue32(0);
187.3139 -       Header.attributes[0]= TransportValue32(Icc -> attributes);
187.3140 -       Header.attributes[1]= TransportValue32(0);
187.3141 -
187.3142 -       Header.renderingIntent = TransportValue32(Icc -> RenderingIntent);
187.3143 -
187.3144 -       // Illuminant is D50
187.3145 -
187.3146 -       Header.illuminant.X = TransportValue32(DOUBLE_TO_FIXED(Icc -> Illuminant.X));
187.3147 -       Header.illuminant.Y = TransportValue32(DOUBLE_TO_FIXED(Icc -> Illuminant.Y));
187.3148 -       Header.illuminant.Z = TransportValue32(DOUBLE_TO_FIXED(Icc -> Illuminant.Z));
187.3149 -
187.3150 -       Header.creator      = TransportValue32(lcmsSignature);
187.3151 -
187.3152 -       ZeroMemory(&Header.reserved, sizeof(Header.reserved));
187.3153 -
187.3154 -       // Set profile ID
187.3155 -       CopyMemory(Header.reserved, Icc ->ProfileID, 16);
187.3156 -
187.3157 -
187.3158 -       Icc ->UsedSpace = 0; // Mark as begin-of-file
187.3159 -
187.3160 -       return Icc ->Write(Icc, sizeof(icHeader), &Header);
187.3161 -}
187.3162 -
187.3163 -
187.3164 -
187.3165 -// Setup base marker
187.3166 -
187.3167 -static
187.3168 -LCMSBOOL SetupBase(icTagTypeSignature sig, LPLCMSICCPROFILE Icc)
187.3169 -{
187.3170 -    icTagBase  Base;
187.3171 -
187.3172 -    Base.sig = (icTagTypeSignature) TransportValue32(sig);
187.3173 -    ZeroMemory(&Base.reserved, sizeof(Base.reserved));
187.3174 -    return Icc -> Write(Icc, sizeof(icTagBase), &Base);
187.3175 -}
187.3176 -
187.3177 -
187.3178 -// Store a XYZ tag
187.3179 -
187.3180 -static
187.3181 -LCMSBOOL SaveXYZNumber(LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
187.3182 -{
187.3183 -
187.3184 -    icXYZNumber XYZ;
187.3185 -
187.3186 -    if (!SetupBase(icSigXYZType, Icc)) return FALSE;
187.3187 -
187.3188 -    XYZ.X = TransportValue32(DOUBLE_TO_FIXED(Value -> X));
187.3189 -    XYZ.Y = TransportValue32(DOUBLE_TO_FIXED(Value -> Y));
187.3190 -    XYZ.Z = TransportValue32(DOUBLE_TO_FIXED(Value -> Z));
187.3191 -
187.3192 -
187.3193 -    return Icc -> Write(Icc, sizeof(icXYZNumber), &XYZ);
187.3194 -}
187.3195 -
187.3196 -
187.3197 -// Store a XYZ array.
187.3198 -
187.3199 -static
187.3200 -LCMSBOOL SaveXYZArray(int n, LPcmsCIEXYZ Value, LPLCMSICCPROFILE Icc)
187.3201 -{
187.3202 -    int i;
187.3203 -    icXYZNumber XYZ;
187.3204 -
187.3205 -    if (!SetupBase(icSigS15Fixed16ArrayType, Icc)) return FALSE;
187.3206 -
187.3207 -    for (i=0; i < n; i++) {
187.3208 -
187.3209 -        XYZ.X = TransportValue32(DOUBLE_TO_FIXED(Value -> X));
187.3210 -        XYZ.Y = TransportValue32(DOUBLE_TO_FIXED(Value -> Y));
187.3211 -        XYZ.Z = TransportValue32(DOUBLE_TO_FIXED(Value -> Z));
187.3212 -
187.3213 -        if (!Icc -> Write(Icc, sizeof(icXYZNumber), &XYZ)) return FALSE;
187.3214 -
187.3215 -        Value++;
187.3216 +            if (!cmsWriteTag(hProfile, cmsSigProfileSequenceIdTag, seq)) return FALSE;
187.3217      }
187.3218  
187.3219      return TRUE;
187.3220  }
187.3221  
187.3222  
187.3223 +// Auxiliar, read and duplicate a MLU if found.
187.3224 +static
187.3225 +cmsMLU* GetMLUFromProfile(cmsHPROFILE h, cmsTagSignature sig)
187.3226 +{
187.3227 +    cmsMLU* mlu = (cmsMLU*) cmsReadTag(h, sig);
187.3228 +    if (mlu == NULL) return NULL;
187.3229  
187.3230 -// Save a gamma structure as a table
187.3231 +    return cmsMLUdup(mlu);
187.3232 +}
187.3233 +
187.3234 +// Create a sequence description out of an array of profiles
187.3235 +cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[])
187.3236 +{
187.3237 +    cmsUInt32Number i;
187.3238 +    cmsSEQ* seq = cmsAllocProfileSequenceDescription(ContextID, nProfiles);
187.3239 +
187.3240 +    if (seq == NULL) return NULL;
187.3241 +
187.3242 +    for (i=0; i < nProfiles; i++) {
187.3243 +
187.3244 +        cmsPSEQDESC* ps = &seq ->seq[i];
187.3245 +        cmsHPROFILE h = hProfiles[i];
187.3246 +        cmsTechnologySignature* techpt;
187.3247 +
187.3248 +        cmsGetHeaderAttributes(h, &ps ->attributes);
187.3249 +        cmsGetHeaderProfileID(h, ps ->ProfileID.ID8);
187.3250 +        ps ->deviceMfg   = cmsGetHeaderManufacturer(h);
187.3251 +        ps ->deviceModel = cmsGetHeaderModel(h);
187.3252 +
187.3253 +        techpt = (cmsTechnologySignature*) cmsReadTag(h, cmsSigTechnologyTag);
187.3254 +        if (techpt == NULL)
187.3255 +            ps ->technology   =  (cmsTechnologySignature) 0;
187.3256 +        else
187.3257 +            ps ->technology   = *techpt;
187.3258 +
187.3259 +        ps ->Manufacturer = GetMLUFromProfile(h,  cmsSigDeviceMfgDescTag);
187.3260 +        ps ->Model        = GetMLUFromProfile(h,  cmsSigDeviceModelDescTag);
187.3261 +        ps ->Description  = GetMLUFromProfile(h, cmsSigProfileDescriptionTag);
187.3262 +
187.3263 +    }
187.3264 +
187.3265 +    return seq;
187.3266 +}
187.3267 +
187.3268 +// -------------------------------------------------------------------------------------------------------------------
187.3269 +
187.3270  
187.3271  static
187.3272 -LCMSBOOL SaveGammaTable(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
187.3273 +const cmsMLU* GetInfo(cmsHPROFILE hProfile, cmsInfoType Info)
187.3274  {
187.3275 -    icInt32Number Count;
187.3276 +    cmsTagSignature sig;
187.3277  
187.3278 -        if (!SetupBase(icSigCurveType, Icc)) return FALSE;
187.3279 +    switch (Info) {
187.3280  
187.3281 -        Count = TransportValue32(Gamma->nEntries);
187.3282 +    case cmsInfoDescription:
187.3283 +        sig = cmsSigProfileDescriptionTag;
187.3284 +        break;
187.3285  
187.3286 -        if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
187.3287 +    case cmsInfoManufacturer:
187.3288 +        sig = cmsSigDeviceMfgDescTag;
187.3289 +        break;
187.3290  
187.3291 -        return SaveWordsTable(Gamma->nEntries, Gamma ->GammaTable, Icc);
187.3292 +    case cmsInfoModel:
187.3293 +        sig = cmsSigDeviceModelDescTag;
187.3294 +         break;
187.3295 +
187.3296 +    case cmsInfoCopyright:
187.3297 +        sig = cmsSigCopyrightTag;
187.3298 +        break;
187.3299 +
187.3300 +    default: return NULL;
187.3301 +    }
187.3302 +
187.3303 +
187.3304 +    return (cmsMLU*) cmsReadTag(hProfile, sig);
187.3305  }
187.3306  
187.3307  
187.3308 -// Save a gamma structure as a one-value
187.3309  
187.3310 -static
187.3311 -LCMSBOOL SaveGammaOneValue(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
187.3312 +cmsUInt32Number CMSEXPORT cmsGetProfileInfo(cmsHPROFILE hProfile, cmsInfoType Info,
187.3313 +                                            const char LanguageCode[3], const char CountryCode[3],
187.3314 +                                            wchar_t* Buffer, cmsUInt32Number BufferSize)
187.3315  {
187.3316 -    icInt32Number Count;
187.3317 -    Fixed32 GammaFixed32;
187.3318 -    WORD    GammaFixed8;
187.3319 +    const cmsMLU* mlu = GetInfo(hProfile, Info);
187.3320 +    if (mlu == NULL) return 0;
187.3321  
187.3322 -        if (!SetupBase(icSigCurveType, Icc)) return FALSE;
187.3323 -
187.3324 -        Count = TransportValue32(1);
187.3325 -        if (!Icc ->Write(Icc, sizeof(icInt32Number), &Count)) return FALSE;
187.3326 -
187.3327 -        GammaFixed32 = DOUBLE_TO_FIXED(Gamma ->Seed.Params[0]);
187.3328 -        GammaFixed8  = (WORD) ((GammaFixed32 >> 8) & 0xFFFF);
187.3329 -        GammaFixed8  = TransportValue16(GammaFixed8);
187.3330 -
187.3331 -        return Icc ->Write(Icc, sizeof(icInt16Number), &GammaFixed8);
187.3332 +    return cmsMLUgetWide(mlu, LanguageCode, CountryCode, Buffer, BufferSize);
187.3333  }
187.3334  
187.3335 -// Save a gamma structure as a parametric gamma
187.3336  
187.3337 -static
187.3338 -LCMSBOOL SaveGammaParametric(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
187.3339 +cmsUInt32Number  CMSEXPORT cmsGetProfileInfoASCII(cmsHPROFILE hProfile, cmsInfoType Info,
187.3340 +                                                          const char LanguageCode[3], const char CountryCode[3],
187.3341 +                                                          char* Buffer, cmsUInt32Number BufferSize)
187.3342  {
187.3343 -    icUInt16Number Type, Reserved;
187.3344 -    int i, nParams;
187.3345 -    int ParamsByType[] = { 1, 3, 4, 5, 7 };
187.3346 +    const cmsMLU* mlu = GetInfo(hProfile, Info);
187.3347 +    if (mlu == NULL) return 0;
187.3348  
187.3349 -    if (!SetupBase(icSigParametricCurveType, Icc)) return FALSE;
187.3350 -
187.3351 -    nParams = ParamsByType[Gamma -> Seed.Type];
187.3352 -
187.3353 -    Type      = (icUInt16Number) TransportValue16((WORD) Gamma -> Seed. Type);
187.3354 -    Reserved  = (icUInt16Number) TransportValue16((WORD) 0);
187.3355 -
187.3356 -    Icc -> Write(Icc, sizeof(icInt16Number),  &Type);
187.3357 -    Icc -> Write(Icc, sizeof(icUInt16Number), &Reserved);
187.3358 -
187.3359 -    for (i=0; i < nParams; i++) {
187.3360 -
187.3361 -        icInt32Number val = TransportValue32(DOUBLE_TO_FIXED(Gamma -> Seed.Params[i]));
187.3362 -        Icc ->Write(Icc, sizeof(icInt32Number), &val);
187.3363 -    }
187.3364 -
187.3365 -
187.3366 -    return TRUE;
187.3367 -
187.3368 +    return cmsMLUgetASCII(mlu, LanguageCode, CountryCode, Buffer, BufferSize);
187.3369  }
187.3370 -
187.3371 -
187.3372 -// Save a gamma table
187.3373 -
187.3374 -static
187.3375 -LCMSBOOL SaveGamma(LPGAMMATABLE Gamma, LPLCMSICCPROFILE Icc)
187.3376 -{
187.3377 -        // Is the gamma curve type supported by ICC format?
187.3378 -
187.3379 -        if (Gamma -> Seed.Type < 0 || Gamma -> Seed.Type > 5 ||
187.3380 -
187.3381 -            // has been modified by user?
187.3382 -
187.3383 -            _cmsCrc32OfGammaTable(Gamma) != Gamma -> Seed.Crc32) {
187.3384 -
187.3385 -            return SaveGammaTable(Gamma, Icc);
187.3386 -        }
187.3387 -
187.3388 -        if (Gamma -> Seed.Type == 1) return SaveGammaOneValue(Gamma, Icc);
187.3389 -
187.3390 -        // Only v4 profiles are allowed to hold parametric curves
187.3391 -
187.3392 -        if (cmsGetProfileICCversion((cmsHPROFILE) Icc) >= 0x4000000)
187.3393 -                return SaveGammaParametric(Gamma, Icc);
187.3394 -
187.3395 -        // Defaults to save as table
187.3396 -
187.3397 -        return SaveGammaTable(Gamma, Icc);
187.3398 -
187.3399 -}
187.3400 -
187.3401 -
187.3402 -
187.3403 -
187.3404 -// Save an DESC Tag
187.3405 -
187.3406 -static
187.3407 -LCMSBOOL SaveDescription(const char *Text, LPLCMSICCPROFILE Icc)
187.3408 -{
187.3409 -
187.3410 -    icUInt32Number len, Count, TotalSize, AlignedSize;
187.3411 -    char Filler[256];
187.3412 -
187.3413 -    len = (icUInt32Number) (strlen(Text) + 1);
187.3414 -
187.3415 -    // * icInt8Number         desc[count]     * NULL terminated ascii string
187.3416 -    // * icUInt32Number       ucLangCode;     * UniCode language code
187.3417 -    // * icUInt32Number       ucCount;        * UniCode description length
187.3418 -    // * icInt16Number        ucDesc[ucCount];* The UniCode description
187.3419 -    // * icUInt16Number       scCode;         * ScriptCode code
187.3420 -    // * icUInt8Number        scCount;        * ScriptCode count
187.3421 -    // * icInt8Number         scDesc[67];     * ScriptCode Description
187.3422 -
187.3423 -    TotalSize = sizeof(icTagBase) + sizeof(icUInt32Number) + len +
187.3424 -                sizeof(icUInt32Number) + sizeof(icUInt32Number) +
187.3425 -                sizeof(icUInt16Number) + sizeof(icUInt8Number) + 67;
187.3426 -
187.3427 -    AlignedSize = TotalSize;  // Can be unaligned!!
187.3428 -
187.3429 -    if (!SetupBase(icSigTextDescriptionType, Icc)) return FALSE;
187.3430 -    AlignedSize -= sizeof(icTagBase);
187.3431 -
187.3432 -    Count = TransportValue32(len);
187.3433 -    if (!Icc ->Write(Icc, sizeof(icUInt32Number), &Count)) return FALSE;
187.3434 -    AlignedSize -= sizeof(icUInt32Number);
187.3435 -
187.3436 -    if (!Icc ->Write(Icc, len, (LPVOID)Text)) return FALSE;
187.3437 -    AlignedSize -= len;
187.3438 -
187.3439 -    if (AlignedSize < 0)
187.3440 -            AlignedSize = 0;
187.3441 -    if (AlignedSize > 255)
187.3442 -            AlignedSize = 255;
187.3443 -
187.3444 -    ZeroMemory(Filler, AlignedSize);
187.3445 -    if (!Icc ->Write(Icc, AlignedSize, Filler)) return FALSE;
187.3446 -
187.3447 -    return TRUE;
187.3448 -}
187.3449 -
187.3450 -// Save an ASCII Tag
187.3451 -
187.3452 -static
187.3453 -LCMSBOOL SaveText(const char *Text, LPLCMSICCPROFILE Icc)
187.3454 -{
187.3455 -    size_t len = strlen(Text) + 1;
187.3456 -
187.3457 -    if (!SetupBase(icSigTextType, Icc)) return FALSE;
187.3458 -    if (!Icc ->Write(Icc, len, (LPVOID) Text)) return FALSE;
187.3459 -    return TRUE;
187.3460 -}
187.3461 -
187.3462 -
187.3463 -// Save one of these new chromaticity values
187.3464 -
187.3465 -static
187.3466 -LCMSBOOL SaveOneChromaticity(double x, double y, LPLCMSICCPROFILE Icc)
187.3467 -{
187.3468 -       Fixed32 xf, yf;
187.3469 -
187.3470 -       xf = TransportValue32(DOUBLE_TO_FIXED(x));
187.3471 -       yf = TransportValue32(DOUBLE_TO_FIXED(y));
187.3472 -
187.3473 -       if (!Icc ->Write(Icc, sizeof(Fixed32), &xf)) return FALSE;
187.3474 -       if (!Icc ->Write(Icc, sizeof(Fixed32), &yf)) return FALSE;
187.3475 -
187.3476 -       return TRUE;
187.3477 -}
187.3478 -
187.3479 -
187.3480 -// New tag added in Addendum II of old spec.
187.3481 -
187.3482 -static
187.3483 -LCMSBOOL SaveChromaticities(LPcmsCIExyYTRIPLE chrm, LPLCMSICCPROFILE Icc)
187.3484 -{
187.3485 -       WORD nChans, Table;
187.3486 -
187.3487 -       if (!SetupBase(icSigChromaticityType, Icc)) return FALSE;
187.3488 -
187.3489 -       nChans = TransportValue16(3);
187.3490 -       if (!Icc ->Write(Icc, sizeof(WORD) , &nChans)) return FALSE;
187.3491 -       Table =  TransportValue16(0);
187.3492 -       if (!Icc ->Write(Icc, sizeof(WORD) , &Table)) return FALSE;
187.3493 -
187.3494 -       if (!SaveOneChromaticity(chrm -> Red.x, chrm -> Red.y, Icc)) return FALSE;
187.3495 -       if (!SaveOneChromaticity(chrm -> Green.x, chrm -> Green.y, Icc)) return FALSE;
187.3496 -       if (!SaveOneChromaticity(chrm -> Blue.x, chrm -> Blue.y, Icc)) return FALSE;
187.3497 -
187.3498 -       return TRUE;
187.3499 -}
187.3500 -
187.3501 -
187.3502 -static
187.3503 -LCMSBOOL SaveSequenceDescriptionTag(LPcmsSEQ seq, LPLCMSICCPROFILE Icc)
187.3504 -{
187.3505 -    icUInt32Number nSeqs;
187.3506 -    icDescStruct   DescStruct;
187.3507 -    int i, n = seq ->n;
187.3508 -    LPcmsPSEQDESC pseq = seq ->seq;
187.3509 -
187.3510 -    if (!SetupBase(icSigProfileSequenceDescType, Icc)) return FALSE;
187.3511 -
187.3512 -    nSeqs = TransportValue32(n);
187.3513 -
187.3514 -    if (!Icc ->Write(Icc, sizeof(icUInt32Number) , &nSeqs)) return FALSE;
187.3515 -
187.3516 -    for (i=0; i < n; i++) {
187.3517 -
187.3518 -        LPcmsPSEQDESC sec = pseq + i;
187.3519 -
187.3520 -
187.3521 -        DescStruct.deviceMfg    = (icTagTypeSignature) TransportValue32(sec ->deviceMfg);
187.3522 -        DescStruct.deviceModel  = (icTagTypeSignature) TransportValue32(sec ->deviceModel);
187.3523 -        DescStruct.technology   = (icTechnologySignature) TransportValue32(sec ->technology);
187.3524 -        DescStruct.attributes[0]= TransportValue32(sec ->attributes[0]);
187.3525 -        DescStruct.attributes[1]= TransportValue32(sec ->attributes[1]);
187.3526 -
187.3527 -        if (!Icc ->Write(Icc, sizeof(icDescStruct) - SIZEOF_UINT8_ALIGNED, &DescStruct)) return FALSE;
187.3528 -
187.3529 -        if (!SaveDescription(sec ->Manufacturer, Icc)) return FALSE;
187.3530 -        if (!SaveDescription(sec ->Model, Icc)) return FALSE;
187.3531 -    }
187.3532 -
187.3533 -    return TRUE;
187.3534 -}
187.3535 -
187.3536 -
187.3537 -// Saves a timestamp tag
187.3538 -
187.3539 -static
187.3540 -LCMSBOOL SaveDateTimeNumber(const struct tm *DateTime, LPLCMSICCPROFILE Icc)
187.3541 -{
187.3542 -    icDateTimeNumber Dest;
187.3543 -
187.3544 -    if (!SetupBase(icSigDateTimeType, Icc)) return FALSE;
187.3545 -    EncodeDateTimeNumber(&Dest, DateTime);
187.3546 -    if (!Icc ->Write(Icc, sizeof(icDateTimeNumber), &Dest)) return FALSE;
187.3547 -
187.3548 -    return TRUE;
187.3549 -}
187.3550 -
187.3551 -
187.3552 -// Saves a named color list into a named color profile
187.3553 -static
187.3554 -LCMSBOOL SaveNamedColorList(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
187.3555 -{
187.3556 -
187.3557 -    icUInt32Number      vendorFlag;     // Bottom 16 bits for IC use
187.3558 -    icUInt32Number      count;          // Count of named colors
187.3559 -    icUInt32Number      nDeviceCoords;  // Num of device coordinates
187.3560 -    char                prefix[32];     // Prefix for each color name
187.3561 -    char                suffix[32];     // Suffix for each color name
187.3562 -    int i;
187.3563 -
187.3564 -    if (!SetupBase(icSigNamedColor2Type, Icc)) return FALSE;
187.3565 -
187.3566 -    vendorFlag    = TransportValue32(0);
187.3567 -    count         = TransportValue32(NamedColorList ->nColors);
187.3568 -    nDeviceCoords = TransportValue32(NamedColorList ->ColorantCount);
187.3569 -
187.3570 -    strncpy(prefix, (const char*) NamedColorList->Prefix, 31);
187.3571 -    strncpy(suffix, (const char*) NamedColorList->Suffix, 31);
187.3572 -
187.3573 -    suffix[31] = prefix[31] = 0;
187.3574 -
187.3575 -    if (!Icc ->Write(Icc, sizeof(icUInt32Number), &vendorFlag)) return FALSE;
187.3576 -    if (!Icc ->Write(Icc, sizeof(icUInt32Number), &count)) return FALSE;
187.3577 -    if (!Icc ->Write(Icc, sizeof(icUInt32Number), &nDeviceCoords)) return FALSE;
187.3578 -    if (!Icc ->Write(Icc, 32 , prefix)) return FALSE;
187.3579 -    if (!Icc ->Write(Icc, 32 , suffix)) return FALSE;
187.3580 -
187.3581 -    for (i=0; i < NamedColorList ->nColors; i++) {
187.3582 -
187.3583 -          icUInt16Number  PCS[3];
187.3584 -          icUInt16Number  Colorant[MAXCHANNELS];
187.3585 -          char            root[32];
187.3586 -          LPcmsNAMEDCOLOR Color;
187.3587 -          int j;
187.3588 -
187.3589 -                    Color = NamedColorList ->List + i;
187.3590 -
187.3591 -                    strncpy(root, Color ->Name, 32);
187.3592 -                    Color ->Name[32] = 0;
187.3593 -
187.3594 -                    if (!Icc ->Write(Icc, 32 , root)) return FALSE;
187.3595 -
187.3596 -                    for (j=0; j < 3; j++)
187.3597 -                        PCS[j] = TransportValue16(Color ->PCS[j]);
187.3598 -
187.3599 -                    if (!Icc ->Write(Icc, 3 * sizeof(icUInt16Number), PCS)) return FALSE;
187.3600 -
187.3601 -                    for (j=0; j < NamedColorList ->ColorantCount; j++)
187.3602 -                        Colorant[j] = TransportValue16(Color ->DeviceColorant[j]);
187.3603 -
187.3604 -                    if (!Icc ->Write(Icc,
187.3605 -                            NamedColorList ->ColorantCount * sizeof(icUInt16Number), Colorant)) return FALSE;
187.3606 -    }
187.3607 -
187.3608 -
187.3609 -    return TRUE;
187.3610 -}
187.3611 -
187.3612 -
187.3613 -
187.3614 -// Saves a colorant table. It is using the named color structure for simplicity sake
187.3615 -
187.3616 -static
187.3617 -LCMSBOOL SaveColorantTable(LPcmsNAMEDCOLORLIST NamedColorList, LPLCMSICCPROFILE Icc)
187.3618 -{
187.3619 -     icUInt32Number count;  // Count of named colors
187.3620 -     int i;
187.3621 -
187.3622 -     if (!SetupBase(icSigColorantTableType, Icc)) return FALSE;
187.3623 -
187.3624 -     count = TransportValue32(NamedColorList ->nColors);
187.3625 -
187.3626 -     if (!Icc ->Write(Icc, sizeof(icUInt32Number), &count)) return FALSE;
187.3627 -
187.3628 -     for (i=0; i < NamedColorList ->nColors; i++) {
187.3629 -
187.3630 -      icUInt16Number PCS[3];
187.3631 -      icInt8Number root[33];
187.3632 -      LPcmsNAMEDCOLOR Color;
187.3633 -      int j;
187.3634 -
187.3635 -            Color = NamedColorList ->List + i;
187.3636 -
187.3637 -            strncpy((char*) root, Color ->Name, 32);
187.3638 -            root[32] = 0;
187.3639 -
187.3640 -            if (!Icc ->Write(Icc, 32 , root)) return FALSE;
187.3641 -
187.3642 -            for (j=0; j < 3; j++)
187.3643 -                PCS[j] = TransportValue16(Color ->PCS[j]);
187.3644 -
187.3645 -            if (!Icc ->Write(Icc, 3 * sizeof(icUInt16Number), PCS)) return FALSE;
187.3646 -
187.3647 -     }
187.3648 -
187.3649 -
187.3650 -     return TRUE;
187.3651 -}
187.3652 -
187.3653 -// Does serialization of LUT16 and writes it.
187.3654 -
187.3655 -static
187.3656 -LCMSBOOL SaveLUT(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
187.3657 -{
187.3658 -       icLut16 LUT16;
187.3659 -       unsigned int i;
187.3660 -       size_t nTabSize;
187.3661 -       WORD NullTbl[2] = { 0, 0xFFFFU};
187.3662 -
187.3663 -
187.3664 -       if (!SetupBase(icSigLut16Type, Icc)) return FALSE;
187.3665 -
187.3666 -       LUT16.clutPoints = (icUInt8Number) NewLUT -> cLutPoints;
187.3667 -       LUT16.inputChan  = (icUInt8Number) NewLUT -> InputChan;
187.3668 -       LUT16.outputChan = (icUInt8Number) NewLUT -> OutputChan;
187.3669 -
187.3670 -       LUT16.inputEnt   = TransportValue16((WORD) ((NewLUT -> wFlags & LUT_HASTL1) ? NewLUT -> InputEntries  : 2));
187.3671 -       LUT16.outputEnt  = TransportValue16((WORD) ((NewLUT -> wFlags & LUT_HASTL2) ? NewLUT -> OutputEntries : 2));
187.3672 -
187.3673 -       if (NewLUT -> wFlags & LUT_HASMATRIX) {
187.3674 -
187.3675 -           LUT16.e00 = TransportValue32(NewLUT -> Matrix.v[0].n[0]);
187.3676 -           LUT16.e01 = TransportValue32(NewLUT -> Matrix.v[0].n[1]);
187.3677 -           LUT16.e02 = TransportValue32(NewLUT -> Matrix.v[0].n[2]);
187.3678 -           LUT16.e10 = TransportValue32(NewLUT -> Matrix.v[1].n[0]);
187.3679 -           LUT16.e11 = TransportValue32(NewLUT -> Matrix.v[1].n[1]);
187.3680 -           LUT16.e12 = TransportValue32(NewLUT -> Matrix.v[1].n[2]);
187.3681 -           LUT16.e20 = TransportValue32(NewLUT -> Matrix.v[2].n[0]);
187.3682 -           LUT16.e21 = TransportValue32(NewLUT -> Matrix.v[2].n[1]);
187.3683 -           LUT16.e22 = TransportValue32(NewLUT -> Matrix.v[2].n[2]);
187.3684 -           }
187.3685 -       else {
187.3686 -
187.3687 -           LUT16.e00 = TransportValue32(DOUBLE_TO_FIXED(1));
187.3688 -           LUT16.e01 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3689 -           LUT16.e02 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3690 -           LUT16.e10 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3691 -           LUT16.e11 = TransportValue32(DOUBLE_TO_FIXED(1));
187.3692 -           LUT16.e12 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3693 -           LUT16.e20 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3694 -           LUT16.e21 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3695 -           LUT16.e22 = TransportValue32(DOUBLE_TO_FIXED(1));
187.3696 -       }
187.3697 -
187.3698 -
187.3699 -       // Save header
187.3700 -
187.3701 -       Icc -> Write(Icc,  sizeof(icLut16)- SIZEOF_UINT16_ALIGNED, &LUT16);
187.3702 -
187.3703 -       // The prelinearization table
187.3704 -
187.3705 -       for (i=0; i < NewLUT -> InputChan; i++) {
187.3706 -
187.3707 -        if (NewLUT -> wFlags & LUT_HASTL1) {
187.3708 -
187.3709 -               if (!SaveWordsTable(NewLUT -> InputEntries,
187.3710 -                                   NewLUT -> L1[i], Icc)) return FALSE;
187.3711 -
187.3712 -        }
187.3713 -        else Icc -> Write(Icc, sizeof(WORD)* 2, NullTbl);
187.3714 -       }
187.3715 -
187.3716 -
187.3717 -       nTabSize = (NewLUT -> OutputChan * uipow(NewLUT->cLutPoints,
187.3718 -                                                 NewLUT->InputChan));
187.3719 -       // The 3D CLUT.
187.3720 -
187.3721 -       if (nTabSize > 0) {
187.3722 -
187.3723 -             if (!SaveWordsTable((int) nTabSize, NewLUT -> T, Icc)) return FALSE;
187.3724 -       }
187.3725 -       // The postlinearization table
187.3726 -
187.3727 -       for (i=0; i < NewLUT -> OutputChan; i++) {
187.3728 -
187.3729 -        if (NewLUT -> wFlags & LUT_HASTL2) {
187.3730 -
187.3731 -                if (!SaveWordsTable(NewLUT -> OutputEntries,
187.3732 -                                    NewLUT -> L2[i], Icc)) return FALSE;
187.3733 -        }
187.3734 -        else Icc -> Write(Icc, sizeof(WORD)* 2, NullTbl);
187.3735 -
187.3736 -       }
187.3737 -
187.3738 -        return TRUE;
187.3739 -}
187.3740 -
187.3741 -
187.3742 -
187.3743 -// Does serialization of LUT8 and writes it
187.3744 -
187.3745 -static
187.3746 -LCMSBOOL SaveLUT8(const LUT* NewLUT, LPLCMSICCPROFILE Icc)
187.3747 -{
187.3748 -       icLut8 LUT8;
187.3749 -       unsigned int i, j;
187.3750 -       size_t nTabSize;
187.3751 -       BYTE val;
187.3752 -
187.3753 -       // Sanity check
187.3754 -
187.3755 -       if (NewLUT -> wFlags & LUT_HASTL1) {
187.3756 -
187.3757 -           if (NewLUT -> InputEntries != 256) {
187.3758 -                cmsSignalError(LCMS_ERRC_ABORTED, "LUT8 needs 256 entries on prelinearization");
187.3759 -                return FALSE;
187.3760 -           }
187.3761 -
187.3762 -       }
187.3763 -
187.3764 -
187.3765 -       if (NewLUT -> wFlags & LUT_HASTL2) {
187.3766 -
187.3767 -           if (NewLUT -> OutputEntries != 256) {
187.3768 -                cmsSignalError(LCMS_ERRC_ABORTED, "LUT8 needs 256 entries on postlinearization");
187.3769 -                return FALSE;
187.3770 -           }
187.3771 -       }
187.3772 -
187.3773 -
187.3774 -
187.3775 -       if (!SetupBase(icSigLut8Type, Icc)) return FALSE;
187.3776 -
187.3777 -       LUT8.clutPoints = (icUInt8Number) NewLUT -> cLutPoints;
187.3778 -       LUT8.inputChan  = (icUInt8Number) NewLUT -> InputChan;
187.3779 -       LUT8.outputChan = (icUInt8Number) NewLUT -> OutputChan;
187.3780 -
187.3781 -
187.3782 -       if (NewLUT -> wFlags & LUT_HASMATRIX) {
187.3783 -
187.3784 -       LUT8.e00 = TransportValue32(NewLUT -> Matrix.v[0].n[0]);
187.3785 -       LUT8.e01 = TransportValue32(NewLUT -> Matrix.v[0].n[1]);
187.3786 -       LUT8.e02 = TransportValue32(NewLUT -> Matrix.v[0].n[2]);
187.3787 -       LUT8.e10 = TransportValue32(NewLUT -> Matrix.v[1].n[0]);
187.3788 -       LUT8.e11 = TransportValue32(NewLUT -> Matrix.v[1].n[1]);
187.3789 -       LUT8.e12 = TransportValue32(NewLUT -> Matrix.v[1].n[2]);
187.3790 -       LUT8.e20 = TransportValue32(NewLUT -> Matrix.v[2].n[0]);
187.3791 -       LUT8.e21 = TransportValue32(NewLUT -> Matrix.v[2].n[1]);
187.3792 -       LUT8.e22 = TransportValue32(NewLUT -> Matrix.v[2].n[2]);
187.3793 -       }
187.3794 -       else {
187.3795 -
187.3796 -       LUT8.e00 = TransportValue32(DOUBLE_TO_FIXED(1));
187.3797 -       LUT8.e01 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3798 -       LUT8.e02 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3799 -       LUT8.e10 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3800 -       LUT8.e11 = TransportValue32(DOUBLE_TO_FIXED(1));
187.3801 -       LUT8.e12 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3802 -       LUT8.e20 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3803 -       LUT8.e21 = TransportValue32(DOUBLE_TO_FIXED(0));
187.3804 -       LUT8.e22 = TransportValue32(DOUBLE_TO_FIXED(1));
187.3805 -       }
187.3806 -
187.3807 -
187.3808 -       // Save header
187.3809 -
187.3810 -       Icc -> Write(Icc,  sizeof(icLut8)- SIZEOF_UINT8_ALIGNED, &LUT8);
187.3811 -
187.3812 -       // The prelinearization table
187.3813 -
187.3814 -       for (i=0; i < NewLUT -> InputChan; i++) {
187.3815 -
187.3816 -           for (j=0; j < 256; j++) {
187.3817 -
187.3818 -               if (NewLUT -> wFlags & LUT_HASTL1)
187.3819 -                        val = (BYTE) floor(NewLUT ->L1[i][j] / 257.0 + .5);
187.3820 -               else
187.3821 -                        val = (BYTE) j;
187.3822 -
187.3823 -               Icc ->Write(Icc, 1, &val);
187.3824 -           }
187.3825 -
187.3826 -       }
187.3827 -
187.3828 -
187.3829 -       nTabSize = (NewLUT -> OutputChan * uipow(NewLUT->cLutPoints,
187.3830 -                                                 NewLUT->InputChan));
187.3831 -       // The 3D CLUT.
187.3832 -
187.3833 -       for (j=0; j < nTabSize; j++) {
187.3834 -
187.3835 -              val = (BYTE) floor(NewLUT ->T[j] / 257.0 + .5);
187.3836 -              Icc ->Write(Icc, 1, &val);
187.3837 -       }
187.3838 -
187.3839 -       // The postlinearization table
187.3840 -
187.3841 -       for (i=0; i < NewLUT -> OutputChan; i++) {
187.3842 -
187.3843 -           for (j=0; j < 256; j++) {
187.3844 -
187.3845 -               if (NewLUT -> wFlags & LUT_HASTL2)
187.3846 -                    val = (BYTE) floor(NewLUT ->L2[i][j] / 257.0 + .5);
187.3847 -               else
187.3848 -                    val = (BYTE) j;
187.3849 -
187.3850 -               Icc ->Write(Icc, 1, &val);
187.3851 -           }
187.3852 -
187.3853 -       }
187.3854 -
187.3855 -        return TRUE;
187.3856 -}
187.3857 -
187.3858 -
187.3859 -
187.3860 -// Set the LUT bitdepth to be saved
187.3861 -
187.3862 -void LCMSEXPORT _cmsSetLUTdepth(cmsHPROFILE hProfile, int depth)
187.3863 -{
187.3864 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.3865 -
187.3866 -    switch (depth) {
187.3867 -
187.3868 -    case 8:  Icc ->SaveAs8Bits = TRUE; break;
187.3869 -    case 16: Icc ->SaveAs8Bits = FALSE; break;
187.3870 -
187.3871 -    default:
187.3872 -        cmsSignalError(LCMS_ERRC_ABORTED, "%d is an unsupported as bitdepth, use 8 or 16 only.", depth);
187.3873 -    }
187.3874 -}
187.3875 -
187.3876 -
187.3877 -// Saves Tag directory
187.3878 -
187.3879 -static
187.3880 -LCMSBOOL SaveTagDirectory(LPLCMSICCPROFILE Icc)
187.3881 -{
187.3882 -       icInt32Number i;
187.3883 -       icTag Tag;
187.3884 -       icInt32Number Count = 0;
187.3885 -
187.3886 -       // Get true count
187.3887 -       for (i=0;  i < Icc -> TagCount; i++) {
187.3888 -            if (Icc ->TagNames[i] != 0)
187.3889 -                    Count++;
187.3890 -       }
187.3891 -
187.3892 -       Count = TransportValue32(Count);
187.3893 -       if (!Icc ->Write(Icc, sizeof(icInt32Number) , &Count)) return FALSE;
187.3894 -
187.3895 -       for (i=0; i < Icc -> TagCount; i++) {
187.3896 -
187.3897 -          if (Icc ->TagNames[i] == 0) continue;
187.3898 -
187.3899 -          Tag.sig    = (icTagSignature)TransportValue32(Icc -> TagNames[i]);
187.3900 -          Tag.offset = TransportValue32((icInt32Number) Icc -> TagOffsets[i]);
187.3901 -          Tag.size   = TransportValue32((icInt32Number) Icc -> TagSizes[i]);
187.3902 -
187.3903 -          if (!Icc ->Write(Icc, sizeof(icTag), &Tag)) return FALSE;
187.3904 -       }
187.3905 -
187.3906 -       return TRUE;
187.3907 -}
187.3908 -
187.3909 -
187.3910 -// Dump tag contents
187.3911 -
187.3912 -static
187.3913 -LCMSBOOL SaveTags(LPLCMSICCPROFILE Icc, LPLCMSICCPROFILE FileOrig)
187.3914 -{
187.3915 -
187.3916 -    LPBYTE Data;
187.3917 -    icInt32Number i;
187.3918 -    size_t Begin;
187.3919 -    size_t AlignedSpace, FillerSize;
187.3920 -
187.3921 -
187.3922 -    for (i=0; i < Icc -> TagCount; i++) {
187.3923 -
187.3924 -         if (Icc ->TagNames[i] == 0) continue;
187.3925 -
187.3926 -        // Align to DWORD boundary, following new spec.
187.3927 -
187.3928 -        AlignedSpace = ALIGNLONG(Icc ->UsedSpace);
187.3929 -        FillerSize  = AlignedSpace - Icc ->UsedSpace;
187.3930 -        if (FillerSize > 0)  {
187.3931 -
187.3932 -            BYTE Filler[20];
187.3933 -
187.3934 -            ZeroMemory(Filler, 16);
187.3935 -            if (!Icc ->Write(Icc, FillerSize, Filler)) return FALSE;
187.3936 -        }
187.3937 -
187.3938 -
187.3939 -       Icc -> TagOffsets[i] = Begin = Icc ->UsedSpace;
187.3940 -       Data = (LPBYTE) Icc -> TagPtrs[i];
187.3941 -       if (!Data) {
187.3942 -
187.3943 -           // Reach here if we are copying a tag from a disk-based ICC profile which has not been modified by user.
187.3944 -           // In this case a blind copy of the block data is performed
187.3945 -
187.3946 -           if (Icc -> TagOffsets[i]) {
187.3947 -
187.3948 -                    size_t TagSize   = FileOrig -> TagSizes[i];
187.3949 -                    size_t TagOffset = FileOrig -> TagOffsets[i];
187.3950 -                    void* Mem;
187.3951 -
187.3952 -                    if (FileOrig ->Seek(FileOrig, TagOffset)) return FALSE;
187.3953 -
187.3954 -                    Mem = _cmsMalloc(TagSize);
187.3955 -
187.3956 -                    if (FileOrig ->Read(Mem, TagSize, 1, FileOrig) != 1) return FALSE;
187.3957 -                    if (!Icc ->Write(Icc, TagSize, Mem)) return FALSE;
187.3958 -
187.3959 -                    Icc -> TagSizes[i] = (Icc ->UsedSpace - Begin);
187.3960 -                    free(Mem);
187.3961 -           }
187.3962 -
187.3963 -              continue;
187.3964 -       }
187.3965 -
187.3966 -
187.3967 -       switch (Icc -> TagNames[i]) {
187.3968 -
187.3969 -       case icSigProfileDescriptionTag:
187.3970 -       case icSigDeviceMfgDescTag:
187.3971 -       case icSigDeviceModelDescTag:
187.3972 -              if (!SaveDescription((const char *) Data, Icc)) return FALSE;
187.3973 -              break;
187.3974 -
187.3975 -       case icSigRedColorantTag:
187.3976 -       case icSigGreenColorantTag:
187.3977 -       case icSigBlueColorantTag:
187.3978 -       case icSigMediaWhitePointTag:
187.3979 -       case icSigMediaBlackPointTag:
187.3980 -               if (!SaveXYZNumber((LPcmsCIEXYZ) Data, Icc)) return FALSE;
187.3981 -               break;
187.3982 -
187.3983 -
187.3984 -       case icSigRedTRCTag:
187.3985 -       case icSigGreenTRCTag:
187.3986 -       case icSigBlueTRCTag:
187.3987 -       case icSigGrayTRCTag:
187.3988 -               if (!SaveGamma((LPGAMMATABLE) Data, Icc)) return FALSE;
187.3989 -               break;
187.3990 -
187.3991 -       case icSigCharTargetTag:
187.3992 -       case icSigCopyrightTag:
187.3993 -              if (!SaveText((const char *) Data, Icc)) return FALSE;
187.3994 -              break;
187.3995 -
187.3996 -       case icSigChromaticityTag:
187.3997 -              if (!SaveChromaticities((LPcmsCIExyYTRIPLE) Data, Icc)) return FALSE;
187.3998 -              break;
187.3999 -
187.4000 -       // Save LUT
187.4001 -
187.4002 -       case icSigAToB0Tag:
187.4003 -       case icSigAToB1Tag:
187.4004 -       case icSigAToB2Tag:
187.4005 -       case icSigBToA0Tag:
187.4006 -       case icSigBToA1Tag:
187.4007 -       case icSigBToA2Tag:
187.4008 -       case icSigGamutTag:
187.4009 -       case icSigPreview0Tag:
187.4010 -       case icSigPreview1Tag:
187.4011 -       case icSigPreview2Tag:
187.4012 -
187.4013 -                if (Icc ->SaveAs8Bits) {
187.4014 -
187.4015 -                        if (!SaveLUT8((LPLUT) Data, Icc)) return FALSE;
187.4016 -                }
187.4017 -                else {
187.4018 -
187.4019 -                        if (!SaveLUT((LPLUT) Data, Icc)) return FALSE;
187.4020 -                }
187.4021 -                break;
187.4022 -
187.4023 -       case icSigProfileSequenceDescTag:
187.4024 -              if (!SaveSequenceDescriptionTag((LPcmsSEQ) Data, Icc)) return FALSE;
187.4025 -              break;
187.4026 -
187.4027 -
187.4028 -       case icSigNamedColor2Tag:
187.4029 -             if (!SaveNamedColorList((LPcmsNAMEDCOLORLIST) Data, Icc)) return FALSE;
187.4030 -             break;
187.4031 -
187.4032 -
187.4033 -       case icSigCalibrationDateTimeTag:
187.4034 -             if (!SaveDateTimeNumber((struct tm *) Data, Icc)) return FALSE;
187.4035 -             break;
187.4036 -
187.4037 -
187.4038 -       case icSigColorantTableTag:
187.4039 -       case icSigColorantTableOutTag:
187.4040 -             if (!SaveColorantTable((LPcmsNAMEDCOLORLIST) Data, Icc)) return FALSE;
187.4041 -             break;
187.4042 -
187.4043 -
187.4044 -       case icSigChromaticAdaptationTag:
187.4045 -              if (!SaveXYZArray(3, (LPcmsCIEXYZ) Data, Icc)) return FALSE;
187.4046 -              break;
187.4047 -
187.4048 -       default:
187.4049 -              return FALSE;
187.4050 -       }
187.4051 -
187.4052 -       Icc -> TagSizes[i] = (Icc ->UsedSpace - Begin);
187.4053 -       }
187.4054 -
187.4055 -
187.4056 -
187.4057 -       return TRUE;
187.4058 -}
187.4059 -
187.4060 -
187.4061 -
187.4062 -// Add tags to profile structure
187.4063 -
187.4064 -LCMSBOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* Tag)
187.4065 -{
187.4066 -   LCMSBOOL rc;
187.4067 -
187.4068 -   switch (sig) {
187.4069 -
187.4070 -       case icSigCharTargetTag:
187.4071 -       case icSigCopyrightTag:
187.4072 -       case icSigProfileDescriptionTag:
187.4073 -       case icSigDeviceMfgDescTag:
187.4074 -       case icSigDeviceModelDescTag:
187.4075 -              rc = _cmsAddTextTag(hProfile, sig, (const char*) Tag);
187.4076 -              break;
187.4077 -
187.4078 -       case icSigRedColorantTag:
187.4079 -       case icSigGreenColorantTag:
187.4080 -       case icSigBlueColorantTag:
187.4081 -       case icSigMediaWhitePointTag:
187.4082 -       case icSigMediaBlackPointTag:
187.4083 -              rc = _cmsAddXYZTag(hProfile, sig, (const cmsCIEXYZ*) Tag);
187.4084 -              break;
187.4085 -
187.4086 -       case icSigRedTRCTag:
187.4087 -       case icSigGreenTRCTag:
187.4088 -       case icSigBlueTRCTag:
187.4089 -       case icSigGrayTRCTag:
187.4090 -              rc =  _cmsAddGammaTag(hProfile, sig, (LPGAMMATABLE) Tag);
187.4091 -              break;
187.4092 -
187.4093 -       case icSigAToB0Tag:
187.4094 -       case icSigAToB1Tag:
187.4095 -       case icSigAToB2Tag:
187.4096 -       case icSigBToA0Tag:
187.4097 -       case icSigBToA1Tag:
187.4098 -       case icSigBToA2Tag:
187.4099 -       case icSigGamutTag:
187.4100 -       case icSigPreview0Tag:
187.4101 -       case icSigPreview1Tag:
187.4102 -       case icSigPreview2Tag:
187.4103 -              rc =  _cmsAddLUTTag(hProfile, sig, Tag);
187.4104 -              break;
187.4105 -
187.4106 -       case icSigChromaticityTag:
187.4107 -              rc =  _cmsAddChromaticityTag(hProfile, sig, (LPcmsCIExyYTRIPLE) Tag);
187.4108 -              break;
187.4109 -
187.4110 -       case icSigProfileSequenceDescTag:
187.4111 -              rc = _cmsAddSequenceDescriptionTag(hProfile, sig, (LPcmsSEQ) Tag);
187.4112 -              break;
187.4113 -
187.4114 -       case icSigNamedColor2Tag:
187.4115 -              rc = _cmsAddNamedColorTag(hProfile, sig, (LPcmsNAMEDCOLORLIST) Tag);
187.4116 -             break;
187.4117 -
187.4118 -       case icSigCalibrationDateTimeTag:
187.4119 -              rc = _cmsAddDateTimeTag(hProfile, sig, (struct tm*) Tag);
187.4120 -              break;
187.4121 -
187.4122 -       case icSigColorantTableTag:
187.4123 -       case icSigColorantTableOutTag:
187.4124 -              rc = _cmsAddColorantTableTag(hProfile, sig, (LPcmsNAMEDCOLORLIST) Tag);
187.4125 -              break;
187.4126 -
187.4127 -
187.4128 -       case icSigChromaticAdaptationTag:
187.4129 -              rc = _cmsAddChromaticAdaptationTag(hProfile, sig, (const cmsCIEXYZ*) Tag);
187.4130 -              break;
187.4131 -
187.4132 -       default:
187.4133 -            cmsSignalError(LCMS_ERRC_ABORTED, "cmsAddTag: Tag '%x' is unsupported", sig);
187.4134 -            return FALSE;
187.4135 -   }
187.4136 -
187.4137 -   // Check for critical tags
187.4138 -
187.4139 -   switch (sig) {
187.4140 -
187.4141 -   case icSigMediaWhitePointTag:
187.4142 -   case icSigMediaBlackPointTag:
187.4143 -   case icSigChromaticAdaptationTag:
187.4144 -
187.4145 -        ReadCriticalTags((LPLCMSICCPROFILE) hProfile);
187.4146 -        break;
187.4147 -
187.4148 -   default:;
187.4149 -   }
187.4150 -
187.4151 -   return rc;
187.4152 -
187.4153 -}
187.4154 -
187.4155 -// Low-level save to disk. It closes the profile on exit
187.4156 -
187.4157 -LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName)
187.4158 -{
187.4159 -       LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.4160 -       LCMSICCPROFILE Keep;
187.4161 -       LCMSBOOL rc;
187.4162 -
187.4163 -        CopyMemory(&Keep, Icc, sizeof(LCMSICCPROFILE));
187.4164 -       _cmsSetSaveToDisk(Icc, NULL);
187.4165 -
187.4166 -       // Pass #1 does compute offsets
187.4167 -
187.4168 -       if (!SaveHeader(Icc)) return FALSE;
187.4169 -       if (!SaveTagDirectory(Icc)) return FALSE;
187.4170 -       if (!SaveTags(Icc, &Keep)) return FALSE;
187.4171 -
187.4172 -
187.4173 -       _cmsSetSaveToDisk(Icc, FileName);
187.4174 -
187.4175 -
187.4176 -       // Pass #2 does save to file
187.4177 -
187.4178 -       if (!SaveHeader(Icc)) goto CleanUp;
187.4179 -       if (!SaveTagDirectory(Icc)) goto CleanUp;
187.4180 -       if (!SaveTags(Icc, &Keep)) goto CleanUp;
187.4181 -
187.4182 -       rc = (Icc ->Close(Icc) == 0);
187.4183 -       CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
187.4184 -       return rc;
187.4185 -
187.4186 -
187.4187 -   CleanUp:
187.4188 -
187.4189 -       Icc ->Close(Icc);
187.4190 -       unlink(FileName);
187.4191 -       CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
187.4192 -       return FALSE;
187.4193 -}
187.4194 -
187.4195 -
187.4196 -// Low-level save from open stream
187.4197 -LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
187.4198 -                                                           size_t* BytesNeeded)
187.4199 -{
187.4200 -    LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
187.4201 -    LCMSICCPROFILE Keep;
187.4202 -
187.4203 -
187.4204 -    CopyMemory(&Keep, Icc, sizeof(LCMSICCPROFILE));
187.4205 -
187.4206 -    _cmsSetSaveToMemory(Icc, NULL, 0);
187.4207 -
187.4208 -    // Pass #1 does compute offsets
187.4209 -
187.4210 -    if (!SaveHeader(Icc)) return FALSE;
187.4211 -    if (!SaveTagDirectory(Icc)) return FALSE;
187.4212 -    if (!SaveTags(Icc, &Keep)) return FALSE;
187.4213 -
187.4214 -    if (!MemPtr) {
187.4215 -
187.4216 -        // update BytesSaved so caller knows how many bytes are needed for MemPtr
187.4217 -        *BytesNeeded = Icc ->UsedSpace;
187.4218 -        CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
187.4219 -        return TRUE;
187.4220 -    }
187.4221 -
187.4222 -    if (*BytesNeeded < Icc ->UsedSpace) {
187.4223 -
187.4224 -        // need at least UsedSpace in MemPtr to continue
187.4225 -        CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
187.4226 -        return FALSE;
187.4227 -    }
187.4228 -
187.4229 -    _cmsSetSaveToMemory(Icc, MemPtr, *BytesNeeded);
187.4230 -
187.4231 -
187.4232 -    // Pass #2 does save to file into supplied stream
187.4233 -    if (!SaveHeader(Icc)) goto CleanUp;
187.4234 -    if (!SaveTagDirectory(Icc)) goto CleanUp;
187.4235 -    if (!SaveTags(Icc, &Keep)) goto CleanUp;
187.4236 -
187.4237 -    // update BytesSaved so caller knows how many bytes put into stream
187.4238 -    *BytesNeeded = Icc ->UsedSpace;
187.4239 -
187.4240 -    Icc ->Close(Icc);
187.4241 -    CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
187.4242 -    return TRUE;
187.4243 -
187.4244 -CleanUp:
187.4245 -
187.4246 -    Icc ->Close(Icc);
187.4247 -    CopyMemory(Icc, &Keep, sizeof(LCMSICCPROFILE));
187.4248 -    return FALSE;
187.4249 -}
187.4250 -
   188.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Thu Sep 23 17:33:40 2010 -0700
   188.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmslut.c	Fri Sep 24 16:41:32 2010 -0700
   188.3 @@ -27,9 +27,10 @@
   188.4  // However, the following notice accompanied the original version of this
   188.5  // file:
   188.6  //
   188.7 +//---------------------------------------------------------------------------------
   188.8  //
   188.9 -//  Little cms
  188.10 -//  Copyright (C) 1998-2007 Marti Maria
  188.11 +//  Little Color Management System
  188.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  188.13  //
  188.14  // Permission is hereby granted, free of charge, to any person obtaining
  188.15  // a copy of this software and associated documentation files (the "Software"),
  188.16 @@ -48,630 +49,1430 @@
  188.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  188.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  188.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  188.20 +//
  188.21 +//---------------------------------------------------------------------------------
  188.22 +//
  188.23  
  188.24 -#include "lcms.h"
  188.25 +#include "lcms2_internal.h"
  188.26  
  188.27 -//  Pipeline of LUT. Enclosed by {} are new revision 4.0 of ICC spec.
  188.28 -//
  188.29 -//  [Mat] -> [L1] -> { [Mat3] -> [Ofs3] -> [L3] ->} [CLUT] { -> [L4] -> [Mat4] -> [Ofs4] } -> [L2]
  188.30 -//
  188.31 -//  Some of these stages would be missing. This implements the totality of
  188.32 -//  combinations of old and new LUT types as follows:
  188.33 -//
  188.34 -//  Lut8 & Lut16
  188.35 -//  ============
  188.36 -//     [Mat] -> [L1] -> [CLUT] -> [L2]
  188.37 -//
  188.38 -//  Mat2, Ofs2, L3, L3, Mat3, Ofs3 are missing
  188.39 -//
  188.40 -//  LutAToB
  188.41 -//  ========
  188.42 -//
  188.43 -//  [L1] -> [CLUT] -> [L4] -> [Mat4] -> [Ofs4] -> [L2]
  188.44 -//
  188.45 -//  Mat, Mat3, Ofs3, L3 are missing
  188.46 -//   L1 = A curves
  188.47 -//   L4 = M curves
  188.48 -//   L2 = B curves
  188.49 -//
  188.50 -//  LutBToA
  188.51 -//  =======
  188.52 -//
  188.53 -//  [L1] -> [Mat3] -> [Ofs3] -> [L3] -> [CLUT] -> [L2]
  188.54 -//
  188.55 -//  Mat, L4, Mat4, Ofs4 are missing
  188.56 -//   L1 = B Curves
  188.57 -//   L3 = M Curves
  188.58 -//   L2 = A curves
  188.59 -//
  188.60 -//
  188.61 -//  V2&3 emulation
  188.62 -//  ===============
  188.63 -//
  188.64 -//  For output, Mat is multiplied by
  188.65 -//
  188.66 -//
  188.67 -//  | 0xff00 / 0xffff      0                    0           |
  188.68 -//  |        0          0xff00 / 0xffff         0           |
  188.69 -//  |        0             0                0xff00 / 0xffff |
  188.70 -//
  188.71 -//
  188.72 -//  For input, an additional matrix is needed at the very last end of the chain
  188.73 -//
  188.74 -//
  188.75 -//  | 0xffff / 0xff00      0                     0        |
  188.76 -//  |        0          0xffff / 0xff00          0        |
  188.77 -//  |        0             0              0xffff / 0xff00 |
  188.78 -//
  188.79 -//
  188.80 -//  Which reduces to (val * 257) >> 8
  188.81  
  188.82 -// A couple of macros to convert between revisions
  188.83 +// Allocates an empty multi profile element
  188.84 +cmsStage* CMSEXPORT _cmsStageAllocPlaceholder(cmsContext ContextID,
  188.85 +                                cmsStageSignature Type,
  188.86 +                                cmsUInt32Number InputChannels,
  188.87 +                                cmsUInt32Number OutputChannels,
  188.88 +                                _cmsStageEvalFn     EvalPtr,
  188.89 +                                _cmsStageDupElemFn  DupElemPtr,
  188.90 +                                _cmsStageFreeElemFn FreePtr,
  188.91 +                                void*             Data)
  188.92 +{
  188.93 +    cmsStage* ph = (cmsStage*) _cmsMallocZero(ContextID, sizeof(cmsStage));
  188.94  
  188.95 -#define FROM_V2_TO_V4(x) (((((x)<<8)+(x))+0x80)>>8)    // BY 65535 DIV 65280 ROUND
  188.96 -#define FROM_V4_TO_V2(x) ((((x)<<8)+0x80)/257)         // BY 65280 DIV 65535 ROUND
  188.97 +    if (ph == NULL) return NULL;
  188.98  
  188.99  
 188.100 -// Lut Creation & Destruction
 188.101 +    ph ->ContextID = ContextID;
 188.102  
 188.103 -LPLUT LCMSEXPORT cmsAllocLUT(void)
 188.104 -{
 188.105 -       LPLUT NewLUT;
 188.106 +    ph ->Type       = Type;
 188.107 +    ph ->Implements = Type;   // By default, no clue on what is implementing
 188.108  
 188.109 -       NewLUT = (LPLUT) _cmsMalloc(sizeof(LUT));
 188.110 -       if (NewLUT)
 188.111 -              ZeroMemory(NewLUT, sizeof(LUT));
 188.112 +    ph ->InputChannels  = InputChannels;
 188.113 +    ph ->OutputChannels = OutputChannels;
 188.114 +    ph ->EvalPtr        = EvalPtr;
 188.115 +    ph ->DupElemPtr     = DupElemPtr;
 188.116 +    ph ->FreePtr        = FreePtr;
 188.117 +    ph ->Data           = Data;
 188.118  
 188.119 -       return NewLUT;
 188.120 +    return ph;
 188.121  }
 188.122  
 188.123 -void LCMSEXPORT cmsFreeLUT(LPLUT Lut)
 188.124 +
 188.125 +static
 188.126 +void EvaluateIdentity(const cmsFloat32Number In[],
 188.127 +                            cmsFloat32Number Out[],
 188.128 +                      const cmsStage *mpe)
 188.129  {
 188.130 -       unsigned int i;
 188.131 -
 188.132 -       if (!Lut) return;
 188.133 -
 188.134 -       if (Lut -> T) free(Lut -> T);
 188.135 -
 188.136 -       for (i=0; i < Lut -> OutputChan; i++)
 188.137 -       {
 188.138 -              if (Lut -> L2[i]) free(Lut -> L2[i]);
 188.139 -       }
 188.140 -
 188.141 -       for (i=0; i < Lut -> InputChan; i++)
 188.142 -       {
 188.143 -
 188.144 -              if (Lut -> L1[i]) free(Lut -> L1[i]);
 188.145 -       }
 188.146 -
 188.147 -
 188.148 -       if (Lut ->wFlags & LUT_HASTL3) {
 188.149 -
 188.150 -            for (i=0; i < Lut -> InputChan; i++) {
 188.151 -
 188.152 -              if (Lut -> L3[i]) free(Lut -> L3[i]);
 188.153 -            }
 188.154 -       }
 188.155 -
 188.156 -       if (Lut ->wFlags & LUT_HASTL4) {
 188.157 -
 188.158 -            for (i=0; i < Lut -> OutputChan; i++) {
 188.159 -
 188.160 -              if (Lut -> L4[i]) free(Lut -> L4[i]);
 188.161 -            }
 188.162 -       }
 188.163 -
 188.164 -       if (Lut ->CLut16params.p8)
 188.165 -           free(Lut ->CLut16params.p8);
 188.166 -
 188.167 -       free(Lut);
 188.168 +    memmove(Out, In, mpe ->InputChannels * sizeof(cmsFloat32Number));
 188.169  }
 188.170  
 188.171  
 188.172 +cmsStage* CMSEXPORT cmsStageAllocIdentity(cmsContext ContextID, cmsUInt32Number nChannels)
 188.173 +{
 188.174 +    return _cmsStageAllocPlaceholder(ContextID,
 188.175 +                                   cmsSigIdentityElemType,
 188.176 +                                   nChannels, nChannels,
 188.177 +                                   EvaluateIdentity,
 188.178 +                                   NULL,
 188.179 +                                   NULL,
 188.180 +                                   NULL);
 188.181 + }
 188.182 +
 188.183 +// Conversion functions. From floating point to 16 bits
 188.184  static
 188.185 -LPVOID DupBlockTab(LPVOID Org, size_t size)
 188.186 +void FromFloatTo16(const cmsFloat32Number In[], cmsUInt16Number Out[], cmsUInt32Number n)
 188.187  {
 188.188 -    LPVOID mem = _cmsMalloc(size);
 188.189 -    if (mem != NULL)
 188.190 -        CopyMemory(mem, Org, size);
 188.191 +    cmsUInt32Number i;
 188.192  
 188.193 -    return mem;
 188.194 +    for (i=0; i < n; i++) {
 188.195 +        Out[i] = _cmsQuickSaturateWord(In[i] * 65535.0);
 188.196 +    }
 188.197  }
 188.198  
 188.199 +// From 16 bits to floating point
 188.200 +static
 188.201 +void From16ToFloat(const cmsUInt16Number In[], cmsFloat32Number Out[], cmsUInt32Number n)
 188.202 +{
 188.203 +    cmsUInt32Number i;
 188.204  
 188.205 -LPLUT LCMSEXPORT cmsDupLUT(LPLUT Orig)
 188.206 -{
 188.207 -    LPLUT NewLUT = cmsAllocLUT();
 188.208 -    unsigned int i;
 188.209 -
 188.210 -       CopyMemory(NewLUT, Orig, sizeof(LUT));
 188.211 -
 188.212 -       for (i=0; i < Orig ->InputChan; i++)
 188.213 -            NewLUT -> L1[i] = (LPWORD) DupBlockTab((LPVOID) Orig ->L1[i],
 188.214 -                                        sizeof(WORD) * Orig ->In16params.nSamples);
 188.215 -
 188.216 -       for (i=0; i < Orig ->OutputChan; i++)
 188.217 -            NewLUT -> L2[i] = (LPWORD) DupBlockTab((LPVOID) Orig ->L2[i],
 188.218 -                                        sizeof(WORD) * Orig ->Out16params.nSamples);
 188.219 -
 188.220 -       NewLUT -> T = (LPWORD) DupBlockTab((LPVOID) Orig ->T, Orig -> Tsize);
 188.221 -
 188.222 -       return NewLUT;
 188.223 +    for (i=0; i < n; i++) {
 188.224 +        Out[i] = (cmsFloat32Number) In[i] / 65535.0F;
 188.225 +    }
 188.226  }
 188.227  
 188.228  
 188.229 -static
 188.230 -unsigned int UIpow(unsigned int a, unsigned int b)
 188.231 +// This function is quite useful to analyze the structure of a LUT and retrieve the MPE elements
 188.232 +// that conform the LUT. It should be called with the LUT, the number of expected elements and
 188.233 +// then a list of expected types followed with a list of cmsFloat64Number pointers to MPE elements. If
 188.234 +// the function founds a match with current pipeline, it fills the pointers and returns TRUE
 188.235 +// if not, returns FALSE without touching anything. Setting pointers to NULL does bypass
 188.236 +// the storage process.
 188.237 +cmsBool  CMSEXPORT cmsPipelineCheckAndRetreiveStages(const cmsPipeline* Lut, cmsUInt32Number n, ...)
 188.238  {
 188.239 -        unsigned int rv = 1;
 188.240 +    va_list args;
 188.241 +    cmsUInt32Number i;
 188.242 +    cmsStage* mpe;
 188.243 +    cmsStageSignature Type;
 188.244 +    void** ElemPtr;
 188.245  
 188.246 -        for (; b > 0; b--)
 188.247 -                rv *= a;
 188.248 +    // Make sure same number of elements
 188.249 +    if (cmsPipelineStageCount(Lut) != n) return FALSE;
 188.250  
 188.251 -        return rv;
 188.252 +    va_start(args, n);
 188.253 +
 188.254 +    // Iterate across asked types
 188.255 +    mpe = Lut ->Elements;
 188.256 +    for (i=0; i < n; i++) {
 188.257 +
 188.258 +        // Get asked type
 188.259 +        Type  = va_arg(args, cmsStageSignature);
 188.260 +        if (mpe ->Type != Type) {
 188.261 +
 188.262 +            va_end(args);       // Mismatch. We are done.
 188.263 +            return FALSE;
 188.264 +        }
 188.265 +        mpe = mpe ->Next;
 188.266 +    }
 188.267 +
 188.268 +    // Found a combination, fill pointers if not NULL
 188.269 +    mpe = Lut ->Elements;
 188.270 +    for (i=0; i < n; i++) {
 188.271 +
 188.272 +        ElemPtr = va_arg(args, void**);
 188.273 +        if (ElemPtr != NULL)
 188.274 +            *ElemPtr = mpe;
 188.275 +
 188.276 +        mpe = mpe ->Next;
 188.277 +    }
 188.278 +
 188.279 +    va_end(args);
 188.280 +    return TRUE;
 188.281  }
 188.282  
 188.283 +// Below there are implementations for several types of elements. Each type may be implemented by a
 188.284 +// evaluation function, a duplication function, a function to free resources and a constructor.
 188.285  
 188.286 -LCMSBOOL _cmsValidateLUT(LPLUT NewLUT)
 188.287 +// *************************************************************************************************
 188.288 +// Type cmsSigCurveSetElemType (curves)
 188.289 +// *************************************************************************************************
 188.290 +
 188.291 +cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe)
 188.292  {
 188.293 -    unsigned int calc = 1;
 188.294 -    unsigned int oldCalc;
 188.295 -    unsigned int power = NewLUT -> InputChan;
 188.296 +    _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) mpe ->Data;
 188.297  
 188.298 -    if (NewLUT -> cLutPoints > 100) return FALSE;
 188.299 -    if (NewLUT -> InputChan > MAXCHANNELS)  return FALSE;
 188.300 -    if (NewLUT -> OutputChan > MAXCHANNELS) return FALSE;
 188.301 +    return Data ->TheCurves;
 188.302 +}
 188.303  
 188.304 -    if (NewLUT -> cLutPoints == 0) return TRUE;
 188.305 +static
 188.306 +void EvaluateCurves(const cmsFloat32Number In[],
 188.307 +                    cmsFloat32Number Out[],
 188.308 +                    const cmsStage *mpe)
 188.309 +{
 188.310 +    _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) mpe ->Data;
 188.311 +    cmsUInt32Number i;
 188.312  
 188.313 -    for (; power > 0; power--) {
 188.314 +    if (Data ->TheCurves == NULL) return;
 188.315  
 188.316 -      oldCalc = calc;
 188.317 -      calc *= NewLUT -> cLutPoints;
 188.318 +    for (i=0; i < Data ->nCurves; i++) {
 188.319 +        Out[i] = cmsEvalToneCurveFloat(Data ->TheCurves[i], In[i]);
 188.320 +    }
 188.321 +}
 188.322  
 188.323 -      if (calc / NewLUT -> cLutPoints != oldCalc) {
 188.324 -        return FALSE;
 188.325 -      }
 188.326 +static
 188.327 +void CurveSetElemTypeFree(cmsStage* mpe)
 188.328 +{
 188.329 +    _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) mpe ->Data;
 188.330 +    cmsUInt32Number i;
 188.331 +
 188.332 +    if (Data ->TheCurves != NULL) {
 188.333 +        for (i=0; i < Data ->nCurves; i++) {
 188.334 +            if (Data ->TheCurves[i] != NULL)
 188.335 +                cmsFreeToneCurve(Data ->TheCurves[i]);
 188.336 +        }
 188.337 +    }
 188.338 +    _cmsFree(mpe ->ContextID, Data ->TheCurves);
 188.339 +    _cmsFree(mpe ->ContextID, Data);
 188.340 +}
 188.341 +
 188.342 +
 188.343 +static
 188.344 +void* CurveSetDup(cmsStage* mpe)
 188.345 +{
 188.346 +    _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) mpe ->Data;
 188.347 +    _cmsStageToneCurvesData* NewElem;
 188.348 +    cmsUInt32Number i;
 188.349 +
 188.350 +    NewElem = (_cmsStageToneCurvesData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageToneCurvesData));
 188.351 +    if (NewElem == NULL) return NULL;
 188.352 +
 188.353 +    NewElem ->nCurves   = Data ->nCurves;
 188.354 +    NewElem ->TheCurves = (cmsToneCurve**) _cmsCalloc(mpe ->ContextID, NewElem ->nCurves, sizeof(cmsToneCurve*));
 188.355 +
 188.356 +    if (NewElem ->TheCurves == NULL) goto Error;
 188.357 +
 188.358 +    for (i=0; i < NewElem ->nCurves; i++) {
 188.359 +
 188.360 +        // Duplicate each curve. It may fail.
 188.361 +        NewElem ->TheCurves[i] = cmsDupToneCurve(Data ->TheCurves[i]);
 188.362 +        if (NewElem ->TheCurves[i] == NULL) goto Error;
 188.363 +
 188.364 +
 188.365 +    }
 188.366 +    return (void*) NewElem;
 188.367 +
 188.368 +Error:
 188.369 +
 188.370 +    if (NewElem ->TheCurves != NULL) {
 188.371 +        for (i=0; i < NewElem ->nCurves; i++) {
 188.372 +            if (NewElem ->TheCurves[i])
 188.373 +                cmsFreeToneCurve(Data ->TheCurves[i]);
 188.374 +        }
 188.375 +    }
 188.376 +    _cmsFree(mpe ->ContextID, Data ->TheCurves);
 188.377 +    _cmsFree(mpe ->ContextID, NewElem);
 188.378 +    return NULL;
 188.379 +}
 188.380 +
 188.381 +
 188.382 +// Curves == NULL forces identity curves
 188.383 +cmsStage* CMSEXPORT cmsStageAllocToneCurves(cmsContext ContextID, cmsUInt32Number nChannels, cmsToneCurve* const Curves[])
 188.384 +{
 188.385 +    cmsUInt32Number i;
 188.386 +    _cmsStageToneCurvesData* NewElem;
 188.387 +    cmsStage* NewMPE;
 188.388 +
 188.389 +
 188.390 +    NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCurveSetElemType, nChannels, nChannels,
 188.391 +                                     EvaluateCurves, CurveSetDup, CurveSetElemTypeFree, NULL );
 188.392 +    if (NewMPE == NULL) return NULL;
 188.393 +
 188.394 +    NewElem = (_cmsStageToneCurvesData*) _cmsMalloc(ContextID, sizeof(_cmsStageToneCurvesData));
 188.395 +    if (NewElem == NULL) {
 188.396 +        cmsStageFree(NewMPE);
 188.397 +        return NULL;
 188.398      }
 188.399  
 188.400 -    oldCalc = calc;
 188.401 -    calc *= NewLUT -> OutputChan;
 188.402 -    if (NewLUT -> OutputChan && calc / NewLUT -> OutputChan != oldCalc) {
 188.403 -      return FALSE;
 188.404 +    NewElem ->nCurves   = nChannels;
 188.405 +    NewElem ->TheCurves = (cmsToneCurve**) _cmsCalloc(ContextID, nChannels, sizeof(cmsToneCurve*));
 188.406 +    if (NewElem ->TheCurves == NULL) {
 188.407 +        cmsStageFree(NewMPE);
 188.408 +        return NULL;
 188.409 +    }
 188.410 +
 188.411 +    for (i=0; i < nChannels; i++) {
 188.412 +
 188.413 +        if (Curves == NULL) {
 188.414 +            NewElem ->TheCurves[i] = cmsBuildGamma(ContextID, 1.0);
 188.415 +        }
 188.416 +        else {
 188.417 +            NewElem ->TheCurves[i] = cmsDupToneCurve(Curves[i]);
 188.418 +        }
 188.419 +
 188.420 +        if (NewElem ->TheCurves[i] == NULL) {
 188.421 +            cmsStageFree(NewMPE);
 188.422 +            return NULL;
 188.423 +        }
 188.424 +    }
 188.425 +
 188.426 +    NewMPE ->Data  = (void*) NewElem;
 188.427 +
 188.428 +    return NewMPE;
 188.429 +}
 188.430 +
 188.431 +
 188.432 +// Create a bunch of identity curves
 188.433 +cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels)
 188.434 +{
 188.435 +    cmsStage* mpe = cmsStageAllocToneCurves(ContextID, nChannels, NULL);
 188.436 +
 188.437 +    if (mpe == NULL) return NULL;
 188.438 +    mpe ->Implements = cmsSigIdentityElemType;
 188.439 +    return mpe;
 188.440 +}
 188.441 +
 188.442 +
 188.443 +// *************************************************************************************************
 188.444 +// Type cmsSigMatrixElemType (Matrices)
 188.445 +// *************************************************************************************************
 188.446 +
 188.447 +
 188.448 +// Special care should be taken here because precision loss. A temporary cmsFloat64Number buffer is being used
 188.449 +static
 188.450 +void EvaluateMatrix(const cmsFloat32Number In[],
 188.451 +                    cmsFloat32Number Out[],
 188.452 +                    const cmsStage *mpe)
 188.453 +{
 188.454 +    cmsUInt32Number i, j;
 188.455 +    _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
 188.456 +    cmsFloat64Number Tmp;
 188.457 +
 188.458 +    // Input is already in 0..1.0 notation
 188.459 +    for (i=0; i < mpe ->OutputChannels; i++) {
 188.460 +
 188.461 +        Tmp = 0;
 188.462 +        for (j=0; j < mpe->InputChannels; j++) {
 188.463 +            Tmp += In[j] * Data->Double[i*mpe->InputChannels + j];
 188.464 +        }
 188.465 +
 188.466 +        if (Data ->Offset != NULL)
 188.467 +            Tmp += Data->Offset[i];
 188.468 +
 188.469 +        Out[i] = (cmsFloat32Number) Tmp;
 188.470 +    }
 188.471 +
 188.472 +
 188.473 +    // Output in 0..1.0 domain
 188.474 +}
 188.475 +
 188.476 +
 188.477 +// Duplicate a yet-existing matrix element
 188.478 +static
 188.479 +void* MatrixElemDup(cmsStage* mpe)
 188.480 +{
 188.481 +    _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
 188.482 +    _cmsStageMatrixData* NewElem;
 188.483 +    cmsUInt32Number sz;
 188.484 +
 188.485 +    NewElem = (_cmsStageMatrixData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageMatrixData));
 188.486 +    if (NewElem == NULL) return NULL;
 188.487 +
 188.488 +    sz = mpe ->InputChannels * mpe ->OutputChannels;
 188.489 +
 188.490 +    NewElem ->Double = (cmsFloat64Number*) _cmsDupMem(mpe ->ContextID, Data ->Double, sz * sizeof(cmsFloat64Number)) ;
 188.491 +
 188.492 +    if (Data ->Offset)
 188.493 +        NewElem ->Offset = (cmsFloat64Number*) _cmsDupMem(mpe ->ContextID,
 188.494 +                                                Data ->Offset, mpe -> OutputChannels * sizeof(cmsFloat64Number)) ;
 188.495 +
 188.496 +    return (void*) NewElem;
 188.497 +}
 188.498 +
 188.499 +
 188.500 +static
 188.501 +void MatrixElemTypeFree(cmsStage* mpe)
 188.502 +{
 188.503 +    _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
 188.504 +    if (Data ->Double)
 188.505 +        _cmsFree(mpe ->ContextID, Data ->Double);
 188.506 +
 188.507 +    if (Data ->Offset)
 188.508 +        _cmsFree(mpe ->ContextID, Data ->Offset);
 188.509 +
 188.510 +    _cmsFree(mpe ->ContextID, mpe ->Data);
 188.511 +}
 188.512 +
 188.513 +
 188.514 +
 188.515 +cmsStage*  CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number Rows, cmsUInt32Number Cols,
 188.516 +                                     const cmsFloat64Number* Matrix, const cmsFloat64Number* Offset)
 188.517 +{
 188.518 +    cmsUInt32Number i, n;
 188.519 +    _cmsStageMatrixData* NewElem;
 188.520 +    cmsStage* NewMPE;
 188.521 +
 188.522 +    n = Rows * Cols;
 188.523 +
 188.524 +    // Check for overflow
 188.525 +    if (n < Rows || n < Cols) return NULL;
 188.526 +
 188.527 +    NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigMatrixElemType, Cols, Rows,
 188.528 +                                     EvaluateMatrix, MatrixElemDup, MatrixElemTypeFree, NULL );
 188.529 +    if (NewMPE == NULL) return NULL;
 188.530 +
 188.531 +
 188.532 +    NewElem = (_cmsStageMatrixData*) _cmsMallocZero(ContextID, sizeof(_cmsStageMatrixData));
 188.533 +    if (NewElem == NULL) return NULL;
 188.534 +
 188.535 +
 188.536 +    NewElem ->Double = (cmsFloat64Number*) _cmsCalloc(ContextID, n, sizeof(cmsFloat64Number));
 188.537 +
 188.538 +    if (NewElem->Double == NULL) {
 188.539 +        MatrixElemTypeFree(NewMPE);
 188.540 +        return NULL;
 188.541 +    }
 188.542 +
 188.543 +    for (i=0; i < n; i++) {
 188.544 +        NewElem ->Double[i] = Matrix[i];
 188.545 +    }
 188.546 +
 188.547 +
 188.548 +    if (Offset != NULL) {
 188.549 +
 188.550 +        NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Cols, sizeof(cmsFloat64Number));
 188.551 +        if (NewElem->Offset == NULL) {
 188.552 +           MatrixElemTypeFree(NewMPE);
 188.553 +           return NULL;
 188.554 +        }
 188.555 +
 188.556 +        for (i=0; i < Cols; i++) {
 188.557 +                NewElem ->Offset[i] = Offset[i];
 188.558 +        }
 188.559 +
 188.560 +    }
 188.561 +
 188.562 +    NewMPE ->Data  = (void*) NewElem;
 188.563 +    return NewMPE;
 188.564 +}
 188.565 +
 188.566 +
 188.567 +// *************************************************************************************************
 188.568 +// Type cmsSigCLutElemType
 188.569 +// *************************************************************************************************
 188.570 +
 188.571 +
 188.572 +// Evaluate in true floating point
 188.573 +static
 188.574 +void EvaluateCLUTfloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
 188.575 +{
 188.576 +    _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data;
 188.577 +
 188.578 +    Data -> Params ->Interpolation.LerpFloat(In, Out, Data->Params);
 188.579 +}
 188.580 +
 188.581 +
 188.582 +// Convert to 16 bits, evaluate, and back to floating point
 188.583 +static
 188.584 +void EvaluateCLUTfloatIn16(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
 188.585 +{
 188.586 +    _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data;
 188.587 +    cmsUInt16Number In16[MAX_STAGE_CHANNELS], Out16[MAX_STAGE_CHANNELS];
 188.588 +
 188.589 +    _cmsAssert(mpe ->InputChannels  <= MAX_STAGE_CHANNELS);
 188.590 +    _cmsAssert(mpe ->OutputChannels <= MAX_STAGE_CHANNELS);
 188.591 +
 188.592 +    FromFloatTo16(In, In16, mpe ->InputChannels);
 188.593 +    Data -> Params ->Interpolation.Lerp16(In16, Out16, Data->Params);
 188.594 +    From16ToFloat(Out16, Out,  mpe ->OutputChannels);
 188.595 +}
 188.596 +
 188.597 +
 188.598 +// Given an hypercube of b dimensions, with Dims[] number of nodes by dimension, calculate the total amount of nodes
 188.599 +static
 188.600 +cmsUInt32Number CubeSize(const cmsUInt32Number Dims[], cmsUInt32Number b)
 188.601 +{
 188.602 +    cmsUInt32Number rv;
 188.603 +
 188.604 +    for (rv = 1; b > 0; b--)
 188.605 +        rv *= Dims[b-1];
 188.606 +
 188.607 +    return rv;
 188.608 +}
 188.609 +
 188.610 +static
 188.611 +void* CLUTElemDup(cmsStage* mpe)
 188.612 +{
 188.613 +    _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data;
 188.614 +    _cmsStageCLutData* NewElem;
 188.615 +
 188.616 +
 188.617 +    NewElem = (_cmsStageCLutData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageCLutData));
 188.618 +    if (NewElem == NULL) return NULL;
 188.619 +
 188.620 +    NewElem ->nEntries       = Data ->nEntries;
 188.621 +    NewElem ->HasFloatValues = Data ->HasFloatValues;
 188.622 +
 188.623 +    if (Data ->Tab.T) {
 188.624 +
 188.625 +        if (Data ->HasFloatValues)
 188.626 +            NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.TFloat, Data ->nEntries * sizeof (cmsFloat32Number));
 188.627 +        else
 188.628 +            NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number));
 188.629 +    }
 188.630 +
 188.631 +    NewElem ->Params   = _cmsComputeInterpParamsEx(mpe ->ContextID,
 188.632 +                                                   Data ->Params ->nSamples,
 188.633 +                                                   Data ->Params ->nInputs,
 188.634 +                                                   Data ->Params ->nOutputs,
 188.635 +                                                   NewElem ->Tab.T,
 188.636 +                                                   Data ->Params ->dwFlags);
 188.637 +
 188.638 +    return (void*) NewElem;
 188.639 +}
 188.640 +
 188.641 +
 188.642 +static
 188.643 +void CLutElemTypeFree(cmsStage* mpe)
 188.644 +{
 188.645 +
 188.646 +    _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data;
 188.647 +
 188.648 +    // Already empty
 188.649 +    if (Data == NULL) return;
 188.650 +
 188.651 +    // This works for both types
 188.652 +    if (Data -> Tab.T)
 188.653 +        _cmsFree(mpe ->ContextID, Data -> Tab.T);
 188.654 +
 188.655 +    _cmsFreeInterpParams(Data ->Params);
 188.656 +    _cmsFree(mpe ->ContextID, mpe ->Data);
 188.657 +}
 188.658 +
 188.659 +
 188.660 +// Allocates a 16-bit multidimensional CLUT. This is evaluated at 16-bit precision. Table may have different
 188.661 +// granularity on each dimension.
 188.662 +cmsStage* CMSEXPORT cmsStageAllocCLut16bitGranular(cmsContext ContextID,
 188.663 +                                         const cmsUInt32Number clutPoints[],
 188.664 +                                         cmsUInt32Number inputChan,
 188.665 +                                         cmsUInt32Number outputChan,
 188.666 +                                         const cmsUInt16Number* Table)
 188.667 +{
 188.668 +    cmsUInt32Number i, n;
 188.669 +    _cmsStageCLutData* NewElem;
 188.670 +    cmsStage* NewMPE;
 188.671 +
 188.672 +    NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCLutElemType, inputChan, outputChan,
 188.673 +                                     EvaluateCLUTfloatIn16, CLUTElemDup, CLutElemTypeFree, NULL );
 188.674 +
 188.675 +    if (NewMPE == NULL) return NULL;
 188.676 +
 188.677 +    NewElem = (_cmsStageCLutData*) _cmsMalloc(ContextID, sizeof(_cmsStageCLutData));
 188.678 +    if (NewElem == NULL) return NULL;
 188.679 +
 188.680 +    NewElem -> nEntries = n = outputChan * CubeSize(clutPoints, inputChan);
 188.681 +    NewElem -> HasFloatValues = FALSE;
 188.682 +
 188.683 +    NewElem ->Tab.T  = (cmsUInt16Number*) _cmsCalloc(ContextID, n, sizeof(cmsUInt16Number));
 188.684 +    if (NewElem ->Tab.T == NULL) {
 188.685 +        cmsStageFree(NewMPE);
 188.686 +        return NULL;
 188.687 +    }
 188.688 +
 188.689 +    if (Table != NULL) {
 188.690 +        for (i=0; i < n; i++) {
 188.691 +            NewElem ->Tab.T[i] = Table[i];
 188.692 +        }
 188.693 +    }
 188.694 +
 188.695 +    NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints, inputChan, outputChan, NewElem ->Tab.T, CMS_LERP_FLAGS_16BITS);
 188.696 +    if (NewElem ->Params == NULL) {
 188.697 +        cmsStageFree(NewMPE);
 188.698 +        return NULL;
 188.699 +    }
 188.700 +
 188.701 +    NewMPE ->Data  = (void*) NewElem;
 188.702 +
 188.703 +    return NewMPE;
 188.704 +}
 188.705 +
 188.706 +cmsStage* CMSEXPORT cmsStageAllocCLut16bit(cmsContext ContextID,
 188.707 +                                    cmsUInt32Number nGridPoints,
 188.708 +                                    cmsUInt32Number inputChan,
 188.709 +                                    cmsUInt32Number outputChan,
 188.710 +                                    const cmsUInt16Number* Table)
 188.711 +{
 188.712 +    cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
 188.713 +    int i;
 188.714 +
 188.715 +   // Our resulting LUT would be same gridpoints on all dimensions
 188.716 +    for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
 188.717 +        Dimensions[i] = nGridPoints;
 188.718 +
 188.719 +
 188.720 +    return cmsStageAllocCLut16bitGranular(ContextID, Dimensions, inputChan, outputChan, Table);
 188.721 +}
 188.722 +
 188.723 +
 188.724 +cmsStage* CMSEXPORT cmsStageAllocCLutFloat(cmsContext ContextID,
 188.725 +                                       cmsUInt32Number nGridPoints,
 188.726 +                                       cmsUInt32Number inputChan,
 188.727 +                                       cmsUInt32Number outputChan,
 188.728 +                                       const cmsFloat32Number* Table)
 188.729 +{
 188.730 +   cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
 188.731 +   int i;
 188.732 +
 188.733 +    // Our resulting LUT would be same gridpoints on all dimensions
 188.734 +    for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
 188.735 +        Dimensions[i] = nGridPoints;
 188.736 +
 188.737 +    return cmsStageAllocCLutFloatGranular(ContextID, Dimensions, inputChan, outputChan, Table);
 188.738 +}
 188.739 +
 188.740 +
 188.741 +
 188.742 +cmsStage* CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const cmsUInt32Number clutPoints[], cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsFloat32Number* Table)
 188.743 +{
 188.744 +    cmsUInt32Number i, n;
 188.745 +    _cmsStageCLutData* NewElem;
 188.746 +    cmsStage* NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCLutElemType, inputChan, outputChan,
 188.747 +                                             EvaluateCLUTfloat, CLUTElemDup, CLutElemTypeFree, NULL);
 188.748 +
 188.749 +    if (NewMPE == NULL) return NULL;
 188.750 +
 188.751 +
 188.752 +    NewElem = (_cmsStageCLutData*) _cmsMalloc(ContextID, sizeof(_cmsStageCLutData));
 188.753 +    if (NewElem == NULL) return NULL;
 188.754 +
 188.755 +    NewElem -> nEntries = n = outputChan * CubeSize( clutPoints, inputChan);
 188.756 +    NewElem -> HasFloatValues = TRUE;
 188.757 +
 188.758 +    NewElem ->Tab.TFloat  = (cmsFloat32Number*) _cmsCalloc(ContextID, n, sizeof(cmsFloat32Number));
 188.759 +    if (NewElem ->Tab.TFloat == NULL) {
 188.760 +        cmsStageFree(NewMPE);
 188.761 +        return NULL;
 188.762 +    }
 188.763 +
 188.764 +    if (Table != NULL) {
 188.765 +        for (i=0; i < n; i++) {
 188.766 +            NewElem ->Tab.TFloat[i] = Table[i];
 188.767 +        }
 188.768 +    }
 188.769 +
 188.770 +    NewMPE ->Data  = (void*) NewElem;
 188.771 +
 188.772 +    NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints,  inputChan, outputChan, NewElem ->Tab.TFloat, CMS_LERP_FLAGS_FLOAT);
 188.773 +    if (NewElem ->Params == NULL) {
 188.774 +        cmsStageFree(NewMPE);
 188.775 +        return NULL;
 188.776 +    }
 188.777 +
 188.778 +
 188.779 +
 188.780 +    return NewMPE;
 188.781 +}
 188.782 +
 188.783 +
 188.784 +static
 188.785 +int IdentitySampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo)
 188.786 +{
 188.787 +    int nChan = *(int*) Cargo;
 188.788 +    int i;
 188.789 +
 188.790 +    for (i=0; i < nChan; i++)
 188.791 +        Out[i] = In[i];
 188.792 +
 188.793 +    return 1;
 188.794 +}
 188.795 +
 188.796 +// Creates an MPE that just copies input to output
 188.797 +cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan)
 188.798 +{
 188.799 +    cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
 188.800 +    cmsStage* mpe ;
 188.801 +    int i;
 188.802 +
 188.803 +    for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
 188.804 +        Dimensions[i] = 2;
 188.805 +
 188.806 +    mpe = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, nChan, nChan, NULL);
 188.807 +    if (mpe == NULL) return NULL;
 188.808 +
 188.809 +    if (!cmsStageSampleCLut16bit(mpe, IdentitySampler, &nChan, 0)) {
 188.810 +        cmsStageFree(mpe);
 188.811 +        return NULL;
 188.812 +    }
 188.813 +
 188.814 +    mpe ->Implements = cmsSigIdentityElemType;
 188.815 +    return mpe;
 188.816 +}
 188.817 +
 188.818 +
 188.819 +
 188.820 +// Quantize a value 0 <= i < MaxSamples to 0..0xffff
 188.821 +cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples)
 188.822 +{
 188.823 +    cmsFloat64Number x;
 188.824 +
 188.825 +    x = ((cmsFloat64Number) i * 65535.) / (cmsFloat64Number) (MaxSamples - 1);
 188.826 +    return _cmsQuickSaturateWord(x);
 188.827 +}
 188.828 +
 188.829 +
 188.830 +// This routine does a sweep on whole input space, and calls its callback
 188.831 +// function on knots. returns TRUE if all ok, FALSE otherwise.
 188.832 +cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void * Cargo, cmsUInt32Number dwFlags)
 188.833 +{
 188.834 +    int i, t, nTotalPoints, index, rest;
 188.835 +    int nInputs, nOutputs;
 188.836 +    cmsUInt32Number* nSamples;
 188.837 +    cmsUInt16Number In[cmsMAXCHANNELS], Out[MAX_STAGE_CHANNELS];
 188.838 +    _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data;
 188.839 +
 188.840 +
 188.841 +    nSamples = clut->Params ->nSamples;
 188.842 +    nInputs  = clut->Params ->nInputs;
 188.843 +    nOutputs = clut->Params ->nOutputs;
 188.844 +
 188.845 +    if (nInputs >= cmsMAXCHANNELS) return FALSE;
 188.846 +    if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
 188.847 +
 188.848 +    nTotalPoints = CubeSize(nSamples, nInputs);
 188.849 +
 188.850 +    index = 0;
 188.851 +    for (i = 0; i < nTotalPoints; i++) {
 188.852 +
 188.853 +        rest = i;
 188.854 +        for (t = nInputs-1; t >=0; --t) {
 188.855 +
 188.856 +            cmsUInt32Number  Colorant = rest % nSamples[t];
 188.857 +
 188.858 +            rest /= nSamples[t];
 188.859 +
 188.860 +            In[t] = _cmsQuantizeVal(Colorant, nSamples[t]);
 188.861 +        }
 188.862 +
 188.863 +        if (clut ->Tab.T != NULL) {
 188.864 +            for (t=0; t < nOutputs; t++)
 188.865 +                Out[t] = clut->Tab.T[index + t];
 188.866 +        }
 188.867 +
 188.868 +        if (!Sampler(In, Out, Cargo))
 188.869 +            return FALSE;
 188.870 +
 188.871 +        if (!(dwFlags & SAMPLER_INSPECT)) {
 188.872 +
 188.873 +            if (clut ->Tab.T != NULL) {
 188.874 +                for (t=0; t < nOutputs; t++)
 188.875 +                    clut->Tab.T[index + t] = Out[t];
 188.876 +            }
 188.877 +        }
 188.878 +
 188.879 +        index += nOutputs;
 188.880      }
 188.881  
 188.882      return TRUE;
 188.883  }
 188.884  
 188.885 -LPLUT LCMSEXPORT cmsAlloc3DGrid(LPLUT NewLUT, int clutPoints, int inputChan, int outputChan)
 188.886 +// Same as anterior, but for floting point
 188.887 +cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void * Cargo, cmsUInt32Number dwFlags)
 188.888  {
 188.889 -    DWORD nTabSize;
 188.890 +    int i, t, nTotalPoints, index, rest;
 188.891 +    int nInputs, nOutputs;
 188.892 +    cmsUInt32Number* nSamples;
 188.893 +    cmsFloat32Number In[cmsMAXCHANNELS], Out[MAX_STAGE_CHANNELS];
 188.894 +    _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data;
 188.895  
 188.896 -       NewLUT -> wFlags       |= LUT_HAS3DGRID;
 188.897 -       NewLUT -> cLutPoints    = clutPoints;
 188.898 -       NewLUT -> InputChan     = inputChan;
 188.899 -       NewLUT -> OutputChan    = outputChan;
 188.900 +    nSamples = clut->Params ->nSamples;
 188.901 +    nInputs  = clut->Params ->nInputs;
 188.902 +    nOutputs = clut->Params ->nOutputs;
 188.903  
 188.904 -       if (!_cmsValidateLUT(NewLUT)) {
 188.905 -         return NULL;
 188.906 -       }
 188.907 +    if (nInputs >= cmsMAXCHANNELS) return FALSE;
 188.908 +    if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
 188.909  
 188.910 -       nTabSize = NewLUT -> OutputChan * UIpow(NewLUT->cLutPoints,
 188.911 -                                               NewLUT->InputChan);
 188.912 +    nTotalPoints = CubeSize(nSamples, nInputs);
 188.913  
 188.914 -       NewLUT -> T = (LPWORD) _cmsCalloc(sizeof(WORD), nTabSize);
 188.915 -       nTabSize *= sizeof(WORD);
 188.916 -       if (NewLUT -> T == NULL) return NULL;
 188.917 +    index = 0;
 188.918 +    for (i = 0; i < nTotalPoints; i++) {
 188.919  
 188.920 -       ZeroMemory(NewLUT -> T, nTabSize);
 188.921 -       NewLUT ->Tsize = nTabSize;
 188.922 +        rest = i;
 188.923 +        for (t = nInputs-1; t >=0; --t) {
 188.924  
 188.925 +            cmsUInt32Number  Colorant = rest % nSamples[t];
 188.926  
 188.927 -       cmsCalcCLUT16Params(NewLUT -> cLutPoints,  NewLUT -> InputChan,
 188.928 -                                                  NewLUT -> OutputChan,
 188.929 -                                                  &NewLUT -> CLut16params);
 188.930 +            rest /= nSamples[t];
 188.931 +
 188.932 +            In[t] =  (cmsFloat32Number) (_cmsQuantizeVal(Colorant, nSamples[t]) / 65535.0);
 188.933 +        }
 188.934 +
 188.935 +        if (clut ->Tab.TFloat != NULL) {
 188.936 +            for (t=0; t < nOutputs; t++)
 188.937 +                Out[t] = clut->Tab.TFloat[index + t];
 188.938 +        }
 188.939 +
 188.940 +        if (!Sampler(In, Out, Cargo))
 188.941 +            return FALSE;
 188.942 +
 188.943 +        if (!(dwFlags & SAMPLER_INSPECT)) {
 188.944 +
 188.945 +            if (clut ->Tab.TFloat != NULL) {
 188.946 +                for (t=0; t < nOutputs; t++)
 188.947 +                    clut->Tab.TFloat[index + t] = Out[t];
 188.948 +            }
 188.949 +        }
 188.950 +
 188.951 +        index += nOutputs;
 188.952 +    }
 188.953 +
 188.954 +    return TRUE;
 188.955 +}
 188.956 +
 188.957 +
 188.958 +
 188.959 +// This routine does a sweep on whole input space, and calls its callback
 188.960 +// function on knots. returns TRUE if all ok, FALSE otherwise.
 188.961 +cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
 188.962 +                                         cmsSAMPLER16 Sampler, void * Cargo)
 188.963 +{
 188.964 +    int i, t, nTotalPoints, rest;
 188.965 +    cmsUInt16Number In[cmsMAXCHANNELS];
 188.966 +
 188.967 +    if (nInputs >= cmsMAXCHANNELS) return FALSE;
 188.968 +
 188.969 +    nTotalPoints = CubeSize(clutPoints, nInputs);
 188.970 +
 188.971 +    for (i = 0; i < nTotalPoints; i++) {
 188.972 +
 188.973 +        rest = i;
 188.974 +        for (t = nInputs-1; t >=0; --t) {
 188.975 +
 188.976 +            cmsUInt32Number  Colorant = rest % clutPoints[t];
 188.977 +
 188.978 +            rest /= clutPoints[t];
 188.979 +            In[t] = _cmsQuantizeVal(Colorant, clutPoints[t]);
 188.980 +
 188.981 +        }
 188.982 +
 188.983 +        if (!Sampler(In, NULL, Cargo))
 188.984 +            return FALSE;
 188.985 +    }
 188.986 +
 188.987 +    return TRUE;
 188.988 +}
 188.989 +
 188.990 +cmsInt32Number CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
 188.991 +                                            cmsSAMPLERFLOAT Sampler, void * Cargo)
 188.992 +{
 188.993 +    int i, t, nTotalPoints, rest;
 188.994 +    cmsFloat32Number In[cmsMAXCHANNELS];
 188.995 +
 188.996 +    if (nInputs >= cmsMAXCHANNELS) return FALSE;
 188.997 +
 188.998 +    nTotalPoints = CubeSize(clutPoints, nInputs);
 188.999 +
188.1000 +    for (i = 0; i < nTotalPoints; i++) {
188.1001 +
188.1002 +        rest = i;
188.1003 +        for (t = nInputs-1; t >=0; --t) {
188.1004 +
188.1005 +            cmsUInt32Number  Colorant = rest % clutPoints[t];
188.1006 +
188.1007 +            rest /= clutPoints[t];
188.1008 +            In[t] =  (cmsFloat32Number) (_cmsQuantizeVal(Colorant, clutPoints[t]) / 65535.0);
188.1009 +
188.1010 +        }
188.1011 +
188.1012 +        if (!Sampler(In, NULL, Cargo))
188.1013 +            return FALSE;
188.1014 +    }
188.1015 +
188.1016 +    return TRUE;
188.1017 +}
188.1018 +
188.1019 +// ********************************************************************************
188.1020 +// Type cmsSigLab2XYZElemType
188.1021 +// ********************************************************************************
188.1022 +
188.1023 +
188.1024 +static
188.1025 +void EvaluateLab2XYZ(const cmsFloat32Number In[],
188.1026 +                     cmsFloat32Number Out[],
188.1027 +                     const cmsStage *mpe)
188.1028 +{
188.1029 +    cmsCIELab Lab;
188.1030 +    cmsCIEXYZ XYZ;
188.1031 +    const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ;
188.1032 +
188.1033 +    // V4 rules
188.1034 +    Lab.L = In[0] * 100.0;
188.1035 +    Lab.a = In[1] * 255.0 - 128.0;
188.1036 +    Lab.b = In[2] * 255.0 - 128.0;
188.1037 +
188.1038 +    cmsLab2XYZ(NULL, &XYZ, &Lab);
188.1039 +
188.1040 +    // From XYZ, range 0..19997 to 0..1.0, note that 1.99997 comes from 0xffff
188.1041 +    // encoded as 1.15 fixed point, so 1 + (32767.0 / 32768.0)
188.1042 +
188.1043 +    Out[0] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.X / XYZadj);
188.1044 +    Out[1] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Y / XYZadj);
188.1045 +    Out[2] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Z / XYZadj);
188.1046 +    return;
188.1047 +
188.1048 +    cmsUNUSED_PARAMETER(mpe);
188.1049 +}
188.1050 +
188.1051 +
188.1052 +// No dup or free routines needed, as the structure has no pointers in it.
188.1053 +cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID)
188.1054 +{
188.1055 +    return _cmsStageAllocPlaceholder(ContextID, cmsSigLab2XYZElemType, 3, 3, EvaluateLab2XYZ, NULL, NULL, NULL);
188.1056 +}
188.1057 +
188.1058 +// ********************************************************************************
188.1059 +
188.1060 +// v2 L=100 is supposed to be placed on 0xFF00. There is no reasonable
188.1061 +// number of gridpoints that would make exact match. However, a prelinearization
188.1062 +// of 258 entries, would map 0xFF00 exactly on entry 257, and this is good to avoid scum dot.
188.1063 +// Almost all what we need but unfortunately, the rest of entries should be scaled by
188.1064 +// (255*257/256) and this is not exact.
188.1065 +
188.1066 +cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID)
188.1067 +{
188.1068 +    cmsStage* mpe;
188.1069 +    cmsToneCurve* LabTable[3];
188.1070 +    int i, j;
188.1071 +
188.1072 +    LabTable[0] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL);
188.1073 +    LabTable[1] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL);
188.1074 +    LabTable[2] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL);
188.1075 +
188.1076 +    for (j=0; j < 3; j++) {
188.1077 +
188.1078 +        if (LabTable[j] == NULL) {
188.1079 +            cmsFreeToneCurveTriple(LabTable);
188.1080 +            return NULL;
188.1081 +        }
188.1082 +
188.1083 +        // We need to map * (0xffff / 0xff00), thats same as (257 / 256)
188.1084 +        // So we can use 258-entry tables to do the trick (i / 257) * (255 * 257) * (257 / 256);
188.1085 +        for (i=0; i < 257; i++)  {
188.1086 +
188.1087 +            LabTable[j]->Table16[i] = (cmsUInt16Number) ((i * 0xffff + 0x80) >> 8);
188.1088 +        }
188.1089 +
188.1090 +        LabTable[j] ->Table16[257] = 0xffff;
188.1091 +    }
188.1092 +
188.1093 +    mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
188.1094 +    cmsFreeToneCurveTriple(LabTable);
188.1095 +
188.1096 +    mpe ->Implements = cmsSigLabV2toV4;
188.1097 +    return mpe;
188.1098 +}
188.1099 +
188.1100 +// ********************************************************************************
188.1101 +
188.1102 +// Matrix-based conversion, which is more accurate, but slower and cannot properly be saved in devicelink profiles
188.1103 +cmsStage* _cmsStageAllocLabV2ToV4(cmsContext ContextID)
188.1104 +{
188.1105 +    static const cmsFloat64Number V2ToV4[] = { 65535.0/65280.0, 0, 0,
188.1106 +                                     0, 65535.0/65280.0, 0,
188.1107 +                                     0, 0, 65535.0/65280.0
188.1108 +                                     };
188.1109 +
188.1110 +    cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, V2ToV4, NULL);
188.1111 +
188.1112 +    if (mpe == NULL) return mpe;
188.1113 +    mpe ->Implements = cmsSigLabV2toV4;
188.1114 +    return mpe;
188.1115 +}
188.1116 +
188.1117 +
188.1118 +// Reverse direction
188.1119 +cmsStage* _cmsStageAllocLabV4ToV2(cmsContext ContextID)
188.1120 +{
188.1121 +    static const cmsFloat64Number V4ToV2[] = { 65280.0/65535.0, 0, 0,
188.1122 +                                     0, 65280.0/65535.0, 0,
188.1123 +                                     0, 0, 65280.0/65535.0
188.1124 +                                     };
188.1125 +
188.1126 +     cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, V4ToV2, NULL);
188.1127 +
188.1128 +    if (mpe == NULL) return mpe;
188.1129 +    mpe ->Implements = cmsSigLabV4toV2;
188.1130 +    return mpe;
188.1131 +}
188.1132 +
188.1133 +
188.1134 +// ********************************************************************************
188.1135 +// Type cmsSigXYZ2LabElemType
188.1136 +// ********************************************************************************
188.1137 +
188.1138 +static
188.1139 +void EvaluateXYZ2Lab(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
188.1140 +{
188.1141 +    cmsCIELab Lab;
188.1142 +    cmsCIEXYZ XYZ;
188.1143 +    const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ;
188.1144 +
188.1145 +    // From 0..1.0 to XYZ
188.1146 +
188.1147 +    XYZ.X = In[0] * XYZadj;
188.1148 +    XYZ.Y = In[1] * XYZadj;
188.1149 +    XYZ.Z = In[2] * XYZadj;
188.1150 +
188.1151 +    cmsXYZ2Lab(NULL, &Lab, &XYZ);
188.1152 +
188.1153 +    // From V4 Lab to 0..1.0
188.1154 +
188.1155 +    Out[0] = (cmsFloat32Number) (Lab.L / 100.0);
188.1156 +    Out[1] = (cmsFloat32Number) ((Lab.a + 128.0) / 255.0);
188.1157 +    Out[2] = (cmsFloat32Number) ((Lab.b + 128.0) / 255.0);
188.1158 +    return;
188.1159 +
188.1160 +    cmsUNUSED_PARAMETER(mpe);
188.1161 +}
188.1162 +
188.1163 +cmsStage* _cmsStageAllocXYZ2Lab(cmsContext ContextID)
188.1164 +{
188.1165 +    return _cmsStageAllocPlaceholder(ContextID, cmsSigXYZ2LabElemType, 3, 3, EvaluateXYZ2Lab, NULL, NULL, NULL);
188.1166 +
188.1167 +}
188.1168 +
188.1169 +// ********************************************************************************
188.1170 +
188.1171 +// For v4, S-Shaped curves are placed in a/b axis to increase resolution near gray
188.1172 +
188.1173 +cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID)
188.1174 +{
188.1175 +    cmsToneCurve* LabTable[3];
188.1176 +    cmsFloat64Number Params[1] =  {2.4} ;
188.1177 +
188.1178 +    LabTable[0] = cmsBuildGamma(ContextID, 1.0);
188.1179 +    LabTable[1] = cmsBuildParametricToneCurve(ContextID, 108, Params);
188.1180 +    LabTable[2] = cmsBuildParametricToneCurve(ContextID, 108, Params);
188.1181 +
188.1182 +    return cmsStageAllocToneCurves(ContextID, 3, LabTable);
188.1183 +}
188.1184 +
188.1185 +
188.1186 +// Free a single MPE
188.1187 +void CMSEXPORT cmsStageFree(cmsStage* mpe)
188.1188 +{
188.1189 +    if (mpe ->FreePtr)
188.1190 +        mpe ->FreePtr(mpe);
188.1191 +
188.1192 +    _cmsFree(mpe ->ContextID, mpe);
188.1193 +}
188.1194 +
188.1195 +
188.1196 +cmsUInt32Number  CMSEXPORT cmsStageInputChannels(const cmsStage* mpe)
188.1197 +{
188.1198 +    return mpe ->InputChannels;
188.1199 +}
188.1200 +
188.1201 +cmsUInt32Number  CMSEXPORT cmsStageOutputChannels(const cmsStage* mpe)
188.1202 +{
188.1203 +    return mpe ->OutputChannels;
188.1204 +}
188.1205 +
188.1206 +cmsStageSignature CMSEXPORT cmsStageType(const cmsStage* mpe)
188.1207 +{
188.1208 +    return mpe -> Type;
188.1209 +}
188.1210 +
188.1211 +void* CMSEXPORT cmsStageData(const cmsStage* mpe)
188.1212 +{
188.1213 +    return mpe -> Data;
188.1214 +}
188.1215 +
188.1216 +cmsStage*  CMSEXPORT cmsStageNext(const cmsStage* mpe)
188.1217 +{
188.1218 +    return mpe -> Next;
188.1219 +}
188.1220 +
188.1221 +
188.1222 +// Duplicates an MPE
188.1223 +cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe)
188.1224 +{
188.1225 +    cmsStage* NewMPE;
188.1226 +
188.1227 +    if (mpe == NULL) return NULL;
188.1228 +    NewMPE = _cmsStageAllocPlaceholder(mpe ->ContextID,
188.1229 +                                     mpe ->Type,
188.1230 +                                     mpe ->InputChannels,
188.1231 +                                     mpe ->OutputChannels,
188.1232 +                                     mpe ->EvalPtr,
188.1233 +                                     mpe ->DupElemPtr,
188.1234 +                                     mpe ->FreePtr,
188.1235 +                                     NULL);
188.1236 +    if (NewMPE == NULL) return NULL;
188.1237 +
188.1238 +    NewMPE ->Implements     = mpe ->Implements;
188.1239 +
188.1240 +    if (mpe ->DupElemPtr)
188.1241 +        NewMPE ->Data       = mpe ->DupElemPtr(mpe);
188.1242 +    else
188.1243 +        NewMPE ->Data       = NULL;
188.1244 +
188.1245 +    return NewMPE;
188.1246 +}
188.1247 +
188.1248 +
188.1249 +// ***********************************************************************************************************
188.1250 +
188.1251 +// This function sets up the channel count
188.1252 +
188.1253 +static
188.1254 +void BlessLUT(cmsPipeline* lut)
188.1255 +{
188.1256 +    // We can set the input/ouput channels only if we have elements.
188.1257 +    if (lut ->Elements != NULL) {
188.1258 +
188.1259 +        cmsStage *First, *Last;
188.1260 +
188.1261 +        First  = cmsPipelineGetPtrToFirstStage(lut);
188.1262 +        Last   = cmsPipelineGetPtrToLastStage(lut);
188.1263 +
188.1264 +        if (First != NULL)lut ->InputChannels = First ->InputChannels;
188.1265 +        if (Last != NULL) lut ->OutputChannels = Last ->OutputChannels;
188.1266 +    }
188.1267 +}
188.1268 +
188.1269 +
188.1270 +// Default to evaluate the LUT on 16 bit-basis. Precision is retained.
188.1271 +static
188.1272 +void _LUTeval16(register const cmsUInt16Number In[], register cmsUInt16Number Out[],  register const void* D)
188.1273 +{
188.1274 +    cmsPipeline* lut = (cmsPipeline*) D;
188.1275 +    cmsStage *mpe;
188.1276 +    cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS];
188.1277 +    int Phase = 0, NextPhase;
188.1278 +
188.1279 +    From16ToFloat(In, &Storage[Phase][0], lut ->InputChannels);
188.1280 +
188.1281 +    for (mpe = lut ->Elements;
188.1282 +         mpe != NULL;
188.1283 +         mpe = mpe ->Next) {
188.1284 +
188.1285 +             NextPhase = Phase ^ 1;
188.1286 +             mpe ->EvalPtr(&Storage[Phase][0], &Storage[NextPhase][0], mpe);
188.1287 +             Phase = NextPhase;
188.1288 +    }
188.1289 +
188.1290 +
188.1291 +    FromFloatTo16(&Storage[Phase][0], Out, lut ->OutputChannels);
188.1292 +}
188.1293 +
188.1294 +
188.1295 +
188.1296 +// Does evaluate the LUT on cmsFloat32Number-basis.
188.1297 +static
188.1298 +void _LUTevalFloat(register const cmsFloat32Number In[], register cmsFloat32Number Out[], const void* D)
188.1299 +{
188.1300 +    cmsPipeline* lut = (cmsPipeline*) D;
188.1301 +    cmsStage *mpe;
188.1302 +    cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS];
188.1303 +    int Phase = 0, NextPhase;
188.1304 +
188.1305 +    memmove(&Storage[Phase][0], In, lut ->InputChannels  * sizeof(cmsFloat32Number));
188.1306 +
188.1307 +    for (mpe = lut ->Elements;
188.1308 +         mpe != NULL;
188.1309 +         mpe = mpe ->Next) {
188.1310 +
188.1311 +              NextPhase = Phase ^ 1;
188.1312 +              mpe ->EvalPtr(&Storage[Phase][0], &Storage[NextPhase][0], mpe);
188.1313 +              Phase = NextPhase;
188.1314 +    }
188.1315 +
188.1316 +    memmove(Out, &Storage[Phase][0], lut ->OutputChannels * sizeof(cmsFloat32Number));
188.1317 +}
188.1318 +
188.1319 +
188.1320 +
188.1321 +
188.1322 +// LUT Creation & Destruction
188.1323 +
188.1324 +cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels)
188.1325 +{
188.1326 +       cmsPipeline* NewLUT;
188.1327 +
188.1328 +       if (InputChannels >= cmsMAXCHANNELS ||
188.1329 +           OutputChannels >= cmsMAXCHANNELS) return NULL;
188.1330 +
188.1331 +       NewLUT = (cmsPipeline*) _cmsMallocZero(ContextID, sizeof(cmsPipeline));
188.1332 +       if (NewLUT == NULL) return NULL;
188.1333 +
188.1334 +
188.1335 +       NewLUT -> InputChannels  = InputChannels;
188.1336 +       NewLUT -> OutputChannels = OutputChannels;
188.1337 +
188.1338 +       NewLUT ->Eval16Fn    = _LUTeval16;
188.1339 +       NewLUT ->EvalFloatFn = _LUTevalFloat;
188.1340 +       NewLUT ->DupDataFn   = NULL;
188.1341 +       NewLUT ->FreeDataFn  = NULL;
188.1342 +       NewLUT ->Data        = NewLUT;
188.1343 +
188.1344 +       NewLUT ->ContextID    = ContextID;
188.1345 +
188.1346 +       BlessLUT(NewLUT);
188.1347  
188.1348         return NewLUT;
188.1349  }
188.1350  
188.1351  
188.1352 -
188.1353 -
188.1354 -LPLUT LCMSEXPORT cmsAllocLinearTable(LPLUT NewLUT, LPGAMMATABLE Tables[], int nTable)
188.1355 +cmsUInt32Number CMSEXPORT cmsPipelineInputChannels(const cmsPipeline* lut)
188.1356  {
188.1357 -       unsigned int i;
188.1358 -       LPWORD PtrW;
188.1359 -
188.1360 -       switch (nTable) {
188.1361 -
188.1362 -
188.1363 -       case 1: NewLUT -> wFlags |= LUT_HASTL1;
188.1364 -               cmsCalcL16Params(Tables[0] -> nEntries, &NewLUT -> In16params);
188.1365 -               NewLUT -> InputEntries = Tables[0] -> nEntries;
188.1366 -
188.1367 -               for (i=0; i < NewLUT -> InputChan; i++) {
188.1368 -
188.1369 -                     PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> InputEntries);
188.1370 -                     if (PtrW == NULL) return NULL;
188.1371 -
188.1372 -                     NewLUT -> L1[i] = PtrW;
188.1373 -                     CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> InputEntries);
188.1374 -                     CopyMemory(&NewLUT -> LCurvesSeed[0][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
188.1375 -               }
188.1376 -
188.1377 -
188.1378 -               break;
188.1379 -
188.1380 -       case 2: NewLUT -> wFlags |= LUT_HASTL2;
188.1381 -               cmsCalcL16Params(Tables[0] -> nEntries, &NewLUT -> Out16params);
188.1382 -               NewLUT -> OutputEntries = Tables[0] -> nEntries;
188.1383 -               for (i=0; i < NewLUT -> OutputChan; i++) {
188.1384 -
188.1385 -                     PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> OutputEntries);
188.1386 -                     if (PtrW == NULL) return NULL;
188.1387 -
188.1388 -                     NewLUT -> L2[i] = PtrW;
188.1389 -                     CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> OutputEntries);
188.1390 -                     CopyMemory(&NewLUT -> LCurvesSeed[1][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
188.1391 -               }
188.1392 -               break;
188.1393 -
188.1394 -
188.1395 -       // 3 & 4 according ICC 4.0 spec
188.1396 -
188.1397 -       case 3:
188.1398 -               NewLUT -> wFlags |= LUT_HASTL3;
188.1399 -               cmsCalcL16Params(Tables[0] -> nEntries, &NewLUT -> L3params);
188.1400 -               NewLUT -> L3Entries = Tables[0] -> nEntries;
188.1401 -
188.1402 -               for (i=0; i < NewLUT -> InputChan; i++) {
188.1403 -
188.1404 -                     PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> L3Entries);
188.1405 -                     if (PtrW == NULL) return NULL;
188.1406 -
188.1407 -                     NewLUT -> L3[i] = PtrW;
188.1408 -                     CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L3Entries);
188.1409 -                     CopyMemory(&NewLUT -> LCurvesSeed[2][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
188.1410 -               }
188.1411 -               break;
188.1412 -
188.1413 -       case 4:
188.1414 -               NewLUT -> wFlags |= LUT_HASTL4;
188.1415 -               cmsCalcL16Params(Tables[0] -> nEntries, &NewLUT -> L4params);
188.1416 -               NewLUT -> L4Entries = Tables[0] -> nEntries;
188.1417 -               for (i=0; i < NewLUT -> OutputChan; i++) {
188.1418 -
188.1419 -                     PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewLUT -> L4Entries);
188.1420 -                     if (PtrW == NULL) return NULL;
188.1421 -
188.1422 -                     NewLUT -> L4[i] = PtrW;
188.1423 -                     CopyMemory(PtrW, Tables[i]->GammaTable, sizeof(WORD) * NewLUT -> L4Entries);
188.1424 -                     CopyMemory(&NewLUT -> LCurvesSeed[3][i], &Tables[i] -> Seed, sizeof(LCMSGAMMAPARAMS));
188.1425 -               }
188.1426 -               break;
188.1427 -
188.1428 -
188.1429 -       default:;
188.1430 -       }
188.1431 -
188.1432 -       return NewLUT;
188.1433 +    return lut ->InputChannels;
188.1434  }
188.1435  
188.1436 -
188.1437 -// Set the LUT matrix
188.1438 -
188.1439 -LPLUT LCMSEXPORT cmsSetMatrixLUT(LPLUT Lut, LPMAT3 M)
188.1440 +cmsUInt32Number CMSEXPORT cmsPipelineOutputChannels(const cmsPipeline* lut)
188.1441  {
188.1442 -        MAT3toFix(&Lut ->Matrix, M);
188.1443 -
188.1444 -        if (!MAT3isIdentity(&Lut->Matrix, 0.0001))
188.1445 -            Lut ->wFlags |= LUT_HASMATRIX;
188.1446 -
188.1447 -        return Lut;
188.1448 +    return lut ->OutputChannels;
188.1449  }
188.1450  
188.1451 +// Free a profile elements LUT
188.1452 +void CMSEXPORT cmsPipelineFree(cmsPipeline* lut)
188.1453 +{
188.1454 +    cmsStage *mpe, *Next;
188.1455  
188.1456 -// Set matrix & offset, v4 compatible
188.1457 +    if (lut == NULL) return;
188.1458  
188.1459 -LPLUT LCMSEXPORT cmsSetMatrixLUT4(LPLUT Lut, LPMAT3 M, LPVEC3 off, DWORD dwFlags)
188.1460 -{
188.1461 -    WMAT3 WMat;
188.1462 -    WVEC3 Woff;
188.1463 -    VEC3  Zero = {{0, 0, 0}};
188.1464 +    for (mpe = lut ->Elements;
188.1465 +        mpe != NULL;
188.1466 +        mpe = Next) {
188.1467  
188.1468 -        MAT3toFix(&WMat, M);
188.1469 +            Next = mpe ->Next;
188.1470 +            cmsStageFree(mpe);
188.1471 +    }
188.1472  
188.1473 -        if (off == NULL)
188.1474 -                off = &Zero;
188.1475 +    if (lut ->FreeDataFn) lut ->FreeDataFn(lut ->ContextID, lut ->Data);
188.1476  
188.1477 -        VEC3toFix(&Woff, off);
188.1478 -
188.1479 -        // Nop if identity
188.1480 -        if (MAT3isIdentity(&WMat, 0.0001) &&
188.1481 -            (Woff.n[VX] == 0 && Woff.n[VY] == 0 && Woff.n[VZ] == 0))
188.1482 -            return Lut;
188.1483 -
188.1484 -        switch (dwFlags) {
188.1485 -
188.1486 -        case LUT_HASMATRIX:
188.1487 -                Lut ->Matrix = WMat;
188.1488 -                Lut ->wFlags |= LUT_HASMATRIX;
188.1489 -                break;
188.1490 -
188.1491 -        case LUT_HASMATRIX3:
188.1492 -                Lut ->Mat3 = WMat;
188.1493 -                Lut ->Ofs3 = Woff;
188.1494 -                Lut ->wFlags |= LUT_HASMATRIX3;
188.1495 -                break;
188.1496 -
188.1497 -        case LUT_HASMATRIX4:
188.1498 -                Lut ->Mat4 = WMat;
188.1499 -                Lut ->Ofs4 = Woff;
188.1500 -                Lut ->wFlags |= LUT_HASMATRIX4;
188.1501 -                break;
188.1502 -
188.1503 -
188.1504 -        default:;
188.1505 -        }
188.1506 -
188.1507 -        return Lut;
188.1508 +    _cmsFree(lut ->ContextID, lut);
188.1509  }
188.1510  
188.1511  
188.1512 -
188.1513 -// The full evaluator
188.1514 -
188.1515 -void LCMSEXPORT cmsEvalLUT(LPLUT Lut, WORD In[], WORD Out[])
188.1516 +// Default to evaluate the LUT on 16 bit-basis.
188.1517 +void CMSEXPORT cmsPipelineEval16(const cmsUInt16Number In[], cmsUInt16Number Out[],  const cmsPipeline* lut)
188.1518  {
188.1519 -       register unsigned int i;
188.1520 -       WORD StageABC[MAXCHANNELS], StageLMN[MAXCHANNELS];
188.1521 -
188.1522 -
188.1523 -       // Try to speedup things on plain devicelinks
188.1524 -       if (Lut ->wFlags == LUT_HAS3DGRID) {
188.1525 -
188.1526 -            Lut ->CLut16params.Interp3D(In, Out, Lut -> T, &Lut -> CLut16params);
188.1527 -            return;
188.1528 -       }
188.1529 -
188.1530 -
188.1531 -       // Nope, evaluate whole LUT
188.1532 -
188.1533 -       for (i=0; i < Lut -> InputChan; i++)
188.1534 -                            StageABC[i] = In[i];
188.1535 -
188.1536 -
188.1537 -       if (Lut ->wFlags & LUT_V4_OUTPUT_EMULATE_V2) {
188.1538 -
188.1539 -           // Clamp Lab to avoid overflow
188.1540 -           if (StageABC[0] > 0xFF00)
188.1541 -               StageABC[0] = 0xFF00;
188.1542 -
188.1543 -           StageABC[0] = (WORD) FROM_V2_TO_V4(StageABC[0]);
188.1544 -           StageABC[1] = (WORD) FROM_V2_TO_V4(StageABC[1]);
188.1545 -           StageABC[2] = (WORD) FROM_V2_TO_V4(StageABC[2]);
188.1546 -
188.1547 -       }
188.1548 -
188.1549 -       if (Lut ->wFlags & LUT_V2_OUTPUT_EMULATE_V4) {
188.1550 -
188.1551 -           StageABC[0] = (WORD) FROM_V4_TO_V2(StageABC[0]);
188.1552 -           StageABC[1] = (WORD) FROM_V4_TO_V2(StageABC[1]);
188.1553 -           StageABC[2] = (WORD) FROM_V4_TO_V2(StageABC[2]);
188.1554 -       }
188.1555 -
188.1556 -
188.1557 -       // Matrix handling.
188.1558 -
188.1559 -       if (Lut -> wFlags & LUT_HASMATRIX) {
188.1560 -
188.1561 -              WVEC3 InVect, OutVect;
188.1562 -
188.1563 -              // In LUT8 here comes the special gray axis fixup
188.1564 -
188.1565 -              if (Lut ->FixGrayAxes) {
188.1566 -
188.1567 -                  StageABC[1] = _cmsClampWord(StageABC[1] - 128);
188.1568 -                  StageABC[2] = _cmsClampWord(StageABC[2] - 128);
188.1569 -              }
188.1570 -
188.1571 -              // Matrix
188.1572 -
188.1573 -              InVect.n[VX] = ToFixedDomain(StageABC[0]);
188.1574 -              InVect.n[VY] = ToFixedDomain(StageABC[1]);
188.1575 -              InVect.n[VZ] = ToFixedDomain(StageABC[2]);
188.1576 -
188.1577 -
188.1578 -              MAT3evalW(&OutVect, &Lut -> Matrix, &InVect);
188.1579 -
188.1580 -              // PCS in 1Fixed15 format, adjusting
188.1581 -
188.1582 -              StageABC[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX]));
188.1583 -              StageABC[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY]));
188.1584 -              StageABC[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ]));
188.1585 -       }
188.1586 -
188.1587 -
188.1588 -       // First linearization
188.1589 -
188.1590 -       if (Lut -> wFlags & LUT_HASTL1)
188.1591 -       {
188.1592 -              for (i=0; i < Lut -> InputChan; i++)
188.1593 -                     StageABC[i] = cmsLinearInterpLUT16(StageABC[i],
188.1594 -                                                   Lut -> L1[i],
188.1595 -                                                   &Lut -> In16params);
188.1596 -       }
188.1597 -
188.1598 -
188.1599 -       //  Mat3, Ofs3, L3 processing
188.1600 -
188.1601 -       if (Lut ->wFlags & LUT_HASMATRIX3) {
188.1602 -
188.1603 -              WVEC3 InVect, OutVect;
188.1604 -
188.1605 -              InVect.n[VX] = ToFixedDomain(StageABC[0]);
188.1606 -              InVect.n[VY] = ToFixedDomain(StageABC[1]);
188.1607 -              InVect.n[VZ] = ToFixedDomain(StageABC[2]);
188.1608 -
188.1609 -              MAT3evalW(&OutVect, &Lut -> Mat3, &InVect);
188.1610 -
188.1611 -              OutVect.n[VX] += Lut ->Ofs3.n[VX];
188.1612 -              OutVect.n[VY] += Lut ->Ofs3.n[VY];
188.1613 -              OutVect.n[VZ] += Lut ->Ofs3.n[VZ];
188.1614 -
188.1615 -              StageABC[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX]));
188.1616 -              StageABC[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY]));
188.1617 -              StageABC[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ]));
188.1618 -
188.1619 -       }
188.1620 -
188.1621 -       if (Lut ->wFlags & LUT_HASTL3) {
188.1622 -
188.1623 -             for (i=0; i < Lut -> InputChan; i++)
188.1624 -                     StageABC[i] = cmsLinearInterpLUT16(StageABC[i],
188.1625 -                                                   Lut -> L3[i],
188.1626 -                                                   &Lut -> L3params);
188.1627 -
188.1628 -       }
188.1629 -
188.1630 -
188.1631 -
188.1632 -       if (Lut -> wFlags & LUT_HAS3DGRID) {
188.1633 -
188.1634 -            Lut ->CLut16params.Interp3D(StageABC, StageLMN, Lut -> T, &Lut -> CLut16params);
188.1635 -
188.1636 -       }
188.1637 -       else
188.1638 -       {
188.1639 -
188.1640 -              for (i=0; i < Lut -> InputChan; i++)
188.1641 -                            StageLMN[i] = StageABC[i];
188.1642 -
188.1643 -       }
188.1644 -
188.1645 -
188.1646 -       // Mat4, Ofs4, L4 processing
188.1647 -
188.1648 -       if (Lut ->wFlags & LUT_HASTL4) {
188.1649 -
188.1650 -            for (i=0; i < Lut -> OutputChan; i++)
188.1651 -                     StageLMN[i] = cmsLinearInterpLUT16(StageLMN[i],
188.1652 -                                                   Lut -> L4[i],
188.1653 -                                                   &Lut -> L4params);
188.1654 -       }
188.1655 -
188.1656 -       if (Lut ->wFlags & LUT_HASMATRIX4) {
188.1657 -
188.1658 -              WVEC3 InVect, OutVect;
188.1659 -
188.1660 -              InVect.n[VX] = ToFixedDomain(StageLMN[0]);
188.1661 -              InVect.n[VY] = ToFixedDomain(StageLMN[1]);
188.1662 -              InVect.n[VZ] = ToFixedDomain(StageLMN[2]);
188.1663 -
188.1664 -              MAT3evalW(&OutVect, &Lut -> Mat4, &InVect);
188.1665 -
188.1666 -              OutVect.n[VX] += Lut ->Ofs4.n[VX];
188.1667 -              OutVect.n[VY] += Lut ->Ofs4.n[VY];
188.1668 -              OutVect.n[VZ] += Lut ->Ofs4.n[VZ];
188.1669 -
188.1670 -              StageLMN[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX]));
188.1671 -              StageLMN[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY]));
188.1672 -              StageLMN[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ]));
188.1673 -
188.1674 -       }
188.1675 -
188.1676 -       // Last linearitzation
188.1677 -
188.1678 -       if (Lut -> wFlags & LUT_HASTL2)
188.1679 -       {
188.1680 -              for (i=0; i < Lut -> OutputChan; i++)
188.1681 -                     Out[i] = cmsLinearInterpLUT16(StageLMN[i],
188.1682 -                                                   Lut -> L2[i],
188.1683 -                                                   &Lut -> Out16params);
188.1684 -       }
188.1685 -       else
188.1686 -       {
188.1687 -       for (i=0; i < Lut -> OutputChan; i++)
188.1688 -              Out[i] = StageLMN[i];
188.1689 -       }
188.1690 -
188.1691 -
188.1692 -
188.1693 -       if (Lut ->wFlags & LUT_V4_INPUT_EMULATE_V2) {
188.1694 -
188.1695 -           Out[0] = (WORD) FROM_V4_TO_V2(Out[0]);
188.1696 -           Out[1] = (WORD) FROM_V4_TO_V2(Out[1]);
188.1697 -           Out[2] = (WORD) FROM_V4_TO_V2(Out[2]);
188.1698 -
188.1699 -       }
188.1700 -
188.1701 -       if (Lut ->wFlags & LUT_V2_INPUT_EMULATE_V4) {
188.1702 -
188.1703 -           Out[0] = (WORD) FROM_V2_TO_V4(Out[0]);
188.1704 -           Out[1] = (WORD) FROM_V2_TO_V4(Out[1]);
188.1705 -           Out[2] = (WORD) FROM_V2_TO_V4(Out[2]);
188.1706 -       }
188.1707 +    lut ->Eval16Fn(In, Out, lut->Data);
188.1708  }
188.1709  
188.1710  
188.1711 -// Precomputes tables for 8-bit on input devicelink.
188.1712 -//
188.1713 -LPLUT _cmsBlessLUT8(LPLUT Lut)
188.1714 +// Does evaluate the LUT on cmsFloat32Number-basis.
188.1715 +void CMSEXPORT cmsPipelineEvalFloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsPipeline* lut)
188.1716  {
188.1717 -   int i, j;
188.1718 -   WORD StageABC[3];
188.1719 -   Fixed32 v1, v2, v3;
188.1720 -   LPL8PARAMS p8;
188.1721 -   LPL16PARAMS p = &Lut ->CLut16params;
188.1722 -
188.1723 -
188.1724 -   p8 = (LPL8PARAMS) _cmsMalloc(sizeof(L8PARAMS));
188.1725 -   if (p8 == NULL) return NULL;
188.1726 -
188.1727 -  // values comes * 257, so we can safely take first byte (x << 8 + x)
188.1728 -  // if there are prelinearization, is already smelted in tables
188.1729 -
188.1730 -   for (i=0; i < 256; i++) {
188.1731 -
188.1732 -           StageABC[0] = StageABC[1] = StageABC[2] = RGB_8_TO_16(i);
188.1733 -
188.1734 -           if (Lut ->wFlags & LUT_HASTL1) {
188.1735 -
188.1736 -              for (j=0; j < 3; j++)
188.1737 -                     StageABC[j] = cmsLinearInterpLUT16(StageABC[j],
188.1738 -                                                        Lut -> L1[j],
188.1739 -                                                       &Lut -> In16params);
188.1740 -              Lut ->wFlags &= ~LUT_HASTL1;
188.1741 -           }
188.1742 -
188.1743 -
188.1744 -           v1 = ToFixedDomain(StageABC[0] * p -> Domain);
188.1745 -           v2 = ToFixedDomain(StageABC[1] * p -> Domain);
188.1746 -           v3 = ToFixedDomain(StageABC[2] * p -> Domain);
188.1747 -
188.1748 -           p8 ->X0[i] = p->opta3 * FIXED_TO_INT(v1);
188.1749 -           p8 ->Y0[i] = p->opta2 * FIXED_TO_INT(v2);
188.1750 -           p8 ->Z0[i] = p->opta1 * FIXED_TO_INT(v3);
188.1751 -
188.1752 -           p8 ->rx[i] = (WORD) FIXED_REST_TO_INT(v1);
188.1753 -           p8 ->ry[i] = (WORD) FIXED_REST_TO_INT(v2);
188.1754 -           p8 ->rz[i] = (WORD) FIXED_REST_TO_INT(v3);
188.1755 -
188.1756 -  }
188.1757 -
188.1758 -   Lut -> CLut16params.p8 = p8;
188.1759 -   Lut -> CLut16params.Interp3D = cmsTetrahedralInterp8;
188.1760 -
188.1761 -   return Lut;
188.1762 -
188.1763 +    lut ->EvalFloatFn(In, Out, lut);
188.1764  }
188.1765  
188.1766  
188.1767  
188.1768 +// Duplicates a LUT
188.1769 +cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut)
188.1770 +{
188.1771 +    cmsPipeline* NewLUT;
188.1772 +    cmsStage *NewMPE, *Anterior = NULL, *mpe;
188.1773 +    cmsBool  First = TRUE;
188.1774 +
188.1775 +    if (lut == NULL) return NULL;
188.1776 +
188.1777 +    NewLUT = cmsPipelineAlloc(lut ->ContextID, lut ->InputChannels, lut ->OutputChannels);
188.1778 +    for (mpe = lut ->Elements;
188.1779 +         mpe != NULL;
188.1780 +         mpe = mpe ->Next) {
188.1781 +
188.1782 +             NewMPE = cmsStageDup(mpe);
188.1783 +
188.1784 +             if (NewMPE == NULL) {
188.1785 +                 cmsPipelineFree(NewLUT);
188.1786 +                 return NULL;
188.1787 +             }
188.1788 +
188.1789 +             if (First) {
188.1790 +                 NewLUT ->Elements = NewMPE;
188.1791 +                 First = FALSE;
188.1792 +             }
188.1793 +             else {
188.1794 +                Anterior ->Next = NewMPE;
188.1795 +             }
188.1796 +
188.1797 +            Anterior = NewMPE;
188.1798 +    }
188.1799 +
188.1800 +    NewLUT ->DupDataFn  = lut ->DupDataFn;
188.1801 +    NewLUT ->FreeDataFn = lut ->FreeDataFn;
188.1802 +
188.1803 +    if (NewLUT ->DupDataFn != NULL)
188.1804 +        NewLUT ->Data = NewLUT ->DupDataFn(lut ->ContextID, lut->Data);
188.1805 +
188.1806 +
188.1807 +    NewLUT ->SaveAs8Bits    = lut ->SaveAs8Bits;
188.1808 +
188.1809 +    BlessLUT(NewLUT);
188.1810 +    return NewLUT;
188.1811 +}
188.1812 +
188.1813 +
188.1814 +void CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe)
188.1815 +{
188.1816 +    cmsStage* Anterior = NULL, *pt;
188.1817 +
188.1818 +    switch (loc) {
188.1819 +
188.1820 +        case cmsAT_BEGIN:
188.1821 +            mpe ->Next = lut ->Elements;
188.1822 +            lut ->Elements = mpe;
188.1823 +            break;
188.1824 +
188.1825 +        case cmsAT_END:
188.1826 +
188.1827 +            if (lut ->Elements == NULL)
188.1828 +                lut ->Elements = mpe;
188.1829 +            else {
188.1830 +
188.1831 +                for (pt = lut ->Elements;
188.1832 +                     pt != NULL;
188.1833 +                     pt = pt -> Next) Anterior = pt;
188.1834 +
188.1835 +                Anterior ->Next = mpe;
188.1836 +                mpe ->Next = NULL;
188.1837 +            }
188.1838 +            break;
188.1839 +        default:;
188.1840 +    }
188.1841 +
188.1842 +    BlessLUT(lut);
188.1843 +}
188.1844 +
188.1845 +// Unlink an element and return the pointer to it
188.1846 +void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe)
188.1847 +{
188.1848 +    cmsStage *Anterior, *pt, *Last;
188.1849 +    cmsStage *Unlinked = NULL;
188.1850 +
188.1851 +
188.1852 +    // If empty LUT, there is nothing to remove
188.1853 +    if (lut ->Elements == NULL) {
188.1854 +        if (mpe) *mpe = NULL;
188.1855 +        return;
188.1856 +    }
188.1857 +
188.1858 +    // On depending on the strategy...
188.1859 +    switch (loc) {
188.1860 +
188.1861 +        case cmsAT_BEGIN:
188.1862 +            {
188.1863 +                cmsStage* elem = lut ->Elements;
188.1864 +
188.1865 +                lut ->Elements = elem -> Next;
188.1866 +                elem ->Next = NULL;
188.1867 +                Unlinked = elem;
188.1868 +
188.1869 +            }
188.1870 +            break;
188.1871 +
188.1872 +        case cmsAT_END:
188.1873 +            Anterior = Last = NULL;
188.1874 +            for (pt = lut ->Elements;
188.1875 +                pt != NULL;
188.1876 +                pt = pt -> Next) {
188.1877 +                    Anterior = Last;
188.1878 +                    Last = pt;
188.1879 +            }
188.1880 +
188.1881 +            Unlinked = Last;  // Next already points to NULL
188.1882 +
188.1883 +            // Truncate the chain
188.1884 +            if (Anterior)
188.1885 +                Anterior ->Next = NULL;
188.1886 +            else
188.1887 +                lut ->Elements = NULL;
188.1888 +            break;
188.1889 +        default:;
188.1890 +    }
188.1891 +
188.1892 +    if (mpe)
188.1893 +        *mpe = Unlinked;
188.1894 +    else
188.1895 +        cmsStageFree(Unlinked);
188.1896 +
188.1897 +    BlessLUT(lut);
188.1898 +}
188.1899 +
188.1900 +
188.1901 +// Concatenate two LUT into a new single one
188.1902 +cmsBool  CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2)
188.1903 +{
188.1904 +    cmsStage* mpe, *NewMPE;
188.1905 +
188.1906 +    // If both LUTS does not have elements, we need to inherit
188.1907 +    // the number of channels
188.1908 +    if (l1 ->Elements == NULL && l2 ->Elements == NULL) {
188.1909 +        l1 ->InputChannels  = l2 ->InputChannels;
188.1910 +        l1 ->OutputChannels = l2 ->OutputChannels;
188.1911 +    }
188.1912 +
188.1913 +    // Cat second
188.1914 +    for (mpe = l2 ->Elements;
188.1915 +         mpe != NULL;
188.1916 +         mpe = mpe ->Next) {
188.1917 +
188.1918 +            // We have to dup each element
188.1919 +             NewMPE = cmsStageDup(mpe);
188.1920 +
188.1921 +             if (NewMPE == NULL) {
188.1922 +                 return FALSE;
188.1923 +             }
188.1924 +
188.1925 +             cmsPipelineInsertStage(l1, cmsAT_END, NewMPE);
188.1926 +    }
188.1927 +
188.1928 +  BlessLUT(l1);
188.1929 +  return TRUE;
188.1930 +}
188.1931 +
188.1932 +
188.1933 +cmsBool CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lut, cmsBool On)
188.1934 +{
188.1935 +    cmsBool Anterior = lut ->SaveAs8Bits;
188.1936 +
188.1937 +    lut ->SaveAs8Bits = On;
188.1938 +    return Anterior;
188.1939 +}
188.1940 +
188.1941 +
188.1942 +cmsStage* CMSEXPORT cmsPipelineGetPtrToFirstStage(const cmsPipeline* lut)
188.1943 +{
188.1944 +    return lut ->Elements;
188.1945 +}
188.1946 +
188.1947 +cmsStage* CMSEXPORT cmsPipelineGetPtrToLastStage(const cmsPipeline* lut)
188.1948 +{
188.1949 +    cmsStage *mpe, *Anterior = NULL;
188.1950 +
188.1951 +    for (mpe = lut ->Elements; mpe != NULL; mpe = mpe ->Next)
188.1952 +        Anterior = mpe;
188.1953 +
188.1954 +    return Anterior;
188.1955 +}
188.1956 +
188.1957 +cmsUInt32Number CMSEXPORT cmsPipelineStageCount(const cmsPipeline* lut)
188.1958 +{
188.1959 +    cmsStage *mpe;
188.1960 +    cmsUInt32Number n;
188.1961 +
188.1962 +    for (n=0, mpe = lut ->Elements; mpe != NULL; mpe = mpe ->Next)
188.1963 +            n++;
188.1964 +
188.1965 +    return n;
188.1966 +}
188.1967 +
188.1968 +// This function may be used to set the optional evalueator and a block of private data. If private data is being used, an optional
188.1969 +// duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality.
188.1970 +void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut,
188.1971 +                                        _cmsOPTeval16Fn Eval16,
188.1972 +                                        void* PrivateData,
188.1973 +                                        _cmsOPTfreeDataFn FreePrivateDataFn,
188.1974 +                                        _cmsOPTdupDataFn DupPrivateDataFn)
188.1975 +{
188.1976 +
188.1977 +    Lut ->Eval16Fn = Eval16;
188.1978 +    Lut ->DupDataFn = DupPrivateDataFn;
188.1979 +    Lut ->FreeDataFn = FreePrivateDataFn;
188.1980 +    Lut ->Data = PrivateData;
188.1981 +}
188.1982 +
188.1983  
188.1984  // ----------------------------------------------------------- Reverse interpolation
188.1985 -
188.1986 -
188.1987  // Here's how it goes. The derivative Df(x) of the function f is the linear
188.1988  // transformation that best approximates f near the point x. It can be represented
188.1989  // by a matrix A whose entries are the partial derivatives of the components of f
188.1990 @@ -693,15 +1494,12 @@
188.1991  // if you have a "good enough" initial guess.
188.1992  
188.1993  
188.1994 -#define JACOBIAN_EPSILON            0.001
188.1995 +#define JACOBIAN_EPSILON            0.001f
188.1996  #define INVERSION_MAX_ITERATIONS    30
188.1997  
188.1998 -
188.1999 -
188.2000  // Increment with reflexion on boundary
188.2001 -
188.2002  static
188.2003 -void IncDelta(double *Val)
188.2004 +void IncDelta(cmsFloat32Number *Val)
188.2005  {
188.2006      if (*Val < (1.0 - JACOBIAN_EPSILON))
188.2007  
188.2008 @@ -714,159 +1512,131 @@
188.2009  
188.2010  
188.2011  
188.2012 +// Euclidean distance between two vectors of n elements each one
188.2013  static
188.2014 -void ToEncoded(WORD Encoded[3], LPVEC3 Float)
188.2015 +cmsFloat32Number EuclideanDistance(cmsFloat32Number a[], cmsFloat32Number b[], int n)
188.2016  {
188.2017 -    Encoded[0] = (WORD) floor(Float->n[0] * 65535.0 + 0.5);
188.2018 -    Encoded[1] = (WORD) floor(Float->n[1] * 65535.0 + 0.5);
188.2019 -    Encoded[2] = (WORD) floor(Float->n[2] * 65535.0 + 0.5);
188.2020 +    cmsFloat32Number sum = 0;
188.2021 +    int i;
188.2022 +
188.2023 +    for (i=0; i < n; i++) {
188.2024 +        cmsFloat32Number dif = b[i] - a[i];
188.2025 +        sum +=  dif * dif;
188.2026 +    }
188.2027 +
188.2028 +    return sqrtf(sum);
188.2029  }
188.2030  
188.2031 -static
188.2032 -void FromEncoded(LPVEC3 Float, WORD Encoded[3])
188.2033 +
188.2034 +// Evaluate a LUT in reverse direction. It only searches on 3->3 LUT. Uses Newton method
188.2035 +//
188.2036 +// x1 <- x - [J(x)]^-1 * f(x)
188.2037 +//
188.2038 +// lut: The LUT on where to do the search
188.2039 +// Target: LabK, 3 values of Lab plus destination K which is fixed
188.2040 +// Result: The obtained CMYK
188.2041 +// Hint:   Location where begin the search
188.2042 +
188.2043 +cmsBool CMSEXPORT cmsPipelineEvalReverseFloat(cmsFloat32Number Target[],
188.2044 +                                              cmsFloat32Number Result[],
188.2045 +                                              cmsFloat32Number Hint[],
188.2046 +                                              const cmsPipeline* lut)
188.2047  {
188.2048 -    Float->n[0] = Encoded[0] / 65535.0;
188.2049 -    Float->n[1] = Encoded[1] / 65535.0;
188.2050 -    Float->n[2] = Encoded[2] / 65535.0;
188.2051 -}
188.2052 +    cmsUInt32Number  i, j;
188.2053 +    cmsFloat64Number  error, LastError = 1E20;
188.2054 +    cmsFloat32Number  fx[4], x[4], xd[4], fxd[4];
188.2055 +    cmsVEC3 tmp, tmp2;
188.2056 +    cmsMAT3 Jacobian;
188.2057 +    cmsFloat64Number LastResult[4];
188.2058  
188.2059 -// Evaluates the CLUT part of a LUT (4 -> 3 only)
188.2060 -static
188.2061 -void EvalLUTdoubleKLab(LPLUT Lut, const VEC3* In, WORD FixedK, LPcmsCIELab Out)
188.2062 -{
188.2063 -    WORD wIn[4], wOut[3];
188.2064  
188.2065 -    wIn[0] = (WORD) floor(In ->n[0] * 65535.0 + 0.5);
188.2066 -    wIn[1] = (WORD) floor(In ->n[1] * 65535.0 + 0.5);
188.2067 -    wIn[2] = (WORD) floor(In ->n[2] * 65535.0 + 0.5);
188.2068 -    wIn[3] = FixedK;
188.2069 +    // Only 3->3 and 4->3 are supported
188.2070 +    if (lut ->InputChannels != 3 && lut ->InputChannels != 4) return FALSE;
188.2071 +    if (lut ->OutputChannels != 3) return FALSE;
188.2072  
188.2073 -    cmsEvalLUT(Lut, wIn, wOut);
188.2074 -    cmsLabEncoded2Float(Out, wOut);
188.2075 -}
188.2076 -
188.2077 -// Builds a Jacobian CMY->Lab
188.2078 -
188.2079 -static
188.2080 -void ComputeJacobianLab(LPLUT Lut, LPMAT3 Jacobian, const VEC3* Colorant, WORD K)
188.2081 -{
188.2082 -    VEC3 ColorantD;
188.2083 -    cmsCIELab Lab, LabD;
188.2084 -    int  j;
188.2085 -
188.2086 -    EvalLUTdoubleKLab(Lut, Colorant, K, &Lab);
188.2087 -
188.2088 -
188.2089 -    for (j = 0; j < 3; j++) {
188.2090 -
188.2091 -        ColorantD.n[0] = Colorant ->n[0];
188.2092 -        ColorantD.n[1] = Colorant ->n[1];
188.2093 -        ColorantD.n[2] = Colorant ->n[2];
188.2094 -
188.2095 -        IncDelta(&ColorantD.n[j]);
188.2096 -
188.2097 -        EvalLUTdoubleKLab(Lut, &ColorantD, K, &LabD);
188.2098 -
188.2099 -        Jacobian->v[0].n[j] = ((LabD.L - Lab.L) / JACOBIAN_EPSILON);
188.2100 -        Jacobian->v[1].n[j] = ((LabD.a - Lab.a) / JACOBIAN_EPSILON);
188.2101 -        Jacobian->v[2].n[j] = ((LabD.b - Lab.b) / JACOBIAN_EPSILON);
188.2102 -
188.2103 -    }
188.2104 -}
188.2105 -
188.2106 -
188.2107 -// Evaluate a LUT in reverse direction. It only searches on 3->3 LUT, but It
188.2108 -// can be used on CMYK -> Lab LUT to obtain black preservation.
188.2109 -// Target holds LabK in this case
188.2110 -
188.2111 -// x1 <- x - [J(x)]^-1 * f(x)
188.2112 -
188.2113 -
188.2114 -LCMSAPI double LCMSEXPORT cmsEvalLUTreverse(LPLUT Lut, WORD Target[], WORD Result[], LPWORD Hint)
188.2115 -{
188.2116 -    int      i;
188.2117 -    double     error, LastError = 1E20;
188.2118 -    cmsCIELab  fx, Goal;
188.2119 -    VEC3       tmp, tmp2, x;
188.2120 -    MAT3       Jacobian;
188.2121 -    WORD       FixedK;
188.2122 -    WORD       LastResult[4];
188.2123 -
188.2124 -
188.2125 -    // This is our Lab goal
188.2126 -    cmsLabEncoded2Float(&Goal, Target);
188.2127 -
188.2128 -    // Special case for CMYK->Lab
188.2129 -
188.2130 -    if (Lut ->InputChan == 4)
188.2131 -            FixedK = Target[3];
188.2132 -    else
188.2133 -            FixedK = 0;
188.2134 -
188.2135 +    // Mark result of -1
188.2136 +    LastResult[0] = LastResult[1] = LastResult[2] = -1.0f;
188.2137  
188.2138      // Take the hint as starting point if specified
188.2139 -
188.2140      if (Hint == NULL) {
188.2141  
188.2142 -        // Begin at any point, we choose 1/3 of neutral CMY gray
188.2143 -
188.2144 -        x.n[0] = x.n[1] = x.n[2] = 0.3;
188.2145 -
188.2146 +        // Begin at any point, we choose 1/3 of CMY axis
188.2147 +        x[0] = x[1] = x[2] = 0.3f;
188.2148      }
188.2149      else {
188.2150  
188.2151 -        FromEncoded(&x, Hint);
188.2152 +        // Only copy 3 channels from hint...
188.2153 +        for (j=0; j < 3; j++)
188.2154 +            x[j] = Hint[j];
188.2155      }
188.2156  
188.2157 +    // If Lut is 4-dimensions, then grab target[3], which is fixed
188.2158 +    if (lut ->InputChannels == 4) {
188.2159 +        x[3] = Target[3];
188.2160 +    }
188.2161 +    else x[3] = 0; // To keep lint happy
188.2162 +
188.2163  
188.2164      // Iterate
188.2165 -
188.2166      for (i = 0; i < INVERSION_MAX_ITERATIONS; i++) {
188.2167  
188.2168          // Get beginning fx
188.2169 -        EvalLUTdoubleKLab(Lut, &x, FixedK, &fx);
188.2170 +        cmsPipelineEvalFloat(x, fx, lut);
188.2171  
188.2172          // Compute error
188.2173 -        error = cmsDeltaE(&fx, &Goal);
188.2174 +        error = EuclideanDistance(fx, Target, 3);
188.2175  
188.2176          // If not convergent, return last safe value
188.2177          if (error >= LastError)
188.2178              break;
188.2179  
188.2180          // Keep latest values
188.2181 -        LastError = error;
188.2182 +        LastError     = error;
188.2183 +        for (j=0; j < lut ->InputChannels; j++)
188.2184 +                Result[j] = x[j];
188.2185  
188.2186 -        ToEncoded(LastResult, &x);
188.2187 -        LastResult[3] = FixedK;
188.2188 +        // Found an exact match?
188.2189 +        if (error <= 0)
188.2190 +            break;
188.2191  
188.2192 -        // Obtain slope
188.2193 -        ComputeJacobianLab(Lut, &Jacobian, &x, FixedK);
188.2194 +        // Obtain slope (the Jacobian)
188.2195 +        for (j = 0; j < 3; j++) {
188.2196 +
188.2197 +            xd[0] = x[0];
188.2198 +            xd[1] = x[1];
188.2199 +            xd[2] = x[2];
188.2200 +            xd[3] = x[3];  // Keep fixed channel
188.2201 +
188.2202 +            IncDelta(&xd[j]);
188.2203 +
188.2204 +            cmsPipelineEvalFloat(xd, fxd, lut);
188.2205 +
188.2206 +            Jacobian.v[0].n[j] = ((fxd[0] - fx[0]) / JACOBIAN_EPSILON);
188.2207 +            Jacobian.v[1].n[j] = ((fxd[1] - fx[1]) / JACOBIAN_EPSILON);
188.2208 +            Jacobian.v[2].n[j] = ((fxd[2] - fx[2]) / JACOBIAN_EPSILON);
188.2209 +        }
188.2210  
188.2211          // Solve system
188.2212 -        tmp2.n[0] = fx.L - Goal.L;
188.2213 -        tmp2.n[1] = fx.a - Goal.a;
188.2214 -        tmp2.n[2] = fx.b - Goal.b;
188.2215 +        tmp2.n[0] = fx[0] - Target[0];
188.2216 +        tmp2.n[1] = fx[1] - Target[1];
188.2217 +        tmp2.n[2] = fx[2] - Target[2];
188.2218  
188.2219 -        if (!MAT3solve(&tmp, &Jacobian, &tmp2))
188.2220 -            break;
188.2221 +        if (!_cmsMAT3solve(&tmp, &Jacobian, &tmp2))
188.2222 +            return FALSE;
188.2223  
188.2224          // Move our guess
188.2225 -        x.n[0] -= tmp.n[0];
188.2226 -        x.n[1] -= tmp.n[1];
188.2227 -        x.n[2] -= tmp.n[2];
188.2228 +        x[0] -= (cmsFloat32Number) tmp.n[0];
188.2229 +        x[1] -= (cmsFloat32Number) tmp.n[1];
188.2230 +        x[2] -= (cmsFloat32Number) tmp.n[2];
188.2231  
188.2232          // Some clipping....
188.2233 -        VEC3saturate(&x);
188.2234 +        for (j=0; j < 3; j++) {
188.2235 +            if (x[j] < 0) x[j] = 0;
188.2236 +            else
188.2237 +                if (x[j] > 1.0) x[j] = 1.0;
188.2238 +        }
188.2239      }
188.2240  
188.2241 -    Result[0] = LastResult[0];
188.2242 -    Result[1] = LastResult[1];
188.2243 -    Result[2] = LastResult[2];
188.2244 -    Result[3] = LastResult[3];
188.2245 -
188.2246 -    return LastError;
188.2247 -
188.2248 +    return TRUE;
188.2249  }
188.2250  
188.2251 -
188.2252 -
   189.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsmatsh.c	Thu Sep 23 17:33:40 2010 -0700
   189.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.3 @@ -1,411 +0,0 @@
   189.4 -/*
   189.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   189.6 - *
   189.7 - * This code is free software; you can redistribute it and/or modify it
   189.8 - * under the terms of the GNU General Public License version 2 only, as
   189.9 - * published by the Free Software Foundation.  Oracle designates this
  189.10 - * particular file as subject to the "Classpath" exception as provided
  189.11 - * by Oracle in the LICENSE file that accompanied this code.
  189.12 - *
  189.13 - * This code is distributed in the hope that it will be useful, but WITHOUT
  189.14 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  189.15 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  189.16 - * version 2 for more details (a copy is included in the LICENSE file that
  189.17 - * accompanied this code).
  189.18 - *
  189.19 - * You should have received a copy of the GNU General Public License version
  189.20 - * 2 along with this work; if not, write to the Free Software Foundation,
  189.21 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  189.22 - *
  189.23 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  189.24 - * or visit www.oracle.com if you need additional information or have any
  189.25 - * questions.
  189.26 - */
  189.27 -
  189.28 -// This file is available under and governed by the GNU General Public
  189.29 -// License version 2 only, as published by the Free Software Foundation.
  189.30 -// However, the following notice accompanied the original version of this
  189.31 -// file:
  189.32 -//
  189.33 -//
  189.34 -//  Little cms
  189.35 -//  Copyright (C) 1998-2007 Marti Maria
  189.36 -//
  189.37 -// Permission is hereby granted, free of charge, to any person obtaining
  189.38 -// a copy of this software and associated documentation files (the "Software"),
  189.39 -// to deal in the Software without restriction, including without limitation
  189.40 -// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  189.41 -// and/or sell copies of the Software, and to permit persons to whom the Software
  189.42 -// is furnished to do so, subject to the following conditions:
  189.43 -//
  189.44 -// The above copyright notice and this permission notice shall be included in
  189.45 -// all copies or substantial portions of the Software.
  189.46 -//
  189.47 -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  189.48 -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  189.49 -// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  189.50 -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  189.51 -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  189.52 -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  189.53 -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  189.54 -
  189.55 -
  189.56 -#include "lcms.h"
  189.57 -
  189.58 -
  189.59 -// Shaper/Matrix handling
  189.60 -// This routines handles the matrix-shaper method. A note about domain
  189.61 -// is here required. If the shaper-matrix is invoked on INPUT profiles,
  189.62 -// after the shaper process, we have a value between 0 and 0xFFFF. Thus,
  189.63 -// for proper matrix handling, we must convert it to 15fix16, so
  189.64 -// ToFixedDomain might be called. But cmsLinearInterpFixed() returns
  189.65 -// data yet in fixed point, so no additional process is required.
  189.66 -// Then, we obtain data on 15.16, so we need to shift >> by 1 to
  189.67 -// obtain 1.15 PCS format.
  189.68 -
  189.69 -// On OUTPUT profiles, things are inverse, we must first expand 1 bit
  189.70 -// by shifting left, and then convert result between 0 and 1.000 to
  189.71 -// RGB, so FromFixedDomain() must be called before pass values to
  189.72 -// shaper. Trickly, there is a situation where this shifts works
  189.73 -// little different. Sometimes, lcms smelts input/output
  189.74 -// matrices into a single, one shaper, process. In such cases, since
  189.75 -// input is encoded from 0 to 0xffff, we must first use the shaper and
  189.76 -// then the matrix, an additional FromFixedDomain() must be used to
  189.77 -// accomodate output values.
  189.78 -
  189.79 -// For a sake of simplicity, I will handle this three behaviours
  189.80 -// with different routines, so the flags MATSHAPER_INPUT and MATSHAPER_OUTPUT
  189.81 -// can be conbined to signal smelted matrix-shapers
  189.82 -
  189.83 -
  189.84 -
  189.85 -static
  189.86 -int ComputeTables(LPGAMMATABLE Table[3], LPWORD Out[3], LPL16PARAMS p16)
  189.87 -{
  189.88 -    int i, AllLinear;
  189.89 -
  189.90 -       cmsCalcL16Params(Table[0] -> nEntries, p16);
  189.91 -
  189.92 -       AllLinear = 0;
  189.93 -       for (i=0; i < 3; i++)
  189.94 -       {
  189.95 -        LPWORD PtrW;
  189.96 -
  189.97 -        PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * p16 -> nSamples);
  189.98 -
  189.99 -        if (PtrW == NULL) return -1;  // Signal error
 189.100 -
 189.101 -        CopyMemory(PtrW, Table[i] -> GammaTable, sizeof(WORD) * Table[i] -> nEntries);
 189.102 -
 189.103 -        Out[i] = PtrW;      // Set table pointer
 189.104 -
 189.105 -        // Linear after all?
 189.106 -
 189.107 -        AllLinear   += cmsIsLinear(PtrW, p16 -> nSamples);
 189.108 -       }
 189.109 -
 189.110 -       // If is all linear, then supress table interpolation (this
 189.111 -       // will speed greately some trivial operations.
 189.112 -       // Return 1 if present, 0 if all linear
 189.113 -
 189.114 -
 189.115 -       if (AllLinear != 3) return 1;
 189.116 -
 189.117 -       return 0;
 189.118 -
 189.119 -}
 189.120 -
 189.121 -
 189.122 -LPMATSHAPER cmsAllocMatShaper2(LPMAT3 Matrix, LPGAMMATABLE In[], LPGAMMATABLE Out[], DWORD Behaviour)
 189.123 -{
 189.124 -       LPMATSHAPER NewMatShaper;
 189.125 -       int rc;
 189.126 -
 189.127 -       NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER));
 189.128 -       if (NewMatShaper)
 189.129 -              ZeroMemory(NewMatShaper, sizeof(MATSHAPER));
 189.130 -
 189.131 -       NewMatShaper->dwFlags = Behaviour & (MATSHAPER_ALLSMELTED);
 189.132 -
 189.133 -       // Fill matrix part
 189.134 -
 189.135 -       MAT3toFix(&NewMatShaper -> Matrix, Matrix);
 189.136 -
 189.137 -       // Reality check
 189.138 -
 189.139 -       if (!MAT3isIdentity(&NewMatShaper -> Matrix, 0.00001))
 189.140 -                     NewMatShaper -> dwFlags |= MATSHAPER_HASMATRIX;
 189.141 -
 189.142 -       // Now, on the table characteristics
 189.143 -
 189.144 -       if (Out) {
 189.145 -
 189.146 -            rc = ComputeTables(Out, NewMatShaper ->L, &NewMatShaper ->p16);
 189.147 -            if (rc < 0) {
 189.148 -                 cmsFreeMatShaper(NewMatShaper);
 189.149 -                 return NULL;
 189.150 -            }
 189.151 -            if (rc == 1) NewMatShaper -> dwFlags |= MATSHAPER_HASSHAPER;
 189.152 -       }
 189.153 -
 189.154 -
 189.155 -       if (In) {
 189.156 -
 189.157 -            rc = ComputeTables(In, NewMatShaper ->L2, &NewMatShaper ->p2_16);
 189.158 -            if (rc < 0) {
 189.159 -                cmsFreeMatShaper(NewMatShaper);
 189.160 -                return NULL;
 189.161 -            }
 189.162 -            if (rc == 1) NewMatShaper -> dwFlags |= MATSHAPER_HASINPSHAPER;
 189.163 -       }
 189.164 -
 189.165 -
 189.166 -       return NewMatShaper;
 189.167 -
 189.168 -}
 189.169 -
 189.170 -
 189.171 -
 189.172 -// Creation & Destruction
 189.173 -
 189.174 -LPMATSHAPER cmsAllocMatShaper(LPMAT3 Matrix, LPGAMMATABLE Tables[], DWORD Behaviour)
 189.175 -{
 189.176 -       LPMATSHAPER NewMatShaper;
 189.177 -       int i, AllLinear;
 189.178 -
 189.179 -           if (Matrix == NULL) return NULL;
 189.180 -           for (i=0; i < 3; i++) {
 189.181 -
 189.182 -                   if (Tables[i] == NULL) return NULL;
 189.183 -           }
 189.184 -
 189.185 -       NewMatShaper = (LPMATSHAPER) _cmsMalloc(sizeof(MATSHAPER));
 189.186 -       if (NewMatShaper)
 189.187 -              ZeroMemory(NewMatShaper, sizeof(MATSHAPER));
 189.188 -
 189.189 -       NewMatShaper->dwFlags = Behaviour & (MATSHAPER_ALLSMELTED);
 189.190 -
 189.191 -       // Fill matrix part
 189.192 -
 189.193 -       MAT3toFix(&NewMatShaper -> Matrix, Matrix);
 189.194 -
 189.195 -       // Reality check
 189.196 -
 189.197 -       if (!MAT3isIdentity(&NewMatShaper -> Matrix, 0.00001))
 189.198 -                     NewMatShaper -> dwFlags |= MATSHAPER_HASMATRIX;
 189.199 -
 189.200 -       // Now, on the table characteristics
 189.201 -       cmsCalcL16Params(Tables[0] -> nEntries, &NewMatShaper -> p16);
 189.202 -
 189.203 -       // Copy tables
 189.204 -
 189.205 -       AllLinear = 0;
 189.206 -       for (i=0; i < 3; i++) {
 189.207 -
 189.208 -        LPWORD PtrW;
 189.209 -
 189.210 -        PtrW = (LPWORD) _cmsMalloc(sizeof(WORD) * NewMatShaper -> p16.nSamples);
 189.211 -
 189.212 -        if (PtrW == NULL) {
 189.213 -              cmsFreeMatShaper(NewMatShaper);
 189.214 -              return NULL;
 189.215 -        }
 189.216 -
 189.217 -        CopyMemory(PtrW, Tables[i] -> GammaTable,
 189.218 -                            sizeof(WORD) * Tables[i] -> nEntries);
 189.219 -
 189.220 -        NewMatShaper -> L[i] = PtrW;      // Set table pointer
 189.221 -
 189.222 -        // Linear after all?
 189.223 -
 189.224 -        AllLinear   += cmsIsLinear(PtrW, NewMatShaper -> p16.nSamples);
 189.225 -       }
 189.226 -
 189.227 -       // If is all linear, then supress table interpolation (this
 189.228 -       // will speed greately some trivial operations
 189.229 -
 189.230 -       if (AllLinear != 3)
 189.231 -              NewMatShaper -> dwFlags |= MATSHAPER_HASSHAPER;
 189.232 -
 189.233 -       return NewMatShaper;
 189.234 -}
 189.235 -
 189.236 -
 189.237 -
 189.238 -// Free associated memory
 189.239 -
 189.240 -void cmsFreeMatShaper(LPMATSHAPER MatShaper)
 189.241 -{
 189.242 -       int i;
 189.243 -
 189.244 -       if (!MatShaper) return;
 189.245 -
 189.246 -       for (i=0; i < 3; i++)
 189.247 -       {
 189.248 -              if (MatShaper -> L[i]) _cmsFree(MatShaper ->L[i]);
 189.249 -              if (MatShaper -> L2[i]) _cmsFree(MatShaper ->L2[i]);
 189.250 -       }
 189.251 -
 189.252 -       _cmsFree(MatShaper);
 189.253 -}
 189.254 -
 189.255 -
 189.256 -// All smelted must postpose gamma to last stage.
 189.257 -
 189.258 -static
 189.259 -void AllSmeltedBehaviour(LPMATSHAPER MatShaper, WORD In[], WORD Out[])
 189.260 -{
 189.261 -
 189.262 -       WORD tmp[3];
 189.263 -       WVEC3 InVect, OutVect;
 189.264 -
 189.265 -       if (MatShaper -> dwFlags & MATSHAPER_HASINPSHAPER)
 189.266 -       {
 189.267 -       InVect.n[VX] = cmsLinearInterpFixed(In[0], MatShaper -> L2[0], &MatShaper -> p2_16);
 189.268 -       InVect.n[VY] = cmsLinearInterpFixed(In[1], MatShaper -> L2[1], &MatShaper -> p2_16);
 189.269 -       InVect.n[VZ] = cmsLinearInterpFixed(In[2], MatShaper -> L2[2], &MatShaper -> p2_16);
 189.270 -       }
 189.271 -       else
 189.272 -       {
 189.273 -            InVect.n[VX] = ToFixedDomain(In[0]);
 189.274 -            InVect.n[VY] = ToFixedDomain(In[1]);
 189.275 -            InVect.n[VZ] = ToFixedDomain(In[2]);
 189.276 -       }
 189.277 -
 189.278 -
 189.279 -       if (MatShaper -> dwFlags & MATSHAPER_HASMATRIX)
 189.280 -       {
 189.281 -
 189.282 -             MAT3evalW(&OutVect, &MatShaper -> Matrix, &InVect);
 189.283 -       }
 189.284 -       else {
 189.285 -
 189.286 -           OutVect.n[VX] = InVect.n[VX];
 189.287 -           OutVect.n[VY] = InVect.n[VY];
 189.288 -           OutVect.n[VZ] = InVect.n[VZ];
 189.289 -       }
 189.290 -
 189.291 -
 189.292 -       tmp[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX]));
 189.293 -       tmp[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY]));
 189.294 -       tmp[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ]));
 189.295 -
 189.296 -
 189.297 -
 189.298 -       if (MatShaper -> dwFlags & MATSHAPER_HASSHAPER)
 189.299 -       {
 189.300 -       Out[0] = cmsLinearInterpLUT16(tmp[0], MatShaper -> L[0], &MatShaper -> p16);
 189.301 -       Out[1] = cmsLinearInterpLUT16(tmp[1], MatShaper -> L[1], &MatShaper -> p16);
 189.302 -       Out[2] = cmsLinearInterpLUT16(tmp[2], MatShaper -> L[2], &MatShaper -> p16);
 189.303 -       }
 189.304 -       else
 189.305 -       {
 189.306 -           Out[0] = tmp[0];
 189.307 -           Out[1] = tmp[1];
 189.308 -           Out[2] = tmp[2];
 189.309 -       }
 189.310 -
 189.311 -}
 189.312 -
 189.313 -
 189.314 -static
 189.315 -void InputBehaviour(LPMATSHAPER MatShaper, WORD In[], WORD Out[])
 189.316 -{
 189.317 -       WVEC3 InVect, OutVect;
 189.318 -
 189.319 -
 189.320 -       if (MatShaper -> dwFlags & MATSHAPER_HASSHAPER)
 189.321 -       {
 189.322 -       InVect.n[VX] = cmsLinearInterpFixed(In[0], MatShaper -> L[0], &MatShaper -> p16);
 189.323 -       InVect.n[VY] = cmsLinearInterpFixed(In[1], MatShaper -> L[1], &MatShaper -> p16);
 189.324 -       InVect.n[VZ] = cmsLinearInterpFixed(In[2], MatShaper -> L[2], &MatShaper -> p16);
 189.325 -       }
 189.326 -       else
 189.327 -       {
 189.328 -       InVect.n[VX] = ToFixedDomain(In[0]);
 189.329 -       InVect.n[VY] = ToFixedDomain(In[1]);
 189.330 -       InVect.n[VZ] = ToFixedDomain(In[2]);
 189.331 -       }
 189.332 -
 189.333 -       if (MatShaper -> dwFlags & MATSHAPER_HASMATRIX)
 189.334 -       {
 189.335 -              MAT3evalW(&OutVect, &MatShaper -> Matrix, &InVect);
 189.336 -       }
 189.337 -       else
 189.338 -       {
 189.339 -       OutVect =  InVect;
 189.340 -       }
 189.341 -
 189.342 -       // PCS in 1Fixed15 format, adjusting
 189.343 -
 189.344 -       Out[0] = _cmsClampWord((OutVect.n[VX]) >> 1);
 189.345 -       Out[1] = _cmsClampWord((OutVect.n[VY]) >> 1);
 189.346 -       Out[2] = _cmsClampWord((OutVect.n[VZ]) >> 1);
 189.347 -
 189.348 -}
 189.349 -
 189.350 -
 189.351 -static
 189.352 -void OutputBehaviour(LPMATSHAPER MatShaper, WORD In[], WORD Out[])
 189.353 -{
 189.354 -       WVEC3 InVect, OutVect;
 189.355 -       int i;
 189.356 -
 189.357 -       // We need to convert from XYZ to RGB, here we must
 189.358 -       // shift << 1 to pass between 1.15 to 15.16 formats
 189.359 -
 189.360 -       InVect.n[VX] = (Fixed32) In[0] << 1;
 189.361 -       InVect.n[VY] = (Fixed32) In[1] << 1;
 189.362 -       InVect.n[VZ] = (Fixed32) In[2] << 1;
 189.363 -
 189.364 -       if (MatShaper -> dwFlags & MATSHAPER_HASMATRIX)
 189.365 -       {
 189.366 -              MAT3evalW(&OutVect, &MatShaper -> Matrix, &InVect);
 189.367 -       }
 189.368 -       else
 189.369 -       {
 189.370 -       OutVect = InVect;
 189.371 -       }
 189.372 -
 189.373 -
 189.374 -       if (MatShaper -> dwFlags & MATSHAPER_HASSHAPER)
 189.375 -       {
 189.376 -              for (i=0; i < 3; i++)
 189.377 -              {
 189.378 -
 189.379 -              Out[i] = cmsLinearInterpLUT16(
 189.380 -                     _cmsClampWord(FromFixedDomain(OutVect.n[i])),
 189.381 -                     MatShaper -> L[i],
 189.382 -                     &MatShaper ->p16);
 189.383 -              }
 189.384 -       }
 189.385 -       else
 189.386 -       {
 189.387 -       // Result from fixed domain to RGB
 189.388 -
 189.389 -       Out[0] = _cmsClampWord(FromFixedDomain(OutVect.n[VX]));
 189.390 -       Out[1] = _cmsClampWord(FromFixedDomain(OutVect.n[VY]));
 189.391 -       Out[2] = _cmsClampWord(FromFixedDomain(OutVect.n[VZ]));
 189.392 -       }
 189.393 -
 189.394 -}
 189.395 -
 189.396 -
 189.397 -// Master on evaluating shapers, 3 different behaviours
 189.398 -
 189.399 -void cmsEvalMatShaper(LPMATSHAPER MatShaper, WORD In[], WORD Out[])
 189.400 -{
 189.401 -
 189.402 -       if ((MatShaper -> dwFlags & MATSHAPER_ALLSMELTED) == MATSHAPER_ALLSMELTED)
 189.403 -       {
 189.404 -              AllSmeltedBehaviour(MatShaper, In, Out);
 189.405 -              return;
 189.406 -       }
 189.407 -       if (MatShaper -> dwFlags & MATSHAPER_INPUT)
 189.408 -       {
 189.409 -              InputBehaviour(MatShaper, In, Out);
 189.410 -              return;
 189.411 -       }
 189.412 -
 189.413 -       OutputBehaviour(MatShaper, In, Out);
 189.414 -}
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsmd5.c	Fri Sep 24 16:41:32 2010 -0700
   190.3 @@ -0,0 +1,346 @@
   190.4 +/*
   190.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   190.6 + *
   190.7 + * This code is free software; you can redistribute it and/or modify it
   190.8 + * under the terms of the GNU General Public License version 2 only, as
   190.9 + * published by the Free Software Foundation.  Oracle designates this
  190.10 + * particular file as subject to the "Classpath" exception as provided
  190.11 + * by Oracle in the LICENSE file that accompanied this code.
  190.12 + *
  190.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  190.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  190.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  190.16 + * version 2 for more details (a copy is included in the LICENSE file that
  190.17 + * accompanied this code).
  190.18 + *
  190.19 + * You should have received a copy of the GNU General Public License version
  190.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  190.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  190.22 + *
  190.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  190.24 + * or visit www.oracle.com if you need additional information or have any
  190.25 + * questions.
  190.26 + */
  190.27 +
  190.28 +// This file is available under and governed by the GNU General Public
  190.29 +// License version 2 only, as published by the Free Software Foundation.
  190.30 +// However, the following notice accompanied the original version of this
  190.31 +// file:
  190.32 +//
  190.33 +//---------------------------------------------------------------------------------
  190.34 +//
  190.35 +//  Little Color Management System
  190.36 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  190.37 +//
  190.38 +// Permission is hereby granted, free of charge, to any person obtaining
  190.39 +// a copy of this software and associated documentation files (the "Software"),
  190.40 +// to deal in the Software without restriction, including without limitation
  190.41 +// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  190.42 +// and/or sell copies of the Software, and to permit persons to whom the Software
  190.43 +// is furnished to do so, subject to the following conditions:
  190.44 +//
  190.45 +// The above copyright notice and this permission notice shall be included in
  190.46 +// all copies or substantial portions of the Software.
  190.47 +//
  190.48 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  190.49 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  190.50 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  190.51 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  190.52 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  190.53 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  190.54 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  190.55 +//
  190.56 +//---------------------------------------------------------------------------------
  190.57 +
  190.58 +
  190.59 +#include "lcms2_internal.h"
  190.60 +
  190.61 +#ifdef CMS_USE_BIG_ENDIAN
  190.62 +
  190.63 +static
  190.64 +void byteReverse(cmsUInt8Number * buf, cmsUInt32Number longs)
  190.65 +{
  190.66 +    do {
  190.67 +
  190.68 +        cmsUInt32Number t = _cmsAdjustEndianess32(*(cmsUInt32Number *) buf);
  190.69 +        *(cmsUInt32Number *) buf = t;
  190.70 +        buf += sizeof(cmsUInt32Number);
  190.71 +
  190.72 +    } while (--longs);
  190.73 +
  190.74 +}
  190.75 +
  190.76 +#else
  190.77 +#define byteReverse(buf, len)
  190.78 +#endif
  190.79 +
  190.80 +
  190.81 +typedef struct {
  190.82 +
  190.83 +    cmsUInt32Number buf[4];
  190.84 +    cmsUInt32Number bits[2];
  190.85 +    cmsUInt8Number in[64];
  190.86 +    cmsContext ContextID;
  190.87 +
  190.88 +} _cmsMD5;
  190.89 +
  190.90 +#define F1(x, y, z) (z ^ (x & (y ^ z)))
  190.91 +#define F2(x, y, z) F1(z, x, y)
  190.92 +#define F3(x, y, z) (x ^ y ^ z)
  190.93 +#define F4(x, y, z) (y ^ (x | ~z))
  190.94 +
  190.95 +#define STEP(f, w, x, y, z, data, s) \
  190.96 +    ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
  190.97 +
  190.98 +
  190.99 +static
 190.100 +void MD5_Transform(cmsUInt32Number buf[4], cmsUInt32Number in[16])
 190.101 +
 190.102 +{
 190.103 +    register cmsUInt32Number a, b, c, d;
 190.104 +
 190.105 +    a = buf[0];
 190.106 +    b = buf[1];
 190.107 +    c = buf[2];
 190.108 +    d = buf[3];
 190.109 +
 190.110 +    STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
 190.111 +    STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
 190.112 +    STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
 190.113 +    STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
 190.114 +    STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
 190.115 +    STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
 190.116 +    STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
 190.117 +    STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
 190.118 +    STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
 190.119 +    STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
 190.120 +    STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
 190.121 +    STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
 190.122 +    STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
 190.123 +    STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
 190.124 +    STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
 190.125 +    STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
 190.126 +
 190.127 +    STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
 190.128 +    STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
 190.129 +    STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
 190.130 +    STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
 190.131 +    STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
 190.132 +    STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
 190.133 +    STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
 190.134 +    STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
 190.135 +    STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
 190.136 +    STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
 190.137 +    STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
 190.138 +    STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
 190.139 +    STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
 190.140 +    STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
 190.141 +    STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
 190.142 +    STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
 190.143 +
 190.144 +    STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
 190.145 +    STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
 190.146 +    STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
 190.147 +    STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
 190.148 +    STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
 190.149 +    STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
 190.150 +    STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
 190.151 +    STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
 190.152 +    STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
 190.153 +    STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
 190.154 +    STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
 190.155 +    STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
 190.156 +    STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
 190.157 +    STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
 190.158 +    STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
 190.159 +    STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
 190.160 +
 190.161 +    STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
 190.162 +    STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
 190.163 +    STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
 190.164 +    STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
 190.165 +    STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
 190.166 +    STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
 190.167 +    STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
 190.168 +    STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
 190.169 +    STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
 190.170 +    STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
 190.171 +    STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
 190.172 +    STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
 190.173 +    STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
 190.174 +    STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
 190.175 +    STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
 190.176 +    STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
 190.177 +
 190.178 +    buf[0] += a;
 190.179 +    buf[1] += b;
 190.180 +    buf[2] += c;
 190.181 +    buf[3] += d;
 190.182 +}
 190.183 +
 190.184 +
 190.185 +// Create a MD5 object
 190.186 +static
 190.187 +cmsHANDLE  MD5alloc(cmsContext ContextID)
 190.188 +{
 190.189 +    _cmsMD5* ctx = (_cmsMD5*) _cmsMallocZero(ContextID, sizeof(_cmsMD5));
 190.190 +    if (ctx == NULL) return NULL;
 190.191 +
 190.192 +    ctx ->ContextID = ContextID;
 190.193 +
 190.194 +    ctx->buf[0] = 0x67452301;
 190.195 +    ctx->buf[1] = 0xefcdab89;
 190.196 +    ctx->buf[2] = 0x98badcfe;
 190.197 +    ctx->buf[3] = 0x10325476;
 190.198 +
 190.199 +    ctx->bits[0] = 0;
 190.200 +    ctx->bits[1] = 0;
 190.201 +
 190.202 +    return (cmsHANDLE) ctx;
 190.203 +}
 190.204 +
 190.205 +
 190.206 +static
 190.207 +void MD5add(cmsHANDLE Handle, cmsUInt8Number* buf, cmsUInt32Number len)
 190.208 +{
 190.209 +    _cmsMD5* ctx = (_cmsMD5*) Handle;
 190.210 +    cmsUInt32Number t;
 190.211 +
 190.212 +    t = ctx->bits[0];
 190.213 +    if ((ctx->bits[0] = t + (len << 3)) < t)
 190.214 +        ctx->bits[1]++;
 190.215 +
 190.216 +    ctx->bits[1] += len >> 29;
 190.217 +
 190.218 +    t = (t >> 3) & 0x3f;
 190.219 +
 190.220 +    if (t) {
 190.221 +
 190.222 +        cmsUInt8Number *p = (cmsUInt8Number *) ctx->in + t;
 190.223 +
 190.224 +        t = 64 - t;
 190.225 +        if (len < t) {
 190.226 +            memmove(p, buf, len);
 190.227 +            return;
 190.228 +        }
 190.229 +
 190.230 +        memmove(p, buf, t);
 190.231 +        byteReverse(ctx->in, 16);
 190.232 +
 190.233 +        MD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in);
 190.234 +        buf += t;
 190.235 +        len -= t;
 190.236 +    }
 190.237 +
 190.238 +    while (len >= 64) {
 190.239 +        memmove(ctx->in, buf, 64);
 190.240 +        byteReverse(ctx->in, 16);
 190.241 +        MD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in);
 190.242 +        buf += 64;
 190.243 +        len -= 64;
 190.244 +    }
 190.245 +
 190.246 +    memmove(ctx->in, buf, len);
 190.247 +}
 190.248 +
 190.249 +// Destroy the object and return the checksum
 190.250 +static
 190.251 +void MD5finish(cmsProfileID* ProfileID,  cmsHANDLE Handle)
 190.252 +{
 190.253 +    _cmsMD5* ctx = (_cmsMD5*) Handle;
 190.254 +    cmsUInt32Number count;
 190.255 +    cmsUInt8Number *p;
 190.256 +
 190.257 +    count = (ctx->bits[0] >> 3) & 0x3F;
 190.258 +
 190.259 +    p = ctx->in + count;
 190.260 +    *p++ = 0x80;
 190.261 +
 190.262 +    count = 64 - 1 - count;
 190.263 +
 190.264 +    if (count < 8) {
 190.265 +
 190.266 +        memset(p, 0, count);
 190.267 +        byteReverse(ctx->in, 16);
 190.268 +        MD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in);
 190.269 +
 190.270 +        memset(ctx->in, 0, 56);
 190.271 +    } else {
 190.272 +        memset(p, 0, count - 8);
 190.273 +    }
 190.274 +    byteReverse(ctx->in, 14);
 190.275 +
 190.276 +    ((cmsUInt32Number *) ctx->in)[14] = ctx->bits[0];
 190.277 +    ((cmsUInt32Number *) ctx->in)[15] = ctx->bits[1];
 190.278 +
 190.279 +    MD5_Transform(ctx->buf, (cmsUInt32Number *) ctx->in);
 190.280 +
 190.281 +    byteReverse((cmsUInt8Number *) ctx->buf, 4);
 190.282 +    memmove(ProfileID ->ID8, ctx->buf, 16);
 190.283 +
 190.284 +    _cmsFree(ctx ->ContextID, ctx);
 190.285 +}
 190.286 +
 190.287 +
 190.288 +
 190.289 +// Assuming io points to an ICC profile, compute and store MD5 checksum
 190.290 +// In the header, rendering intentent, attributes and ID should be set to zero
 190.291 +// before computing MD5 checksum (per 6.1.13 in ICC spec)
 190.292 +
 190.293 +cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
 190.294 +{
 190.295 +    cmsContext   ContextID;
 190.296 +    cmsUInt32Number BytesNeeded;
 190.297 +    cmsUInt8Number* Mem = NULL;
 190.298 +    cmsHANDLE  MD5 = NULL;
 190.299 +    _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
 190.300 +    _cmsICCPROFILE Keep;
 190.301 +
 190.302 +    _cmsAssert(hProfile != NULL);
 190.303 +
 190.304 +    ContextID = cmsGetProfileContextID(hProfile);
 190.305 +
 190.306 +    // Save a copy of the profile header
 190.307 +    memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
 190.308 +
 190.309 +    // Set RI, attributes and ID
 190.310 +    memset(&Icc ->attributes, 0, sizeof(Icc ->attributes));
 190.311 +    Icc ->RenderingIntent = 0;
 190.312 +    memset(&Icc ->ProfileID, 0, sizeof(Icc ->ProfileID));
 190.313 +
 190.314 +    // Compute needed storage
 190.315 +    if (!cmsSaveProfileToMem(hProfile, NULL, &BytesNeeded)) goto Error;
 190.316 +
 190.317 +    // Allocate memory
 190.318 +    Mem = (cmsUInt8Number*) _cmsMalloc(ContextID, BytesNeeded);
 190.319 +    if (Mem == NULL) goto Error;
 190.320 +
 190.321 +    // Save to temporary storage
 190.322 +    if (!cmsSaveProfileToMem(hProfile, Mem, &BytesNeeded)) goto Error;
 190.323 +
 190.324 +    // Create MD5 object
 190.325 +    MD5 = MD5alloc(ContextID);
 190.326 +    if (MD5 == NULL) goto Error;
 190.327 +
 190.328 +    // Add all bytes
 190.329 +    MD5add(MD5, Mem, BytesNeeded);
 190.330 +
 190.331 +    // Temp storage is no longer needed
 190.332 +    _cmsFree(ContextID, Mem);
 190.333 +
 190.334 +    // Restore header
 190.335 +    memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
 190.336 +
 190.337 +    // And store the ID
 190.338 +    MD5finish(&Icc ->ProfileID,  MD5);
 190.339 +    return TRUE;
 190.340 +
 190.341 +Error:
 190.342 +
 190.343 +    // Free resources as something went wrong
 190.344 +    if (MD5 != NULL) _cmsFree(ContextID, MD5);
 190.345 +    if (Mem != NULL) _cmsFree(ContextID, Mem);
 190.346 +    memmove(Icc, &Keep, sizeof(_cmsICCPROFILE));
 190.347 +    return FALSE;
 190.348 +}
 190.349 +
   191.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsmtrx.c	Thu Sep 23 17:33:40 2010 -0700
   191.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsmtrx.c	Fri Sep 24 16:41:32 2010 -0700
   191.3 @@ -27,9 +27,10 @@
   191.4  // However, the following notice accompanied the original version of this
   191.5  // file:
   191.6  //
   191.7 +//---------------------------------------------------------------------------------
   191.8  //
   191.9 -//  Little cms
  191.10 -//  Copyright (C) 1998-2007 Marti Maria
  191.11 +//  Little Color Management System
  191.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  191.13  //
  191.14  // Permission is hereby granted, free of charge, to any person obtaining
  191.15  // a copy of this software and associated documentation files (the "Software"),
  191.16 @@ -48,447 +49,105 @@
  191.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  191.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  191.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  191.20 +//
  191.21 +//---------------------------------------------------------------------------------
  191.22 +//
  191.23  
  191.24 -// Vector & Matrix stuff
  191.25 +#include "lcms2_internal.h"
  191.26  
  191.27 -#include "lcms.h"
  191.28  
  191.29 +#define DSWAP(x, y)     {cmsFloat64Number tmp = (x); (x)=(y); (y)=tmp;}
  191.30  
  191.31 -void cdecl VEC3init(LPVEC3 r, double x, double y, double z);
  191.32 -void cdecl VEC3initF(LPWVEC3 r, double x, double y, double z);
  191.33 -void cdecl VEC3toFix(LPWVEC3 r, LPVEC3 v);
  191.34 -void cdecl VEC3scaleFix(LPWORD r, LPWVEC3 Scale);
  191.35 -void cdecl VEC3swap(LPVEC3 a, LPVEC3 b);
  191.36 -void cdecl VEC3divK(LPVEC3 r, LPVEC3 v, double d);
  191.37 -void cdecl VEC3perK(LPVEC3 r, LPVEC3 v, double d);
  191.38 -void cdecl VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b);
  191.39 -void cdecl VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b);
  191.40 -void cdecl VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d);
  191.41 -void cdecl VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v);
  191.42 -void cdecl VEC3saturate(LPVEC3 v);
  191.43  
  191.44 -double cdecl VEC3length(LPVEC3 a);
  191.45 -double cdecl VEC3distance(LPVEC3 a, LPVEC3 b);
  191.46 -
  191.47 -
  191.48 -void      cdecl MAT3identity(LPMAT3 a);
  191.49 -void      cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
  191.50 -int       cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
  191.51 -LCMSBOOL  cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
  191.52 -double    cdecl MAT3det(LPMAT3 m);
  191.53 -void      cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
  191.54 -void      cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
  191.55 -void      cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
  191.56 -void      cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
  191.57 -void      cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
  191.58 -
  191.59 -// --------------------- Implementation ----------------------------
  191.60 -
  191.61 -#define DSWAP(x, y)     {double tmp = (x); (x)=(y); (y)=tmp;}
  191.62 -
  191.63 -
  191.64 -
  191.65 -#ifdef USE_ASSEMBLER
  191.66 -
  191.67 -
  191.68 -#ifdef _MSC_VER
  191.69 -#pragma warning(disable : 4033)
  191.70 -#pragma warning(disable : 4035)
  191.71 -#endif
  191.72 -
  191.73 -
  191.74 -
  191.75 -Fixed32 FixedMul(Fixed32 a, Fixed32 b)
  191.76 +// Initiate a vector
  191.77 +void CMSEXPORT _cmsVEC3init(cmsVEC3* r, cmsFloat64Number x, cmsFloat64Number y, cmsFloat64Number z)
  191.78  {
  191.79 -       ASM {
  191.80 -
  191.81 -              mov    eax, ss:a
  191.82 -              mov    edx, ss:b
  191.83 -              imul   edx
  191.84 -              add    eax, 0x8000
  191.85 -              adc    edx, 0
  191.86 -              shrd   eax, edx, 16
  191.87 -
  191.88 -       }
  191.89 -
  191.90 -       RET(_EAX);
  191.91 +    r -> n[VX] = x;
  191.92 +    r -> n[VY] = y;
  191.93 +    r -> n[VZ] = z;
  191.94  }
  191.95  
  191.96 -
  191.97 -
  191.98 -
  191.99 -Fixed32 FixedSquare(Fixed32 a)
 191.100 -{
 191.101 -       ASM {
 191.102 -              pushf
 191.103 -              push   edx
 191.104 -              mov    eax, ss:a
 191.105 -              imul   eax
 191.106 -              add    eax, 0x8000
 191.107 -              adc    edx, 0
 191.108 -              shrd   eax, edx, 16
 191.109 -              sar    eax, 16
 191.110 -              pop    edx
 191.111 -              popf
 191.112 -       }
 191.113 -
 191.114 -       RET(_EAX);
 191.115 -}
 191.116 -
 191.117 -
 191.118 -
 191.119 -
 191.120 -// Linear intERPolation
 191.121 -// a * (h - l) >> 16 + l
 191.122 -
 191.123 -Fixed32 FixedLERP(Fixed32 a, Fixed32 l, Fixed32 h)
 191.124 -{
 191.125 -       ASM {
 191.126 -              mov    eax, dword ptr ss:h
 191.127 -              mov    edx, dword ptr ss:l
 191.128 -              push   edx
 191.129 -              mov    ecx, dword ptr ss:a
 191.130 -              sub    eax, edx
 191.131 -              imul   ecx
 191.132 -              add    eax, 0x8000
 191.133 -              adc    edx, 0
 191.134 -              shrd   eax, edx, 16
 191.135 -              pop    edx
 191.136 -              add    eax, edx
 191.137 -       }
 191.138 -
 191.139 -       RET(_EAX);
 191.140 -}
 191.141 -
 191.142 -
 191.143 -// a as word is scaled by s as float
 191.144 -
 191.145 -WORD FixedScale(WORD a, Fixed32 s)
 191.146 -{
 191.147 -       ASM {
 191.148 -
 191.149 -              xor    eax,eax
 191.150 -              mov    ax, ss:a        // This is faster that movzx  eax, ss:a
 191.151 -              sal    eax, 16
 191.152 -              mov    edx, ss:s
 191.153 -              mul    edx
 191.154 -              add    eax, 0x8000
 191.155 -              adc    edx, 0
 191.156 -              mov    eax, edx
 191.157 -       }
 191.158 -
 191.159 -       RET(_EAX);
 191.160 -}
 191.161 -
 191.162 -#ifdef _MSC_VER
 191.163 -#pragma warning(default : 4033)
 191.164 -#pragma warning(default : 4035)
 191.165 -#endif
 191.166 -
 191.167 -#else
 191.168 -
 191.169 -
 191.170 -// These are floating point versions for compilers that doesn't
 191.171 -// support asm at all. Use with care, since this will slow down
 191.172 -// all operations
 191.173 -
 191.174 -
 191.175 -Fixed32 FixedMul(Fixed32 a, Fixed32 b)
 191.176 -{
 191.177 -#ifdef USE_INT64
 191.178 -       LCMSULONGLONG l = (LCMSULONGLONG) (LCMSSLONGLONG) a * (LCMSULONGLONG) (LCMSSLONGLONG) b + (LCMSULONGLONG) 0x8000;
 191.179 -       l >>= 16;
 191.180 -       return (Fixed32) l;
 191.181 -#else
 191.182 -       return DOUBLE_TO_FIXED(FIXED_TO_DOUBLE(a) * FIXED_TO_DOUBLE(b));
 191.183 -#endif
 191.184 -}
 191.185 -
 191.186 -Fixed32 FixedSquare(Fixed32 a)
 191.187 -{
 191.188 -       return FixedMul(a, a);
 191.189 -}
 191.190 -
 191.191 -
 191.192 -Fixed32 FixedLERP(Fixed32 a, Fixed32 l, Fixed32 h)
 191.193 -{
 191.194 -#ifdef USE_INT64
 191.195 -
 191.196 -       LCMSULONGLONG dif = (LCMSULONGLONG) (h - l) * a + 0x8000;
 191.197 -       dif = (dif >> 16) + l;
 191.198 -       return (Fixed32) (dif);
 191.199 -#else
 191.200 -       double dif = h - l;
 191.201 -
 191.202 -       dif *= a;
 191.203 -       dif /= 65536.0;
 191.204 -       dif += l;
 191.205 -
 191.206 -       return (Fixed32) (dif + 0.5);
 191.207 -#endif
 191.208 -
 191.209 -}
 191.210 -
 191.211 -
 191.212 -WORD FixedScale(WORD a, Fixed32 s)
 191.213 -{
 191.214 -       return (WORD) (a * FIXED_TO_DOUBLE(s));
 191.215 -}
 191.216 -
 191.217 -#endif
 191.218 -
 191.219 -
 191.220 -#ifndef USE_INLINE
 191.221 -
 191.222 -Fixed32 ToFixedDomain(int a)
 191.223 -{
 191.224 -    return a + ((a + 0x7fff) / 0xffff);
 191.225 -}
 191.226 -
 191.227 -
 191.228 -int FromFixedDomain(Fixed32 a)
 191.229 -{
 191.230 -    return a - ((a + 0x7fff) >> 16);
 191.231 -}
 191.232 -
 191.233 -#endif
 191.234 -
 191.235 -
 191.236 -
 191.237 -// Initiate a vector (double version)
 191.238 -
 191.239 -
 191.240 -void VEC3init(LPVEC3 r, double x, double y, double z)
 191.241 -{
 191.242 -       r -> n[VX] = x;
 191.243 -       r -> n[VY] = y;
 191.244 -       r -> n[VZ] = z;
 191.245 -}
 191.246 -
 191.247 -// Init a vector (fixed version)
 191.248 -
 191.249 -void VEC3initF(LPWVEC3 r, double x, double y, double z)
 191.250 -{
 191.251 -       r -> n[VX] = DOUBLE_TO_FIXED(x);
 191.252 -       r -> n[VY] = DOUBLE_TO_FIXED(y);
 191.253 -       r -> n[VZ] = DOUBLE_TO_FIXED(z);
 191.254 -}
 191.255 -
 191.256 -
 191.257 -// Convert to fixed point encoding is 1.0 = 0xFFFF
 191.258 -
 191.259 -void VEC3toFix(LPWVEC3 r, LPVEC3 v)
 191.260 -{
 191.261 -       r -> n[VX] = DOUBLE_TO_FIXED(v -> n[VX]);
 191.262 -       r -> n[VY] = DOUBLE_TO_FIXED(v -> n[VY]);
 191.263 -       r -> n[VZ] = DOUBLE_TO_FIXED(v -> n[VZ]);
 191.264 -}
 191.265 -
 191.266 -// Convert from fixed point
 191.267 -
 191.268 -void VEC3fromFix(LPVEC3 r, LPWVEC3 v)
 191.269 -{
 191.270 -       r -> n[VX] = FIXED_TO_DOUBLE(v -> n[VX]);
 191.271 -       r -> n[VY] = FIXED_TO_DOUBLE(v -> n[VY]);
 191.272 -       r -> n[VZ] = FIXED_TO_DOUBLE(v -> n[VZ]);
 191.273 -}
 191.274 -
 191.275 -
 191.276 -// Swap two double vectors
 191.277 -
 191.278 -void VEC3swap(LPVEC3 a, LPVEC3 b)
 191.279 -{
 191.280 -        DSWAP(a-> n[VX], b-> n[VX]);
 191.281 -        DSWAP(a-> n[VY], b-> n[VY]);
 191.282 -        DSWAP(a-> n[VZ], b-> n[VZ]);
 191.283 -}
 191.284 -
 191.285 -// Divide a vector by a constant
 191.286 -
 191.287 -void VEC3divK(LPVEC3 r, LPVEC3 v, double d)
 191.288 -{
 191.289 -        double d_inv = 1./d;
 191.290 -
 191.291 -        r -> n[VX] = v -> n[VX] * d_inv;
 191.292 -        r -> n[VY] = v -> n[VY] * d_inv;
 191.293 -        r -> n[VZ] = v -> n[VZ] * d_inv;
 191.294 -}
 191.295 -
 191.296 -// Multiply by a constant
 191.297 -
 191.298 -void VEC3perK(LPVEC3 r, LPVEC3 v, double d )
 191.299 -{
 191.300 -        r -> n[VX] = v -> n[VX] * d;
 191.301 -        r -> n[VY] = v -> n[VY] * d;
 191.302 -        r -> n[VZ] = v -> n[VZ] * d;
 191.303 -}
 191.304 -
 191.305 -
 191.306 -void VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b)
 191.307 -{
 191.308 -       r -> n[VX] = a->n[VX]*b->n[VX];
 191.309 -       r -> n[VY] = a->n[VY]*b->n[VY];
 191.310 -       r -> n[VZ] = a->n[VZ]*b->n[VZ];
 191.311 -}
 191.312 -
 191.313 -// Minus
 191.314 -
 191.315 -
 191.316 -void VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b)
 191.317 +// Vector substraction
 191.318 +void CMSEXPORT _cmsVEC3minus(cmsVEC3* r, const cmsVEC3* a, const cmsVEC3* b)
 191.319  {
 191.320    r -> n[VX] = a -> n[VX] - b -> n[VX];
 191.321    r -> n[VY] = a -> n[VY] - b -> n[VY];
 191.322    r -> n[VZ] = a -> n[VZ] - b -> n[VZ];
 191.323  }
 191.324  
 191.325 -
 191.326 -// Check id two vectors are the same, allowing tolerance
 191.327 -
 191.328 -static
 191.329 -LCMSBOOL RangeCheck(double l, double h, double v)
 191.330 +// Vector cross product
 191.331 +void CMSEXPORT _cmsVEC3cross(cmsVEC3* r, const cmsVEC3* u, const cmsVEC3* v)
 191.332  {
 191.333 -       return (v >= l && v <= h);
 191.334 -}
 191.335 -
 191.336 -
 191.337 -LCMSBOOL VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance)
 191.338 -{
 191.339 -       int i;
 191.340 -       double c;
 191.341 -
 191.342 -       for (i=0; i < 3; i++)
 191.343 -       {
 191.344 -              c = FIXED_TO_DOUBLE(a -> n[i]);
 191.345 -              if (!RangeCheck(c - Tolerance,
 191.346 -                              c + Tolerance,
 191.347 -                              FIXED_TO_DOUBLE(b->n[i]))) return FALSE;
 191.348 -       }
 191.349 -
 191.350 -       return TRUE;
 191.351 -}
 191.352 -
 191.353 -LCMSBOOL VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance)
 191.354 -{
 191.355 -       int i;
 191.356 -       double c;
 191.357 -
 191.358 -       for (i=0; i < 3; i++)
 191.359 -       {
 191.360 -              c = a -> n[i];
 191.361 -              if (!RangeCheck(c - Tolerance,
 191.362 -                              c + Tolerance,
 191.363 -                              b->n[i])) return FALSE;
 191.364 -       }
 191.365 -
 191.366 -       return TRUE;
 191.367 -}
 191.368 -
 191.369 -
 191.370 -void VEC3scaleFix(LPWORD r, LPWVEC3 Scale)
 191.371 -{
 191.372 -       if (Scale -> n[VX] == 0x00010000L &&
 191.373 -           Scale -> n[VY] == 0x00010000L &&
 191.374 -           Scale -> n[VZ] == 0x00010000L) return;
 191.375 -
 191.376 -       r[0] = (WORD) FixedScale(r[0], Scale -> n[VX]);
 191.377 -       r[1] = (WORD) FixedScale(r[1], Scale -> n[VY]);
 191.378 -       r[2] = (WORD) FixedScale(r[2], Scale -> n[VZ]);
 191.379 -
 191.380 -}
 191.381 -
 191.382 -
 191.383 -
 191.384 -// Vector cross product
 191.385 -
 191.386 -void VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v)
 191.387 -{
 191.388 -
 191.389      r ->n[VX] = u->n[VY] * v->n[VZ] - v->n[VY] * u->n[VZ];
 191.390      r ->n[VY] = u->n[VZ] * v->n[VX] - v->n[VZ] * u->n[VX];
 191.391      r ->n[VZ] = u->n[VX] * v->n[VY] - v->n[VX] * u->n[VY];
 191.392  }
 191.393  
 191.394 +// Vector dot product
 191.395 +cmsFloat64Number CMSEXPORT _cmsVEC3dot(const cmsVEC3* u, const cmsVEC3* v)
 191.396 +{
 191.397 +    return u->n[VX] * v->n[VX] + u->n[VY] * v->n[VY] + u->n[VZ] * v->n[VZ];
 191.398 +}
 191.399  
 191.400 -
 191.401 -// The vector size
 191.402 -
 191.403 -double VEC3length(LPVEC3 a)
 191.404 +// Euclidean length
 191.405 +cmsFloat64Number CMSEXPORT _cmsVEC3length(const cmsVEC3* a)
 191.406  {
 191.407      return sqrt(a ->n[VX] * a ->n[VX] +
 191.408                  a ->n[VY] * a ->n[VY] +
 191.409                  a ->n[VZ] * a ->n[VZ]);
 191.410  }
 191.411  
 191.412 -
 191.413 -// Saturate a vector into 0..1.0 range
 191.414 -
 191.415 -void VEC3saturate(LPVEC3 v)
 191.416 +// Euclidean distance
 191.417 +cmsFloat64Number CMSEXPORT _cmsVEC3distance(const cmsVEC3* a, const cmsVEC3* b)
 191.418  {
 191.419 -    int i;
 191.420 -    for (i=0; i < 3; i++) {
 191.421 -        if (v ->n[i] < 0)
 191.422 -                v ->n[i] = 0;
 191.423 -        else
 191.424 -        if (v ->n[i] > 1.0)
 191.425 -                v ->n[i] = 1.0;
 191.426 -    }
 191.427 -}
 191.428 -
 191.429 -
 191.430 -// Euclidean distance
 191.431 -
 191.432 -double VEC3distance(LPVEC3 a, LPVEC3 b)
 191.433 -{
 191.434 -    double d1 = a ->n[VX] - b ->n[VX];
 191.435 -    double d2 = a ->n[VY] - b ->n[VY];
 191.436 -    double d3 = a ->n[VZ] - b ->n[VZ];
 191.437 +    cmsFloat64Number d1 = a ->n[VX] - b ->n[VX];
 191.438 +    cmsFloat64Number d2 = a ->n[VY] - b ->n[VY];
 191.439 +    cmsFloat64Number d3 = a ->n[VZ] - b ->n[VZ];
 191.440  
 191.441      return sqrt(d1*d1 + d2*d2 + d3*d3);
 191.442  }
 191.443  
 191.444  
 191.445 -// Identity
 191.446  
 191.447 -
 191.448 -void MAT3identity(LPMAT3 a)
 191.449 +// 3x3 Identity
 191.450 +void CMSEXPORT _cmsMAT3identity(cmsMAT3* a)
 191.451  {
 191.452 -        VEC3init(&a-> v[0], 1.0, 0.0, 0.0);
 191.453 -        VEC3init(&a-> v[1], 0.0, 1.0, 0.0);
 191.454 -        VEC3init(&a-> v[2], 0.0, 0.0, 1.0);
 191.455 +    _cmsVEC3init(&a-> v[0], 1.0, 0.0, 0.0);
 191.456 +    _cmsVEC3init(&a-> v[1], 0.0, 1.0, 0.0);
 191.457 +    _cmsVEC3init(&a-> v[2], 0.0, 0.0, 1.0);
 191.458  }
 191.459  
 191.460 -
 191.461 -
 191.462 -
 191.463 -// Check if matrix is Identity. Allow a tolerance as %
 191.464 -
 191.465 -LCMSBOOL MAT3isIdentity(LPWMAT3 a, double Tolerance)
 191.466 +static
 191.467 +cmsBool CloseEnough(cmsFloat64Number a, cmsFloat64Number b)
 191.468  {
 191.469 -       int i;
 191.470 -       MAT3 Idd;
 191.471 -       WMAT3 Idf;
 191.472 -
 191.473 -       MAT3identity(&Idd);
 191.474 -       MAT3toFix(&Idf, &Idd);
 191.475 -
 191.476 -       for (i=0; i < 3; i++)
 191.477 -              if (!VEC3equal(&a -> v[i], &Idf.v[i], Tolerance)) return FALSE;
 191.478 -
 191.479 -       return TRUE;
 191.480 -
 191.481 +    return fabs(b - a) < (1.0 / 65535.0);
 191.482  }
 191.483  
 191.484 +
 191.485 +cmsBool CMSEXPORT _cmsMAT3isIdentity(const cmsMAT3* a)
 191.486 +{
 191.487 +    cmsMAT3 Identity;
 191.488 +    int i, j;
 191.489 +
 191.490 +    _cmsMAT3identity(&Identity);
 191.491 +
 191.492 +    for (i=0; i < 3; i++)
 191.493 +        for (j=0; j < 3; j++)
 191.494 +            if (!CloseEnough(a ->v[i].n[j], Identity.v[i].n[j])) return FALSE;
 191.495 +
 191.496 +    return TRUE;
 191.497 +}
 191.498 +
 191.499 +
 191.500  // Multiply two matrices
 191.501 -
 191.502 -
 191.503 -void MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b)
 191.504 +void CMSEXPORT _cmsMAT3per(cmsMAT3* r, const cmsMAT3* a, const cmsMAT3* b)
 191.505  {
 191.506  #define ROWCOL(i, j) \
 191.507      a->v[i].n[0]*b->v[0].n[j] + a->v[i].n[1]*b->v[1].n[j] + a->v[i].n[2]*b->v[2].n[j]
 191.508  
 191.509 -    VEC3init(&r-> v[0], ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2));
 191.510 -    VEC3init(&r-> v[1], ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2));
 191.511 -    VEC3init(&r-> v[2], ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2));
 191.512 +    _cmsVEC3init(&r-> v[0], ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2));
 191.513 +    _cmsVEC3init(&r-> v[1], ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2));
 191.514 +    _cmsVEC3init(&r-> v[2], ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2));
 191.515  
 191.516  #undef ROWCOL //(i, j)
 191.517  }
 191.518 @@ -496,350 +155,50 @@
 191.519  
 191.520  
 191.521  // Inverse of a matrix b = a^(-1)
 191.522 -// Gauss-Jordan elimination with partial pivoting
 191.523 +cmsBool  CMSEXPORT _cmsMAT3inverse(const cmsMAT3* a, cmsMAT3* b)
 191.524 +{
 191.525 +   cmsFloat64Number det, c0, c1, c2;
 191.526  
 191.527 -int MAT3inverse(LPMAT3 a, LPMAT3 b)
 191.528 -{
 191.529 -    register int  i, j, max;
 191.530 +   c0 =  a -> v[1].n[1]*a -> v[2].n[2] - a -> v[1].n[2]*a -> v[2].n[1];
 191.531 +   c1 = -a -> v[1].n[0]*a -> v[2].n[2] + a -> v[1].n[2]*a -> v[2].n[0];
 191.532 +   c2 =  a -> v[1].n[0]*a -> v[2].n[1] - a -> v[1].n[1]*a -> v[2].n[0];
 191.533  
 191.534 -    MAT3identity(b);
 191.535 +   det = a -> v[0].n[0]*c0 + a -> v[0].n[1]*c1 + a -> v[0].n[2]*c2;
 191.536  
 191.537 -    // Loop over cols of a from left to right, eliminating above and below diag
 191.538 -    for (j=0; j<3; j++) {   // Find largest pivot in column j among rows j..2
 191.539 +   if (fabs(det) < MATRIX_DET_TOLERANCE) return FALSE;  // singular matrix; can't invert
 191.540  
 191.541 -    max = j;                 // Row with largest pivot candidate
 191.542 -    for (i=j+1; i<3; i++)
 191.543 -        if (fabs(a -> v[i].n[j]) > fabs(a -> v[max].n[j]))
 191.544 -            max = i;
 191.545 +   b -> v[0].n[0] = c0/det;
 191.546 +   b -> v[0].n[1] = (a -> v[0].n[2]*a -> v[2].n[1] - a -> v[0].n[1]*a -> v[2].n[2])/det;
 191.547 +   b -> v[0].n[2] = (a -> v[0].n[1]*a -> v[1].n[2] - a -> v[0].n[2]*a -> v[1].n[1])/det;
 191.548 +   b -> v[1].n[0] = c1/det;
 191.549 +   b -> v[1].n[1] = (a -> v[0].n[0]*a -> v[2].n[2] - a -> v[0].n[2]*a -> v[2].n[0])/det;
 191.550 +   b -> v[1].n[2] = (a -> v[0].n[2]*a -> v[1].n[0] - a -> v[0].n[0]*a -> v[1].n[2])/det;
 191.551 +   b -> v[2].n[0] = c2/det;
 191.552 +   b -> v[2].n[1] = (a -> v[0].n[1]*a -> v[2].n[0] - a -> v[0].n[0]*a -> v[2].n[1])/det;
 191.553 +   b -> v[2].n[2] = (a -> v[0].n[0]*a -> v[1].n[1] - a -> v[0].n[1]*a -> v[1].n[0])/det;
 191.554  
 191.555 -    // Swap rows max and j in a and b to put pivot on diagonal
 191.556 -
 191.557 -    VEC3swap(&a -> v[max], &a -> v[j]);
 191.558 -    VEC3swap(&b -> v[max], &b -> v[j]);
 191.559 -
 191.560 -    // Scale row j to have a unit diagonal
 191.561 -
 191.562 -    if (a -> v[j].n[j]==0.)
 191.563 -        return -1;                 // singular matrix; can't invert
 191.564 -
 191.565 -    VEC3divK(&b-> v[j], &b -> v[j], a->v[j].n[j]);
 191.566 -    VEC3divK(&a-> v[j], &a -> v[j], a->v[j].n[j]);
 191.567 -
 191.568 -    // Eliminate off-diagonal elems in col j of a, doing identical ops to b
 191.569 -    for (i=0; i<3; i++)
 191.570 -
 191.571 -        if (i !=j) {
 191.572 -                  VEC3 temp;
 191.573 -
 191.574 -          VEC3perK(&temp, &b -> v[j], a -> v[i].n[j]);
 191.575 -          VEC3minus(&b -> v[i], &b -> v[i], &temp);
 191.576 -
 191.577 -          VEC3perK(&temp, &a -> v[j], a -> v[i].n[j]);
 191.578 -          VEC3minus(&a -> v[i], &a -> v[i], &temp);
 191.579 -    }
 191.580 -    }
 191.581 -
 191.582 -    return 1;
 191.583 +   return TRUE;
 191.584  }
 191.585  
 191.586  
 191.587  // Solve a system in the form Ax = b
 191.588 +cmsBool  CMSEXPORT _cmsMAT3solve(cmsVEC3* x, cmsMAT3* a, cmsVEC3* b)
 191.589 +{
 191.590 +    cmsMAT3 m, a_1;
 191.591  
 191.592 -LCMSBOOL MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b)
 191.593 -{
 191.594 -    MAT3 m, a_1;
 191.595 +    memmove(&m, a, sizeof(cmsMAT3));
 191.596  
 191.597 -    CopyMemory(&m, a, sizeof(MAT3));
 191.598 +    if (!_cmsMAT3inverse(&m, &a_1)) return FALSE;  // Singular matrix
 191.599  
 191.600 -    if (!MAT3inverse(&m, &a_1)) return FALSE;  // Singular matrix
 191.601 -
 191.602 -    MAT3eval(x, &a_1, b);
 191.603 +    _cmsMAT3eval(x, &a_1, b);
 191.604      return TRUE;
 191.605  }
 191.606  
 191.607 -
 191.608 -// The determinant
 191.609 -
 191.610 -double MAT3det(LPMAT3 m)
 191.611 -{
 191.612 -
 191.613 -    double a1 = m ->v[VX].n[VX];
 191.614 -    double a2 = m ->v[VX].n[VY];
 191.615 -    double a3 = m ->v[VX].n[VZ];
 191.616 -    double b1 = m ->v[VY].n[VX];
 191.617 -    double b2 = m ->v[VY].n[VY];
 191.618 -    double b3 = m ->v[VY].n[VZ];
 191.619 -    double c1 = m ->v[VZ].n[VX];
 191.620 -    double c2 = m ->v[VZ].n[VY];
 191.621 -    double c3 = m ->v[VZ].n[VZ];
 191.622 -
 191.623 -
 191.624 -    return a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 - a3*b1*c2 - a3*b2*c1;
 191.625 -}
 191.626 -
 191.627 -
 191.628 -// linear transform
 191.629 -
 191.630 -
 191.631 -void MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v)
 191.632 +// Evaluate a vector across a matrix
 191.633 +void CMSEXPORT _cmsMAT3eval(cmsVEC3* r, const cmsMAT3* a, const cmsVEC3* v)
 191.634  {
 191.635      r->n[VX] = a->v[0].n[VX]*v->n[VX] + a->v[0].n[VY]*v->n[VY] + a->v[0].n[VZ]*v->n[VZ];
 191.636      r->n[VY] = a->v[1].n[VX]*v->n[VX] + a->v[1].n[VY]*v->n[VY] + a->v[1].n[VZ]*v->n[VZ];
 191.637      r->n[VZ] = a->v[2].n[VX]*v->n[VX] + a->v[2].n[VY]*v->n[VY] + a->v[2].n[VZ]*v->n[VZ];
 191.638  }
 191.639  
 191.640 -
 191.641 -// Ok, this is another bottleneck of performance.
 191.642 -
 191.643 -
 191.644 -#ifdef USE_ASSEMBLER
 191.645 -
 191.646 -// ecx:ebx is result in 64 bits format
 191.647 -// edi points to matrix, esi points to input vector
 191.648 -// since only 3 accesses are in output, this is a stack variable
 191.649 -
 191.650 -
 191.651 -void MAT3evalW(LPWVEC3 r_, LPWMAT3 a_, LPWVEC3 v_)
 191.652 -{
 191.653 -
 191.654 -       ASM {
 191.655 -
 191.656 -
 191.657 -       mov    esi, dword ptr ss:v_
 191.658 -       mov    edi, dword ptr ss:a_
 191.659 -
 191.660 -   //     r->n[VX] = FixedMul(a->v[0].n[0], v->n[0]) +
 191.661 -
 191.662 -       mov       eax,dword ptr [esi]
 191.663 -       mov       edx,dword ptr [edi]
 191.664 -       imul      edx
 191.665 -       mov       ecx, eax
 191.666 -       mov       ebx, edx
 191.667 -
 191.668 -   //          FixedMul(a->v[0].n[1], v->n[1]) +
 191.669 -
 191.670 -       mov       eax,dword ptr [esi+4]
 191.671 -       mov       edx,dword ptr [edi+4]
 191.672 -       imul      edx
 191.673 -       add       ecx, eax
 191.674 -       adc       ebx, edx
 191.675 -
 191.676 -   //         FixedMul(a->v[0].n[2], v->n[2]);
 191.677 -
 191.678 -       mov       eax,dword ptr [esi+8]
 191.679 -       mov       edx,dword ptr [edi+8]
 191.680 -       imul      edx
 191.681 -       add       ecx, eax
 191.682 -       adc       ebx, edx
 191.683 -
 191.684 -   //  Back to Fixed 15.16
 191.685 -
 191.686 -       add       ecx, 0x8000
 191.687 -       adc       ebx, 0
 191.688 -       shrd      ecx, ebx, 16
 191.689 -
 191.690 -       push      edi
 191.691 -       mov       edi, dword ptr ss:r_
 191.692 -       mov       dword ptr [edi], ecx      //  r -> n[VX]
 191.693 -       pop       edi
 191.694 -
 191.695 -
 191.696 -
 191.697 -   //   2nd row ***************************
 191.698 -
 191.699 -   //        FixedMul(a->v[1].n[0], v->n[0])
 191.700 -
 191.701 -       mov       eax,dword ptr [esi]
 191.702 -       mov       edx,dword ptr [edi+12]
 191.703 -       imul      edx
 191.704 -       mov       ecx, eax
 191.705 -       mov       ebx, edx
 191.706 -
 191.707 -   //         FixedMul(a->v[1].n[1], v->n[1]) +
 191.708 -
 191.709 -       mov       eax,dword ptr [esi+4]
 191.710 -       mov       edx,dword ptr [edi+16]
 191.711 -       imul      edx
 191.712 -       add       ecx, eax
 191.713 -       adc       ebx, edx
 191.714 -
 191.715 -       //     FixedMul(a->v[1].n[2], v->n[2]);
 191.716 -
 191.717 -       mov       eax,dword ptr [esi+8]
 191.718 -       mov       edx,dword ptr [edi+20]
 191.719 -       imul      edx
 191.720 -       add       ecx, eax
 191.721 -       adc       ebx, edx
 191.722 -
 191.723 -       add       ecx, 0x8000
 191.724 -       adc       ebx, 0
 191.725 -       shrd      ecx, ebx, 16
 191.726 -
 191.727 -       push      edi
 191.728 -       mov       edi, dword ptr ss:r_
 191.729 -       mov       dword ptr [edi+4], ecx      // r -> n[VY]
 191.730 -       pop       edi
 191.731 -
 191.732 -//     3d row **************************
 191.733 -
 191.734 -   //       r->n[VZ] = FixedMul(a->v[2].n[0], v->n[0]) +
 191.735 -
 191.736 -       mov       eax,dword ptr [esi]
 191.737 -       mov       edx,dword ptr [edi+24]
 191.738 -       imul      edx
 191.739 -       mov       ecx, eax
 191.740 -       mov       ebx, edx
 191.741 -
 191.742 -   //    FixedMul(a->v[2].n[1], v->n[1]) +
 191.743 -
 191.744 -       mov       eax,dword ptr [esi+4]
 191.745 -       mov       edx,dword ptr [edi+28]
 191.746 -       imul      edx
 191.747 -       add       ecx, eax
 191.748 -       adc       ebx, edx
 191.749 -
 191.750 -   //   FixedMul(a->v[2].n[2], v->n[2]);
 191.751 -
 191.752 -       mov       eax,dword ptr [esi+8]
 191.753 -       mov       edx,dword ptr [edi+32]
 191.754 -       imul      edx
 191.755 -       add       ecx, eax
 191.756 -       adc       ebx, edx
 191.757 -
 191.758 -       add       ecx, 0x8000
 191.759 -       adc       ebx, 0
 191.760 -       shrd      ecx, ebx, 16
 191.761 -
 191.762 -       mov       edi, dword ptr ss:r_
 191.763 -       mov       dword ptr [edi+8], ecx      // r -> n[VZ]
 191.764 -       }
 191.765 -}
 191.766 -
 191.767 -
 191.768 -#else
 191.769 -
 191.770 -
 191.771 -#ifdef USE_FLOAT
 191.772 -
 191.773 -void MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v)
 191.774 -{
 191.775 -    r->n[VX] = DOUBLE_TO_FIXED(
 191.776 -                 FIXED_TO_DOUBLE(a->v[0].n[0]) * FIXED_TO_DOUBLE(v->n[0]) +
 191.777 -                 FIXED_TO_DOUBLE(a->v[0].n[1]) * FIXED_TO_DOUBLE(v->n[1]) +
 191.778 -                 FIXED_TO_DOUBLE(a->v[0].n[2]) * FIXED_TO_DOUBLE(v->n[2])
 191.779 -                );
 191.780 -
 191.781 -    r->n[VY] = DOUBLE_TO_FIXED(
 191.782 -                 FIXED_TO_DOUBLE(a->v[1].n[0]) * FIXED_TO_DOUBLE(v->n[0]) +
 191.783 -                 FIXED_TO_DOUBLE(a->v[1].n[1]) * FIXED_TO_DOUBLE(v->n[1]) +
 191.784 -                 FIXED_TO_DOUBLE(a->v[1].n[2]) * FIXED_TO_DOUBLE(v->n[2])
 191.785 -               );
 191.786 -
 191.787 -    r->n[VZ] = DOUBLE_TO_FIXED(
 191.788 -                FIXED_TO_DOUBLE(a->v[2].n[0]) * FIXED_TO_DOUBLE(v->n[0]) +
 191.789 -                FIXED_TO_DOUBLE(a->v[2].n[1]) * FIXED_TO_DOUBLE(v->n[1]) +
 191.790 -                FIXED_TO_DOUBLE(a->v[2].n[2]) * FIXED_TO_DOUBLE(v->n[2])
 191.791 -               );
 191.792 -}
 191.793 -
 191.794 -
 191.795 -#else
 191.796 -
 191.797 -void MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v)
 191.798 -{
 191.799 -
 191.800 -#ifdef USE_INT64
 191.801 -
 191.802 -    LCMSULONGLONG l1 = (LCMSULONGLONG) (LCMSSLONGLONG) a->v[0].n[0] *
 191.803 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[0] +
 191.804 -                       (LCMSULONGLONG) (LCMSSLONGLONG) a->v[0].n[1] *
 191.805 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[1] +
 191.806 -                       (LCMSULONGLONG) (LCMSSLONGLONG) a->v[0].n[2] *
 191.807 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[2] + (LCMSULONGLONG) 0x8000;
 191.808 -
 191.809 -    LCMSULONGLONG l2 = (LCMSULONGLONG) (LCMSSLONGLONG) a->v[1].n[0] *
 191.810 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[0] +
 191.811 -                       (LCMSULONGLONG) (LCMSSLONGLONG) a->v[1].n[1] *
 191.812 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[1] +
 191.813 -                       (LCMSULONGLONG) (LCMSSLONGLONG) a->v[1].n[2] *
 191.814 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[2] + (LCMSULONGLONG) 0x8000;
 191.815 -
 191.816 -    LCMSULONGLONG l3 = (LCMSULONGLONG) (LCMSSLONGLONG) a->v[2].n[0] *
 191.817 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[0] +
 191.818 -                       (LCMSULONGLONG) (LCMSSLONGLONG) a->v[2].n[1] *
 191.819 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[1] +
 191.820 -                       (LCMSULONGLONG) (LCMSSLONGLONG) a->v[2].n[2] *
 191.821 -                       (LCMSULONGLONG) (LCMSSLONGLONG) v->n[2] + (LCMSULONGLONG) 0x8000;
 191.822 -    l1 >>= 16;
 191.823 -    l2 >>= 16;
 191.824 -    l3 >>= 16;
 191.825 -
 191.826 -    r->n[VX] = (Fixed32) l1;
 191.827 -    r->n[VY] = (Fixed32) l2;
 191.828 -    r->n[VZ] = (Fixed32) l3;
 191.829 -
 191.830 -#else
 191.831 -
 191.832 -    // FIXME: Rounding should be done at very last stage. There is 1-Contone rounding error!
 191.833 -
 191.834 -    r->n[VX] = FixedMul(a->v[0].n[0], v->n[0]) +
 191.835 -               FixedMul(a->v[0].n[1], v->n[1]) +
 191.836 -               FixedMul(a->v[0].n[2], v->n[2]);
 191.837 -
 191.838 -    r->n[VY] = FixedMul(a->v[1].n[0], v->n[0]) +
 191.839 -               FixedMul(a->v[1].n[1], v->n[1]) +
 191.840 -               FixedMul(a->v[1].n[2], v->n[2]);
 191.841 -
 191.842 -    r->n[VZ] = FixedMul(a->v[2].n[0], v->n[0]) +
 191.843 -               FixedMul(a->v[2].n[1], v->n[1]) +
 191.844 -               FixedMul(a->v[2].n[2], v->n[2]);
 191.845 -#endif
 191.846 -}
 191.847 -
 191.848 -#endif
 191.849 -#endif
 191.850 -
 191.851 -
 191.852 -void MAT3perK(LPMAT3 r, LPMAT3 v, double d)
 191.853 -{
 191.854 -       VEC3perK(&r -> v[0], &v -> v[0], d);
 191.855 -       VEC3perK(&r -> v[1], &v -> v[1], d);
 191.856 -       VEC3perK(&r -> v[2], &v -> v[2], d);
 191.857 -}
 191.858 -
 191.859 -
 191.860 -void MAT3toFix(LPWMAT3 r, LPMAT3 v)
 191.861 -{
 191.862 -       VEC3toFix(&r -> v[0], &v -> v[0]);
 191.863 -       VEC3toFix(&r -> v[1], &v -> v[1]);
 191.864 -       VEC3toFix(&r -> v[2], &v -> v[2]);
 191.865 -}
 191.866 -
 191.867 -void MAT3fromFix(LPMAT3 r, LPWMAT3 v)
 191.868 -{
 191.869 -       VEC3fromFix(&r -> v[0], &v -> v[0]);
 191.870 -       VEC3fromFix(&r -> v[1], &v -> v[1]);
 191.871 -       VEC3fromFix(&r -> v[2], &v -> v[2]);
 191.872 -}
 191.873 -
 191.874 -
 191.875 -
 191.876 -// Scale v by d and store it in r giving INTEGER
 191.877 -
 191.878 -void VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d)
 191.879 -{
 191.880 -        r -> n[VX] = (int) floor(v -> n[VX] * d + .5);
 191.881 -        r -> n[VY] = (int) floor(v -> n[VY] * d + .5);
 191.882 -        r -> n[VZ] = (int) floor(v -> n[VZ] * d + .5);
 191.883 -}
 191.884 -
 191.885 -void MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d)
 191.886 -{
 191.887 -       VEC3scaleAndCut(&r -> v[0], &v -> v[0], d);
 191.888 -       VEC3scaleAndCut(&r -> v[1], &v -> v[1], d);
 191.889 -       VEC3scaleAndCut(&r -> v[2], &v -> v[2], d);
 191.890 -}
 191.891 -
 191.892 -
 191.893 -
 191.894 -
   192.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c	Thu Sep 23 17:33:40 2010 -0700
   192.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsnamed.c	Fri Sep 24 16:41:32 2010 -0700
   192.3 @@ -27,9 +27,10 @@
   192.4  // However, the following notice accompanied the original version of this
   192.5  // file:
   192.6  //
   192.7 +//---------------------------------------------------------------------------------
   192.8  //
   192.9 -//  Little cms
  192.10 -//  Copyright (C) 1998-2007 Marti Maria
  192.11 +//  Little Color Management System
  192.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  192.13  //
  192.14  // Permission is hereby granted, free of charge, to any person obtaining
  192.15  // a copy of this software and associated documentation files (the "Software"),
  192.16 @@ -48,153 +49,725 @@
  192.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  192.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  192.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  192.20 +//
  192.21 +//---------------------------------------------------------------------------------
  192.22 +//
  192.23  
  192.24 +#include "lcms2_internal.h"
  192.25  
  192.26 -// Named color support
  192.27 +// Multilocalized unicode objects. That is an attempt to encapsulate i18n.
  192.28  
  192.29 -#include "lcms.h"
  192.30  
  192.31 +// Allocates an empty multi localizad unicode object
  192.32 +cmsMLU* CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems)
  192.33 +{
  192.34 +    cmsMLU* mlu;
  192.35  
  192.36 +    // nItems should be positive if given
  192.37 +    if (nItems <= 0) nItems = 2;
  192.38  
  192.39 +    // Create the container
  192.40 +    mlu = (cmsMLU*) _cmsMallocZero(ContextID, sizeof(cmsMLU));
  192.41 +    if (mlu == NULL) return NULL;
  192.42 +
  192.43 +    mlu ->ContextID = ContextID;
  192.44 +
  192.45 +    // Create entry array
  192.46 +    mlu ->Entries = (_cmsMLUentry*) _cmsCalloc(ContextID, nItems, sizeof(_cmsMLUentry));
  192.47 +    if (mlu ->Entries == NULL) {
  192.48 +        _cmsFree(ContextID, mlu);
  192.49 +        return NULL;
  192.50 +    }
  192.51 +
  192.52 +    // Ok, keep indexes up to date
  192.53 +    mlu ->AllocatedEntries    = nItems;
  192.54 +    mlu ->UsedEntries         = 0;
  192.55 +
  192.56 +    return mlu;
  192.57 +}
  192.58 +
  192.59 +
  192.60 +// Grows a mempool table for a MLU. Each time this function is called, mempool size is multiplied times two.
  192.61  static
  192.62 -LPcmsNAMEDCOLORLIST GrowNamedColorList(LPcmsNAMEDCOLORLIST v, int ByElements)
  192.63 +cmsBool GrowMLUpool(cmsMLU* mlu)
  192.64  {
  192.65 -    if (ByElements > v ->Allocated) {
  192.66 +    cmsUInt32Number size;
  192.67 +    void *NewPtr;
  192.68  
  192.69 -        LPcmsNAMEDCOLORLIST TheNewList;
  192.70 -        int NewElements;
  192.71 -        size_t size;
  192.72 +    // Sanity check
  192.73 +    if (mlu == NULL) return FALSE;
  192.74  
  192.75 -        if (v ->Allocated == 0)
  192.76 -            NewElements = 64;   // Initial guess
  192.77 -        else
  192.78 -            NewElements = v ->Allocated;
  192.79 +    if (mlu ->PoolSize == 0)
  192.80 +        size = 256;
  192.81 +    else
  192.82 +        size = mlu ->PoolSize * 2;
  192.83  
  192.84 -        while (ByElements > NewElements)
  192.85 -                NewElements *= 2;
  192.86 +    // Check for overflow
  192.87 +    if (size < mlu ->PoolSize) return FALSE;
  192.88  
  192.89 -        size = sizeof(cmsNAMEDCOLORLIST) + (sizeof(cmsNAMEDCOLOR) * NewElements);
  192.90 -        TheNewList = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
  192.91 +    // Reallocate the pool
  192.92 +    NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size);
  192.93 +    if (NewPtr == NULL) return FALSE;
  192.94  
  192.95  
  192.96 -        if (TheNewList == NULL) {
  192.97 -            cmsSignalError(LCMS_ERRC_ABORTED, "Out of memory reallocating named color list");
  192.98 -            return NULL;
  192.99 -        }
 192.100 -        else {
 192.101 -              ZeroMemory(TheNewList, size);
 192.102 -              CopyMemory(TheNewList, v, sizeof(cmsNAMEDCOLORLIST) + (v ->nColors - 1) * sizeof(cmsNAMEDCOLOR));
 192.103 -              TheNewList -> Allocated = NewElements;
 192.104 +    mlu ->MemPool  = NewPtr;
 192.105 +    mlu ->PoolSize = size;
 192.106  
 192.107 -              _cmsFree(v);
 192.108 -              return TheNewList;
 192.109 +    return TRUE;
 192.110 +}
 192.111 +
 192.112 +
 192.113 +// Grows a ntry table for a MLU. Each time this function is called, table size is multiplied times two.
 192.114 +static
 192.115 +cmsBool GrowMLUtable(cmsMLU* mlu)
 192.116 +{
 192.117 +    int AllocatedEntries;
 192.118 +    _cmsMLUentry *NewPtr;
 192.119 +
 192.120 +    // Sanity check
 192.121 +    if (mlu == NULL) return FALSE;
 192.122 +
 192.123 +    AllocatedEntries = mlu ->AllocatedEntries * 2;
 192.124 +
 192.125 +    // Check for overflow
 192.126 +    if (AllocatedEntries < mlu ->AllocatedEntries) return FALSE;
 192.127 +
 192.128 +    // Reallocate the memory
 192.129 +    NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedEntries*sizeof(_cmsMLUentry));
 192.130 +    if (NewPtr == NULL) return FALSE;
 192.131 +
 192.132 +    mlu ->Entries          = NewPtr;
 192.133 +    mlu ->AllocatedEntries = AllocatedEntries;
 192.134 +
 192.135 +    return TRUE;
 192.136 +}
 192.137 +
 192.138 +
 192.139 +// Search for a specific entry in the structure. Language and Country are used.
 192.140 +static
 192.141 +int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
 192.142 +{
 192.143 +    int i;
 192.144 +
 192.145 +    // Sanity check
 192.146 +    if (mlu == NULL) return -1;
 192.147 +
 192.148 +    // Iterate whole table
 192.149 +    for (i=0; i < mlu ->UsedEntries; i++) {
 192.150 +
 192.151 +        if (mlu ->Entries[i].Country  == CountryCode &&
 192.152 +            mlu ->Entries[i].Language == LanguageCode) return i;
 192.153 +    }
 192.154 +
 192.155 +    // Not found
 192.156 +    return -1;
 192.157 +}
 192.158 +
 192.159 +// Add a block of characters to the intended MLU. Language and country are specified.
 192.160 +// Only one entry for Language/country pair is allowed.
 192.161 +static
 192.162 +cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
 192.163 +                     cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
 192.164 +{
 192.165 +    cmsUInt32Number Offset;
 192.166 +    cmsUInt8Number* Ptr;
 192.167 +
 192.168 +    // Sanity check
 192.169 +    if (mlu == NULL) return FALSE;
 192.170 +
 192.171 +    // Is there any room available?
 192.172 +    if (mlu ->UsedEntries >= mlu ->AllocatedEntries) {
 192.173 +        if (!GrowMLUtable(mlu)) return FALSE;
 192.174 +    }
 192.175 +
 192.176 +    // Only one ASCII string
 192.177 +    if (SearchMLUEntry(mlu, LanguageCode, CountryCode) >= 0) return FALSE;  // Only one  is allowed!
 192.178 +
 192.179 +    // Check for size
 192.180 +    while ((mlu ->PoolSize - mlu ->PoolUsed) < size) {
 192.181 +
 192.182 +            if (!GrowMLUpool(mlu)) return FALSE;
 192.183 +    }
 192.184 +
 192.185 +    Offset = mlu ->PoolUsed;
 192.186 +
 192.187 +    Ptr = (cmsUInt8Number*) mlu ->MemPool;
 192.188 +    if (Ptr == NULL) return FALSE;
 192.189 +
 192.190 +    // Set the entry
 192.191 +    memmove(Ptr + Offset, Block, size);
 192.192 +    mlu ->PoolUsed += size;
 192.193 +
 192.194 +    mlu ->Entries[mlu ->UsedEntries].StrW     = Offset;
 192.195 +    mlu ->Entries[mlu ->UsedEntries].Len      = size;
 192.196 +    mlu ->Entries[mlu ->UsedEntries].Country  = CountryCode;
 192.197 +    mlu ->Entries[mlu ->UsedEntries].Language = LanguageCode;
 192.198 +    mlu ->UsedEntries++;
 192.199 +
 192.200 +    return TRUE;
 192.201 +}
 192.202 +
 192.203 +
 192.204 +// Add an ASCII entry.
 192.205 +cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString)
 192.206 +{
 192.207 +    cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString)+1;
 192.208 +    wchar_t* WStr;
 192.209 +    cmsBool  rc;
 192.210 +    cmsUInt16Number Lang  = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
 192.211 +    cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
 192.212 +
 192.213 +    if (mlu == NULL) return FALSE;
 192.214 +
 192.215 +    WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, len,  sizeof(wchar_t));
 192.216 +    if (WStr == NULL) return FALSE;
 192.217 +
 192.218 +    for (i=0; i < len; i++)
 192.219 +        WStr[i] = (wchar_t) ASCIIString[i];
 192.220 +
 192.221 +    rc = AddMLUBlock(mlu, len  * sizeof(wchar_t), WStr, Lang, Cntry);
 192.222 +
 192.223 +    _cmsFree(mlu ->ContextID, WStr);
 192.224 +    return rc;
 192.225 +
 192.226 +}
 192.227 +
 192.228 +// We don't need any wcs support library
 192.229 +static
 192.230 +cmsUInt32Number mywcslen(const wchar_t *s)
 192.231 +{
 192.232 +    const wchar_t *p;
 192.233 +
 192.234 +    p = s;
 192.235 +    while (*p)
 192.236 +        p++;
 192.237 +
 192.238 +    return (cmsUInt32Number)(p - s);
 192.239 +}
 192.240 +
 192.241 +
 192.242 +// Add a wide entry
 192.243 +cmsBool  CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char Country[3], const wchar_t* WideString)
 192.244 +{
 192.245 +    cmsUInt16Number Lang  = _cmsAdjustEndianess16(*(cmsUInt16Number*) Language);
 192.246 +    cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) Country);
 192.247 +    cmsUInt32Number len;
 192.248 +
 192.249 +    if (mlu == NULL) return FALSE;
 192.250 +    if (WideString == NULL) return FALSE;
 192.251 +
 192.252 +    len = (cmsUInt32Number) (mywcslen(WideString) + 1) * sizeof(wchar_t);
 192.253 +    return AddMLUBlock(mlu, len, WideString, Lang, Cntry);
 192.254 +}
 192.255 +
 192.256 +// Duplicating a MLU is as easy as copying all members
 192.257 +cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu)
 192.258 +{
 192.259 +    cmsMLU* NewMlu = NULL;
 192.260 +
 192.261 +    // Duplicating a NULL obtains a NULL
 192.262 +    if (mlu == NULL) return NULL;
 192.263 +
 192.264 +    NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries);
 192.265 +    if (NewMlu == NULL) return NULL;
 192.266 +
 192.267 +    // Should never happen
 192.268 +    if (NewMlu ->AllocatedEntries < mlu ->UsedEntries)
 192.269 +        goto Error;
 192.270 +
 192.271 +    // Sanitize...
 192.272 +    if (NewMlu ->Entries == NULL || mlu ->Entries == NULL)  goto Error;
 192.273 +
 192.274 +    memmove(NewMlu ->Entries, mlu ->Entries, mlu ->UsedEntries * sizeof(_cmsMLUentry));
 192.275 +    NewMlu ->UsedEntries = mlu ->UsedEntries;
 192.276 +
 192.277 +    // The MLU may be empty
 192.278 +    if (mlu ->PoolUsed == 0) {
 192.279 +        NewMlu ->MemPool = NULL;
 192.280 +    }
 192.281 +    else {
 192.282 +        // It is not empty
 192.283 +        NewMlu ->MemPool = _cmsMalloc(mlu ->ContextID, mlu ->PoolUsed);
 192.284 +        if (NewMlu ->MemPool == NULL) goto Error;
 192.285 +    }
 192.286 +
 192.287 +    NewMlu ->PoolSize = mlu ->PoolUsed;
 192.288 +
 192.289 +    if (NewMlu ->MemPool == NULL || mlu ->MemPool == NULL) goto Error;
 192.290 +
 192.291 +    memmove(NewMlu ->MemPool, mlu->MemPool, mlu ->PoolUsed);
 192.292 +    NewMlu ->PoolUsed = mlu ->PoolUsed;
 192.293 +
 192.294 +    return NewMlu;
 192.295 +
 192.296 +Error:
 192.297 +
 192.298 +    if (NewMlu != NULL) cmsMLUfree(NewMlu);
 192.299 +    return NULL;
 192.300 +}
 192.301 +
 192.302 +// Free any used memory
 192.303 +void CMSEXPORT cmsMLUfree(cmsMLU* mlu)
 192.304 +{
 192.305 +    if (mlu) {
 192.306 +
 192.307 +        if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries);
 192.308 +        if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool);
 192.309 +
 192.310 +        _cmsFree(mlu ->ContextID, mlu);
 192.311 +    }
 192.312 +}
 192.313 +
 192.314 +
 192.315 +// The algorithm first searches for an exact match of country and language, if not found it uses
 192.316 +// the Language. If none is found, first entry is used instead.
 192.317 +static
 192.318 +const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
 192.319 +                              cmsUInt32Number *len,
 192.320 +                              cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode,
 192.321 +                              cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
 192.322 +{
 192.323 +    int i;
 192.324 +    int Best = -1;
 192.325 +    _cmsMLUentry* v;
 192.326 +
 192.327 +    if (mlu == NULL) return NULL;
 192.328 +
 192.329 +    if (mlu -> AllocatedEntries <= 0) return NULL;
 192.330 +
 192.331 +    for (i=0; i < mlu ->UsedEntries; i++) {
 192.332 +
 192.333 +        v = mlu ->Entries + i;
 192.334 +
 192.335 +        if (v -> Language == LanguageCode) {
 192.336 +
 192.337 +            if (Best == -1) Best = i;
 192.338 +
 192.339 +            if (v -> Country == CountryCode) {
 192.340 +
 192.341 +                if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
 192.342 +                if (UsedCountryCode  != NULL) *UsedCountryCode = v ->Country;
 192.343 +
 192.344 +                if (len != NULL) *len = v ->Len;
 192.345 +
 192.346 +                return (wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v -> StrW);        // Found exact match
 192.347 +            }
 192.348          }
 192.349      }
 192.350  
 192.351 +    // No string found. Return First one
 192.352 +    if (Best == -1)
 192.353 +        Best = 0;
 192.354 +
 192.355 +    v = mlu ->Entries + Best;
 192.356 +
 192.357 +    if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
 192.358 +    if (UsedCountryCode  != NULL) *UsedCountryCode = v ->Country;
 192.359 +
 192.360 +    if (len != NULL) *len   = v ->Len;
 192.361 +
 192.362 +    return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
 192.363 +}
 192.364 +
 192.365 +
 192.366 +// Obtain an ASCII representation of the wide string. Setting buffer to NULL returns the len
 192.367 +cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
 192.368 +                                         const char LanguageCode[3], const char CountryCode[3],
 192.369 +                                         char* Buffer, cmsUInt32Number BufferSize)
 192.370 +{
 192.371 +    const wchar_t *Wide;
 192.372 +    cmsUInt32Number  StrLen = 0;
 192.373 +    cmsUInt32Number ASCIIlen, i;
 192.374 +
 192.375 +    cmsUInt16Number Lang  = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
 192.376 +    cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
 192.377 +
 192.378 +    // Sanitize
 192.379 +    if (mlu == NULL) return 0;
 192.380 +
 192.381 +    // Get WideChar
 192.382 +    Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
 192.383 +    if (Wide == NULL) return 0;
 192.384 +
 192.385 +    ASCIIlen = StrLen / sizeof(wchar_t);
 192.386 +
 192.387 +    // Maybe we want only to know the len?
 192.388 +    if (Buffer == NULL) return ASCIIlen + 1; // Note the zero at the end
 192.389 +
 192.390 +    // No buffer size means no data
 192.391 +    if (BufferSize <= 0) return 0;
 192.392 +
 192.393 +    // Some clipping may be required
 192.394 +    if (BufferSize < ASCIIlen + 1)
 192.395 +        ASCIIlen = BufferSize - 1;
 192.396 +
 192.397 +    // Precess each character
 192.398 +    for (i=0; i < ASCIIlen; i++) {
 192.399 +
 192.400 +        if (Wide[i] == 0)
 192.401 +            Buffer[i] = 0;
 192.402 +        else
 192.403 +            Buffer[i] = (char) Wide[i];
 192.404 +    }
 192.405 +
 192.406 +    // We put a termination "\0"
 192.407 +    Buffer[ASCIIlen] = 0;
 192.408 +    return ASCIIlen + 1;
 192.409 +}
 192.410 +
 192.411 +// Obtain a wide representation of the MLU, on depending on current locale settings
 192.412 +cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
 192.413 +                                        const char LanguageCode[3], const char CountryCode[3],
 192.414 +                                        wchar_t* Buffer, cmsUInt32Number BufferSize)
 192.415 +{
 192.416 +    const wchar_t *Wide;
 192.417 +    cmsUInt32Number  StrLen = 0;
 192.418 +
 192.419 +    cmsUInt16Number Lang  = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
 192.420 +    cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
 192.421 +
 192.422 +    // Sanitize
 192.423 +    if (mlu == NULL) return 0;
 192.424 +
 192.425 +    Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
 192.426 +    if (Wide == NULL) return 0;
 192.427 +
 192.428 +    // Maybe we want only to know the len?
 192.429 +    if (Buffer == NULL) return StrLen + sizeof(wchar_t);
 192.430 +
 192.431 +  // No buffer size means no data
 192.432 +    if (BufferSize <= 0) return 0;
 192.433 +
 192.434 +    // Some clipping may be required
 192.435 +    if (BufferSize < StrLen + sizeof(wchar_t))
 192.436 +        StrLen = BufferSize - + sizeof(wchar_t);
 192.437 +
 192.438 +    memmove(Buffer, Wide, StrLen);
 192.439 +    Buffer[StrLen / sizeof(wchar_t)] = 0;
 192.440 +
 192.441 +    return StrLen + sizeof(wchar_t);
 192.442 +}
 192.443 +
 192.444 +
 192.445 +// Get also the language and country
 192.446 +CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
 192.447 +                                              const char LanguageCode[3], const char CountryCode[3],
 192.448 +                                              char ObtainedLanguage[3], char ObtainedCountry[3])
 192.449 +{
 192.450 +    const wchar_t *Wide;
 192.451 +
 192.452 +    cmsUInt16Number Lang  = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
 192.453 +    cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
 192.454 +    cmsUInt16Number ObtLang, ObtCode;
 192.455 +
 192.456 +    // Sanitize
 192.457 +    if (mlu == NULL) return FALSE;
 192.458 +
 192.459 +    Wide = _cmsMLUgetWide(mlu, NULL, Lang, Cntry, &ObtLang, &ObtCode);
 192.460 +    if (Wide == NULL) return FALSE;
 192.461 +
 192.462 +    // Get used language and code
 192.463 +    *(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang);
 192.464 +    *(cmsUInt16Number *)ObtainedCountry  = _cmsAdjustEndianess16(ObtCode);
 192.465 +
 192.466 +    ObtainedLanguage[2] = ObtainedCountry[2] = 0;
 192.467 +    return TRUE;
 192.468 +}
 192.469 +
 192.470 +
 192.471 +// Named color lists --------------------------------------------------------------------------------------------
 192.472 +
 192.473 +// Grow the list to keep at least NumElements
 192.474 +static
 192.475 +cmsBool  GrowNamedColorList(cmsNAMEDCOLORLIST* v)
 192.476 +{
 192.477 +    cmsUInt32Number size;
 192.478 +    _cmsNAMEDCOLOR * NewPtr;
 192.479 +
 192.480 +    if (v == NULL) return FALSE;
 192.481 +
 192.482 +    if (v ->Allocated == 0)
 192.483 +        size = 64;   // Initial guess
 192.484 +    else
 192.485 +        size = v ->Allocated * 2;
 192.486 +
 192.487 +    NewPtr = (_cmsNAMEDCOLOR*) _cmsRealloc(v ->ContextID, v ->List, size * sizeof(_cmsNAMEDCOLOR));
 192.488 +    if (NewPtr == NULL)
 192.489 +        return FALSE;
 192.490 +
 192.491 +    v ->List      = NewPtr;
 192.492 +    v ->Allocated = size;
 192.493 +    return TRUE;
 192.494 +}
 192.495 +
 192.496 +// Allocate a list for n elements
 192.497 +cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID, cmsUInt32Number n, cmsUInt32Number ColorantCount, const char* Prefix, const char* Suffix)
 192.498 +{
 192.499 +    cmsNAMEDCOLORLIST* v = (cmsNAMEDCOLORLIST*) _cmsMallocZero(ContextID, sizeof(cmsNAMEDCOLORLIST));
 192.500 +
 192.501 +    if (v == NULL) return NULL;
 192.502 +
 192.503 +    v ->List      = NULL;
 192.504 +    v ->nColors   = 0;
 192.505 +    v ->ContextID  = ContextID;
 192.506 +
 192.507 +    while (v -> Allocated < n)
 192.508 +        GrowNamedColorList(v);
 192.509 +
 192.510 +    strncpy(v ->Prefix, Prefix, sizeof(v ->Prefix));
 192.511 +    strncpy(v ->Suffix, Suffix, sizeof(v ->Suffix));
 192.512 +    v -> ColorantCount = ColorantCount;
 192.513 +
 192.514      return v;
 192.515  }
 192.516  
 192.517 +// Free a list
 192.518 +void CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v)
 192.519 +{
 192.520 +    if (v ->List) _cmsFree(v ->ContextID, v ->List);
 192.521 +    if (v) _cmsFree(v ->ContextID, v);
 192.522 +}
 192.523  
 192.524 -LPcmsNAMEDCOLORLIST cmsAllocNamedColorList(int n)
 192.525 +cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v)
 192.526  {
 192.527 -    size_t size = sizeof(cmsNAMEDCOLORLIST) + (n - 1) * sizeof(cmsNAMEDCOLOR);
 192.528 +    cmsNAMEDCOLORLIST* NewNC;
 192.529  
 192.530 -    LPcmsNAMEDCOLORLIST v = (LPcmsNAMEDCOLORLIST) _cmsMalloc(size);
 192.531 +    if (v == NULL) return NULL;
 192.532  
 192.533 +    NewNC= cmsAllocNamedColorList(v ->ContextID, v -> nColors, v ->ColorantCount, v ->Prefix, v ->Suffix);
 192.534 +    if (NewNC == NULL) return NULL;
 192.535  
 192.536 -    if (v == NULL) {
 192.537 -        cmsSignalError(LCMS_ERRC_ABORTED, "Out of memory creating named color list");
 192.538 -        return NULL;
 192.539 +    // For really large tables we need this
 192.540 +    while (NewNC ->Allocated < v ->Allocated)
 192.541 +        GrowNamedColorList(NewNC);
 192.542 +
 192.543 +    memmove(NewNC ->Prefix, v ->Prefix, sizeof(v ->Prefix));
 192.544 +    memmove(NewNC ->Suffix, v ->Suffix, sizeof(v ->Suffix));
 192.545 +    NewNC ->ColorantCount = v ->ColorantCount;
 192.546 +    memmove(NewNC->List, v ->List, v->nColors * sizeof(_cmsNAMEDCOLOR));
 192.547 +    NewNC ->nColors = v ->nColors;
 192.548 +    return NewNC;
 192.549 +}
 192.550 +
 192.551 +
 192.552 +// Append a color to a list. List pointer may change if reallocated
 192.553 +cmsBool  CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* NamedColorList,
 192.554 +                                       const char* Name,
 192.555 +                                       cmsUInt16Number PCS[3], cmsUInt16Number Colorant[cmsMAXCHANNELS])
 192.556 +{
 192.557 +    cmsUInt32Number i;
 192.558 +
 192.559 +    if (NamedColorList == NULL) return FALSE;
 192.560 +
 192.561 +    if (NamedColorList ->nColors + 1 > NamedColorList ->Allocated) {
 192.562 +        if (!GrowNamedColorList(NamedColorList)) return FALSE;
 192.563      }
 192.564  
 192.565 -    ZeroMemory(v, size);
 192.566 -
 192.567 -    v ->nColors   = n;
 192.568 -    v ->Allocated = n;
 192.569 -    v ->Prefix[0] = 0;
 192.570 -    v ->Suffix[0] = 0;
 192.571 -
 192.572 -    return v;
 192.573 -}
 192.574 -
 192.575 -void cmsFreeNamedColorList(LPcmsNAMEDCOLORLIST v)
 192.576 -{
 192.577 -    if (v == NULL) {
 192.578 -        cmsSignalError(LCMS_ERRC_RECOVERABLE, "Couldn't free a NULL named color list");
 192.579 -        return;
 192.580 -    }
 192.581 -
 192.582 -    _cmsFree(v);
 192.583 -}
 192.584 -
 192.585 -LCMSBOOL cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS])
 192.586 -{
 192.587 -    _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
 192.588 -    LPcmsNAMEDCOLORLIST List;
 192.589 -    int i;
 192.590 -
 192.591 -    if (v ->NamedColorList == NULL) return FALSE;
 192.592 -
 192.593 -    v ->NamedColorList = GrowNamedColorList(v ->NamedColorList, v->NamedColorList ->nColors + 1);
 192.594 -
 192.595 -    List = v ->NamedColorList;
 192.596 -
 192.597 -    for (i=0; i < MAXCHANNELS; i++)
 192.598 -        List ->List[List ->nColors].DeviceColorant[i] = Colorant[i];
 192.599 +    for (i=0; i < NamedColorList ->ColorantCount; i++)
 192.600 +        NamedColorList ->List[NamedColorList ->nColors].DeviceColorant[i] = Colorant == NULL? 0 : Colorant[i];
 192.601  
 192.602      for (i=0; i < 3; i++)
 192.603 -        List ->List[List ->nColors].PCS[i] = PCS[i];
 192.604 +        NamedColorList ->List[NamedColorList ->nColors].PCS[i] = PCS == NULL ? 0 : PCS[i];
 192.605  
 192.606 -    strncpy(List ->List[List ->nColors].Name, Name, MAX_PATH-1);
 192.607 -    List ->List[List ->nColors].Name[MAX_PATH-1] = 0;
 192.608 +    if (Name != NULL)
 192.609 +        strncpy(NamedColorList ->List[NamedColorList ->nColors].Name, Name,
 192.610 +                    sizeof(NamedColorList ->List[NamedColorList ->nColors].Name));
 192.611 +    else
 192.612 +        NamedColorList ->List[NamedColorList ->nColors].Name[0] = 0;
 192.613  
 192.614 -    List ->nColors++;
 192.615 +
 192.616 +    NamedColorList ->nColors++;
 192.617      return TRUE;
 192.618  }
 192.619  
 192.620 -
 192.621 -
 192.622 -// Returns named color count
 192.623 -
 192.624 -int LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform)
 192.625 +// Returns number of elements
 192.626 +cmsUInt32Number CMSEXPORT cmsNamedColorCount(const cmsNAMEDCOLORLIST* NamedColorList)
 192.627  {
 192.628 -     _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
 192.629 -
 192.630 -     if (v ->NamedColorList == NULL) return 0;
 192.631 -     return v ->NamedColorList ->nColors;
 192.632 +     if (NamedColorList == NULL) return 0;
 192.633 +     return NamedColorList ->nColors;
 192.634  }
 192.635  
 192.636 +// Info aboout a given color
 192.637 +cmsBool  CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cmsUInt32Number nColor,
 192.638 +                                     char* Name,
 192.639 +                                     char* Prefix,
 192.640 +                                     char* Suffix,
 192.641 +                                     cmsUInt16Number* PCS,
 192.642 +                                     cmsUInt16Number* Colorant)
 192.643 +{
 192.644 +    if (NamedColorList == NULL) return FALSE;
 192.645  
 192.646 -LCMSBOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix)
 192.647 -{
 192.648 -    _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
 192.649 +    if (nColor >= cmsNamedColorCount(NamedColorList)) return FALSE;
 192.650  
 192.651 -     if (v ->NamedColorList == NULL) return FALSE;
 192.652 +    if (Name) strcpy(Name, NamedColorList->List[nColor].Name);
 192.653 +    if (Prefix) strcpy(Prefix, NamedColorList->Prefix);
 192.654 +    if (Suffix) strcpy(Suffix, NamedColorList->Suffix);
 192.655 +    if (PCS)
 192.656 +        memmove(PCS, NamedColorList ->List[nColor].PCS, 3*sizeof(cmsUInt16Number));
 192.657  
 192.658 -     if (nColor < 0 || nColor >= cmsNamedColorCount(xform)) return FALSE;
 192.659 +    if (Colorant)
 192.660 +        memmove(Colorant, NamedColorList ->List[nColor].DeviceColorant,
 192.661 +                                sizeof(cmsUInt16Number) * NamedColorList ->ColorantCount);
 192.662  
 192.663 -         if (Name)   { strncpy(Name, v ->NamedColorList->List[nColor].Name, 31); Name[31] = 0; }
 192.664 -         if (Prefix) { strncpy(Prefix, v ->NamedColorList->Prefix, 31); Prefix[31] = 0; }
 192.665 -         if (Suffix) { strncpy(Suffix, v ->NamedColorList->Suffix, 31); Suffix[31] = 0; }
 192.666  
 192.667 -     return TRUE;
 192.668 +    return TRUE;
 192.669  }
 192.670  
 192.671 -
 192.672 -int  LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name)
 192.673 +// Search for a given color name (no prefix or suffix)
 192.674 +cmsInt32Number CMSEXPORT cmsNamedColorIndex(const cmsNAMEDCOLORLIST* NamedColorList, const char* Name)
 192.675  {
 192.676 -    _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
 192.677      int i, n;
 192.678  
 192.679 -         if (v ->NamedColorList == NULL) return -1;
 192.680 +    if (NamedColorList == NULL) return -1;
 192.681 +    n = cmsNamedColorCount(NamedColorList);
 192.682 +    for (i=0; i < n; i++) {
 192.683 +        if (cmsstrcasecmp(Name,  NamedColorList->List[i].Name) == 0)
 192.684 +            return i;
 192.685 +    }
 192.686  
 192.687 -        n = cmsNamedColorCount(xform);
 192.688 -        for (i=0; i < n; i++) {
 192.689 -            if (stricmp(Name,  v ->NamedColorList->List[i].Name) == 0)
 192.690 -                    return i;
 192.691 -        }
 192.692 -
 192.693 -        return -1;
 192.694 +    return -1;
 192.695  }
 192.696  
 192.697 +// MPE support -----------------------------------------------------------------------------------------------------------------
 192.698  
 192.699 +static
 192.700 +void FreeNamedColorList(cmsStage* mpe)
 192.701 +{
 192.702 +    cmsNAMEDCOLORLIST* List = (cmsNAMEDCOLORLIST*) mpe ->Data;
 192.703 +    cmsFreeNamedColorList(List);
 192.704 +}
 192.705 +
 192.706 +static
 192.707 +void* DupNamedColorList(cmsStage* mpe)
 192.708 +{
 192.709 +    cmsNAMEDCOLORLIST* List = (cmsNAMEDCOLORLIST*) mpe ->Data;
 192.710 +    return cmsDupNamedColorList(List);
 192.711 +}
 192.712 +
 192.713 +static
 192.714 +void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
 192.715 +{
 192.716 +    cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) mpe ->Data;
 192.717 +    cmsUInt16Number index = (cmsUInt16Number) _cmsQuickSaturateWord(In[0] * 65535.0);
 192.718 +    cmsUInt32Number j;
 192.719 +
 192.720 +    if (index >= NamedColorList-> nColors) {
 192.721 +        cmsSignalError(NamedColorList ->ContextID, cmsERROR_RANGE, "Color %d out of range; ignored", index);
 192.722 +    }
 192.723 +    else {
 192.724 +        for (j=0; j < NamedColorList ->ColorantCount; j++)
 192.725 +            Out[j] = (cmsFloat32Number) (NamedColorList->List[index].DeviceColorant[j] / 65535.0);
 192.726 +    }
 192.727 +}
 192.728 +
 192.729 +
 192.730 +// Named color lookup element
 192.731 +cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList)
 192.732 +{
 192.733 +    return _cmsStageAllocPlaceholder(NamedColorList ->ContextID,
 192.734 +                                     cmsSigNamedColorElemType,
 192.735 +                                     1, 3,
 192.736 +                                     EvalNamedColor,
 192.737 +                                     DupNamedColorList,
 192.738 +                                     FreeNamedColorList,
 192.739 +                                     cmsDupNamedColorList(NamedColorList));
 192.740 +
 192.741 +}
 192.742 +
 192.743 +
 192.744 +// Retrieve the named color list from a transform. Should be first element in the LUT
 192.745 +cmsNAMEDCOLORLIST* CMSEXPORT cmsGetNamedColorList(cmsHTRANSFORM xform)
 192.746 +{
 192.747 +    _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
 192.748 +    cmsStage* mpe  = v ->Lut->Elements;
 192.749 +
 192.750 +    if (mpe ->Type != cmsSigNamedColorElemType) return NULL;
 192.751 +    return (cmsNAMEDCOLORLIST*) mpe ->Data;
 192.752 +}
 192.753 +
 192.754 +
 192.755 +// Profile sequence description routines -------------------------------------------------------------------------------------
 192.756 +
 192.757 +cmsSEQ* CMSEXPORT cmsAllocProfileSequenceDescription(cmsContext ContextID, cmsUInt32Number n)
 192.758 +{
 192.759 +    cmsSEQ* Seq;
 192.760 +    cmsUInt32Number i;
 192.761 +
 192.762 +    if (n == 0) return NULL;
 192.763 +
 192.764 +    // In a absolutely arbitrary way, I hereby decide to allow a maxim of 255 profiles linked
 192.765 +    // in a devicelink. It makes not sense anyway and may be used for exploits, so let's close the door!
 192.766 +    if (n > 255) return NULL;
 192.767 +
 192.768 +    Seq = (cmsSEQ*) _cmsMallocZero(ContextID, sizeof(cmsSEQ));
 192.769 +    if (Seq == NULL) return NULL;
 192.770 +
 192.771 +    Seq -> ContextID = ContextID;
 192.772 +    Seq -> seq      = (cmsPSEQDESC*) _cmsCalloc(ContextID, n, sizeof(cmsPSEQDESC));
 192.773 +    Seq -> n        = n;
 192.774 +
 192.775 +
 192.776 +    for (i=0; i < n; i++) {
 192.777 +        Seq -> seq[i].Manufacturer = NULL;
 192.778 +        Seq -> seq[i].Model        = NULL;
 192.779 +        Seq -> seq[i].Description  = NULL;
 192.780 +    }
 192.781 +
 192.782 +    return Seq;
 192.783 +}
 192.784 +
 192.785 +void CMSEXPORT cmsFreeProfileSequenceDescription(cmsSEQ* pseq)
 192.786 +{
 192.787 +    cmsUInt32Number i;
 192.788 +
 192.789 +    for (i=0; i < pseq ->n; i++) {
 192.790 +        if (pseq ->seq[i].Manufacturer != NULL) cmsMLUfree(pseq ->seq[i].Manufacturer);
 192.791 +        if (pseq ->seq[i].Model != NULL) cmsMLUfree(pseq ->seq[i].Model);
 192.792 +        if (pseq ->seq[i].Description != NULL) cmsMLUfree(pseq ->seq[i].Description);
 192.793 +    }
 192.794 +
 192.795 +    if (pseq ->seq != NULL) _cmsFree(pseq ->ContextID, pseq ->seq);
 192.796 +    _cmsFree(pseq -> ContextID, pseq);
 192.797 +}
 192.798 +
 192.799 +cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq)
 192.800 +{
 192.801 +    cmsSEQ *NewSeq;
 192.802 +    cmsUInt32Number i;
 192.803 +
 192.804 +    if (pseq == NULL)
 192.805 +        return NULL;
 192.806 +
 192.807 +    NewSeq = (cmsSEQ*) _cmsMalloc(pseq -> ContextID, sizeof(cmsSEQ));
 192.808 +    if (NewSeq == NULL) return NULL;
 192.809 +
 192.810 +
 192.811 +    NewSeq -> seq      = (cmsPSEQDESC*) _cmsCalloc(pseq ->ContextID, pseq ->n, sizeof(cmsPSEQDESC));
 192.812 +    if (NewSeq ->seq == NULL) goto Error;
 192.813 +
 192.814 +    NewSeq -> ContextID = pseq ->ContextID;
 192.815 +    NewSeq -> n        = pseq ->n;
 192.816 +
 192.817 +    for (i=0; i < pseq->n; i++) {
 192.818 +
 192.819 +        memmove(&NewSeq ->seq[i].attributes, &pseq ->seq[i].attributes, sizeof(cmsUInt64Number));
 192.820 +
 192.821 +        NewSeq ->seq[i].deviceMfg   = pseq ->seq[i].deviceMfg;
 192.822 +        NewSeq ->seq[i].deviceModel = pseq ->seq[i].deviceModel;
 192.823 +        memmove(&NewSeq ->seq[i].ProfileID, &pseq ->seq[i].ProfileID, sizeof(cmsProfileID));
 192.824 +        NewSeq ->seq[i].technology  = pseq ->seq[i].technology;
 192.825 +
 192.826 +        NewSeq ->seq[i].Manufacturer = cmsMLUdup(pseq ->seq[i].Manufacturer);
 192.827 +        NewSeq ->seq[i].Model        = cmsMLUdup(pseq ->seq[i].Model);
 192.828 +        NewSeq ->seq[i].Description  = cmsMLUdup(pseq ->seq[i].Description);
 192.829 +
 192.830 +    }
 192.831 +
 192.832 +    return NewSeq;
 192.833 +
 192.834 +Error:
 192.835 +
 192.836 +    cmsFreeProfileSequenceDescription(NewSeq);
 192.837 +    return NULL;
 192.838 +}
 192.839 +
   193.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsopt.c	Fri Sep 24 16:41:32 2010 -0700
   193.3 @@ -0,0 +1,1657 @@
   193.4 +/*
   193.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   193.6 + *
   193.7 + * This code is free software; you can redistribute it and/or modify it
   193.8 + * under the terms of the GNU General Public License version 2 only, as
   193.9 + * published by the Free Software Foundation.  Oracle designates this
  193.10 + * particular file as subject to the "Classpath" exception as provided
  193.11 + * by Oracle in the LICENSE file that accompanied this code.
  193.12 + *
  193.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  193.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  193.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  193.16 + * version 2 for more details (a copy is included in the LICENSE file that
  193.17 + * accompanied this code).
  193.18 + *
  193.19 + * You should have received a copy of the GNU General Public License version
  193.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  193.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  193.22 + *
  193.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  193.24 + * or visit www.oracle.com if you need additional information or have any
  193.25 + * questions.
  193.26 + */
  193.27 +
  193.28 +// This file is available under and governed by the GNU General Public
  193.29 +// License version 2 only, as published by the Free Software Foundation.
  193.30 +// However, the following notice accompanied the original version of this
  193.31 +// file:
  193.32 +//
  193.33 +//---------------------------------------------------------------------------------
  193.34 +//
  193.35 +//  Little Color Management System
  193.36 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  193.37 +//
  193.38 +// Permission is hereby granted, free of charge, to any person obtaining
  193.39 +// a copy of this software and associated documentation files (the "Software"),
  193.40 +// to deal in the Software without restriction, including without limitation
  193.41 +// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  193.42 +// and/or sell copies of the Software, and to permit persons to whom the Software
  193.43 +// is furnished to do so, subject to the following conditions:
  193.44 +//
  193.45 +// The above copyright notice and this permission notice shall be included in
  193.46 +// all copies or substantial portions of the Software.
  193.47 +//
  193.48 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  193.49 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  193.50 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  193.51 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  193.52 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  193.53 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  193.54 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  193.55 +//
  193.56 +//---------------------------------------------------------------------------------
  193.57 +//
  193.58 +
  193.59 +#include "lcms2_internal.h"
  193.60 +
  193.61 +
  193.62 +//----------------------------------------------------------------------------------
  193.63 +
  193.64 +// Optimization for 8 bits, Shaper-CLUT (3 inputs only)
  193.65 +typedef struct {
  193.66 +
  193.67 +    cmsContext ContextID;
  193.68 +
  193.69 +    const cmsInterpParams* p;   // Tetrahedrical interpolation parameters. This is a not-owned pointer.
  193.70 +
  193.71 +    cmsUInt16Number rx[256], ry[256], rz[256];
  193.72 +    cmsUInt32Number X0[256], Y0[256], Z0[256];  // Precomputed nodes and offsets for 8-bit input data
  193.73 +
  193.74 +
  193.75 +} Prelin8Data;
  193.76 +
  193.77 +
  193.78 +// Generic optimization for 16 bits Shaper-CLUT-Shaper (any inputs)
  193.79 +typedef struct {
  193.80 +
  193.81 +    cmsContext ContextID;
  193.82 +
  193.83 +    // Number of channels
  193.84 +    int nInputs;
  193.85 +    int nOutputs;
  193.86 +
  193.87 +    // Since there is no limitation of the output number of channels, this buffer holding the connexion CLUT-shaper
  193.88 +    // has to be dynamically allocated. This is not the case of first step shaper-CLUT, which is limited to max inputs
  193.89 +    cmsUInt16Number* StageDEF;
  193.90 +
  193.91 +    _cmsInterpFn16 EvalCurveIn16[MAX_INPUT_DIMENSIONS];       // The maximum number of input channels is known in advance
  193.92 +    cmsInterpParams*  ParamsCurveIn16[MAX_INPUT_DIMENSIONS];
  193.93 +
  193.94 +    _cmsInterpFn16 EvalCLUT;            // The evaluator for 3D grid
  193.95 +    const cmsInterpParams* CLUTparams;  // (not-owned pointer)
  193.96 +
  193.97 +
  193.98 +    _cmsInterpFn16* EvalCurveOut16;       // Points to an array of curve evaluators in 16 bits (not-owned pointer)
  193.99 +    cmsInterpParams**  ParamsCurveOut16;  // Points to an array of references to interpolation params (not-owned pointer)
 193.100 +
 193.101 +
 193.102 +} Prelin16Data;
 193.103 +
 193.104 +
 193.105 +// Optimization for matrix-shaper in 8 bits. Numbers are operated in n.14 signed, tables are stored in 1.14 fixed
 193.106 +
 193.107 +typedef cmsInt32Number cmsS1Fixed14Number;   // Note that this may hold more than 16 bits!
 193.108 +
 193.109 +#define DOUBLE_TO_1FIXED14(x) ((cmsS1Fixed14Number) floor((x) * 16384.0 + 0.5))
 193.110 +
 193.111 +typedef struct {
 193.112 +
 193.113 +    cmsContext ContextID;
 193.114 +
 193.115 +    cmsS1Fixed14Number Shaper1R[256];  // from 0..255 to 1.14  (0.0...1.0)
 193.116 +    cmsS1Fixed14Number Shaper1G[256];
 193.117 +    cmsS1Fixed14Number Shaper1B[256];
 193.118 +
 193.119 +    cmsS1Fixed14Number Mat[3][3];     // n.14 to n.14 (needs a saturation after that)
 193.120 +    cmsS1Fixed14Number Off[3];
 193.121 +
 193.122 +    cmsUInt16Number Shaper2R[16385];    // 1.14 to 0..255
 193.123 +    cmsUInt16Number Shaper2G[16385];
 193.124 +    cmsUInt16Number Shaper2B[16385];
 193.125 +
 193.126 +} MatShaper8Data;
 193.127 +
 193.128 +// Curves, optimization is shared between 8 and 16 bits
 193.129 +typedef struct {
 193.130 +
 193.131 +    cmsContext ContextID;
 193.132 +
 193.133 +    int nCurves;                  // Number of curves
 193.134 +    int nElements;                // Elements in curves
 193.135 +    cmsUInt16Number** Curves;     // Points to a dynamically  allocated array
 193.136 +
 193.137 +} Curves16Data;
 193.138 +
 193.139 +
 193.140 +// Simple optimizations ----------------------------------------------------------------------------------------------------------
 193.141 +
 193.142 +
 193.143 +// Remove an element in linked chain
 193.144 +static
 193.145 +void _RemoveElement(cmsStage** head)
 193.146 +{
 193.147 +    cmsStage* mpe = *head;
 193.148 +    cmsStage* next = mpe ->Next;
 193.149 +    *head = next;
 193.150 +    cmsStageFree(mpe);
 193.151 +}
 193.152 +
 193.153 +// Remove all identities in chain. Note that pt actually is a double pointer to the element that holds the pointer.
 193.154 +static
 193.155 +cmsBool _Remove1Op(cmsPipeline* Lut, cmsStageSignature UnaryOp)
 193.156 +{
 193.157 +    cmsStage** pt = &Lut ->Elements;
 193.158 +    cmsBool AnyOpt = FALSE;
 193.159 +
 193.160 +    while (*pt != NULL) {
 193.161 +
 193.162 +        if ((*pt) ->Implements == UnaryOp) {
 193.163 +            _RemoveElement(pt);
 193.164 +            AnyOpt = TRUE;
 193.165 +        }
 193.166 +        else
 193.167 +            pt = &((*pt) -> Next);
 193.168 +    }
 193.169 +
 193.170 +    return AnyOpt;
 193.171 +}
 193.172 +
 193.173 +// Same, but only if two adjacent elements are found
 193.174 +static
 193.175 +cmsBool _Remove2Op(cmsPipeline* Lut, cmsStageSignature Op1, cmsStageSignature Op2)
 193.176 +{
 193.177 +    cmsStage** pt1;
 193.178 +    cmsStage** pt2;
 193.179 +    cmsBool AnyOpt = FALSE;
 193.180 +
 193.181 +    pt1 = &Lut ->Elements;
 193.182 +    if (*pt1 == NULL) return AnyOpt;
 193.183 +
 193.184 +    while (*pt1 != NULL) {
 193.185 +
 193.186 +        pt2 = &((*pt1) -> Next);
 193.187 +        if (*pt2 == NULL) return AnyOpt;
 193.188 +
 193.189 +        if ((*pt1) ->Implements == Op1 && (*pt2) ->Implements == Op2) {
 193.190 +            _RemoveElement(pt2);
 193.191 +            _RemoveElement(pt1);
 193.192 +            AnyOpt = TRUE;
 193.193 +        }
 193.194 +        else
 193.195 +            pt1 = &((*pt1) -> Next);
 193.196 +    }
 193.197 +
 193.198 +    return AnyOpt;
 193.199 +}
 193.200 +
 193.201 +// Preoptimize just gets rif of no-ops coming paired. Conversion from v2 to v4 followed
 193.202 +// by a v4 to v2 and vice-versa. The elements are then discarded.
 193.203 +static
 193.204 +cmsBool PreOptimize(cmsPipeline* Lut)
 193.205 +{
 193.206 +    cmsBool AnyOpt = FALSE, Opt;
 193.207 +
 193.208 +    AnyOpt = FALSE;
 193.209 +
 193.210 +    do {
 193.211 +
 193.212 +        Opt = FALSE;
 193.213 +
 193.214 +        // Remove all identities
 193.215 +        Opt |= _Remove1Op(Lut, cmsSigIdentityElemType);
 193.216 +
 193.217 +        // Remove XYZ2Lab followed by Lab2XYZ
 193.218 +        Opt |= _Remove2Op(Lut, cmsSigXYZ2LabElemType, cmsSigLab2XYZElemType);
 193.219 +
 193.220 +        // Remove Lab2XYZ followed by XYZ2Lab
 193.221 +        Opt |= _Remove2Op(Lut, cmsSigLab2XYZElemType, cmsSigXYZ2LabElemType);
 193.222 +
 193.223 +        // Remove V4 to V2 followed by V2 to V4
 193.224 +        Opt |= _Remove2Op(Lut, cmsSigLabV4toV2, cmsSigLabV2toV4);
 193.225 +
 193.226 +        // Remove V2 to V4 followed by V4 to V2
 193.227 +        Opt |= _Remove2Op(Lut, cmsSigLabV2toV4, cmsSigLabV4toV2);
 193.228 +
 193.229 +        if (Opt) AnyOpt = TRUE;
 193.230 +
 193.231 +    } while (Opt);
 193.232 +
 193.233 +    return AnyOpt;
 193.234 +}
 193.235 +
 193.236 +static
 193.237 +void Eval16nop1D(register const cmsUInt16Number Input[],
 193.238 +                 register cmsUInt16Number Output[],
 193.239 +                 register const struct _cms_interp_struc* p)
 193.240 +{
 193.241 +    Output[0] = Input[0];
 193.242 +
 193.243 +    cmsUNUSED_PARAMETER(p);
 193.244 +}
 193.245 +
 193.246 +static
 193.247 +void PrelinEval16(register const cmsUInt16Number Input[],
 193.248 +                  register cmsUInt16Number Output[],
 193.249 +                  register const void* D)
 193.250 +{
 193.251 +    Prelin16Data* p16 = (Prelin16Data*) D;
 193.252 +    cmsUInt16Number  StageABC[MAX_INPUT_DIMENSIONS];
 193.253 +    int i;
 193.254 +
 193.255 +    for (i=0; i < p16 ->nInputs; i++) {
 193.256 +
 193.257 +        p16 ->EvalCurveIn16[i](&Input[i], &StageABC[i], p16 ->ParamsCurveIn16[i]);
 193.258 +    }
 193.259 +
 193.260 +    p16 ->EvalCLUT(StageABC, p16 ->StageDEF, p16 ->CLUTparams);
 193.261 +
 193.262 +    for (i=0; i < p16 ->nOutputs; i++) {
 193.263 +
 193.264 +        p16 ->EvalCurveOut16[i](&p16->StageDEF[i], &Output[i], p16 ->ParamsCurveOut16[i]);
 193.265 +    }
 193.266 +}
 193.267 +
 193.268 +
 193.269 +static
 193.270 +void PrelinOpt16free(cmsContext ContextID, void* ptr)
 193.271 +{
 193.272 +    Prelin16Data* p16 = (Prelin16Data*) ptr;
 193.273 +
 193.274 +    _cmsFree(ContextID, p16 ->StageDEF);
 193.275 +    _cmsFree(ContextID, p16 ->EvalCurveOut16);
 193.276 +    _cmsFree(ContextID, p16 ->ParamsCurveOut16);
 193.277 +
 193.278 +    _cmsFree(ContextID, p16);
 193.279 +}
 193.280 +
 193.281 +static
 193.282 +void* Prelin16dup(cmsContext ContextID, const void* ptr)
 193.283 +{
 193.284 +    Prelin16Data* p16 = (Prelin16Data*) ptr;
 193.285 +    Prelin16Data* Duped = _cmsDupMem(ContextID, p16, sizeof(Prelin16Data));
 193.286 +
 193.287 +    if (Duped == NULL) return NULL;
 193.288 +
 193.289 +    Duped ->StageDEF         = _cmsCalloc(ContextID, p16 ->nOutputs, sizeof(cmsUInt16Number));
 193.290 +    Duped ->EvalCurveOut16   = _cmsDupMem(ContextID, p16 ->EvalCurveOut16, p16 ->nOutputs * sizeof(_cmsInterpFn16));
 193.291 +    Duped ->ParamsCurveOut16 = _cmsDupMem(ContextID, p16 ->ParamsCurveOut16, p16 ->nOutputs * sizeof(cmsInterpParams* ));
 193.292 +
 193.293 +    return Duped;
 193.294 +}
 193.295 +
 193.296 +
 193.297 +static
 193.298 +Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
 193.299 +                               const cmsInterpParams* ColorMap,
 193.300 +                               int nInputs, cmsToneCurve** In,
 193.301 +                               int nOutputs, cmsToneCurve** Out )
 193.302 +{
 193.303 +    int i;
 193.304 +    Prelin16Data* p16 = (Prelin16Data*) _cmsMallocZero(ContextID, sizeof(Prelin16Data));
 193.305 +    if (p16 == NULL) return NULL;
 193.306 +
 193.307 +    p16 ->nInputs = nInputs;
 193.308 +    p16 -> nOutputs = nOutputs;
 193.309 +
 193.310 +
 193.311 +    for (i=0; i < nInputs; i++) {
 193.312 +
 193.313 +        if (In == NULL) {
 193.314 +            p16 -> ParamsCurveIn16[i] = NULL;
 193.315 +            p16 -> EvalCurveIn16[i] = Eval16nop1D;
 193.316 +
 193.317 +        }
 193.318 +        else {
 193.319 +            p16 -> ParamsCurveIn16[i] = In[i] ->InterpParams;
 193.320 +            p16 -> EvalCurveIn16[i] = p16 ->ParamsCurveIn16[i]->Interpolation.Lerp16;
 193.321 +        }
 193.322 +    }
 193.323 +
 193.324 +    p16 ->CLUTparams = ColorMap;
 193.325 +    p16 ->EvalCLUT   = ColorMap ->Interpolation.Lerp16;
 193.326 +
 193.327 +
 193.328 +    p16 -> StageDEF = _cmsCalloc(ContextID, p16 ->nOutputs, sizeof(cmsUInt16Number));
 193.329 +    p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16));
 193.330 +    p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* ));
 193.331 +
 193.332 +    for (i=0; i < nOutputs; i++) {
 193.333 +
 193.334 +        if (Out == NULL) {
 193.335 +            p16 ->ParamsCurveOut16[i] = NULL;
 193.336 +            p16 -> EvalCurveOut16[i] = Eval16nop1D;
 193.337 +        }
 193.338 +        else {
 193.339 +
 193.340 +            p16 ->ParamsCurveOut16[i] = Out[i] ->InterpParams;
 193.341 +            p16 -> EvalCurveOut16[i] = p16 ->ParamsCurveOut16[i]->Interpolation.Lerp16;
 193.342 +        }
 193.343 +    }
 193.344 +
 193.345 +    return p16;
 193.346 +}
 193.347 +
 193.348 +
 193.349 +
 193.350 +// Resampling ---------------------------------------------------------------------------------
 193.351 +
 193.352 +#define PRELINEARIZATION_POINTS 4096
 193.353 +
 193.354 +// Sampler implemented by another LUT. This is a clean way to precalculate the devicelink 3D CLUT for
 193.355 +// almost any transform. We use floating point precision and then convert from floating point to 16 bits.
 193.356 +static
 193.357 +int XFormSampler16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
 193.358 +{
 193.359 +    cmsPipeline* Lut = (cmsPipeline*) Cargo;
 193.360 +    cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS];
 193.361 +    cmsUInt32Number i;
 193.362 +
 193.363 +    _cmsAssert(Lut -> InputChannels < cmsMAXCHANNELS);
 193.364 +    _cmsAssert(Lut -> OutputChannels < cmsMAXCHANNELS);
 193.365 +
 193.366 +    // From 16 bit to floating point
 193.367 +    for (i=0; i < Lut ->InputChannels; i++)
 193.368 +        InFloat[i] = (cmsFloat32Number) (In[i] / 65535.0);
 193.369 +
 193.370 +    // Evaluate in floating point
 193.371 +    cmsPipelineEvalFloat(InFloat, OutFloat, Lut);
 193.372 +
 193.373 +    // Back to 16 bits representation
 193.374 +    for (i=0; i < Lut ->OutputChannels; i++)
 193.375 +        Out[i] = _cmsQuickSaturateWord(OutFloat[i] * 65535.0);
 193.376 +
 193.377 +    // Always succeed
 193.378 +    return TRUE;
 193.379 +}
 193.380 +
 193.381 +// Try to see if the curves of a given MPE are linear
 193.382 +static
 193.383 +cmsBool AllCurvesAreLinear(cmsStage* mpe)
 193.384 +{
 193.385 +    cmsToneCurve** Curves;
 193.386 +    cmsUInt32Number i, n;
 193.387 +
 193.388 +    Curves = _cmsStageGetPtrToCurveSet(mpe);
 193.389 +    if (Curves == NULL) return FALSE;
 193.390 +
 193.391 +    n = cmsStageOutputChannels(mpe);
 193.392 +
 193.393 +    for (i=0; i < n; i++) {
 193.394 +        if (!cmsIsToneCurveLinear(Curves[i])) return FALSE;
 193.395 +    }
 193.396 +
 193.397 +    return TRUE;
 193.398 +}
 193.399 +
 193.400 +// This function replaces a specific node placed in "At" by the "Value" numbers. Its purpose
 193.401 +// is to fix scum dot on broken profiles/transforms. Works on 1, 3 and 4 channels
 193.402 +static
 193.403 +cmsBool  PatchLUT(cmsStage* CLUT, cmsUInt16Number At[], cmsUInt16Number Value[],
 193.404 +                  int nChannelsOut, int nChannelsIn)
 193.405 +{
 193.406 +    _cmsStageCLutData* Grid = (_cmsStageCLutData*) CLUT ->Data;
 193.407 +    cmsInterpParams* p16  = Grid ->Params;
 193.408 +    cmsFloat64Number px, py, pz, pw;
 193.409 +    int        x0, y0, z0, w0;
 193.410 +    int        i, index;
 193.411 +
 193.412 +    if (CLUT -> Type != cmsSigCLutElemType) {
 193.413 +        cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) Attempt to PatchLUT on non-lut MPE");
 193.414 +        return FALSE;
 193.415 +    }
 193.416 +
 193.417 +    px = ((cmsFloat64Number) At[0] * (p16->Domain[0])) / 65535.0;
 193.418 +    py = ((cmsFloat64Number) At[1] * (p16->Domain[1])) / 65535.0;
 193.419 +    pz = ((cmsFloat64Number) At[2] * (p16->Domain[2])) / 65535.0;
 193.420 +    pw = ((cmsFloat64Number) At[3] * (p16->Domain[3])) / 65535.0;
 193.421 +
 193.422 +    x0 = (int) floor(px);
 193.423 +    y0 = (int) floor(py);
 193.424 +    z0 = (int) floor(pz);
 193.425 +    w0 = (int) floor(pw);
 193.426 +
 193.427 +    if (nChannelsIn == 4) {
 193.428 +
 193.429 +        if (((px - x0) != 0) ||
 193.430 +            ((py - y0) != 0) ||
 193.431 +            ((pz - z0) != 0) ||
 193.432 +            ((pw - w0) != 0)) return FALSE; // Not on exact node
 193.433 +
 193.434 +        index = p16 -> opta[3] * x0 +
 193.435 +            p16 -> opta[2] * y0 +
 193.436 +            p16 -> opta[1] * z0 +
 193.437 +            p16 -> opta[0] * w0;
 193.438 +    }
 193.439 +    else
 193.440 +        if (nChannelsIn == 3) {
 193.441 +
 193.442 +            if (((px - x0) != 0) ||
 193.443 +                ((py - y0) != 0) ||
 193.444 +                ((pz - z0) != 0)) return FALSE;  // Not on exact node
 193.445 +
 193.446 +            index = p16 -> opta[2] * x0 +
 193.447 +                p16 -> opta[1] * y0 +
 193.448 +                p16 -> opta[0] * z0;
 193.449 +        }
 193.450 +        else
 193.451 +            if (nChannelsIn == 1) {
 193.452 +
 193.453 +                if (((px - x0) != 0)) return FALSE; // Not on exact node
 193.454 +
 193.455 +                index = p16 -> opta[0] * x0;
 193.456 +            }
 193.457 +            else {
 193.458 +                cmsSignalError(CLUT->ContextID, cmsERROR_INTERNAL, "(internal) %d Channels are not supported on PatchLUT", nChannelsIn);
 193.459 +                return FALSE;
 193.460 +            }
 193.461 +
 193.462 +            for (i=0; i < nChannelsOut; i++)
 193.463 +                Grid -> Tab.T[index + i] = Value[i];
 193.464 +
 193.465 +            return TRUE;
 193.466 +}
 193.467 +
 193.468 +// Auxiliar, to see if two values are equal.
 193.469 +static
 193.470 +cmsBool WhitesAreEqual(int n, cmsUInt16Number White1[], cmsUInt16Number White2[] )
 193.471 +{
 193.472 +    int i;
 193.473 +
 193.474 +    for (i=0; i < n; i++) {
 193.475 +        if (White1[i] != White2[i]) return FALSE;
 193.476 +    }
 193.477 +    return TRUE;
 193.478 +}
 193.479 +
 193.480 +
 193.481 +// Locate the node for the white point and fix it to pure white in order to avoid scum dot.
 193.482 +static
 193.483 +cmsBool FixWhiteMisalignment(cmsPipeline* Lut, cmsColorSpaceSignature EntryColorSpace, cmsColorSpaceSignature ExitColorSpace)
 193.484 +{
 193.485 +    cmsUInt16Number *WhitePointIn, *WhitePointOut;
 193.486 +    cmsUInt16Number  WhiteIn[cmsMAXCHANNELS], WhiteOut[cmsMAXCHANNELS], ObtainedOut[cmsMAXCHANNELS];
 193.487 +    cmsUInt32Number i, nOuts, nIns;
 193.488 +    cmsStage *PreLin = NULL, *CLUT = NULL, *PostLin = NULL;
 193.489 +
 193.490 +    if (!_cmsEndPointsBySpace(EntryColorSpace,
 193.491 +        &WhitePointIn, NULL, &nIns)) return FALSE;
 193.492 +
 193.493 +    if (!_cmsEndPointsBySpace(ExitColorSpace,
 193.494 +        &WhitePointOut, NULL, &nOuts)) return FALSE;
 193.495 +
 193.496 +    // It needs to be fixed?
 193.497 +
 193.498 +    cmsPipelineEval16(WhitePointIn, ObtainedOut, Lut);
 193.499 +
 193.500 +    if (WhitesAreEqual(nOuts, WhitePointOut, ObtainedOut)) return TRUE; // whites already match
 193.501 +
 193.502 +    // Check if the LUT comes as Prelin, CLUT or Postlin. We allow all combinations
 193.503 +    if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &PreLin, &CLUT, &PostLin))
 193.504 +        if (!cmsPipelineCheckAndRetreiveStages(Lut, 2, cmsSigCurveSetElemType, cmsSigCLutElemType, &PreLin, &CLUT))
 193.505 +            if (!cmsPipelineCheckAndRetreiveStages(Lut, 2, cmsSigCLutElemType, cmsSigCurveSetElemType, &CLUT, &PostLin))
 193.506 +                if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCLutElemType, &CLUT))
 193.507 +                    return FALSE;
 193.508 +
 193.509 +    // We need to interpolate white points of both, pre and post curves
 193.510 +    if (PreLin) {
 193.511 +
 193.512 +        cmsToneCurve** Curves = _cmsStageGetPtrToCurveSet(PreLin);
 193.513 +
 193.514 +        for (i=0; i < nIns; i++) {
 193.515 +            WhiteIn[i] = cmsEvalToneCurve16(Curves[i], WhitePointIn[i]);
 193.516 +        }
 193.517 +    }
 193.518 +    else {
 193.519 +        for (i=0; i < nIns; i++)
 193.520 +            WhiteIn[i] = WhitePointIn[i];
 193.521 +    }
 193.522 +
 193.523 +    // If any post-linearization, we need to find how is represented white before the curve, do
 193.524 +    // a reverse interpolation in this case.
 193.525 +    if (PostLin) {
 193.526 +
 193.527 +        cmsToneCurve** Curves = _cmsStageGetPtrToCurveSet(PostLin);
 193.528 +
 193.529 +        for (i=0; i < nOuts; i++) {
 193.530 +
 193.531 +            cmsToneCurve* InversePostLin = cmsReverseToneCurve(Curves[i]);
 193.532 +            WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]);
 193.533 +            cmsFreeToneCurve(InversePostLin);
 193.534 +        }
 193.535 +    }
 193.536 +    else {
 193.537 +        for (i=0; i < nOuts; i++)
 193.538 +            WhiteOut[i] = WhitePointOut[i];
 193.539 +    }
 193.540 +
 193.541 +    // Ok, proceed with patching. May fail and we don't care if it fails
 193.542 +    PatchLUT(CLUT, WhiteIn, WhiteOut, nOuts, nIns);
 193.543 +
 193.544 +    return TRUE;
 193.545 +}
 193.546 +
 193.547 +// -----------------------------------------------------------------------------------------------------------------------------------------------
 193.548 +// This function creates simple LUT from complex ones. The generated LUT has an optional set of
 193.549 +// prelinearization curves, a CLUT of nGridPoints and optional postlinearization tables.
 193.550 +// These curves have to exist in the original LUT in order to be used in the simplified output.
 193.551 +// Caller may also use the flags to allow this feature.
 193.552 +// LUTS with all curves will be simplified to a single curve. Parametric curves are lost.
 193.553 +// This function should be used on 16-bits LUTS only, as floating point losses precision when simplified
 193.554 +// -----------------------------------------------------------------------------------------------------------------------------------------------
 193.555 +
 193.556 +static
 193.557 +cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
 193.558 +{
 193.559 +    cmsPipeline* Src;
 193.560 +    cmsPipeline* Dest;
 193.561 +    cmsStage* CLUT;
 193.562 +    cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL;
 193.563 +    int nGridPoints;
 193.564 +    cmsColorSpaceSignature ColorSpace, OutputColorSpace;
 193.565 +    cmsStage *NewPreLin = NULL;
 193.566 +    cmsStage *NewPostLin = NULL;
 193.567 +    _cmsStageCLutData* DataCLUT;
 193.568 +    cmsToneCurve** DataSetIn;
 193.569 +    cmsToneCurve** DataSetOut;
 193.570 +    Prelin16Data* p16;
 193.571 +
 193.572 +
 193.573 +    // This is a loosy optimization! does not apply in floating-point cases
 193.574 +    if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;
 193.575 +
 193.576 +    ColorSpace       = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat));
 193.577 +    OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat));
 193.578 +    nGridPoints      = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags);
 193.579 +
 193.580 +    // For empty LUTs, 2 points are enough
 193.581 +    if (cmsPipelineStageCount(*Lut) == 0)
 193.582 +        nGridPoints = 2;
 193.583 +
 193.584 +    Src = *Lut;
 193.585 +
 193.586 +    // Allocate an empty LUT
 193.587 +    Dest =  cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
 193.588 +    if (!Dest) return FALSE;
 193.589 +
 193.590 +    // Prelinearization tables are kept unless indicated by flags
 193.591 +    if (*dwFlags & cmsFLAGS_CLUT_PRE_LINEARIZATION) {
 193.592 +
 193.593 +        // Get a pointer to the prelinearization element
 193.594 +        cmsStage* PreLin = cmsPipelineGetPtrToFirstStage(Src);
 193.595 +
 193.596 +        // Check if suitable
 193.597 +        if (PreLin ->Type == cmsSigCurveSetElemType) {
 193.598 +
 193.599 +            // Maybe this is a linear tram, so we can avoid the whole stuff
 193.600 +            if (!AllCurvesAreLinear(PreLin)) {
 193.601 +
 193.602 +                // All seems ok, proceed.
 193.603 +                NewPreLin = cmsStageDup(PreLin);
 193.604 +                cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin);
 193.605 +
 193.606 +                // Remove prelinearization. Since we have duplicated the curve
 193.607 +                // in destination LUT, the sampling shoud be applied after this stage.
 193.608 +                cmsPipelineUnlinkStage(Src, cmsAT_BEGIN, &KeepPreLin);
 193.609 +            }
 193.610 +        }
 193.611 +    }
 193.612 +
 193.613 +    // Allocate the CLUT
 193.614 +    CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL);
 193.615 +    if (CLUT == NULL) return FALSE;
 193.616 +
 193.617 +    // Add the CLUT to the destination LUT
 193.618 +    cmsPipelineInsertStage(Dest, cmsAT_END, CLUT);
 193.619 +
 193.620 +    // Postlinearization tables are kept unless indicated by flags
 193.621 +    if (*dwFlags & cmsFLAGS_CLUT_POST_LINEARIZATION) {
 193.622 +
 193.623 +        // Get a pointer to the postlinearization if present
 193.624 +        cmsStage* PostLin = cmsPipelineGetPtrToLastStage(Src);
 193.625 +
 193.626 +        // Check if suitable
 193.627 +        if (cmsStageType(PostLin) == cmsSigCurveSetElemType) {
 193.628 +
 193.629 +            // Maybe this is a linear tram, so we can avoid the whole stuff
 193.630 +            if (!AllCurvesAreLinear(PostLin)) {
 193.631 +
 193.632 +                // All seems ok, proceed.
 193.633 +                NewPostLin = cmsStageDup(PostLin);
 193.634 +                cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin);
 193.635 +
 193.636 +                // In destination LUT, the sampling shoud be applied after this stage.
 193.637 +                cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin);
 193.638 +            }
 193.639 +        }
 193.640 +    }
 193.641 +
 193.642 +    // Now its time to do the sampling. We have to ignore pre/post linearization
 193.643 +    // The source LUT whithout pre/post curves is passed as parameter.
 193.644 +    if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) {
 193.645 +
 193.646 +        // Ops, something went wrong, Restore stages
 193.647 +        if (KeepPreLin != NULL)  cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin);
 193.648 +        if (KeepPostLin != NULL) cmsPipelineInsertStage(Src, cmsAT_END,   KeepPostLin);
 193.649 +        cmsPipelineFree(Dest);
 193.650 +        return FALSE;
 193.651 +    }
 193.652 +
 193.653 +    // Done.
 193.654 +
 193.655 +    if (KeepPreLin != NULL) cmsStageFree(KeepPreLin);
 193.656 +    if (KeepPostLin != NULL) cmsStageFree(KeepPostLin);
 193.657 +    cmsPipelineFree(Src);
 193.658 +
 193.659 +    DataCLUT = (_cmsStageCLutData*) CLUT ->Data;
 193.660 +
 193.661 +    if (NewPreLin == NULL) DataSetIn = NULL;
 193.662 +    else DataSetIn = ((_cmsStageToneCurvesData*) NewPreLin ->Data) ->TheCurves;
 193.663 +
 193.664 +    if (NewPostLin == NULL) DataSetOut = NULL;
 193.665 +    else  DataSetOut = ((_cmsStageToneCurvesData*) NewPostLin ->Data) ->TheCurves;
 193.666 +
 193.667 +
 193.668 +    if (DataSetIn == NULL && DataSetOut == NULL) {
 193.669 +
 193.670 +        _cmsPipelineSetOptimizationParameters(Dest, (_cmsOPTeval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
 193.671 +    }
 193.672 +    else {
 193.673 +
 193.674 +        p16 = PrelinOpt16alloc(Dest ->ContextID,
 193.675 +                               DataCLUT ->Params,
 193.676 +                               Dest ->InputChannels,
 193.677 +                               DataSetIn,
 193.678 +                               Dest ->OutputChannels,
 193.679 +                               DataSetOut);
 193.680 +
 193.681 +
 193.682 +        _cmsPipelineSetOptimizationParameters(Dest, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);
 193.683 +    }
 193.684 +
 193.685 +
 193.686 +    // Don't fix white on absolute colorimetric
 193.687 +    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
 193.688 +        *dwFlags |= cmsFLAGS_NOWHITEONWHITEFIXUP;
 193.689 +
 193.690 +    if (!(*dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) {
 193.691 +
 193.692 +        FixWhiteMisalignment(Dest, ColorSpace, OutputColorSpace);
 193.693 +    }
 193.694 +
 193.695 +    *Lut = Dest;
 193.696 +    return TRUE;
 193.697 +
 193.698 +    cmsUNUSED_PARAMETER(Intent);
 193.699 +}
 193.700 +
 193.701 +
 193.702 +// -----------------------------------------------------------------------------------------------------------------------------------------------
 193.703 +// Fixes the gamma balancing of transform. This is described in my paper "Prelinearization Stages on
 193.704 +// Color-Management Application-Specific Integrated Circuits (ASICs)" presented at NIP24. It only works
 193.705 +// for RGB transforms. See the paper for more details
 193.706 +// -----------------------------------------------------------------------------------------------------------------------------------------------
 193.707 +
 193.708 +
 193.709 +// Normalize endpoints by slope limiting max and min. This assures endpoints as well.
 193.710 +// Descending curves are handled as well.
 193.711 +static
 193.712 +void SlopeLimiting(cmsToneCurve* g)
 193.713 +{
 193.714 +    int BeginVal, EndVal;
 193.715 +    int AtBegin = (int) floor((cmsFloat64Number) g ->nEntries * 0.02 + 0.5);   // Cutoff at 2%
 193.716 +    int AtEnd   = g ->nEntries - AtBegin - 1;                                  // And 98%
 193.717 +    cmsFloat64Number Val, Slope, beta;
 193.718 +    int i;
 193.719 +
 193.720 +    if (cmsIsToneCurveDescending(g)) {
 193.721 +        BeginVal = 0xffff; EndVal = 0;
 193.722 +    }
 193.723 +    else {
 193.724 +        BeginVal = 0; EndVal = 0xffff;
 193.725 +    }
 193.726 +
 193.727 +    // Compute slope and offset for begin of curve
 193.728 +    Val   = g ->Table16[AtBegin];
 193.729 +    Slope = (Val - BeginVal) / AtBegin;
 193.730 +    beta  = Val - Slope * AtBegin;
 193.731 +
 193.732 +    for (i=0; i < AtBegin; i++)
 193.733 +        g ->Table16[i] = _cmsQuickSaturateWord(i * Slope + beta);
 193.734 +
 193.735 +    // Compute slope and offset for the end
 193.736 +    Val   = g ->Table16[AtEnd];
 193.737 +    Slope = (EndVal - Val) / AtBegin;   // AtBegin holds the X interval, which is same in both cases
 193.738 +    beta  = Val - Slope * AtEnd;
 193.739 +
 193.740 +    for (i = AtEnd; i < (int) g ->nEntries; i++)
 193.741 +        g ->Table16[i] = _cmsQuickSaturateWord(i * Slope + beta);
 193.742 +}
 193.743 +
 193.744 +
 193.745 +// Precomputes tables for 8-bit on input devicelink.
 193.746 +static
 193.747 +Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cmsToneCurve* G[3])
 193.748 +{
 193.749 +    int i;
 193.750 +    cmsUInt16Number Input[3];
 193.751 +    cmsS15Fixed16Number v1, v2, v3;
 193.752 +    Prelin8Data* p8;
 193.753 +
 193.754 +    p8 = _cmsMallocZero(ContextID, sizeof(Prelin8Data));
 193.755 +    if (p8 == NULL) return NULL;
 193.756 +
 193.757 +    // Since this only works for 8 bit input, values comes always as x * 257,
 193.758 +    // we can safely take msb byte (x << 8 + x)
 193.759 +
 193.760 +    for (i=0; i < 256; i++) {
 193.761 +
 193.762 +        if (G != NULL) {
 193.763 +
 193.764 +            // Get 16-bit representation
 193.765 +            Input[0] = cmsEvalToneCurve16(G[0], FROM_8_TO_16(i));
 193.766 +            Input[1] = cmsEvalToneCurve16(G[1], FROM_8_TO_16(i));
 193.767 +            Input[2] = cmsEvalToneCurve16(G[2], FROM_8_TO_16(i));
 193.768 +        }
 193.769 +        else {
 193.770 +            Input[0] = FROM_8_TO_16(i);
 193.771 +            Input[1] = FROM_8_TO_16(i);
 193.772 +            Input[2] = FROM_8_TO_16(i);
 193.773 +        }
 193.774 +
 193.775 +
 193.776 +        // Move to 0..1.0 in fixed domain
 193.777 +        v1 = _cmsToFixedDomain(Input[0] * p -> Domain[0]);
 193.778 +        v2 = _cmsToFixedDomain(Input[1] * p -> Domain[1]);
 193.779 +        v3 = _cmsToFixedDomain(Input[2] * p -> Domain[2]);
 193.780 +
 193.781 +        // Store the precalculated table of nodes
 193.782 +        p8 ->X0[i] = (p->opta[2] * FIXED_TO_INT(v1));
 193.783 +        p8 ->Y0[i] = (p->opta[1] * FIXED_TO_INT(v2));
 193.784 +        p8 ->Z0[i] = (p->opta[0] * FIXED_TO_INT(v3));
 193.785 +
 193.786 +        // Store the precalculated table of offsets
 193.787 +        p8 ->rx[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v1);
 193.788 +        p8 ->ry[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v2);
 193.789 +        p8 ->rz[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v3);
 193.790 +    }
 193.791 +
 193.792 +    p8 ->ContextID = ContextID;
 193.793 +    p8 ->p = p;
 193.794 +
 193.795 +    return p8;
 193.796 +}
 193.797 +
 193.798 +static
 193.799 +void Prelin8free(cmsContext ContextID, void* ptr)
 193.800 +{
 193.801 +    _cmsFree(ContextID, ptr);
 193.802 +}
 193.803 +
 193.804 +static
 193.805 +void* Prelin8dup(cmsContext ContextID, const void* ptr)
 193.806 +{
 193.807 +    return _cmsDupMem(ContextID, ptr, sizeof(Prelin8Data));
 193.808 +}
 193.809 +
 193.810 +
 193.811 +
 193.812 +// A optimized interpolation for 8-bit input.
 193.813 +#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
 193.814 +static
 193.815 +void PrelinEval8(register const cmsUInt16Number Input[],
 193.816 +                  register cmsUInt16Number Output[],
 193.817 +                  register const void* D)
 193.818 +{
 193.819 +
 193.820 +    cmsUInt8Number         r, g, b;
 193.821 +    cmsS15Fixed16Number    rx, ry, rz;
 193.822 +    cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
 193.823 +    int        OutChan;
 193.824 +    register   cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
 193.825 +    Prelin8Data* p8 = (Prelin8Data*) D;
 193.826 +    register const cmsInterpParams* p = p8 ->p;
 193.827 +    int                    TotalOut = p -> nOutputs;
 193.828 +    const cmsUInt16Number* LutTable = p -> Table;
 193.829 +
 193.830 +    r = Input[0] >> 8;
 193.831 +    g = Input[1] >> 8;
 193.832 +    b = Input[2] >> 8;
 193.833 +
 193.834 +    X0 = X1 = p8->X0[r];
 193.835 +    Y0 = Y1 = p8->Y0[g];
 193.836 +    Z0 = Z1 = p8->Z0[b];
 193.837 +
 193.838 +    rx = p8 ->rx[r];
 193.839 +    ry = p8 ->ry[g];
 193.840 +    rz = p8 ->rz[b];
 193.841 +
 193.842 +    X1 = X0 + ((rx == 0) ? 0 : p ->opta[2]);
 193.843 +    Y1 = Y0 + ((ry == 0) ? 0 : p ->opta[1]);
 193.844 +    Z1 = Z0 + ((rz == 0) ? 0 : p ->opta[0]);
 193.845 +
 193.846 +
 193.847 +    // These are the 6 Tetrahedral
 193.848 +    for (OutChan=0; OutChan < TotalOut; OutChan++) {
 193.849 +
 193.850 +        c0 = DENS(X0, Y0, Z0);
 193.851 +
 193.852 +        if (rx >= ry && ry >= rz)
 193.853 +        {
 193.854 +            c1 = DENS(X1, Y0, Z0) - c0;
 193.855 +            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
 193.856 +            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
 193.857 +        }
 193.858 +        else
 193.859 +            if (rx >= rz && rz >= ry)
 193.860 +            {
 193.861 +                c1 = DENS(X1, Y0, Z0) - c0;
 193.862 +                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
 193.863 +                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
 193.864 +            }
 193.865 +            else
 193.866 +                if (rz >= rx && rx >= ry)
 193.867 +                {
 193.868 +                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
 193.869 +                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
 193.870 +                    c3 = DENS(X0, Y0, Z1) - c0;
 193.871 +                }
 193.872 +                else
 193.873 +                    if (ry >= rx && rx >= rz)
 193.874 +                    {
 193.875 +                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
 193.876 +                        c2 = DENS(X0, Y1, Z0) - c0;
 193.877 +                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
 193.878 +                    }
 193.879 +                    else
 193.880 +                        if (ry >= rz && rz >= rx)
 193.881 +                        {
 193.882 +                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
 193.883 +                            c2 = DENS(X0, Y1, Z0) - c0;
 193.884 +                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
 193.885 +                        }
 193.886 +                        else
 193.887 +                            if (rz >= ry && ry >= rx)
 193.888 +                            {
 193.889 +                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
 193.890 +                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
 193.891 +                                c3 = DENS(X0, Y0, Z1) - c0;
 193.892 +                            }
 193.893 +                            else  {
 193.894 +                                c1 = c2 = c3 = 0;
 193.895 +                            }
 193.896 +
 193.897 +
 193.898 +                            Rest = c1 * rx + c2 * ry + c3 * rz;
 193.899 +
 193.900 +                            Output[OutChan] = (cmsUInt16Number)c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
 193.901 +
 193.902 +    }
 193.903 +}
 193.904 +
 193.905 +#undef DENS
 193.906 +
 193.907 +// --------------------------------------------------------------------------------------------------------------
 193.908 +// We need xput over here
 193.909 +
 193.910 +static
 193.911 +cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
 193.912 +{
 193.913 +    cmsPipeline* OriginalLut;
 193.914 +    int nGridPoints;
 193.915 +    cmsToneCurve *Trans[cmsMAXCHANNELS], *TransReverse[cmsMAXCHANNELS];
 193.916 +    cmsUInt32Number t, i;
 193.917 +    cmsFloat32Number v, In[cmsMAXCHANNELS], Out[cmsMAXCHANNELS];
 193.918 +    cmsBool lIsSuitable, lIsLinear;
 193.919 +    cmsPipeline* OptimizedLUT = NULL, *LutPlusCurves = NULL;
 193.920 +    cmsStage* OptimizedCLUTmpe;
 193.921 +    cmsColorSpaceSignature ColorSpace, OutputColorSpace;
 193.922 +    cmsStage* OptimizedPrelinMpe;
 193.923 +    cmsToneCurve**   OptimizedPrelinCurves;
 193.924 +    _cmsStageCLutData*     OptimizedPrelinCLUT;
 193.925 +
 193.926 +
 193.927 +    // This is a loosy optimization! does not apply in floating-point cases
 193.928 +    if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;
 193.929 +
 193.930 +    // Only on RGB
 193.931 +    if (T_COLORSPACE(*InputFormat)  != PT_RGB) return FALSE;
 193.932 +    if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE;
 193.933 +
 193.934 +
 193.935 +    // On 16 bits, user has to specify the feature
 193.936 +    if (!_cmsFormatterIs8bit(*InputFormat)) {
 193.937 +        if (!(*dwFlags & cmsFLAGS_CLUT_PRE_LINEARIZATION)) return FALSE;
 193.938 +    }
 193.939 +
 193.940 +    OriginalLut = *Lut;
 193.941 +    ColorSpace       = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat));
 193.942 +    OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat));
 193.943 +    nGridPoints      = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags);
 193.944 +
 193.945 +    // Empty gamma containers
 193.946 +    memset(Trans, 0, sizeof(Trans));
 193.947 +    memset(TransReverse, 0, sizeof(TransReverse));
 193.948 +
 193.949 +    for (t = 0; t < OriginalLut ->InputChannels; t++) {
 193.950 +        Trans[t] = cmsBuildTabulatedToneCurve16(OriginalLut ->ContextID, PRELINEARIZATION_POINTS, NULL);
 193.951 +        if (Trans[t] == NULL) goto Error;
 193.952 +    }
 193.953 +
 193.954 +    // Populate the curves
 193.955 +    for (i=0; i < PRELINEARIZATION_POINTS; i++) {
 193.956 +
 193.957 +        v = (cmsFloat32Number) ((cmsFloat64Number) i / (PRELINEARIZATION_POINTS - 1));
 193.958 +
 193.959 +        // Feed input with a gray ramp
 193.960 +        for (t=0; t < OriginalLut ->InputChannels; t++)
 193.961 +            In[t] = v;
 193.962 +
 193.963 +        // Evaluate the gray value
 193.964 +        cmsPipelineEvalFloat(In, Out, OriginalLut);
 193.965 +
 193.966 +        // Store result in curve
 193.967 +        for (t=0; t < OriginalLut ->InputChannels; t++)
 193.968 +            Trans[t] ->Table16[i] = _cmsQuickSaturateWord(Out[t] * 65535.0);
 193.969 +    }
 193.970 +
 193.971 +    // Slope-limit the obtained curves
 193.972 +    for (t = 0; t < OriginalLut ->InputChannels; t++)
 193.973 +        SlopeLimiting(Trans[t]);
 193.974 +
 193.975 +    // Check for validity
 193.976 +    lIsSuitable = TRUE;
 193.977 +    lIsLinear   = TRUE;
 193.978 +    for (t=0; (lIsSuitable && (t < OriginalLut ->InputChannels)); t++) {
 193.979 +
 193.980 +        // Exclude if already linear
 193.981 +        if (!cmsIsToneCurveLinear(Trans[t]))
 193.982 +            lIsLinear = FALSE;
 193.983 +
 193.984 +        // Exclude if non-monotonic
 193.985 +        if (!cmsIsToneCurveMonotonic(Trans[t]))
 193.986 +            lIsSuitable = FALSE;
 193.987 +    }
 193.988 +
 193.989 +    // If it is not suitable, just quit
 193.990 +    if (!lIsSuitable) goto Error;
 193.991 +
 193.992 +    // Invert curves if possible
 193.993 +    for (t = 0; t < OriginalLut ->InputChannels; t++) {
 193.994 +        TransReverse[t] = cmsReverseToneCurveEx(PRELINEARIZATION_POINTS, Trans[t]);
 193.995 +        if (TransReverse[t] == NULL) goto Error;
 193.996 +    }
 193.997 +
 193.998 +    // Now inset the reversed curves at the begin of transform
 193.999 +    LutPlusCurves = cmsPipelineDup(OriginalLut);
193.1000 +    if (LutPlusCurves == NULL) goto Error;
193.1001 +
193.1002 +    cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse));
193.1003 +
193.1004 +    // Create the result LUT
193.1005 +    OptimizedLUT = cmsPipelineAlloc(OriginalLut ->ContextID, OriginalLut ->InputChannels, OriginalLut ->OutputChannels);
193.1006 +    if (OptimizedLUT == NULL) goto Error;
193.1007 +
193.1008 +    OptimizedPrelinMpe = cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, Trans);
193.1009 +
193.1010 +    // Create and insert the curves at the beginning
193.1011 +    cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe);
193.1012 +
193.1013 +    // Allocate the CLUT for result
193.1014 +    OptimizedCLUTmpe = cmsStageAllocCLut16bit(OriginalLut ->ContextID, nGridPoints, OriginalLut ->InputChannels, OriginalLut ->OutputChannels, NULL);
193.1015 +
193.1016 +    // Add the CLUT to the destination LUT
193.1017 +    cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe);
193.1018 +
193.1019 +    // Resample the LUT
193.1020 +    if (!cmsStageSampleCLut16bit(OptimizedCLUTmpe, XFormSampler16, (void*) LutPlusCurves, 0)) goto Error;
193.1021 +
193.1022 +    // Free resources
193.1023 +    for (t = 0; t < OriginalLut ->InputChannels; t++) {
193.1024 +
193.1025 +        if (Trans[t]) cmsFreeToneCurve(Trans[t]);
193.1026 +        if (TransReverse[t]) cmsFreeToneCurve(TransReverse[t]);
193.1027 +    }
193.1028 +
193.1029 +    cmsPipelineFree(LutPlusCurves);
193.1030 +
193.1031 +
193.1032 +    OptimizedPrelinCurves = _cmsStageGetPtrToCurveSet(OptimizedPrelinMpe);
193.1033 +    OptimizedPrelinCLUT   = (_cmsStageCLutData*) OptimizedCLUTmpe ->Data;
193.1034 +
193.1035 +    // Set the evaluator if 8-bit
193.1036 +    if (_cmsFormatterIs8bit(*InputFormat)) {
193.1037 +
193.1038 +        Prelin8Data* p8 = PrelinOpt8alloc(OptimizedLUT ->ContextID,
193.1039 +                                                OptimizedPrelinCLUT ->Params,
193.1040 +                                                OptimizedPrelinCurves);
193.1041 +        if (p8 == NULL) return FALSE;
193.1042 +
193.1043 +        _cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval8, (void*) p8, Prelin8free, Prelin8dup);
193.1044 +
193.1045 +    }
193.1046 +    else
193.1047 +    {
193.1048 +        Prelin16Data* p16 = PrelinOpt16alloc(OptimizedLUT ->ContextID,
193.1049 +            OptimizedPrelinCLUT ->Params,
193.1050 +            3, OptimizedPrelinCurves, 3, NULL);
193.1051 +        if (p16 == NULL) return FALSE;
193.1052 +
193.1053 +        _cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);
193.1054 +
193.1055 +    }
193.1056 +
193.1057 +    // Don't fix white on absolute colorimetric
193.1058 +    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
193.1059 +        *dwFlags |= cmsFLAGS_NOWHITEONWHITEFIXUP;
193.1060 +
193.1061 +    if (!(*dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) {
193.1062 +
193.1063 +        if (!FixWhiteMisalignment(OptimizedLUT, ColorSpace, OutputColorSpace)) {
193.1064 +
193.1065 +            return FALSE;
193.1066 +        }
193.1067 +    }
193.1068 +
193.1069 +    // And return the obtained LUT
193.1070 +
193.1071 +    cmsPipelineFree(OriginalLut);
193.1072 +    *Lut = OptimizedLUT;
193.1073 +    return TRUE;
193.1074 +
193.1075 +Error:
193.1076 +
193.1077 +    for (t = 0; t < OriginalLut ->InputChannels; t++) {
193.1078 +
193.1079 +        if (Trans[t]) cmsFreeToneCurve(Trans[t]);
193.1080 +        if (TransReverse[t]) cmsFreeToneCurve(TransReverse[t]);
193.1081 +    }
193.1082 +
193.1083 +    if (LutPlusCurves != NULL) cmsPipelineFree(LutPlusCurves);
193.1084 +    if (OptimizedLUT != NULL) cmsPipelineFree(OptimizedLUT);
193.1085 +
193.1086 +    return FALSE;
193.1087 +
193.1088 +    cmsUNUSED_PARAMETER(Intent);
193.1089 +}
193.1090 +
193.1091 +
193.1092 +// Curves optimizer ------------------------------------------------------------------------------------------------------------------
193.1093 +
193.1094 +static
193.1095 +void CurvesFree(cmsContext ContextID, void* ptr)
193.1096 +{
193.1097 +     Curves16Data* Data = (Curves16Data*) ptr;
193.1098 +     int i;
193.1099 +
193.1100 +     for (i=0; i < Data -> nCurves; i++) {
193.1101 +
193.1102 +         _cmsFree(ContextID, Data ->Curves[i]);
193.1103 +     }
193.1104 +
193.1105 +     _cmsFree(ContextID, Data ->Curves);
193.1106 +     _cmsFree(ContextID, ptr);
193.1107 +}
193.1108 +
193.1109 +static
193.1110 +void* CurvesDup(cmsContext ContextID, const void* ptr)
193.1111 +{
193.1112 +    Curves16Data* Data = _cmsDupMem(ContextID, ptr, sizeof(Curves16Data));
193.1113 +    int i;
193.1114 +
193.1115 +    if (Data == NULL) return NULL;
193.1116 +
193.1117 +    Data ->Curves = _cmsDupMem(ContextID, Data ->Curves, Data ->nCurves * sizeof(cmsUInt16Number*));
193.1118 +
193.1119 +    for (i=0; i < Data -> nCurves; i++) {
193.1120 +        Data ->Curves[i] = _cmsDupMem(ContextID, Data ->Curves[i], Data -> nElements * sizeof(cmsUInt16Number));
193.1121 +    }
193.1122 +
193.1123 +    return (void*) Data;
193.1124 +}
193.1125 +
193.1126 +// Precomputes tables for 8-bit on input devicelink.
193.1127 +static
193.1128 +Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsToneCurve** G)
193.1129 +{
193.1130 +    int i, j;
193.1131 +    Curves16Data* c16;
193.1132 +
193.1133 +    c16 = _cmsMallocZero(ContextID, sizeof(Curves16Data));
193.1134 +    if (c16 == NULL) return NULL;
193.1135 +
193.1136 +    c16 ->nCurves = nCurves;
193.1137 +    c16 ->nElements = nElements;
193.1138 +
193.1139 +    c16 ->Curves = _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*));
193.1140 +    if (c16 ->Curves == NULL) return NULL;
193.1141 +
193.1142 +    for (i=0; i < nCurves; i++) {
193.1143 +
193.1144 +        c16->Curves[i] = _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number));
193.1145 +
193.1146 +        if (nElements == 256) {
193.1147 +
193.1148 +            for (j=0; j < nElements; j++) {
193.1149 +
193.1150 +                c16 ->Curves[i][j] = cmsEvalToneCurve16(G[i], FROM_8_TO_16(j));
193.1151 +            }
193.1152 +        }
193.1153 +        else {
193.1154 +
193.1155 +            for (j=0; j < nElements; j++) {
193.1156 +                c16 ->Curves[i][j] = cmsEvalToneCurve16(G[i], (cmsUInt16Number) j);
193.1157 +            }
193.1158 +        }
193.1159 +    }
193.1160 +
193.1161 +    return c16;
193.1162 +}
193.1163 +
193.1164 +static
193.1165 +void FastEvaluateCurves8(register const cmsUInt16Number In[],
193.1166 +                          register cmsUInt16Number Out[],
193.1167 +                          register const void* D)
193.1168 +{
193.1169 +    Curves16Data* Data = (Curves16Data*) D;
193.1170 +    cmsUInt8Number x;
193.1171 +    int i;
193.1172 +
193.1173 +    for (i=0; i < Data ->nCurves; i++) {
193.1174 +
193.1175 +         x = (In[i] >> 8);
193.1176 +         Out[i] = Data -> Curves[i][x];
193.1177 +    }
193.1178 +}
193.1179 +
193.1180 +
193.1181 +static
193.1182 +void FastEvaluateCurves16(register const cmsUInt16Number In[],
193.1183 +                          register cmsUInt16Number Out[],
193.1184 +                          register const void* D)
193.1185 +{
193.1186 +    Curves16Data* Data = (Curves16Data*) D;
193.1187 +    int i;
193.1188 +
193.1189 +    for (i=0; i < Data ->nCurves; i++) {
193.1190 +         Out[i] = Data -> Curves[i][In[i]];
193.1191 +    }
193.1192 +}
193.1193 +
193.1194 +
193.1195 +static
193.1196 +void FastIdentity16(register const cmsUInt16Number In[],
193.1197 +                    register cmsUInt16Number Out[],
193.1198 +                    register const void* D)
193.1199 +{
193.1200 +    cmsPipeline* Lut = (cmsPipeline*) D;
193.1201 +    cmsUInt32Number i;
193.1202 +
193.1203 +    for (i=0; i < Lut ->InputChannels; i++) {
193.1204 +         Out[i] = In[i];
193.1205 +    }
193.1206 +}
193.1207 +
193.1208 +
193.1209 +// If the target LUT holds only curves, the optimization procedure is to join all those
193.1210 +// curves together. That only works on curves and does not work on matrices.
193.1211 +static
193.1212 +cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
193.1213 +{
193.1214 +    cmsToneCurve** GammaTables = NULL;
193.1215 +    cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS];
193.1216 +    cmsUInt32Number i, j;
193.1217 +    cmsPipeline* Src = *Lut;
193.1218 +    cmsPipeline* Dest = NULL;
193.1219 +    cmsStage* mpe;
193.1220 +    cmsStage* ObtainedCurves = NULL;
193.1221 +
193.1222 +
193.1223 +    // This is a loosy optimization! does not apply in floating-point cases
193.1224 +    if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;
193.1225 +
193.1226 +    //  Only curves in this LUT?
193.1227 +    for (mpe = cmsPipelineGetPtrToFirstStage(Src);
193.1228 +         mpe != NULL;
193.1229 +         mpe = cmsStageNext(mpe)) {
193.1230 +            if (cmsStageType(mpe) != cmsSigCurveSetElemType) return FALSE;
193.1231 +    }
193.1232 +
193.1233 +    // Allocate an empty LUT
193.1234 +    Dest =  cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
193.1235 +    if (Dest == NULL) return FALSE;
193.1236 +
193.1237 +    // Create target curves
193.1238 +    GammaTables = (cmsToneCurve**) _cmsCalloc(Src ->ContextID, Src ->InputChannels, sizeof(cmsToneCurve*));
193.1239 +    if (GammaTables == NULL) goto Error;
193.1240 +
193.1241 +    for (i=0; i < Src ->InputChannels; i++) {
193.1242 +        GammaTables[i] = cmsBuildTabulatedToneCurve16(Src ->ContextID, PRELINEARIZATION_POINTS, NULL);
193.1243 +        if (GammaTables[i] == NULL) goto Error;
193.1244 +    }
193.1245 +
193.1246 +    // Compute 16 bit result by using floating point
193.1247 +    for (i=0; i < PRELINEARIZATION_POINTS; i++) {
193.1248 +
193.1249 +        for (j=0; j < Src ->InputChannels; j++)
193.1250 +            InFloat[j] = (cmsFloat32Number) ((cmsFloat64Number) i / (PRELINEARIZATION_POINTS - 1));
193.1251 +
193.1252 +        cmsPipelineEvalFloat(InFloat, OutFloat, Src);
193.1253 +
193.1254 +        for (j=0; j < Src ->InputChannels; j++)
193.1255 +            GammaTables[j] -> Table16[i] = _cmsQuickSaturateWord(OutFloat[j] * 65535.0);
193.1256 +    }
193.1257 +
193.1258 +    ObtainedCurves = cmsStageAllocToneCurves(Src ->ContextID, Src ->InputChannels, GammaTables);
193.1259 +    if (ObtainedCurves == NULL) goto Error;
193.1260 +
193.1261 +    for (i=0; i < Src ->InputChannels; i++) {
193.1262 +        cmsFreeToneCurve(GammaTables[i]);
193.1263 +        GammaTables[i] = NULL;
193.1264 +    }
193.1265 +
193.1266 +    if (GammaTables != NULL) _cmsFree(Src ->ContextID, GammaTables);
193.1267 +
193.1268 +    // Maybe the curves are linear at the end
193.1269 +    if (!AllCurvesAreLinear(ObtainedCurves)) {
193.1270 +
193.1271 +        cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves);
193.1272 +
193.1273 +        // If the curves are to be applied in 8 bits, we can save memory
193.1274 +        if (_cmsFormatterIs8bit(*InputFormat)) {
193.1275 +
193.1276 +            _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) ObtainedCurves ->Data;
193.1277 +             Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 256, Data ->TheCurves);
193.1278 +
193.1279 +             *dwFlags |= cmsFLAGS_NOCACHE;
193.1280 +            _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves8, c16, CurvesFree, CurvesDup);
193.1281 +
193.1282 +        }
193.1283 +        else {
193.1284 +
193.1285 +            _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) cmsStageData(ObtainedCurves);
193.1286 +             Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 65536, Data ->TheCurves);
193.1287 +
193.1288 +             *dwFlags |= cmsFLAGS_NOCACHE;
193.1289 +            _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves16, c16, CurvesFree, CurvesDup);
193.1290 +        }
193.1291 +    }
193.1292 +    else {
193.1293 +
193.1294 +        // LUT optimizes to nothing. Set the identity LUT
193.1295 +        cmsStageFree(ObtainedCurves);
193.1296 +
193.1297 +        cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels));
193.1298 +
193.1299 +        *dwFlags |= cmsFLAGS_NOCACHE;
193.1300 +        _cmsPipelineSetOptimizationParameters(Dest, FastIdentity16, (void*) Dest, NULL, NULL);
193.1301 +    }
193.1302 +
193.1303 +    // We are done.
193.1304 +    cmsPipelineFree(Src);
193.1305 +    *Lut = Dest;
193.1306 +    return TRUE;
193.1307 +
193.1308 +Error:
193.1309 +
193.1310 +    if (ObtainedCurves != NULL) cmsStageFree(ObtainedCurves);
193.1311 +    if (GammaTables != NULL) {
193.1312 +        for (i=0; i < Src ->InputChannels; i++) {
193.1313 +            if (GammaTables[i] != NULL) cmsFreeToneCurve(GammaTables[i]);
193.1314 +        }
193.1315 +
193.1316 +        _cmsFree(Src ->ContextID, GammaTables);
193.1317 +    }
193.1318 +
193.1319 +    if (Dest != NULL) cmsPipelineFree(Dest);
193.1320 +    return FALSE;
193.1321 +
193.1322 +    cmsUNUSED_PARAMETER(Intent);
193.1323 +    cmsUNUSED_PARAMETER(InputFormat);
193.1324 +    cmsUNUSED_PARAMETER(OutputFormat);
193.1325 +    cmsUNUSED_PARAMETER(dwFlags);
193.1326 +}
193.1327 +
193.1328 +// -------------------------------------------------------------------------------------------------------------------------------------
193.1329 +// LUT is Shaper - Matrix - Matrix - Shaper, which is very frequent when combining two matrix-shaper profiles
193.1330 +
193.1331 +
193.1332 +static
193.1333 +void  FreeMatShaper(cmsContext ContextID, void* Data)
193.1334 +{
193.1335 +    if (Data != NULL) _cmsFree(ContextID, Data);
193.1336 +}
193.1337 +
193.1338 +static
193.1339 +void* DupMatShaper(cmsContext ContextID, const void* Data)
193.1340 +{
193.1341 +    return _cmsDupMem(ContextID, Data, sizeof(MatShaper8Data));
193.1342 +}
193.1343 +
193.1344 +
193.1345 +// A fast matrix-shaper evaluator for 8 bits. This is a bit ticky since I'm using 1.14 signed fixed point
193.1346 +// to accomplish some performance. Actually it takes 256x3 16 bits tables and 16385 x 3 tables of 8 bits,
193.1347 +// in total about 50K, and the performance boost is huge!
193.1348 +static
193.1349 +void MatShaperEval16(register const cmsUInt16Number In[],
193.1350 +                     register cmsUInt16Number Out[],
193.1351 +                     register const void* D)
193.1352 +{
193.1353 +    MatShaper8Data* p = (MatShaper8Data*) D;
193.1354 +    cmsS1Fixed14Number l1, l2, l3, r, g, b;
193.1355 +    cmsUInt32Number ri, gi, bi;
193.1356 +
193.1357 +    // In this case (and only in this case!) we can use this simplification since
193.1358 +    // In[] is assured to come from a 8 bit number. (a << 8 | a)
193.1359 +    ri = In[0] & 0xFF;
193.1360 +    gi = In[1] & 0xFF;
193.1361 +    bi = In[2] & 0xFF;
193.1362 +
193.1363 +    // Across first shaper, which also converts to 1.14 fixed point
193.1364 +    r = p->Shaper1R[ri];
193.1365 +    g = p->Shaper1G[gi];
193.1366 +    b = p->Shaper1B[bi];
193.1367 +
193.1368 +    // Evaluate the matrix in 1.14 fixed point
193.1369 +    l1 =  (p->Mat[0][0] * r + p->Mat[0][1] * g + p->Mat[0][2] * b + p->Off[0] + 0x2000) >> 14;
193.1370 +    l2 =  (p->Mat[1][0] * r + p->Mat[1][1] * g + p->Mat[1][2] * b + p->Off[1] + 0x2000) >> 14;
193.1371 +    l3 =  (p->Mat[2][0] * r + p->Mat[2][1] * g + p->Mat[2][2] * b + p->Off[2] + 0x2000) >> 14;
193.1372 +
193.1373 +    // Now we have to clip to 0..1.0 range
193.1374 +    ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384 : l1);
193.1375 +    gi = (l2 < 0) ? 0 : ((l2 > 16384) ? 16384 : l2);
193.1376 +    bi = (l3 < 0) ? 0 : ((l3 > 16384) ? 16384 : l3);
193.1377 +
193.1378 +    // And across second shaper,
193.1379 +    Out[0] = p->Shaper2R[ri];
193.1380 +    Out[1] = p->Shaper2G[gi];
193.1381 +    Out[2] = p->Shaper2B[bi];
193.1382 +
193.1383 +}
193.1384 +
193.1385 +// This table converts from 8 bits to 1.14 after applying the curve
193.1386 +static
193.1387 +void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve)
193.1388 +{
193.1389 +    int i;
193.1390 +    cmsFloat32Number R, y;
193.1391 +
193.1392 +    for (i=0; i < 256; i++) {
193.1393 +
193.1394 +        R   = (cmsFloat32Number) (i / 255.0);
193.1395 +        y   = cmsEvalToneCurveFloat(Curve, R);
193.1396 +
193.1397 +        Table[i] = DOUBLE_TO_1FIXED14(y);
193.1398 +    }
193.1399 +}
193.1400 +
193.1401 +// This table converts form 1.14 (being 0x4000 the last entry) to 8 bits after applying the curve
193.1402 +static
193.1403 +void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput)
193.1404 +{
193.1405 +    int i;
193.1406 +    cmsFloat32Number R, Val;
193.1407 +
193.1408 +    for (i=0; i < 16385; i++) {
193.1409 +
193.1410 +        R   = (cmsFloat32Number) (i / 16384.0);
193.1411 +        Val = cmsEvalToneCurveFloat(Curve, R);    // Val comes 0..1.0
193.1412 +
193.1413 +        if (Is8BitsOutput) {
193.1414 +
193.1415 +            // If 8 bits output, we can optimize further by computing the / 257 part.
193.1416 +            // first we compute the resulting byte and then we store the byte times
193.1417 +            // 257. This quantization allows to round very quick by doing a >> 8, but
193.1418 +            // since the low byte is always equal to msb, we can do a & 0xff and this works!
193.1419 +            cmsUInt16Number w = _cmsQuickSaturateWord(Val * 65535.0 + 0.5);
193.1420 +            cmsUInt8Number  b = FROM_16_TO_8(w);
193.1421 +
193.1422 +            Table[i] = FROM_8_TO_16(b);
193.1423 +        }
193.1424 +        else Table[i]  = _cmsQuickSaturateWord(Val * 65535.0 + 0.5);
193.1425 +    }
193.1426 +}
193.1427 +
193.1428 +// Compute the matrix-shaper structure
193.1429 +static
193.1430 +cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, cmsVEC3* Off, cmsToneCurve* Curve2[3], cmsUInt32Number* OutputFormat)
193.1431 +{
193.1432 +    MatShaper8Data* p;
193.1433 +    int i, j;
193.1434 +    cmsBool Is8Bits = _cmsFormatterIs8bit(*OutputFormat);
193.1435 +
193.1436 +    // Allocate a big chuck of memory to store precomputed tables
193.1437 +    p = (MatShaper8Data*) _cmsMalloc(Dest ->ContextID, sizeof(MatShaper8Data));
193.1438 +    if (p == NULL) return FALSE;
193.1439 +
193.1440 +    p -> ContextID = Dest -> ContextID;
193.1441 +
193.1442 +    // Precompute tables
193.1443 +    FillFirstShaper(p ->Shaper1R, Curve1[0]);
193.1444 +    FillFirstShaper(p ->Shaper1G, Curve1[1]);
193.1445 +    FillFirstShaper(p ->Shaper1B, Curve1[2]);
193.1446 +
193.1447 +    FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits);
193.1448 +    FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits);
193.1449 +    FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits);
193.1450 +
193.1451 +    // Convert matrix to nFixed14. Note that those values may take more than 16 bits as
193.1452 +    for (i=0; i < 3; i++) {
193.1453 +        for (j=0; j < 3; j++) {
193.1454 +            p ->Mat[i][j] = DOUBLE_TO_1FIXED14(Mat->v[i].n[j]);
193.1455 +        }
193.1456 +    }
193.1457 +
193.1458 +    for (i=0; i < 3; i++) {
193.1459 +
193.1460 +        if (Off == NULL) {
193.1461 +            p ->Off[i] = 0;
193.1462 +        }
193.1463 +        else {
193.1464 +            p ->Off[i] = DOUBLE_TO_1FIXED14(Off->n[i]);
193.1465 +        }
193.1466 +    }
193.1467 +
193.1468 +    // Mark as optimized for faster formatter
193.1469 +    if (Is8Bits)
193.1470 +        *OutputFormat |= OPTIMIZED_SH(1);
193.1471 +
193.1472 +    // Fill function pointers
193.1473 +    _cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper);
193.1474 +    return TRUE;
193.1475 +}
193.1476 +
193.1477 +//  8 bits on input allows matrix-shaper boot up to 25 Mpixels per second on RGB. That's fast!
193.1478 +// TODO: Allow a third matrix for abs. colorimetric
193.1479 +static
193.1480 +cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
193.1481 +{
193.1482 +    cmsStage* Curve1, *Curve2;
193.1483 +    cmsStage* Matrix1, *Matrix2;
193.1484 +    _cmsStageMatrixData* Data1;
193.1485 +    _cmsStageMatrixData* Data2;
193.1486 +    cmsMAT3 res;
193.1487 +    cmsBool IdentityMat;
193.1488 +    cmsPipeline* Dest, *Src;
193.1489 +
193.1490 +    // Only works on RGB to RGB
193.1491 +    if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE;
193.1492 +
193.1493 +    // Only works on 8 bit input
193.1494 +    if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE;
193.1495 +
193.1496 +    // Seems suitable, proceed
193.1497 +    Src = *Lut;
193.1498 +
193.1499 +    // Check for shaper-matrix-matrix-shaper structure, that is what this optimizer stands for
193.1500 +    if (!cmsPipelineCheckAndRetreiveStages(Src, 4,
193.1501 +        cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
193.1502 +        &Curve1, &Matrix1, &Matrix2, &Curve2)) return FALSE;
193.1503 +
193.1504 +    // Get both matrices
193.1505 +    Data1 = (_cmsStageMatrixData*) cmsStageData(Matrix1);
193.1506 +    Data2 = (_cmsStageMatrixData*) cmsStageData(Matrix2);
193.1507 +
193.1508 +    // Input offset should be zero
193.1509 +    if (Data1 ->Offset != NULL) return FALSE;
193.1510 +
193.1511 +    // Multiply both matrices to get the result
193.1512 +    _cmsMAT3per(&res, (cmsMAT3*) Data2 ->Double, (cmsMAT3*) Data1 ->Double);
193.1513 +
193.1514 +    // Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
193.1515 +    IdentityMat = FALSE;
193.1516 +    if (_cmsMAT3isIdentity(&res) && Data2 ->Offset == NULL) {
193.1517 +
193.1518 +        // We can get rid of full matrix
193.1519 +        IdentityMat = TRUE;
193.1520 +    }
193.1521 +
193.1522 +      // Allocate an empty LUT
193.1523 +    Dest =  cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
193.1524 +    if (!Dest) return FALSE;
193.1525 +
193.1526 +    // Assamble the new LUT
193.1527 +    cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1));
193.1528 +    if (!IdentityMat)
193.1529 +        cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest ->ContextID, 3, 3, (const cmsFloat64Number*) &res, Data2 ->Offset));
193.1530 +    cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2));
193.1531 +
193.1532 +    // If identity on matrix, we can further optimize the curves, so call the join curves routine
193.1533 +    if (IdentityMat) {
193.1534 +
193.1535 +        OptimizeByJoiningCurves(&Dest, Intent, InputFormat, OutputFormat, dwFlags);
193.1536 +    }
193.1537 +    else {
193.1538 +        _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1);
193.1539 +        _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2);
193.1540 +
193.1541 +        // In this particular optimization, caché does not help as it takes more time to deal with
193.1542 +        // the caché that with the pixel handling
193.1543 +        *dwFlags |= cmsFLAGS_NOCACHE;
193.1544 +
193.1545 +        // Setup the optimizarion routines
193.1546 +        SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Data2 ->Offset, mpeC2->TheCurves, OutputFormat);
193.1547 +    }
193.1548 +
193.1549 +    cmsPipelineFree(Src);
193.1550 +    *Lut = Dest;
193.1551 +    return TRUE;
193.1552 +}
193.1553 +
193.1554 +
193.1555 +// -------------------------------------------------------------------------------------------------------------------------------------
193.1556 +// Optimization plug-ins
193.1557 +
193.1558 +// List of optimizations
193.1559 +typedef struct _cmsOptimizationCollection_st {
193.1560 +
193.1561 +    _cmsOPToptimizeFn  OptimizePtr;
193.1562 +
193.1563 +    struct _cmsOptimizationCollection_st *Next;
193.1564 +
193.1565 +} _cmsOptimizationCollection;
193.1566 +
193.1567 +
193.1568 +// The built-in list. We currently implement 4 types of optimizations. Joining of curves, matrix-shaper, linearization and resampling
193.1569 +static _cmsOptimizationCollection DefaultOptimization[] = {
193.1570 +
193.1571 +    { OptimizeByJoiningCurves,            &DefaultOptimization[1] },
193.1572 +    { OptimizeMatrixShaper,               &DefaultOptimization[2] },
193.1573 +    { OptimizeByComputingLinearization,   &DefaultOptimization[3] },
193.1574 +    { OptimizeByResampling,               NULL }
193.1575 +};
193.1576 +
193.1577 +// The linked list head
193.1578 +static _cmsOptimizationCollection* OptimizationCollection = DefaultOptimization;
193.1579 +
193.1580 +// Register new ways to optimize
193.1581 +cmsBool  _cmsRegisterOptimizationPlugin(cmsPluginBase* Data)
193.1582 +{
193.1583 +    cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data;
193.1584 +    _cmsOptimizationCollection* fl;
193.1585 +
193.1586 +    if (Data == NULL) {
193.1587 +
193.1588 +        OptimizationCollection = DefaultOptimization;
193.1589 +        return TRUE;
193.1590 +    }
193.1591 +
193.1592 +    // Optimizer callback is required
193.1593 +    if (Plugin ->OptimizePtr == NULL) return FALSE;
193.1594 +
193.1595 +    fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(sizeof(_cmsOptimizationCollection));
193.1596 +    if (fl == NULL) return FALSE;
193.1597 +
193.1598 +    // Copy the parameters
193.1599 +    fl ->OptimizePtr = Plugin ->OptimizePtr;
193.1600 +
193.1601 +    // Keep linked list
193.1602 +    fl ->Next = OptimizationCollection;
193.1603 +    OptimizationCollection = fl;
193.1604 +
193.1605 +    // All is ok
193.1606 +    return TRUE;
193.1607 +}
193.1608 +
193.1609 +// The entry point for LUT optimization
193.1610 +cmsBool _cmsOptimizePipeline(cmsPipeline**    PtrLut,
193.1611 +                             int              Intent,
193.1612 +                             cmsUInt32Number* InputFormat,
193.1613 +                             cmsUInt32Number* OutputFormat,
193.1614 +                             cmsUInt32Number* dwFlags)
193.1615 +{
193.1616 +    _cmsOptimizationCollection* Opts;
193.1617 +    cmsBool AnySuccess = FALSE;
193.1618 +
193.1619 +    // A CLUT is being asked, so force this specific optimization
193.1620 +    if (*dwFlags & cmsFLAGS_FORCE_CLUT) {
193.1621 +
193.1622 +        PreOptimize(*PtrLut);
193.1623 +        return OptimizeByResampling(PtrLut, Intent, InputFormat, OutputFormat, dwFlags);
193.1624 +    }
193.1625 +
193.1626 +    // Anything to optimize?
193.1627 +    if ((*PtrLut) ->Elements == NULL) {
193.1628 +        _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL);
193.1629 +        return TRUE;
193.1630 +    }
193.1631 +
193.1632 +    // Try to get rid of identities and trivial conversions.
193.1633 +    AnySuccess = PreOptimize(*PtrLut);
193.1634 +
193.1635 +    // After removal do we end with an identity?
193.1636 +    if ((*PtrLut) ->Elements == NULL) {
193.1637 +        _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL);
193.1638 +        return TRUE;
193.1639 +    }
193.1640 +
193.1641 +    // Do not optimize, keep all precision
193.1642 +    if (*dwFlags & cmsFLAGS_NOOPTIMIZE)
193.1643 +        return FALSE;
193.1644 +
193.1645 +    // Try built-in optimizations and plug-in
193.1646 +    for (Opts = OptimizationCollection;
193.1647 +         Opts != NULL;
193.1648 +         Opts = Opts ->Next) {
193.1649 +
193.1650 +            // If one schema succeeded, we are done
193.1651 +            if (Opts ->OptimizePtr(PtrLut, Intent, InputFormat, OutputFormat, dwFlags)) {
193.1652 +
193.1653 +                return TRUE;    // Optimized!
193.1654 +            }
193.1655 +    }
193.1656 +
193.1657 +    // Only simple optimizations succeeded
193.1658 +    return AnySuccess;
193.1659 +}
193.1660 +
   194.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmspack.c	Thu Sep 23 17:33:40 2010 -0700
   194.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmspack.c	Fri Sep 24 16:41:32 2010 -0700
   194.3 @@ -27,8 +27,10 @@
   194.4  // However, the following notice accompanied the original version of this
   194.5  // file:
   194.6  //
   194.7 -//  Little cms
   194.8 -//  Copyright (C) 1998-2007 Marti Maria
   194.9 +//---------------------------------------------------------------------------------
  194.10 +//
  194.11 +//  Little Color Management System
  194.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  194.13  //
  194.14  // Permission is hereby granted, free of charge, to any person obtaining
  194.15  // a copy of this software and associated documentation files (the "Software"),
  194.16 @@ -47,2129 +49,2551 @@
  194.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  194.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  194.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  194.20 -
  194.21 -
  194.22 -#include "lcms.h"
  194.23 -
  194.24 -// This module handles all formats supported by lcms
  194.25 -
  194.26 +//
  194.27 +//---------------------------------------------------------------------------------
  194.28 +//
  194.29 +
  194.30 +#include "lcms2_internal.h"
  194.31 +
  194.32 +// This module handles all formats supported by lcms. There are two flavors, 16 bits and
  194.33 +// floating point. Floating point is supported only in a subset, those formats holding
  194.34 +// cmsFloat32Number (4 bytes per component) and double (marked as 0 bytes per component as special
  194.35 +// case)
  194.36  
  194.37  // ---------------------------------------------------------------------------
  194.38  
  194.39  
  194.40  // This macro return words stored as big endian
  194.41 -
  194.42 -#define CHANGE_ENDIAN(w)    (WORD) ((WORD) ((w)<<8)|((w)>>8))
  194.43 +#define CHANGE_ENDIAN(w)    (cmsUInt16Number) ((cmsUInt16Number) ((w)<<8)|((w)>>8))
  194.44  
  194.45  // These macros handles reversing (negative)
  194.46 -
  194.47 -#define REVERSE_FLAVOR_8(x)     ((BYTE) (0xff-(x)))
  194.48 -#define REVERSE_FLAVOR_16(x)    ((WORD)(0xffff-(x)))
  194.49 +#define REVERSE_FLAVOR_8(x)     ((cmsUInt8Number) (0xff-(x)))
  194.50 +#define REVERSE_FLAVOR_16(x)    ((cmsUInt16Number)(0xffff-(x)))
  194.51 +
  194.52 +// * 0xffff / 0xff00 = (255 * 257) / (255 * 256) = 257 / 256
  194.53 +cmsINLINE cmsUInt16Number FomLabV2ToLabV4(cmsUInt16Number x)
  194.54 +{
  194.55 +    int a;
  194.56 +
  194.57 +    a = (x << 8 | x) >> 8;  // * 257 / 256
  194.58 +    if ( a > 0xffff) return 0xffff;
  194.59 +    return (cmsUInt16Number) a;
  194.60 +}
  194.61 +
  194.62 +// * 0xf00 / 0xffff = * 256 / 257
  194.63 +cmsINLINE cmsUInt16Number FomLabV4ToLabV2(cmsUInt16Number x)
  194.64 +{
  194.65 +    return (cmsUInt16Number) (((x << 8) + 0x80) / 257);
  194.66 +}
  194.67 +
  194.68 +
  194.69 +typedef struct {
  194.70 +    cmsUInt32Number Type;
  194.71 +    cmsUInt32Number Mask;
  194.72 +    cmsFormatter16 Frm;
  194.73 +
  194.74 +} cmsFormatters16;
  194.75 +
  194.76 +typedef struct {
  194.77 +    cmsUInt32Number    Type;
  194.78 +    cmsUInt32Number    Mask;
  194.79 +    cmsFormatterFloat Frm;
  194.80 +
  194.81 +} cmsFormattersFloat;
  194.82 +
  194.83 +#define ANYSPACE        COLORSPACE_SH(31)
  194.84 +#define ANYCHANNELS     CHANNELS_SH(15)
  194.85 +#define ANYEXTRA        EXTRA_SH(7)
  194.86 +#define ANYPLANAR       PLANAR_SH(1)
  194.87 +#define ANYENDIAN       ENDIAN16_SH(1)
  194.88 +#define ANYSWAP         DOSWAP_SH(1)
  194.89 +#define ANYSWAPFIRST    SWAPFIRST_SH(1)
  194.90 +#define ANYFLAVOR       FLAVOR_SH(1)
  194.91 +
  194.92  
  194.93  // Supress waning about info never being used
  194.94  
  194.95 -#ifdef __BORLANDC__
  194.96 -#pragma warn -par
  194.97 -#endif
  194.98 -
  194.99  #ifdef _MSC_VER
 194.100  #pragma warning(disable : 4100)
 194.101  #endif
 194.102  
 194.103 -// -------------------------------------------------------- Unpacking routines.
 194.104 -
 194.105 -
 194.106 +// Unpacking routines (16 bits) ----------------------------------------------------------------------------------------
 194.107 +
 194.108 +// Does almost everything but is slow
 194.109  static
 194.110 -LPBYTE UnrollAnyBytes(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.111 +cmsUInt8Number* UnrollChunkyBytes(register _cmsTRANSFORM* info,
 194.112 +                                  register cmsUInt16Number wIn[],
 194.113 +                                  register cmsUInt8Number* accum,
 194.114 +                                  register cmsUInt32Number Stride)
 194.115  {
 194.116 -       int nChan = T_CHANNELS(info -> InputFormat);
 194.117 -       register int i;
 194.118 -
 194.119 -       for (i=0; i < nChan; i++) {
 194.120 -
 194.121 -              wIn[i] = RGB_8_TO_16(*accum); accum++;
 194.122 -       }
 194.123 -
 194.124 -       return accum + T_EXTRA(info -> InputFormat);
 194.125 +    int nChan      = T_CHANNELS(info -> InputFormat);
 194.126 +    int DoSwap     = T_DOSWAP(info ->InputFormat);
 194.127 +    int Reverse    = T_FLAVOR(info ->InputFormat);
 194.128 +    int SwapFirst  = T_SWAPFIRST(info -> InputFormat);
 194.129 +    int Extra      = T_EXTRA(info -> InputFormat);
 194.130 +    int ExtraFirst = DoSwap && !SwapFirst;
 194.131 +    cmsUInt16Number v;
 194.132 +    int i;
 194.133 +
 194.134 +    if (ExtraFirst) {
 194.135 +        accum += Extra;
 194.136 +    }
 194.137 +
 194.138 +    for (i=0; i < nChan; i++) {
 194.139 +        int index = DoSwap ? (nChan - i - 1) : i;
 194.140 +
 194.141 +        v = FROM_8_TO_16(*accum);
 194.142 +        v = Reverse ? REVERSE_FLAVOR_16(v) : v;
 194.143 +        wIn[index] = v;
 194.144 +        accum++;
 194.145 +    }
 194.146 +
 194.147 +    if (!ExtraFirst) {
 194.148 +        accum += Extra;
 194.149 +    }
 194.150 +
 194.151 +    if (Extra == 0 && SwapFirst) {
 194.152 +        cmsUInt16Number tmp = wIn[0];
 194.153 +
 194.154 +        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
 194.155 +        wIn[nChan-1] = tmp;
 194.156 +    }
 194.157 +
 194.158 +    return accum;
 194.159  }
 194.160  
 194.161 -
 194.162 -
 194.163 +// Extra channels are just ignored because come in the next planes
 194.164  static
 194.165 -LPBYTE Unroll4Bytes(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.166 +cmsUInt8Number* UnrollPlanarBytes(register _cmsTRANSFORM* info,
 194.167 +                                  register cmsUInt16Number wIn[],
 194.168 +                                  register cmsUInt8Number* accum,
 194.169 +                                  register cmsUInt32Number Stride)
 194.170  {
 194.171 -       wIn[0] = RGB_8_TO_16(*accum); accum++; // C
 194.172 -       wIn[1] = RGB_8_TO_16(*accum); accum++; // M
 194.173 -       wIn[2] = RGB_8_TO_16(*accum); accum++; // Y
 194.174 -       wIn[3] = RGB_8_TO_16(*accum); accum++; // K
 194.175 -
 194.176 -       return accum;
 194.177 +    int nChan = T_CHANNELS(info -> InputFormat);
 194.178 +    int DoSwap= T_DOSWAP(info ->InputFormat);
 194.179 +    int Reverse= T_FLAVOR(info ->InputFormat);
 194.180 +    int i;
 194.181 +    cmsUInt8Number* Init = accum;
 194.182 +
 194.183 +    if (DoSwap) {
 194.184 +        accum += T_EXTRA(info -> InputFormat) * Stride;
 194.185 +    }
 194.186 +
 194.187 +    for (i=0; i < nChan; i++) {
 194.188 +
 194.189 +        int index = DoSwap ? (nChan - i - 1) : i;
 194.190 +        cmsUInt16Number v = FROM_8_TO_16(*accum);
 194.191 +
 194.192 +        wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
 194.193 +        accum += Stride;
 194.194 +    }
 194.195 +
 194.196 +    return (Init + 1);
 194.197  }
 194.198  
 194.199 +// Special cases, provided for performance
 194.200  static
 194.201 -LPBYTE Unroll4BytesReverse(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.202 +cmsUInt8Number* Unroll4Bytes(register _cmsTRANSFORM* info,
 194.203 +                             register cmsUInt16Number wIn[],
 194.204 +                             register cmsUInt8Number* accum,
 194.205 +                             register cmsUInt32Number Stride)
 194.206  {
 194.207 -       wIn[0] = RGB_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C
 194.208 -       wIn[1] = RGB_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M
 194.209 -       wIn[2] = RGB_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y
 194.210 -       wIn[3] = RGB_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K
 194.211 -
 194.212 -       return accum;
 194.213 +    wIn[0] = FROM_8_TO_16(*accum); accum++; // C
 194.214 +    wIn[1] = FROM_8_TO_16(*accum); accum++; // M
 194.215 +    wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
 194.216 +    wIn[3] = FROM_8_TO_16(*accum); accum++; // K
 194.217 +
 194.218 +    return accum;
 194.219  }
 194.220  
 194.221 -
 194.222  static
 194.223 -LPBYTE Unroll4BytesSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.224 +cmsUInt8Number* Unroll4BytesReverse(register _cmsTRANSFORM* info,
 194.225 +                                    register cmsUInt16Number wIn[],
 194.226 +                                    register cmsUInt8Number* accum,
 194.227 +                                    register cmsUInt32Number Stride)
 194.228  {
 194.229 -
 194.230 -       wIn[3] = RGB_8_TO_16(*accum); accum++; // K
 194.231 -       wIn[0] = RGB_8_TO_16(*accum); accum++; // C
 194.232 -       wIn[1] = RGB_8_TO_16(*accum); accum++; // M
 194.233 -       wIn[2] = RGB_8_TO_16(*accum); accum++; // Y
 194.234 -
 194.235 -
 194.236 -       return accum;
 194.237 +    wIn[0] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // C
 194.238 +    wIn[1] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // M
 194.239 +    wIn[2] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // Y
 194.240 +    wIn[3] = FROM_8_TO_16(REVERSE_FLAVOR_8(*accum)); accum++; // K
 194.241 +
 194.242 +    return accum;
 194.243  }
 194.244  
 194.245 -
 194.246 +static
 194.247 +cmsUInt8Number* Unroll4BytesSwapFirst(register _cmsTRANSFORM* info,
 194.248 +                                      register cmsUInt16Number wIn[],
 194.249 +                                      register cmsUInt8Number* accum,
 194.250 +                                      register cmsUInt32Number Stride)
 194.251 +{
 194.252 +    wIn[3] = FROM_8_TO_16(*accum); accum++; // K
 194.253 +    wIn[0] = FROM_8_TO_16(*accum); accum++; // C
 194.254 +    wIn[1] = FROM_8_TO_16(*accum); accum++; // M
 194.255 +    wIn[2] = FROM_8_TO_16(*accum); accum++; // Y
 194.256 +
 194.257 +    return accum;
 194.258 +}
 194.259  
 194.260  // KYMC
 194.261  static
 194.262 -LPBYTE Unroll4BytesSwap(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.263 +cmsUInt8Number* Unroll4BytesSwap(register _cmsTRANSFORM* info,
 194.264 +                                 register cmsUInt16Number wIn[],
 194.265 +                                 register cmsUInt8Number* accum,
 194.266 +                                 register cmsUInt32Number Stride)
 194.267  {
 194.268 -       wIn[3] = RGB_8_TO_16(*accum); accum++;  // K
 194.269 -       wIn[2] = RGB_8_TO_16(*accum); accum++;  // Y
 194.270 -       wIn[1] = RGB_8_TO_16(*accum); accum++;  // M
 194.271 -       wIn[0] = RGB_8_TO_16(*accum); accum++;  // C
 194.272 -
 194.273 -       return accum;
 194.274 +    wIn[3] = FROM_8_TO_16(*accum); accum++;  // K
 194.275 +    wIn[2] = FROM_8_TO_16(*accum); accum++;  // Y
 194.276 +    wIn[1] = FROM_8_TO_16(*accum); accum++;  // M
 194.277 +    wIn[0] = FROM_8_TO_16(*accum); accum++;  // C
 194.278 +
 194.279 +    return accum;
 194.280  }
 194.281  
 194.282 -
 194.283  static
 194.284 -LPBYTE Unroll4BytesSwapSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.285 +cmsUInt8Number* Unroll4BytesSwapSwapFirst(register _cmsTRANSFORM* info,
 194.286 +                                          register cmsUInt16Number wIn[],
 194.287 +                                          register cmsUInt8Number* accum,
 194.288 +                                          register cmsUInt32Number Stride)
 194.289  {
 194.290 -       wIn[2] = RGB_8_TO_16(*accum); accum++;  // K
 194.291 -       wIn[1] = RGB_8_TO_16(*accum); accum++;  // Y
 194.292 -       wIn[0] = RGB_8_TO_16(*accum); accum++;  // M
 194.293 -       wIn[3] = RGB_8_TO_16(*accum); accum++;  // C
 194.294 -
 194.295 -       return accum;
 194.296 +    wIn[2] = FROM_8_TO_16(*accum); accum++;  // K
 194.297 +    wIn[1] = FROM_8_TO_16(*accum); accum++;  // Y
 194.298 +    wIn[0] = FROM_8_TO_16(*accum); accum++;  // M
 194.299 +    wIn[3] = FROM_8_TO_16(*accum); accum++;  // C
 194.300 +
 194.301 +    return accum;
 194.302  }
 194.303  
 194.304 -
 194.305  static
 194.306 -LPBYTE UnrollAnyWords(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.307 +cmsUInt8Number* Unroll3Bytes(register _cmsTRANSFORM* info,
 194.308 +                             register cmsUInt16Number wIn[],
 194.309 +                             register cmsUInt8Number* accum,
 194.310 +                             register cmsUInt32Number Stride)
 194.311  {
 194.312 -     int nChan = T_CHANNELS(info -> InputFormat);
 194.313 -     register int i;
 194.314 -
 194.315 -     for (i=0; i < nChan; i++) {
 194.316 -
 194.317 -              wIn[i] = *(LPWORD) accum; accum += 2;
 194.318 -     }
 194.319 -
 194.320 -     return accum + T_EXTRA(info -> InputFormat) * sizeof(WORD);
 194.321 +    wIn[0] = FROM_8_TO_16(*accum); accum++;     // R
 194.322 +    wIn[1] = FROM_8_TO_16(*accum); accum++;     // G
 194.323 +    wIn[2] = FROM_8_TO_16(*accum); accum++;     // B
 194.324 +
 194.325 +    return accum;
 194.326  }
 194.327  
 194.328 -
 194.329  static
 194.330 -LPBYTE Unroll4Words(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.331 +cmsUInt8Number* Unroll3BytesSkip1Swap(register _cmsTRANSFORM* info,
 194.332 +                                      register cmsUInt16Number wIn[],
 194.333 +                                      register cmsUInt8Number* accum,
 194.334 +                                      register cmsUInt32Number Stride)
 194.335  {
 194.336 -       wIn[0] = *(LPWORD) accum; accum+= 2; // C
 194.337 -       wIn[1] = *(LPWORD) accum; accum+= 2; // M
 194.338 -       wIn[2] = *(LPWORD) accum; accum+= 2; // Y
 194.339 -       wIn[3] = *(LPWORD) accum; accum+= 2; // K
 194.340 -
 194.341 -       return accum;
 194.342 +    accum++; // A
 194.343 +    wIn[2] = FROM_8_TO_16(*accum); accum++; // B
 194.344 +    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
 194.345 +    wIn[0] = FROM_8_TO_16(*accum); accum++; // R
 194.346 +
 194.347 +    return accum;
 194.348  }
 194.349  
 194.350  static
 194.351 -LPBYTE Unroll4WordsReverse(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.352 +cmsUInt8Number* Unroll3BytesSkip1SwapFirst(register _cmsTRANSFORM* info,
 194.353 +                                           register cmsUInt16Number wIn[],
 194.354 +                                           register cmsUInt8Number* accum,
 194.355 +                                           register cmsUInt32Number Stride)
 194.356  {
 194.357 -       wIn[0] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; // C
 194.358 -       wIn[1] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; // M
 194.359 -       wIn[2] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; // Y
 194.360 -       wIn[3] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2; // K
 194.361 -
 194.362 -       return accum;
 194.363 +    accum++; // A
 194.364 +    wIn[0] = FROM_8_TO_16(*accum); accum++; // R
 194.365 +    wIn[1] = FROM_8_TO_16(*accum); accum++; // G
 194.366 +    wIn[2] = FROM_8_TO_16(*accum); accum++; // B
 194.367 +
 194.368 +    return accum;
 194.369  }
 194.370  
 194.371  
 194.372 +// BRG
 194.373  static
 194.374 -LPBYTE Unroll4WordsSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.375 +cmsUInt8Number* Unroll3BytesSwap(register _cmsTRANSFORM* info,
 194.376 +                                 register cmsUInt16Number wIn[],
 194.377 +                                 register cmsUInt8Number* accum,
 194.378 +                                 register cmsUInt32Number Stride)
 194.379  {
 194.380 -       wIn[3] = *(LPWORD) accum; accum+= 2; // K
 194.381 -       wIn[0] = *(LPWORD) accum; accum+= 2; // C
 194.382 -       wIn[1] = *(LPWORD) accum; accum+= 2; // M
 194.383 -       wIn[2] = *(LPWORD) accum; accum+= 2; // Y
 194.384 -
 194.385 -       return accum;
 194.386 +    wIn[2] = FROM_8_TO_16(*accum); accum++;     // B
 194.387 +    wIn[1] = FROM_8_TO_16(*accum); accum++;     // G
 194.388 +    wIn[0] = FROM_8_TO_16(*accum); accum++;     // R
 194.389 +
 194.390 +    return accum;
 194.391  }
 194.392  
 194.393 +static
 194.394 +cmsUInt8Number* UnrollLabV2_8(register _cmsTRANSFORM* info,
 194.395 +                              register cmsUInt16Number wIn[],
 194.396 +                              register cmsUInt8Number* accum,
 194.397 +                              register cmsUInt32Number Stride)
 194.398 +{
 194.399 +    wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
 194.400 +    wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
 194.401 +    wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b
 194.402 +
 194.403 +    return accum;
 194.404 +}
 194.405 +
 194.406 +static
 194.407 +cmsUInt8Number* UnrollALabV2_8(register _cmsTRANSFORM* info,
 194.408 +                               register cmsUInt16Number wIn[],
 194.409 +                               register cmsUInt8Number* accum,
 194.410 +                               register cmsUInt32Number Stride)
 194.411 +{
 194.412 +    accum++;  // A
 194.413 +    wIn[0] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // L
 194.414 +    wIn[1] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // a
 194.415 +    wIn[2] = FomLabV2ToLabV4(FROM_8_TO_16(*accum)); accum++;     // b
 194.416 +
 194.417 +    return accum;
 194.418 +}
 194.419 +
 194.420 +static
 194.421 +cmsUInt8Number* UnrollLabV2_16(register _cmsTRANSFORM* info,
 194.422 +                               register cmsUInt16Number wIn[],
 194.423 +                               register cmsUInt8Number* accum,
 194.424 +                               register cmsUInt32Number Stride)
 194.425 +{
 194.426 +    wIn[0] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // L
 194.427 +    wIn[1] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // a
 194.428 +    wIn[2] = FomLabV2ToLabV4(*(cmsUInt16Number*) accum); accum += 2;     // b
 194.429 +
 194.430 +    return accum;
 194.431 +}
 194.432 +
 194.433 +
 194.434 +
 194.435 +// Monochrome + alpha. Alpha is lost
 194.436 +static
 194.437 +cmsUInt8Number* Unroll2Bytes(register _cmsTRANSFORM* info,
 194.438 +                             register cmsUInt16Number wIn[],
 194.439 +                             register cmsUInt8Number* accum,
 194.440 +                             register cmsUInt32Number Stride)
 194.441 +{
 194.442 +    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
 194.443 +    wIn[3] = FROM_8_TO_16(*accum); accum++;                       // alpha
 194.444 +    return accum;
 194.445 +}
 194.446 +
 194.447 +static
 194.448 +cmsUInt8Number* Unroll2ByteSwapFirst(register _cmsTRANSFORM* info,
 194.449 +                                     register cmsUInt16Number wIn[],
 194.450 +                                     register cmsUInt8Number* accum,
 194.451 +                                     register cmsUInt32Number Stride)
 194.452 +{
 194.453 +    wIn[3] = FROM_8_TO_16(*accum); accum++;                       // alpha
 194.454 +    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
 194.455 +    return accum;
 194.456 +}
 194.457 +
 194.458 +
 194.459 +// Monochrome duplicates L into RGB for null-transforms
 194.460 +static
 194.461 +cmsUInt8Number* Unroll1Byte(register _cmsTRANSFORM* info,
 194.462 +                            register cmsUInt16Number wIn[],
 194.463 +                            register cmsUInt8Number* accum,
 194.464 +                            register cmsUInt32Number Stride)
 194.465 +{
 194.466 +    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
 194.467 +    return accum;
 194.468 +}
 194.469 +
 194.470 +static
 194.471 +cmsUInt8Number* Unroll1ByteSkip2(register _cmsTRANSFORM* info,
 194.472 +                                 register cmsUInt16Number wIn[],
 194.473 +                                 register cmsUInt8Number* accum,
 194.474 +                                 register cmsUInt32Number Stride)
 194.475 +{
 194.476 +    wIn[0] = wIn[1] = wIn[2] = FROM_8_TO_16(*accum); accum++;     // L
 194.477 +    accum += 2;
 194.478 +    return accum;
 194.479 +}
 194.480 +
 194.481 +static
 194.482 +cmsUInt8Number* Unroll1ByteReversed(register _cmsTRANSFORM* info,
 194.483 +                                    register cmsUInt16Number wIn[],
 194.484 +                                    register cmsUInt8Number* accum,
 194.485 +                                    register cmsUInt32Number Stride)
 194.486 +{
 194.487 +    wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(FROM_8_TO_16(*accum)); accum++;     // L
 194.488 +    return accum;
 194.489 +}
 194.490 +
 194.491 +
 194.492 +static
 194.493 +cmsUInt8Number* UnrollAnyWords(register _cmsTRANSFORM* info,
 194.494 +                               register cmsUInt16Number wIn[],
 194.495 +                               register cmsUInt8Number* accum,
 194.496 +                               register cmsUInt32Number Stride)
 194.497 +{
 194.498 +    int nChan       = T_CHANNELS(info -> InputFormat);
 194.499 +    int SwapEndian  = T_ENDIAN16(info -> InputFormat);
 194.500 +    int DoSwap      = T_DOSWAP(info ->InputFormat);
 194.501 +    int Reverse     = T_FLAVOR(info ->InputFormat);
 194.502 +    int SwapFirst   = T_SWAPFIRST(info -> InputFormat);
 194.503 +    int Extra       = T_EXTRA(info -> InputFormat);
 194.504 +    int ExtraFirst  = DoSwap && !SwapFirst;
 194.505 +    int i;
 194.506 +
 194.507 +    if (ExtraFirst) {
 194.508 +        accum += Extra * sizeof(cmsUInt16Number);
 194.509 +    }
 194.510 +
 194.511 +    for (i=0; i < nChan; i++) {
 194.512 +
 194.513 +        int index = DoSwap ? (nChan - i - 1) : i;
 194.514 +        cmsUInt16Number v = *(cmsUInt16Number*) accum;
 194.515 +
 194.516 +        if (SwapEndian)
 194.517 +            v = CHANGE_ENDIAN(v);
 194.518 +
 194.519 +        wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
 194.520 +
 194.521 +        accum += sizeof(cmsUInt16Number);
 194.522 +    }
 194.523 +
 194.524 +    if (!ExtraFirst) {
 194.525 +        accum += Extra * sizeof(cmsUInt16Number);
 194.526 +    }
 194.527 +
 194.528 +    if (Extra == 0 && SwapFirst) {
 194.529 +
 194.530 +        cmsUInt16Number tmp = wIn[0];
 194.531 +
 194.532 +        memmove(&wIn[0], &wIn[1], (nChan-1) * sizeof(cmsUInt16Number));
 194.533 +        wIn[nChan-1] = tmp;
 194.534 +    }
 194.535 +
 194.536 +    return accum;
 194.537 +}
 194.538 +
 194.539 +static
 194.540 +cmsUInt8Number* UnrollPlanarWords(register _cmsTRANSFORM* info,
 194.541 +                                  register cmsUInt16Number wIn[],
 194.542 +                                  register cmsUInt8Number* accum,
 194.543 +                                  register cmsUInt32Number Stride)
 194.544 +{
 194.545 +    int nChan = T_CHANNELS(info -> InputFormat);
 194.546 +    int DoSwap= T_DOSWAP(info ->InputFormat);
 194.547 +    int Reverse= T_FLAVOR(info ->InputFormat);
 194.548 +    int SwapEndian = T_ENDIAN16(info -> InputFormat);
 194.549 +    int i;
 194.550 +    cmsUInt8Number* Init = accum;
 194.551 +
 194.552 +    if (DoSwap) {
 194.553 +        accum += T_EXTRA(info -> InputFormat) * Stride * sizeof(cmsUInt16Number);
 194.554 +    }
 194.555 +
 194.556 +    for (i=0; i < nChan; i++) {
 194.557 +
 194.558 +        int index = DoSwap ? (nChan - i - 1) : i;
 194.559 +        cmsUInt16Number v = *(cmsUInt16Number*) accum;
 194.560 +
 194.561 +        if (SwapEndian)
 194.562 +            v = CHANGE_ENDIAN(v);
 194.563 +
 194.564 +        wIn[index] = Reverse ? REVERSE_FLAVOR_16(v) : v;
 194.565 +
 194.566 +        accum +=  Stride * sizeof(cmsUInt16Number);
 194.567 +    }
 194.568 +
 194.569 +    return (Init + sizeof(cmsUInt16Number));
 194.570 +}
 194.571 +
 194.572 +
 194.573 +static
 194.574 +cmsUInt8Number* Unroll4Words(register _cmsTRANSFORM* info,
 194.575 +                             register cmsUInt16Number wIn[],
 194.576 +                             register cmsUInt8Number* accum,
 194.577 +                             register cmsUInt32Number Stride)
 194.578 +{
 194.579 +    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
 194.580 +    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
 194.581 +    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
 194.582 +    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
 194.583 +
 194.584 +    return accum;
 194.585 +}
 194.586 +
 194.587 +static
 194.588 +cmsUInt8Number* Unroll4WordsReverse(register _cmsTRANSFORM* info,
 194.589 +                                    register cmsUInt16Number wIn[],
 194.590 +                                    register cmsUInt8Number* accum,
 194.591 +                                    register cmsUInt32Number Stride)
 194.592 +{
 194.593 +    wIn[0] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // C
 194.594 +    wIn[1] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // M
 194.595 +    wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // Y
 194.596 +    wIn[3] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2; // K
 194.597 +
 194.598 +    return accum;
 194.599 +}
 194.600 +
 194.601 +static
 194.602 +cmsUInt8Number* Unroll4WordsSwapFirst(register _cmsTRANSFORM* info,
 194.603 +                                      register cmsUInt16Number wIn[],
 194.604 +                                      register cmsUInt8Number* accum,
 194.605 +                                      register cmsUInt32Number Stride)
 194.606 +{
 194.607 +    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
 194.608 +    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
 194.609 +    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
 194.610 +    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
 194.611 +
 194.612 +    return accum;
 194.613 +}
 194.614  
 194.615  // KYMC
 194.616  static
 194.617 -LPBYTE Unroll4WordsSwap(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.618 +cmsUInt8Number* Unroll4WordsSwap(register _cmsTRANSFORM* info,
 194.619 +                                 register cmsUInt16Number wIn[],
 194.620 +                                 register cmsUInt8Number* accum,
 194.621 +                                 register cmsUInt32Number Stride)
 194.622  {
 194.623 -       wIn[3] = *(LPWORD) accum; accum+= 2; // K
 194.624 -       wIn[2] = *(LPWORD) accum; accum+= 2; // Y
 194.625 -       wIn[1] = *(LPWORD) accum; accum+= 2; // M
 194.626 -       wIn[0] = *(LPWORD) accum; accum+= 2; // C
 194.627 -
 194.628 -       return accum;
 194.629 +    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // K
 194.630 +    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // Y
 194.631 +    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // M
 194.632 +    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // C
 194.633 +
 194.634 +    return accum;
 194.635  }
 194.636  
 194.637  static
 194.638 -LPBYTE Unroll4WordsSwapSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.639 +cmsUInt8Number* Unroll4WordsSwapSwapFirst(register _cmsTRANSFORM* info,
 194.640 +                                          register cmsUInt16Number wIn[],
 194.641 +                                          register cmsUInt8Number* accum,
 194.642 +                                          register cmsUInt32Number Stride)
 194.643  {
 194.644 -       wIn[2] = *(LPWORD) accum; accum+= 2; // K
 194.645 -       wIn[1] = *(LPWORD) accum; accum+= 2; // Y
 194.646 -       wIn[0] = *(LPWORD) accum; accum+= 2; // M
 194.647 -       wIn[3] = *(LPWORD) accum; accum+= 2; // C
 194.648 -
 194.649 -       return accum;
 194.650 +    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2; // K
 194.651 +    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2; // Y
 194.652 +    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2; // M
 194.653 +    wIn[3] = *(cmsUInt16Number*) accum; accum+= 2; // C
 194.654 +
 194.655 +    return accum;
 194.656  }
 194.657  
 194.658 -
 194.659  static
 194.660 -LPBYTE Unroll4WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.661 +cmsUInt8Number* Unroll3Words(register _cmsTRANSFORM* info,
 194.662 +                             register cmsUInt16Number wIn[],
 194.663 +                             register cmsUInt8Number* accum,
 194.664 +                             register cmsUInt32Number Stride)
 194.665  {
 194.666 -       wIn[0] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //C
 194.667 -       wIn[1] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //M
 194.668 -       wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //Y
 194.669 -       wIn[3] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //K
 194.670 -
 194.671 -       return accum;
 194.672 +    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2;  // C R
 194.673 +    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2;  // M G
 194.674 +    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;  // Y B
 194.675 +    return accum;
 194.676  }
 194.677  
 194.678  static
 194.679 -LPBYTE Unroll4WordsBigEndianReverse(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.680 +cmsUInt8Number* Unroll3WordsSwap(register _cmsTRANSFORM* info,
 194.681 +                                 register cmsUInt16Number wIn[],
 194.682 +                                 register cmsUInt8Number* accum,
 194.683 +                                 register cmsUInt32Number Stride)
 194.684  {
 194.685 -       wIn[0] = REVERSE_FLAVOR_16(CHANGE_ENDIAN(*(LPWORD) accum)); accum+= 2; //C
 194.686 -       wIn[1] = REVERSE_FLAVOR_16(CHANGE_ENDIAN(*(LPWORD) accum)); accum+= 2; //M
 194.687 -       wIn[2] = REVERSE_FLAVOR_16(CHANGE_ENDIAN(*(LPWORD) accum)); accum+= 2; //Y
 194.688 -       wIn[3] = REVERSE_FLAVOR_16(CHANGE_ENDIAN(*(LPWORD) accum)); accum+= 2; //K
 194.689 -
 194.690 -       return accum;
 194.691 +    wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;  // C R
 194.692 +    wIn[1] = *(cmsUInt16Number*) accum; accum+= 2;  // M G
 194.693 +    wIn[0] = *(cmsUInt16Number*) accum; accum+= 2;  // Y B
 194.694 +    return accum;
 194.695  }
 194.696  
 194.697 -
 194.698 -// KYMC
 194.699  static
 194.700 -LPBYTE Unroll4WordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.701 +cmsUInt8Number* Unroll3WordsSkip1Swap(register _cmsTRANSFORM* info,
 194.702 +                                      register cmsUInt16Number wIn[],
 194.703 +                                      register cmsUInt8Number* accum,
 194.704 +                                      register cmsUInt32Number Stride)
 194.705  {
 194.706 -       wIn[3] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //K
 194.707 -       wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //Y
 194.708 -       wIn[1] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //M
 194.709 -       wIn[0] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2; //C
 194.710 -
 194.711 -       return accum;
 194.712 +    accum += 2; // A
 194.713 +    wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // R
 194.714 +    wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
 194.715 +    wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // B
 194.716 +
 194.717 +    return accum;
 194.718  }
 194.719  
 194.720  static
 194.721 -LPBYTE Unroll3Bytes(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.722 +cmsUInt8Number* Unroll3WordsSkip1SwapFirst(register _cmsTRANSFORM* info,
 194.723 +                                           register cmsUInt16Number wIn[],
 194.724 +                                           register cmsUInt8Number* accum,
 194.725 +                                           register cmsUInt32Number Stride)
 194.726  {
 194.727 -
 194.728 -       wIn[0] = RGB_8_TO_16(*accum); accum++;     // R
 194.729 -       wIn[1] = RGB_8_TO_16(*accum); accum++;     // G
 194.730 -       wIn[2] = RGB_8_TO_16(*accum); accum++;     // B
 194.731 -
 194.732 -       return accum;
 194.733 +    accum += 2; // A
 194.734 +    wIn[0] = *(cmsUInt16Number*) accum; accum += 2; // R
 194.735 +    wIn[1] = *(cmsUInt16Number*) accum; accum += 2; // G
 194.736 +    wIn[2] = *(cmsUInt16Number*) accum; accum += 2; // B
 194.737 +
 194.738 +    return accum;
 194.739  }
 194.740  
 194.741 -
 194.742 -// Lab8 encoding using v2 PCS
 194.743 -
 194.744  static
 194.745 -LPBYTE Unroll3BytesLab(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.746 +cmsUInt8Number* Unroll1Word(register _cmsTRANSFORM* info,
 194.747 +                            register cmsUInt16Number wIn[],
 194.748 +                            register cmsUInt8Number* accum,
 194.749 +                            register cmsUInt32Number Stride)
 194.750  {
 194.751 -
 194.752 -       wIn[0] = (WORD) ((*accum) << 8); accum++;
 194.753 -       wIn[1] = (WORD) ((*accum) << 8); accum++;
 194.754 -       wIn[2] = (WORD) ((*accum) << 8); accum++;
 194.755 -
 194.756 -       return accum;
 194.757 +    wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;   // L
 194.758 +    return accum;
 194.759  }
 194.760  
 194.761 -
 194.762 -// BRG
 194.763 -
 194.764  static
 194.765 -LPBYTE Unroll3BytesSwap(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.766 +cmsUInt8Number* Unroll1WordReversed(register _cmsTRANSFORM* info,
 194.767 +                                    register cmsUInt16Number wIn[],
 194.768 +                                    register cmsUInt8Number* accum,
 194.769 +                                    register cmsUInt32Number Stride)
 194.770  {
 194.771 -
 194.772 -       wIn[2] = RGB_8_TO_16(*accum); accum++;     // B
 194.773 -       wIn[1] = RGB_8_TO_16(*accum); accum++;     // G
 194.774 -       wIn[0] = RGB_8_TO_16(*accum); accum++;     // R
 194.775 -
 194.776 -       return accum;
 194.777 +    wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(cmsUInt16Number*) accum); accum+= 2;
 194.778 +    return accum;
 194.779  }
 194.780  
 194.781  static
 194.782 -LPBYTE Unroll3Words(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.783 +cmsUInt8Number* Unroll1WordSkip3(register _cmsTRANSFORM* info,
 194.784 +                                 register cmsUInt16Number wIn[],
 194.785 +                                 register cmsUInt8Number* accum,
 194.786 +                                 register cmsUInt32Number Stride)
 194.787  {
 194.788 -       wIn[0] = *(LPWORD) accum; accum+= 2;  // C R
 194.789 -       wIn[1] = *(LPWORD) accum; accum+= 2;  // M G
 194.790 -       wIn[2] = *(LPWORD) accum; accum+= 2;  // Y B
 194.791 -       return accum;
 194.792 +    wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum;
 194.793 +
 194.794 +    accum += 8;
 194.795 +    return accum;
 194.796  }
 194.797  
 194.798 -
 194.799  static
 194.800 -LPBYTE Unroll3WordsSwap(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.801 +cmsUInt8Number* Unroll2Words(register _cmsTRANSFORM* info,
 194.802 +                             register cmsUInt16Number wIn[],
 194.803 +                             register cmsUInt8Number* accum,
 194.804 +                             register cmsUInt32Number Stride)
 194.805  {
 194.806 -       wIn[2] = *(LPWORD) accum; accum+= 2;  // C R
 194.807 -       wIn[1] = *(LPWORD) accum; accum+= 2;  // M G
 194.808 -       wIn[0] = *(LPWORD) accum; accum+= 2;  // Y B
 194.809 -       return accum;
 194.810 +    wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;   // L
 194.811 +    wIn[3] = *(cmsUInt16Number*) accum; accum += 2;                    // alpha
 194.812 +
 194.813 +    return accum;
 194.814  }
 194.815  
 194.816 -
 194.817  static
 194.818 -LPBYTE Unroll3WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.819 +cmsUInt8Number* Unroll2WordSwapFirst(register _cmsTRANSFORM* info,
 194.820 +                                     register cmsUInt16Number wIn[],
 194.821 +                                     register cmsUInt8Number* accum,
 194.822 +                                     register cmsUInt32Number Stride)
 194.823  {
 194.824 -       wIn[0] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.825 -       wIn[1] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.826 -       wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.827 -       return accum;
 194.828 +    wIn[3] = *(cmsUInt16Number*) accum; accum += 2;                    // alpha
 194.829 +    wIn[0] = wIn[1] = wIn[2] = *(cmsUInt16Number*) accum; accum+= 2;   // L
 194.830 +
 194.831 +    return accum;
 194.832  }
 194.833  
 194.834 -
 194.835 +// This is a conversion of Lab double to 16 bits
 194.836  static
 194.837 -LPBYTE Unroll3WordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.838 +cmsUInt8Number* UnrollLabDoubleTo16(register _cmsTRANSFORM* info,
 194.839 +                                    register cmsUInt16Number wIn[],
 194.840 +                                    register cmsUInt8Number* accum,
 194.841 +                                    register cmsUInt32Number  Stride)
 194.842  {
 194.843 -       wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.844 -       wIn[1] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.845 -       wIn[0] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.846 -       return accum;
 194.847 -}
 194.848 -
 194.849 -
 194.850 -
 194.851 -// Monochrome duplicates L into RGB for null-transforms
 194.852 -
 194.853 -static
 194.854 -LPBYTE Unroll1Byte(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.855 -{
 194.856 -       wIn[0] = wIn[1] = wIn[2] = RGB_8_TO_16(*accum); accum++;     // L
 194.857 -       return accum;
 194.858 -}
 194.859 -
 194.860 -
 194.861 -static
 194.862 -LPBYTE Unroll1ByteSkip2(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.863 -{
 194.864 -       wIn[0] = wIn[1] = wIn[2] = RGB_8_TO_16(*accum); accum++;     // L
 194.865 -       accum += 2;
 194.866 -       return accum;
 194.867 -}
 194.868 -
 194.869 -static
 194.870 -LPBYTE Unroll1ByteReversed(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.871 -{
 194.872 -       wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(RGB_8_TO_16(*accum)); accum++;     // L
 194.873 -       return accum;
 194.874 -}
 194.875 -
 194.876 -
 194.877 -static
 194.878 -LPBYTE Unroll1Word(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.879 -{
 194.880 -       wIn[0] = wIn[1] = wIn[2] = *(LPWORD) accum; accum+= 2;   // L
 194.881 -       return accum;
 194.882 -}
 194.883 -
 194.884 -static
 194.885 -LPBYTE Unroll1WordReversed(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.886 -{
 194.887 -       wIn[0] = wIn[1] = wIn[2] = REVERSE_FLAVOR_16(*(LPWORD) accum); accum+= 2;
 194.888 -       return accum;
 194.889 -}
 194.890 -
 194.891 -
 194.892 -static
 194.893 -LPBYTE Unroll1WordBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.894 -{
 194.895 -       wIn[0] = wIn[1] = wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.896 -       return accum;
 194.897 -}
 194.898 -
 194.899 -static
 194.900 -LPBYTE Unroll1WordSkip3(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.901 -{
 194.902 -       wIn[0] = wIn[1] = wIn[2] = *(LPWORD) accum;
 194.903 -
 194.904 -       accum += 8;
 194.905 -       return accum;
 194.906 -}
 194.907 -
 194.908 -
 194.909 -// Monochrome + alpha. Alpha is lost
 194.910 -
 194.911 -static
 194.912 -LPBYTE Unroll2Byte(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.913 -{
 194.914 -       wIn[0] = wIn[1] = wIn[2] = RGB_8_TO_16(*accum); accum++;     // L
 194.915 -       wIn[3] = RGB_8_TO_16(*accum); accum++;                       // alpha
 194.916 -       return accum;
 194.917 -}
 194.918 -
 194.919 -static
 194.920 -LPBYTE Unroll2ByteSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.921 -{
 194.922 -       wIn[3] = RGB_8_TO_16(*accum); accum++;                       // alpha
 194.923 -       wIn[0] = wIn[1] = wIn[2] = RGB_8_TO_16(*accum); accum++;     // L
 194.924 -       return accum;
 194.925 -}
 194.926 -
 194.927 -
 194.928 -static
 194.929 -LPBYTE Unroll2Word(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.930 -{
 194.931 -       wIn[0] = wIn[1] = wIn[2] = *(LPWORD) accum; accum+= 2;   // L
 194.932 -       wIn[3] = *(LPWORD) accum; accum += 2;                    // alpha
 194.933 -
 194.934 -       return accum;
 194.935 -}
 194.936 -
 194.937 -
 194.938 -static
 194.939 -LPBYTE Unroll2WordSwapFirst(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.940 -{
 194.941 -       wIn[3] = *(LPWORD) accum; accum += 2;                    // alpha
 194.942 -       wIn[0] = wIn[1] = wIn[2] = *(LPWORD) accum; accum+= 2;   // L
 194.943 -
 194.944 -       return accum;
 194.945 -}
 194.946 -
 194.947 -static
 194.948 -LPBYTE Unroll2WordBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.949 -{
 194.950 -       wIn[0] = wIn[1] = wIn[2] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.951 -       wIn[3] = CHANGE_ENDIAN(*(LPWORD) accum); accum+= 2;
 194.952 -
 194.953 -       return accum;
 194.954 -}
 194.955 -
 194.956 -
 194.957 -
 194.958 -
 194.959 -static
 194.960 -LPBYTE UnrollPlanarBytes(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.961 -{
 194.962 -       int nChan = T_CHANNELS(info -> InputFormat);
 194.963 -       register int i;
 194.964 -       LPBYTE Init = accum;
 194.965 -
 194.966 -       for (i=0; i < nChan; i++) {
 194.967 -
 194.968 -              wIn[i] = RGB_8_TO_16(*accum);
 194.969 -              accum += info -> StrideIn;
 194.970 -       }
 194.971 -
 194.972 -       return (Init + 1);
 194.973 -}
 194.974 -
 194.975 -
 194.976 -
 194.977 -static
 194.978 -LPBYTE UnrollPlanarWords(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.979 -{
 194.980 -       int nChan = T_CHANNELS(info -> InputFormat);
 194.981 -       register int i;
 194.982 -       LPBYTE Init = accum;
 194.983 -
 194.984 -       for (i=0; i < nChan; i++) {
 194.985 -
 194.986 -              wIn[i] = *(LPWORD) accum;
 194.987 -              accum += (info -> StrideIn * sizeof(WORD));
 194.988 -       }
 194.989 -
 194.990 -       return (Init + sizeof(WORD));
 194.991 -}
 194.992 -
 194.993 -
 194.994 -
 194.995 -static
 194.996 -LPBYTE UnrollPlanarWordsBigEndian(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
 194.997 -{
 194.998 -       int nChan = T_CHANNELS(info -> InputFormat);
 194.999 -       register int i;
194.1000 -       LPBYTE Init = accum;
194.1001 -
194.1002 -       for (i=0; i < nChan; i++) {
194.1003 -
194.1004 -              wIn[i] = CHANGE_ENDIAN(*(LPWORD) accum);
194.1005 -              accum += (info -> StrideIn * sizeof(WORD));
194.1006 -       }
194.1007 -
194.1008 -       return (Init + sizeof(WORD));
194.1009 -}
194.1010 -
194.1011 -
194.1012 -// floating point
194.1013 -static
194.1014 -LPBYTE UnrollLabDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
194.1015 -{
194.1016 -
194.1017      if (T_PLANAR(info -> InputFormat)) {
194.1018  
194.1019 -        double* Pt = (double*) accum;
194.1020 +        cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
194.1021  
194.1022          cmsCIELab Lab;
194.1023  
194.1024          Lab.L = Pt[0];
194.1025 -        Lab.a = Pt[info->StrideIn];
194.1026 -        Lab.b = Pt[info->StrideIn*2];
194.1027 -
194.1028 -        if (info ->lInputV4Lab)
194.1029 -            cmsFloat2LabEncoded4(wIn, &Lab);
194.1030 -        else
194.1031 -            cmsFloat2LabEncoded(wIn, &Lab);
194.1032 -
194.1033 -        return accum + sizeof(double);
194.1034 +        Lab.a = Pt[Stride];
194.1035 +        Lab.b = Pt[Stride*2];
194.1036 +
194.1037 +        cmsFloat2LabEncoded(wIn, &Lab);
194.1038 +        return accum + sizeof(cmsFloat64Number);
194.1039      }
194.1040      else {
194.1041  
194.1042 -        if (info ->lInputV4Lab)
194.1043 -            cmsFloat2LabEncoded4(wIn, (LPcmsCIELab) accum);
194.1044 -        else
194.1045 -            cmsFloat2LabEncoded(wIn, (LPcmsCIELab) accum);
194.1046 -
194.1047 +        cmsFloat2LabEncoded(wIn, (cmsCIELab*) accum);
194.1048          accum += sizeof(cmsCIELab);
194.1049 -
194.1050          return accum;
194.1051      }
194.1052  }
194.1053  
194.1054 +// This is a conversion of XYZ double to 16 bits
194.1055  static
194.1056 -LPBYTE UnrollXYZDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
194.1057 +cmsUInt8Number* UnrollXYZDoubleTo16(register _cmsTRANSFORM* info,
194.1058 +                                    register cmsUInt16Number wIn[],
194.1059 +                                    register cmsUInt8Number* accum,
194.1060 +                                    register cmsUInt32Number Stride)
194.1061  {
194.1062      if (T_PLANAR(info -> InputFormat)) {
194.1063  
194.1064 -        double* Pt = (double*) accum;
194.1065 +        cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
194.1066          cmsCIEXYZ XYZ;
194.1067  
194.1068          XYZ.X = Pt[0];
194.1069 -        XYZ.Y = Pt[info->StrideIn];
194.1070 -        XYZ.Z = Pt[info->StrideIn*2];
194.1071 +        XYZ.Y = Pt[Stride];
194.1072 +        XYZ.Z = Pt[Stride*2];
194.1073          cmsFloat2XYZEncoded(wIn, &XYZ);
194.1074  
194.1075 -        return accum + sizeof(double);
194.1076 +        return accum + sizeof(cmsFloat64Number);
194.1077  
194.1078      }
194.1079  
194.1080      else {
194.1081 -
194.1082 -
194.1083 -        cmsFloat2XYZEncoded(wIn, (LPcmsCIEXYZ) accum);
194.1084 +        cmsFloat2XYZEncoded(wIn, (cmsCIEXYZ*) accum);
194.1085          accum += sizeof(cmsCIEXYZ);
194.1086  
194.1087          return accum;
194.1088      }
194.1089  }
194.1090  
194.1091 -
194.1092 -
194.1093 -// Inks does come in percentage
194.1094 +// Check if space is marked as ink
194.1095 +cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)
194.1096 +{
194.1097 +    switch (T_COLORSPACE(Type)) {
194.1098 +
194.1099 +     case PT_CMY:
194.1100 +     case PT_CMYK:
194.1101 +     case PT_MCH5:
194.1102 +     case PT_MCH6:
194.1103 +     case PT_MCH7:
194.1104 +     case PT_MCH8:
194.1105 +     case PT_MCH9:
194.1106 +     case PT_MCH10:
194.1107 +     case PT_MCH11:
194.1108 +     case PT_MCH12:
194.1109 +     case PT_MCH13:
194.1110 +     case PT_MCH14:
194.1111 +     case PT_MCH15: return TRUE;
194.1112 +
194.1113 +     default: return FALSE;
194.1114 +    }
194.1115 +}
194.1116 +
194.1117 +// Inks does come in percentage, remaining cases are between 0..1.0, again to 16 bits
194.1118  static
194.1119 -LPBYTE UnrollInkDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
194.1120 +cmsUInt8Number* UnrollDoubleTo16(register _cmsTRANSFORM* info,
194.1121 +                                 register cmsUInt16Number wIn[],
194.1122 +                                 register cmsUInt8Number* accum,
194.1123 +                                 register cmsUInt32Number Stride)
194.1124  {
194.1125 -    double* Inks = (double*) accum;
194.1126 +    cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
194.1127      int nChan  = T_CHANNELS(info -> InputFormat);
194.1128      int Planar = T_PLANAR(info -> InputFormat);
194.1129      int i;
194.1130 -    double v;
194.1131 -
194.1132 -    for (i=0; i <  nChan; i++) {
194.1133 +    cmsFloat64Number v;
194.1134 +    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
194.1135 +
194.1136 +    for (i=0; i < nChan; i++) {
194.1137  
194.1138          if (Planar)
194.1139  
194.1140 -            v = Inks[i * info ->StrideIn];
194.1141 +            v = Inks[i * Stride];
194.1142          else
194.1143              v = Inks[i];
194.1144  
194.1145 -        v = floor(v * 655.35 + 0.5);
194.1146 -
194.1147 -        if (v > 65535.0) v = 65535.0;
194.1148 -        if (v < 0) v = 0;
194.1149 -
194.1150 -        wIn[i] = (WORD) v;
194.1151 +        wIn[i] = _cmsQuickSaturateWord(v * maximum);
194.1152      }
194.1153  
194.1154      if (T_PLANAR(info -> InputFormat))
194.1155 -        return accum + sizeof(double);
194.1156 +        return accum + sizeof(cmsFloat64Number);
194.1157      else
194.1158 -        return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(double);
194.1159 +        return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat64Number);
194.1160  }
194.1161  
194.1162 -
194.1163 -// Remaining cases are between 0..1.0
194.1164  static
194.1165 -LPBYTE UnrollDouble(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
194.1166 +cmsUInt8Number* UnrollFloatTo16(register _cmsTRANSFORM* info,
194.1167 +                                register cmsUInt16Number wIn[],
194.1168 +                                register cmsUInt8Number* accum,
194.1169 +                                register cmsUInt32Number Stride)
194.1170  {
194.1171 -    double* Inks = (double*) accum;
194.1172 -    int nChan = T_CHANNELS(info -> InputFormat);
194.1173 +    cmsFloat32Number* Inks = (cmsFloat32Number*) accum;
194.1174 +    int nChan  = T_CHANNELS(info -> InputFormat);
194.1175      int Planar = T_PLANAR(info -> InputFormat);
194.1176      int i;
194.1177 -    double v;
194.1178 +    cmsFloat32Number v;
194.1179 +    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 655.35 : 65535.0;
194.1180  
194.1181      for (i=0; i < nChan; i++) {
194.1182  
194.1183          if (Planar)
194.1184  
194.1185 -            v = Inks[i * info ->StrideIn];
194.1186 +            v = Inks[i * Stride];
194.1187          else
194.1188              v = Inks[i];
194.1189  
194.1190 -        v = floor(v * 65535.0 + 0.5);
194.1191 -
194.1192 -        if (v > 65535.0) v = 65535.0;
194.1193 -        if (v < 0) v = 0;
194.1194 -
194.1195 -        wIn[i] = (WORD) v;
194.1196 +        wIn[i] = _cmsQuickSaturateWord(v * maximum);
194.1197      }
194.1198  
194.1199      if (T_PLANAR(info -> InputFormat))
194.1200 -        return accum + sizeof(double);
194.1201 +        return accum + sizeof(cmsFloat32Number);
194.1202      else
194.1203 -        return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(double);
194.1204 +        return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number);
194.1205  }
194.1206  
194.1207  
194.1208 -
194.1209 +// For 1 channel, we need to duplicate data (it comes in 0..1.0 range)
194.1210  static
194.1211 -LPBYTE UnrollDouble1Chan(register _LPcmsTRANSFORM info, register WORD wIn[], register LPBYTE accum)
194.1212 +cmsUInt8Number* UnrollDouble1Chan(register _cmsTRANSFORM* info,
194.1213 +                                  register cmsUInt16Number wIn[],
194.1214 +                                  register cmsUInt8Number* accum,
194.1215 +                                  register cmsUInt32Number Stride)
194.1216  {
194.1217 -    double* Inks = (double*) accum;
194.1218 -    double v;
194.1219 -
194.1220 -
194.1221 -    v = floor(Inks[0] * 65535.0 + 0.5);
194.1222 -
194.1223 -    if (v > 65535.0) v = 65535.0;
194.1224 -    if (v < 0) v = 0;
194.1225 -
194.1226 -
194.1227 -    wIn[0] = wIn[1] = wIn[2] = (WORD) v;
194.1228 -
194.1229 -    return accum + sizeof(double);
194.1230 +    cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
194.1231 +
194.1232 +    wIn[0] = wIn[1] = wIn[2] = _cmsQuickSaturateWord(Inks[0] * 65535.0);
194.1233 +
194.1234 +    return accum + sizeof(cmsFloat64Number);
194.1235  }
194.1236  
194.1237 -
194.1238 -// ----------------------------------------------------------- Packing routines
194.1239 -
194.1240 -
194.1241 -// Generic N-bytes plus dither 16-to-8 conversion. Currently is just a quick hack
194.1242 -
194.1243 -static int err[MAXCHANNELS];
194.1244 -
194.1245 +//-------------------------------------------------------------------------------------------------------------------
194.1246 +
194.1247 +// True cmsFloat32Number transformation.
194.1248 +
194.1249 +// For anything going from cmsFloat32Number
194.1250  static
194.1251 -LPBYTE PackNBytesDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1252 +cmsUInt8Number* UnrollFloatsToFloat(_cmsTRANSFORM* info,
194.1253 +                                    cmsFloat32Number wIn[],
194.1254 +                                    cmsUInt8Number* accum,
194.1255 +                                    cmsUInt32Number Stride)
194.1256  {
194.1257 -       int nChan  = T_CHANNELS(info -> OutputFormat);
194.1258 -       register int i;
194.1259 -       unsigned int n, pe, pf;
194.1260 -
194.1261 -       for (i=0; i < nChan;  i++) {
194.1262 -
194.1263 -              n = wOut[i] + err[i]; // Value
194.1264 -
194.1265 -              pe = (n / 257);       // Whole part
194.1266 -              pf = (n % 257);       // Fractional part
194.1267 -
194.1268 -              err[i] = pf;          // Store it for next pixel
194.1269 -
194.1270 -              *output++ = (BYTE) pe;
194.1271 -       }
194.1272 -
194.1273 -       return output + T_EXTRA(info ->OutputFormat);
194.1274 +    cmsFloat32Number* Inks = (cmsFloat32Number*) accum;
194.1275 +    int nChan  = T_CHANNELS(info -> InputFormat);
194.1276 +    int Planar = T_PLANAR(info -> InputFormat);
194.1277 +    int i;
194.1278 +    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
194.1279 +
194.1280 +
194.1281 +    for (i=0; i <  nChan; i++) {
194.1282 +
194.1283 +        if (Planar)
194.1284 +            wIn[i] = (cmsFloat32Number) (Inks[i * Stride] / maximum);
194.1285 +        else
194.1286 +            wIn[i] = (cmsFloat32Number) (Inks[i] / maximum);
194.1287 +    }
194.1288 +
194.1289 +    if (T_PLANAR(info -> InputFormat))
194.1290 +        return accum + sizeof(cmsFloat32Number);
194.1291 +    else
194.1292 +        return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat32Number);
194.1293  }
194.1294  
194.1295 -
194.1296 -
194.1297 +// For anything going from double
194.1298  static
194.1299 -LPBYTE PackNBytesSwapDither(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1300 +cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,
194.1301 +                                     cmsFloat32Number wIn[],
194.1302 +                                     cmsUInt8Number* accum,
194.1303 +                                     cmsUInt32Number Stride)
194.1304  {
194.1305 -       int nChan  = T_CHANNELS(info -> OutputFormat);
194.1306 -       register int i;
194.1307 -       unsigned int n, pe, pf;
194.1308 -
194.1309 -       for (i=nChan-1; i >= 0;  --i) {
194.1310 -
194.1311 -              n = wOut[i] + err[i];     // Value
194.1312 -
194.1313 -              pe = (n / 257);           // Whole part
194.1314 -              pf = (n % 257);           // Fractional part
194.1315 -
194.1316 -              err[i] = pf;              // Store it for next pixel
194.1317 -
194.1318 -              *output++ = (BYTE) pe;
194.1319 -       }
194.1320 -
194.1321 -
194.1322 -       return output + T_EXTRA(info ->OutputFormat);
194.1323 +    cmsFloat64Number* Inks = (cmsFloat64Number*) accum;
194.1324 +    int nChan  = T_CHANNELS(info -> InputFormat);
194.1325 +    int Planar = T_PLANAR(info -> InputFormat);
194.1326 +    int i;
194.1327 +    cmsFloat64Number maximum = IsInkSpace(info ->InputFormat) ? 100.0 : 1.0;
194.1328 +
194.1329 +    for (i=0; i <  nChan; i++) {
194.1330 +
194.1331 +        if (Planar)
194.1332 +            wIn[i] = (cmsFloat32Number) (Inks[i * Stride] / maximum);
194.1333 +        else
194.1334 +            wIn[i] = (cmsFloat32Number) (Inks[i] / maximum);
194.1335 +    }
194.1336 +
194.1337 +    if (T_PLANAR(info -> InputFormat))
194.1338 +        return accum + sizeof(cmsFloat64Number);
194.1339 +    else
194.1340 +        return accum + (nChan + T_EXTRA(info ->InputFormat)) * sizeof(cmsFloat64Number);
194.1341  }
194.1342  
194.1343  
194.1344 +// From Lab double to cmsFloat32Number
194.1345 +static
194.1346 +cmsUInt8Number* UnrollLabDoubleToFloat(_cmsTRANSFORM* info,
194.1347 +                                       cmsFloat32Number wIn[],
194.1348 +                                       cmsUInt8Number* accum,
194.1349 +                                       cmsUInt32Number Stride)
194.1350 +{
194.1351 +    cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
194.1352 +
194.1353 +    if (T_PLANAR(info -> InputFormat)) {
194.1354 +
194.1355 +        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);                            // from 0..100 to 0..1
194.1356 +        wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0);    // form -128..+127 to 0..1
194.1357 +        wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
194.1358 +
194.1359 +        return accum + sizeof(cmsFloat64Number);
194.1360 +    }
194.1361 +    else {
194.1362 +
194.1363 +        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);             // from 0..100 to 0..1
194.1364 +        wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0);    // form -128..+127 to 0..1
194.1365 +        wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
194.1366 +
194.1367 +        accum += sizeof(cmsFloat64Number)*3;
194.1368 +        return accum;
194.1369 +    }
194.1370 +}
194.1371 +
194.1372 +// From Lab double to cmsFloat32Number
194.1373 +static
194.1374 +cmsUInt8Number* UnrollLabFloatToFloat(_cmsTRANSFORM* info,
194.1375 +                                      cmsFloat32Number wIn[],
194.1376 +                                      cmsUInt8Number* accum,
194.1377 +                                      cmsUInt32Number Stride)
194.1378 +{
194.1379 +    cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
194.1380 +
194.1381 +    if (T_PLANAR(info -> InputFormat)) {
194.1382 +
194.1383 +        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);                            // from 0..100 to 0..1
194.1384 +        wIn[1] = (cmsFloat32Number) ((Pt[Stride] + 128) / 255.0);    // form -128..+127 to 0..1
194.1385 +        wIn[2] = (cmsFloat32Number) ((Pt[Stride*2] + 128) / 255.0);
194.1386 +
194.1387 +        return accum + sizeof(cmsFloat32Number);
194.1388 +    }
194.1389 +    else {
194.1390 +
194.1391 +        wIn[0] = (cmsFloat32Number) (Pt[0] / 100.0);             // from 0..100 to 0..1
194.1392 +        wIn[1] = (cmsFloat32Number) ((Pt[1] + 128) / 255.0);    // form -128..+127 to 0..1
194.1393 +        wIn[2] = (cmsFloat32Number) ((Pt[2] + 128) / 255.0);
194.1394 +
194.1395 +        accum += sizeof(cmsFloat32Number)*3;
194.1396 +        return accum;
194.1397 +    }
194.1398 +}
194.1399 +
194.1400 +
194.1401 +// 1.15 fixed point, that means maximum value is MAX_ENCODEABLE_XYZ (0xFFFF)
194.1402 +static
194.1403 +cmsUInt8Number* UnrollXYZDoubleToFloat(_cmsTRANSFORM* info,
194.1404 +                                       cmsFloat32Number wIn[],
194.1405 +                                       cmsUInt8Number* accum,
194.1406 +                                       cmsUInt32Number Stride)
194.1407 +{
194.1408 +    cmsFloat64Number* Pt = (cmsFloat64Number*) accum;
194.1409 +
194.1410 +    if (T_PLANAR(info -> InputFormat)) {
194.1411 +
194.1412 +        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
194.1413 +        wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
194.1414 +        wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
194.1415 +
194.1416 +        return accum + sizeof(cmsFloat64Number);
194.1417 +    }
194.1418 +    else {
194.1419 +
194.1420 +        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
194.1421 +        wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
194.1422 +        wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
194.1423 +
194.1424 +        accum += sizeof(cmsFloat64Number)*3;
194.1425 +        return accum;
194.1426 +    }
194.1427 +}
194.1428 +
194.1429 +static
194.1430 +cmsUInt8Number* UnrollXYZFloatToFloat(_cmsTRANSFORM* info,
194.1431 +                                      cmsFloat32Number wIn[],
194.1432 +                                      cmsUInt8Number* accum,
194.1433 +                                      cmsUInt32Number Stride)
194.1434 +{
194.1435 +    cmsFloat32Number* Pt = (cmsFloat32Number*) accum;
194.1436 +
194.1437 +    if (T_PLANAR(info -> InputFormat)) {
194.1438 +
194.1439 +        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
194.1440 +        wIn[1] = (cmsFloat32Number) (Pt[Stride] / MAX_ENCODEABLE_XYZ);
194.1441 +        wIn[2] = (cmsFloat32Number) (Pt[Stride*2] / MAX_ENCODEABLE_XYZ);
194.1442 +
194.1443 +        return accum + sizeof(cmsFloat32Number);
194.1444 +    }
194.1445 +    else {
194.1446 +
194.1447 +        wIn[0] = (cmsFloat32Number) (Pt[0] / MAX_ENCODEABLE_XYZ);
194.1448 +        wIn[1] = (cmsFloat32Number) (Pt[1] / MAX_ENCODEABLE_XYZ);
194.1449 +        wIn[2] = (cmsFloat32Number) (Pt[2] / MAX_ENCODEABLE_XYZ);
194.1450 +
194.1451 +        accum += sizeof(cmsFloat32Number)*3;
194.1452 +        return accum;
194.1453 +    }
194.1454 +}
194.1455 +
194.1456 +// Packing routines -----------------------------------------------------------------------------------------------------------
194.1457 +
194.1458  
194.1459  // Generic chunky for byte
194.1460  
194.1461  static
194.1462 -LPBYTE PackNBytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1463 +cmsUInt8Number* PackAnyBytes(register _cmsTRANSFORM* info,
194.1464 +                             register cmsUInt16Number wOut[],
194.1465 +                             register cmsUInt8Number* output,
194.1466 +                             register cmsUInt32Number Stride)
194.1467  {
194.1468 -       int nChan  = T_CHANNELS(info -> OutputFormat);
194.1469 -       register int i;
194.1470 -
194.1471 -       for (i=0; i < nChan;  i++)
194.1472 -              *output++ = RGB_16_TO_8(wOut[i]);
194.1473 -
194.1474 -       return output + T_EXTRA(info ->OutputFormat);
194.1475 +    int nChan      = T_CHANNELS(info -> OutputFormat);
194.1476 +    int DoSwap     = T_DOSWAP(info ->OutputFormat);
194.1477 +    int Reverse    = T_FLAVOR(info ->OutputFormat);
194.1478 +    int Extra      = T_EXTRA(info -> OutputFormat);
194.1479 +    int SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
194.1480 +    int ExtraFirst = DoSwap && !SwapFirst;
194.1481 +    cmsUInt8Number* swap1;
194.1482 +    cmsUInt8Number v = 0;
194.1483 +    int i;
194.1484 +
194.1485 +    swap1 = output;
194.1486 +
194.1487 +    if (ExtraFirst) {
194.1488 +        output += Extra;
194.1489 +    }
194.1490 +
194.1491 +    for (i=0; i < nChan; i++) {
194.1492 +
194.1493 +        int index = DoSwap ? (nChan - i - 1) : i;
194.1494 +
194.1495 +        v = FROM_16_TO_8(wOut[index]);
194.1496 +
194.1497 +        if (Reverse)
194.1498 +            v = REVERSE_FLAVOR_8(v);
194.1499 +
194.1500 +        *output++ = v;
194.1501 +    }
194.1502 +
194.1503 +    if (!ExtraFirst) {
194.1504 +        output += Extra;
194.1505 +    }
194.1506 +
194.1507 +    if (Extra == 0 && SwapFirst) {
194.1508 +
194.1509 +        memmove(swap1 + 1, swap1, nChan-1);
194.1510 +        *swap1 = v;
194.1511 +    }
194.1512 +
194.1513 +
194.1514 +    return output;
194.1515  }
194.1516  
194.1517 -// Chunky reversed order bytes
194.1518 +
194.1519  
194.1520  static
194.1521 -LPBYTE PackNBytesSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1522 +cmsUInt8Number* PackAnyWords(register _cmsTRANSFORM* info,
194.1523 +                             register cmsUInt16Number wOut[],
194.1524 +                             register cmsUInt8Number* output,
194.1525 +                             register cmsUInt32Number Stride)
194.1526  {
194.1527 -       int nChan  = T_CHANNELS(info -> OutputFormat);
194.1528 -       register int i;
194.1529 -
194.1530 -       for (i=nChan-1; i >= 0;  --i)
194.1531 -              *output++ = RGB_16_TO_8(wOut[i]);
194.1532 -
194.1533 -       return output + T_EXTRA(info ->OutputFormat);
194.1534 -
194.1535 +    int nChan      = T_CHANNELS(info -> OutputFormat);
194.1536 +    int SwapEndian = T_ENDIAN16(info -> InputFormat);
194.1537 +    int DoSwap     = T_DOSWAP(info ->OutputFormat);
194.1538 +    int Reverse    = T_FLAVOR(info ->OutputFormat);
194.1539 +    int Extra      = T_EXTRA(info -> OutputFormat);
194.1540 +    int SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
194.1541 +    int ExtraFirst = DoSwap && !SwapFirst;
194.1542 +    cmsUInt16Number* swap1;
194.1543 +    cmsUInt16Number v = 0;
194.1544 +    int i;
194.1545 +
194.1546 +    swap1 = (cmsUInt16Number*) output;
194.1547 +
194.1548 +    if (ExtraFirst) {
194.1549 +        output += Extra * sizeof(cmsUInt16Number);
194.1550 +    }
194.1551 +
194.1552 +    for (i=0; i < nChan; i++) {
194.1553 +
194.1554 +        int index = DoSwap ? (nChan - i - 1) : i;
194.1555 +
194.1556 +        v = wOut[index];
194.1557 +
194.1558 +        if (SwapEndian)
194.1559 +            v = CHANGE_ENDIAN(v);
194.1560 +
194.1561 +        if (Reverse)
194.1562 +            v = REVERSE_FLAVOR_16(v);
194.1563 +
194.1564 +        *(cmsUInt16Number*) output = v;
194.1565 +
194.1566 +        output += sizeof(cmsUInt16Number);
194.1567 +    }
194.1568 +
194.1569 +    if (!ExtraFirst) {
194.1570 +        output += Extra * sizeof(cmsUInt16Number);
194.1571 +    }
194.1572 +
194.1573 +    if (Extra == 0 && SwapFirst) {
194.1574 +
194.1575 +        memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsUInt16Number));
194.1576 +        *swap1 = v;
194.1577 +    }
194.1578 +
194.1579 +
194.1580 +    return output;
194.1581  }
194.1582  
194.1583  
194.1584  static
194.1585 -LPBYTE PackNWords(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1586 +cmsUInt8Number* PackPlanarBytes(register _cmsTRANSFORM* info,
194.1587 +                                register cmsUInt16Number wOut[],
194.1588 +                                register cmsUInt8Number* output,
194.1589 +                                register cmsUInt32Number Stride)
194.1590  {
194.1591 -       int nChan  = T_CHANNELS(info -> OutputFormat);
194.1592 -       register int i;
194.1593 -
194.1594 -       for (i=0; i < nChan; i++) {
194.1595 -              *(LPWORD) output = wOut[i];
194.1596 -              output += sizeof(WORD);
194.1597 -       }
194.1598 -
194.1599 -       return output + T_EXTRA(info ->OutputFormat) * sizeof(WORD);
194.1600 +    int nChan = T_CHANNELS(info -> OutputFormat);
194.1601 +    int DoSwap = T_DOSWAP(info ->OutputFormat);
194.1602 +    int Reverse= T_FLAVOR(info ->OutputFormat);
194.1603 +    int i;
194.1604 +    cmsUInt8Number* Init = output;
194.1605 +
194.1606 +    for (i=0; i < nChan; i++) {
194.1607 +
194.1608 +        int index = DoSwap ? (nChan - i - 1) : i;
194.1609 +        cmsUInt8Number v = FROM_16_TO_8(wOut[index]);
194.1610 +
194.1611 +        *(cmsUInt8Number*)  output = (cmsUInt8Number) (Reverse ? REVERSE_FLAVOR_8(v) : v);
194.1612 +        output += Stride;
194.1613 +    }
194.1614 +
194.1615 +    return (Init + 1);
194.1616  }
194.1617  
194.1618 +
194.1619  static
194.1620 -LPBYTE PackNWordsSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1621 +cmsUInt8Number* PackPlanarWords(register _cmsTRANSFORM* info,
194.1622 +                                register cmsUInt16Number wOut[],
194.1623 +                                register cmsUInt8Number* output,
194.1624 +                                register cmsUInt32Number Stride)
194.1625  {
194.1626 -       int nChan  = T_CHANNELS(info -> OutputFormat);
194.1627 -       register int i;
194.1628 -
194.1629 -       for (i=nChan-1; i >= 0; --i) {
194.1630 -              *(LPWORD) output = wOut[i];
194.1631 -              output += sizeof(WORD);
194.1632 -       }
194.1633 -
194.1634 -       return output + T_EXTRA(info ->OutputFormat) * sizeof(WORD);
194.1635 +    int nChan = T_CHANNELS(info -> OutputFormat);
194.1636 +    int DoSwap = T_DOSWAP(info ->OutputFormat);
194.1637 +    int Reverse= T_FLAVOR(info ->OutputFormat);
194.1638 +    int SwapEndian = T_ENDIAN16(info -> OutputFormat);
194.1639 +    int i;
194.1640 +    cmsUInt8Number* Init = output;
194.1641 +    cmsUInt16Number v;
194.1642 +
194.1643 +    if (DoSwap) {
194.1644 +        output += T_EXTRA(info -> OutputFormat) * Stride * sizeof(cmsUInt16Number);
194.1645 +    }
194.1646 +
194.1647 +    for (i=0; i < nChan; i++) {
194.1648 +
194.1649 +        int index = DoSwap ? (nChan - i - 1) : i;
194.1650 +
194.1651 +        v = wOut[index];
194.1652 +
194.1653 +        if (SwapEndian)
194.1654 +            v = CHANGE_ENDIAN(v);
194.1655 +
194.1656 +        if (Reverse)
194.1657 +            v =  REVERSE_FLAVOR_16(v);
194.1658 +
194.1659 +        *(cmsUInt16Number*) output = v;
194.1660 +        output += (Stride * sizeof(cmsUInt16Number));
194.1661 +    }
194.1662 +
194.1663 +    return (Init + sizeof(cmsUInt16Number));
194.1664  }
194.1665  
194.1666 -
194.1667 +// CMYKcm (unrolled for speed)
194.1668  
194.1669  static
194.1670 -LPBYTE PackNWordsBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1671 +cmsUInt8Number* Pack6Bytes(register _cmsTRANSFORM* info,
194.1672 +                           register cmsUInt16Number wOut[],
194.1673 +                           register cmsUInt8Number* output,
194.1674 +                           register cmsUInt32Number Stride)
194.1675  {
194.1676 -       int nChan  = T_CHANNELS(info -> OutputFormat);
194.1677 -       register int i;
194.1678 -
194.1679 -       for (i=0; i < nChan; i++) {
194.1680 -              *(LPWORD) output = CHANGE_ENDIAN(wOut[i]);
194.1681 -              output += sizeof(WORD);
194.1682 -       }
194.1683 -
194.1684 -       return output + T_EXTRA(info ->OutputFormat) * sizeof(WORD);
194.1685 +    *output++ = FROM_16_TO_8(wOut[0]);
194.1686 +    *output++ = FROM_16_TO_8(wOut[1]);
194.1687 +    *output++ = FROM_16_TO_8(wOut[2]);
194.1688 +    *output++ = FROM_16_TO_8(wOut[3]);
194.1689 +    *output++ = FROM_16_TO_8(wOut[4]);
194.1690 +    *output++ = FROM_16_TO_8(wOut[5]);
194.1691 +
194.1692 +    return output;
194.1693  }
194.1694  
194.1695 +// KCMYcm
194.1696  
194.1697  static
194.1698 -LPBYTE PackNWordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1699 +cmsUInt8Number* Pack6BytesSwap(register _cmsTRANSFORM* info,
194.1700 +                               register cmsUInt16Number wOut[],
194.1701 +                               register cmsUInt8Number* output,
194.1702 +                               register cmsUInt32Number Stride)
194.1703  {
194.1704 -       int nChan  = T_CHANNELS(info -> OutputFormat);
194.1705 -       register int i;
194.1706 -
194.1707 -       for (i=nChan-1; i >= 0; --i) {
194.1708 -              *(LPWORD) output = CHANGE_ENDIAN(wOut[i]);
194.1709 -              output += sizeof(WORD);
194.1710 -       }
194.1711 -
194.1712 -       return output + T_EXTRA(info ->OutputFormat) * sizeof(WORD);
194.1713 -}
194.1714 -
194.1715 -
194.1716 -static
194.1717 -LPBYTE PackPlanarBytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1718 -{
194.1719 -       int nChan = T_CHANNELS(info -> OutputFormat);
194.1720 -       register int i;
194.1721 -       LPBYTE Init = output;
194.1722 -
194.1723 -       for (i=0; i < nChan; i++) {
194.1724 -
194.1725 -              *(LPBYTE) output = RGB_16_TO_8(wOut[i]);
194.1726 -              output += info -> StrideOut;
194.1727 -       }
194.1728 -
194.1729 -       return (Init + 1);
194.1730 -}
194.1731 -
194.1732 -
194.1733 -static
194.1734 -LPBYTE PackPlanarWords(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1735 -{
194.1736 -       int nChan = T_CHANNELS(info -> OutputFormat);
194.1737 -       register int i;
194.1738 -       LPBYTE Init = output;
194.1739 -
194.1740 -       for (i=0; i < nChan; i++) {
194.1741 -
194.1742 -              *(LPWORD) output = wOut[i];
194.1743 -              output += (info -> StrideOut * sizeof(WORD));
194.1744 -       }
194.1745 -
194.1746 -       return (Init + 2);
194.1747 -}
194.1748 -
194.1749 -
194.1750 -// CMYKcm (unrolled for speed)
194.1751 -
194.1752 -static
194.1753 -LPBYTE Pack6Bytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1754 -{
194.1755 -         *output++ = RGB_16_TO_8(wOut[0]);
194.1756 -         *output++ = RGB_16_TO_8(wOut[1]);
194.1757 -         *output++ = RGB_16_TO_8(wOut[2]);
194.1758 -         *output++ = RGB_16_TO_8(wOut[3]);
194.1759 -         *output++ = RGB_16_TO_8(wOut[4]);
194.1760 -         *output++ = RGB_16_TO_8(wOut[5]);
194.1761 -
194.1762 -         return output;
194.1763 -}
194.1764 -
194.1765 -// KCMYcm
194.1766 -
194.1767 -static
194.1768 -LPBYTE Pack6BytesSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1769 -{
194.1770 -       *output++ = RGB_16_TO_8(wOut[3]);
194.1771 -       *output++ = RGB_16_TO_8(wOut[0]);
194.1772 -       *output++ = RGB_16_TO_8(wOut[1]);
194.1773 -       *output++ = RGB_16_TO_8(wOut[2]);
194.1774 -       *output++ = RGB_16_TO_8(wOut[4]);
194.1775 -       *output++ = RGB_16_TO_8(wOut[5]);
194.1776 -
194.1777 -       return output;
194.1778 +    *output++ = FROM_16_TO_8(wOut[5]);
194.1779 +    *output++ = FROM_16_TO_8(wOut[4]);
194.1780 +    *output++ = FROM_16_TO_8(wOut[3]);
194.1781 +    *output++ = FROM_16_TO_8(wOut[2]);
194.1782 +    *output++ = FROM_16_TO_8(wOut[1]);
194.1783 +    *output++ = FROM_16_TO_8(wOut[0]);
194.1784 +
194.1785 +    return output;
194.1786  }
194.1787  
194.1788  // CMYKcm
194.1789  static
194.1790 -LPBYTE Pack6Words(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1791 +cmsUInt8Number* Pack6Words(register _cmsTRANSFORM* info,
194.1792 +                           register cmsUInt16Number wOut[],
194.1793 +                           register cmsUInt8Number* output,
194.1794 +                           register cmsUInt32Number Stride)
194.1795  {
194.1796 -       *(LPWORD) output = wOut[0];
194.1797 -       output+= 2;
194.1798 -       *(LPWORD) output = wOut[1];
194.1799 -       output+= 2;
194.1800 -       *(LPWORD) output = wOut[2];
194.1801 -       output+= 2;
194.1802 -       *(LPWORD) output = wOut[3];
194.1803 -       output+= 2;
194.1804 -       *(LPWORD) output = wOut[4];
194.1805 -       output+= 2;
194.1806 -       *(LPWORD) output = wOut[5];
194.1807 -       output+= 2;
194.1808 -
194.1809 -       return output;
194.1810 +    *(cmsUInt16Number*) output = wOut[0];
194.1811 +    output+= 2;
194.1812 +    *(cmsUInt16Number*) output = wOut[1];
194.1813 +    output+= 2;
194.1814 +    *(cmsUInt16Number*) output = wOut[2];
194.1815 +    output+= 2;
194.1816 +    *(cmsUInt16Number*) output = wOut[3];
194.1817 +    output+= 2;
194.1818 +    *(cmsUInt16Number*) output = wOut[4];
194.1819 +    output+= 2;
194.1820 +    *(cmsUInt16Number*) output = wOut[5];
194.1821 +    output+= 2;
194.1822 +
194.1823 +    return output;
194.1824  }
194.1825  
194.1826  // KCMYcm
194.1827  static
194.1828 -LPBYTE Pack6WordsSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1829 +cmsUInt8Number* Pack6WordsSwap(register _cmsTRANSFORM* info,
194.1830 +                               register cmsUInt16Number wOut[],
194.1831 +                               register cmsUInt8Number* output,
194.1832 +                               register cmsUInt32Number Stride)
194.1833  {
194.1834 -       *(LPWORD) output = wOut[3];
194.1835 -       output+= 2;
194.1836 -       *(LPWORD) output = wOut[0];
194.1837 -       output+= 2;
194.1838 -       *(LPWORD) output = wOut[1];
194.1839 -       output+= 2;
194.1840 -       *(LPWORD) output = wOut[2];
194.1841 -       output+= 2;
194.1842 -       *(LPWORD) output = wOut[4];
194.1843 -       output+= 2;
194.1844 -       *(LPWORD) output = wOut[5];
194.1845 -       output+= 2;
194.1846 -
194.1847 -       return output;
194.1848 +    *(cmsUInt16Number*) output = wOut[5];
194.1849 +    output+= 2;
194.1850 +    *(cmsUInt16Number*) output = wOut[4];
194.1851 +    output+= 2;
194.1852 +    *(cmsUInt16Number*) output = wOut[3];
194.1853 +    output+= 2;
194.1854 +    *(cmsUInt16Number*) output = wOut[2];
194.1855 +    output+= 2;
194.1856 +    *(cmsUInt16Number*) output = wOut[1];
194.1857 +    output+= 2;
194.1858 +    *(cmsUInt16Number*) output = wOut[0];
194.1859 +    output+= 2;
194.1860 +
194.1861 +    return output;
194.1862  }
194.1863  
194.1864 -// CMYKcm
194.1865 +
194.1866  static
194.1867 -LPBYTE Pack6WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1868 +cmsUInt8Number* Pack4Bytes(register _cmsTRANSFORM* info,
194.1869 +                           register cmsUInt16Number wOut[],
194.1870 +                           register cmsUInt8Number* output,
194.1871 +                           register cmsUInt32Number Stride)
194.1872  {
194.1873 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.1874 -       output+= 2;
194.1875 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[1]);
194.1876 -       output+= 2;
194.1877 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[2]);
194.1878 -       output+= 2;
194.1879 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[3]);
194.1880 -       output+= 2;
194.1881 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[4]);
194.1882 -       output+= 2;
194.1883 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[5]);
194.1884 -       output+= 2;
194.1885 -
194.1886 -       return output;
194.1887 +    *output++ = FROM_16_TO_8(wOut[0]);
194.1888 +    *output++ = FROM_16_TO_8(wOut[1]);
194.1889 +    *output++ = FROM_16_TO_8(wOut[2]);
194.1890 +    *output++ = FROM_16_TO_8(wOut[3]);
194.1891 +
194.1892 +    return output;
194.1893  }
194.1894  
194.1895 -// KCMYcm
194.1896  static
194.1897 -LPBYTE Pack6WordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1898 +cmsUInt8Number* Pack4BytesReverse(register _cmsTRANSFORM* info,
194.1899 +                                  register cmsUInt16Number wOut[],
194.1900 +                                  register cmsUInt8Number* output,
194.1901 +                                  register cmsUInt32Number Stride)
194.1902  {
194.1903 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[3]);
194.1904 -       output+= 2;
194.1905 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.1906 -       output+= 2;
194.1907 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[1]);
194.1908 -       output+= 2;
194.1909 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[2]);
194.1910 -       output+= 2;
194.1911 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[4]);
194.1912 -       output+= 2;
194.1913 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[5]);
194.1914 -       output+= 2;
194.1915 -
194.1916 -       return output;
194.1917 +    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[0]));
194.1918 +    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[1]));
194.1919 +    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[2]));
194.1920 +    *output++ = REVERSE_FLAVOR_8(FROM_16_TO_8(wOut[3]));
194.1921 +
194.1922 +    return output;
194.1923  }
194.1924  
194.1925  
194.1926  static
194.1927 -LPBYTE Pack4Bytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1928 +cmsUInt8Number* Pack4BytesSwapFirst(register _cmsTRANSFORM* info,
194.1929 +                                    register cmsUInt16Number wOut[],
194.1930 +                                    register cmsUInt8Number* output,
194.1931 +                                    register cmsUInt32Number Stride)
194.1932  {
194.1933 -         *output++ = RGB_16_TO_8(wOut[0]);
194.1934 -         *output++ = RGB_16_TO_8(wOut[1]);
194.1935 -         *output++ = RGB_16_TO_8(wOut[2]);
194.1936 -         *output++ = RGB_16_TO_8(wOut[3]);
194.1937 -
194.1938 -         return output;
194.1939 +    *output++ = FROM_16_TO_8(wOut[3]);
194.1940 +    *output++ = FROM_16_TO_8(wOut[0]);
194.1941 +    *output++ = FROM_16_TO_8(wOut[1]);
194.1942 +    *output++ = FROM_16_TO_8(wOut[2]);
194.1943 +
194.1944 +    return output;
194.1945  }
194.1946  
194.1947 +// ABGR
194.1948  static
194.1949 -LPBYTE Pack4BytesReverse(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1950 +cmsUInt8Number* Pack4BytesSwap(register _cmsTRANSFORM* info,
194.1951 +                               register cmsUInt16Number wOut[],
194.1952 +                               register cmsUInt8Number* output,
194.1953 +                               register cmsUInt32Number Stride)
194.1954  {
194.1955 -         *output++ = REVERSE_FLAVOR_8(RGB_16_TO_8(wOut[0]));
194.1956 -         *output++ = REVERSE_FLAVOR_8(RGB_16_TO_8(wOut[1]));
194.1957 -         *output++ = REVERSE_FLAVOR_8(RGB_16_TO_8(wOut[2]));
194.1958 -         *output++ = REVERSE_FLAVOR_8(RGB_16_TO_8(wOut[3]));
194.1959 -
194.1960 -         return output;
194.1961 +    *output++ = FROM_16_TO_8(wOut[3]);
194.1962 +    *output++ = FROM_16_TO_8(wOut[2]);
194.1963 +    *output++ = FROM_16_TO_8(wOut[1]);
194.1964 +    *output++ = FROM_16_TO_8(wOut[0]);
194.1965 +
194.1966 +    return output;
194.1967  }
194.1968  
194.1969 -
194.1970  static
194.1971 -LPBYTE Pack4BytesSwapFirst(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.1972 +cmsUInt8Number* Pack4BytesSwapSwapFirst(register _cmsTRANSFORM* info,
194.1973 +                                        register cmsUInt16Number wOut[],
194.1974 +                                        register cmsUInt8Number* output,
194.1975 +                                        register cmsUInt32Number Stride)
194.1976  {
194.1977 -         *output++ = RGB_16_TO_8(wOut[3]);
194.1978 -         *output++ = RGB_16_TO_8(wOut[0]);
194.1979 -         *output++ = RGB_16_TO_8(wOut[1]);
194.1980 -         *output++ = RGB_16_TO_8(wOut[2]);
194.1981 -
194.1982 -         return output;
194.1983 +    *output++ = FROM_16_TO_8(wOut[2]);
194.1984 +    *output++ = FROM_16_TO_8(wOut[1]);
194.1985 +    *output++ = FROM_16_TO_8(wOut[0]);
194.1986 +    *output++ = FROM_16_TO_8(wOut[3]);
194.1987 +
194.1988 +    return output;
194.1989  }
194.1990  
194.1991 +static
194.1992 +cmsUInt8Number* Pack4Words(register _cmsTRANSFORM* info,
194.1993 +                           register cmsUInt16Number wOut[],
194.1994 +                           register cmsUInt8Number* output,
194.1995 +                           register cmsUInt32Number Stride)
194.1996 +{
194.1997 +    *(cmsUInt16Number*) output = wOut[0];
194.1998 +    output+= 2;
194.1999 +    *(cmsUInt16Number*) output = wOut[1];
194.2000 +    output+= 2;
194.2001 +    *(cmsUInt16Number*) output = wOut[2];
194.2002 +    output+= 2;
194.2003 +    *(cmsUInt16Number*) output = wOut[3];
194.2004 +    output+= 2;
194.2005 +
194.2006 +    return output;
194.2007 +}
194.2008 +
194.2009 +static
194.2010 +cmsUInt8Number* Pack4WordsReverse(register _cmsTRANSFORM* info,
194.2011 +                                  register cmsUInt16Number wOut[],
194.2012 +                                  register cmsUInt8Number* output,
194.2013 +                                  register cmsUInt32Number Stride)
194.2014 +{
194.2015 +    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
194.2016 +    output+= 2;
194.2017 +    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[1]);
194.2018 +    output+= 2;
194.2019 +    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[2]);
194.2020 +    output+= 2;
194.2021 +    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[3]);
194.2022 +    output+= 2;
194.2023 +
194.2024 +    return output;
194.2025 +}
194.2026  
194.2027  // ABGR
194.2028 -
194.2029  static
194.2030 -LPBYTE Pack4BytesSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2031 +cmsUInt8Number* Pack4WordsSwap(register _cmsTRANSFORM* info,
194.2032 +                               register cmsUInt16Number wOut[],
194.2033 +                               register cmsUInt8Number* output,
194.2034 +                               register cmsUInt32Number Stride)
194.2035  {
194.2036 -       *output++ = RGB_16_TO_8(wOut[3]);
194.2037 -       *output++ = RGB_16_TO_8(wOut[2]);
194.2038 -       *output++ = RGB_16_TO_8(wOut[1]);
194.2039 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2040 -
194.2041 -       return output;
194.2042 -}
194.2043 -
194.2044 -
194.2045 -static
194.2046 -LPBYTE Pack4BytesSwapSwapFirst(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2047 -{
194.2048 -       *output++ = RGB_16_TO_8(wOut[2]);
194.2049 -       *output++ = RGB_16_TO_8(wOut[1]);
194.2050 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2051 -       *output++ = RGB_16_TO_8(wOut[3]);
194.2052 -
194.2053 -       return output;
194.2054 -}
194.2055 -
194.2056 -
194.2057 -static
194.2058 -LPBYTE Pack4Words(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2059 -{
194.2060 -       *(LPWORD) output = wOut[0];
194.2061 -       output+= 2;
194.2062 -       *(LPWORD) output = wOut[1];
194.2063 -       output+= 2;
194.2064 -       *(LPWORD) output = wOut[2];
194.2065 -       output+= 2;
194.2066 -       *(LPWORD) output = wOut[3];
194.2067 -       output+= 2;
194.2068 -
194.2069 -       return output;
194.2070 -}
194.2071 -
194.2072 -
194.2073 -static
194.2074 -LPBYTE Pack4WordsReverse(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2075 -{
194.2076 -       *(LPWORD) output = REVERSE_FLAVOR_16(wOut[0]);
194.2077 -       output+= 2;
194.2078 -       *(LPWORD) output = REVERSE_FLAVOR_16(wOut[1]);
194.2079 -       output+= 2;
194.2080 -       *(LPWORD) output = REVERSE_FLAVOR_16(wOut[2]);
194.2081 -       output+= 2;
194.2082 -       *(LPWORD) output = REVERSE_FLAVOR_16(wOut[3]);
194.2083 -       output+= 2;
194.2084 -
194.2085 -       return output;
194.2086 -}
194.2087 -
194.2088 -// ABGR
194.2089 -
194.2090 -static
194.2091 -LPBYTE Pack4WordsSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2092 -{
194.2093 -       *(LPWORD) output = wOut[3];
194.2094 -       output+= 2;
194.2095 -       *(LPWORD) output = wOut[2];
194.2096 -       output+= 2;
194.2097 -       *(LPWORD) output = wOut[1];
194.2098 -       output+= 2;
194.2099 -       *(LPWORD) output = wOut[0];
194.2100 -       output+= 2;
194.2101 -
194.2102 -       return output;
194.2103 +    *(cmsUInt16Number*) output = wOut[3];
194.2104 +    output+= 2;
194.2105 +    *(cmsUInt16Number*) output = wOut[2];
194.2106 +    output+= 2;
194.2107 +    *(cmsUInt16Number*) output = wOut[1];
194.2108 +    output+= 2;
194.2109 +    *(cmsUInt16Number*) output = wOut[0];
194.2110 +    output+= 2;
194.2111 +
194.2112 +    return output;
194.2113  }
194.2114  
194.2115  // CMYK
194.2116  static
194.2117 -LPBYTE Pack4WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2118 +cmsUInt8Number* Pack4WordsBigEndian(register _cmsTRANSFORM* info,
194.2119 +                                    register cmsUInt16Number wOut[],
194.2120 +                                    register cmsUInt8Number* output,
194.2121 +                                    register cmsUInt32Number Stride)
194.2122  {
194.2123 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.2124 -       output+= 2;
194.2125 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[1]);
194.2126 -       output+= 2;
194.2127 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[2]);
194.2128 -       output+= 2;
194.2129 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[3]);
194.2130 -       output+= 2;
194.2131 -
194.2132 -       return output;
194.2133 +    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
194.2134 +    output+= 2;
194.2135 +    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
194.2136 +    output+= 2;
194.2137 +    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
194.2138 +    output+= 2;
194.2139 +    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[3]);
194.2140 +    output+= 2;
194.2141 +
194.2142 +    return output;
194.2143  }
194.2144  
194.2145  
194.2146  static
194.2147 -LPBYTE Pack4WordsBigEndianReverse(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2148 +cmsUInt8Number* PackLabV2_8(register _cmsTRANSFORM* info,
194.2149 +                            register cmsUInt16Number wOut[],
194.2150 +                            register cmsUInt8Number* output,
194.2151 +                            register cmsUInt32Number Stride)
194.2152  {
194.2153 -       *(LPWORD) output = CHANGE_ENDIAN(REVERSE_FLAVOR_16(wOut[0]));
194.2154 -       output+= 2;
194.2155 -       *(LPWORD) output = CHANGE_ENDIAN(REVERSE_FLAVOR_16(wOut[1]));
194.2156 -       output+= 2;
194.2157 -       *(LPWORD) output = CHANGE_ENDIAN(REVERSE_FLAVOR_16(wOut[2]));
194.2158 -       output+= 2;
194.2159 -       *(LPWORD) output = CHANGE_ENDIAN(REVERSE_FLAVOR_16(wOut[3]));
194.2160 -       output+= 2;
194.2161 -
194.2162 -       return output;
194.2163 +    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
194.2164 +    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
194.2165 +    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
194.2166 +
194.2167 +    return output;
194.2168  }
194.2169  
194.2170 -// KYMC
194.2171 -
194.2172  static
194.2173 -LPBYTE Pack4WordsSwapBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2174 +cmsUInt8Number* PackALabV2_8(register _cmsTRANSFORM* info,
194.2175 +                             register cmsUInt16Number wOut[],
194.2176 +                             register cmsUInt8Number* output,
194.2177 +                             register cmsUInt32Number Stride)
194.2178  {
194.2179 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[3]);
194.2180 -       output+= 2;
194.2181 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[2]);
194.2182 -       output+= 2;
194.2183 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[1]);
194.2184 -       output+= 2;
194.2185 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.2186 -       output+= 2;
194.2187 -
194.2188 -       return output;
194.2189 +    output++;
194.2190 +    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[0]));
194.2191 +    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[1]));
194.2192 +    *output++ = FROM_16_TO_8(FomLabV4ToLabV2(wOut[2]));
194.2193 +
194.2194 +    return output;
194.2195  }
194.2196  
194.2197  static
194.2198 -LPBYTE Pack3Bytes(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2199 +cmsUInt8Number* PackLabV2_16(register _cmsTRANSFORM* info,
194.2200 +                             register cmsUInt16Number wOut[],
194.2201 +                             register cmsUInt8Number* output,
194.2202 +                             register cmsUInt32Number Stride)
194.2203  {
194.2204 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2205 -       *output++ = RGB_16_TO_8(wOut[1]);
194.2206 -       *output++ = RGB_16_TO_8(wOut[2]);
194.2207 -
194.2208 -       return output;
194.2209 +    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[0]);
194.2210 +    output += 2;
194.2211 +    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[1]);
194.2212 +    output += 2;
194.2213 +    *(cmsUInt16Number*) output = FomLabV4ToLabV2(wOut[2]);
194.2214 +    output += 2;
194.2215 +
194.2216 +    return output;
194.2217  }
194.2218  
194.2219  static
194.2220 -LPBYTE Pack3BytesLab(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2221 +cmsUInt8Number* Pack3Bytes(register _cmsTRANSFORM* info,
194.2222 +                           register cmsUInt16Number wOut[],
194.2223 +                           register cmsUInt8Number* output,
194.2224 +                           register cmsUInt32Number Stride)
194.2225  {
194.2226 -       *output++ = (BYTE) (wOut[0] >> 8);
194.2227 -       *output++ = (BYTE) (wOut[1] >> 8);
194.2228 -       *output++ = (BYTE) (wOut[2] >> 8);
194.2229 -
194.2230 -       return output;
194.2231 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2232 +    *output++ = FROM_16_TO_8(wOut[1]);
194.2233 +    *output++ = FROM_16_TO_8(wOut[2]);
194.2234 +
194.2235 +    return output;
194.2236  }
194.2237  
194.2238 -
194.2239  static
194.2240 -LPBYTE Pack3BytesSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2241 +cmsUInt8Number* Pack3BytesOptimized(register _cmsTRANSFORM* info,
194.2242 +                                    register cmsUInt16Number wOut[],
194.2243 +                                    register cmsUInt8Number* output,
194.2244 +                                    register cmsUInt32Number Stride)
194.2245  {
194.2246 -       *output++ = RGB_16_TO_8(wOut[2]);
194.2247 -       *output++ = RGB_16_TO_8(wOut[1]);
194.2248 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2249 -
194.2250 -       return output;
194.2251 +    *output++ = (wOut[0] & 0xFF);
194.2252 +    *output++ = (wOut[1] & 0xFF);
194.2253 +    *output++ = (wOut[2] & 0xFF);
194.2254 +
194.2255 +    return output;
194.2256  }
194.2257  
194.2258 -
194.2259  static
194.2260 -LPBYTE Pack3Words(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2261 +cmsUInt8Number* Pack3BytesSwap(register _cmsTRANSFORM* info,
194.2262 +                               register cmsUInt16Number wOut[],
194.2263 +                               register cmsUInt8Number* output,
194.2264 +                               register cmsUInt32Number Stride)
194.2265  {
194.2266 -       *(LPWORD) output = wOut[0];
194.2267 -       output+= 2;
194.2268 -       *(LPWORD) output = wOut[1];
194.2269 -       output+= 2;
194.2270 -       *(LPWORD) output = wOut[2];
194.2271 -       output+= 2;
194.2272 -
194.2273 -       return output;
194.2274 +    *output++ = FROM_16_TO_8(wOut[2]);
194.2275 +    *output++ = FROM_16_TO_8(wOut[1]);
194.2276 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2277 +
194.2278 +    return output;
194.2279  }
194.2280  
194.2281  static
194.2282 -LPBYTE Pack3WordsSwap(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2283 +cmsUInt8Number* Pack3BytesSwapOptimized(register _cmsTRANSFORM* info,
194.2284 +                                        register cmsUInt16Number wOut[],
194.2285 +                                        register cmsUInt8Number* output,
194.2286 +                                        register cmsUInt32Number Stride)
194.2287  {
194.2288 -       *(LPWORD) output = wOut[2];
194.2289 -       output+= 2;
194.2290 -       *(LPWORD) output = wOut[1];
194.2291 -       output+= 2;
194.2292 -       *(LPWORD) output = wOut[0];
194.2293 -       output+= 2;
194.2294 -
194.2295 -       return output;
194.2296 +    *output++ = (wOut[2] & 0xFF);
194.2297 +    *output++ = (wOut[1] & 0xFF);
194.2298 +    *output++ = (wOut[0] & 0xFF);
194.2299 +
194.2300 +    return output;
194.2301  }
194.2302  
194.2303 +
194.2304  static
194.2305 -LPBYTE Pack3WordsBigEndian(register _LPcmsTRANSFORM info, register WORD wOut[], register LPBYTE output)
194.2306 +cmsUInt8Number* Pack3Words(register _cmsTRANSFORM* info,
194.2307 +                           register cmsUInt16Number wOut[],
194.2308 +                           register cmsUInt8Number* output,
194.2309 +                           register cmsUInt32Number Stride)
194.2310  {
194.2311 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.2312 -       output+= 2;
194.2313 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[1]);
194.2314 -       output+= 2;
194.2315 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[2]);
194.2316 -       output+= 2;
194.2317 -
194.2318 -       return output;
194.2319 +    *(cmsUInt16Number*) output = wOut[0];
194.2320 +    output+= 2;
194.2321 +    *(cmsUInt16Number*) output = wOut[1];
194.2322 +    output+= 2;
194.2323 +    *(cmsUInt16Number*) output = wOut[2];
194.2324 +    output+= 2;
194.2325 +
194.2326 +    return output;
194.2327  }
194.2328  
194.2329 -
194.2330  static
194.2331 -LPBYTE Pack3WordsSwapBigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2332 +cmsUInt8Number* Pack3WordsSwap(register _cmsTRANSFORM* info,
194.2333 +                               register cmsUInt16Number wOut[],
194.2334 +                               register cmsUInt8Number* output,
194.2335 +                               register cmsUInt32Number Stride)
194.2336  {
194.2337 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[2]);
194.2338 -       output+= 2;
194.2339 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[1]);
194.2340 -       output+= 2;
194.2341 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.2342 -       output+= 2;
194.2343 -
194.2344 -       return output;
194.2345 +    *(cmsUInt16Number*) output = wOut[2];
194.2346 +    output+= 2;
194.2347 +    *(cmsUInt16Number*) output = wOut[1];
194.2348 +    output+= 2;
194.2349 +    *(cmsUInt16Number*) output = wOut[0];
194.2350 +    output+= 2;
194.2351 +
194.2352 +    return output;
194.2353  }
194.2354  
194.2355 -
194.2356  static
194.2357 -LPBYTE Pack3BytesAndSkip1(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2358 +cmsUInt8Number* Pack3WordsBigEndian(register _cmsTRANSFORM* info,
194.2359 +                                    register cmsUInt16Number wOut[],
194.2360 +                                    register cmsUInt8Number* output,
194.2361 +                                    register cmsUInt32Number Stride)
194.2362  {
194.2363 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2364 -       *output++ = RGB_16_TO_8(wOut[1]);
194.2365 -       *output++ = RGB_16_TO_8(wOut[2]);
194.2366 -       output++;
194.2367 -
194.2368 -       return output;
194.2369 +    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
194.2370 +    output+= 2;
194.2371 +    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[1]);
194.2372 +    output+= 2;
194.2373 +    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[2]);
194.2374 +    output+= 2;
194.2375 +
194.2376 +    return output;
194.2377  }
194.2378  
194.2379 -
194.2380  static
194.2381 -LPBYTE Pack3BytesAndSkip1SwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2382 +cmsUInt8Number* Pack3BytesAndSkip1(register _cmsTRANSFORM* Info,
194.2383 +                                   register cmsUInt16Number wOut[],
194.2384 +                                   register cmsUInt8Number* output,
194.2385 +                                   register cmsUInt32Number Stride)
194.2386  {
194.2387 -        output++;
194.2388 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2389 -       *output++ = RGB_16_TO_8(wOut[1]);
194.2390 -       *output++ = RGB_16_TO_8(wOut[2]);
194.2391 -
194.2392 -       return output;
194.2393 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2394 +    *output++ = FROM_16_TO_8(wOut[1]);
194.2395 +    *output++ = FROM_16_TO_8(wOut[2]);
194.2396 +    output++;
194.2397 +
194.2398 +    return output;
194.2399  }
194.2400  
194.2401  static
194.2402 -LPBYTE Pack3BytesAndSkip1Swap(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2403 +cmsUInt8Number* Pack3BytesAndSkip1Optimized(register _cmsTRANSFORM* Info,
194.2404 +                                            register cmsUInt16Number wOut[],
194.2405 +                                            register cmsUInt8Number* output,
194.2406 +                                            register cmsUInt32Number Stride)
194.2407  {
194.2408 -        output++;
194.2409 -       *output++ = RGB_16_TO_8(wOut[2]);
194.2410 -       *output++ = RGB_16_TO_8(wOut[1]);
194.2411 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2412 -
194.2413 -       return output;
194.2414 +    *output++ = (wOut[0] & 0xFF);
194.2415 +    *output++ = (wOut[1] & 0xFF);
194.2416 +    *output++ = (wOut[2] & 0xFF);
194.2417 +    output++;
194.2418 +
194.2419 +    return output;
194.2420  }
194.2421  
194.2422  
194.2423  static
194.2424 -LPBYTE Pack3BytesAndSkip1SwapSwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2425 +cmsUInt8Number* Pack3BytesAndSkip1SwapFirst(register _cmsTRANSFORM* Info,
194.2426 +                                            register cmsUInt16Number wOut[],
194.2427 +                                            register cmsUInt8Number* output,
194.2428 +                                            register cmsUInt32Number Stride)
194.2429  {
194.2430 -       *output++ = RGB_16_TO_8(wOut[2]);
194.2431 -       *output++ = RGB_16_TO_8(wOut[1]);
194.2432 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2433 -       output++;
194.2434 -
194.2435 -       return output;
194.2436 +    output++;
194.2437 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2438 +    *output++ = FROM_16_TO_8(wOut[1]);
194.2439 +    *output++ = FROM_16_TO_8(wOut[2]);
194.2440 +
194.2441 +    return output;
194.2442  }
194.2443  
194.2444 -
194.2445  static
194.2446 -LPBYTE Pack3WordsAndSkip1(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2447 +cmsUInt8Number* Pack3BytesAndSkip1SwapFirstOptimized(register _cmsTRANSFORM* Info,
194.2448 +                                                     register cmsUInt16Number wOut[],
194.2449 +                                                     register cmsUInt8Number* output,
194.2450 +                                                     register cmsUInt32Number Stride)
194.2451  {
194.2452 -       *(LPWORD) output = wOut[0];
194.2453 -       output+= 2;
194.2454 -       *(LPWORD) output = wOut[1];
194.2455 -       output+= 2;
194.2456 -       *(LPWORD) output = wOut[2];
194.2457 -       output+= 2;
194.2458 -       output+= 2;
194.2459 -
194.2460 -       return output;
194.2461 +    output++;
194.2462 +    *output++ = (wOut[0] & 0xFF);
194.2463 +    *output++ = (wOut[1] & 0xFF);
194.2464 +    *output++ = (wOut[2] & 0xFF);
194.2465 +
194.2466 +    return output;
194.2467  }
194.2468  
194.2469  static
194.2470 -LPBYTE Pack3WordsAndSkip1Swap(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2471 +cmsUInt8Number* Pack3BytesAndSkip1Swap(register _cmsTRANSFORM* Info,
194.2472 +                                       register cmsUInt16Number wOut[],
194.2473 +                                       register cmsUInt8Number* output,
194.2474 +                                       register cmsUInt32Number Stride)
194.2475  {
194.2476 -       output+= 2;
194.2477 -       *(LPWORD) output = wOut[2];
194.2478 -       output+= 2;
194.2479 -       *(LPWORD) output = wOut[1];
194.2480 -       output+= 2;
194.2481 -       *(LPWORD) output = wOut[0];
194.2482 -       output+= 2;
194.2483 -
194.2484 -
194.2485 -       return output;
194.2486 +    output++;
194.2487 +    *output++ = FROM_16_TO_8(wOut[2]);
194.2488 +    *output++ = FROM_16_TO_8(wOut[1]);
194.2489 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2490 +
194.2491 +    return output;
194.2492  }
194.2493  
194.2494 -
194.2495  static
194.2496 -LPBYTE Pack3WordsAndSkip1SwapSwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2497 +cmsUInt8Number* Pack3BytesAndSkip1SwapOptimized(register _cmsTRANSFORM* Info,
194.2498 +                                                register cmsUInt16Number wOut[],
194.2499 +                                                register cmsUInt8Number* output,
194.2500 +                                                register cmsUInt32Number Stride)
194.2501  {
194.2502 -       *(LPWORD) output = wOut[2];
194.2503 -       output+= 2;
194.2504 -       *(LPWORD) output = wOut[1];
194.2505 -       output+= 2;
194.2506 -       *(LPWORD) output = wOut[0];
194.2507 -       output+= 2;
194.2508 -       output+= 2;
194.2509 -
194.2510 -
194.2511 -       return output;
194.2512 +    output++;
194.2513 +    *output++ = (wOut[2] & 0xFF);
194.2514 +    *output++ = (wOut[1] & 0xFF);
194.2515 +    *output++ = (wOut[0] & 0xFF);
194.2516 +
194.2517 +    return output;
194.2518  }
194.2519  
194.2520  
194.2521  static
194.2522 -LPBYTE Pack3WordsAndSkip1BigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2523 +cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirst(register _cmsTRANSFORM* Info,
194.2524 +                                                register cmsUInt16Number wOut[],
194.2525 +                                                register cmsUInt8Number* output,
194.2526 +                                                register cmsUInt32Number Stride)
194.2527  {
194.2528 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.2529 -       output+= 2;
194.2530 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[1]);
194.2531 -       output+= 2;
194.2532 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[2]);
194.2533 -       output+= 2;
194.2534 -       output+= 2;
194.2535 -
194.2536 -       return output;
194.2537 +    *output++ = FROM_16_TO_8(wOut[2]);
194.2538 +    *output++ = FROM_16_TO_8(wOut[1]);
194.2539 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2540 +    output++;
194.2541 +
194.2542 +    return output;
194.2543  }
194.2544  
194.2545 -
194.2546  static
194.2547 -LPBYTE Pack3WordsAndSkip1SwapBigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2548 +cmsUInt8Number* Pack3BytesAndSkip1SwapSwapFirstOptimized(register _cmsTRANSFORM* Info,
194.2549 +                                                         register cmsUInt16Number wOut[],
194.2550 +                                                         register cmsUInt8Number* output,
194.2551 +                                                         register cmsUInt32Number Stride)
194.2552  {
194.2553 -        output+= 2;
194.2554 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[2]);
194.2555 -       output+= 2;
194.2556 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[1]);
194.2557 -       output+= 2;
194.2558 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.2559 -       output+= 2;
194.2560 -
194.2561 -
194.2562 -       return output;
194.2563 +    *output++ = (wOut[2] & 0xFF);
194.2564 +    *output++ = (wOut[1] & 0xFF);
194.2565 +    *output++ = (wOut[0] & 0xFF);
194.2566 +    output++;
194.2567 +
194.2568 +    return output;
194.2569  }
194.2570  
194.2571 -
194.2572 -
194.2573  static
194.2574 -LPBYTE Pack1Byte(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2575 +cmsUInt8Number* Pack3WordsAndSkip1(register _cmsTRANSFORM* Info,
194.2576 +                                   register cmsUInt16Number wOut[],
194.2577 +                                   register cmsUInt8Number* output,
194.2578 +                                   register cmsUInt32Number Stride)
194.2579  {
194.2580 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2581 -       return output;
194.2582 +    *(cmsUInt16Number*) output = wOut[0];
194.2583 +    output+= 2;
194.2584 +    *(cmsUInt16Number*) output = wOut[1];
194.2585 +    output+= 2;
194.2586 +    *(cmsUInt16Number*) output = wOut[2];
194.2587 +    output+= 2;
194.2588 +    output+= 2;
194.2589 +
194.2590 +    return output;
194.2591  }
194.2592  
194.2593 -
194.2594  static
194.2595 -LPBYTE Pack1ByteAndSkip1(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2596 +cmsUInt8Number* Pack3WordsAndSkip1Swap(register _cmsTRANSFORM* Info,
194.2597 +                                       register cmsUInt16Number wOut[],
194.2598 +                                       register cmsUInt8Number* output,
194.2599 +                                       register cmsUInt32Number Stride)
194.2600  {
194.2601 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2602 -       output++;
194.2603 -       return output;
194.2604 +    output+= 2;
194.2605 +    *(cmsUInt16Number*) output = wOut[2];
194.2606 +    output+= 2;
194.2607 +    *(cmsUInt16Number*) output = wOut[1];
194.2608 +    output+= 2;
194.2609 +    *(cmsUInt16Number*) output = wOut[0];
194.2610 +    output+= 2;
194.2611 +
194.2612 +    return output;
194.2613  }
194.2614  
194.2615  
194.2616  static
194.2617 -LPBYTE Pack1ByteAndSkip1SwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2618 +cmsUInt8Number* Pack3WordsAndSkip1SwapFirst(register _cmsTRANSFORM* Info,
194.2619 +                                            register cmsUInt16Number wOut[],
194.2620 +                                            register cmsUInt8Number* output,
194.2621 +                                            register cmsUInt32Number Stride)
194.2622  {
194.2623 -       output++;
194.2624 -       *output++ = RGB_16_TO_8(wOut[0]);
194.2625 -
194.2626 -       return output;
194.2627 +    output+= 2;
194.2628 +    *(cmsUInt16Number*) output = wOut[0];
194.2629 +    output+= 2;
194.2630 +    *(cmsUInt16Number*) output = wOut[1];
194.2631 +    output+= 2;
194.2632 +    *(cmsUInt16Number*) output = wOut[2];
194.2633 +    output+= 2;
194.2634 +
194.2635 +    return output;
194.2636  }
194.2637  
194.2638 +
194.2639  static
194.2640 -LPBYTE Pack1Word(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2641 +cmsUInt8Number* Pack3WordsAndSkip1SwapSwapFirst(register _cmsTRANSFORM* Info,
194.2642 +                                                register cmsUInt16Number wOut[],
194.2643 +                                                register cmsUInt8Number* output,
194.2644 +                                                register cmsUInt32Number Stride)
194.2645  {
194.2646 -       *(LPWORD) output = wOut[0];
194.2647 -       output+= 2;
194.2648 -
194.2649 -       return output;
194.2650 +    *(cmsUInt16Number*) output = wOut[2];
194.2651 +    output+= 2;
194.2652 +    *(cmsUInt16Number*) output = wOut[1];
194.2653 +    output+= 2;
194.2654 +    *(cmsUInt16Number*) output = wOut[0];
194.2655 +    output+= 2;
194.2656 +    output+= 2;
194.2657 +
194.2658 +    return output;
194.2659  }
194.2660  
194.2661 +
194.2662 +
194.2663  static
194.2664 -LPBYTE Pack1WordBigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2665 +cmsUInt8Number* Pack1Byte(register _cmsTRANSFORM* Info,
194.2666 +                          register cmsUInt16Number wOut[],
194.2667 +                          register cmsUInt8Number* output,
194.2668 +                          register cmsUInt32Number Stride)
194.2669  {
194.2670 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.2671 -       output+= 2;
194.2672 -
194.2673 -       return output;
194.2674 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2675 +    return output;
194.2676  }
194.2677  
194.2678  
194.2679  static
194.2680 -LPBYTE Pack1WordAndSkip1(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2681 +cmsUInt8Number* Pack1ByteReversed(register _cmsTRANSFORM* Info,
194.2682 +                                  register cmsUInt16Number wOut[],
194.2683 +                                  register cmsUInt8Number* output,
194.2684 +                                  register cmsUInt32Number Stride)
194.2685  {
194.2686 -       *(LPWORD) output = wOut[0];
194.2687 -       output+= 4;
194.2688 -
194.2689 -       return output;
194.2690 +    *output++ = FROM_16_TO_8(REVERSE_FLAVOR_16(wOut[0]));
194.2691 +    return output;
194.2692  }
194.2693  
194.2694 +
194.2695  static
194.2696 -LPBYTE Pack1WordAndSkip1SwapFirst(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2697 +cmsUInt8Number* Pack1ByteSkip1(register _cmsTRANSFORM* Info,
194.2698 +                               register cmsUInt16Number wOut[],
194.2699 +                               register cmsUInt8Number* output,
194.2700 +                               register cmsUInt32Number Stride)
194.2701  {
194.2702 -       output += 2;
194.2703 -       *(LPWORD) output = wOut[0];
194.2704 -       output+= 2;
194.2705 -
194.2706 -       return output;
194.2707 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2708 +    output++;
194.2709 +    return output;
194.2710  }
194.2711  
194.2712  
194.2713  static
194.2714 -LPBYTE Pack1WordAndSkip1BigEndian(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2715 +cmsUInt8Number* Pack1ByteSkip1SwapFirst(register _cmsTRANSFORM* Info,
194.2716 +                                        register cmsUInt16Number wOut[],
194.2717 +                                        register cmsUInt8Number* output,
194.2718 +                                        register cmsUInt32Number Stride)
194.2719  {
194.2720 -       *(LPWORD) output = CHANGE_ENDIAN(wOut[0]);
194.2721 -       output+= 4;
194.2722 -
194.2723 -       return output;
194.2724 +    output++;
194.2725 +    *output++ = FROM_16_TO_8(wOut[0]);
194.2726 +
194.2727 +    return output;
194.2728  }
194.2729  
194.2730 +static
194.2731 +cmsUInt8Number* Pack1Word(register _cmsTRANSFORM* Info,
194.2732 +                          register cmsUInt16Number wOut[],
194.2733 +                          register cmsUInt8Number* output,
194.2734 +                          register cmsUInt32Number Stride)
194.2735 +{
194.2736 +    *(cmsUInt16Number*) output = wOut[0];
194.2737 +    output+= 2;
194.2738 +
194.2739 +    return output;
194.2740 +}
194.2741 +
194.2742 +
194.2743 +static
194.2744 +cmsUInt8Number* Pack1WordReversed(register _cmsTRANSFORM* Info,
194.2745 +                                  register cmsUInt16Number wOut[],
194.2746 +                                  register cmsUInt8Number* output,
194.2747 +                                  register cmsUInt32Number Stride)
194.2748 +{
194.2749 +    *(cmsUInt16Number*) output = REVERSE_FLAVOR_16(wOut[0]);
194.2750 +    output+= 2;
194.2751 +
194.2752 +    return output;
194.2753 +}
194.2754 +
194.2755 +static
194.2756 +cmsUInt8Number* Pack1WordBigEndian(register _cmsTRANSFORM* Info,
194.2757 +                                   register cmsUInt16Number wOut[],
194.2758 +                                   register cmsUInt8Number* output,
194.2759 +                                   register cmsUInt32Number Stride)
194.2760 +{
194.2761 +    *(cmsUInt16Number*) output = CHANGE_ENDIAN(wOut[0]);
194.2762 +    output+= 2;
194.2763 +
194.2764 +    return output;
194.2765 +}
194.2766 +
194.2767 +
194.2768 +static
194.2769 +cmsUInt8Number* Pack1WordSkip1(register _cmsTRANSFORM* Info,
194.2770 +                               register cmsUInt16Number wOut[],
194.2771 +                               register cmsUInt8Number* output,
194.2772 +                               register cmsUInt32Number Stride)
194.2773 +{
194.2774 +    *(cmsUInt16Number*) output = wOut[0];
194.2775 +    output+= 4;
194.2776 +
194.2777 +    return output;
194.2778 +}
194.2779 +
194.2780 +static
194.2781 +cmsUInt8Number* Pack1WordSkip1SwapFirst(register _cmsTRANSFORM* Info,
194.2782 +                                        register cmsUInt16Number wOut[],
194.2783 +                                        register cmsUInt8Number* output,
194.2784 +                                        register cmsUInt32Number Stride)
194.2785 +{
194.2786 +    output += 2;
194.2787 +    *(cmsUInt16Number*) output = wOut[0];
194.2788 +    output+= 2;
194.2789 +
194.2790 +    return output;
194.2791 +}
194.2792 +
194.2793  
194.2794  // Unencoded Float values -- don't try optimize speed
194.2795 -
194.2796  static
194.2797 -LPBYTE PackLabDouble(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2798 +cmsUInt8Number* PackLabDoubleFrom16(register _cmsTRANSFORM* Info,
194.2799 +                                    register cmsUInt16Number wOut[],
194.2800 +                                    register cmsUInt8Number* output,
194.2801 +                                    register cmsUInt32Number Stride)
194.2802  {
194.2803  
194.2804      if (T_PLANAR(Info -> OutputFormat)) {
194.2805  
194.2806          cmsCIELab  Lab;
194.2807 -        double* Out = (double*) output;
194.2808 +        cmsFloat64Number* Out = (cmsFloat64Number*) output;
194.2809          cmsLabEncoded2Float(&Lab, wOut);
194.2810  
194.2811 -        Out[0]                  = Lab.L;
194.2812 -        Out[Info ->StrideOut]   = Lab.a;
194.2813 -        Out[Info ->StrideOut*2] = Lab.b;
194.2814 -
194.2815 -        return output + sizeof(double);
194.2816 -
194.2817 +        Out[0]        = Lab.L;
194.2818 +        Out[Stride]   = Lab.a;
194.2819 +        Out[Stride*2] = Lab.b;
194.2820 +
194.2821 +        return output + sizeof(cmsFloat64Number);
194.2822      }
194.2823      else {
194.2824  
194.2825 -       if (Info ->lOutputV4Lab)
194.2826 -           cmsLabEncoded2Float4((LPcmsCIELab) output, wOut);
194.2827 -       else
194.2828 -           cmsLabEncoded2Float((LPcmsCIELab) output, wOut);
194.2829 -
194.2830 -        return output + (sizeof(cmsCIELab) + T_EXTRA(Info ->OutputFormat) * sizeof(double));
194.2831 +        cmsLabEncoded2Float((cmsCIELab*) output, wOut);
194.2832 +        return output + (sizeof(cmsCIELab) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
194.2833      }
194.2834  
194.2835  }
194.2836  
194.2837  static
194.2838 -LPBYTE PackXYZDouble(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2839 +cmsUInt8Number* PackXYZDoubleFrom16(register _cmsTRANSFORM* Info,
194.2840 +                                    register cmsUInt16Number wOut[],
194.2841 +                                    register cmsUInt8Number* output,
194.2842 +                                    register cmsUInt32Number Stride)
194.2843  {
194.2844 -
194.2845      if (T_PLANAR(Info -> OutputFormat)) {
194.2846  
194.2847          cmsCIEXYZ XYZ;
194.2848 -        double* Out = (double*) output;
194.2849 +        cmsFloat64Number* Out = (cmsFloat64Number*) output;
194.2850          cmsXYZEncoded2Float(&XYZ, wOut);
194.2851  
194.2852          Out[0]                  = XYZ.X;
194.2853 -        Out[Info ->StrideOut]   = XYZ.Y;
194.2854 -        Out[Info ->StrideOut*2] = XYZ.Z;
194.2855 -
194.2856 -        return output + sizeof(double);
194.2857 +        Out[Stride]   = XYZ.Y;
194.2858 +        Out[Stride*2] = XYZ.Z;
194.2859 +
194.2860 +        return output + sizeof(cmsFloat64Number);
194.2861  
194.2862      }
194.2863      else {
194.2864  
194.2865 -        cmsXYZEncoded2Float((LPcmsCIEXYZ) output, wOut);
194.2866 -
194.2867 -        return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(double));
194.2868 +        cmsXYZEncoded2Float((cmsCIEXYZ*) output, wOut);
194.2869 +
194.2870 +        return output + (sizeof(cmsCIEXYZ) + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
194.2871      }
194.2872  }
194.2873  
194.2874 -
194.2875 -
194.2876  static
194.2877 -LPBYTE PackInkDouble(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2878 +cmsUInt8Number* PackDoubleFrom16(register _cmsTRANSFORM* Info,
194.2879 +                                 register cmsUInt16Number wOut[],
194.2880 +                                 register cmsUInt8Number* output,
194.2881 +                                 register cmsUInt32Number Stride)
194.2882  {
194.2883 -    double* Inks = (double*) output;
194.2884 +    cmsFloat64Number* Inks = (cmsFloat64Number*) output;
194.2885      int nChan = T_CHANNELS(Info -> OutputFormat);
194.2886      int i;
194.2887 +    cmsFloat64Number maximum = IsInkSpace(Info ->InputFormat) ? 655.35 : 65535.0;
194.2888  
194.2889      if (T_PLANAR(Info -> OutputFormat)) {
194.2890  
194.2891          for (i=0; i <  nChan; i++) {
194.2892  
194.2893 -            Inks[i*Info ->StrideOut] = wOut[i] / 655.35;
194.2894 +            Inks[i*Stride] = wOut[i] / maximum;
194.2895          }
194.2896  
194.2897 -        return output + sizeof(double);
194.2898 +        return output + sizeof(cmsFloat64Number);
194.2899      }
194.2900      else {
194.2901  
194.2902          for (i=0; i <  nChan; i++) {
194.2903  
194.2904 -            Inks[i] = wOut[i] /  655.35;
194.2905 +            Inks[i] = wOut[i] /  maximum;
194.2906          }
194.2907  
194.2908  
194.2909 -    return output + (nChan + T_EXTRA(Info ->OutputFormat)) * sizeof(double);
194.2910 +        return output + (nChan + T_EXTRA(Info ->OutputFormat)) * sizeof(cmsFloat64Number);
194.2911      }
194.2912  
194.2913  }
194.2914  
194.2915 -
194.2916  static
194.2917 -LPBYTE PackDouble(register _LPcmsTRANSFORM Info, register WORD wOut[], register LPBYTE output)
194.2918 +cmsUInt8Number* PackFloatFrom16(register _cmsTRANSFORM* Info,
194.2919 +                                register cmsUInt16Number wOut[],
194.2920 +                                register cmsUInt8Number* output,
194.2921 +                                register cmsUInt32Number Stride)
194.2922  {
194.2923 -    double* Inks = (double*) output;
194.2924 +    cmsFloat32Number* Inks = (cmsFloat32Number*) output;
194.2925      int nChan = T_CHANNELS(Info -> OutputFormat);
194.2926      int i;
194.2927 -
194.2928 +    cmsFloat64Number maximum = IsInkSpace(Info ->OutputFormat) ? 655.35 : 65535.0;
194.2929  
194.2930      if (T_PLANAR(Info -> OutputFormat)) {
194.2931  
194.2932          for (i=0; i <  nChan; i++) {
194.2933  
194.2934 -            Inks[i*Info ->StrideOut] = wOut[i] / 65535.0;
194.2935 +            Inks[i*Stride] = (cmsFloat32Number) (wOut[i] / maximum);
194.2936          }
194.2937  
194.2938 -        return output + sizeof(double);
194.2939 -
194.2940 +        return output + sizeof(cmsFloat32Number);
194.2941      }
194.2942      else {
194.2943 +
194.2944          for (i=0; i <  nChan; i++) {
194.2945  
194.2946 -            Inks[i] = wOut[i] /  65535.0;
194.2947 +            Inks[i] = (cmsFloat32Number) (wOut[i] /  maximum);
194.2948          }
194.2949  
194.2950 -        return output + (nChan + T_EXTRA(Info ->OutputFormat)) * sizeof(double);
194.2951 +
194.2952 +        return output + (nChan + T_EXTRA(Info ->OutputFormat)) * sizeof(cmsFloat32Number);
194.2953      }
194.2954  
194.2955  }
194.2956  
194.2957  
194.2958 -//  choose routine from Input identifier
194.2959 -
194.2960 -_cmsFIXFN _cmsIdentifyInputFormat(_LPcmsTRANSFORM xform, DWORD dwInput)
194.2961 +// --------------------------------------------------------------------------------------------------------
194.2962 +
194.2963 +static
194.2964 +cmsUInt8Number* PackChunkyFloatsFromFloat(_cmsTRANSFORM* info,
194.2965 +                                          cmsFloat32Number wOut[],
194.2966 +                                          cmsUInt8Number* output,
194.2967 +                                          cmsUInt32Number Stride)
194.2968  {
194.2969 -       _cmsFIXFN FromInput = NULL;
194.2970 -
194.2971 -
194.2972 -       // Check Named Color
194.2973 -
194.2974 -       if (xform) {
194.2975 -
194.2976 -           if (xform ->InputProfile) {
194.2977 -
194.2978 -           if (cmsGetDeviceClass(xform ->InputProfile) == icSigNamedColorClass) {
194.2979 -
194.2980 -                if (dwInput != TYPE_NAMED_COLOR_INDEX) {
194.2981 -                    cmsSignalError(LCMS_ERRC_ABORTED, "Named color needs TYPE_NAMED_COLOR_INDEX");
194.2982 -                    return NULL;
194.2983 -                }
194.2984 -           }
194.2985 -
194.2986 +    int nChan      = T_CHANNELS(info -> OutputFormat);
194.2987 +    int DoSwap     = T_DOSWAP(info ->OutputFormat);
194.2988 +    int Reverse    = T_FLAVOR(info ->OutputFormat);
194.2989 +    int Extra      = T_EXTRA(info -> OutputFormat);
194.2990 +    int SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
194.2991 +    int ExtraFirst = DoSwap && !SwapFirst;
194.2992 +    cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
194.2993 +    cmsFloat32Number* swap1;
194.2994 +    cmsFloat64Number v = 0;
194.2995 +    int i;
194.2996 +
194.2997 +    swap1 = (cmsFloat32Number*) output;
194.2998 +
194.2999 +    if (ExtraFirst) {
194.3000 +        output += Extra * sizeof(cmsFloat32Number);
194.3001 +    }
194.3002 +
194.3003 +    for (i=0; i < nChan; i++) {
194.3004 +
194.3005 +        int index = DoSwap ? (nChan - i - 1) : i;
194.3006 +
194.3007 +        v = wOut[index] * maximum;
194.3008 +
194.3009 +        if (Reverse)
194.3010 +            v = maximum - v;
194.3011 +
194.3012 +        *(cmsFloat32Number*) output = (cmsFloat32Number) v;
194.3013 +
194.3014 +        output += sizeof(cmsFloat32Number);
194.3015 +    }
194.3016 +
194.3017 +    if (!ExtraFirst) {
194.3018 +        output += Extra * sizeof(cmsFloat32Number);
194.3019 +    }
194.3020 +
194.3021 +    if (Extra == 0 && SwapFirst) {
194.3022 +
194.3023 +        memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat32Number));
194.3024 +        *swap1 = (cmsFloat32Number) v;
194.3025 +    }
194.3026 +
194.3027 +
194.3028 +    return output;
194.3029 +}
194.3030 +
194.3031 +static
194.3032 +cmsUInt8Number* PackPlanarFloatsFromFloat(_cmsTRANSFORM* info,
194.3033 +                                          cmsFloat32Number wOut[],
194.3034 +                                          cmsUInt8Number* output,
194.3035 +                                          cmsUInt32Number Stride)
194.3036 +{
194.3037 +    int nChan = T_CHANNELS(info -> OutputFormat);
194.3038 +    int DoSwap = T_DOSWAP(info ->OutputFormat);
194.3039 +    int Reverse= T_FLAVOR(info ->OutputFormat);
194.3040 +    int i;
194.3041 +    cmsUInt8Number* Init = output;
194.3042 +    cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
194.3043 +    cmsFloat64Number v;
194.3044 +
194.3045 +    if (DoSwap) {
194.3046 +        output += T_EXTRA(info -> OutputFormat) * Stride * sizeof(cmsFloat32Number);
194.3047 +    }
194.3048 +
194.3049 +    for (i=0; i < nChan; i++) {
194.3050 +
194.3051 +        int index = DoSwap ? (nChan - i - 1) : i;
194.3052 +
194.3053 +        v = wOut[index] * maximum;
194.3054 +
194.3055 +        if (Reverse)
194.3056 +            v =  maximum - v;
194.3057 +
194.3058 +        *(cmsFloat32Number*) output = (cmsFloat32Number) v;
194.3059 +        output += (Stride * sizeof(cmsFloat32Number));
194.3060 +    }
194.3061 +
194.3062 +    return (Init + sizeof(cmsFloat32Number));
194.3063 +}
194.3064 +
194.3065 +
194.3066 +static
194.3067 +cmsUInt8Number* PackChunkyDoublesFromFloat(_cmsTRANSFORM* info,
194.3068 +                                           cmsFloat32Number wOut[],
194.3069 +                                           cmsUInt8Number* output,
194.3070 +                                           cmsUInt32Number Stride)
194.3071 +{
194.3072 +    int nChan      = T_CHANNELS(info -> OutputFormat);
194.3073 +    int DoSwap     = T_DOSWAP(info ->OutputFormat);
194.3074 +    int Reverse    = T_FLAVOR(info ->OutputFormat);
194.3075 +    int Extra      = T_EXTRA(info -> OutputFormat);
194.3076 +    int SwapFirst  = T_SWAPFIRST(info -> OutputFormat);
194.3077 +    int ExtraFirst = DoSwap && !SwapFirst;
194.3078 +    cmsFloat64Number* swap1;
194.3079 +    cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
194.3080 +    cmsFloat64Number v = 0;
194.3081 +    int i;
194.3082 +
194.3083 +    swap1 = (cmsFloat64Number*) output;
194.3084 +
194.3085 +    if (ExtraFirst) {
194.3086 +        output += Extra * sizeof(cmsFloat64Number);
194.3087 +    }
194.3088 +
194.3089 +    for (i=0; i < nChan; i++) {
194.3090 +
194.3091 +        int index = DoSwap ? (nChan - i - 1) : i;
194.3092 +
194.3093 +        v = (cmsFloat64Number) wOut[index] * maximum;
194.3094 +
194.3095 +        if (Reverse)
194.3096 +            v = maximum - v;
194.3097 +
194.3098 +        *(cmsFloat64Number*) output = v;
194.3099 +
194.3100 +        output += sizeof(cmsFloat64Number);
194.3101 +    }
194.3102 +
194.3103 +    if (!ExtraFirst) {
194.3104 +        output += Extra * sizeof(cmsFloat64Number);
194.3105 +    }
194.3106 +
194.3107 +    if (Extra == 0 && SwapFirst) {
194.3108 +
194.3109 +        memmove(swap1 + 1, swap1, (nChan-1)* sizeof(cmsFloat64Number));
194.3110 +        *swap1 = v;
194.3111 +    }
194.3112 +
194.3113 +
194.3114 +    return output;
194.3115 +}
194.3116 +
194.3117 +static
194.3118 +cmsUInt8Number* PackPlanarDoublesFromFloat(_cmsTRANSFORM* info,
194.3119 +                                           cmsFloat32Number wOut[],
194.3120 +                                           cmsUInt8Number* output,
194.3121 +                                           cmsUInt32Number Stride)
194.3122 +{
194.3123 +    int nChan = T_CHANNELS(info -> OutputFormat);
194.3124 +    int DoSwap = T_DOSWAP(info ->OutputFormat);
194.3125 +    int Reverse= T_FLAVOR(info ->OutputFormat);
194.3126 +    int i;
194.3127 +    cmsUInt8Number* Init = output;
194.3128 +    cmsFloat64Number maximum = IsInkSpace(info ->OutputFormat) ? 100.0 : 1.0;
194.3129 +    cmsFloat64Number v;
194.3130 +
194.3131 +    if (DoSwap) {
194.3132 +        output += T_EXTRA(info -> OutputFormat) * Stride * sizeof(cmsFloat64Number);
194.3133 +    }
194.3134 +
194.3135 +    for (i=0; i < nChan; i++) {
194.3136 +
194.3137 +        int index = DoSwap ? (nChan - i - 1) : i;
194.3138 +
194.3139 +        v = (cmsFloat64Number) wOut[index] * maximum;
194.3140 +
194.3141 +        if (Reverse)
194.3142 +            v =  maximum - v;
194.3143 +
194.3144 +        *(cmsFloat64Number*) output = v;
194.3145 +        output += (Stride * sizeof(cmsFloat64Number));
194.3146 +    }
194.3147 +
194.3148 +    return (Init + sizeof(cmsFloat64Number));
194.3149 +}
194.3150 +
194.3151 +
194.3152 +
194.3153 +
194.3154 +static
194.3155 +cmsUInt8Number* PackLabFloatFromFloat(_cmsTRANSFORM* Info,
194.3156 +                                      cmsFloat32Number wOut[],
194.3157 +                                      cmsUInt8Number* output,
194.3158 +                                      cmsUInt32Number Stride)
194.3159 +{
194.3160 +    cmsFloat32Number* Out = (cmsFloat32Number*) output;
194.3161 +
194.3162 +    if (T_PLANAR(Info -> OutputFormat)) {
194.3163 +
194.3164 +        Out[0]                  = (cmsFloat32Number) (wOut[0] * 100.0);
194.3165 +        Out[Stride]   = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);
194.3166 +        Out[Stride*2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);
194.3167 +
194.3168 +        return output + sizeof(cmsFloat32Number);
194.3169 +    }
194.3170 +    else {
194.3171 +
194.3172 +        Out[0] = (cmsFloat32Number) (wOut[0] * 100.0);
194.3173 +        Out[1] = (cmsFloat32Number) (wOut[1] * 255.0 - 128.0);
194.3174 +        Out[2] = (cmsFloat32Number) (wOut[2] * 255.0 - 128.0);
194.3175 +
194.3176 +        return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
194.3177 +    }
194.3178 +
194.3179 +}
194.3180 +
194.3181 +static
194.3182 +cmsUInt8Number* PackLabDoubleFromFloat(_cmsTRANSFORM* Info,
194.3183 +                                       cmsFloat32Number wOut[],
194.3184 +                                       cmsUInt8Number* output,
194.3185 +                                       cmsUInt32Number Stride)
194.3186 +{
194.3187 +    cmsFloat64Number* Out = (cmsFloat64Number*) output;
194.3188 +
194.3189 +    if (T_PLANAR(Info -> OutputFormat)) {
194.3190 +
194.3191 +        Out[0]                  = (cmsFloat64Number) (wOut[0] * 100.0);
194.3192 +        Out[Stride]   = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
194.3193 +        Out[Stride*2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
194.3194 +
194.3195 +        return output + sizeof(cmsFloat64Number);
194.3196 +    }
194.3197 +    else {
194.3198 +
194.3199 +        Out[0] = (cmsFloat64Number) (wOut[0] * 100.0);
194.3200 +        Out[1] = (cmsFloat64Number) (wOut[1] * 255.0 - 128.0);
194.3201 +        Out[2] = (cmsFloat64Number) (wOut[2] * 255.0 - 128.0);
194.3202 +
194.3203 +        return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
194.3204 +    }
194.3205 +
194.3206 +}
194.3207 +
194.3208 +
194.3209 +// From 0..1 range to 0..MAX_ENCODEABLE_XYZ
194.3210 +static
194.3211 +cmsUInt8Number* PackXYZFloatFromFloat(_cmsTRANSFORM* Info,
194.3212 +                                      cmsFloat32Number wOut[],
194.3213 +                                      cmsUInt8Number* output,
194.3214 +                                      cmsUInt32Number Stride)
194.3215 +{
194.3216 +    cmsFloat32Number* Out = (cmsFloat32Number*) output;
194.3217 +
194.3218 +    if (T_PLANAR(Info -> OutputFormat)) {
194.3219 +
194.3220 +        Out[0]                  = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
194.3221 +        Out[Stride]   = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
194.3222 +        Out[Stride*2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
194.3223 +
194.3224 +        return output + sizeof(cmsFloat32Number);
194.3225 +    }
194.3226 +    else {
194.3227 +
194.3228 +        Out[0] = (cmsFloat32Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
194.3229 +        Out[1] = (cmsFloat32Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
194.3230 +        Out[2] = (cmsFloat32Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
194.3231 +
194.3232 +        return output + (sizeof(cmsFloat32Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat32Number));
194.3233 +    }
194.3234 +
194.3235 +}
194.3236 +
194.3237 +
194.3238 +// Same, but convert to double
194.3239 +static
194.3240 +cmsUInt8Number* PackXYZDoubleFromFloat(_cmsTRANSFORM* Info,
194.3241 +                                       cmsFloat32Number wOut[],
194.3242 +                                       cmsUInt8Number* output,
194.3243 +                                       cmsUInt32Number Stride)
194.3244 +{
194.3245 +    cmsFloat64Number* Out = (cmsFloat64Number*) output;
194.3246 +
194.3247 +    if (T_PLANAR(Info -> OutputFormat)) {
194.3248 +
194.3249 +        Out[0]                  = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
194.3250 +        Out[Stride]   = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
194.3251 +        Out[Stride*2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
194.3252 +
194.3253 +        return output + sizeof(cmsFloat64Number);
194.3254 +    }
194.3255 +    else {
194.3256 +
194.3257 +        Out[0] = (cmsFloat64Number) (wOut[0] * MAX_ENCODEABLE_XYZ);
194.3258 +        Out[1] = (cmsFloat64Number) (wOut[1] * MAX_ENCODEABLE_XYZ);
194.3259 +        Out[2] = (cmsFloat64Number) (wOut[2] * MAX_ENCODEABLE_XYZ);
194.3260 +
194.3261 +        return output + (sizeof(cmsFloat64Number)*3 + T_EXTRA(Info ->OutputFormat) * sizeof(cmsFloat64Number));
194.3262 +    }
194.3263 +
194.3264 +}
194.3265 +
194.3266 +
194.3267 +// ----------------------------------------------------------------------------------------------------------------
194.3268 +
194.3269 +
194.3270 +static cmsFormatters16 InputFormatters16[] = {
194.3271 +
194.3272 +    //    Type                                          Mask                  Function
194.3273 +    //  ----------------------------   ------------------------------------  ----------------------------
194.3274 +    { TYPE_Lab_DBL,                                          ANYPLANAR,   UnrollLabDoubleTo16},
194.3275 +    { TYPE_XYZ_DBL,                                          ANYPLANAR,   UnrollXYZDoubleTo16},
194.3276 +    { TYPE_GRAY_DBL,                                                 0,   UnrollDouble1Chan},
194.3277 +    { FLOAT_SH(1)|BYTES_SH(0), ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE,   UnrollDoubleTo16},
194.3278 +    { FLOAT_SH(1)|BYTES_SH(4), ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE,   UnrollFloatTo16},
194.3279 +
194.3280 +
194.3281 +    { CHANNELS_SH(1)|BYTES_SH(1),                              ANYSPACE,  Unroll1Byte},
194.3282 +    { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(2),                  ANYSPACE,  Unroll1ByteSkip2},
194.3283 +    { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1),                 ANYSPACE,  Unroll1ByteReversed},
194.3284 +
194.3285 +    { CHANNELS_SH(2)|BYTES_SH(1),                              ANYSPACE,  Unroll2Bytes},
194.3286 +    { CHANNELS_SH(2)|BYTES_SH(1)|SWAPFIRST_SH(1),              ANYSPACE,  Unroll2ByteSwapFirst},
194.3287 +
194.3288 +    { TYPE_LabV2_8,                                                   0,  UnrollLabV2_8 },
194.3289 +    { TYPE_ALabV2_8,                                                  0,  UnrollALabV2_8 },
194.3290 +    { TYPE_LabV2_16,                                                  0,  UnrollLabV2_16 },
194.3291 +
194.3292 +    { CHANNELS_SH(3)|BYTES_SH(1),                              ANYSPACE,  Unroll3Bytes},
194.3293 +    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1),                 ANYSPACE,  Unroll3BytesSwap},
194.3294 +    { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|DOSWAP_SH(1),     ANYSPACE,  Unroll3BytesSkip1Swap},
194.3295 +    { CHANNELS_SH(3)|EXTRA_SH(1)|BYTES_SH(1)|SWAPFIRST_SH(1),  ANYSPACE,  Unroll3BytesSkip1SwapFirst},
194.3296 +
194.3297 +    { CHANNELS_SH(4)|BYTES_SH(1),                              ANYSPACE,  Unroll4Bytes},
194.3298 +    { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1),                 ANYSPACE,  Unroll4BytesReverse},
194.3299 +    { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1),              ANYSPACE,  Unroll4BytesSwapFirst},
194.3300 +    { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1),                 ANYSPACE,  Unroll4BytesSwap},
194.3301 +    { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE,  Unroll4BytesSwapSwapFirst},
194.3302 +
194.3303 +    { BYTES_SH(1)|PLANAR_SH(1),    ANYFLAVOR|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollPlanarBytes},
194.3304 +    { BYTES_SH(1),    ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, UnrollChunkyBytes},
194.3305 +
194.3306 +
194.3307 +    { CHANNELS_SH(1)|BYTES_SH(2),                              ANYSPACE,  Unroll1Word},
194.3308 +    { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1),                 ANYSPACE,  Unroll1WordReversed},
194.3309 +    { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(3),                  ANYSPACE,  Unroll1WordSkip3},
194.3310 +
194.3311 +    { CHANNELS_SH(2)|BYTES_SH(2),                              ANYSPACE,  Unroll2Words},
194.3312 +    { CHANNELS_SH(2)|BYTES_SH(2)|SWAPFIRST_SH(1),              ANYSPACE,  Unroll2WordSwapFirst},
194.3313 +
194.3314 +    { CHANNELS_SH(3)|BYTES_SH(2),                              ANYSPACE,  Unroll3Words},
194.3315 +    { CHANNELS_SH(4)|BYTES_SH(2),                              ANYSPACE,  Unroll4Words},
194.3316 +
194.3317 +    { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1),                 ANYSPACE,  Unroll3WordsSwap},
194.3318 +    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1),  ANYSPACE,  Unroll3WordsSkip1SwapFirst},
194.3319 +    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1),     ANYSPACE,  Unroll3WordsSkip1Swap},
194.3320 +    { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1),                 ANYSPACE,  Unroll4WordsReverse},
194.3321 +    { CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1),              ANYSPACE,  Unroll4WordsSwapFirst},
194.3322 +    { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1),                 ANYSPACE,  Unroll4WordsSwap},
194.3323 +    { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1), ANYSPACE,  Unroll4WordsSwapSwapFirst},
194.3324 +
194.3325 +
194.3326 +    { BYTES_SH(2)|PLANAR_SH(1),  ANYFLAVOR|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE,  UnrollPlanarWords },
194.3327 +    { BYTES_SH(2),  ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE,  UnrollAnyWords},
194.3328 +};
194.3329 +
194.3330 +
194.3331 +
194.3332 +static cmsFormattersFloat InputFormattersFloat[] = {
194.3333 +
194.3334 +    //    Type                                          Mask                  Function
194.3335 +    //  ----------------------------   ------------------------------------  ----------------------------
194.3336 +    {     TYPE_Lab_DBL,                                                    ANYPLANAR,   UnrollLabDoubleToFloat},
194.3337 +    {     TYPE_Lab_FLT,                                                    ANYPLANAR,   UnrollLabFloatToFloat},
194.3338 +    {     TYPE_XYZ_DBL,                                                    ANYPLANAR,   UnrollXYZDoubleToFloat},
194.3339 +    {     TYPE_XYZ_FLT,                                                    ANYPLANAR,   UnrollXYZFloatToFloat},
194.3340 +
194.3341 +    {     FLOAT_SH(1)|BYTES_SH(4),           ANYPLANAR|ANYEXTRA|ANYCHANNELS|ANYSPACE,   UnrollFloatsToFloat},
194.3342 +    {     FLOAT_SH(1)|BYTES_SH(0),           ANYPLANAR|ANYEXTRA|ANYCHANNELS|ANYSPACE,   UnrollDoublesToFloat},
194.3343 +};
194.3344 +
194.3345 +
194.3346 +// Bit fields set to one in the mask are not compared
194.3347 +static
194.3348 +cmsFormatter _cmsGetStockInputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)
194.3349 +{
194.3350 +    cmsUInt32Number i;
194.3351 +    cmsFormatter fr;
194.3352 +
194.3353 +
194.3354 +    if (!(dwFlags & CMS_PACK_FLAGS_FLOAT)) {
194.3355 +
194.3356 +        for (i=0; i < sizeof(InputFormatters16) / sizeof(cmsFormatters16); i++) {
194.3357 +            cmsFormatters16* f = InputFormatters16 + i;
194.3358 +
194.3359 +            if ((dwInput & ~f ->Mask) == f ->Type) {
194.3360 +                fr.Fmt16 = f ->Frm;
194.3361 +                return fr;
194.3362 +            }
194.3363          }
194.3364 -       }
194.3365 -
194.3366 -       // Unencoded modes
194.3367 -
194.3368 -       if (T_BYTES(dwInput) == 0) {
194.3369 -
194.3370 -           switch (T_COLORSPACE(dwInput)) {
194.3371 -
194.3372 -           case PT_Lab:
194.3373 -                    FromInput = UnrollLabDouble;
194.3374 -                    break;
194.3375 -           case PT_XYZ:
194.3376 -                    FromInput = UnrollXYZDouble;
194.3377 -                    break;
194.3378 -
194.3379 -           // 0.0 .. 1.0 range
194.3380 -
194.3381 -           case PT_GRAY:
194.3382 -           case PT_RGB:
194.3383 -           case PT_YCbCr:
194.3384 -           case PT_YUV:
194.3385 -           case PT_YUVK:
194.3386 -           case PT_HSV:
194.3387 -           case PT_HLS:
194.3388 -           case PT_Yxy:
194.3389 -                    if (T_CHANNELS(dwInput) == 1)
194.3390 -                        FromInput = UnrollDouble1Chan;
194.3391 -                    else
194.3392 -                        FromInput = UnrollDouble;
194.3393 -                    break;
194.3394 -
194.3395 -            // Inks (%) 0.0 .. 100.0
194.3396 -
194.3397 -           default:
194.3398 -                    FromInput = UnrollInkDouble;
194.3399 -                    break;
194.3400 -           }
194.3401 -
194.3402 -       }
194.3403 -       else {
194.3404 -
194.3405 -           if (T_PLANAR(dwInput)) {
194.3406 -
194.3407 -               switch (T_BYTES(dwInput)) {
194.3408 -
194.3409 -               case 1:
194.3410 -                   FromInput = UnrollPlanarBytes;
194.3411 -                   break;
194.3412 -
194.3413 -               case 2:
194.3414 -                   if (T_ENDIAN16(dwInput))
194.3415 -                       FromInput = UnrollPlanarWordsBigEndian;
194.3416 -                   else
194.3417 -                       FromInput = UnrollPlanarWords;
194.3418 -                   break;
194.3419 -
194.3420 -               default:;
194.3421 -               }
194.3422 -       }
194.3423 -       else {
194.3424 -
194.3425 -       switch (T_BYTES(dwInput)) {
194.3426 -
194.3427 -       case 1: // 1 byte per channel
194.3428 -
194.3429 -              switch (T_CHANNELS(dwInput) + T_EXTRA(dwInput)) {
194.3430 -
194.3431 -              case 1: if (T_FLAVOR(dwInput))
194.3432 -                                FromInput = Unroll1ByteReversed;
194.3433 -                            else
194.3434 -                                  FromInput = Unroll1Byte;
194.3435 -                      break;
194.3436 -
194.3437 -              case 2: if (T_SWAPFIRST(dwInput))
194.3438 -                        FromInput = Unroll2ByteSwapFirst;
194.3439 -                      else
194.3440 -                        FromInput = Unroll2Byte;
194.3441 -                      break;
194.3442 -
194.3443 -              case 3: if (T_DOSWAP(dwInput))
194.3444 -                            FromInput = Unroll3BytesSwap;
194.3445 -                      else {
194.3446 -                            if (T_EXTRA(dwInput) == 2)
194.3447 -                                FromInput = Unroll1ByteSkip2;
194.3448 -                            else
194.3449 -                                if (T_COLORSPACE(dwInput) == PT_Lab)
194.3450 -                                    FromInput = Unroll3BytesLab;
194.3451 -                                else
194.3452 -                                    FromInput = Unroll3Bytes;
194.3453 -                      }
194.3454 -                      break;
194.3455 -              case 4:
194.3456 -                      // TODO: ALab8 must be fixed to match v2 encoding
194.3457 -
194.3458 -                      if (T_DOSWAP(dwInput)) {
194.3459 -                            if (T_SWAPFIRST(dwInput))
194.3460 -
194.3461 -                                FromInput = Unroll4BytesSwapSwapFirst;
194.3462 -                            else
194.3463 -                                FromInput = Unroll4BytesSwap;
194.3464 -                      }
194.3465 -                      else {
194.3466 -                            if (T_SWAPFIRST(dwInput))
194.3467 -                                FromInput = Unroll4BytesSwapFirst;
194.3468 -                            else {
194.3469 -                                if (T_FLAVOR(dwInput))
194.3470 -                                    FromInput = Unroll4BytesReverse;
194.3471 -                                else
194.3472 -                                    FromInput = Unroll4Bytes;
194.3473 -                            }
194.3474 -                      }
194.3475 -                      break;
194.3476 -
194.3477 -
194.3478 -              case 5:
194.3479 -              case 6:
194.3480 -              case 7:
194.3481 -              case 8:
194.3482 -                   if (!T_DOSWAP(dwInput) && !T_SWAPFIRST(dwInput))
194.3483 -                       FromInput = UnrollAnyBytes;
194.3484 -                   break;
194.3485 -
194.3486 -
194.3487 -              default:;
194.3488 -              }
194.3489 -              break;
194.3490 -
194.3491 -
194.3492 -       case 2: // 1 word per channel
194.3493 -
194.3494 -              switch (T_CHANNELS(dwInput) + T_EXTRA(dwInput))
194.3495 -              {
194.3496 -              case 1: if (T_ENDIAN16(dwInput))
194.3497 -                            FromInput = Unroll1WordBigEndian;
194.3498 -                      else
194.3499 -                          if (T_FLAVOR(dwInput))
194.3500 -                                FromInput = Unroll1WordReversed;
194.3501 -                            else
194.3502 -                                  FromInput = Unroll1Word;
194.3503 -                      break;
194.3504 -
194.3505 -              case 2: if (T_ENDIAN16(dwInput))
194.3506 -                            FromInput = Unroll2WordBigEndian;
194.3507 -                        else {
194.3508 -                          if (T_SWAPFIRST(dwInput))
194.3509 -                              FromInput = Unroll2WordSwapFirst;
194.3510 -                          else
194.3511 -                              FromInput = Unroll2Word;
194.3512 -                        }
194.3513 -                        break;
194.3514 -
194.3515 -              case 3: if (T_DOSWAP(dwInput)) {
194.3516 -                            if (T_ENDIAN16(dwInput))
194.3517 -                                   FromInput = Unroll3WordsSwapBigEndian;
194.3518 -                            else
194.3519 -                                   FromInput = Unroll3WordsSwap;
194.3520 -                      }
194.3521 -                      else {
194.3522 -                            if (T_ENDIAN16(dwInput))
194.3523 -                                   FromInput = Unroll3WordsBigEndian;
194.3524 -                            else
194.3525 -                                   FromInput = Unroll3Words;
194.3526 -                      }
194.3527 -                      break;
194.3528 -
194.3529 -              case 4: if (T_DOSWAP(dwInput)) {
194.3530 -
194.3531 -                            if (T_ENDIAN16(dwInput))
194.3532 -                                   FromInput = Unroll4WordsSwapBigEndian;
194.3533 -                            else {
194.3534 -
194.3535 -                                    if (T_SWAPFIRST(dwInput))
194.3536 -                                        FromInput = Unroll4WordsSwapSwapFirst;
194.3537 -                                    else
194.3538 -                                        FromInput = Unroll4WordsSwap;
194.3539 -
194.3540 -                            }
194.3541 -
194.3542 -                      }
194.3543 -                      else {
194.3544 -
194.3545 -                            if (T_EXTRA(dwInput) == 3)
194.3546 -                                    FromInput = Unroll1WordSkip3;
194.3547 -                            else
194.3548 -
194.3549 -                                if (T_ENDIAN16(dwInput)) {
194.3550 -
194.3551 -                                    if (T_FLAVOR(dwInput))
194.3552 -                                        FromInput = Unroll4WordsBigEndianReverse;
194.3553 -                                    else
194.3554 -                                        FromInput = Unroll4WordsBigEndian;
194.3555 -                                }
194.3556 -                            else {
194.3557 -                                  if (T_SWAPFIRST(dwInput))
194.3558 -                                    FromInput = Unroll4WordsSwapFirst;
194.3559 -                                  else {
194.3560 -                                      if (T_FLAVOR(dwInput))
194.3561 -                                            FromInput = Unroll4WordsReverse;
194.3562 -                                      else
194.3563 -                                            FromInput = Unroll4Words;
194.3564 -                                  }
194.3565 -                            }
194.3566 -                      }
194.3567 -                      break;
194.3568 -
194.3569 -
194.3570 -              case 5:
194.3571 -              case 6:
194.3572 -              case 7:
194.3573 -              case 8:
194.3574 -                    if (!T_DOSWAP(dwInput) && !T_SWAPFIRST(dwInput))
194.3575 -                       FromInput = UnrollAnyWords;
194.3576 -                    break;
194.3577 -
194.3578 -              }
194.3579 -              break;
194.3580 -
194.3581 -       default:;
194.3582 -       }
194.3583 -       }
194.3584 -       }
194.3585 -
194.3586 -
194.3587 -       if (!FromInput)
194.3588 -              cmsSignalError(LCMS_ERRC_ABORTED, "Unknown input format");
194.3589 -
194.3590 -       return FromInput;
194.3591 +    }
194.3592 +    else {
194.3593 +        for (i=0; i < sizeof(InputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
194.3594 +            cmsFormattersFloat* f = InputFormattersFloat + i;
194.3595 +
194.3596 +            if ((dwInput & ~f ->Mask) == f ->Type) {
194.3597 +                fr.FmtFloat = f ->Frm;
194.3598 +                return fr;
194.3599 +            }
194.3600 +        }
194.3601 +    }
194.3602 +
194.3603 +    fr.Fmt16 = NULL;
194.3604 +    return fr;
194.3605  }
194.3606  
194.3607 -//  choose routine from Input identifier
194.3608 -
194.3609 -_cmsFIXFN _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput)
194.3610 +static cmsFormatters16 OutputFormatters16[] = {
194.3611 +    //    Type                                          Mask                  Function
194.3612 +    //  ----------------------------   ------------------------------------  ----------------------------
194.3613 +
194.3614 +    { TYPE_Lab_DBL,                                               ANYPLANAR,  PackLabDoubleFrom16},
194.3615 +    { TYPE_XYZ_DBL,                                               ANYPLANAR,  PackXYZDoubleFrom16},
194.3616 +    { FLOAT_SH(1)|BYTES_SH(0),      ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE,  PackDoubleFrom16},
194.3617 +    { FLOAT_SH(1)|BYTES_SH(4),      ANYCHANNELS|ANYPLANAR|ANYEXTRA|ANYSPACE,  PackFloatFrom16},
194.3618 +
194.3619 +    { CHANNELS_SH(1)|BYTES_SH(1),                                  ANYSPACE,  Pack1Byte},
194.3620 +    { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1),                      ANYSPACE,  Pack1ByteSkip1},
194.3621 +    { CHANNELS_SH(1)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1),      ANYSPACE,  Pack1ByteSkip1SwapFirst},
194.3622 +
194.3623 +    { CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1),                     ANYSPACE,  Pack1ByteReversed},
194.3624 +
194.3625 +    { TYPE_LabV2_8,                                                       0,  PackLabV2_8 },
194.3626 +    { TYPE_ALabV2_8,                                                      0,  PackALabV2_8 },
194.3627 +    { TYPE_LabV2_16,                                                      0,  PackLabV2_16 },
194.3628 +
194.3629 +    { CHANNELS_SH(3)|BYTES_SH(1)|OPTIMIZED_SH(1),                  ANYSPACE,  Pack3BytesOptimized},
194.3630 +    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1),      ANYSPACE,  Pack3BytesAndSkip1Optimized},
194.3631 +    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),
194.3632 +                                                                   ANYSPACE,  Pack3BytesAndSkip1SwapFirstOptimized},
194.3633 +    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1)|OPTIMIZED_SH(1),
194.3634 +                                                                   ANYSPACE,  Pack3BytesAndSkip1SwapSwapFirstOptimized},
194.3635 +    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1)|OPTIMIZED_SH(1),
194.3636 +                                                                   ANYSPACE,  Pack3BytesAndSkip1SwapOptimized},
194.3637 +    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|OPTIMIZED_SH(1),     ANYSPACE,  Pack3BytesSwapOptimized},
194.3638 +
194.3639 +
194.3640 +
194.3641 +    { CHANNELS_SH(3)|BYTES_SH(1),                                  ANYSPACE,  Pack3Bytes},
194.3642 +    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1),                      ANYSPACE,  Pack3BytesAndSkip1},
194.3643 +    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|SWAPFIRST_SH(1),      ANYSPACE,  Pack3BytesAndSkip1SwapFirst},
194.3644 +    { CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
194.3645 +                                                                   ANYSPACE,  Pack3BytesAndSkip1SwapSwapFirst},
194.3646 +    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|EXTRA_SH(1),         ANYSPACE,  Pack3BytesAndSkip1Swap},
194.3647 +    { CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1),                     ANYSPACE,  Pack3BytesSwap},
194.3648 +    { CHANNELS_SH(6)|BYTES_SH(1),                                  ANYSPACE,  Pack6Bytes},
194.3649 +    { CHANNELS_SH(6)|BYTES_SH(1)|DOSWAP_SH(1),                     ANYSPACE,  Pack6BytesSwap},
194.3650 +    { CHANNELS_SH(4)|BYTES_SH(1),                                  ANYSPACE,  Pack4Bytes},
194.3651 +    { CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1),                     ANYSPACE,  Pack4BytesReverse},
194.3652 +    { CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1),                  ANYSPACE,  Pack4BytesSwapFirst},
194.3653 +    { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1),                     ANYSPACE,  Pack4BytesSwap},
194.3654 +    { CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),     ANYSPACE,  Pack4BytesSwapSwapFirst},
194.3655 +
194.3656 +    { BYTES_SH(1),                 ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyBytes},
194.3657 +    { BYTES_SH(1)|PLANAR_SH(1),    ANYFLAVOR|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarBytes},
194.3658 +
194.3659 +    { CHANNELS_SH(1)|BYTES_SH(2),                                  ANYSPACE,  Pack1Word},
194.3660 +    { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1),                      ANYSPACE,  Pack1WordSkip1},
194.3661 +    { CHANNELS_SH(1)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1),      ANYSPACE,  Pack1WordSkip1SwapFirst},
194.3662 +    { CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1),                     ANYSPACE,  Pack1WordReversed},
194.3663 +    { CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1),                   ANYSPACE,  Pack1WordBigEndian},
194.3664 +    { CHANNELS_SH(3)|BYTES_SH(2),                                  ANYSPACE,  Pack3Words},
194.3665 +    { CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1),                     ANYSPACE,  Pack3WordsSwap},
194.3666 +    { CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1),                   ANYSPACE,  Pack3WordsBigEndian},
194.3667 +    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1),                      ANYSPACE,  Pack3WordsAndSkip1},
194.3668 +    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1),         ANYSPACE,  Pack3WordsAndSkip1Swap},
194.3669 +    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|SWAPFIRST_SH(1),      ANYSPACE,  Pack3WordsAndSkip1SwapFirst},
194.3670 +
194.3671 +    { CHANNELS_SH(3)|BYTES_SH(2)|EXTRA_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1),
194.3672 +                                                                   ANYSPACE,  Pack3WordsAndSkip1SwapSwapFirst},
194.3673 +
194.3674 +    { CHANNELS_SH(4)|BYTES_SH(2),                                  ANYSPACE,  Pack4Words},
194.3675 +    { CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1),                     ANYSPACE,  Pack4WordsReverse},
194.3676 +    { CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1),                     ANYSPACE,  Pack4WordsSwap},
194.3677 +    { CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1),                   ANYSPACE,  Pack4WordsBigEndian},
194.3678 +
194.3679 +    { CHANNELS_SH(6)|BYTES_SH(2),                                  ANYSPACE,  Pack6Words},
194.3680 +    { CHANNELS_SH(6)|BYTES_SH(2)|DOSWAP_SH(1),                     ANYSPACE,  Pack6WordsSwap},
194.3681 +
194.3682 +    { BYTES_SH(2)|PLANAR_SH(1),     ANYFLAVOR|ANYENDIAN|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackPlanarWords},
194.3683 +    { BYTES_SH(2),                  ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYENDIAN|ANYEXTRA|ANYCHANNELS|ANYSPACE, PackAnyWords}
194.3684 +
194.3685 +};
194.3686 +
194.3687 +
194.3688 +static cmsFormattersFloat OutputFormattersFloat[] = {
194.3689 +    //    Type                                          Mask                                 Function
194.3690 +    //  ----------------------------   ---------------------------------------------------  ----------------------------
194.3691 +    {     TYPE_Lab_FLT,                                                         ANYPLANAR,   PackLabFloatFromFloat},
194.3692 +    {     TYPE_XYZ_FLT,                                                         ANYPLANAR,   PackXYZFloatFromFloat},
194.3693 +    {     TYPE_Lab_DBL,                                                         ANYPLANAR,   PackLabDoubleFromFloat},
194.3694 +    {     TYPE_XYZ_DBL,                                                         ANYPLANAR,   PackXYZDoubleFromFloat},
194.3695 +    {     FLOAT_SH(1)|BYTES_SH(4),
194.3696 +          ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackChunkyFloatsFromFloat },
194.3697 +    {     FLOAT_SH(1)|BYTES_SH(4)|PLANAR_SH(1),             ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackPlanarFloatsFromFloat},
194.3698 +    {     FLOAT_SH(1)|BYTES_SH(0),
194.3699 +          ANYFLAVOR|ANYSWAPFIRST|ANYSWAP|ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackChunkyDoublesFromFloat },
194.3700 +    {     FLOAT_SH(1)|BYTES_SH(0)|PLANAR_SH(1),             ANYEXTRA|ANYCHANNELS|ANYSPACE,   PackPlanarDoublesFromFloat},
194.3701 +
194.3702 +
194.3703 +};
194.3704 +
194.3705 +
194.3706 +// Bit fields set to one in the mask are not compared
194.3707 +cmsFormatter _cmsGetStockOutputFormatter(cmsUInt32Number dwInput, cmsUInt32Number dwFlags)
194.3708  {
194.3709 -       _cmsFIXFN ToOutput = NULL;
194.3710 -
194.3711 -
194.3712 -       if (T_BYTES(dwOutput) == 0) {
194.3713 -
194.3714 -           switch (T_COLORSPACE(dwOutput)) {
194.3715 -
194.3716 -           case PT_Lab:
194.3717 -                    ToOutput = PackLabDouble;
194.3718 -                    break;
194.3719 -           case PT_XYZ:
194.3720 -                    ToOutput = PackXYZDouble;
194.3721 -                    break;
194.3722 -
194.3723 -           // 0.0 .. 1.0 range
194.3724 -           case PT_GRAY:
194.3725 -           case PT_RGB:
194.3726 -           case PT_YCbCr:
194.3727 -           case PT_YUV:
194.3728 -           case PT_YUVK:
194.3729 -           case PT_HSV:
194.3730 -           case PT_HLS:
194.3731 -           case PT_Yxy:
194.3732 -                    ToOutput = PackDouble;
194.3733 -                    break;
194.3734 -
194.3735 -            // Inks (%) 0.0 .. 100.0
194.3736 -
194.3737 -           default:
194.3738 -                    ToOutput = PackInkDouble;
194.3739 -                    break;
194.3740 -           }
194.3741 -
194.3742 -       }
194.3743 -       else
194.3744 -
194.3745 -       if (T_PLANAR(dwOutput)) {
194.3746 -
194.3747 -       switch (T_BYTES(dwOutput)) {
194.3748 -
194.3749 -              case 1: ToOutput = PackPlanarBytes;
194.3750 -                      break;
194.3751 -
194.3752 -              case 2:if (!T_ENDIAN16(dwOutput))
194.3753 -                            ToOutput = PackPlanarWords;
194.3754 -                      break;
194.3755 -
194.3756 -              default:;
194.3757 -       }
194.3758 -       }
194.3759 -       else {
194.3760 -
194.3761 -              switch (T_BYTES(dwOutput)) {
194.3762 -
194.3763 -              case 1:
194.3764 -                     switch (T_CHANNELS(dwOutput))
194.3765 -                     {
194.3766 -                     case 1:
194.3767 -                            if (T_DITHER(dwOutput))
194.3768 -                                    ToOutput = PackNBytesDither;
194.3769 -                            else
194.3770 -                            ToOutput = Pack1Byte;
194.3771 -                            if (T_EXTRA(dwOutput) == 1) {
194.3772 -                                if (T_SWAPFIRST(dwOutput))
194.3773 -                                   ToOutput = Pack1ByteAndSkip1SwapFirst;
194.3774 -                                else
194.3775 -                                   ToOutput = Pack1ByteAndSkip1;
194.3776 -                            }
194.3777 -                            break;
194.3778 -
194.3779 -                     case 3:
194.3780 -                         switch (T_EXTRA(dwOutput)) {
194.3781 -
194.3782 -                         case 0: if (T_DOSWAP(dwOutput))
194.3783 -                                   ToOutput = Pack3BytesSwap;
194.3784 -                                 else
194.3785 -                                     if (T_COLORSPACE(dwOutput) == PT_Lab)
194.3786 -                                        ToOutput = Pack3BytesLab;
194.3787 -                                     else {
194.3788 -                                         if (T_DITHER(dwOutput))
194.3789 -                                                 ToOutput = PackNBytesDither;
194.3790 -                                     else
194.3791 -                                        ToOutput = Pack3Bytes;
194.3792 -                                     }
194.3793 -                             break;
194.3794 -
194.3795 -                         case 1:    // TODO: ALab8 should be handled here
194.3796 -
194.3797 -                                    if (T_DOSWAP(dwOutput)) {
194.3798 -
194.3799 -                                    if (T_SWAPFIRST(dwOutput))
194.3800 -                                        ToOutput = Pack3BytesAndSkip1SwapSwapFirst;
194.3801 -                                    else
194.3802 -                                        ToOutput = Pack3BytesAndSkip1Swap;
194.3803 -                                 }
194.3804 -                             else {
194.3805 -                                   if (T_SWAPFIRST(dwOutput))
194.3806 -                                    ToOutput = Pack3BytesAndSkip1SwapFirst;
194.3807 -                                   else
194.3808 -                                    ToOutput = Pack3BytesAndSkip1;
194.3809 -                             }
194.3810 -                             break;
194.3811 -
194.3812 -                         default:;
194.3813 -                         }
194.3814 -                         break;
194.3815 -
194.3816 -                     case 4: if (T_EXTRA(dwOutput) == 0) {
194.3817 -
194.3818 -
194.3819 -                                if (T_DOSWAP(dwOutput)) {
194.3820 -
194.3821 -
194.3822 -                                     if (T_SWAPFIRST(dwOutput)) {
194.3823 -                                         ToOutput = Pack4BytesSwapSwapFirst;
194.3824 -                                     }
194.3825 -                                     else {
194.3826 -
194.3827 -                                           if (T_DITHER(dwOutput)) {
194.3828 -                                                  ToOutput = PackNBytesSwapDither;
194.3829 -                                           }
194.3830 -                                           else {
194.3831 -                                         ToOutput = Pack4BytesSwap;
194.3832 -                                 }
194.3833 -                                     }
194.3834 -                                 }
194.3835 -                                 else {
194.3836 -                                     if (T_SWAPFIRST(dwOutput))
194.3837 -                                         ToOutput = Pack4BytesSwapFirst;
194.3838 -                                     else {
194.3839 -
194.3840 -                                         if (T_FLAVOR(dwOutput))
194.3841 -                                             ToOutput = Pack4BytesReverse;
194.3842 -                                         else {
194.3843 -                                             if (T_DITHER(dwOutput))
194.3844 -                                                 ToOutput = PackNBytesDither;
194.3845 -                                         else
194.3846 -                                             ToOutput = Pack4Bytes;
194.3847 -                                     }
194.3848 -                                 }
194.3849 -                             }
194.3850 -                             }
194.3851 -                            else {
194.3852 -                                    if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput))
194.3853 -                                             ToOutput = PackNBytes;
194.3854 -                            }
194.3855 -                            break;
194.3856 -
194.3857 -                     // Hexachrome separations.
194.3858 -                     case 6: if (T_EXTRA(dwOutput) == 0) {
194.3859 -
194.3860 -                                    if( T_DOSWAP(dwOutput))
194.3861 -                                            ToOutput = Pack6BytesSwap;
194.3862 -                            else
194.3863 -                                   ToOutput = Pack6Bytes;
194.3864 -                            }
194.3865 -                            else {
194.3866 -                                    if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput))
194.3867 -                                             ToOutput = PackNBytes;
194.3868 -
194.3869 -                            }
194.3870 -                            break;
194.3871 -
194.3872 -                     case 2:
194.3873 -                     case 5:
194.3874 -                     case 7:
194.3875 -                     case 8:
194.3876 -                     case 9:
194.3877 -                     case 10:
194.3878 -                     case 11:
194.3879 -                     case 12:
194.3880 -                     case 13:
194.3881 -                     case 14:
194.3882 -                     case 15:
194.3883 -
194.3884 -                            if ((T_EXTRA(dwOutput) == 0) && (T_SWAPFIRST(dwOutput) == 0))
194.3885 -                            {
194.3886 -                                   if (T_DOSWAP(dwOutput))
194.3887 -                                          ToOutput = PackNBytesSwap;
194.3888 -                                   else {
194.3889 -
194.3890 -                                       if (T_DITHER(dwOutput))
194.3891 -                                                 ToOutput = PackNBytesDither;
194.3892 -                                   else
194.3893 -                                          ToOutput = PackNBytes;
194.3894 -                                   }
194.3895 -                            }
194.3896 -                            break;
194.3897 -
194.3898 -                     default:;
194.3899 -                     }
194.3900 -                     break;
194.3901 -
194.3902 -
194.3903 -              case 2:
194.3904 -
194.3905 -                     switch (T_CHANNELS(dwOutput)) {
194.3906 -
194.3907 -                     case 1:
194.3908 -                            if (T_ENDIAN16(dwOutput))
194.3909 -
194.3910 -                                   ToOutput = Pack1WordBigEndian;
194.3911 -                            else
194.3912 -                                   ToOutput = Pack1Word;
194.3913 -
194.3914 -                            if (T_EXTRA(dwOutput) == 1) {
194.3915 -
194.3916 -                               if (T_ENDIAN16(dwOutput))
194.3917 -
194.3918 -                                   ToOutput = Pack1WordAndSkip1BigEndian;
194.3919 -                               else {
194.3920 -                                   if (T_SWAPFIRST(dwOutput))
194.3921 -                                      ToOutput = Pack1WordAndSkip1SwapFirst;
194.3922 -                                   else
194.3923 -                                      ToOutput = Pack1WordAndSkip1;
194.3924 -                               }
194.3925 -                            }
194.3926 -                            break;
194.3927 -
194.3928 -                     case 3:
194.3929 -
194.3930 -                         switch (T_EXTRA(dwOutput)) {
194.3931 -
194.3932 -                         case 0:
194.3933 -                               if (T_DOSWAP(dwOutput)) {
194.3934 -
194.3935 -                                   if (T_ENDIAN16(dwOutput))
194.3936 -
194.3937 -                                          ToOutput = Pack3WordsSwapBigEndian;
194.3938 -                                   else
194.3939 -                                          ToOutput = Pack3WordsSwap;
194.3940 -                               }
194.3941 -                               else {
194.3942 -                                   if (T_ENDIAN16(dwOutput))
194.3943 -
194.3944 -                                      ToOutput = Pack3WordsBigEndian;
194.3945 -                                   else
194.3946 -                                      ToOutput = Pack3Words;
194.3947 -                                   }
194.3948 -                             break;
194.3949 -
194.3950 -                         case 1: if (T_DOSWAP(dwOutput)) {
194.3951 -
194.3952 -                                   if (T_ENDIAN16(dwOutput))
194.3953 -
194.3954 -                                          ToOutput = Pack3WordsAndSkip1SwapBigEndian;
194.3955 -                                   else {
194.3956 -                                       if (T_SWAPFIRST(dwOutput))
194.3957 -                                          ToOutput = Pack3WordsAndSkip1SwapSwapFirst;
194.3958 -                                       else
194.3959 -                                          ToOutput = Pack3WordsAndSkip1Swap;
194.3960 -                                   }
194.3961 -                             }
194.3962 -                             else  {
194.3963 -                                   if (T_ENDIAN16(dwOutput))
194.3964 -                                          ToOutput = Pack3WordsAndSkip1BigEndian;
194.3965 -                                   else
194.3966 -                                          ToOutput = Pack3WordsAndSkip1;
194.3967 -                                   }
194.3968 -                         default:;
194.3969 -                         }
194.3970 -                         break;
194.3971 -
194.3972 -                     case 4: if (T_EXTRA(dwOutput) == 0) {
194.3973 -
194.3974 -                                   if (T_DOSWAP(dwOutput)) {
194.3975 -
194.3976 -                                           if (T_ENDIAN16(dwOutput))
194.3977 -                                                 ToOutput = Pack4WordsSwapBigEndian;
194.3978 -                                           else
194.3979 -                                                 ToOutput = Pack4WordsSwap;
194.3980 -                                   }
194.3981 -                                   else {
194.3982 -
194.3983 -                                       if (T_ENDIAN16(dwOutput)) {
194.3984 -
194.3985 -                                           if (T_FLAVOR(dwOutput))
194.3986 -                                                ToOutput = Pack4WordsBigEndianReverse;
194.3987 -                                           else
194.3988 -                                                ToOutput = Pack4WordsBigEndian;
194.3989 -                                       }
194.3990 -                                       else {
194.3991 -                                          if (T_FLAVOR(dwOutput))
194.3992 -                                              ToOutput = Pack4WordsReverse;
194.3993 -                                          else
194.3994 -                                               ToOutput = Pack4Words;
194.3995 -                                        }
194.3996 -                                   }
194.3997 -                            }
194.3998 -                            else {
194.3999 -                                    if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput))
194.4000 -                                             ToOutput = PackNWords;
194.4001 -                            }
194.4002 -                            break;
194.4003 -
194.4004 -                     case 6: if (T_EXTRA(dwOutput) == 0) {
194.4005 -
194.4006 -                                   if (T_DOSWAP(dwOutput)) {
194.4007 -
194.4008 -                                          if (T_ENDIAN16(dwOutput))
194.4009 -                                                 ToOutput = Pack6WordsSwapBigEndian;
194.4010 -                                          else
194.4011 -                                                 ToOutput = Pack6WordsSwap;
194.4012 -                                   }
194.4013 -                                   else {
194.4014 -
194.4015 -                                   if (T_ENDIAN16(dwOutput))
194.4016 -                                          ToOutput = Pack6WordsBigEndian;
194.4017 -                                   else
194.4018 -                                          ToOutput = Pack6Words;
194.4019 -                                   }
194.4020 -                             }
194.4021 -                            else {
194.4022 -                                    if (!T_DOSWAP(dwOutput) && !T_SWAPFIRST(dwOutput))
194.4023 -                                             ToOutput = PackNWords;
194.4024 -                            }
194.4025 -                            break;
194.4026 -
194.4027 -
194.4028 -                     case 2:
194.4029 -                     case 5:
194.4030 -                     case 7:
194.4031 -                     case 8:
194.4032 -                     case 9:
194.4033 -                     case 10:
194.4034 -                     case 11:
194.4035 -                     case 12:
194.4036 -                     case 13:
194.4037 -                     case 14:
194.4038 -                     case 15: if ((T_EXTRA(dwOutput) == 0) && (T_SWAPFIRST(dwOutput) == 0)) {
194.4039 -
194.4040 -                                   if (T_DOSWAP(dwOutput)) {
194.4041 -
194.4042 -                                          if (T_ENDIAN16(dwOutput))
194.4043 -                                                 ToOutput = PackNWordsSwapBigEndian;
194.4044 -                                          else
194.4045 -                                                 ToOutput = PackNWordsSwap;
194.4046 -                                   }
194.4047 -                                   else {
194.4048 -
194.4049 -                                          if (T_ENDIAN16(dwOutput))
194.4050 -                                                 ToOutput = PackNWordsBigEndian;
194.4051 -                                          else
194.4052 -                                                 ToOutput = PackNWords;
194.4053 -                                          }
194.4054 -                             }
194.4055 -                             break;
194.4056 -
194.4057 -                     default:;
194.4058 -                     }
194.4059 -                     break;
194.4060 -
194.4061 -              default:;
194.4062 -              }
194.4063 -              }
194.4064 -
194.4065 -              if (!ToOutput)
194.4066 -                     cmsSignalError(LCMS_ERRC_ABORTED, "Unknown output format");
194.4067 -
194.4068 -              return ToOutput;
194.4069 +    cmsUInt32Number i;
194.4070 +    cmsFormatter fr;
194.4071 +
194.4072 +
194.4073 +    if (dwFlags & CMS_PACK_FLAGS_FLOAT) {
194.4074 +
194.4075 +        for (i=0; i < sizeof(OutputFormattersFloat) / sizeof(cmsFormattersFloat); i++) {
194.4076 +            cmsFormattersFloat* f = OutputFormattersFloat + i;
194.4077 +
194.4078 +            if ((dwInput & ~f ->Mask) == f ->Type) {
194.4079 +                fr.FmtFloat = f ->Frm;
194.4080 +                return fr;
194.4081 +            }
194.4082 +        }
194.4083 +
194.4084 +    }
194.4085 +    else {
194.4086 +
194.4087 +        for (i=0; i < sizeof(OutputFormatters16) / sizeof(cmsFormatters16); i++) {
194.4088 +            cmsFormatters16* f = OutputFormatters16 + i;
194.4089 +
194.4090 +            if ((dwInput & ~f ->Mask) == f ->Type) {
194.4091 +                fr.Fmt16 = f ->Frm;
194.4092 +                return fr;
194.4093 +            }
194.4094 +        }
194.4095 +    }
194.4096 +
194.4097 +    fr.Fmt16 = NULL;
194.4098 +    return fr;
194.4099  }
194.4100  
194.4101 -// User formatters for (weird) cases not already included
194.4102 -
194.4103 -void LCMSEXPORT cmsSetUserFormatters(cmsHTRANSFORM hTransform, DWORD dwInput,  cmsFORMATTER Input,
194.4104 -                                                               DWORD dwOutput, cmsFORMATTER Output)
194.4105 +
194.4106 +typedef struct _cms_formatters_factory_list {
194.4107 +
194.4108 +    cmsFormatterFactory Factory;
194.4109 +    struct _cms_formatters_factory_list *Next;
194.4110 +
194.4111 +} cmsFormattersFactoryList;
194.4112 +
194.4113 +static cmsFormattersFactoryList* FactoryList = NULL;
194.4114 +
194.4115 +
194.4116 +// Formatters management
194.4117 +cmsBool  _cmsRegisterFormattersPlugin(cmsPluginBase* Data)
194.4118  {
194.4119 -    _LPcmsTRANSFORM xform = (_LPcmsTRANSFORM) (LPSTR) hTransform;
194.4120 -
194.4121 -    if (Input != NULL) {
194.4122 -        xform ->FromInput = (_cmsFIXFN) Input;
194.4123 -        xform ->InputFormat = dwInput;
194.4124 +    cmsPluginFormatters* Plugin = (cmsPluginFormatters*) Data;
194.4125 +    cmsFormattersFactoryList* fl ;
194.4126 +
194.4127 +    // Reset
194.4128 +    if (Data == NULL) {
194.4129 +
194.4130 +        FactoryList = NULL;
194.4131 +        return TRUE;
194.4132      }
194.4133  
194.4134 -    if (Output != NULL) {
194.4135 -        xform ->ToOutput  = (_cmsFIXFN) Output;
194.4136 -        xform ->OutputFormat = dwOutput;
194.4137 +    fl = (cmsFormattersFactoryList*) _cmsPluginMalloc(sizeof(cmsFormattersFactoryList));
194.4138 +    if (fl == NULL) return FALSE;
194.4139 +
194.4140 +    fl ->Factory    = Plugin ->FormattersFactory;
194.4141 +
194.4142 +    fl ->Next = FactoryList;
194.4143 +    FactoryList = fl;
194.4144 +
194.4145 +    return TRUE;
194.4146 +}
194.4147 +
194.4148 +cmsFormatter _cmsGetFormatter(cmsUInt32Number Type,         // Specific type, i.e. TYPE_RGB_8
194.4149 +                             cmsFormatterDirection Dir,
194.4150 +                             cmsUInt32Number dwFlags)       // Float or 16 bits
194.4151 +{
194.4152 +    cmsFormattersFactoryList* f;
194.4153 +
194.4154 +    for (f = FactoryList; f != NULL; f = f ->Next) {
194.4155 +
194.4156 +        cmsFormatter fn = f ->Factory(Type, Dir, dwFlags);
194.4157 +        if (fn.Fmt16 != NULL) return fn;
194.4158      }
194.4159  
194.4160 +    // Revert to default
194.4161 +    if (Dir == cmsFormatterInput)
194.4162 +        return _cmsGetStockInputFormatter(Type, dwFlags);
194.4163 +    else
194.4164 +        return _cmsGetStockOutputFormatter(Type, dwFlags);
194.4165  }
194.4166  
194.4167 -void LCMSEXPORT cmsGetUserFormatters(cmsHTRANSFORM hTransform,
194.4168 -                                     LPDWORD InputFormat, cmsFORMATTER* Input,
194.4169 -                                     LPDWORD OutputFormat, cmsFORMATTER* Output)
194.4170 +
194.4171 +// Return whatever given formatter refers to float values
194.4172 +cmsBool  _cmsFormatterIsFloat(cmsUInt32Number Type)
194.4173  {
194.4174 -    _LPcmsTRANSFORM xform = (_LPcmsTRANSFORM) (LPSTR) hTransform;
194.4175 -
194.4176 -    if (Input)        *Input =  (cmsFORMATTER) xform ->FromInput;
194.4177 -    if (InputFormat)  *InputFormat = xform -> InputFormat;
194.4178 -    if (Output)       *Output = (cmsFORMATTER) xform ->ToOutput;
194.4179 -    if (OutputFormat) *OutputFormat = xform -> OutputFormat;
194.4180 +    return T_FLOAT(Type) ? TRUE : FALSE;
194.4181  }
194.4182  
194.4183 -
194.4184 -// Change format of yet existing transform. No colorspace checking is performed
194.4185 -
194.4186 -void LCMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform,
194.4187 -                                        DWORD dwInputFormat,
194.4188 -                                        DWORD dwOutputFormat)
194.4189 +// Return whatever given formatter refers to 8 bits
194.4190 +cmsBool  _cmsFormatterIs8bit(cmsUInt32Number Type)
194.4191  {
194.4192 -
194.4193 -    cmsSetUserFormatters(hTransform,
194.4194 -                        dwInputFormat,
194.4195 -                        (cmsFORMATTER) _cmsIdentifyInputFormat((_LPcmsTRANSFORM) hTransform, dwInputFormat),
194.4196 -                        dwOutputFormat,
194.4197 -                        (cmsFORMATTER) _cmsIdentifyOutputFormat((_LPcmsTRANSFORM) hTransform, dwOutputFormat));
194.4198 +    int Bytes = T_BYTES(Type);
194.4199 +
194.4200 +    return (Bytes == 1);
194.4201  }
194.4202 +
194.4203 +// Build a suitable formatter for the colorspace of this profile
194.4204 +cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
194.4205 +{
194.4206 +
194.4207 +    cmsColorSpaceSignature ColorSpace      = cmsGetColorSpace(hProfile);
194.4208 +    cmsUInt32Number        ColorSpaceBits  = _cmsLCMScolorSpace(ColorSpace);
194.4209 +    cmsUInt32Number        nOutputChans    = cmsChannelsOf(ColorSpace);
194.4210 +    cmsUInt32Number        Float           = lIsFloat ? 1 : 0;
194.4211 +
194.4212 +    // Create a fake formatter for result
194.4213 +    return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
194.4214 +}
194.4215 +
194.4216 +// Build a suitable formatter for the colorspace of this profile
194.4217 +cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat)
194.4218 +{
194.4219 +
194.4220 +    cmsColorSpaceSignature ColorSpace      = cmsGetPCS(hProfile);
194.4221 +    int                    ColorSpaceBits  = _cmsLCMScolorSpace(ColorSpace);
194.4222 +    cmsUInt32Number        nOutputChans    = cmsChannelsOf(ColorSpace);
194.4223 +    cmsUInt32Number        Float           = lIsFloat ? 1 : 0;
194.4224 +
194.4225 +    // Create a fake formatter for result
194.4226 +    return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
194.4227 +}
   195.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmspcs.c	Thu Sep 23 17:33:40 2010 -0700
   195.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmspcs.c	Fri Sep 24 16:41:32 2010 -0700
   195.3 @@ -27,9 +27,10 @@
   195.4  // However, the following notice accompanied the original version of this
   195.5  // file:
   195.6  //
   195.7 +//---------------------------------------------------------------------------------
   195.8  //
   195.9 -//  Little cms
  195.10 -//  Copyright (C) 1998-2007 Marti Maria
  195.11 +//  Little Color Management System
  195.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  195.13  //
  195.14  // Permission is hereby granted, free of charge, to any person obtaining
  195.15  // a copy of this software and associated documentation files (the "Software"),
  195.16 @@ -48,11 +49,13 @@
  195.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  195.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  195.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  195.20 +//
  195.21 +//---------------------------------------------------------------------------------
  195.22 +//
  195.23 +
  195.24 +#include "lcms2_internal.h"
  195.25  
  195.26  //      inter PCS conversions XYZ <-> CIE L* a* b*
  195.27 -
  195.28 -#include "lcms.h"
  195.29 -
  195.30  /*
  195.31  
  195.32  
  195.33 @@ -75,7 +78,7 @@
  195.34  
  195.35  
  195.36  
  195.37 -       Following ICC. PCS in Lab is coded as:
  195.38 +       PCS in Lab2 is encoded as:
  195.39  
  195.40                8 bit Lab PCS:
  195.41  
  195.42 @@ -90,9 +93,6 @@
  195.43                       b*
  195.44  
  195.45  
  195.46 -       We are always playing with 16 bits-data, so I will ignore the
  195.47 -       8-bits encoding scheme.
  195.48 -
  195.49  
  195.50  Interchange Space   Component     Actual Range        Encoded Range
  195.51  CIE XYZ             X             0 -> 1.99997        0x0000 -> 0xffff
  195.52 @@ -116,318 +116,134 @@
  195.53  
  195.54  */
  195.55  
  195.56 +// Conversions
  195.57 +void CMSEXPORT cmsXYZ2xyY(cmsCIExyY* Dest, const cmsCIEXYZ* Source)
  195.58 +{
  195.59 +    cmsFloat64Number ISum;
  195.60  
  195.61 +    ISum = 1./(Source -> X + Source -> Y + Source -> Z);
  195.62  
  195.63 +    Dest -> x = (Source -> X) * ISum;
  195.64 +    Dest -> y = (Source -> Y) * ISum;
  195.65 +    Dest -> Y = Source -> Y;
  195.66 +}
  195.67  
  195.68 -// On most modern computers, D > 4 M (i.e. a division takes more than 4
  195.69 -// multiplications worth of time), so it is probably preferable to compute
  195.70 -// a 24 bit result directly.
  195.71 -
  195.72 -// #define ITERATE 1
  195.73 -
  195.74 -static
  195.75 -float CubeRoot(float x)
  195.76 +void CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source)
  195.77  {
  195.78 -       float fr, r;
  195.79 -       int ex, shx;
  195.80 -
  195.81 -       /* Argument reduction */
  195.82 -       fr = (float) frexp(x, &ex); /* separate into mantissa and exponent */
  195.83 -       shx = ex % 3;
  195.84 -
  195.85 -       if (shx > 0)
  195.86 -              shx -= 3; /* compute shx such that (ex - shx) is divisible by 3 */
  195.87 -
  195.88 -       ex = (ex - shx) / 3;        /* exponent of cube root */
  195.89 -       fr = (float) ldexp(fr, shx);
  195.90 -
  195.91 -       /* 0.125 <= fr < 1.0 */
  195.92 -
  195.93 -#ifdef ITERATE
  195.94 -       /* Compute seed with a quadratic approximation */
  195.95 -
  195.96 -       fr = (-0.46946116F * fr + 1.072302F) * fr + 0.3812513F;/* 0.5<=fr<1 */
  195.97 -       r = ldexp(fr, ex);          /* 6 bits of precision */
  195.98 -
  195.99 -       /* Newton-Raphson iterations */
 195.100 -
 195.101 -       r = (float)(2.0/3.0) * r + (float)(1.0/3.0) * x / (r * r); /* 12 bits */
 195.102 -       r = (float)(2.0/3.0) * r + (float)(1.0/3.0) * x / (r * r); /* 24 bits */
 195.103 -#else /* ITERATE */
 195.104 -
 195.105 -       /* Use quartic rational polynomial with error < 2^(-24) */
 195.106 -
 195.107 -       fr = (float) (((((45.2548339756803022511987494 * fr +
 195.108 -       192.2798368355061050458134625) * fr +
 195.109 -       119.1654824285581628956914143) * fr +
 195.110 -       13.43250139086239872172837314) * fr +
 195.111 -       0.1636161226585754240958355063)
 195.112 -       /
 195.113 -       ((((14.80884093219134573786480845 * fr +
 195.114 -       151.9714051044435648658557668) * fr +
 195.115 -       168.5254414101568283957668343) * fr +
 195.116 -       33.9905941350215598754191872) * fr +
 195.117 -       1.0));
 195.118 -       r = (float) ldexp(fr, ex); /* 24 bits of precision */
 195.119 -#endif
 195.120 -       return r;
 195.121 +    Dest -> X = (Source -> x / Source -> y) * Source -> Y;
 195.122 +    Dest -> Y = Source -> Y;
 195.123 +    Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y;
 195.124  }
 195.125  
 195.126  static
 195.127 -double f(double t)
 195.128 +cmsFloat64Number f(cmsFloat64Number t)
 195.129  {
 195.130 +    const cmsFloat64Number Limit = (24.0/116.0) * (24.0/116.0) * (24.0/116.0);
 195.131  
 195.132 -      const double Limit = (24.0/116.0) * (24.0/116.0) * (24.0/116.0);
 195.133 -
 195.134 -       if (t <= Limit)
 195.135 -              return (841.0/108.0) * t + (16.0/116.0);
 195.136 -       else
 195.137 -              return CubeRoot((float) t);
 195.138 +    if (t <= Limit)
 195.139 +        return (841.0/108.0) * t + (16.0/116.0);
 195.140 +    else
 195.141 +        return pow(t, 1.0/3.0);
 195.142  }
 195.143  
 195.144 +static
 195.145 +cmsFloat64Number f_1(cmsFloat64Number t)
 195.146 +{
 195.147 +    const cmsFloat64Number Limit = (24.0/116.0);
 195.148  
 195.149 -static
 195.150 -double f_1(double t)
 195.151 -{
 195.152 -       const double Limit = (24.0/116.0);
 195.153 +    if (t <= Limit) {
 195.154 +        return (108.0/841.0) * (t - (16.0/116.0));
 195.155 +    }
 195.156  
 195.157 -       if (t <= Limit)
 195.158 -       {
 195.159 -              double tmp;
 195.160 -
 195.161 -              tmp = (108.0/841.0) * (t - (16.0/116.0));
 195.162 -              if (tmp <= 0.0) return 0.0;
 195.163 -              else return tmp;
 195.164 -       }
 195.165 -
 195.166 -       return t * t * t;
 195.167 +    return t * t * t;
 195.168  }
 195.169  
 195.170  
 195.171 +// Standard XYZ to Lab. it can handle negative XZY numbers in some cases
 195.172 +void CMSEXPORT cmsXYZ2Lab(const cmsCIEXYZ* WhitePoint, cmsCIELab* Lab, const cmsCIEXYZ* xyz)
 195.173 +{
 195.174 +    cmsFloat64Number fx, fy, fz;
 195.175  
 195.176 -void LCMSEXPORT cmsXYZ2Lab(LPcmsCIEXYZ WhitePoint, LPcmsCIELab Lab, const cmsCIEXYZ* xyz)
 195.177 -{
 195.178 -       double fx, fy, fz;
 195.179 +    if (WhitePoint == NULL)
 195.180 +        WhitePoint = cmsD50_XYZ();
 195.181  
 195.182 -       if (xyz -> X == 0 && xyz -> Y == 0 && xyz -> Z == 0)
 195.183 -       {
 195.184 -        Lab -> L = 0;
 195.185 -        Lab -> a = 0;
 195.186 -        Lab -> b = 0;
 195.187 -        return;
 195.188 -       }
 195.189 +    fx = f(xyz->X / WhitePoint->X);
 195.190 +    fy = f(xyz->Y / WhitePoint->Y);
 195.191 +    fz = f(xyz->Z / WhitePoint->Z);
 195.192  
 195.193 -       if (WhitePoint == NULL)
 195.194 -            WhitePoint = cmsD50_XYZ();
 195.195 -
 195.196 -       fx = f(xyz->X / WhitePoint->X);
 195.197 -       fy = f(xyz->Y / WhitePoint->Y);
 195.198 -       fz = f(xyz->Z / WhitePoint->Z);
 195.199 -
 195.200 -       Lab->L = 116.0* fy - 16.;
 195.201 -
 195.202 -       Lab->a = 500.0*(fx - fy);
 195.203 -       Lab->b = 200.0*(fy - fz);
 195.204 +    Lab->L = 116.0*fy - 16.0;
 195.205 +    Lab->a = 500.0*(fx - fy);
 195.206 +    Lab->b = 200.0*(fy - fz);
 195.207  }
 195.208  
 195.209  
 195.210 +// Standard XYZ to Lab. It can return negative XYZ in some cases
 195.211 +void CMSEXPORT cmsLab2XYZ(const cmsCIEXYZ* WhitePoint, cmsCIEXYZ* xyz,  const cmsCIELab* Lab)
 195.212 +{
 195.213 +    cmsFloat64Number x, y, z;
 195.214  
 195.215 -void cmsXYZ2LabEncoded(WORD XYZ[3], WORD Lab[3])
 195.216 -{
 195.217 -       Fixed32 X, Y, Z;
 195.218 -       double x, y, z, L, a, b;
 195.219 -       double fx, fy, fz;
 195.220 -       Fixed32 wL, wa, wb;
 195.221 +    if (WhitePoint == NULL)
 195.222 +        WhitePoint = cmsD50_XYZ();
 195.223  
 195.224 -       X = (Fixed32) XYZ[0] << 1;
 195.225 -       Y = (Fixed32) XYZ[1] << 1;
 195.226 -       Z = (Fixed32) XYZ[2] << 1;
 195.227 +    y = (Lab-> L + 16.0) / 116.0;
 195.228 +    x = y + 0.002 * Lab -> a;
 195.229 +    z = y - 0.005 * Lab -> b;
 195.230  
 195.231 -
 195.232 -       if (X==0 && Y==0 && Z==0) {
 195.233 -
 195.234 -                     Lab[0] = 0;
 195.235 -                     Lab[1] = Lab[2] =  0x8000;
 195.236 -                     return;
 195.237 -       }
 195.238 -
 195.239 -       // PCS is in D50
 195.240 -
 195.241 -
 195.242 -       x = FIXED_TO_DOUBLE(X) / D50X;
 195.243 -       y = FIXED_TO_DOUBLE(Y) / D50Y;
 195.244 -       z = FIXED_TO_DOUBLE(Z) / D50Z;
 195.245 -
 195.246 -
 195.247 -       fx = f(x);
 195.248 -       fy = f(y);
 195.249 -       fz = f(z);
 195.250 -
 195.251 -       L = 116.* fy - 16.;
 195.252 -
 195.253 -       a = 500.*(fx - fy);
 195.254 -       b = 200.*(fy - fz);
 195.255 -
 195.256 -       a += 128.;
 195.257 -       b += 128.;
 195.258 -
 195.259 -       wL = (int) (L * 652.800 + .5);
 195.260 -       wa = (int) (a * 256.0   + .5);
 195.261 -       wb = (int) (b * 256.0   + .5);
 195.262 -
 195.263 -
 195.264 -       Lab[0] = Clamp_L(wL);
 195.265 -       Lab[1] = Clamp_ab(wa);
 195.266 -       Lab[2] = Clamp_ab(wb);
 195.267 -
 195.268 -
 195.269 -}
 195.270 -
 195.271 -
 195.272 -
 195.273 -
 195.274 -
 195.275 -
 195.276 -void LCMSEXPORT cmsLab2XYZ(LPcmsCIEXYZ WhitePoint, LPcmsCIEXYZ xyz,  const cmsCIELab* Lab)
 195.277 -{
 195.278 -        double x, y, z;
 195.279 -
 195.280 -        if (Lab -> L <= 0) {
 195.281 -               xyz -> X = 0;
 195.282 -               xyz -> Y = 0;
 195.283 -               xyz -> Z = 0;
 195.284 -               return;
 195.285 -        }
 195.286 -
 195.287 -
 195.288 -       if (WhitePoint == NULL)
 195.289 -            WhitePoint = cmsD50_XYZ();
 195.290 -
 195.291 -       y = (Lab-> L + 16.0) / 116.0;
 195.292 -       x = y + 0.002 * Lab -> a;
 195.293 -       z = y - 0.005 * Lab -> b;
 195.294 -
 195.295 -       xyz -> X = f_1(x) * WhitePoint -> X;
 195.296 -       xyz -> Y = f_1(y) * WhitePoint -> Y;
 195.297 -       xyz -> Z = f_1(z) * WhitePoint -> Z;
 195.298 -
 195.299 -}
 195.300 -
 195.301 -
 195.302 -
 195.303 -void cmsLab2XYZEncoded(WORD Lab[3], WORD XYZ[3])
 195.304 -{
 195.305 -       double L, a, b;
 195.306 -       double X, Y, Z, x, y, z;
 195.307 -
 195.308 -
 195.309 -       L = ((double) Lab[0] * 100.0) / 65280.0;
 195.310 -       if (L==0.0) {
 195.311 -
 195.312 -       XYZ[0] = 0; XYZ[1] = 0; XYZ[2] = 0;
 195.313 -       return;
 195.314 -       }
 195.315 -
 195.316 -       a = ((double) Lab[1] / 256.0) - 128.0;
 195.317 -       b = ((double) Lab[2] / 256.0) - 128.0;
 195.318 -
 195.319 -       y = (L + 16.) / 116.0;
 195.320 -       x = y + 0.002 * a;
 195.321 -       z = y - 0.005 * b;
 195.322 -
 195.323 -       X = f_1(x) * D50X;
 195.324 -       Y = f_1(y) * D50Y;
 195.325 -       Z = f_1(z) * D50Z;
 195.326 -
 195.327 -       // Convert to 1.15 fixed format PCS
 195.328 -
 195.329 -
 195.330 -       XYZ[0] = _cmsClampWord((int) floor(X * 32768.0 + 0.5));
 195.331 -       XYZ[1] = _cmsClampWord((int) floor(Y * 32768.0 + 0.5));
 195.332 -       XYZ[2] = _cmsClampWord((int) floor(Z * 32768.0 + 0.5));
 195.333 -
 195.334 +    xyz -> X = f_1(x) * WhitePoint -> X;
 195.335 +    xyz -> Y = f_1(y) * WhitePoint -> Y;
 195.336 +    xyz -> Z = f_1(z) * WhitePoint -> Z;
 195.337  
 195.338  }
 195.339  
 195.340  static
 195.341 -double L2float3(WORD v)
 195.342 +cmsFloat64Number L2float2(cmsUInt16Number v)
 195.343  {
 195.344 -       Fixed32 fix32;
 195.345 -
 195.346 -       fix32 = (Fixed32) v;
 195.347 -       return (double) fix32 / 652.800;
 195.348 +    return (cmsFloat64Number) v / 652.800;
 195.349  }
 195.350  
 195.351 -
 195.352  // the a/b part
 195.353 -
 195.354  static
 195.355 -double ab2float3(WORD v)
 195.356 +cmsFloat64Number ab2float2(cmsUInt16Number v)
 195.357  {
 195.358 -       Fixed32 fix32;
 195.359 -
 195.360 -       fix32 = (Fixed32) v;
 195.361 -       return ((double) fix32/256.0)-128.0;
 195.362 +    return ((cmsFloat64Number) v / 256.0) - 128.0;
 195.363  }
 195.364  
 195.365  static
 195.366 -WORD L2Fix3(double L)
 195.367 +cmsUInt16Number L2Fix2(cmsFloat64Number L)
 195.368  {
 195.369 -        return (WORD) (L *  652.800 + 0.5);
 195.370 +    return _cmsQuickSaturateWord(L *  652.8);
 195.371  }
 195.372  
 195.373  static
 195.374 -WORD ab2Fix3(double ab)
 195.375 +cmsUInt16Number ab2Fix2(cmsFloat64Number ab)
 195.376  {
 195.377 -        return (WORD) ((ab + 128.0) * 256.0 + 0.5);
 195.378 +    return _cmsQuickSaturateWord((ab + 128.0) * 256.0);
 195.379  }
 195.380  
 195.381  
 195.382 -// ICC 4.0 -- ICC has changed PCS Lab encoding.
 195.383 -
 195.384  static
 195.385 -WORD L2Fix4(double L)
 195.386 +cmsFloat64Number L2float4(cmsUInt16Number v)
 195.387  {
 195.388 -     return (WORD) (L *  655.35 + 0.5);
 195.389 +    return (cmsFloat64Number) v / 655.35;
 195.390  }
 195.391  
 195.392 +// the a/b part
 195.393  static
 195.394 -WORD ab2Fix4(double ab)
 195.395 +cmsFloat64Number ab2float4(cmsUInt16Number v)
 195.396  {
 195.397 -        return (WORD) ((ab + 128.0) * 257.0 + 0.5);
 195.398 +    return ((cmsFloat64Number) v / 257.0) - 128.0;
 195.399  }
 195.400  
 195.401 -static
 195.402 -double L2float4(WORD v)
 195.403 +
 195.404 +void CMSEXPORT cmsLabEncoded2FloatV2(cmsCIELab* Lab, const cmsUInt16Number wLab[3])
 195.405  {
 195.406 -       Fixed32 fix32;
 195.407 -
 195.408 -       fix32 = (Fixed32) v;
 195.409 -       return (double) fix32 / 655.35;
 195.410 +        Lab->L = L2float2(wLab[0]);
 195.411 +        Lab->a = ab2float2(wLab[1]);
 195.412 +        Lab->b = ab2float2(wLab[2]);
 195.413  }
 195.414  
 195.415  
 195.416 -// the a/b part
 195.417 -
 195.418 -static
 195.419 -double ab2float4(WORD v)
 195.420 -{
 195.421 -       Fixed32 fix32;
 195.422 -
 195.423 -       fix32 = (Fixed32) v;
 195.424 -       return ((double) fix32/257.0)-128.0;
 195.425 -}
 195.426 -
 195.427 -
 195.428 -void LCMSEXPORT cmsLabEncoded2Float(LPcmsCIELab Lab, const WORD wLab[3])
 195.429 -{
 195.430 -        Lab->L = L2float3(wLab[0]);
 195.431 -        Lab->a = ab2float3(wLab[1]);
 195.432 -        Lab->b = ab2float3(wLab[2]);
 195.433 -}
 195.434 -
 195.435 -
 195.436 -void LCMSEXPORT cmsLabEncoded2Float4(LPcmsCIELab Lab, const WORD wLab[3])
 195.437 +void CMSEXPORT cmsLabEncoded2Float(cmsCIELab* Lab, const cmsUInt16Number wLab[3])
 195.438  {
 195.439          Lab->L = L2float4(wLab[0]);
 195.440          Lab->a = ab2float4(wLab[1]);
 195.441 @@ -435,122 +251,147 @@
 195.442  }
 195.443  
 195.444  static
 195.445 -double Clamp_L_double(double L)
 195.446 +cmsFloat64Number Clamp_L_doubleV2(cmsFloat64Number L)
 195.447  {
 195.448 +    const cmsFloat64Number L_max = (cmsFloat64Number) (0xFFFF * 100.0) / 0xFF00;
 195.449 +
 195.450      if (L < 0) L = 0;
 195.451 -    if (L > 100) L = 100;
 195.452 +    if (L > L_max) L = L_max;
 195.453  
 195.454      return L;
 195.455  }
 195.456  
 195.457  
 195.458  static
 195.459 -double Clamp_ab_double(double ab)
 195.460 +cmsFloat64Number Clamp_ab_doubleV2(cmsFloat64Number ab)
 195.461  {
 195.462 -    if (ab < -128) ab = -128.0;
 195.463 -    if (ab > +127.9961) ab = +127.9961;
 195.464 +    if (ab < MIN_ENCODEABLE_ab2) ab = MIN_ENCODEABLE_ab2;
 195.465 +    if (ab > MAX_ENCODEABLE_ab2) ab = MAX_ENCODEABLE_ab2;
 195.466  
 195.467      return ab;
 195.468  }
 195.469  
 195.470 -void LCMSEXPORT cmsFloat2LabEncoded(WORD wLab[3], const cmsCIELab* fLab)
 195.471 +void CMSEXPORT cmsFloat2LabEncodedV2(cmsUInt16Number wLab[3], const cmsCIELab* fLab)
 195.472  {
 195.473      cmsCIELab Lab;
 195.474  
 195.475 +    Lab.L = Clamp_L_doubleV2(fLab ->L);
 195.476 +    Lab.a = Clamp_ab_doubleV2(fLab ->a);
 195.477 +    Lab.b = Clamp_ab_doubleV2(fLab ->b);
 195.478  
 195.479 -    Lab.L = Clamp_L_double(fLab ->L);
 195.480 -    Lab.a = Clamp_ab_double(fLab ->a);
 195.481 -    Lab.b = Clamp_ab_double(fLab ->b);
 195.482 -
 195.483 -    wLab[0] = L2Fix3(Lab.L);
 195.484 -    wLab[1] = ab2Fix3(Lab.a);
 195.485 -    wLab[2] = ab2Fix3(Lab.b);
 195.486 +    wLab[0] = L2Fix2(Lab.L);
 195.487 +    wLab[1] = ab2Fix2(Lab.a);
 195.488 +    wLab[2] = ab2Fix2(Lab.b);
 195.489  }
 195.490  
 195.491  
 195.492 -void LCMSEXPORT cmsFloat2LabEncoded4(WORD wLab[3], const cmsCIELab* fLab)
 195.493 +static
 195.494 +cmsFloat64Number Clamp_L_doubleV4(cmsFloat64Number L)
 195.495 +{
 195.496 +    if (L < 0) L = 0;
 195.497 +    if (L > 100.0) L = 100.0;
 195.498 +
 195.499 +    return L;
 195.500 +}
 195.501 +
 195.502 +static
 195.503 +cmsFloat64Number Clamp_ab_doubleV4(cmsFloat64Number ab)
 195.504 +{
 195.505 +    if (ab < MIN_ENCODEABLE_ab4) ab = MIN_ENCODEABLE_ab4;
 195.506 +    if (ab > MAX_ENCODEABLE_ab4) ab = MAX_ENCODEABLE_ab4;
 195.507 +
 195.508 +    return ab;
 195.509 +}
 195.510 +
 195.511 +static
 195.512 +cmsUInt16Number L2Fix4(cmsFloat64Number L)
 195.513 +{
 195.514 +    return _cmsQuickSaturateWord(L *  655.35);
 195.515 +}
 195.516 +
 195.517 +static
 195.518 +cmsUInt16Number ab2Fix4(cmsFloat64Number ab)
 195.519 +{
 195.520 +    return _cmsQuickSaturateWord((ab + 128.0) * 257.0);
 195.521 +}
 195.522 +
 195.523 +void CMSEXPORT cmsFloat2LabEncoded(cmsUInt16Number wLab[3], const cmsCIELab* fLab)
 195.524  {
 195.525      cmsCIELab Lab;
 195.526  
 195.527 -
 195.528 -    Lab.L = fLab ->L;
 195.529 -    Lab.a = fLab ->a;
 195.530 -    Lab.b = fLab ->b;
 195.531 -
 195.532 -
 195.533 -    if (Lab.L < 0) Lab.L = 0;
 195.534 -    if (Lab.L > 100.) Lab.L = 100.;
 195.535 -
 195.536 -    if (Lab.a < -128.) Lab.a = -128.;
 195.537 -    if (Lab.a > 127.) Lab.a = 127.;
 195.538 -    if (Lab.b < -128.) Lab.b = -128.;
 195.539 -    if (Lab.b > 127.) Lab.b = 127.;
 195.540 -
 195.541 +    Lab.L = Clamp_L_doubleV4(fLab ->L);
 195.542 +    Lab.a = Clamp_ab_doubleV4(fLab ->a);
 195.543 +    Lab.b = Clamp_ab_doubleV4(fLab ->b);
 195.544  
 195.545      wLab[0] = L2Fix4(Lab.L);
 195.546      wLab[1] = ab2Fix4(Lab.a);
 195.547      wLab[2] = ab2Fix4(Lab.b);
 195.548  }
 195.549  
 195.550 -
 195.551 -
 195.552 -
 195.553 -void LCMSEXPORT cmsLab2LCh(LPcmsCIELCh LCh, const cmsCIELab* Lab)
 195.554 +// Auxiliar: convert to Radians
 195.555 +static
 195.556 +cmsFloat64Number RADIANS(cmsFloat64Number deg)
 195.557  {
 195.558 -    double a, b;
 195.559 -
 195.560 -    LCh -> L = Clamp_L_double(Lab -> L);
 195.561 -
 195.562 -    a = Clamp_ab_double(Lab -> a);
 195.563 -    b = Clamp_ab_double(Lab -> b);
 195.564 -
 195.565 -    LCh -> C = pow(a * a + b * b, 0.5);
 195.566 -
 195.567 -    if (a == 0 && b == 0)
 195.568 -            LCh -> h   = 0;
 195.569 -    else
 195.570 -            LCh -> h = atan2(b, a);
 195.571 -
 195.572 -
 195.573 -    LCh -> h *= (180. / M_PI);
 195.574 -
 195.575 -
 195.576 -    while (LCh -> h >= 360.)         // Not necessary, but included as a check.
 195.577 -                LCh -> h -= 360.;
 195.578 -
 195.579 -    while (LCh -> h < 0)
 195.580 -                LCh -> h += 360.;
 195.581 -
 195.582 +    return (deg * M_PI) / 180.;
 195.583  }
 195.584  
 195.585  
 195.586 +// Auxiliar: atan2 but operating in degrees and returning 0 if a==b==0
 195.587 +static
 195.588 +cmsFloat64Number atan2deg(cmsFloat64Number a, cmsFloat64Number b)
 195.589 +{
 195.590 +   cmsFloat64Number h;
 195.591  
 195.592 +   if (a == 0 && b == 0)
 195.593 +            h   = 0;
 195.594 +    else
 195.595 +            h = atan2(a, b);
 195.596  
 195.597 -void LCMSEXPORT cmsLCh2Lab(LPcmsCIELab Lab, const cmsCIELCh* LCh)
 195.598 -{
 195.599 +    h *= (180. / M_PI);
 195.600  
 195.601 -    double h = (LCh -> h * M_PI) / 180.0;
 195.602 +    while (h > 360.)
 195.603 +        h -= 360.;
 195.604  
 195.605 -    Lab -> L = Clamp_L_double(LCh -> L);
 195.606 -    Lab -> a = Clamp_ab_double(LCh -> C * cos(h));
 195.607 -    Lab -> b = Clamp_ab_double(LCh -> C * sin(h));
 195.608 +    while ( h < 0)
 195.609 +        h += 360.;
 195.610  
 195.611 +    return h;
 195.612  }
 195.613  
 195.614  
 195.615 +// Auxiliar: Square
 195.616 +static
 195.617 +cmsFloat64Number Sqr(cmsFloat64Number v)
 195.618 +{
 195.619 +    return v *  v;
 195.620 +}
 195.621 +// From cylindrical coordinates. No check is performed, then negative values are allowed
 195.622 +void CMSEXPORT cmsLab2LCh(cmsCIELCh* LCh, const cmsCIELab* Lab)
 195.623 +{
 195.624 +    LCh -> L = Lab -> L;
 195.625 +    LCh -> C = pow(Sqr(Lab ->a) + Sqr(Lab ->b), 0.5);
 195.626 +    LCh -> h = atan2deg(Lab ->b, Lab ->a);
 195.627 +}
 195.628  
 195.629  
 195.630 +// To cylindrical coordinates. No check is performed, then negative values are allowed
 195.631 +void CMSEXPORT cmsLCh2Lab(cmsCIELab* Lab, const cmsCIELCh* LCh)
 195.632 +{
 195.633 +    cmsFloat64Number h = (LCh -> h * M_PI) / 180.0;
 195.634 +
 195.635 +    Lab -> L = LCh -> L;
 195.636 +    Lab -> a = LCh -> C * cos(h);
 195.637 +    Lab -> b = LCh -> C * sin(h);
 195.638 +}
 195.639  
 195.640  // In XYZ All 3 components are encoded using 1.15 fixed point
 195.641 -
 195.642  static
 195.643 -WORD XYZ2Fix(double d)
 195.644 +cmsUInt16Number XYZ2Fix(cmsFloat64Number d)
 195.645  {
 195.646 -    return (WORD) floor(d * 32768.0 + 0.5);
 195.647 +    return _cmsQuickSaturateWord(d * 32768.0);
 195.648  }
 195.649  
 195.650 -
 195.651 -void LCMSEXPORT cmsFloat2XYZEncoded(WORD XYZ[3], const cmsCIEXYZ* fXYZ)
 195.652 +void CMSEXPORT cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3], const cmsCIEXYZ* fXYZ)
 195.653  {
 195.654      cmsCIEXYZ xyz;
 195.655  
 195.656 @@ -558,73 +399,557 @@
 195.657      xyz.Y = fXYZ -> Y;
 195.658      xyz.Z = fXYZ -> Z;
 195.659  
 195.660 -
 195.661      // Clamp to encodeable values.
 195.662 -    // 1.99997 is reserved as out-of-gamut marker
 195.663 -
 195.664 -
 195.665      if (xyz.Y <= 0) {
 195.666  
 195.667 -                xyz.X = 0;
 195.668 -                xyz.Y = 0;
 195.669 -                xyz.Z = 0;
 195.670 +        xyz.X = 0;
 195.671 +        xyz.Y = 0;
 195.672 +        xyz.Z = 0;
 195.673      }
 195.674  
 195.675 -
 195.676 -    if (xyz.X > 1.99996)
 195.677 -           xyz.X = 1.99996;
 195.678 +    if (xyz.X > MAX_ENCODEABLE_XYZ)
 195.679 +        xyz.X = MAX_ENCODEABLE_XYZ;
 195.680  
 195.681      if (xyz.X < 0)
 195.682 -           xyz.X = 0;
 195.683 +        xyz.X = 0;
 195.684  
 195.685 -    if (xyz.Y > 1.99996)
 195.686 -                xyz.Y = 1.99996;
 195.687 +    if (xyz.Y > MAX_ENCODEABLE_XYZ)
 195.688 +        xyz.Y = MAX_ENCODEABLE_XYZ;
 195.689  
 195.690      if (xyz.Y < 0)
 195.691 -           xyz.Y = 0;
 195.692 +        xyz.Y = 0;
 195.693  
 195.694 -
 195.695 -    if (xyz.Z > 1.99996)
 195.696 -                xyz.Z = 1.99996;
 195.697 +    if (xyz.Z > MAX_ENCODEABLE_XYZ)
 195.698 +        xyz.Z = MAX_ENCODEABLE_XYZ;
 195.699  
 195.700      if (xyz.Z < 0)
 195.701 -           xyz.Z = 0;
 195.702 -
 195.703 +        xyz.Z = 0;
 195.704  
 195.705  
 195.706      XYZ[0] = XYZ2Fix(xyz.X);
 195.707      XYZ[1] = XYZ2Fix(xyz.Y);
 195.708      XYZ[2] = XYZ2Fix(xyz.Z);
 195.709 -
 195.710  }
 195.711  
 195.712  
 195.713 -//  To convert from Fixed 1.15 point to double
 195.714 +//  To convert from Fixed 1.15 point to cmsFloat64Number
 195.715 +static
 195.716 +cmsFloat64Number XYZ2float(cmsUInt16Number v)
 195.717 +{
 195.718 +    cmsS15Fixed16Number fix32;
 195.719  
 195.720 -static
 195.721 -double XYZ2float(WORD v)
 195.722 -{
 195.723 -       Fixed32 fix32;
 195.724 +    // From 1.15 to 15.16
 195.725 +    fix32 = v << 1;
 195.726  
 195.727 -       // From 1.15 to 15.16
 195.728 -
 195.729 -       fix32 = v << 1;
 195.730 -
 195.731 -       // From fixed 15.16 to double
 195.732 -
 195.733 -       return FIXED_TO_DOUBLE(fix32);
 195.734 +    // From fixed 15.16 to cmsFloat64Number
 195.735 +    return _cms15Fixed16toDouble(fix32);
 195.736  }
 195.737  
 195.738  
 195.739 -void LCMSEXPORT cmsXYZEncoded2Float(LPcmsCIEXYZ fXYZ, const WORD XYZ[3])
 195.740 +void CMSEXPORT cmsXYZEncoded2Float(cmsCIEXYZ* fXYZ, const cmsUInt16Number XYZ[3])
 195.741  {
 195.742 -
 195.743      fXYZ -> X = XYZ2float(XYZ[0]);
 195.744      fXYZ -> Y = XYZ2float(XYZ[1]);
 195.745      fXYZ -> Z = XYZ2float(XYZ[2]);
 195.746 -
 195.747  }
 195.748  
 195.749  
 195.750 +// Returns dE on two Lab values
 195.751 +cmsFloat64Number CMSEXPORT cmsDeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2)
 195.752 +{
 195.753 +    cmsFloat64Number dL, da, db;
 195.754  
 195.755 +    dL = fabs(Lab1 -> L - Lab2 -> L);
 195.756 +    da = fabs(Lab1 -> a - Lab2 -> a);
 195.757 +    db = fabs(Lab1 -> b - Lab2 -> b);
 195.758  
 195.759 +    return pow(Sqr(dL) + Sqr(da) + Sqr(db), 0.5);
 195.760 +}
 195.761 +
 195.762 +
 195.763 +// Return the CIE94 Delta E
 195.764 +cmsFloat64Number CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2)
 195.765 +{
 195.766 +    cmsCIELCh LCh1, LCh2;
 195.767 +    cmsFloat64Number dE, dL, dC, dh, dhsq;
 195.768 +    cmsFloat64Number c12, sc, sh;
 195.769 +
 195.770 +    dL = fabs(Lab1 ->L - Lab2 ->L);
 195.771 +
 195.772 +    cmsLab2LCh(&LCh1, Lab1);
 195.773 +    cmsLab2LCh(&LCh2, Lab2);
 195.774 +
 195.775 +    dC  = fabs(LCh1.C - LCh2.C);
 195.776 +    dE  = cmsDeltaE(Lab1, Lab2);
 195.777 +
 195.778 +    dhsq = Sqr(dE) - Sqr(dL) - Sqr(dC);
 195.779 +    if (dhsq < 0)
 195.780 +        dh = 0;
 195.781 +    else
 195.782 +        dh = pow(dhsq, 0.5);
 195.783 +
 195.784 +    c12 = sqrt(LCh1.C * LCh2.C);
 195.785 +
 195.786 +    sc = 1.0 + (0.048 * c12);
 195.787 +    sh = 1.0 + (0.014 * c12);
 195.788 +
 195.789 +    return sqrt(Sqr(dL)  + Sqr(dC) / Sqr(sc) + Sqr(dh) / Sqr(sh));
 195.790 +}
 195.791 +
 195.792 +
 195.793 +// Auxiliary
 195.794 +static
 195.795 +cmsFloat64Number ComputeLBFD(const cmsCIELab* Lab)
 195.796 +{
 195.797 +  cmsFloat64Number yt;
 195.798 +
 195.799 +  if (Lab->L > 7.996969)
 195.800 +        yt = (Sqr((Lab->L+16)/116)*((Lab->L+16)/116))*100;
 195.801 +  else
 195.802 +        yt = 100 * (Lab->L / 903.3);
 195.803 +
 195.804 +  return (54.6 * (M_LOG10E * (log(yt + 1.5))) - 9.6);
 195.805 +}
 195.806 +
 195.807 +
 195.808 +
 195.809 +// bfd - gets BFD(1:1) difference between Lab1, Lab2
 195.810 +cmsFloat64Number CMSEXPORT cmsBFDdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2)
 195.811 +{
 195.812 +    cmsFloat64Number lbfd1,lbfd2,AveC,Aveh,dE,deltaL,
 195.813 +        deltaC,deltah,dc,t,g,dh,rh,rc,rt,bfd;
 195.814 +    cmsCIELCh LCh1, LCh2;
 195.815 +
 195.816 +
 195.817 +    lbfd1 = ComputeLBFD(Lab1);
 195.818 +    lbfd2 = ComputeLBFD(Lab2);
 195.819 +    deltaL = lbfd2 - lbfd1;
 195.820 +
 195.821 +    cmsLab2LCh(&LCh1, Lab1);
 195.822 +    cmsLab2LCh(&LCh2, Lab2);
 195.823 +
 195.824 +    deltaC = LCh2.C - LCh1.C;
 195.825 +    AveC = (LCh1.C+LCh2.C)/2;
 195.826 +    Aveh = (LCh1.h+LCh2.h)/2;
 195.827 +
 195.828 +    dE = cmsDeltaE(Lab1, Lab2);
 195.829 +
 195.830 +    if (Sqr(dE)>(Sqr(Lab2->L-Lab1->L)+Sqr(deltaC)))
 195.831 +        deltah = sqrt(Sqr(dE)-Sqr(Lab2->L-Lab1->L)-Sqr(deltaC));
 195.832 +    else
 195.833 +        deltah =0;
 195.834 +
 195.835 +
 195.836 +    dc   = 0.035 * AveC / (1 + 0.00365 * AveC)+0.521;
 195.837 +    g    = sqrt(Sqr(Sqr(AveC))/(Sqr(Sqr(AveC))+14000));
 195.838 +    t    = 0.627+(0.055*cos((Aveh-254)/(180/M_PI))-
 195.839 +           0.040*cos((2*Aveh-136)/(180/M_PI))+
 195.840 +           0.070*cos((3*Aveh-31)/(180/M_PI))+
 195.841 +           0.049*cos((4*Aveh+114)/(180/M_PI))-
 195.842 +           0.015*cos((5*Aveh-103)/(180/M_PI)));
 195.843 +
 195.844 +    dh    = dc*(g*t+1-g);
 195.845 +    rh    = -0.260*cos((Aveh-308)/(180/M_PI))-
 195.846 +           0.379*cos((2*Aveh-160)/(180/M_PI))-
 195.847 +           0.636*cos((3*Aveh+254)/(180/M_PI))+
 195.848 +           0.226*cos((4*Aveh+140)/(180/M_PI))-
 195.849 +           0.194*cos((5*Aveh+280)/(180/M_PI));
 195.850 +
 195.851 +    rc = sqrt((AveC*AveC*AveC*AveC*AveC*AveC)/((AveC*AveC*AveC*AveC*AveC*AveC)+70000000));
 195.852 +    rt = rh*rc;
 195.853 +
 195.854 +    bfd = sqrt(Sqr(deltaL)+Sqr(deltaC/dc)+Sqr(deltah/dh)+(rt*(deltaC/dc)*(deltah/dh)));
 195.855 +
 195.856 +    return bfd;
 195.857 +}
 195.858 +
 195.859 +
 195.860 +//  cmc - CMC(l:c) difference between Lab1, Lab2
 195.861 +cmsFloat64Number CMSEXPORT cmsCMCdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2, cmsFloat64Number l, cmsFloat64Number c)
 195.862 +{
 195.863 +  cmsFloat64Number dE,dL,dC,dh,sl,sc,sh,t,f,cmc;
 195.864 +  cmsCIELCh LCh1, LCh2;
 195.865 +
 195.866 +  if (Lab1 ->L == 0 && Lab2 ->L == 0) return 0;
 195.867 +
 195.868 +  cmsLab2LCh(&LCh1, Lab1);
 195.869 +  cmsLab2LCh(&LCh2, Lab2);
 195.870 +
 195.871 +
 195.872 +  dL = Lab2->L-Lab1->L;
 195.873 +  dC = LCh2.C-LCh1.C;
 195.874 +
 195.875 +  dE = cmsDeltaE(Lab1, Lab2);
 195.876 +
 195.877 +  if (Sqr(dE)>(Sqr(dL)+Sqr(dC)))
 195.878 +            dh = sqrt(Sqr(dE)-Sqr(dL)-Sqr(dC));
 195.879 +  else
 195.880 +            dh =0;
 195.881 +
 195.882 +  if ((LCh1.h > 164) && (LCh1.h < 345))
 195.883 +      t = 0.56 + fabs(0.2 * cos(((LCh1.h + 168)/(180/M_PI))));
 195.884 +  else
 195.885 +      t = 0.36 + fabs(0.4 * cos(((LCh1.h + 35 )/(180/M_PI))));
 195.886 +
 195.887 +   sc  = 0.0638   * LCh1.C / (1 + 0.0131  * LCh1.C) + 0.638;
 195.888 +   sl  = 0.040975 * Lab1->L /(1 + 0.01765 * Lab1->L);
 195.889 +
 195.890 +   if (Lab1->L<16)
 195.891 +         sl = 0.511;
 195.892 +
 195.893 +   f   = sqrt((LCh1.C * LCh1.C * LCh1.C * LCh1.C)/((LCh1.C * LCh1.C * LCh1.C * LCh1.C)+1900));
 195.894 +   sh  = sc*(t*f+1-f);
 195.895 +   cmc = sqrt(Sqr(dL/(l*sl))+Sqr(dC/(c*sc))+Sqr(dh/sh));
 195.896 +
 195.897 +   return cmc;
 195.898 +}
 195.899 +
 195.900 +// dE2000 The weightings KL, KC and KH can be modified to reflect the relative
 195.901 +// importance of lightness, chroma and hue in different industrial applications
 195.902 +cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2,
 195.903 +                                  cmsFloat64Number Kl, cmsFloat64Number Kc, cmsFloat64Number Kh)
 195.904 +{
 195.905 +    cmsFloat64Number L1  = Lab1->L;
 195.906 +    cmsFloat64Number a1  = Lab1->a;
 195.907 +    cmsFloat64Number b1  = Lab1->b;
 195.908 +    cmsFloat64Number C   = sqrt( Sqr(a1) + Sqr(b1) );
 195.909 +
 195.910 +    cmsFloat64Number Ls = Lab2 ->L;
 195.911 +    cmsFloat64Number as = Lab2 ->a;
 195.912 +    cmsFloat64Number bs = Lab2 ->b;
 195.913 +    cmsFloat64Number Cs = sqrt( Sqr(as) + Sqr(bs) );
 195.914 +
 195.915 +    cmsFloat64Number G = 0.5 * ( 1 - sqrt(pow((C + Cs) / 2 , 7.0) / (pow((C + Cs) / 2, 7.0) + pow(25.0, 7.0) ) ));
 195.916 +
 195.917 +    cmsFloat64Number a_p = (1 + G ) * a1;
 195.918 +    cmsFloat64Number b_p = b1;
 195.919 +    cmsFloat64Number C_p = sqrt( Sqr(a_p) + Sqr(b_p));
 195.920 +    cmsFloat64Number h_p = atan2deg(b_p, a_p);
 195.921 +
 195.922 +
 195.923 +    cmsFloat64Number a_ps = (1 + G) * as;
 195.924 +    cmsFloat64Number b_ps = bs;
 195.925 +    cmsFloat64Number C_ps = sqrt(Sqr(a_ps) + Sqr(b_ps));
 195.926 +    cmsFloat64Number h_ps = atan2deg(b_ps, a_ps);
 195.927 +
 195.928 +    cmsFloat64Number meanC_p =(C_p + C_ps) / 2;
 195.929 +
 195.930 +    cmsFloat64Number hps_plus_hp  = h_ps + h_p;
 195.931 +    cmsFloat64Number hps_minus_hp = h_ps - h_p;
 195.932 +
 195.933 +    cmsFloat64Number meanh_p = fabs(hps_minus_hp) <= 180.000001 ? (hps_plus_hp)/2 :
 195.934 +                            (hps_plus_hp) < 360 ? (hps_plus_hp + 360)/2 :
 195.935 +                                                 (hps_plus_hp - 360)/2;
 195.936 +
 195.937 +    cmsFloat64Number delta_h = (hps_minus_hp) <= -180.000001 ?  (hps_minus_hp + 360) :
 195.938 +                            (hps_minus_hp) > 180 ? (hps_minus_hp - 360) :
 195.939 +                                                    (hps_minus_hp);
 195.940 +    cmsFloat64Number delta_L = (Ls - L1);
 195.941 +    cmsFloat64Number delta_C = (C_ps - C_p );
 195.942 +
 195.943 +
 195.944 +    cmsFloat64Number delta_H =2 * sqrt(C_ps*C_p) * sin(RADIANS(delta_h) / 2);
 195.945 +
 195.946 +    cmsFloat64Number T = 1 - 0.17 * cos(RADIANS(meanh_p-30))
 195.947 +                 + 0.24 * cos(RADIANS(2*meanh_p))
 195.948 +                 + 0.32 * cos(RADIANS(3*meanh_p + 6))
 195.949 +                 - 0.2  * cos(RADIANS(4*meanh_p - 63));
 195.950 +
 195.951 +    cmsFloat64Number Sl = 1 + (0.015 * Sqr((Ls + L1) /2- 50) )/ sqrt(20 + Sqr( (Ls+L1)/2 - 50) );
 195.952 +
 195.953 +    cmsFloat64Number Sc = 1 + 0.045 * (C_p + C_ps)/2;
 195.954 +    cmsFloat64Number Sh = 1 + 0.015 * ((C_ps + C_p)/2) * T;
 195.955 +
 195.956 +    cmsFloat64Number delta_ro = 30 * exp( -Sqr(((meanh_p - 275 ) / 25)));
 195.957 +
 195.958 +    cmsFloat64Number Rc = 2 * sqrt(( pow(meanC_p, 7.0) )/( pow(meanC_p, 7.0) + pow(25.0, 7.0)));
 195.959 +
 195.960 +    cmsFloat64Number Rt = -sin(2 * RADIANS(delta_ro)) * Rc;
 195.961 +
 195.962 +    cmsFloat64Number deltaE00 = sqrt( Sqr(delta_L /(Sl * Kl)) +
 195.963 +                            Sqr(delta_C/(Sc * Kc))  +
 195.964 +                            Sqr(delta_H/(Sh * Kh))  +
 195.965 +                            Rt*(delta_C/(Sc * Kc)) * (delta_H / (Sh * Kh)));
 195.966 +
 195.967 +    return deltaE00;
 195.968 +}
 195.969 +
 195.970 +// This function returns a number of gridpoints to be used as LUT table. It assumes same number
 195.971 +// of gripdpoints in all dimensions. Flags may override the choice.
 195.972 +int _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags)
 195.973 +{
 195.974 +    int nChannels;
 195.975 +
 195.976 +    // Already specified?
 195.977 +    if (dwFlags & 0x00FF0000) {
 195.978 +            // Yes, grab'em
 195.979 +            return (dwFlags >> 16) & 0xFF;
 195.980 +    }
 195.981 +
 195.982 +    nChannels = cmsChannelsOf(Colorspace);
 195.983 +
 195.984 +    // HighResPrecalc is maximum resolution
 195.985 +    if (dwFlags & cmsFLAGS_HIGHRESPRECALC) {
 195.986 +
 195.987 +        if (nChannels > 4)
 195.988 +                return 7;       // 7 for Hifi
 195.989 +
 195.990 +        if (nChannels == 4)     // 23 for CMYK
 195.991 +                return 23;
 195.992 +
 195.993 +        return 49;      // 49 for RGB and others
 195.994 +    }
 195.995 +
 195.996 +
 195.997 +    // LowResPrecal is lower resolution
 195.998 +    if (dwFlags & cmsFLAGS_LOWRESPRECALC) {
 195.999 +
195.1000 +        if (nChannels > 4)
195.1001 +                return 6;       // 6 for more than 4 channels
195.1002 +
195.1003 +        if (nChannels == 1)
195.1004 +                return 33;      // For monochrome
195.1005 +
195.1006 +        return 17;              // 17 for remaining
195.1007 +    }
195.1008 +
195.1009 +    // Default values
195.1010 +    if (nChannels > 4)
195.1011 +                return 7;       // 7 for Hifi
195.1012 +
195.1013 +    if (nChannels == 4)
195.1014 +                return 17;      // 17 for CMYK
195.1015 +
195.1016 +    return 33;                  // 33 for RGB
195.1017 +}
195.1018 +
195.1019 +
195.1020 +cmsBool  _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
195.1021 +                             cmsUInt16Number **White,
195.1022 +                             cmsUInt16Number **Black,
195.1023 +                             cmsUInt32Number *nOutputs)
195.1024 +{
195.1025 +       // Only most common spaces
195.1026 +
195.1027 +       static cmsUInt16Number RGBblack[4]  = { 0, 0, 0 };
195.1028 +       static cmsUInt16Number RGBwhite[4]  = { 0xffff, 0xffff, 0xffff };
195.1029 +       static cmsUInt16Number CMYKblack[4] = { 0xffff, 0xffff, 0xffff, 0xffff };   // 400% of ink
195.1030 +       static cmsUInt16Number CMYKwhite[4] = { 0, 0, 0, 0 };
195.1031 +       static cmsUInt16Number LABblack[4]  = { 0, 0x8080, 0x8080 };               // V4 Lab encoding
195.1032 +       static cmsUInt16Number LABwhite[4]  = { 0xFFFF, 0x8080, 0x8080 };
195.1033 +       static cmsUInt16Number CMYblack[4]  = { 0xffff, 0xffff, 0xffff };
195.1034 +       static cmsUInt16Number CMYwhite[4]  = { 0, 0, 0 };
195.1035 +       static cmsUInt16Number Grayblack[4] = { 0 };
195.1036 +       static cmsUInt16Number GrayWhite[4] = { 0xffff };
195.1037 +
195.1038 +       switch (Space) {
195.1039 +
195.1040 +       case cmsSigGrayData: if (White)    *White = GrayWhite;
195.1041 +                           if (Black)    *Black = Grayblack;
195.1042 +                           if (nOutputs) *nOutputs = 1;
195.1043 +                           return TRUE;
195.1044 +
195.1045 +       case cmsSigRgbData:  if (White)    *White = RGBwhite;
195.1046 +                           if (Black)    *Black = RGBblack;
195.1047 +                           if (nOutputs) *nOutputs = 3;
195.1048 +                           return TRUE;
195.1049 +
195.1050 +       case cmsSigLabData:  if (White)    *White = LABwhite;
195.1051 +                           if (Black)    *Black = LABblack;
195.1052 +                           if (nOutputs) *nOutputs = 3;
195.1053 +                           return TRUE;
195.1054 +
195.1055 +       case cmsSigCmykData: if (White)    *White = CMYKwhite;
195.1056 +                           if (Black)    *Black = CMYKblack;
195.1057 +                           if (nOutputs) *nOutputs = 4;
195.1058 +                           return TRUE;
195.1059 +
195.1060 +       case cmsSigCmyData:  if (White)    *White = CMYwhite;
195.1061 +                           if (Black)    *Black = CMYblack;
195.1062 +                           if (nOutputs) *nOutputs = 3;
195.1063 +                           return TRUE;
195.1064 +
195.1065 +       default:;
195.1066 +       }
195.1067 +
195.1068 +  return FALSE;
195.1069 +}
195.1070 +
195.1071 +
195.1072 +
195.1073 +// Several utilities -------------------------------------------------------
195.1074 +
195.1075 +// Translate from our colorspace to ICC representation
195.1076 +
195.1077 +cmsColorSpaceSignature CMSEXPORT _cmsICCcolorSpace(int OurNotation)
195.1078 +{
195.1079 +       switch (OurNotation) {
195.1080 +
195.1081 +       case 1:
195.1082 +       case PT_GRAY: return cmsSigGrayData;
195.1083 +
195.1084 +       case 2:
195.1085 +       case PT_RGB:  return cmsSigRgbData;
195.1086 +
195.1087 +       case PT_CMY:  return cmsSigCmyData;
195.1088 +       case PT_CMYK: return cmsSigCmykData;
195.1089 +       case PT_YCbCr:return cmsSigYCbCrData;
195.1090 +       case PT_YUV:  return cmsSigLuvData;
195.1091 +       case PT_XYZ:  return cmsSigXYZData;
195.1092 +
195.1093 +       case PT_LabV2:
195.1094 +       case PT_Lab:  return cmsSigLabData;
195.1095 +
195.1096 +       case PT_YUVK: return cmsSigLuvKData;
195.1097 +       case PT_HSV:  return cmsSigHsvData;
195.1098 +       case PT_HLS:  return cmsSigHlsData;
195.1099 +       case PT_Yxy:  return cmsSigYxyData;
195.1100 +
195.1101 +       case PT_MCH1: return cmsSigMCH1Data;
195.1102 +       case PT_MCH2: return cmsSigMCH2Data;
195.1103 +       case PT_MCH3: return cmsSigMCH3Data;
195.1104 +       case PT_MCH4: return cmsSigMCH4Data;
195.1105 +       case PT_MCH5: return cmsSigMCH5Data;
195.1106 +       case PT_MCH6: return cmsSigMCH6Data;
195.1107 +       case PT_MCH7: return cmsSigMCH7Data;
195.1108 +       case PT_MCH8: return cmsSigMCH8Data;
195.1109 +
195.1110 +       case PT_MCH9:  return cmsSigMCH9Data;
195.1111 +       case PT_MCH10: return cmsSigMCHAData;
195.1112 +       case PT_MCH11: return cmsSigMCHBData;
195.1113 +       case PT_MCH12: return cmsSigMCHCData;
195.1114 +       case PT_MCH13: return cmsSigMCHDData;
195.1115 +       case PT_MCH14: return cmsSigMCHEData;
195.1116 +       case PT_MCH15: return cmsSigMCHFData;
195.1117 +
195.1118 +       default:  return (cmsColorSpaceSignature) (-1);
195.1119 +       }
195.1120 +}
195.1121 +
195.1122 +
195.1123 +int CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace)
195.1124 +{
195.1125 +    switch (ProfileSpace) {
195.1126 +
195.1127 +    case cmsSigGrayData: return  PT_GRAY;
195.1128 +    case cmsSigRgbData:  return  PT_RGB;
195.1129 +    case cmsSigCmyData:  return  PT_CMY;
195.1130 +    case cmsSigCmykData: return  PT_CMYK;
195.1131 +    case cmsSigYCbCrData:return  PT_YCbCr;
195.1132 +    case cmsSigLuvData:  return  PT_YUV;
195.1133 +    case cmsSigXYZData:  return  PT_XYZ;
195.1134 +    case cmsSigLabData:  return  PT_Lab;
195.1135 +    case cmsSigLuvKData: return  PT_YUVK;
195.1136 +    case cmsSigHsvData:  return  PT_HSV;
195.1137 +    case cmsSigHlsData:  return  PT_HLS;
195.1138 +    case cmsSigYxyData:  return  PT_Yxy;
195.1139 +
195.1140 +    case cmsSig1colorData:
195.1141 +    case cmsSigMCH1Data: return PT_MCH1;
195.1142 +
195.1143 +    case cmsSig2colorData:
195.1144 +    case cmsSigMCH2Data: return PT_MCH2;
195.1145 +
195.1146 +    case cmsSig3colorData:
195.1147 +    case cmsSigMCH3Data: return PT_MCH3;
195.1148 +
195.1149 +    case cmsSig4colorData:
195.1150 +    case cmsSigMCH4Data: return PT_MCH4;
195.1151 +
195.1152 +    case cmsSig5colorData:
195.1153 +    case cmsSigMCH5Data: return PT_MCH5;
195.1154 +
195.1155 +    case cmsSig6colorData:
195.1156 +    case cmsSigMCH6Data: return PT_MCH6;
195.1157 +
195.1158 +    case cmsSigMCH7Data:
195.1159 +    case cmsSig7colorData:return PT_MCH7;
195.1160 +
195.1161 +    case cmsSigMCH8Data:
195.1162 +    case cmsSig8colorData:return PT_MCH8;
195.1163 +
195.1164 +    case cmsSigMCH9Data:
195.1165 +    case cmsSig9colorData:return PT_MCH9;
195.1166 +
195.1167 +    case cmsSigMCHAData:
195.1168 +    case cmsSig10colorData:return PT_MCH10;
195.1169 +
195.1170 +    case cmsSigMCHBData:
195.1171 +    case cmsSig11colorData:return PT_MCH11;
195.1172 +
195.1173 +    case cmsSigMCHCData:
195.1174 +    case cmsSig12colorData:return PT_MCH12;
195.1175 +
195.1176 +    case cmsSigMCHDData:
195.1177 +    case cmsSig13colorData:return PT_MCH13;
195.1178 +
195.1179 +    case cmsSigMCHEData:
195.1180 +    case cmsSig14colorData:return PT_MCH14;
195.1181 +
195.1182 +    case cmsSigMCHFData:
195.1183 +    case cmsSig15colorData:return PT_MCH15;
195.1184 +
195.1185 +    default:  return (cmsColorSpaceSignature) (-1);
195.1186 +    }
195.1187 +}
195.1188 +
195.1189 +
195.1190 +cmsUInt32Number CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace)
195.1191 +{
195.1192 +    switch (ColorSpace) {
195.1193 +
195.1194 +    case cmsSigGrayData: return 1;
195.1195 +
195.1196 +    case cmsSig2colorData:  return 2;
195.1197 +
195.1198 +    case cmsSigXYZData:
195.1199 +    case cmsSigLabData:
195.1200 +    case cmsSigLuvData:
195.1201 +    case cmsSigYCbCrData:
195.1202 +    case cmsSigYxyData:
195.1203 +    case cmsSigRgbData:
195.1204 +    case cmsSigHsvData:
195.1205 +    case cmsSigHlsData:
195.1206 +    case cmsSigCmyData:
195.1207 +    case cmsSig3colorData:  return 3;
195.1208 +
195.1209 +    case cmsSigLuvKData:
195.1210 +    case cmsSigCmykData:
195.1211 +    case cmsSig4colorData:  return 4;
195.1212 +
195.1213 +    case cmsSigMCH5Data:
195.1214 +    case cmsSig5colorData:  return 5;
195.1215 +
195.1216 +    case cmsSigMCH6Data:
195.1217 +    case cmsSig6colorData:  return 6;
195.1218 +
195.1219 +    case cmsSigMCH7Data:
195.1220 +    case cmsSig7colorData:  return  7;
195.1221 +
195.1222 +    case cmsSigMCH8Data:
195.1223 +    case cmsSig8colorData:  return  8;
195.1224 +
195.1225 +    case cmsSigMCH9Data:
195.1226 +    case cmsSig9colorData:  return  9;
195.1227 +
195.1228 +    case cmsSigMCHAData:
195.1229 +    case cmsSig10colorData: return 10;
195.1230 +
195.1231 +    case cmsSigMCHBData:
195.1232 +    case cmsSig11colorData: return 11;
195.1233 +
195.1234 +    case cmsSigMCHCData:
195.1235 +    case cmsSig12colorData: return 12;
195.1236 +
195.1237 +    case cmsSigMCHDData:
195.1238 +    case cmsSig13colorData: return 13;
195.1239 +
195.1240 +    case cmsSigMCHEData:
195.1241 +    case cmsSig14colorData: return 14;
195.1242 +
195.1243 +    case cmsSigMCHFData:
195.1244 +    case cmsSig15colorData: return 15;
195.1245 +
195.1246 +    default: return 3;
195.1247 +    }
195.1248 +}
   196.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c	Fri Sep 24 16:41:32 2010 -0700
   196.3 @@ -0,0 +1,641 @@
   196.4 +/*
   196.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   196.6 + *
   196.7 + * This code is free software; you can redistribute it and/or modify it
   196.8 + * under the terms of the GNU General Public License version 2 only, as
   196.9 + * published by the Free Software Foundation.  Oracle designates this
  196.10 + * particular file as subject to the "Classpath" exception as provided
  196.11 + * by Oracle in the LICENSE file that accompanied this code.
  196.12 + *
  196.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  196.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  196.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  196.16 + * version 2 for more details (a copy is included in the LICENSE file that
  196.17 + * accompanied this code).
  196.18 + *
  196.19 + * You should have received a copy of the GNU General Public License version
  196.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  196.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  196.22 + *
  196.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  196.24 + * or visit www.oracle.com if you need additional information or have any
  196.25 + * questions.
  196.26 + */
  196.27 +
  196.28 +// This file is available under and governed by the GNU General Public
  196.29 +// License version 2 only, as published by the Free Software Foundation.
  196.30 +// However, the following notice accompanied the original version of this
  196.31 +// file:
  196.32 +//
  196.33 +//---------------------------------------------------------------------------------
  196.34 +//
  196.35 +//  Little Color Management System
  196.36 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  196.37 +//
  196.38 +// Permission is hereby granted, free of charge, to any person obtaining
  196.39 +// a copy of this software and associated documentation files (the "Software"),
  196.40 +// to deal in the Software without restriction, including without limitation
  196.41 +// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  196.42 +// and/or sell copies of the Software, and to permit persons to whom the Software
  196.43 +// is furnished to do so, subject to the following conditions:
  196.44 +//
  196.45 +// The above copyright notice and this permission notice shall be included in
  196.46 +// all copies or substantial portions of the Software.
  196.47 +//
  196.48 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  196.49 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  196.50 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  196.51 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  196.52 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  196.53 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  196.54 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  196.55 +//
  196.56 +//---------------------------------------------------------------------------------
  196.57 +//
  196.58 +
  196.59 +#include "lcms2_internal.h"
  196.60 +
  196.61 +
  196.62 +// ----------------------------------------------------------------------------------
  196.63 +// Encoding & Decoding support functions
  196.64 +// ----------------------------------------------------------------------------------
  196.65 +
  196.66 +//      Little-Endian to Big-Endian
  196.67 +
  196.68 +// Adjust a word value after being readed/ before being written from/to an ICC profile
  196.69 +cmsUInt16Number CMSEXPORT  _cmsAdjustEndianess16(cmsUInt16Number Word)
  196.70 +{
  196.71 +#ifndef CMS_USE_BIG_ENDIAN
  196.72 +
  196.73 +    cmsUInt8Number* pByte = (cmsUInt8Number*) &Word;
  196.74 +    cmsUInt8Number tmp;
  196.75 +
  196.76 +    tmp = pByte[0];
  196.77 +    pByte[0] = pByte[1];
  196.78 +    pByte[1] = tmp;
  196.79 +#endif
  196.80 +
  196.81 +    return Word;
  196.82 +}
  196.83 +
  196.84 +
  196.85 +// Transports to properly encoded values - note that icc profiles does use big endian notation.
  196.86 +
  196.87 +// 1 2 3 4
  196.88 +// 4 3 2 1
  196.89 +
  196.90 +cmsUInt32Number CMSEXPORT  _cmsAdjustEndianess32(cmsUInt32Number DWord)
  196.91 +{
  196.92 +#ifndef CMS_USE_BIG_ENDIAN
  196.93 +
  196.94 +    cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord;
  196.95 +    cmsUInt8Number temp1;
  196.96 +    cmsUInt8Number temp2;
  196.97 +
  196.98 +    temp1 = *pByte++;
  196.99 +    temp2 = *pByte++;
 196.100 +    *(pByte-1) = *pByte;
 196.101 +    *pByte++ = temp2;
 196.102 +    *(pByte-3) = *pByte;
 196.103 +    *pByte = temp1;
 196.104 +#endif
 196.105 +    return DWord;
 196.106 +}
 196.107 +
 196.108 +// 1 2 3 4 5 6 7 8
 196.109 +// 8 7 6 5 4 3 2 1
 196.110 +
 196.111 +void CMSEXPORT  _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number QWord)
 196.112 +{
 196.113 +
 196.114 +#ifndef CMS_USE_BIG_ENDIAN
 196.115 +
 196.116 +    cmsUInt8Number* pIn  = (cmsUInt8Number*) &QWord;
 196.117 +    cmsUInt8Number* pOut = (cmsUInt8Number*) Result;
 196.118 +
 196.119 +    _cmsAssert(Result != NULL);
 196.120 +
 196.121 +    pOut[7] = pIn[0];
 196.122 +    pOut[6] = pIn[1];
 196.123 +    pOut[5] = pIn[2];
 196.124 +    pOut[4] = pIn[3];
 196.125 +    pOut[3] = pIn[4];
 196.126 +    pOut[2] = pIn[5];
 196.127 +    pOut[1] = pIn[6];
 196.128 +    pOut[0] = pIn[7];
 196.129 +
 196.130 +#else
 196.131 +
 196.132 +    _cmsAssert(Result != NULL);
 196.133 +
 196.134 +    *Result = QWord;
 196.135 +#endif
 196.136 +}
 196.137 +
 196.138 +// Auxiliar -- read 8, 16 and 32-bit numbers
 196.139 +cmsBool CMSEXPORT  _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n)
 196.140 +{
 196.141 +    cmsUInt8Number tmp;
 196.142 +
 196.143 +    _cmsAssert(io != NULL);
 196.144 +
 196.145 +    if (io -> Read(io, &tmp, sizeof(cmsUInt8Number), 1) != 1)
 196.146 +            return FALSE;
 196.147 +
 196.148 +    if (n != NULL) *n = tmp;
 196.149 +    return TRUE;
 196.150 +}
 196.151 +
 196.152 +cmsBool CMSEXPORT  _cmsReadUInt16Number(cmsIOHANDLER* io, cmsUInt16Number* n)
 196.153 +{
 196.154 +    cmsUInt16Number tmp;
 196.155 +
 196.156 +    _cmsAssert(io != NULL);
 196.157 +
 196.158 +    if (io -> Read(io, &tmp, sizeof(cmsUInt16Number), 1) != 1)
 196.159 +            return FALSE;
 196.160 +
 196.161 +    if (n != NULL) *n = _cmsAdjustEndianess16(tmp);
 196.162 +    return TRUE;
 196.163 +}
 196.164 +
 196.165 +cmsBool CMSEXPORT  _cmsReadUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, cmsUInt16Number* Array)
 196.166 +{
 196.167 +    cmsUInt32Number i;
 196.168 +
 196.169 +    _cmsAssert(io != NULL);
 196.170 +
 196.171 +    for (i=0; i < n; i++) {
 196.172 +
 196.173 +        if (Array != NULL) {
 196.174 +            if (!_cmsReadUInt16Number(io, Array + i)) return FALSE;
 196.175 +        }
 196.176 +        else {
 196.177 +            if (!_cmsReadUInt16Number(io, NULL)) return FALSE;
 196.178 +        }
 196.179 +
 196.180 +    }
 196.181 +    return TRUE;
 196.182 +}
 196.183 +
 196.184 +cmsBool CMSEXPORT  _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n)
 196.185 +{
 196.186 +    cmsUInt32Number tmp;
 196.187 +
 196.188 +    _cmsAssert(io != NULL);
 196.189 +
 196.190 +    if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
 196.191 +            return FALSE;
 196.192 +
 196.193 +    if (n != NULL) *n = _cmsAdjustEndianess32(tmp);
 196.194 +    return TRUE;
 196.195 +}
 196.196 +
 196.197 +cmsBool CMSEXPORT  _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n)
 196.198 +{
 196.199 +    cmsUInt32Number tmp;
 196.200 +
 196.201 +    _cmsAssert(io != NULL);
 196.202 +
 196.203 +    if (io -> Read(io, &tmp, sizeof(cmsFloat32Number), 1) != 1)
 196.204 +            return FALSE;
 196.205 +
 196.206 +    if (n != NULL) {
 196.207 +
 196.208 +        tmp = _cmsAdjustEndianess32(tmp);
 196.209 +        *n = *(cmsFloat32Number*) &tmp;
 196.210 +    }
 196.211 +    return TRUE;
 196.212 +}
 196.213 +
 196.214 +
 196.215 +cmsBool CMSEXPORT   _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)
 196.216 +{
 196.217 +    cmsUInt64Number tmp;
 196.218 +
 196.219 +    _cmsAssert(io != NULL);
 196.220 +
 196.221 +    if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1)
 196.222 +            return FALSE;
 196.223 +
 196.224 +    if (n != NULL) _cmsAdjustEndianess64(n, tmp);
 196.225 +    return TRUE;
 196.226 +}
 196.227 +
 196.228 +
 196.229 +cmsBool CMSEXPORT  _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n)
 196.230 +{
 196.231 +    cmsUInt32Number tmp;
 196.232 +
 196.233 +    _cmsAssert(io != NULL);
 196.234 +
 196.235 +    if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
 196.236 +            return FALSE;
 196.237 +
 196.238 +    if (n != NULL) {
 196.239 +        *n = _cms15Fixed16toDouble(_cmsAdjustEndianess32(tmp));
 196.240 +    }
 196.241 +
 196.242 +    return TRUE;
 196.243 +}
 196.244 +
 196.245 +
 196.246 +// Jun-21-2000: Some profiles (those that comes with W2K) comes
 196.247 +// with the media white (media black?) x 100. Add a sanity check
 196.248 +
 196.249 +static
 196.250 +void NormalizeXYZ(cmsCIEXYZ* Dest)
 196.251 +{
 196.252 +    while (Dest -> X > 2. &&
 196.253 +           Dest -> Y > 2. &&
 196.254 +           Dest -> Z > 2.) {
 196.255 +
 196.256 +               Dest -> X /= 10.;
 196.257 +               Dest -> Y /= 10.;
 196.258 +               Dest -> Z /= 10.;
 196.259 +       }
 196.260 +}
 196.261 +
 196.262 +cmsBool CMSEXPORT  _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ)
 196.263 +{
 196.264 +    cmsEncodedXYZNumber xyz;
 196.265 +
 196.266 +    _cmsAssert(io != NULL);
 196.267 +
 196.268 +    if (io ->Read(io, &xyz, sizeof(cmsEncodedXYZNumber), 1) != 1) return FALSE;
 196.269 +
 196.270 +    if (XYZ != NULL) {
 196.271 +
 196.272 +        XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X));
 196.273 +        XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y));
 196.274 +        XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z));
 196.275 +
 196.276 +        NormalizeXYZ(XYZ);
 196.277 +    }
 196.278 +    return TRUE;
 196.279 +}
 196.280 +
 196.281 +cmsBool CMSEXPORT  _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n)
 196.282 +{
 196.283 +    _cmsAssert(io != NULL);
 196.284 +
 196.285 +    if (io -> Write(io, sizeof(cmsUInt8Number), &n) != 1)
 196.286 +            return FALSE;
 196.287 +
 196.288 +    return TRUE;
 196.289 +}
 196.290 +
 196.291 +cmsBool CMSEXPORT  _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n)
 196.292 +{
 196.293 +    cmsUInt16Number tmp;
 196.294 +
 196.295 +    _cmsAssert(io != NULL);
 196.296 +
 196.297 +    tmp = _cmsAdjustEndianess16(n);
 196.298 +    if (io -> Write(io, sizeof(cmsUInt16Number), &tmp) != 1)
 196.299 +            return FALSE;
 196.300 +
 196.301 +    return TRUE;
 196.302 +}
 196.303 +
 196.304 +cmsBool CMSEXPORT  _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array)
 196.305 +{
 196.306 +    cmsUInt32Number i;
 196.307 +
 196.308 +    _cmsAssert(io != NULL);
 196.309 +    _cmsAssert(Array != NULL);
 196.310 +
 196.311 +    for (i=0; i < n; i++) {
 196.312 +        if (!_cmsWriteUInt16Number(io, Array[i])) return FALSE;
 196.313 +    }
 196.314 +
 196.315 +    return TRUE;
 196.316 +}
 196.317 +
 196.318 +cmsBool CMSEXPORT  _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n)
 196.319 +{
 196.320 +    cmsUInt32Number tmp;
 196.321 +
 196.322 +    _cmsAssert(io != NULL);
 196.323 +
 196.324 +    tmp = _cmsAdjustEndianess32(n);
 196.325 +    if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
 196.326 +            return FALSE;
 196.327 +
 196.328 +    return TRUE;
 196.329 +}
 196.330 +
 196.331 +
 196.332 +cmsBool CMSEXPORT  _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n)
 196.333 +{
 196.334 +    cmsUInt32Number tmp;
 196.335 +
 196.336 +    _cmsAssert(io != NULL);
 196.337 +
 196.338 +    tmp = *(cmsUInt32Number*) &n;
 196.339 +    tmp = _cmsAdjustEndianess32(tmp);
 196.340 +    if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
 196.341 +            return FALSE;
 196.342 +
 196.343 +    return TRUE;
 196.344 +}
 196.345 +
 196.346 +cmsBool CMSEXPORT  _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number n)
 196.347 +{
 196.348 +    cmsUInt64Number tmp;
 196.349 +
 196.350 +    _cmsAssert(io != NULL);
 196.351 +
 196.352 +    _cmsAdjustEndianess64(&tmp, n);
 196.353 +    if (io -> Write(io, sizeof(cmsUInt64Number), &tmp) != 1)
 196.354 +            return FALSE;
 196.355 +
 196.356 +    return TRUE;
 196.357 +}
 196.358 +
 196.359 +cmsBool CMSEXPORT  _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n)
 196.360 +{
 196.361 +    cmsUInt32Number tmp;
 196.362 +
 196.363 +    _cmsAssert(io != NULL);
 196.364 +
 196.365 +    tmp = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(n));
 196.366 +    if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
 196.367 +            return FALSE;
 196.368 +
 196.369 +    return TRUE;
 196.370 +}
 196.371 +
 196.372 +cmsBool CMSEXPORT  _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ)
 196.373 +{
 196.374 +    cmsEncodedXYZNumber xyz;
 196.375 +
 196.376 +    _cmsAssert(io != NULL);
 196.377 +    _cmsAssert(XYZ != NULL);
 196.378 +
 196.379 +    xyz.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->X));
 196.380 +    xyz.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Y));
 196.381 +    xyz.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Z));
 196.382 +
 196.383 +    return io -> Write(io,  sizeof(cmsEncodedXYZNumber), &xyz);
 196.384 +}
 196.385 +
 196.386 +// from Fixed point 8.8 to double
 196.387 +cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8)
 196.388 +{
 196.389 +       cmsUInt8Number  msb, lsb;
 196.390 +
 196.391 +       lsb = (cmsUInt8Number) (fixed8 & 0xff);
 196.392 +       msb = (cmsUInt8Number) (((cmsUInt16Number) fixed8 >> 8) & 0xff);
 196.393 +
 196.394 +       return (cmsFloat64Number) ((cmsFloat64Number) msb + ((cmsFloat64Number) lsb / 256.0));
 196.395 +}
 196.396 +
 196.397 +cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val)
 196.398 +{
 196.399 +    cmsS15Fixed16Number GammaFixed32 = _cmsDoubleTo15Fixed16(val);
 196.400 +    return  (cmsUInt16Number) ((GammaFixed32 >> 8) & 0xFFFF);
 196.401 +}
 196.402 +
 196.403 +// from Fixed point 15.16 to double
 196.404 +cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32)
 196.405 +{
 196.406 +    cmsFloat64Number floater, sign, mid;
 196.407 +    int Whole, FracPart;
 196.408 +
 196.409 +    sign  = (fix32 < 0 ? -1 : 1);
 196.410 +    fix32 = abs(fix32);
 196.411 +
 196.412 +    Whole     = (cmsUInt16Number)(fix32 >> 16) & 0xffff;
 196.413 +    FracPart  = (cmsUInt16Number)(fix32 & 0xffff);
 196.414 +
 196.415 +    mid     = (cmsFloat64Number) FracPart / 65536.0;
 196.416 +    floater = (cmsFloat64Number) Whole + mid;
 196.417 +
 196.418 +    return sign * floater;
 196.419 +}
 196.420 +
 196.421 +// from double to Fixed point 15.16
 196.422 +cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v)
 196.423 +{
 196.424 +    return ((cmsS15Fixed16Number) floor((v)*65536.0 + 0.5));
 196.425 +}
 196.426 +
 196.427 +// Date/Time functions
 196.428 +
 196.429 +void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest)
 196.430 +{
 196.431 +
 196.432 +    _cmsAssert(Dest != NULL);
 196.433 +    _cmsAssert(Source != NULL);
 196.434 +
 196.435 +    Dest->tm_sec   = _cmsAdjustEndianess16(Source->seconds);
 196.436 +    Dest->tm_min   = _cmsAdjustEndianess16(Source->minutes);
 196.437 +    Dest->tm_hour  = _cmsAdjustEndianess16(Source->hours);
 196.438 +    Dest->tm_mday  = _cmsAdjustEndianess16(Source->day);
 196.439 +    Dest->tm_mon   = _cmsAdjustEndianess16(Source->month) - 1;
 196.440 +    Dest->tm_year  = _cmsAdjustEndianess16(Source->year) - 1900;
 196.441 +    Dest->tm_wday  = -1;
 196.442 +    Dest->tm_yday  = -1;
 196.443 +    Dest->tm_isdst = 0;
 196.444 +}
 196.445 +
 196.446 +void CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source)
 196.447 +{
 196.448 +    _cmsAssert(Dest != NULL);
 196.449 +    _cmsAssert(Source != NULL);
 196.450 +
 196.451 +    Dest->seconds = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_sec);
 196.452 +    Dest->minutes = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_min);
 196.453 +    Dest->hours   = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_hour);
 196.454 +    Dest->day     = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_mday);
 196.455 +    Dest->month   = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_mon + 1));
 196.456 +    Dest->year    = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_year + 1900));
 196.457 +}
 196.458 +
 196.459 +// Read base and return type base
 196.460 +cmsTagTypeSignature CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io)
 196.461 +{
 196.462 +    _cmsTagBase Base;
 196.463 +
 196.464 +    _cmsAssert(io != NULL);
 196.465 +
 196.466 +    if (io -> Read(io, &Base, sizeof(_cmsTagBase), 1) != 1)
 196.467 +        return (cmsTagTypeSignature) 0;
 196.468 +
 196.469 +    return (cmsTagTypeSignature) _cmsAdjustEndianess32(Base.sig);
 196.470 +}
 196.471 +
 196.472 +// Setup base marker
 196.473 +cmsBool  CMSEXPORT _cmsWriteTypeBase(cmsIOHANDLER* io, cmsTagTypeSignature sig)
 196.474 +{
 196.475 +    _cmsTagBase  Base;
 196.476 +
 196.477 +    _cmsAssert(io != NULL);
 196.478 +
 196.479 +    Base.sig = (cmsTagTypeSignature) _cmsAdjustEndianess32(sig);
 196.480 +    memset(&Base.reserved, 0, sizeof(Base.reserved));
 196.481 +    return io -> Write(io, sizeof(_cmsTagBase), &Base);
 196.482 +}
 196.483 +
 196.484 +cmsBool CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io)
 196.485 +{
 196.486 +    cmsUInt8Number  Buffer[4];
 196.487 +    cmsUInt32Number NextAligned, At;
 196.488 +    cmsUInt32Number BytesToNextAlignedPos;
 196.489 +
 196.490 +    _cmsAssert(io != NULL);
 196.491 +
 196.492 +    At = io -> Tell(io);
 196.493 +    NextAligned = _cmsALIGNLONG(At);
 196.494 +    BytesToNextAlignedPos = NextAligned - At;
 196.495 +    if (BytesToNextAlignedPos == 0) return TRUE;
 196.496 +    if (BytesToNextAlignedPos > 4)  return FALSE;
 196.497 +
 196.498 +    return (io ->Read(io, Buffer, BytesToNextAlignedPos, 1) == 1);
 196.499 +}
 196.500 +
 196.501 +cmsBool CMSEXPORT _cmsWriteAlignment(cmsIOHANDLER* io)
 196.502 +{
 196.503 +    cmsUInt8Number  Buffer[4];
 196.504 +    cmsUInt32Number NextAligned, At;
 196.505 +    cmsUInt32Number BytesToNextAlignedPos;
 196.506 +
 196.507 +    _cmsAssert(io != NULL);
 196.508 +
 196.509 +    At = io -> Tell(io);
 196.510 +    NextAligned = _cmsALIGNLONG(At);
 196.511 +    BytesToNextAlignedPos = NextAligned - At;
 196.512 +    if (BytesToNextAlignedPos == 0) return TRUE;
 196.513 +    if (BytesToNextAlignedPos > 4)  return FALSE;
 196.514 +
 196.515 +    memset(Buffer, 0, BytesToNextAlignedPos);
 196.516 +    return io -> Write(io, BytesToNextAlignedPos, Buffer);
 196.517 +}
 196.518 +
 196.519 +
 196.520 +// To deal with text streams. 2K at most
 196.521 +cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
 196.522 +{
 196.523 +    va_list args;
 196.524 +    int len;
 196.525 +    cmsUInt8Number Buffer[2048];
 196.526 +    cmsBool rc;
 196.527 +
 196.528 +    _cmsAssert(io != NULL);
 196.529 +    _cmsAssert(frm != NULL);
 196.530 +
 196.531 +    va_start(args, frm);
 196.532 +
 196.533 +    len = vsnprintf((char*) Buffer, 2047, frm, args);
 196.534 +    if (len < 0) return FALSE;   // Truncated, which is a fatal error for us
 196.535 +
 196.536 +    rc = io ->Write(io, len, Buffer);
 196.537 +
 196.538 +    va_end(args);
 196.539 +
 196.540 +    return rc;
 196.541 +}
 196.542 +
 196.543 +
 196.544 +// Plugin memory management -------------------------------------------------------------------------------------------------
 196.545 +
 196.546 +static _cmsSubAllocator* PluginPool = NULL;
 196.547 +
 196.548 +// Specialized malloc for plug-ins, that is freed upon exit.
 196.549 +void* _cmsPluginMalloc(cmsUInt32Number size)
 196.550 +{
 196.551 +    if (PluginPool == NULL)
 196.552 +        PluginPool = _cmsCreateSubAlloc(0, 4*1024);
 196.553 +
 196.554 +    return _cmsSubAlloc(PluginPool, size);
 196.555 +}
 196.556 +
 196.557 +
 196.558 +// Main plug-in dispatcher
 196.559 +cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
 196.560 +{
 196.561 +    cmsPluginBase* Plugin;
 196.562 +
 196.563 +    for (Plugin = (cmsPluginBase*) Plug_in;
 196.564 +         Plugin != NULL;
 196.565 +         Plugin = Plugin -> Next) {
 196.566 +
 196.567 +            if (Plugin -> Magic != cmsPluginMagicNumber) {
 196.568 +                cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
 196.569 +                return FALSE;
 196.570 +            }
 196.571 +
 196.572 +            if (Plugin ->ExpectedVersion > LCMS_VERSION) {
 196.573 +                cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current  version is %d",
 196.574 +                               Plugin ->ExpectedVersion, LCMS_VERSION);
 196.575 +                return FALSE;
 196.576 +            }
 196.577 +
 196.578 +            switch (Plugin -> Type) {
 196.579 +
 196.580 +                case cmsPluginMemHandlerSig:
 196.581 +                    if (!_cmsRegisterMemHandlerPlugin(Plugin)) return FALSE;
 196.582 +                    break;
 196.583 +
 196.584 +                case cmsPluginInterpolationSig:
 196.585 +                    if (!_cmsRegisterInterpPlugin(Plugin)) return FALSE;
 196.586 +                    break;
 196.587 +
 196.588 +                case cmsPluginTagTypeSig:
 196.589 +                    if (!_cmsRegisterTagTypePlugin(Plugin)) return FALSE;
 196.590 +                    break;
 196.591 +
 196.592 +                case cmsPluginTagSig:
 196.593 +                    if (!_cmsRegisterTagPlugin(Plugin)) return FALSE;
 196.594 +                    break;
 196.595 +
 196.596 +                case cmsPluginFormattersSig:
 196.597 +                    if (!_cmsRegisterFormattersPlugin(Plugin)) return FALSE;
 196.598 +                    break;
 196.599 +
 196.600 +                case cmsPluginRenderingIntentSig:
 196.601 +                    if (!_cmsRegisterRenderingIntentPlugin(Plugin)) return FALSE;
 196.602 +                    break;
 196.603 +
 196.604 +                case cmsPluginParametricCurveSig:
 196.605 +                    if (!_cmsRegisterParametricCurvesPlugin(Plugin)) return FALSE;
 196.606 +                    break;
 196.607 +
 196.608 +                case cmsPluginMultiProcessElementSig:
 196.609 +                    if (!_cmsRegisterMultiProcessElementPlugin(Plugin)) return FALSE;
 196.610 +                    break;
 196.611 +
 196.612 +                case cmsPluginOptimizationSig:
 196.613 +                    if (!_cmsRegisterOptimizationPlugin(Plugin)) return FALSE;
 196.614 +                    break;
 196.615 +
 196.616 +                default:
 196.617 +                    cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
 196.618 +                    return FALSE;
 196.619 +            }
 196.620 +    }
 196.621 +
 196.622 +    // Keep a reference to the plug-in
 196.623 +    return TRUE;
 196.624 +}
 196.625 +
 196.626 +
 196.627 +// Revert all plug-ins to default
 196.628 +void CMSEXPORT cmsUnregisterPlugins(void)
 196.629 +{
 196.630 +    _cmsRegisterMemHandlerPlugin(NULL);
 196.631 +    _cmsRegisterInterpPlugin(NULL);
 196.632 +    _cmsRegisterTagTypePlugin(NULL);
 196.633 +    _cmsRegisterTagPlugin(NULL);
 196.634 +    _cmsRegisterFormattersPlugin(NULL);
 196.635 +    _cmsRegisterRenderingIntentPlugin(NULL);
 196.636 +    _cmsRegisterParametricCurvesPlugin(NULL);
 196.637 +    _cmsRegisterMultiProcessElementPlugin(NULL);
 196.638 +    _cmsRegisterOptimizationPlugin(NULL);
 196.639 +
 196.640 +    if (PluginPool != NULL)
 196.641 +        _cmsSubAllocDestroy(PluginPool);
 196.642 +
 196.643 +    PluginPool = NULL;
 196.644 +}
   197.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsps2.c	Thu Sep 23 17:33:40 2010 -0700
   197.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsps2.c	Fri Sep 24 16:41:32 2010 -0700
   197.3 @@ -27,9 +27,10 @@
   197.4  // However, the following notice accompanied the original version of this
   197.5  // file:
   197.6  //
   197.7 +//---------------------------------------------------------------------------------
   197.8  //
   197.9 -//  Little cms
  197.10 -//  Copyright (C) 1998-2007 Marti Maria
  197.11 +//  Little Color Management System
  197.12 +//  Copyright (c) 1998-2008 Marti Maria Saguer
  197.13  //
  197.14  // Permission is hereby granted, free of charge, to any person obtaining
  197.15  // a copy of this software and associated documentation files (the "Software"),
  197.16 @@ -48,22 +49,14 @@
  197.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  197.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  197.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  197.20 +//
  197.21 +//---------------------------------------------------------------------------------
  197.22 +//
  197.23  
  197.24 -
  197.25 -// Postscript level 2 operators
  197.26 -
  197.27 -
  197.28 -
  197.29 -#include "lcms.h"
  197.30 -#include <time.h>
  197.31 -#include <stdarg.h>
  197.32 +#include "lcms2_internal.h"
  197.33  
  197.34  // PostScript ColorRenderingDictionary and ColorSpaceArray
  197.35  
  197.36 -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, int Intent, LPVOID Buffer, DWORD dwBufferLen);
  197.37 -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCRD(cmsHPROFILE hProfile, int Intent, LPVOID Buffer, DWORD dwBufferLen);
  197.38 -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile, int Intent, DWORD dwFlags, LPVOID Buffer, DWORD dwBufferLen);
  197.39 -// -------------------------------------------------------------------- Implementation
  197.40  
  197.41  #define MAXPSCOLS   60      // Columns on tables
  197.42  
  197.43 @@ -83,9 +76,9 @@
  197.44    Color Space Arrays (CSA)
  197.45    ==================================================================================
  197.46  
  197.47 -  In order to obtain precission, code chooses between three ways to implement
  197.48 +  In order to obtain precision, code chooses between three ways to implement
  197.49    the device -> XYZ transform. These cases identifies monochrome profiles (often
  197.50 -  implemented as a set of curves), matrix-shaper and LUT-based.
  197.51 +  implemented as a set of curves), matrix-shaper and Pipeline-based.
  197.52  
  197.53    Monochrome
  197.54    -----------
  197.55 @@ -101,7 +94,7 @@
  197.56        <<
  197.57              /DecodeA { transfer function } bind
  197.58              /MatrixA [D50]
  197.59 -            /RangeLMN [ 0.0 D50X 0.0 D50Y 0.0 D50Z ]
  197.60 +            /RangeLMN [ 0.0 cmsD50X 0.0 cmsD50Y 0.0 cmsD50Z ]
  197.61              /WhitePoint [D50]
  197.62              /BlackPoint [BP]
  197.63              /RenderingIntent (intent)
  197.64 @@ -115,7 +108,7 @@
  197.65     -------------------
  197.66  
  197.67     This is implemented both with /CIEBasedABC or /CIEBasedDEF on dependig
  197.68 -   of profile implementation. Since here is no interpolation tables, I do
  197.69 +   of profile implementation. Since here there are no interpolation tables, I do
  197.70     the conversion directly to XYZ
  197.71  
  197.72  
  197.73 @@ -124,7 +117,7 @@
  197.74              <<
  197.75                  /DecodeABC [ {transfer1} {transfer2} {transfer3} ]
  197.76                  /MatrixABC [Matrix]
  197.77 -                /RangeLMN [ 0.0 D50X 0.0 D50Y 0.0 D50Z ]
  197.78 +                /RangeLMN [ 0.0 cmsD50X 0.0 cmsD50Y 0.0 cmsD50Z ]
  197.79                  /DecodeLMN [ { / 2} dup dup ]
  197.80                  /WhitePoint [D50]
  197.81                  /BlackPoint [BP]
  197.82 @@ -299,153 +292,66 @@
  197.83  
  197.84  */
  197.85  
  197.86 -static icTagSignature Device2PCSTab[] = {icSigAToB0Tag,       // Perceptual
  197.87 -                                         icSigAToB1Tag,       // Relative colorimetric
  197.88 -                                         icSigAToB2Tag,       // Saturation
  197.89 -                                         icSigAToB1Tag };     // Absolute colorimetric
  197.90 -                                                           // (Relative/WhitePoint)
  197.91  
  197.92 +// This struct holds the memory block currently being write
  197.93 +typedef struct {
  197.94 +    _cmsStageCLutData* Pipeline;
  197.95 +    cmsIOHANDLER* m;
  197.96  
  197.97 -// --------------------------------------------------------------- Memory Stream
  197.98 -//
  197.99 -// This struct holds the memory block currently being write
 197.100 -//
 197.101 +    int FirstComponent;
 197.102 +    int SecondComponent;
 197.103  
 197.104 -typedef struct {
 197.105 -                LPBYTE Block;
 197.106 -                LPBYTE Ptr;
 197.107 -                DWORD  dwMax;
 197.108 -                DWORD  dwUsed;
 197.109 -                int    MaxCols;
 197.110 -                int    Col;
 197.111 -                int    HasError;
 197.112 +    const char* PreMaj;
 197.113 +    const char* PostMaj;
 197.114 +    const char* PreMin;
 197.115 +    const char* PostMin;
 197.116  
 197.117 -            } MEMSTREAM, FAR* LPMEMSTREAM;
 197.118 +    int  FixWhite;    // Force mapping of pure white
 197.119  
 197.120 +    cmsColorSpaceSignature  ColorSpace;  // ColorSpace of profile
 197.121  
 197.122 -typedef struct {
 197.123 -                LPLUT Lut;
 197.124 -                LPMEMSTREAM m;
 197.125  
 197.126 -                int FirstComponent;
 197.127 -                int SecondComponent;
 197.128 +} cmsPsSamplerCargo;
 197.129  
 197.130 -                int   bps;
 197.131 -                const char* PreMaj;
 197.132 -                const char* PostMaj;
 197.133 -                const char* PreMin;
 197.134 -                const char* PostMin;
 197.135 -
 197.136 -                int  lIsInput;    // Handle L* encoding
 197.137 -                int  FixWhite;    // Force mapping of pure white
 197.138 -
 197.139 -                icColorSpaceSignature  ColorSpace;  // ColorSpace of profile
 197.140 -
 197.141 -
 197.142 -            } SAMPLERCARGO, FAR* LPSAMPLERCARGO;
 197.143 -
 197.144 -
 197.145 -// Creates a ready to use memory stream
 197.146 -static
 197.147 -LPMEMSTREAM CreateMemStream(LPBYTE Buffer, DWORD dwMax, int MaxCols)
 197.148 -{
 197.149 -    LPMEMSTREAM m = (LPMEMSTREAM) _cmsMalloc(sizeof(MEMSTREAM));
 197.150 -    if (m == NULL) return NULL;
 197.151 -
 197.152 -    ZeroMemory(m, sizeof(MEMSTREAM));
 197.153 -
 197.154 -    m -> Block   = m -> Ptr = Buffer;
 197.155 -    m -> dwMax   = dwMax;
 197.156 -    m -> dwUsed  = 0;
 197.157 -    m -> MaxCols = MaxCols;
 197.158 -    m -> Col     = 0;
 197.159 -    m -> HasError = 0;
 197.160 -
 197.161 -    return m;
 197.162 -}
 197.163 -
 197.164 +static int _cmsPSActualColumn = 0;
 197.165  
 197.166  
 197.167  // Convert to byte
 197.168  static
 197.169 -BYTE Word2Byte(WORD w)
 197.170 +cmsUInt8Number Word2Byte(cmsUInt16Number w)
 197.171  {
 197.172 -    return (BYTE) floor((double) w / 257.0 + 0.5);
 197.173 +    return (cmsUInt8Number) floor((cmsFloat64Number) w / 257.0 + 0.5);
 197.174  }
 197.175  
 197.176  
 197.177  // Convert to byte (using ICC2 notation)
 197.178 +/*
 197.179 +static
 197.180 +cmsUInt8Number L2Byte(cmsUInt16Number w)
 197.181 +{
 197.182 +        int ww = w + 0x0080;
 197.183 +
 197.184 +        if (ww > 0xFFFF) return 0xFF;
 197.185 +
 197.186 +    return (cmsUInt8Number) ((cmsUInt16Number) (ww >> 8) & 0xFF);
 197.187 +}
 197.188 +*/
 197.189 +
 197.190 +// Write a cooked byte
 197.191  
 197.192  static
 197.193 -BYTE L2Byte(WORD w)
 197.194 +void WriteByte(cmsIOHANDLER* m, cmsUInt8Number b)
 197.195  {
 197.196 -    int ww = w + 0x0080;
 197.197 +    _cmsIOPrintf(m, "%02x", b);
 197.198 +    _cmsPSActualColumn += 2;
 197.199  
 197.200 -    if (ww > 0xFFFF) return 0xFF;
 197.201 +    if (_cmsPSActualColumn > MAXPSCOLS) {
 197.202  
 197.203 -    return (BYTE) ((WORD) (ww >> 8) & 0xFF);
 197.204 +        _cmsIOPrintf(m, "\n");
 197.205 +        _cmsPSActualColumn = 0;
 197.206 +    }
 197.207  }
 197.208  
 197.209 -// Write a raw, uncooked byte. Check for space
 197.210 -static
 197.211 -void WriteRawByte(LPMEMSTREAM m, BYTE b)
 197.212 -{
 197.213 -    if (m -> dwUsed + 1 > m -> dwMax) {
 197.214 -        m -> HasError = 1;
 197.215 -    }
 197.216 -
 197.217 -    if (!m ->HasError && m ->Block) {
 197.218 -        *m ->Ptr++ = b;
 197.219 -    }
 197.220 -
 197.221 -    m -> dwUsed++;
 197.222 -}
 197.223 -
 197.224 -// Write a cooked byte
 197.225 -static
 197.226 -void WriteByte(LPMEMSTREAM m, BYTE b)
 197.227 -{
 197.228 -    static const BYTE Hex[] = "0123456789ABCDEF";
 197.229 -    BYTE c;
 197.230 -
 197.231 -        c = Hex[(b >> 4) & 0x0f];
 197.232 -        WriteRawByte(m, c);
 197.233 -
 197.234 -        c = Hex[b & 0x0f];
 197.235 -        WriteRawByte(m, c);
 197.236 -
 197.237 -        m -> Col += 2;
 197.238 -
 197.239 -        if (m -> Col > m -> MaxCols) {
 197.240 -
 197.241 -            WriteRawByte(m, '\n');
 197.242 -            m -> Col = 0;
 197.243 -        }
 197.244 -
 197.245 -}
 197.246 -
 197.247 -// Does write a formatted string. Guaranteed to be 2048 bytes at most.
 197.248 -static
 197.249 -void Writef(LPMEMSTREAM m, const char *frm, ...)
 197.250 -{
 197.251 -        va_list args;
 197.252 -        LPBYTE pt;
 197.253 -        BYTE Buffer[2048];
 197.254 -
 197.255 -        va_start(args, frm);
 197.256 -
 197.257 -        vsnprintf((char*) Buffer, 2048, frm, args);
 197.258 -
 197.259 -        for (pt = Buffer; *pt; pt++)  {
 197.260 -
 197.261 -            WriteRawByte(m, *pt);
 197.262 -        }
 197.263 -
 197.264 -        va_end(args);
 197.265 -}
 197.266 -
 197.267 -
 197.268 -
 197.269  // ----------------------------------------------------------------- PostScript generation
 197.270  
 197.271  
 197.272 @@ -466,21 +372,31 @@
 197.273  }
 197.274  
 197.275  static
 197.276 -void EmitHeader(LPMEMSTREAM m, const char* Title, cmsHPROFILE hProfile)
 197.277 +void EmitHeader(cmsIOHANDLER* m, const char* Title, cmsHPROFILE hProfile)
 197.278  {
 197.279 -
 197.280      time_t timer;
 197.281 +    cmsMLU *Description, *Copyright;
 197.282 +    char DescASCII[256], CopyrightASCII[256];
 197.283  
 197.284      time(&timer);
 197.285  
 197.286 -    Writef(m, "%%!PS-Adobe-3.0\n");
 197.287 -    Writef(m, "%%\n");
 197.288 -    Writef(m, "%% %s\n", Title);
 197.289 -    Writef(m, "%% Source: %s\n", RemoveCR(cmsTakeProductName(hProfile)));
 197.290 -    Writef(m, "%% Description: %s\n", RemoveCR(cmsTakeProductDesc(hProfile)));
 197.291 -    Writef(m, "%% Created: %s", ctime(&timer)); // ctime appends a \n!!!
 197.292 -    Writef(m, "%%\n");
 197.293 -    Writef(m, "%%%%BeginResource\n");
 197.294 +    Description = (cmsMLU*) cmsReadTag(hProfile, cmsSigProfileDescriptionTag);
 197.295 +    Copyright   = (cmsMLU*) cmsReadTag(hProfile, cmsSigCopyrightTag);
 197.296 +
 197.297 +    DescASCII[0] = DescASCII[255] = 0;
 197.298 +    CopyrightASCII[0] = CopyrightASCII[255] = 0;
 197.299 +
 197.300 +    if (Description != NULL) cmsMLUgetASCII(Description,  cmsNoLanguage, cmsNoCountry, DescASCII,       255);
 197.301 +    if (Copyright != NULL)   cmsMLUgetASCII(Copyright,    cmsNoLanguage, cmsNoCountry, CopyrightASCII,  255);
 197.302 +
 197.303 +    _cmsIOPrintf(m, "%%!PS-Adobe-3.0\n");
 197.304 +    _cmsIOPrintf(m, "%%\n");
 197.305 +    _cmsIOPrintf(m, "%% %s\n", Title);
 197.306 +    _cmsIOPrintf(m, "%% Source: %s\n", RemoveCR(DescASCII));
 197.307 +    _cmsIOPrintf(m, "%%         %s\n", RemoveCR(CopyrightASCII));
 197.308 +    _cmsIOPrintf(m, "%% Created: %s", ctime(&timer)); // ctime appends a \n!!!
 197.309 +    _cmsIOPrintf(m, "%%\n");
 197.310 +    _cmsIOPrintf(m, "%%%%BeginResource\n");
 197.311  
 197.312  }
 197.313  
 197.314 @@ -489,31 +405,31 @@
 197.315  // Black point adapted to D50.
 197.316  
 197.317  static
 197.318 -void EmitWhiteBlackD50(LPMEMSTREAM m, LPcmsCIEXYZ BlackPoint)
 197.319 +void EmitWhiteBlackD50(cmsIOHANDLER* m, cmsCIEXYZ* BlackPoint)
 197.320  {
 197.321  
 197.322 -    Writef(m, "/BlackPoint [%f %f %f]\n", BlackPoint -> X,
 197.323 +    _cmsIOPrintf(m, "/BlackPoint [%f %f %f]\n", BlackPoint -> X,
 197.324                                            BlackPoint -> Y,
 197.325                                            BlackPoint -> Z);
 197.326  
 197.327 -    Writef(m, "/WhitePoint [%f %f %f]\n", cmsD50_XYZ()->X,
 197.328 +    _cmsIOPrintf(m, "/WhitePoint [%f %f %f]\n", cmsD50_XYZ()->X,
 197.329                                            cmsD50_XYZ()->Y,
 197.330                                            cmsD50_XYZ()->Z);
 197.331  }
 197.332  
 197.333  
 197.334  static
 197.335 -void EmitRangeCheck(LPMEMSTREAM m)
 197.336 +void EmitRangeCheck(cmsIOHANDLER* m)
 197.337  {
 197.338 -    Writef(m, "dup 0.0 lt { pop 0.0 } if "
 197.339 -              "dup 1.0 gt { pop 1.0 } if ");
 197.340 +    _cmsIOPrintf(m, "dup 0.0 lt { pop 0.0 } if "
 197.341 +                    "dup 1.0 gt { pop 1.0 } if ");
 197.342  
 197.343  }
 197.344  
 197.345  // Does write the intent
 197.346  
 197.347  static
 197.348 -void EmitIntent(LPMEMSTREAM m, int RenderingIntent)
 197.349 +void EmitIntent(cmsIOHANDLER* m, int RenderingIntent)
 197.350  {
 197.351      const char *intent;
 197.352  
 197.353 @@ -527,7 +443,7 @@
 197.354          default: intent = "Undefined"; break;
 197.355      }
 197.356  
 197.357 -    Writef(m, "/RenderingIntent (%s)\n", intent );
 197.358 +    _cmsIOPrintf(m, "/RenderingIntent (%s)\n", intent );
 197.359  }
 197.360  
 197.361  //
 197.362 @@ -539,9 +455,9 @@
 197.363  
 197.364  /*
 197.365  static
 197.366 -void EmitL2Y(LPMEMSTREAM m)
 197.367 +void EmitL2Y(cmsIOHANDLER* m)
 197.368  {
 197.369 -    Writef(m,
 197.370 +    _cmsIOPrintf(m,
 197.371              "{ "
 197.372                  "100 mul 16 add 116 div "               // (L * 100 + 16) / 116
 197.373                   "dup 6 29 div ge "                     // >= 6 / 29 ?
 197.374 @@ -555,21 +471,21 @@
 197.375  // Lab -> XYZ, see the discussion above
 197.376  
 197.377  static
 197.378 -void EmitLab2XYZ(LPMEMSTREAM m)
 197.379 +void EmitLab2XYZ(cmsIOHANDLER* m)
 197.380  {
 197.381 -    Writef(m, "/RangeABC [ 0 1 0 1 0 1]\n");
 197.382 -    Writef(m, "/DecodeABC [\n");
 197.383 -    Writef(m, "{100 mul  16 add 116 div } bind\n");
 197.384 -    Writef(m, "{255 mul 128 sub 500 div } bind\n");
 197.385 -    Writef(m, "{255 mul 128 sub 200 div } bind\n");
 197.386 -    Writef(m, "]\n");
 197.387 -    Writef(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n");
 197.388 -    Writef(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n");
 197.389 -    Writef(m, "/DecodeLMN [\n");
 197.390 -    Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n");
 197.391 -    Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n");
 197.392 -    Writef(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind\n");
 197.393 -    Writef(m, "]\n");
 197.394 +    _cmsIOPrintf(m, "/RangeABC [ 0 1 0 1 0 1]\n");
 197.395 +    _cmsIOPrintf(m, "/DecodeABC [\n");
 197.396 +    _cmsIOPrintf(m, "{100 mul  16 add 116 div } bind\n");
 197.397 +    _cmsIOPrintf(m, "{255 mul 128 sub 500 div } bind\n");
 197.398 +    _cmsIOPrintf(m, "{255 mul 128 sub 200 div } bind\n");
 197.399 +    _cmsIOPrintf(m, "]\n");
 197.400 +    _cmsIOPrintf(m, "/MatrixABC [ 1 1 1 1 0 0 0 0 -1]\n");
 197.401 +    _cmsIOPrintf(m, "/RangeLMN [ -0.236 1.254 0 1 -0.635 1.640 ]\n");
 197.402 +    _cmsIOPrintf(m, "/DecodeLMN [\n");
 197.403 +    _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.964200 mul} bind\n");
 197.404 +    _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse } bind\n");
 197.405 +    _cmsIOPrintf(m, "{dup 6 29 div ge {dup dup mul mul} {4 29 div sub 108 841 div mul} ifelse 0.824900 mul} bind\n");
 197.406 +    _cmsIOPrintf(m, "]\n");
 197.407  }
 197.408  
 197.409  
 197.410 @@ -577,29 +493,25 @@
 197.411  // Outputs a table of words. It does use 16 bits
 197.412  
 197.413  static
 197.414 -void Emit1Gamma(LPMEMSTREAM m, LPWORD Table, int nEntries)
 197.415 +void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table)
 197.416  {
 197.417 -    int i;
 197.418 -    double gamma;
 197.419 +    cmsUInt32Number i;
 197.420 +    cmsFloat64Number gamma;
 197.421  
 197.422  
 197.423 -    if (nEntries <= 0) return;  // Empty table
 197.424 +    if (Table ->nEntries <= 0) return;  // Empty table
 197.425  
 197.426      // Suppress whole if identity
 197.427 -    if (cmsIsLinear(Table, nEntries)) {
 197.428 -            Writef(m, "{} ");
 197.429 -            return;
 197.430 -    }
 197.431 -
 197.432 +    if (cmsIsToneCurveLinear(Table)) return;
 197.433  
 197.434      // Check if is really an exponential. If so, emit "exp"
 197.435 -     gamma = cmsEstimateGammaEx(Table, nEntries, 0.001);
 197.436 +    gamma = cmsEstimateGamma(Table, 0.001);
 197.437       if (gamma > 0) {
 197.438 -            Writef(m, "{ %g exp } bind ", gamma);
 197.439 +            _cmsIOPrintf(m, "{ %g exp } bind ", gamma);
 197.440              return;
 197.441       }
 197.442  
 197.443 -    Writef(m, "{ ");
 197.444 +    _cmsIOPrintf(m, "{ ");
 197.445  
 197.446      // Bounds check
 197.447      EmitRangeCheck(m);
 197.448 @@ -609,94 +521,74 @@
 197.449      // PostScript code                      Stack
 197.450      // ===============                      ========================
 197.451                                              // v
 197.452 -    Writef(m, " [");
 197.453 +    _cmsIOPrintf(m, " [");
 197.454  
 197.455 -    // TODO: Check for endianess!!!
 197.456 -
 197.457 -    for (i=0; i < nEntries; i++) {
 197.458 -            Writef(m, "%d ", Table[i]);
 197.459 +    for (i=0; i < Table->nEntries; i++) {
 197.460 +        _cmsIOPrintf(m, "%d ", Table->Table16[i]);
 197.461      }
 197.462  
 197.463 -    Writef(m, "] ");                        // v tab
 197.464 +    _cmsIOPrintf(m, "] ");                        // v tab
 197.465  
 197.466 -    Writef(m, "dup ");                      // v tab tab
 197.467 -    Writef(m, "length 1 sub ");             // v tab dom
 197.468 -    Writef(m, "3 -1 roll ");                // tab dom v
 197.469 -    Writef(m, "mul ");                      // tab val2
 197.470 -    Writef(m, "dup ");                      // tab val2 val2
 197.471 -    Writef(m, "dup ");                      // tab val2 val2 val2
 197.472 -    Writef(m, "floor cvi ");                // tab val2 val2 cell0
 197.473 -    Writef(m, "exch ");                     // tab val2 cell0 val2
 197.474 -    Writef(m, "ceiling cvi ");              // tab val2 cell0 cell1
 197.475 -    Writef(m, "3 index ");                  // tab val2 cell0 cell1 tab
 197.476 -    Writef(m, "exch ");                     // tab val2 cell0 tab cell1
 197.477 -    Writef(m, "get ");                      // tab val2 cell0 y1
 197.478 -    Writef(m, "4 -1 roll ");                // val2 cell0 y1 tab
 197.479 -    Writef(m, "3 -1 roll ");                // val2 y1 tab cell0
 197.480 -    Writef(m, "get ");                      // val2 y1 y0
 197.481 -    Writef(m, "dup ");                      // val2 y1 y0 y0
 197.482 -    Writef(m, "3 1 roll ");                 // val2 y0 y1 y0
 197.483 -    Writef(m, "sub ");                      // val2 y0 (y1-y0)
 197.484 -    Writef(m, "3 -1 roll ");                // y0 (y1-y0) val2
 197.485 -    Writef(m, "dup ");                      // y0 (y1-y0) val2 val2
 197.486 -    Writef(m, "floor cvi ");                // y0 (y1-y0) val2 floor(val2)
 197.487 -    Writef(m, "sub ");                      // y0 (y1-y0) rest
 197.488 -    Writef(m, "mul ");                      // y0 t1
 197.489 -    Writef(m, "add ");                      // y
 197.490 -    Writef(m, "65535 div ");                // result
 197.491 +    _cmsIOPrintf(m, "dup ");                      // v tab tab
 197.492 +    _cmsIOPrintf(m, "length 1 sub ");             // v tab dom
 197.493 +    _cmsIOPrintf(m, "3 -1 roll ");                // tab dom v
 197.494 +    _cmsIOPrintf(m, "mul ");                      // tab val2
 197.495 +    _cmsIOPrintf(m, "dup ");                      // tab val2 val2
 197.496 +    _cmsIOPrintf(m, "dup ");                      // tab val2 val2 val2
 197.497 +    _cmsIOPrintf(m, "floor cvi ");                // tab val2 val2 cell0
 197.498 +    _cmsIOPrintf(m, "exch ");                     // tab val2 cell0 val2
 197.499 +    _cmsIOPrintf(m, "ceiling cvi ");              // tab val2 cell0 cell1
 197.500 +    _cmsIOPrintf(m, "3 index ");                  // tab val2 cell0 cell1 tab
 197.501 +    _cmsIOPrintf(m, "exch ");                     // tab val2 cell0 tab cell1
 197.502 +    _cmsIOPrintf(m, "get ");                      // tab val2 cell0 y1
 197.503 +    _cmsIOPrintf(m, "4 -1 roll ");                // val2 cell0 y1 tab
 197.504 +    _cmsIOPrintf(m, "3 -1 roll ");                // val2 y1 tab cell0
 197.505 +    _cmsIOPrintf(m, "get ");                      // val2 y1 y0
 197.506 +    _cmsIOPrintf(m, "dup ");                      // val2 y1 y0 y0
 197.507 +    _cmsIOPrintf(m, "3 1 roll ");                 // val2 y0 y1 y0
 197.508 +    _cmsIOPrintf(m, "sub ");                      // val2 y0 (y1-y0)
 197.509 +    _cmsIOPrintf(m, "3 -1 roll ");                // y0 (y1-y0) val2
 197.510 +    _cmsIOPrintf(m, "dup ");                      // y0 (y1-y0) val2 val2
 197.511 +    _cmsIOPrintf(m, "floor cvi ");                // y0 (y1-y0) val2 floor(val2)
 197.512 +    _cmsIOPrintf(m, "sub ");                      // y0 (y1-y0) rest
 197.513 +    _cmsIOPrintf(m, "mul ");                      // y0 t1
 197.514 +    _cmsIOPrintf(m, "add ");                      // y
 197.515 +    _cmsIOPrintf(m, "65535 div ");                // result
 197.516  
 197.517 -    Writef(m, " } bind ");
 197.518 +    _cmsIOPrintf(m, " } bind ");
 197.519  }
 197.520  
 197.521  
 197.522  // Compare gamma table
 197.523  
 197.524  static
 197.525 -LCMSBOOL GammaTableEquals(LPWORD g1, LPWORD g2, int nEntries)
 197.526 +cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, int nEntries)
 197.527  {
 197.528 -    return memcmp(g1, g2, nEntries* sizeof(WORD)) == 0;
 197.529 +    return memcmp(g1, g2, nEntries* sizeof(cmsUInt16Number)) == 0;
 197.530  }
 197.531  
 197.532  
 197.533  // Does write a set of gamma curves
 197.534  
 197.535  static
 197.536 -void EmitNGamma(LPMEMSTREAM m, int n, LPWORD g[], int nEntries)
 197.537 +void EmitNGamma(cmsIOHANDLER* m, int n, cmsToneCurve* g[])
 197.538  {
 197.539      int i;
 197.540  
 197.541      for( i=0; i < n; i++ )
 197.542      {
 197.543 -        if (i > 0 && GammaTableEquals(g[i-1], g[i], nEntries)) {
 197.544 +        if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i]->nEntries)) {
 197.545  
 197.546 -            Writef(m, "dup ");
 197.547 +            _cmsIOPrintf(m, "dup ");
 197.548          }
 197.549          else {
 197.550 -            Emit1Gamma(m, g[i], nEntries);
 197.551 +            Emit1Gamma(m, g[i]);
 197.552          }
 197.553      }
 197.554  
 197.555  }
 197.556  
 197.557  
 197.558 -// Check whatever a profile has CLUT tables (only on input)
 197.559 -
 197.560 -static
 197.561 -LCMSBOOL IsLUTbased(cmsHPROFILE hProfile, int Intent)
 197.562 -{
 197.563 -    icTagSignature Tag;
 197.564 -
 197.565 -    // Check if adequate tag is present
 197.566 -    Tag = Device2PCSTab[Intent];
 197.567 -
 197.568 -    if (cmsIsTag(hProfile, Tag)) return 1;
 197.569 -
 197.570 -    // If not present, revert to default (perceptual)
 197.571 -    Tag = icSigAToB0Tag;
 197.572 -
 197.573 -    // If no tag present, try matrix-shaper
 197.574 -    return cmsIsTag(hProfile, Tag);
 197.575 -}
 197.576  
 197.577  
 197.578  
 197.579 @@ -707,19 +599,19 @@
 197.580  // that is, the callback will be called for each knot with
 197.581  //
 197.582  //          In[]  The grid location coordinates, normalized to 0..ffff
 197.583 -//          Out[] The LUT values, normalized to 0..ffff
 197.584 +//          Out[] The Pipeline values, normalized to 0..ffff
 197.585  //
 197.586  //  Returning a value other than 0 does terminate the sampling process
 197.587  //
 197.588 -//  Each row contains LUT values for all but first component. So, I
 197.589 +//  Each row contains Pipeline values for all but first component. So, I
 197.590  //  detect row changing by keeping a copy of last value of first
 197.591  //  component. -1 is used to mark begining of whole block.
 197.592  
 197.593  static
 197.594 -int OutputValueSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
 197.595 +int OutputValueSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
 197.596  {
 197.597 -    LPSAMPLERCARGO sc = (LPSAMPLERCARGO) Cargo;
 197.598 -    unsigned int i;
 197.599 +    cmsPsSamplerCargo* sc = (cmsPsSamplerCargo*) Cargo;
 197.600 +    cmsUInt32Number i;
 197.601  
 197.602  
 197.603      if (sc -> FixWhite) {
 197.604 @@ -729,14 +621,14 @@
 197.605              if ((In[1] >= 0x7800 && In[1] <= 0x8800) &&
 197.606                  (In[2] >= 0x7800 && In[2] <= 0x8800)) {
 197.607  
 197.608 -                WORD* Black;
 197.609 -                WORD* White;
 197.610 -                int nOutputs;
 197.611 +                cmsUInt16Number* Black;
 197.612 +                cmsUInt16Number* White;
 197.613 +                cmsUInt32Number nOutputs;
 197.614  
 197.615                  if (!_cmsEndPointsBySpace(sc ->ColorSpace, &White, &Black, &nOutputs))
 197.616                          return 0;
 197.617  
 197.618 -                for (i=0; i < (unsigned int) nOutputs; i++)
 197.619 +                for (i=0; i < nOutputs; i++)
 197.620                          Out[i] = White[i];
 197.621              }
 197.622  
 197.623 @@ -751,15 +643,15 @@
 197.624  
 197.625              if (sc ->FirstComponent != -1) {
 197.626  
 197.627 -                    Writef(sc ->m, sc ->PostMin);
 197.628 +                    _cmsIOPrintf(sc ->m, sc ->PostMin);
 197.629                      sc ->SecondComponent = -1;
 197.630 -                    Writef(sc ->m, sc ->PostMaj);
 197.631 +                    _cmsIOPrintf(sc ->m, sc ->PostMaj);
 197.632              }
 197.633  
 197.634              // Begin block
 197.635 -            sc->m->Col = 0;
 197.636 +            _cmsPSActualColumn = 0;
 197.637  
 197.638 -            Writef(sc ->m, sc ->PreMaj);
 197.639 +            _cmsIOPrintf(sc ->m, sc ->PreMaj);
 197.640              sc ->FirstComponent = In[0];
 197.641      }
 197.642  
 197.643 @@ -768,96 +660,66 @@
 197.644  
 197.645              if (sc ->SecondComponent != -1) {
 197.646  
 197.647 -                    Writef(sc ->m, sc ->PostMin);
 197.648 +                    _cmsIOPrintf(sc ->m, sc ->PostMin);
 197.649              }
 197.650  
 197.651 -            Writef(sc ->m, sc ->PreMin);
 197.652 +            _cmsIOPrintf(sc ->m, sc ->PreMin);
 197.653              sc ->SecondComponent = In[1];
 197.654      }
 197.655  
 197.656 +      // Dump table.
 197.657  
 197.658 +      for (i=0; i < sc -> Pipeline ->Params->nOutputs; i++) {
 197.659  
 197.660 -    // Dump table. Could be Word or byte based on
 197.661 -    // depending on bps member (16 bps mode is not currently
 197.662 -    // being used at all, but is here for future ampliations)
 197.663 +          cmsUInt16Number wWordOut = Out[i];
 197.664 +          cmsUInt8Number wByteOut;           // Value as byte
 197.665  
 197.666 -    for (i=0; i < sc -> Lut ->OutputChan; i++) {
 197.667 +          // We always deal with Lab4
 197.668  
 197.669 -        WORD wWordOut = Out[i];
 197.670 +          wByteOut = Word2Byte(wWordOut);
 197.671 +          WriteByte(sc -> m, wByteOut);
 197.672 +      }
 197.673  
 197.674 -        if (sc ->bps == 8) {
 197.675 -
 197.676 -            // Value as byte
 197.677 -            BYTE wByteOut;
 197.678 -
 197.679 -            // If is input, convert from Lab2 to Lab4 (just divide by 256)
 197.680 -
 197.681 -            if (sc ->lIsInput) {
 197.682 -
 197.683 -
 197.684 -                wByteOut = L2Byte(wWordOut);
 197.685 -            }
 197.686 -            else
 197.687 -                wByteOut = Word2Byte(wWordOut);
 197.688 -
 197.689 -            WriteByte(sc -> m, wByteOut);
 197.690 -        }
 197.691 -        else {
 197.692 -
 197.693 -            // Value as word
 197.694 -            WriteByte(sc -> m, (BYTE) (wWordOut & 0xFF));
 197.695 -            WriteByte(sc -> m, (BYTE) ((wWordOut >> 8) & 0xFF));
 197.696 -        }
 197.697 -     }
 197.698 -
 197.699 -    return 1;
 197.700 +      return 1;
 197.701  }
 197.702  
 197.703 -// Writes a LUT on memstream. Could be 8 or 16 bits based
 197.704 +// Writes a Pipeline on memstream. Could be 8 or 16 bits based
 197.705  
 197.706  static
 197.707 -void WriteCLUT(LPMEMSTREAM m, LPLUT Lut, int bps, const char* PreMaj,
 197.708 -                                                  const char* PostMaj,
 197.709 -                                                  const char* PreMin,
 197.710 -                                                  const char* PostMin,
 197.711 -                                                  int lIsInput,
 197.712 -                                                  int FixWhite,
 197.713 -                                                  icColorSpaceSignature ColorSpace)
 197.714 +void WriteCLUT(cmsIOHANDLER* m, cmsStage* mpe, const char* PreMaj,
 197.715 +                                             const char* PostMaj,
 197.716 +                                             const char* PreMin,
 197.717 +                                             const char* PostMin,
 197.718 +                                             int FixWhite,
 197.719 +                                             cmsColorSpaceSignature ColorSpace)
 197.720  {
 197.721 -    unsigned int i;
 197.722 -    SAMPLERCARGO sc;
 197.723 +    cmsUInt32Number i;
 197.724 +    cmsPsSamplerCargo sc;
 197.725  
 197.726      sc.FirstComponent = -1;
 197.727      sc.SecondComponent = -1;
 197.728 -    sc.Lut = Lut;
 197.729 +    sc.Pipeline = (_cmsStageCLutData *) mpe ->Data;
 197.730      sc.m   = m;
 197.731 -    sc.bps = bps;
 197.732      sc.PreMaj = PreMaj;
 197.733      sc.PostMaj= PostMaj;
 197.734  
 197.735      sc.PreMin   = PreMin;
 197.736      sc.PostMin  = PostMin;
 197.737 -    sc.lIsInput = lIsInput;
 197.738      sc.FixWhite = FixWhite;
 197.739      sc.ColorSpace = ColorSpace;
 197.740  
 197.741 -    Writef(m, "[");
 197.742 +    _cmsIOPrintf(m, "[");
 197.743  
 197.744 -    for (i=0; i < Lut ->InputChan; i++)
 197.745 -            Writef(m, " %d ", Lut ->cLutPoints);
 197.746 +    for (i=0; i < sc.Pipeline->Params->nInputs; i++)
 197.747 +        _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
 197.748  
 197.749 -    Writef(m, " [\n");
 197.750 +    _cmsIOPrintf(m, " [\n");
 197.751  
 197.752 +    cmsStageSampleCLut16bit(mpe, OutputValueSampler, (void*) &sc, SAMPLER_INSPECT);
 197.753  
 197.754 -
 197.755 -    cmsSample3DGrid(Lut, OutputValueSampler, (LPVOID) &sc, SAMPLER_INSPECT);
 197.756 -
 197.757 -
 197.758 -    Writef(m, PostMin);
 197.759 -    Writef(m, PostMaj);
 197.760 -    Writef(m, "] ");
 197.761 -
 197.762 -
 197.763 +    _cmsIOPrintf(m, PostMin);
 197.764 +    _cmsIOPrintf(m, PostMaj);
 197.765 +    _cmsIOPrintf(m, "] ");
 197.766  
 197.767  }
 197.768  
 197.769 @@ -865,89 +727,92 @@
 197.770  // Dumps CIEBasedA Color Space Array
 197.771  
 197.772  static
 197.773 -int EmitCIEBasedA(LPMEMSTREAM m, LPWORD Tab, int nEntries, LPcmsCIEXYZ BlackPoint)
 197.774 +int EmitCIEBasedA(cmsIOHANDLER* m, cmsToneCurve* Curve, cmsCIEXYZ* BlackPoint)
 197.775  {
 197.776  
 197.777 -        Writef(m, "[ /CIEBasedA\n");
 197.778 -        Writef(m, "  <<\n");
 197.779 +    _cmsIOPrintf(m, "[ /CIEBasedA\n");
 197.780 +    _cmsIOPrintf(m, "  <<\n");
 197.781  
 197.782 -        Writef(m, "/DecodeA ");
 197.783 +    _cmsIOPrintf(m, "/DecodeA ");
 197.784  
 197.785 -        Emit1Gamma(m,Tab, nEntries);
 197.786 +    Emit1Gamma(m, Curve);
 197.787  
 197.788 -        Writef(m, " \n");
 197.789 +    _cmsIOPrintf(m, " \n");
 197.790  
 197.791 -        Writef(m, "/MatrixA [ 0.9642 1.0000 0.8249 ]\n");
 197.792 -        Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
 197.793 +    _cmsIOPrintf(m, "/MatrixA [ 0.9642 1.0000 0.8249 ]\n");
 197.794 +    _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
 197.795  
 197.796 -        EmitWhiteBlackD50(m, BlackPoint);
 197.797 -        EmitIntent(m, INTENT_PERCEPTUAL);
 197.798 +    EmitWhiteBlackD50(m, BlackPoint);
 197.799 +    EmitIntent(m, INTENT_PERCEPTUAL);
 197.800  
 197.801 -        Writef(m, ">>\n");
 197.802 -        Writef(m, "]\n");
 197.803 +    _cmsIOPrintf(m, ">>\n");
 197.804 +    _cmsIOPrintf(m, "]\n");
 197.805  
 197.806 -        return 1;
 197.807 +    return 1;
 197.808  }
 197.809  
 197.810  
 197.811  // Dumps CIEBasedABC Color Space Array
 197.812  
 197.813  static
 197.814 -int EmitCIEBasedABC(LPMEMSTREAM m, LPWORD L[], int nEntries, LPWMAT3 Matrix, LPcmsCIEXYZ BlackPoint)
 197.815 +int EmitCIEBasedABC(cmsIOHANDLER* m, cmsFloat64Number* Matrix, cmsToneCurve** CurveSet, cmsCIEXYZ* BlackPoint)
 197.816  {
 197.817      int i;
 197.818  
 197.819 -        Writef(m, "[ /CIEBasedABC\n");
 197.820 -        Writef(m, "<<\n");
 197.821 -        Writef(m, "/DecodeABC [ ");
 197.822 +    _cmsIOPrintf(m, "[ /CIEBasedABC\n");
 197.823 +    _cmsIOPrintf(m, "<<\n");
 197.824 +    _cmsIOPrintf(m, "/DecodeABC [ ");
 197.825  
 197.826 -        EmitNGamma(m, 3, L, nEntries);
 197.827 +    EmitNGamma(m, 3, CurveSet);
 197.828  
 197.829 -        Writef(m, "]\n");
 197.830 +    _cmsIOPrintf(m, "]\n");
 197.831  
 197.832 -        Writef(m, "/MatrixABC [ " );
 197.833 +    _cmsIOPrintf(m, "/MatrixABC [ " );
 197.834  
 197.835 -        for( i=0; i < 3; i++ ) {
 197.836 +    for( i=0; i < 3; i++ ) {
 197.837  
 197.838 -            Writef(m, "%.6f %.6f %.6f ",
 197.839 -                        FIXED_TO_DOUBLE(Matrix->v[0].n[i]),
 197.840 -                        FIXED_TO_DOUBLE(Matrix->v[1].n[i]),
 197.841 -                        FIXED_TO_DOUBLE(Matrix->v[2].n[i]));
 197.842 -        }
 197.843 +        _cmsIOPrintf(m, "%.6f %.6f %.6f ", Matrix[0 + 3*i],
 197.844 +                     Matrix[1 + 3*i],
 197.845 +                     Matrix[2 + 3*i]);
 197.846 +    }
 197.847  
 197.848  
 197.849 -        Writef(m, "]\n");
 197.850 +    _cmsIOPrintf(m, "]\n");
 197.851  
 197.852 -        Writef(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
 197.853 +    _cmsIOPrintf(m, "/RangeLMN [ 0.0 0.9642 0.0 1.0000 0.0 0.8249 ]\n");
 197.854  
 197.855 -        EmitWhiteBlackD50(m, BlackPoint);
 197.856 -        EmitIntent(m, INTENT_PERCEPTUAL);
 197.857 +    EmitWhiteBlackD50(m, BlackPoint);
 197.858 +    EmitIntent(m, INTENT_PERCEPTUAL);
 197.859  
 197.860 -        Writef(m, ">>\n");
 197.861 -        Writef(m, "]\n");
 197.862 +    _cmsIOPrintf(m, ">>\n");
 197.863 +    _cmsIOPrintf(m, "]\n");
 197.864  
 197.865  
 197.866 -        return 1;
 197.867 +    return 1;
 197.868  }
 197.869  
 197.870  
 197.871  static
 197.872 -int EmitCIEBasedDEF(LPMEMSTREAM m, LPLUT Lut, int Intent, LPcmsCIEXYZ BlackPoint)
 197.873 +int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, int Intent, cmsCIEXYZ* BlackPoint)
 197.874  {
 197.875      const char* PreMaj;
 197.876      const char* PostMaj;
 197.877      const char* PreMin, *PostMin;
 197.878 +    cmsStage* mpe;
 197.879  
 197.880 -    switch (Lut ->InputChan) {
 197.881 +    mpe = Pipeline ->Elements;
 197.882 +
 197.883 +
 197.884 +    switch (cmsStageInputChannels(mpe)) {
 197.885      case 3:
 197.886  
 197.887 -            Writef(m, "[ /CIEBasedDEF\n");
 197.888 +            _cmsIOPrintf(m, "[ /CIEBasedDEF\n");
 197.889              PreMaj ="<";
 197.890              PostMaj= ">\n";
 197.891              PreMin = PostMin = "";
 197.892              break;
 197.893      case 4:
 197.894 -            Writef(m, "[ /CIEBasedDEFG\n");
 197.895 +            _cmsIOPrintf(m, "[ /CIEBasedDEFG\n");
 197.896              PreMaj = "[";
 197.897              PostMaj = "]\n";
 197.898              PreMin = "<";
 197.899 @@ -958,30 +823,32 @@
 197.900  
 197.901      }
 197.902  
 197.903 -    Writef(m, "<<\n");
 197.904 +    _cmsIOPrintf(m, "<<\n");
 197.905  
 197.906 -    if (Lut ->wFlags & LUT_HASTL1) {
 197.907 +    if (cmsStageType(mpe) == cmsSigCurveSetElemType) {
 197.908  
 197.909 -        Writef(m, "/DecodeDEF [ ");
 197.910 -        EmitNGamma(m, Lut ->InputChan, Lut ->L1, Lut ->CLut16params.nSamples);
 197.911 -        Writef(m, "]\n");
 197.912 +        _cmsIOPrintf(m, "/DecodeDEF [ ");
 197.913 +        EmitNGamma(m, cmsStageOutputChannels(mpe), _cmsStageGetPtrToCurveSet(mpe));
 197.914 +        _cmsIOPrintf(m, "]\n");
 197.915 +
 197.916 +        mpe = mpe ->Next;
 197.917      }
 197.918  
 197.919  
 197.920  
 197.921 -    if (Lut ->wFlags & LUT_HAS3DGRID) {
 197.922 +    if (cmsStageType(mpe) == cmsSigCLutElemType) {
 197.923  
 197.924 -            Writef(m, "/Table ");
 197.925 -            WriteCLUT(m, Lut, 8, PreMaj, PostMaj, PreMin, PostMin, TRUE, FALSE, (icColorSpaceSignature) 0);
 197.926 -            Writef(m, "]\n");
 197.927 +            _cmsIOPrintf(m, "/Table ");
 197.928 +            WriteCLUT(m, mpe, PreMaj, PostMaj, PreMin, PostMin, FALSE, (cmsColorSpaceSignature) 0);
 197.929 +            _cmsIOPrintf(m, "]\n");
 197.930      }
 197.931  
 197.932      EmitLab2XYZ(m);
 197.933      EmitWhiteBlackD50(m, BlackPoint);
 197.934      EmitIntent(m, Intent);
 197.935  
 197.936 -    Writef(m, "   >>\n");
 197.937 -    Writef(m, "]\n");
 197.938 +    _cmsIOPrintf(m, "   >>\n");
 197.939 +    _cmsIOPrintf(m, "]\n");
 197.940  
 197.941  
 197.942      return 1;
 197.943 @@ -990,21 +857,21 @@
 197.944  // Generates a curve from a gray profile
 197.945  
 197.946  static
 197.947 -LPGAMMATABLE ExtractGray2Y(cmsHPROFILE hProfile, int Intent)
 197.948 +cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, int Intent)
 197.949  {
 197.950 -    LPGAMMATABLE Out = cmsAllocGamma(256);
 197.951 -    cmsHPROFILE hXYZ = cmsCreateXYZProfile();
 197.952 -    cmsHTRANSFORM xform = cmsCreateTransform(hProfile, TYPE_GRAY_8, hXYZ, TYPE_XYZ_DBL, Intent, cmsFLAGS_NOTPRECALC);
 197.953 +    cmsToneCurve* Out = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL);
 197.954 +    cmsHPROFILE hXYZ  = cmsCreateXYZProfile();
 197.955 +    cmsHTRANSFORM xform = cmsCreateTransformTHR(ContextID, hProfile, TYPE_GRAY_8, hXYZ, TYPE_XYZ_DBL, Intent, cmsFLAGS_NOOPTIMIZE);
 197.956      int i;
 197.957  
 197.958      for (i=0; i < 256; i++) {
 197.959  
 197.960 -      BYTE Gray = (BYTE) i;
 197.961 +      cmsUInt8Number Gray = (cmsUInt8Number) i;
 197.962        cmsCIEXYZ XYZ;
 197.963  
 197.964          cmsDoTransform(xform, &Gray, &XYZ, 1);
 197.965  
 197.966 -        Out ->GammaTable[i] =_cmsClampWord((int) floor(XYZ.Y * 65535.0 + 0.5));
 197.967 +        Out ->Table16[i] =_cmsQuickSaturateWord(XYZ.Y * 65535.0);
 197.968      }
 197.969  
 197.970      cmsDeleteTransform(xform);
 197.971 @@ -1014,17 +881,16 @@
 197.972  
 197.973  
 197.974  
 197.975 -// Because PostScrip has only 8 bits in /Table, we should use
 197.976 +// Because PostScript has only 8 bits in /Table, we should use
 197.977  // a more perceptually uniform space... I do choose Lab.
 197.978  
 197.979  static
 197.980 -int WriteInputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent)
 197.981 +int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags)
 197.982  {
 197.983      cmsHPROFILE hLab;
 197.984      cmsHTRANSFORM xform;
 197.985 -    icColorSpaceSignature ColorSpace;
 197.986 -    int nChannels;
 197.987 -    DWORD InputFormat;
 197.988 +    cmsUInt32Number nChannels;
 197.989 +    cmsUInt32Number InputFormat;
 197.990      int rc;
 197.991      cmsHPROFILE Profiles[2];
 197.992      cmsCIEXYZ BlackPointAdaptedToD50;
 197.993 @@ -1032,49 +898,25 @@
 197.994      // Does create a device-link based transform.
 197.995      // The DeviceLink is next dumped as working CSA.
 197.996  
 197.997 -    hLab        = cmsCreateLabProfile(NULL);
 197.998 -    ColorSpace  =  cmsGetColorSpace(hProfile);
 197.999 -    nChannels   = _cmsChannelsOf(ColorSpace);
197.1000 -    InputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2);
197.1001 +    InputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE);
197.1002 +    nChannels   = T_CHANNELS(InputFormat);
197.1003  
197.1004 -    cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent,LCMS_BPFLAGS_D50_ADAPTED);
197.1005  
197.1006 -    // Is a devicelink profile?
197.1007 -    if (cmsGetDeviceClass(hProfile) == icSigLinkClass) {
197.1008 +    cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0);
197.1009  
197.1010 -        // if devicelink output already Lab, use it directly
197.1011 +    // Adjust output to Lab4
197.1012 +    hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
197.1013  
197.1014 -        if (cmsGetPCS(hProfile) == icSigLabData) {
197.1015 +    Profiles[0] = hProfile;
197.1016 +    Profiles[1] = hLab;
197.1017  
197.1018 -            xform = cmsCreateTransform(hProfile, InputFormat, NULL,
197.1019 -                            TYPE_Lab_DBL, Intent, 0);
197.1020 -        }
197.1021 -        else {
197.1022 -
197.1023 -            // Nope, adjust output to Lab if possible
197.1024 -
197.1025 -            Profiles[0] = hProfile;
197.1026 -            Profiles[1] = hLab;
197.1027 -
197.1028 -            xform = cmsCreateMultiprofileTransform(Profiles, 2,  InputFormat,
197.1029 -                                    TYPE_Lab_DBL, Intent, 0);
197.1030 -        }
197.1031 -
197.1032 -
197.1033 -    }
197.1034 -    else {
197.1035 -
197.1036 -        // This is a normal profile
197.1037 -        xform = cmsCreateTransform(hProfile, InputFormat, hLab,
197.1038 -                            TYPE_Lab_DBL, Intent, 0);
197.1039 -    }
197.1040 -
197.1041 -
197.1042 +    xform = cmsCreateMultiprofileTransform(Profiles, 2,  InputFormat, TYPE_Lab_DBL, Intent, 0);
197.1043 +    cmsCloseProfile(hLab);
197.1044  
197.1045      if (xform == NULL) {
197.1046  
197.1047 -            cmsSignalError(LCMS_ERRC_ABORTED, "Cannot create transform Profile -> Lab");
197.1048 -            return 0;
197.1049 +        cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Profile -> Lab");
197.1050 +        return 0;
197.1051      }
197.1052  
197.1053      // Only 1, 3 and 4 channels are allowed
197.1054 @@ -1082,211 +924,201 @@
197.1055      switch (nChannels) {
197.1056  
197.1057      case 1: {
197.1058 -            LPGAMMATABLE Gray2Y = ExtractGray2Y(hProfile, Intent);
197.1059 -            EmitCIEBasedA(m, Gray2Y->GammaTable, Gray2Y ->nEntries, &BlackPointAdaptedToD50);
197.1060 -            cmsFreeGamma(Gray2Y);
197.1061 +        cmsToneCurve* Gray2Y = ExtractGray2Y(m ->ContextID, hProfile, Intent);
197.1062 +            EmitCIEBasedA(m, Gray2Y, &BlackPointAdaptedToD50);
197.1063 +            cmsFreeToneCurve(Gray2Y);
197.1064              }
197.1065              break;
197.1066  
197.1067      case 3:
197.1068      case 4: {
197.1069 -            LPLUT DeviceLink;
197.1070 -            _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
197.1071 +        cmsUInt32Number OutFrm = TYPE_Lab_16;
197.1072 +            cmsPipeline* DeviceLink;
197.1073 +            _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
197.1074  
197.1075 -            if (v ->DeviceLink)
197.1076 -                rc = EmitCIEBasedDEF(m, v->DeviceLink, Intent, &BlackPointAdaptedToD50);
197.1077 -            else {
197.1078 -                DeviceLink = _cmsPrecalculateDeviceLink(xform, 0);
197.1079 -                rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
197.1080 -                cmsFreeLUT(DeviceLink);
197.1081 -            }
197.1082 +            DeviceLink = cmsPipelineDup(v ->Lut);
197.1083 +            if (DeviceLink == NULL) return 0;
197.1084 +
197.1085 +            dwFlags |= cmsFLAGS_FORCE_CLUT;
197.1086 +            _cmsOptimizePipeline(&DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags);
197.1087 +
197.1088 +            rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
197.1089 +            cmsPipelineFree(DeviceLink);
197.1090              }
197.1091              break;
197.1092  
197.1093      default:
197.1094  
197.1095 -            cmsSignalError(LCMS_ERRC_ABORTED, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels);
197.1096 -            return 0;
197.1097 +        cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels supported for CSA. This profile has %d channels.", nChannels);
197.1098 +        return 0;
197.1099      }
197.1100  
197.1101  
197.1102      cmsDeleteTransform(xform);
197.1103 +
197.1104 +    return 1;
197.1105 +}
197.1106 +
197.1107 +static
197.1108 +cmsFloat64Number* GetPtrToMatrix(const cmsStage* mpe)
197.1109 +{
197.1110 +    _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
197.1111 +
197.1112 +    return Data -> Double;
197.1113 +}
197.1114 +
197.1115 +
197.1116 +// Does create CSA based on matrix-shaper. Allowed types are gray and RGB based
197.1117 +
197.1118 +static
197.1119 +int WriteInputMatrixShaper(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsStage* Matrix, cmsStage* Shaper)
197.1120 +{
197.1121 +    cmsColorSpaceSignature ColorSpace;
197.1122 +    int rc;
197.1123 +    cmsCIEXYZ BlackPointAdaptedToD50;
197.1124 +
197.1125 +    ColorSpace = cmsGetColorSpace(hProfile);
197.1126 +
197.1127 +    cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, INTENT_RELATIVE_COLORIMETRIC, 0);
197.1128 +
197.1129 +    if (ColorSpace == cmsSigGrayData) {
197.1130 +
197.1131 +        cmsToneCurve** ShaperCurve = _cmsStageGetPtrToCurveSet(Shaper);
197.1132 +            rc = EmitCIEBasedA(m, ShaperCurve[0], &BlackPointAdaptedToD50);
197.1133 +
197.1134 +    }
197.1135 +    else
197.1136 +        if (ColorSpace == cmsSigRgbData) {
197.1137 +
197.1138 +            rc = EmitCIEBasedABC(m,  GetPtrToMatrix(Matrix),
197.1139 +                                 _cmsStageGetPtrToCurveSet(Shaper),
197.1140 +                                 &BlackPointAdaptedToD50);
197.1141 +        }
197.1142 +        else  {
197.1143 +
197.1144 +            cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Profile is not suitable for CSA. Unsupported colorspace.");
197.1145 +            return 0;
197.1146 +        }
197.1147 +
197.1148 +    return rc;
197.1149 +}
197.1150 +
197.1151 +
197.1152 +
197.1153 +// Creates a PostScript color list from a named profile data.
197.1154 +// This is a HP extension, and it works in Lab instead of XYZ
197.1155 +
197.1156 +static
197.1157 +int WriteNamedColorCSA(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent)
197.1158 +{
197.1159 +    cmsHTRANSFORM xform;
197.1160 +    cmsHPROFILE   hLab;
197.1161 +    int i, nColors;
197.1162 +    char ColorName[32];
197.1163 +    cmsNAMEDCOLORLIST* NamedColorList;
197.1164 +
197.1165 +    hLab  = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
197.1166 +    xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, hLab, TYPE_Lab_DBL, Intent, 0);
197.1167 +    if (xform == NULL) return 0;
197.1168 +
197.1169 +    NamedColorList = cmsGetNamedColorList(xform);
197.1170 +    if (NamedColorList == NULL) return 0;
197.1171 +
197.1172 +    _cmsIOPrintf(m, "<<\n");
197.1173 +    _cmsIOPrintf(m, "(colorlistcomment) (%s)\n", "Named color CSA");
197.1174 +    _cmsIOPrintf(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n");
197.1175 +    _cmsIOPrintf(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n");
197.1176 +
197.1177 +    nColors   = cmsNamedColorCount(NamedColorList);
197.1178 +
197.1179 +
197.1180 +    for (i=0; i < nColors; i++) {
197.1181 +
197.1182 +        cmsUInt16Number In[1];
197.1183 +        cmsCIELab Lab;
197.1184 +
197.1185 +        In[0] = (cmsUInt16Number) i;
197.1186 +
197.1187 +        if (!cmsNamedColorInfo(NamedColorList, i, ColorName, NULL, NULL, NULL, NULL))
197.1188 +                continue;
197.1189 +
197.1190 +        cmsDoTransform(xform, In, &Lab, 1);
197.1191 +        _cmsIOPrintf(m, "  (%s) [ %.3f %.3f %.3f ]\n", ColorName, Lab.L, Lab.a, Lab.b);
197.1192 +    }
197.1193 +
197.1194 +
197.1195 +
197.1196 +    _cmsIOPrintf(m, ">>\n");
197.1197 +
197.1198 +    cmsDeleteTransform(xform);
197.1199      cmsCloseProfile(hLab);
197.1200      return 1;
197.1201  }
197.1202  
197.1203  
197.1204 -
197.1205 -// Does create CSA based on matrix-shaper. Allowed types are gray and RGB based
197.1206 -
197.1207 +// Does create a Color Space Array on XYZ colorspace for PostScript usage
197.1208  static
197.1209 -int WriteInputMatrixShaper(LPMEMSTREAM m, cmsHPROFILE hProfile)
197.1210 +cmsUInt32Number GenerateCSA(cmsContext ContextID,
197.1211 +                            cmsHPROFILE hProfile,
197.1212 +                            cmsUInt32Number Intent,
197.1213 +                            cmsUInt32Number dwFlags,
197.1214 +                            cmsIOHANDLER* mem)
197.1215  {
197.1216 -    icColorSpaceSignature ColorSpace;
197.1217 -    LPMATSHAPER MatShaper;
197.1218 -    int rc;
197.1219 -    cmsCIEXYZ BlackPointAdaptedToD50;
197.1220 -
197.1221 -
197.1222 -    ColorSpace = cmsGetColorSpace(hProfile);
197.1223 -    MatShaper  = cmsBuildInputMatrixShaper(hProfile);
197.1224 -
197.1225 -    cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, INTENT_RELATIVE_COLORIMETRIC, LCMS_BPFLAGS_D50_ADAPTED);
197.1226 -
197.1227 -    if (MatShaper == NULL) {
197.1228 -
197.1229 -                cmsSignalError(LCMS_ERRC_ABORTED, "This profile is not suitable for input");
197.1230 -                return 0;
197.1231 -    }
197.1232 -
197.1233 -    if (ColorSpace == icSigGrayData) {
197.1234 -
197.1235 -            rc = EmitCIEBasedA(m, MatShaper ->L[0],
197.1236 -                                  MatShaper ->p16.nSamples,
197.1237 -                                  &BlackPointAdaptedToD50);
197.1238 -
197.1239 -    }
197.1240 -    else
197.1241 -        if (ColorSpace == icSigRgbData) {
197.1242 -
197.1243 -
197.1244 -            rc = EmitCIEBasedABC(m, MatShaper->L,
197.1245 -                                        MatShaper ->p16.nSamples,
197.1246 -                                        &MatShaper ->Matrix,
197.1247 -                                        &BlackPointAdaptedToD50);
197.1248 -        }
197.1249 -        else  {
197.1250 -
197.1251 -            cmsSignalError(LCMS_ERRC_ABORTED, "Profile is not suitable for CSA. Unsupported colorspace.");
197.1252 -            return 0;
197.1253 -        }
197.1254 -
197.1255 -    cmsFreeMatShaper(MatShaper);
197.1256 -    return rc;
197.1257 -}
197.1258 -
197.1259 -
197.1260 -
197.1261 -// Creates a PostScript color list from a named profile data.
197.1262 -// This is a HP extension, and it works in Lab instead of XYZ
197.1263 -
197.1264 -static
197.1265 -int WriteNamedColorCSA(LPMEMSTREAM m, cmsHPROFILE hNamedColor, int Intent)
197.1266 -{
197.1267 -    cmsHTRANSFORM xform;
197.1268 -    cmsHPROFILE   hLab;
197.1269 -    int i, nColors;
197.1270 -    char ColorName[32];
197.1271 -
197.1272 -
197.1273 -    hLab  = cmsCreateLabProfile(NULL);
197.1274 -    xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX,
197.1275 -                        hLab, TYPE_Lab_DBL, Intent, cmsFLAGS_NOTPRECALC);
197.1276 -    if (xform == NULL) return 0;
197.1277 -
197.1278 -
197.1279 -    Writef(m, "<<\n");
197.1280 -    Writef(m, "(colorlistcomment) (%s)\n", "Named color CSA");
197.1281 -    Writef(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n");
197.1282 -    Writef(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n");
197.1283 -
197.1284 -    nColors   = cmsNamedColorCount(xform);
197.1285 -
197.1286 -
197.1287 -    for (i=0; i < nColors; i++) {
197.1288 -
197.1289 -        WORD In[1];
197.1290 -        cmsCIELab Lab;
197.1291 -
197.1292 -        In[0] = (WORD) i;
197.1293 -
197.1294 -        if (!cmsNamedColorInfo(xform, i, ColorName, NULL, NULL))
197.1295 -                continue;
197.1296 -
197.1297 -        cmsDoTransform(xform, In, &Lab, 1);
197.1298 -        Writef(m, "  (%s) [ %.3f %.3f %.3f ]\n", ColorName, Lab.L, Lab.a, Lab.b);
197.1299 -    }
197.1300 -
197.1301 -
197.1302 -
197.1303 -    Writef(m, ">>\n");
197.1304 -
197.1305 -    cmsDeleteTransform(xform);
197.1306 -    cmsCloseProfile(hLab);
197.1307 -    return 1;
197.1308 -}
197.1309 -
197.1310 -
197.1311 -// Does create a Color Space Array on XYZ colorspace for PostScript usage
197.1312 -
197.1313 -DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile,
197.1314 -                              int Intent,
197.1315 -                              LPVOID Buffer, DWORD dwBufferLen)
197.1316 -{
197.1317 -
197.1318 -    LPMEMSTREAM mem;
197.1319 -    DWORD dwBytesUsed;
197.1320 -
197.1321 -    // Set up the serialization engine
197.1322 -    mem = CreateMemStream((LPBYTE) Buffer, dwBufferLen, MAXPSCOLS);
197.1323 -    if (!mem) return 0;
197.1324 +    cmsUInt32Number dwBytesUsed;
197.1325 +    cmsPipeline* lut = NULL;
197.1326 +    cmsStage* Matrix, *Shaper;
197.1327  
197.1328  
197.1329      // Is a named color profile?
197.1330 -    if (cmsGetDeviceClass(hProfile) == icSigNamedColorClass) {
197.1331 +    if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) {
197.1332  
197.1333 -        if (!WriteNamedColorCSA(mem, hProfile, Intent)) {
197.1334 -
197.1335 -                    _cmsFree((void*) mem);
197.1336 -                    return 0;
197.1337 -        }
197.1338 +        if (!WriteNamedColorCSA(mem, hProfile, Intent)) goto Error;
197.1339      }
197.1340      else {
197.1341  
197.1342  
197.1343 -    // Any profile class are allowed (including devicelink), but
197.1344 -    // output (PCS) colorspace must be XYZ or Lab
197.1345 -    icColorSpaceSignature ColorSpace = cmsGetPCS(hProfile);
197.1346 +        // Any profile class are allowed (including devicelink), but
197.1347 +        // output (PCS) colorspace must be XYZ or Lab
197.1348 +        cmsColorSpaceSignature ColorSpace = cmsGetPCS(hProfile);
197.1349  
197.1350 -    if (ColorSpace != icSigXYZData &&
197.1351 -        ColorSpace != icSigLabData) {
197.1352 +        if (ColorSpace != cmsSigXYZData &&
197.1353 +            ColorSpace != cmsSigLabData) {
197.1354  
197.1355 -            cmsSignalError(LCMS_ERRC_ABORTED, "Invalid output color space");
197.1356 -            _cmsFree((void*) mem);
197.1357 -            return 0;
197.1358 +            cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Invalid output color space");
197.1359 +            goto Error;
197.1360 +        }
197.1361 +
197.1362 +
197.1363 +        // Read the lut with all necessary conversion stages
197.1364 +        lut = _cmsReadInputLUT(hProfile, Intent);
197.1365 +        if (lut == NULL) goto Error;
197.1366 +
197.1367 +
197.1368 +        // Tone curves + matrix can be implemented without any LUT
197.1369 +        if (cmsPipelineCheckAndRetreiveStages(lut, 2, cmsSigCurveSetElemType, cmsSigMatrixElemType, &Shaper, &Matrix)) {
197.1370 +
197.1371 +            if (!WriteInputMatrixShaper(mem, hProfile, Matrix, Shaper)) goto Error;
197.1372 +
197.1373 +        }
197.1374 +        else {
197.1375 +            // We need a LUT for the rest
197.1376 +            if (!WriteInputLUT(mem, hProfile, Intent, dwFlags)) goto Error;
197.1377 +        }
197.1378      }
197.1379  
197.1380 -    // Is there any CLUT?
197.1381 -    if (IsLUTbased(hProfile, Intent)) {
197.1382 -
197.1383 -        // Yes, so handle as LUT-based
197.1384 -        if (!WriteInputLUT(mem, hProfile, Intent)) {
197.1385 -
197.1386 -                    _cmsFree((void*) mem);
197.1387 -                    return 0;
197.1388 -        }
197.1389 -    }
197.1390 -    else {
197.1391 -
197.1392 -        // No, try Matrix-shaper (this only works on XYZ)
197.1393 -
197.1394 -        if (!WriteInputMatrixShaper(mem, hProfile)) {
197.1395 -
197.1396 -                    _cmsFree((void*) mem);  // Something went wrong
197.1397 -                    return 0;
197.1398 -        }
197.1399 -    }
197.1400 -    }
197.1401 -
197.1402  
197.1403      // Done, keep memory usage
197.1404 -    dwBytesUsed = mem ->dwUsed;
197.1405 +    dwBytesUsed = mem ->UsedSpace;
197.1406  
197.1407 -    // Get rid of memory stream
197.1408 -    _cmsFree((void*) mem);
197.1409 +    // Get rid of LUT
197.1410 +    if (lut != NULL) cmsPipelineFree(lut);
197.1411  
197.1412      // Finally, return used byte count
197.1413      return dwBytesUsed;
197.1414 +
197.1415 +Error:
197.1416 +    if (lut != NULL) cmsPipelineFree(lut);
197.1417 +    return 0;
197.1418  }
197.1419  
197.1420  // ------------------------------------------------------ Color Rendering Dictionary (CRD)
197.1421 @@ -1356,45 +1188,45 @@
197.1422  
197.1423  
197.1424  static
197.1425 -void EmitPQRStage(LPMEMSTREAM m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute)
197.1426 +void EmitPQRStage(cmsIOHANDLER* m, cmsHPROFILE hProfile, int DoBPC, int lIsAbsolute)
197.1427  {
197.1428  
197.1429  
197.1430          if (lIsAbsolute) {
197.1431  
197.1432              // For absolute colorimetric intent, encode back to relative
197.1433 -            // and generate a relative LUT
197.1434 +            // and generate a relative Pipeline
197.1435  
197.1436              // Relative encoding is obtained across XYZpcs*(D50/WhitePoint)
197.1437  
197.1438              cmsCIEXYZ White;
197.1439  
197.1440 -            cmsTakeMediaWhitePoint(&White, hProfile);
197.1441 +            _cmsReadMediaWhitePoint(&White, hProfile);
197.1442  
197.1443 -            Writef(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n");
197.1444 -            Writef(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
197.1445 +            _cmsIOPrintf(m,"/MatrixPQR [1 0 0 0 1 0 0 0 1 ]\n");
197.1446 +            _cmsIOPrintf(m,"/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
197.1447  
197.1448 -            Writef(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n"
197.1449 +            _cmsIOPrintf(m, "%% Absolute colorimetric -- encode to relative to maximize LUT usage\n"
197.1450                        "/TransformPQR [\n"
197.1451                        "{0.9642 mul %g div exch pop exch pop exch pop exch pop} bind\n"
197.1452                        "{1.0000 mul %g div exch pop exch pop exch pop exch pop} bind\n"
197.1453                        "{0.8249 mul %g div exch pop exch pop exch pop exch pop} bind\n]\n",
197.1454 -                      White.X, White.Y, White.Z);
197.1455 +                         White.X, White.Y, White.Z);
197.1456              return;
197.1457          }
197.1458  
197.1459  
197.1460 -        Writef(m,"%% Bradford Cone Space\n"
197.1461 +        _cmsIOPrintf(m,"%% Bradford Cone Space\n"
197.1462                   "/MatrixPQR [0.8951 -0.7502 0.0389 0.2664 1.7135 -0.0685 -0.1614 0.0367 1.0296 ] \n");
197.1463  
197.1464 -        Writef(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
197.1465 +        _cmsIOPrintf(m, "/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ]\n");
197.1466  
197.1467  
197.1468          // No BPC
197.1469  
197.1470          if (!DoBPC) {
197.1471  
197.1472 -            Writef(m, "%% VonKries-like transform in Bradford Cone Space\n"
197.1473 +            _cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space\n"
197.1474                        "/TransformPQR [\n"
197.1475                        "{exch pop exch 3 get mul exch pop exch 3 get div} bind\n"
197.1476                        "{exch pop exch 4 get mul exch pop exch 4 get div} bind\n"
197.1477 @@ -1403,22 +1235,22 @@
197.1478  
197.1479              // BPC
197.1480  
197.1481 -            Writef(m, "%% VonKries-like transform in Bradford Cone Space plus BPC\n"
197.1482 +            _cmsIOPrintf(m, "%% VonKries-like transform in Bradford Cone Space plus BPC\n"
197.1483                        "/TransformPQR [\n");
197.1484  
197.1485 -            Writef(m, "{4 index 3 get div 2 index 3 get mul "
197.1486 +            _cmsIOPrintf(m, "{4 index 3 get div 2 index 3 get mul "
197.1487                      "2 index 3 get 2 index 3 get sub mul "
197.1488                      "2 index 3 get 4 index 3 get 3 index 3 get sub mul sub "
197.1489                      "3 index 3 get 3 index 3 get exch sub div "
197.1490                      "exch pop exch pop exch pop exch pop } bind\n");
197.1491  
197.1492 -            Writef(m, "{4 index 4 get div 2 index 4 get mul "
197.1493 +            _cmsIOPrintf(m, "{4 index 4 get div 2 index 4 get mul "
197.1494                      "2 index 4 get 2 index 4 get sub mul "
197.1495                      "2 index 4 get 4 index 4 get 3 index 4 get sub mul sub "
197.1496                      "3 index 4 get 3 index 4 get exch sub div "
197.1497                      "exch pop exch pop exch pop exch pop } bind\n");
197.1498  
197.1499 -            Writef(m, "{4 index 5 get div 2 index 5 get mul "
197.1500 +            _cmsIOPrintf(m, "{4 index 5 get div 2 index 5 get mul "
197.1501                      "2 index 5 get 2 index 5 get sub mul "
197.1502                      "2 index 5 get 4 index 5 get 3 index 5 get sub mul sub "
197.1503                      "3 index 5 get 3 index 5 get exch sub div "
197.1504 @@ -1431,24 +1263,24 @@
197.1505  
197.1506  
197.1507  static
197.1508 -void EmitXYZ2Lab(LPMEMSTREAM m)
197.1509 +void EmitXYZ2Lab(cmsIOHANDLER* m)
197.1510  {
197.1511 -    Writef(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n");
197.1512 -    Writef(m, "/EncodeLMN [\n");
197.1513 -    Writef(m, "{ 0.964200  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
197.1514 -    Writef(m, "{ 1.000000  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
197.1515 -    Writef(m, "{ 0.824900  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
197.1516 -    Writef(m, "]\n");
197.1517 -    Writef(m, "/MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ]\n");
197.1518 -    Writef(m, "/EncodeABC [\n");
197.1519 +    _cmsIOPrintf(m, "/RangeLMN [ -0.635 2.0 0 2 -0.635 2.0 ]\n");
197.1520 +    _cmsIOPrintf(m, "/EncodeLMN [\n");
197.1521 +    _cmsIOPrintf(m, "{ 0.964200  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
197.1522 +    _cmsIOPrintf(m, "{ 1.000000  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
197.1523 +    _cmsIOPrintf(m, "{ 0.824900  div dup 0.008856 le {7.787 mul 16 116 div add}{1 3 div exp} ifelse } bind\n");
197.1524 +    _cmsIOPrintf(m, "]\n");
197.1525 +    _cmsIOPrintf(m, "/MatrixABC [ 0 1 0 1 -1 1 0 0 -1 ]\n");
197.1526 +    _cmsIOPrintf(m, "/EncodeABC [\n");
197.1527  
197.1528  
197.1529 -    Writef(m, "{ 116 mul  16 sub 100 div  } bind\n");
197.1530 -    Writef(m, "{ 500 mul 128 add 256 div  } bind\n");
197.1531 -    Writef(m, "{ 200 mul 128 add 256 div  } bind\n");
197.1532 +    _cmsIOPrintf(m, "{ 116 mul  16 sub 100 div  } bind\n");
197.1533 +    _cmsIOPrintf(m, "{ 500 mul 128 add 256 div  } bind\n");
197.1534 +    _cmsIOPrintf(m, "{ 200 mul 128 add 256 div  } bind\n");
197.1535  
197.1536  
197.1537 -    Writef(m, "]\n");
197.1538 +    _cmsIOPrintf(m, "]\n");
197.1539  
197.1540  
197.1541  }
197.1542 @@ -1460,104 +1292,74 @@
197.1543  // 8 bits.
197.1544  
197.1545  static
197.1546 -int WriteOutputLUT(LPMEMSTREAM m, cmsHPROFILE hProfile, int Intent, DWORD dwFlags)
197.1547 +int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, int Intent, cmsUInt32Number dwFlags)
197.1548  {
197.1549      cmsHPROFILE hLab;
197.1550      cmsHTRANSFORM xform;
197.1551 -    icColorSpaceSignature ColorSpace;
197.1552      int i, nChannels;
197.1553 -    DWORD OutputFormat;
197.1554 -    _LPcmsTRANSFORM v;
197.1555 -    LPLUT DeviceLink;
197.1556 +    cmsUInt32Number OutputFormat;
197.1557 +    _cmsTRANSFORM* v;
197.1558 +    cmsPipeline* DeviceLink;
197.1559      cmsHPROFILE Profiles[3];
197.1560      cmsCIEXYZ BlackPointAdaptedToD50;
197.1561 -    LCMSBOOL lFreeDeviceLink = FALSE;
197.1562 -    LCMSBOOL lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
197.1563 -    LCMSBOOL lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP);
197.1564 +    cmsBool lDoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
197.1565 +    cmsBool lFixWhite = !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP);
197.1566 +    cmsUInt32Number InFrm = TYPE_Lab_16;
197.1567      int RelativeEncodingIntent;
197.1568 +    cmsColorSpaceSignature ColorSpace;
197.1569  
197.1570  
197.1571 +    hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
197.1572 +    if (hLab == NULL) return 0;
197.1573  
197.1574 -    hLab = cmsCreateLabProfile(NULL);
197.1575 +    OutputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE);
197.1576 +    nChannels    = T_CHANNELS(OutputFormat);
197.1577  
197.1578 -    ColorSpace  =  cmsGetColorSpace(hProfile);
197.1579 -    nChannels   = _cmsChannelsOf(ColorSpace);
197.1580 -    OutputFormat = CHANNELS_SH(nChannels) | BYTES_SH(2);
197.1581 +    ColorSpace = cmsGetColorSpace(hProfile);
197.1582  
197.1583 -    // For absolute colorimetric, the LUT is encoded as relative
197.1584 -    // in order to preserve precission.
197.1585 +    // For absolute colorimetric, the LUT is encoded as relative in order to preserve precision.
197.1586  
197.1587      RelativeEncodingIntent = Intent;
197.1588      if (RelativeEncodingIntent == INTENT_ABSOLUTE_COLORIMETRIC)
197.1589          RelativeEncodingIntent = INTENT_RELATIVE_COLORIMETRIC;
197.1590  
197.1591  
197.1592 -    // Is a devicelink profile?
197.1593 -    if (cmsGetDeviceClass(hProfile) == icSigLinkClass) {
197.1594 +    // Use V4 Lab always
197.1595 +    Profiles[0] = hLab;
197.1596 +    Profiles[1] = hProfile;
197.1597  
197.1598 -        // if devicelink input already in Lab
197.1599 -
197.1600 -        if (ColorSpace == icSigLabData) {
197.1601 -
197.1602 -              // adjust input to Lab to our v4
197.1603 -
197.1604 -            Profiles[0] = hLab;
197.1605 -            Profiles[1] = hProfile;
197.1606 -
197.1607 -            xform = cmsCreateMultiprofileTransform(Profiles, 2, TYPE_Lab_DBL,
197.1608 -                                                        OutputFormat, RelativeEncodingIntent,
197.1609 -                                                        dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
197.1610 -
197.1611 -        }
197.1612 -        else {
197.1613 -          cmsSignalError(LCMS_ERRC_ABORTED, "Cannot use devicelink profile for CRD creation");
197.1614 -          return 0;
197.1615 -        }
197.1616 -
197.1617 -
197.1618 -    }
197.1619 -    else {
197.1620 -
197.1621 -        // This is a normal profile
197.1622 -        xform = cmsCreateTransform(hLab, TYPE_Lab_DBL, hProfile,
197.1623 -                            OutputFormat, RelativeEncodingIntent, dwFlags|cmsFLAGS_NOWHITEONWHITEFIXUP|cmsFLAGS_NOPRELINEARIZATION);
197.1624 -    }
197.1625 +    xform = cmsCreateMultiprofileTransformTHR(m ->ContextID,
197.1626 +                                              Profiles, 2, TYPE_Lab_DBL,
197.1627 +                                              OutputFormat, RelativeEncodingIntent, 0);
197.1628 +    cmsCloseProfile(hLab);
197.1629  
197.1630      if (xform == NULL) {
197.1631  
197.1632 -            cmsSignalError(LCMS_ERRC_ABORTED, "Cannot create transform Lab -> Profile in CRD creation");
197.1633 -            return 0;
197.1634 +        cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation");
197.1635 +        return 0;
197.1636      }
197.1637  
197.1638 -    // Get the internal precalculated devicelink
197.1639 +    // Get a copy of the internal devicelink
197.1640 +    v = (_cmsTRANSFORM*) xform;
197.1641 +    DeviceLink = cmsPipelineDup(v ->Lut);
197.1642 +    if (DeviceLink == NULL) return 0;
197.1643  
197.1644 -    v = (_LPcmsTRANSFORM) xform;
197.1645 -    DeviceLink = v ->DeviceLink;
197.1646  
197.1647 -    if (!DeviceLink) {
197.1648 +    // We need a CLUT
197.1649 +    dwFlags |= cmsFLAGS_FORCE_CLUT;
197.1650 +    _cmsOptimizePipeline(&DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
197.1651  
197.1652 -        DeviceLink = _cmsPrecalculateDeviceLink(xform, cmsFLAGS_NOPRELINEARIZATION);
197.1653 -        lFreeDeviceLink = TRUE;
197.1654 -    }
197.1655 +    _cmsIOPrintf(m, "<<\n");
197.1656 +    _cmsIOPrintf(m, "/ColorRenderingType 1\n");
197.1657  
197.1658 -    Writef(m, "<<\n");
197.1659 -    Writef(m, "/ColorRenderingType 1\n");
197.1660  
197.1661 -
197.1662 -    cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, LCMS_BPFLAGS_D50_ADAPTED);
197.1663 +    cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0);
197.1664  
197.1665      // Emit headers, etc.
197.1666      EmitWhiteBlackD50(m, &BlackPointAdaptedToD50);
197.1667      EmitPQRStage(m, hProfile, lDoBPC, Intent == INTENT_ABSOLUTE_COLORIMETRIC);
197.1668      EmitXYZ2Lab(m);
197.1669  
197.1670 -    if (DeviceLink ->wFlags & LUT_HASTL1) {
197.1671 -
197.1672 -        // Shouldn't happen
197.1673 -        cmsSignalError(LCMS_ERRC_ABORTED, "Internal error (prelinearization on CRD)");
197.1674 -        return 0;
197.1675 -    }
197.1676 -
197.1677  
197.1678      // FIXUP: map Lab (100, 0, 0) to perfect white, because the particular encoding for Lab
197.1679      // does map a=b=0 not falling into any specific node. Since range a,b goes -128..127,
197.1680 @@ -1568,31 +1370,30 @@
197.1681      if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
197.1682              lFixWhite = FALSE;
197.1683  
197.1684 -    Writef(m, "/RenderTable ");
197.1685 +    _cmsIOPrintf(m, "/RenderTable ");
197.1686  
197.1687 -    WriteCLUT(m, DeviceLink, 8, "<", ">\n", "", "", FALSE,
197.1688 -                lFixWhite, ColorSpace);
197.1689  
197.1690 -    Writef(m, " %d {} bind ", nChannels);
197.1691 +    WriteCLUT(m, cmsPipelineGetPtrToFirstStage(DeviceLink), "<", ">\n", "", "", lFixWhite, ColorSpace);
197.1692 +
197.1693 +    _cmsIOPrintf(m, " %d {} bind ", nChannels);
197.1694  
197.1695      for (i=1; i < nChannels; i++)
197.1696 -            Writef(m, "dup ");
197.1697 +            _cmsIOPrintf(m, "dup ");
197.1698  
197.1699 -    Writef(m, "]\n");
197.1700 +    _cmsIOPrintf(m, "]\n");
197.1701  
197.1702  
197.1703      EmitIntent(m, Intent);
197.1704  
197.1705 -    Writef(m, ">>\n");
197.1706 +    _cmsIOPrintf(m, ">>\n");
197.1707  
197.1708      if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) {
197.1709  
197.1710 -        Writef(m, "/Current exch /ColorRendering defineresource pop\n");
197.1711 +        _cmsIOPrintf(m, "/Current exch /ColorRendering defineresource pop\n");
197.1712      }
197.1713  
197.1714 -    if (lFreeDeviceLink) cmsFreeLUT(DeviceLink);
197.1715 +    cmsPipelineFree(DeviceLink);
197.1716      cmsDeleteTransform(xform);
197.1717 -    cmsCloseProfile(hLab);
197.1718  
197.1719      return 1;
197.1720  }
197.1721 @@ -1600,14 +1401,14 @@
197.1722  
197.1723  // Builds a ASCII string containing colorant list in 0..1.0 range
197.1724  static
197.1725 -void BuildColorantList(char *Colorant, int nColorant, WORD Out[])
197.1726 +void BuildColorantList(char *Colorant, int nColorant, cmsUInt16Number Out[])
197.1727  {
197.1728      char Buff[32];
197.1729      int j;
197.1730  
197.1731      Colorant[0] = 0;
197.1732 -    if (nColorant > MAXCHANNELS)
197.1733 -        nColorant = MAXCHANNELS;
197.1734 +    if (nColorant > cmsMAXCHANNELS)
197.1735 +        nColorant = cmsMAXCHANNELS;
197.1736  
197.1737      for (j=0; j < nColorant; j++) {
197.1738  
197.1739 @@ -1624,50 +1425,54 @@
197.1740  // This is a HP extension.
197.1741  
197.1742  static
197.1743 -int WriteNamedColorCRD(LPMEMSTREAM m, cmsHPROFILE hNamedColor, int Intent, DWORD dwFlags)
197.1744 +int WriteNamedColorCRD(cmsIOHANDLER* m, cmsHPROFILE hNamedColor, int Intent, cmsUInt32Number dwFlags)
197.1745  {
197.1746      cmsHTRANSFORM xform;
197.1747      int i, nColors, nColorant;
197.1748 -    DWORD OutputFormat;
197.1749 +    cmsUInt32Number OutputFormat;
197.1750      char ColorName[32];
197.1751      char Colorant[128];
197.1752 +    cmsNAMEDCOLORLIST* NamedColorList;
197.1753  
197.1754 -    nColorant = _cmsChannelsOf(cmsGetColorSpace(hNamedColor));
197.1755 -    OutputFormat = CHANNELS_SH(nColorant) | BYTES_SH(2);
197.1756  
197.1757 -    xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX,
197.1758 -                        NULL, OutputFormat, Intent, cmsFLAGS_NOTPRECALC);
197.1759 +    OutputFormat = cmsFormatterForColorspaceOfProfile(hNamedColor, 2, FALSE);
197.1760 +    nColorant    = T_CHANNELS(OutputFormat);
197.1761 +
197.1762 +
197.1763 +    xform = cmsCreateTransform(hNamedColor, TYPE_NAMED_COLOR_INDEX, NULL, OutputFormat, Intent, dwFlags);
197.1764      if (xform == NULL) return 0;
197.1765  
197.1766  
197.1767 -    Writef(m, "<<\n");
197.1768 -    Writef(m, "(colorlistcomment) (%s) \n", "Named profile");
197.1769 -    Writef(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n");
197.1770 -    Writef(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n");
197.1771 +    NamedColorList = cmsGetNamedColorList(xform);
197.1772 +    if (NamedColorList == NULL) return 0;
197.1773  
197.1774 -    nColors   = cmsNamedColorCount(xform);
197.1775 +    _cmsIOPrintf(m, "<<\n");
197.1776 +    _cmsIOPrintf(m, "(colorlistcomment) (%s) \n", "Named profile");
197.1777 +    _cmsIOPrintf(m, "(Prefix) [ (Pantone ) (PANTONE ) ]\n");
197.1778 +    _cmsIOPrintf(m, "(Suffix) [ ( CV) ( CVC) ( C) ]\n");
197.1779  
197.1780 +    nColors   = cmsNamedColorCount(NamedColorList);
197.1781  
197.1782      for (i=0; i < nColors; i++) {
197.1783  
197.1784 -        WORD In[1];
197.1785 -        WORD Out[MAXCHANNELS];
197.1786 +        cmsUInt16Number In[1];
197.1787 +        cmsUInt16Number Out[cmsMAXCHANNELS];
197.1788  
197.1789 -        In[0] = (WORD) i;
197.1790 +        In[0] = (cmsUInt16Number) i;
197.1791  
197.1792 -        if (!cmsNamedColorInfo(xform, i, ColorName, NULL, NULL))
197.1793 +        if (!cmsNamedColorInfo(NamedColorList, i, ColorName, NULL, NULL, NULL, NULL))
197.1794                  continue;
197.1795  
197.1796          cmsDoTransform(xform, In, Out, 1);
197.1797          BuildColorantList(Colorant, nColorant, Out);
197.1798 -        Writef(m, "  (%s) [ %s ]\n", ColorName, Colorant);
197.1799 +        _cmsIOPrintf(m, "  (%s) [ %s ]\n", ColorName, Colorant);
197.1800      }
197.1801  
197.1802 -    Writef(m, "   >>");
197.1803 +    _cmsIOPrintf(m, "   >>");
197.1804  
197.1805      if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) {
197.1806  
197.1807 -    Writef(m, " /Current exch /HPSpotTable defineresource pop\n");
197.1808 +    _cmsIOPrintf(m, " /Current exch /HPSpotTable defineresource pop\n");
197.1809      }
197.1810  
197.1811      cmsDeleteTransform(xform);
197.1812 @@ -1680,67 +1485,129 @@
197.1813  // CRD are always LUT-Based, no matter if profile is
197.1814  // implemented as matrix-shaper.
197.1815  
197.1816 -DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile,
197.1817 -                              int Intent, DWORD dwFlags,
197.1818 -                              LPVOID Buffer, DWORD dwBufferLen)
197.1819 +static
197.1820 +cmsUInt32Number  GenerateCRD(cmsContext ContextID,
197.1821 +                             cmsHPROFILE hProfile,
197.1822 +                             cmsUInt32Number Intent, cmsUInt32Number dwFlags,
197.1823 +                             cmsIOHANDLER* mem)
197.1824  {
197.1825 -
197.1826 -    LPMEMSTREAM mem;
197.1827 -    DWORD dwBytesUsed;
197.1828 -
197.1829 -    // Set up the serialization artifact
197.1830 -    mem = CreateMemStream((LPBYTE) Buffer, dwBufferLen, MAXPSCOLS);
197.1831 -    if (!mem) return 0;
197.1832 -
197.1833 +    cmsUInt32Number dwBytesUsed;
197.1834  
197.1835      if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) {
197.1836  
197.1837 -    EmitHeader(mem, "Color Rendering Dictionary (CRD)", hProfile);
197.1838 +        EmitHeader(mem, "Color Rendering Dictionary (CRD)", hProfile);
197.1839      }
197.1840  
197.1841  
197.1842      // Is a named color profile?
197.1843 -    if (cmsGetDeviceClass(hProfile) == icSigNamedColorClass) {
197.1844 +    if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) {
197.1845  
197.1846          if (!WriteNamedColorCRD(mem, hProfile, Intent, dwFlags)) {
197.1847 -
197.1848 -                    _cmsFree((void*) mem);
197.1849 -                    return 0;
197.1850 +            return 0;
197.1851          }
197.1852      }
197.1853      else {
197.1854  
197.1855 -    // CRD are always implemented as LUT.
197.1856 +        // CRD are always implemented as LUT
197.1857  
197.1858 -
197.1859 -    if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) {
197.1860 -        _cmsFree((void*) mem);
197.1861 -        return 0;
197.1862 -    }
197.1863 +        if (!WriteOutputLUT(mem, hProfile, Intent, dwFlags)) {
197.1864 +            return 0;
197.1865 +        }
197.1866      }
197.1867  
197.1868      if (!(dwFlags & cmsFLAGS_NODEFAULTRESOURCEDEF)) {
197.1869  
197.1870 -    Writef(mem, "%%%%EndResource\n");
197.1871 -    Writef(mem, "\n%% CRD End\n");
197.1872 +        _cmsIOPrintf(mem, "%%%%EndResource\n");
197.1873 +        _cmsIOPrintf(mem, "\n%% CRD End\n");
197.1874      }
197.1875  
197.1876      // Done, keep memory usage
197.1877 -    dwBytesUsed = mem ->dwUsed;
197.1878 -
197.1879 -    // Get rid of memory stream
197.1880 -    _cmsFree((void*) mem);
197.1881 +    dwBytesUsed = mem ->UsedSpace;
197.1882  
197.1883      // Finally, return used byte count
197.1884      return dwBytesUsed;
197.1885 +
197.1886 +    cmsUNUSED_PARAMETER(ContextID);
197.1887  }
197.1888  
197.1889  
197.1890 -// For compatibility with previous versions
197.1891  
197.1892 -DWORD LCMSEXPORT cmsGetPostScriptCRD(cmsHPROFILE hProfile,
197.1893 -                              int Intent,
197.1894 -                              LPVOID Buffer, DWORD dwBufferLen)
197.1895 +
197.1896 +cmsUInt32Number CMSEXPORT cmsGetPostScriptColorResource(cmsContext ContextID,
197.1897 +                                                        cmsPSResourceType Type,
197.1898 +                                                        cmsHPROFILE hProfile,
197.1899 +                                                        cmsUInt32Number Intent,
197.1900 +                                                        cmsUInt32Number dwFlags,
197.1901 +                                                        cmsIOHANDLER* io)
197.1902  {
197.1903 -    return cmsGetPostScriptCRDEx(hProfile, Intent, 0, Buffer, dwBufferLen);
197.1904 +    cmsUInt32Number  rc;
197.1905 +
197.1906 +
197.1907 +    switch (Type) {
197.1908 +
197.1909 +      case cmsPS_RESOURCE_CSA:
197.1910 +          rc = GenerateCSA(ContextID, hProfile, Intent, dwFlags, io);
197.1911 +          break;
197.1912 +      default:
197.1913 +      case cmsPS_RESOURCE_CRD:
197.1914 +          rc = GenerateCRD(ContextID, hProfile, Intent, dwFlags, io);
197.1915 +          break;
197.1916 +    }
197.1917 +
197.1918 +    return rc;
197.1919  }
197.1920 +
197.1921 +
197.1922 +
197.1923 +cmsUInt32Number CMSEXPORT cmsGetPostScriptCRD(cmsContext ContextID,
197.1924 +                                              cmsHPROFILE hProfile,
197.1925 +                              cmsUInt32Number Intent, cmsUInt32Number dwFlags,
197.1926 +                              void* Buffer, cmsUInt32Number dwBufferLen)
197.1927 +{
197.1928 +    cmsIOHANDLER* mem;
197.1929 +    cmsUInt32Number dwBytesUsed;
197.1930 +
197.1931 +    // Set up the serialization engine
197.1932 +    if (Buffer == NULL)
197.1933 +        mem = cmsOpenIOhandlerFromNULL(ContextID);
197.1934 +    else
197.1935 +        mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w");
197.1936 +
197.1937 +    if (!mem) return 0;
197.1938 +
197.1939 +    dwBytesUsed =  cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CRD, hProfile, Intent, dwFlags, mem);
197.1940 +
197.1941 +    // Get rid of memory stream
197.1942 +    cmsCloseIOhandler(mem);
197.1943 +
197.1944 +    return dwBytesUsed;
197.1945 +}
197.1946 +
197.1947 +
197.1948 +
197.1949 +// Does create a Color Space Array on XYZ colorspace for PostScript usage
197.1950 +cmsUInt32Number CMSEXPORT cmsGetPostScriptCSA(cmsContext ContextID,
197.1951 +                                              cmsHPROFILE hProfile,
197.1952 +                                              cmsUInt32Number Intent,
197.1953 +                                              cmsUInt32Number dwFlags,
197.1954 +                                              void* Buffer,
197.1955 +                                              cmsUInt32Number dwBufferLen)
197.1956 +{
197.1957 +    cmsIOHANDLER* mem;
197.1958 +    cmsUInt32Number dwBytesUsed;
197.1959 +
197.1960 +    if (Buffer == NULL)
197.1961 +        mem = cmsOpenIOhandlerFromNULL(ContextID);
197.1962 +    else
197.1963 +        mem = cmsOpenIOhandlerFromMem(ContextID, Buffer, dwBufferLen, "w");
197.1964 +
197.1965 +    if (!mem) return 0;
197.1966 +
197.1967 +    dwBytesUsed =  cmsGetPostScriptColorResource(ContextID, cmsPS_RESOURCE_CSA, hProfile, Intent, dwFlags, mem);
197.1968 +
197.1969 +    // Get rid of memory stream
197.1970 +    cmsCloseIOhandler(mem);
197.1971 +
197.1972 +    return dwBytesUsed;
197.1973 +
197.1974 +}
   198.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmssamp.c	Thu Sep 23 17:33:40 2010 -0700
   198.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmssamp.c	Fri Sep 24 16:41:32 2010 -0700
   198.3 @@ -27,9 +27,10 @@
   198.4  // However, the following notice accompanied the original version of this
   198.5  // file:
   198.6  //
   198.7 +//---------------------------------------------------------------------------------
   198.8  //
   198.9 -//  Little cms
  198.10 -//  Copyright (C) 1998-2007 Marti Maria
  198.11 +//  Little Color Management System
  198.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  198.13  //
  198.14  // Permission is hereby granted, free of charge, to any person obtaining
  198.15  // a copy of this software and associated documentation files (the "Software"),
  198.16 @@ -48,650 +49,246 @@
  198.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  198.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  198.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  198.20 +//
  198.21 +//---------------------------------------------------------------------------------
  198.22 +//
  198.23  
  198.24 +#include "lcms2_internal.h"
  198.25  
  198.26 -#include "lcms.h"
  198.27  
  198.28  
  198.29 -// ---------------------------------------------------------------------------------
  198.30 +// This file contains routines for resampling and LUT optimization, black point detection
  198.31 +// and black preservation.
  198.32  
  198.33 -static volatile int GlobalBlackPreservationStrategy = 0;
  198.34 +// Black point detection -------------------------------------------------------------------------
  198.35  
  198.36 -// Quantize a value 0 <= i < MaxSamples
  198.37  
  198.38 -WORD _cmsQuantizeVal(double i, int MaxSamples)
  198.39 +// PCS -> PCS round trip transform, always uses relative intent on the device -> pcs
  198.40 +static
  198.41 +cmsHTRANSFORM CreateRoundtripXForm(cmsHPROFILE hProfile, cmsUInt32Number nIntent)
  198.42  {
  198.43 -       double x;
  198.44 +    cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
  198.45 +    cmsHTRANSFORM xform;
  198.46 +    cmsBool BPC[4] = { FALSE, FALSE, FALSE, FALSE };
  198.47 +    cmsFloat64Number States[4] = { 1.0, 1.0, 1.0, 1.0 };
  198.48 +    cmsHPROFILE hProfiles[4];
  198.49 +    cmsUInt32Number Intents[4];
  198.50 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
  198.51  
  198.52 -       x = ((double) i * 65535.) / (double) (MaxSamples - 1);
  198.53 +    hProfiles[0] = hLab; hProfiles[1] = hProfile; hProfiles[2] = hProfile; hProfiles[3] = hLab;
  198.54 +    Intents[0]   = INTENT_RELATIVE_COLORIMETRIC; Intents[1] = nIntent; Intents[2] = INTENT_RELATIVE_COLORIMETRIC; Intents[3] = INTENT_RELATIVE_COLORIMETRIC;
  198.55  
  198.56 -       return (WORD) floor(x + .5);
  198.57 +    xform =  cmsCreateExtendedTransform(ContextID, 4, hProfiles, BPC, Intents,
  198.58 +        States, NULL, 0, TYPE_Lab_DBL, TYPE_Lab_DBL, cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
  198.59 +
  198.60 +    cmsCloseProfile(hLab);
  198.61 +    return xform;
  198.62  }
  198.63  
  198.64 +// Use darker colorants to obtain black point. This works in the relative colorimetric intent and
  198.65 +// assumes more ink results in darker colors. No ink limit is assumed.
  198.66 +static
  198.67 +cmsBool  BlackPointAsDarkerColorant(cmsHPROFILE    hInput,
  198.68 +                                    cmsUInt32Number Intent,
  198.69 +                                    cmsCIEXYZ* BlackPoint,
  198.70 +                                    cmsUInt32Number dwFlags)
  198.71 +{
  198.72 +    cmsUInt16Number *Black;
  198.73 +    cmsHTRANSFORM xform;
  198.74 +    cmsColorSpaceSignature Space;
  198.75 +    cmsUInt32Number nChannels;
  198.76 +    cmsUInt32Number dwFormat;
  198.77 +    cmsHPROFILE hLab;
  198.78 +    cmsCIELab  Lab;
  198.79 +    cmsCIEXYZ  BlackXYZ;
  198.80 +    cmsContext ContextID = cmsGetProfileContextID(hInput);
  198.81  
  198.82 -// Is a table linear?
  198.83 +    // If the profile does not support input direction, assume Black point 0
  198.84 +    if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) {
  198.85  
  198.86 -int cmsIsLinear(WORD Table[], int nEntries)
  198.87 -{
  198.88 -       register int i;
  198.89 -       int diff;
  198.90 +        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
  198.91 +        return FALSE;
  198.92 +    }
  198.93  
  198.94 -       for (i=0; i < nEntries; i++) {
  198.95 +    // Create a formatter which has n channels and floating point
  198.96 +    dwFormat = cmsFormatterForColorspaceOfProfile(hInput, 2, FALSE);
  198.97  
  198.98 -           diff = abs((int) Table[i] - (int) _cmsQuantizeVal(i, nEntries));
  198.99 -           if (diff > 3)
 198.100 -                     return 0;
 198.101 -       }
 198.102 +   // Try to get black by using black colorant
 198.103 +    Space = cmsGetColorSpace(hInput);
 198.104  
 198.105 -       return 1;
 198.106 +    // This function returns darker colorant in 16 bits for several spaces
 198.107 +    if (!_cmsEndPointsBySpace(Space, NULL, &Black, &nChannels)) {
 198.108 +
 198.109 +        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 198.110 +        return FALSE;
 198.111 +    }
 198.112 +
 198.113 +    if (nChannels != T_CHANNELS(dwFormat)) {
 198.114 +       BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 198.115 +       return FALSE;
 198.116 +    }
 198.117 +
 198.118 +    // Lab will be used as the output space, but lab2 will avoid recursion
 198.119 +    hLab = cmsCreateLab2ProfileTHR(ContextID, NULL);
 198.120 +    if (hLab == NULL) {
 198.121 +       BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 198.122 +       return FALSE;
 198.123 +    }
 198.124 +
 198.125 +    // Create the transform
 198.126 +    xform = cmsCreateTransformTHR(ContextID, hInput, dwFormat,
 198.127 +                                hLab, TYPE_Lab_DBL, Intent, cmsFLAGS_NOOPTIMIZE|cmsFLAGS_NOCACHE);
 198.128 +    cmsCloseProfile(hLab);
 198.129 +
 198.130 +    if (xform == NULL) {
 198.131 +        // Something went wrong. Get rid of open resources and return zero as black
 198.132 +
 198.133 +        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 198.134 +        return FALSE;
 198.135 +    }
 198.136 +
 198.137 +    // Convert black to Lab
 198.138 +    cmsDoTransform(xform, Black, &Lab, 1);
 198.139 +
 198.140 +    // Force it to be neutral, clip to max. L* of 50
 198.141 +    Lab.a = Lab.b = 0;
 198.142 +    if (Lab.L > 50) Lab.L = 50;
 198.143 +
 198.144 +    // Free the resources
 198.145 +    cmsDeleteTransform(xform);
 198.146 +
 198.147 +    // Convert from Lab (which is now clipped) to XYZ.
 198.148 +    cmsLab2XYZ(NULL, &BlackXYZ, &Lab);
 198.149 +
 198.150 +    if (BlackPoint != NULL)
 198.151 +        *BlackPoint = BlackXYZ;
 198.152 +
 198.153 +    return TRUE;
 198.154 +
 198.155 +    cmsUNUSED_PARAMETER(dwFlags);
 198.156  }
 198.157  
 198.158 +// Get a black point of output CMYK profile, discounting any ink-limiting embedded
 198.159 +// in the profile. For doing that, we use perceptual intent in input direction:
 198.160 +// Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab
 198.161 +static
 198.162 +cmsBool BlackPointUsingPerceptualBlack(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile)
 198.163  
 198.164 +{
 198.165 +    cmsHTRANSFORM hRoundTrip;
 198.166 +    cmsCIELab LabIn, LabOut;
 198.167 +    cmsCIEXYZ  BlackXYZ;
 198.168  
 198.169 -// pow() restricted to integer
 198.170 +     // Is the intent supported by the profile?
 198.171 +    if (!cmsIsIntentSupported(hProfile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT)) {
 198.172  
 198.173 -static
 198.174 -int ipow(int base, int exp)
 198.175 -{
 198.176 -        int res = base;
 198.177 +        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 198.178 +        return TRUE;
 198.179 +    }
 198.180  
 198.181 -        while (--exp)
 198.182 -               res *= base;
 198.183 +    hRoundTrip = CreateRoundtripXForm(hProfile, INTENT_PERCEPTUAL);
 198.184 +    if (hRoundTrip == NULL) {
 198.185 +        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 198.186 +        return FALSE;
 198.187 +    }
 198.188  
 198.189 -        return res;
 198.190 -}
 198.191 +    LabIn.L = LabIn.a = LabIn.b = 0;
 198.192 +    cmsDoTransform(hRoundTrip, &LabIn, &LabOut, 1);
 198.193  
 198.194 +    // Clip Lab to reasonable limits
 198.195 +    if (LabOut.L > 50) LabOut.L = 50;
 198.196 +    LabOut.a = LabOut.b = 0;
 198.197  
 198.198 -// Given n, 0<=n<=clut^dim, returns the colorant.
 198.199 +    cmsDeleteTransform(hRoundTrip);
 198.200  
 198.201 -static
 198.202 -int ComponentOf(int n, int clut, int nColorant)
 198.203 -{
 198.204 -        if (nColorant <= 0)
 198.205 -                return (n % clut);
 198.206 +    // Convert it to XYZ
 198.207 +    cmsLab2XYZ(NULL, &BlackXYZ, &LabOut);
 198.208  
 198.209 -        n /= ipow(clut, nColorant);
 198.210 -
 198.211 -        return (n % clut);
 198.212 -}
 198.213 -
 198.214 -
 198.215 -
 198.216 -// This routine does a sweep on whole input space, and calls its callback
 198.217 -// function on knots. returns TRUE if all ok, FALSE otherwise.
 198.218 -
 198.219 -LCMSBOOL LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags)
 198.220 -{
 198.221 -   int i, t, nTotalPoints, Colorant, index;
 198.222 -   WORD In[MAXCHANNELS], Out[MAXCHANNELS];
 198.223 -
 198.224 -   nTotalPoints = ipow(Lut->cLutPoints, Lut -> InputChan);
 198.225 -
 198.226 -   index = 0;
 198.227 -   for (i = 0; i < nTotalPoints; i++) {
 198.228 -
 198.229 -        for (t=0; t < (int) Lut -> InputChan; t++) {
 198.230 -
 198.231 -                Colorant =  ComponentOf(i, Lut -> cLutPoints, (Lut -> InputChan - t  - 1 ));
 198.232 -                In[t]    = _cmsQuantizeVal(Colorant, Lut -> cLutPoints);
 198.233 -        }
 198.234 -
 198.235 -
 198.236 -        if (dwFlags & SAMPLER_HASTL1) {
 198.237 -
 198.238 -                 for (t=0; t < (int) Lut -> InputChan; t++)
 198.239 -                     In[t] = cmsReverseLinearInterpLUT16(In[t],
 198.240 -                                                Lut -> L1[t],
 198.241 -                                                &Lut -> In16params);
 198.242 -        }
 198.243 -
 198.244 -        for (t=0; t < (int) Lut -> OutputChan; t++)
 198.245 -                     Out[t] = Lut->T[index + t];
 198.246 -
 198.247 -        if (dwFlags & SAMPLER_HASTL2) {
 198.248 -
 198.249 -             for (t=0; t < (int) Lut -> OutputChan; t++)
 198.250 -                     Out[t] = cmsLinearInterpLUT16(Out[t],
 198.251 -                                                   Lut -> L2[t],
 198.252 -                                                   &Lut -> Out16params);
 198.253 -        }
 198.254 -
 198.255 -
 198.256 -        if (!Sampler(In, Out, Cargo))
 198.257 -                return FALSE;
 198.258 -
 198.259 -        if (!(dwFlags & SAMPLER_INSPECT)) {
 198.260 -
 198.261 -            if (dwFlags & SAMPLER_HASTL2) {
 198.262 -
 198.263 -                for (t=0; t < (int) Lut -> OutputChan; t++)
 198.264 -                     Out[t] = cmsReverseLinearInterpLUT16(Out[t],
 198.265 -                                                   Lut -> L2[t],
 198.266 -                                                   &Lut -> Out16params);
 198.267 -                }
 198.268 -
 198.269 -
 198.270 -            for (t=0; t < (int) Lut -> OutputChan; t++)
 198.271 -                        Lut->T[index + t] = Out[t];
 198.272 -
 198.273 -        }
 198.274 -
 198.275 -        index += Lut -> OutputChan;
 198.276 -
 198.277 -    }
 198.278 +    if (BlackPoint != NULL)
 198.279 +        *BlackPoint = BlackXYZ;
 198.280  
 198.281      return TRUE;
 198.282  }
 198.283  
 198.284 +// This function shouldn't exist at all -- there is such quantity of broken
 198.285 +// profiles on black point tag, that we must somehow fix chromaticity to
 198.286 +// avoid huge tint when doing Black point compensation. This function does
 198.287 +// just that. There is a special flag for using black point tag, but turned
 198.288 +// off by default because it is bogus on most profiles. The detection algorithm
 198.289 +// involves to turn BP to neutral and to use only L component.
 198.290  
 198.291 +cmsBool CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 198.292 +{
 198.293  
 198.294 +    // Zero for black point
 198.295 +    if (cmsGetDeviceClass(hProfile) == cmsSigLinkClass) {
 198.296  
 198.297 -
 198.298 -
 198.299 -// choose reasonable resolution
 198.300 -int _cmsReasonableGridpointsByColorspace(icColorSpaceSignature Colorspace, DWORD dwFlags)
 198.301 -{
 198.302 -    int nChannels;
 198.303 -
 198.304 -    // Already specified?
 198.305 -    if (dwFlags & 0x00FF0000) {
 198.306 -            // Yes, grab'em
 198.307 -            return (dwFlags >> 16) & 0xFF;
 198.308 +        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 198.309 +        return FALSE;
 198.310      }
 198.311  
 198.312 -    nChannels = _cmsChannelsOf(Colorspace);
 198.313 +    // v4 + perceptual & saturation intents does have its own black point, and it is
 198.314 +    // well specified enough to use it. Black point tag is deprecated in V4.
 198.315  
 198.316 -    // HighResPrecalc is maximum resolution
 198.317 +    if ((cmsGetEncodedICCversion(hProfile) >= 0x4000000) &&
 198.318 +        (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
 198.319  
 198.320 -    if (dwFlags & cmsFLAGS_HIGHRESPRECALC) {
 198.321 +            // Matrix shaper share MRC & perceptual intents
 198.322 +            if (cmsIsMatrixShaper(hProfile))
 198.323 +                return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, 0);
 198.324  
 198.325 -        if (nChannels > 4)
 198.326 -                return 7;       // 7 for Hifi
 198.327 +            // Get Perceptual black out of v4 profiles. That is fixed for perceptual & saturation intents
 198.328 +            BlackPoint -> X = cmsPERCEPTUAL_BLACK_X;
 198.329 +            BlackPoint -> Y = cmsPERCEPTUAL_BLACK_Y;
 198.330 +            BlackPoint -> Z = cmsPERCEPTUAL_BLACK_Z;
 198.331  
 198.332 -        if (nChannels == 4)     // 23 for CMYK
 198.333 -                return 23;
 198.334 -
 198.335 -        return 49;      // 49 for RGB and others
 198.336 +            return TRUE;
 198.337      }
 198.338  
 198.339  
 198.340 -    // LowResPrecal is stripped resolution
 198.341 +#ifdef CMS_USE_PROFILE_BLACK_POINT_TAG
 198.342  
 198.343 -    if (dwFlags & cmsFLAGS_LOWRESPRECALC) {
 198.344 +    // v2, v4 rel/abs colorimetric
 198.345 +    if (cmsIsTag(hProfile, cmsSigMediaBlackPointTag) &&
 198.346 +        Intent == INTENT_RELATIVE_COLORIMETRIC) {
 198.347  
 198.348 -        if (nChannels > 4)
 198.349 -                return 6;       // 6 for Hifi
 198.350 +            cmsCIEXYZ *BlackPtr, BlackXYZ, UntrustedBlackPoint, TrustedBlackPoint, MediaWhite;
 198.351 +            cmsCIELab Lab;
 198.352  
 198.353 -        if (nChannels == 1)
 198.354 -                return 33;      // For monochrome
 198.355 +            // If black point is specified, then use it,
 198.356  
 198.357 -        return 17;              // 17 for remaining
 198.358 +            BlackPtr = cmsReadTag(hProfile, cmsSigMediaBlackPointTag);
 198.359 +            if (BlackPtr != NULL) {
 198.360 +
 198.361 +                BlackXYZ = *BlackPtr;
 198.362 +                _cmsReadMediaWhitePoint(&MediaWhite, hProfile);
 198.363 +
 198.364 +                // Black point is absolute XYZ, so adapt to D50 to get PCS value
 198.365 +                cmsAdaptToIlluminant(&UntrustedBlackPoint, &MediaWhite, cmsD50_XYZ(), &BlackXYZ);
 198.366 +
 198.367 +                // Force a=b=0 to get rid of any chroma
 198.368 +                cmsXYZ2Lab(NULL, &Lab, &UntrustedBlackPoint);
 198.369 +                Lab.a = Lab.b = 0;
 198.370 +                if (Lab.L > 50) Lab.L = 50; // Clip to L* <= 50
 198.371 +                cmsLab2XYZ(NULL, &TrustedBlackPoint, &Lab);
 198.372 +
 198.373 +                if (BlackPoint != NULL)
 198.374 +                    *BlackPoint = TrustedBlackPoint;
 198.375 +
 198.376 +                return TRUE;
 198.377 +            }
 198.378      }
 198.379 +#endif
 198.380  
 198.381 -    // Default values
 198.382 +    // That is about v2 profiles.
 198.383  
 198.384 -    if (nChannels > 4)
 198.385 -                return 7;       // 7 for Hifi
 198.386 +    // If output profile, discount ink-limiting and that's all
 198.387 +    if (Intent == INTENT_RELATIVE_COLORIMETRIC &&
 198.388 +        (cmsGetDeviceClass(hProfile) == cmsSigOutputClass) &&
 198.389 +        (cmsGetColorSpace(hProfile)  == cmsSigCmykData))
 198.390 +        return BlackPointUsingPerceptualBlack(BlackPoint, hProfile);
 198.391  
 198.392 -    if (nChannels == 4)
 198.393 -                return 17;      // 17 for CMYK
 198.394 -
 198.395 -    return 33;                  // 33 for RGB
 198.396 -
 198.397 +    // Nope, compute BP using current intent.
 198.398 +    return BlackPointAsDarkerColorant(hProfile, Intent, BlackPoint, dwFlags);
 198.399  }
 198.400  
 198.401 -// Sampler implemented by another transform. This is a clean way to
 198.402 -// precalculate the devicelink 3D CLUT for almost any transform
 198.403 -
 198.404 -static
 198.405 -int XFormSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
 198.406 -{
 198.407 -        cmsDoTransform((cmsHTRANSFORM) Cargo, In, Out, 1);
 198.408 -        return TRUE;
 198.409 -}
 198.410 -
 198.411 -// This routine does compute the devicelink CLUT containing whole
 198.412 -// transform. Handles any channel number.
 198.413 -
 198.414 -LPLUT _cmsPrecalculateDeviceLink(cmsHTRANSFORM h, DWORD dwFlags)
 198.415 -{
 198.416 -       _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) h;
 198.417 -       LPLUT Grid;
 198.418 -       int nGridPoints;
 198.419 -       DWORD dwFormatIn, dwFormatOut;
 198.420 -       DWORD SaveFormatIn, SaveFormatOut;
 198.421 -       int ChannelsIn, ChannelsOut;
 198.422 -       LPLUT SaveGamutLUT;
 198.423 -
 198.424 -
 198.425 -       // Remove any gamut checking
 198.426 -       SaveGamutLUT = p ->Gamut;
 198.427 -       p ->Gamut = NULL;
 198.428 -
 198.429 -       ChannelsIn   = _cmsChannelsOf(p -> EntryColorSpace);
 198.430 -       ChannelsOut  = _cmsChannelsOf(p -> ExitColorSpace);
 198.431 -
 198.432 -       nGridPoints = _cmsReasonableGridpointsByColorspace(p -> EntryColorSpace, dwFlags);
 198.433 -
 198.434 -       Grid =  cmsAllocLUT();
 198.435 -       if (!Grid) return NULL;
 198.436 -
 198.437 -       Grid = cmsAlloc3DGrid(Grid, nGridPoints, ChannelsIn, ChannelsOut);
 198.438 -
 198.439 -       // Compute device link on 16-bit basis
 198.440 -       dwFormatIn   = (CHANNELS_SH(ChannelsIn)|BYTES_SH(2));
 198.441 -       dwFormatOut  = (CHANNELS_SH(ChannelsOut)|BYTES_SH(2));
 198.442 -
 198.443 -       SaveFormatIn  = p ->InputFormat;
 198.444 -       SaveFormatOut = p ->OutputFormat;
 198.445 -
 198.446 -       p -> InputFormat  = dwFormatIn;
 198.447 -       p -> OutputFormat = dwFormatOut;
 198.448 -       p -> FromInput    = _cmsIdentifyInputFormat(p, dwFormatIn);
 198.449 -       p -> ToOutput     = _cmsIdentifyOutputFormat(p, dwFormatOut);
 198.450 -
 198.451 -       // Fix gamut & gamma possible mismatches.
 198.452 -
 198.453 -       if (!(dwFlags & cmsFLAGS_NOPRELINEARIZATION)) {
 198.454 -
 198.455 -           cmsHTRANSFORM hOne[1];
 198.456 -           hOne[0] = h;
 198.457 -
 198.458 -           _cmsComputePrelinearizationTablesFromXFORM(hOne, 1, Grid);
 198.459 -       }
 198.460 -
 198.461 -       // Attention to this typecast! we can take the luxury to
 198.462 -       // do this since cmsHTRANSFORM is only an alias to a pointer
 198.463 -       // to the transform struct.
 198.464 -
 198.465 -       if (!cmsSample3DGrid(Grid, XFormSampler, (LPVOID) p, Grid -> wFlags)) {
 198.466 -
 198.467 -                cmsFreeLUT(Grid);
 198.468 -                Grid = NULL;
 198.469 -       }
 198.470 -
 198.471 -       p ->Gamut        = SaveGamutLUT;
 198.472 -       p ->InputFormat  = SaveFormatIn;
 198.473 -       p ->OutputFormat = SaveFormatOut;
 198.474 -
 198.475 -       return Grid;
 198.476 -}
 198.477 -
 198.478 -
 198.479 -
 198.480 -// Sampler for Black-preserving CMYK->CMYK transforms
 198.481 -
 198.482 -typedef struct {
 198.483 -                cmsHTRANSFORM cmyk2cmyk;
 198.484 -                cmsHTRANSFORM cmyk2Lab;
 198.485 -                LPGAMMATABLE  KTone;
 198.486 -                L16PARAMS     KToneParams;
 198.487 -                LPLUT         LabK2cmyk;
 198.488 -                double        MaxError;
 198.489 -
 198.490 -                cmsHTRANSFORM hRoundTrip;
 198.491 -                int           MaxTAC;
 198.492 -
 198.493 -                cmsHTRANSFORM hProofOutput;
 198.494 -
 198.495 -    } BPCARGO, *LPBPCARGO;
 198.496 -
 198.497 -
 198.498 -
 198.499 -// Preserve black only if that is the only ink used
 198.500 -static
 198.501 -int BlackPreservingGrayOnlySampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
 198.502 -{
 198.503 -    BPCARGO* bp = (LPBPCARGO) Cargo;
 198.504 -
 198.505 -    // If going across black only, keep black only
 198.506 -    if (In[0] == 0 && In[1] == 0 && In[2] == 0) {
 198.507 -
 198.508 -        // TAC does not apply because it is black ink!
 198.509 -        Out[0] = Out[1] = Out[2] = 0;
 198.510 -        Out[3] = cmsLinearInterpLUT16(In[3], bp->KTone ->GammaTable, &bp->KToneParams);
 198.511 -        return 1;
 198.512 -    }
 198.513 -
 198.514 -    // Keep normal transform for other colors
 198.515 -    cmsDoTransform(bp ->cmyk2cmyk, In, Out, 1);
 198.516 -    return 1;
 198.517 -}
 198.518 -
 198.519 -
 198.520 -
 198.521 -// Preserve all K plane.
 198.522 -static
 198.523 -int BlackPreservingSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
 198.524 -{
 198.525 -
 198.526 -    WORD LabK[4];
 198.527 -    double SumCMY, SumCMYK, Error;
 198.528 -    cmsCIELab ColorimetricLab, BlackPreservingLab;
 198.529 -    BPCARGO* bp = (LPBPCARGO) Cargo;
 198.530 -
 198.531 -    // Get the K across Tone curve
 198.532 -    LabK[3] = cmsLinearInterpLUT16(In[3], bp->KTone ->GammaTable, &bp->KToneParams);
 198.533 -
 198.534 -    // If going across black only, keep black only
 198.535 -    if (In[0] == 0 && In[1] == 0 && In[2] == 0) {
 198.536 -
 198.537 -        Out[0] = Out[1] = Out[2] = 0;
 198.538 -        Out[3] = LabK[3];
 198.539 -        return 1;
 198.540 -    }
 198.541 -
 198.542 -    // Try the original transform, maybe K is already ok (valid on K=0)
 198.543 -    cmsDoTransform(bp ->cmyk2cmyk, In, Out, 1);
 198.544 -    if (Out[3] == LabK[3]) return 1;
 198.545 -
 198.546 -
 198.547 -    // No, mesure and keep Lab measurement for further usage
 198.548 -    cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1);
 198.549 -
 198.550 -    // Is not black only and the transform doesn't keep black.
 198.551 -    // Obtain the Lab of CMYK. After that we have Lab + K
 198.552 -    cmsDoTransform(bp ->cmyk2Lab, In, LabK, 1);
 198.553 -
 198.554 -    // Obtain the corresponding CMY using reverse interpolation.
 198.555 -    // As a seed, we use the colorimetric CMY
 198.556 -    cmsEvalLUTreverse(bp ->LabK2cmyk, LabK, Out, Out);
 198.557 -
 198.558 -    // Estimate the error
 198.559 -    cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1);
 198.560 -    Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab);
 198.561 -
 198.562 -
 198.563 -    // Apply TAC if needed
 198.564 -
 198.565 -    SumCMY   = Out[0]  + Out[1] + Out[2];
 198.566 -    SumCMYK  = SumCMY + Out[3];
 198.567 -
 198.568 -    if (SumCMYK > bp ->MaxTAC) {
 198.569 -
 198.570 -        double Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY);
 198.571 -        if (Ratio < 0)
 198.572 -                  Ratio = 0;
 198.573 -
 198.574 -        Out[0] = (WORD) floor(Out[0] * Ratio + 0.5);     // C
 198.575 -        Out[1] = (WORD) floor(Out[1] * Ratio + 0.5);     // M
 198.576 -        Out[2] = (WORD) floor(Out[2] * Ratio + 0.5);     // Y
 198.577 -    }
 198.578 -
 198.579 -    return 1;
 198.580 -}
 198.581 -
 198.582 -
 198.583 -// Sample whole gamut to estimate maximum TAC
 198.584 -
 198.585 -#ifdef _MSC_VER
 198.586 -#pragma warning(disable : 4100)
 198.587 -#endif
 198.588 -
 198.589 -static
 198.590 -int EstimateTAC(register WORD In[], register WORD Out[], register LPVOID Cargo)
 198.591 -{
 198.592 -    BPCARGO* bp = (LPBPCARGO) Cargo;
 198.593 -    WORD RoundTrip[4];
 198.594 -    int Sum;
 198.595 -
 198.596 -    cmsDoTransform(bp->hRoundTrip, In, RoundTrip, 1);
 198.597 -
 198.598 -    Sum = RoundTrip[0] + RoundTrip[1] + RoundTrip[2] + RoundTrip[3];
 198.599 -
 198.600 -    if (Sum > bp ->MaxTAC)
 198.601 -            bp ->MaxTAC = Sum;
 198.602 -
 198.603 -    return 1;
 198.604 -}
 198.605 -
 198.606 -
 198.607 -// Estimate the maximum error
 198.608 -static
 198.609 -int BlackPreservingEstimateErrorSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
 198.610 -{
 198.611 -    BPCARGO* bp = (LPBPCARGO) Cargo;
 198.612 -    WORD ColorimetricOut[4];
 198.613 -    cmsCIELab ColorimetricLab, BlackPreservingLab;
 198.614 -    double Error;
 198.615 -
 198.616 -    if (In[0] == 0 && In[1] == 0 && In[2] == 0) return 1;
 198.617 -
 198.618 -    cmsDoTransform(bp->cmyk2cmyk, In, ColorimetricOut, 1);
 198.619 -
 198.620 -    cmsDoTransform(bp->hProofOutput, ColorimetricOut, &ColorimetricLab, 1);
 198.621 -    cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1);
 198.622 -
 198.623 -    Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab);
 198.624 -
 198.625 -    if (Error > bp ->MaxError)
 198.626 -        bp ->MaxError = Error;
 198.627 -
 198.628 -    return 1;
 198.629 -}
 198.630 -
 198.631 -// Setup the K preservation strategy
 198.632 -int LCMSEXPORT cmsSetCMYKPreservationStrategy(int n)
 198.633 -{
 198.634 -    int OldVal = GlobalBlackPreservationStrategy;
 198.635 -
 198.636 -    if (n >= 0)
 198.637 -            GlobalBlackPreservationStrategy = n;
 198.638 -
 198.639 -    return OldVal;
 198.640 -}
 198.641 -
 198.642 -#pragma warning(disable: 4550)
 198.643 -
 198.644 -// Get a pointer to callback on depending of strategy
 198.645 -static
 198.646 -_cmsSAMPLER _cmsGetBlackPreservationSampler(void)
 198.647 -{
 198.648 -    switch (GlobalBlackPreservationStrategy) {
 198.649 -
 198.650 -        case 0: return BlackPreservingGrayOnlySampler;
 198.651 -        default: return BlackPreservingSampler;
 198.652 -   }
 198.653 -
 198.654 -}
 198.655 -
 198.656 -// This is the black-preserving devicelink generator
 198.657 -LPLUT _cmsPrecalculateBlackPreservingDeviceLink(cmsHTRANSFORM hCMYK2CMYK, DWORD dwFlags)
 198.658 -{
 198.659 -       _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) hCMYK2CMYK;
 198.660 -       BPCARGO Cargo;
 198.661 -       LPLUT Grid;
 198.662 -       DWORD LocalFlags;
 198.663 -       cmsHPROFILE hLab = cmsCreateLabProfile(NULL);
 198.664 -       int nGridPoints;
 198.665 -       icTagSignature Device2PCS[] = {icSigAToB0Tag,       // Perceptual
 198.666 -                                      icSigAToB1Tag,       // Relative colorimetric
 198.667 -                                      icSigAToB2Tag,       // Saturation
 198.668 -                                      icSigAToB1Tag };     // Absolute colorimetric
 198.669 -                                                           // (Relative/WhitePoint)
 198.670 -
 198.671 -       nGridPoints = _cmsReasonableGridpointsByColorspace(p -> EntryColorSpace, dwFlags);
 198.672 -
 198.673 -       // Get a copy of inteserting flags for this kind of xform
 198.674 -       LocalFlags = cmsFLAGS_NOTPRECALC;
 198.675 -       if (p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION)
 198.676 -           LocalFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
 198.677 -
 198.678 -       // Fill in cargo struct
 198.679 -       Cargo.cmyk2cmyk = hCMYK2CMYK;
 198.680 -
 198.681 -       // Compute tone curve.
 198.682 -       Cargo.KTone  =  _cmsBuildKToneCurve(hCMYK2CMYK, 256);
 198.683 -       if (Cargo.KTone == NULL) return NULL;
 198.684 -       cmsCalcL16Params(Cargo.KTone ->nEntries, &Cargo.KToneParams);
 198.685 -
 198.686 -
 198.687 -       // Create a CMYK->Lab "normal" transform on input, without K-preservation
 198.688 -       Cargo.cmyk2Lab  = cmsCreateTransform(p ->InputProfile, TYPE_CMYK_16,
 198.689 -                                            hLab, TYPE_Lab_16, p->Intent, LocalFlags);
 198.690 -
 198.691 -       // We are going to use the reverse of proof direction
 198.692 -       Cargo.LabK2cmyk = cmsReadICCLut(p->OutputProfile, Device2PCS[p->Intent]);
 198.693 -
 198.694 -       // Is there any table available?
 198.695 -       if (Cargo.LabK2cmyk == NULL) {
 198.696 -
 198.697 -           Grid = NULL;
 198.698 -           goto Cleanup;
 198.699 -       }
 198.700 -
 198.701 -       // Setup a roundtrip on output profile for TAC estimation
 198.702 -       Cargo.hRoundTrip = cmsCreateTransform(p ->OutputProfile, TYPE_CMYK_16,
 198.703 -                                             p ->OutputProfile, TYPE_CMYK_16, p->Intent, cmsFLAGS_NOTPRECALC);
 198.704 -
 198.705 -
 198.706 -       // Setup a proof CMYK->Lab on output
 198.707 -       Cargo.hProofOutput  = cmsCreateTransform(p ->OutputProfile, TYPE_CMYK_16,
 198.708 -                                            hLab, TYPE_Lab_DBL, p->Intent, LocalFlags);
 198.709 -
 198.710 -
 198.711 -       // Create an empty LUT for holding K-preserving xform
 198.712 -       Grid =  cmsAllocLUT();
 198.713 -       if (!Grid) goto Cleanup;
 198.714 -
 198.715 -       Grid = cmsAlloc3DGrid(Grid, nGridPoints, 4, 4);
 198.716 -
 198.717 -       // Setup formatters
 198.718 -       p -> FromInput = _cmsIdentifyInputFormat(p,  TYPE_CMYK_16);
 198.719 -       p -> ToOutput  = _cmsIdentifyOutputFormat(p, TYPE_CMYK_16);
 198.720 -
 198.721 -
 198.722 -
 198.723 -       // Step #1, estimate TAC
 198.724 -       Cargo.MaxTAC = 0;
 198.725 -       if (!cmsSample3DGrid(Grid, EstimateTAC, (LPVOID) &Cargo, 0)) {
 198.726 -
 198.727 -                cmsFreeLUT(Grid);
 198.728 -                Grid = NULL;
 198.729 -                goto Cleanup;
 198.730 -       }
 198.731 -
 198.732 -
 198.733 -       // Step #2, compute approximation
 198.734 -       if (!cmsSample3DGrid(Grid, _cmsGetBlackPreservationSampler(), (LPVOID) &Cargo, 0)) {
 198.735 -
 198.736 -                cmsFreeLUT(Grid);
 198.737 -                Grid = NULL;
 198.738 -                goto Cleanup;
 198.739 -       }
 198.740 -
 198.741 -       // Step #3, estimate error
 198.742 -        Cargo.MaxError = 0;
 198.743 -        cmsSample3DGrid(Grid, BlackPreservingEstimateErrorSampler, (LPVOID) &Cargo, SAMPLER_INSPECT);
 198.744 -
 198.745 -
 198.746 -Cleanup:
 198.747 -
 198.748 -       if (Cargo.cmyk2Lab) cmsDeleteTransform(Cargo.cmyk2Lab);
 198.749 -       if (Cargo.hRoundTrip) cmsDeleteTransform(Cargo.hRoundTrip);
 198.750 -       if (Cargo.hProofOutput) cmsDeleteTransform(Cargo.hProofOutput);
 198.751 -
 198.752 -       if (hLab) cmsCloseProfile(hLab);
 198.753 -       if (Cargo.KTone) cmsFreeGamma(Cargo.KTone);
 198.754 -       if (Cargo.LabK2cmyk) cmsFreeLUT(Cargo.LabK2cmyk);
 198.755 -
 198.756 -       return Grid;
 198.757 -}
 198.758 -
 198.759 -
 198.760 -
 198.761 -// Fix broken LUT. just to obtain other CMS compatibility
 198.762 -
 198.763 -static
 198.764 -void PatchLUT(LPLUT Grid, WORD At[], WORD Value[],
 198.765 -                     int nChannelsOut, int nChannelsIn)
 198.766 -{
 198.767 -       LPL16PARAMS p16  = &Grid -> CLut16params;
 198.768 -       double     px, py, pz, pw;
 198.769 -       int        x0, y0, z0, w0;
 198.770 -       int        i, index;
 198.771 -
 198.772 -
 198.773 -       if (Grid ->wFlags & LUT_HASTL1) return;  // There is a prelinearization
 198.774 -
 198.775 -       px = ((double) At[0] * (p16->Domain)) / 65535.0;
 198.776 -       py = ((double) At[1] * (p16->Domain)) / 65535.0;
 198.777 -       pz = ((double) At[2] * (p16->Domain)) / 65535.0;
 198.778 -       pw = ((double) At[3] * (p16->Domain)) / 65535.0;
 198.779 -
 198.780 -       x0 = (int) floor(px);
 198.781 -       y0 = (int) floor(py);
 198.782 -       z0 = (int) floor(pz);
 198.783 -       w0 = (int) floor(pw);
 198.784 -
 198.785 -       if (nChannelsIn == 4) {
 198.786 -
 198.787 -              if (((px - x0) != 0) ||
 198.788 -                  ((py - y0) != 0) ||
 198.789 -                  ((pz - z0) != 0) ||
 198.790 -                  ((pw - w0) != 0)) return; // Not on exact node
 198.791 -
 198.792 -              index = p16 -> opta4 * x0 +
 198.793 -                      p16 -> opta3 * y0 +
 198.794 -                      p16 -> opta2 * z0 +
 198.795 -                      p16 -> opta1 * w0;
 198.796 -       }
 198.797 -       else
 198.798 -       if (nChannelsIn == 3) {
 198.799 -
 198.800 -              if (((px - x0) != 0) ||
 198.801 -                  ((py - y0) != 0) ||
 198.802 -                  ((pz - z0) != 0)) return;  // Not on exact node
 198.803 -
 198.804 -              index = p16 -> opta3 * x0 +
 198.805 -                      p16 -> opta2 * y0 +
 198.806 -                      p16 -> opta1 * z0;
 198.807 -       }
 198.808 -       else
 198.809 -       if (nChannelsIn == 1) {
 198.810 -
 198.811 -              if (((px - x0) != 0)) return; // Not on exact node
 198.812 -
 198.813 -              index = p16 -> opta1 * x0;
 198.814 -       }
 198.815 -       else {
 198.816 -           cmsSignalError(LCMS_ERRC_ABORTED, "(internal) %d Channels are not supported on PatchLUT", nChannelsIn);
 198.817 -           return;
 198.818 -       }
 198.819 -
 198.820 -       for (i=0; i < nChannelsOut; i++)
 198.821 -              Grid -> T[index + i] = Value[i];
 198.822 -
 198.823 -}
 198.824 -
 198.825 -
 198.826 -
 198.827 -LCMSBOOL _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p)
 198.828 -{
 198.829 -
 198.830 -       WORD *WhitePointIn, *WhitePointOut, *BlackPointIn, *BlackPointOut;
 198.831 -       int nOuts, nIns;
 198.832 -
 198.833 -
 198.834 -       if (!p -> DeviceLink) return FALSE;
 198.835 -
 198.836 -       if (p ->Intent == INTENT_ABSOLUTE_COLORIMETRIC) return FALSE;
 198.837 -       if ((p ->PreviewProfile != NULL) &&
 198.838 -           (p ->ProofIntent == INTENT_ABSOLUTE_COLORIMETRIC)) return FALSE;
 198.839 -
 198.840 -
 198.841 -       if (!_cmsEndPointsBySpace(p -> EntryColorSpace,
 198.842 -                                 &WhitePointIn, &BlackPointIn, &nIns)) return FALSE;
 198.843 -
 198.844 -
 198.845 -       if (!_cmsEndPointsBySpace(p -> ExitColorSpace,
 198.846 -                                   &WhitePointOut, &BlackPointOut, &nOuts)) return FALSE;
 198.847 -
 198.848 -       // Fix white only
 198.849 -
 198.850 -       PatchLUT(p -> DeviceLink, WhitePointIn, WhitePointOut, nOuts, nIns);
 198.851 -       // PatchLUT(p -> DeviceLink, BlackPointIn, BlackPointOut, nOuts, nIns);
 198.852 -
 198.853 -       return TRUE;
 198.854 -}
 198.855 -
   199.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   199.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmssm.c	Fri Sep 24 16:41:32 2010 -0700
   199.3 @@ -0,0 +1,762 @@
   199.4 +/*
   199.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   199.6 + *
   199.7 + * This code is free software; you can redistribute it and/or modify it
   199.8 + * under the terms of the GNU General Public License version 2 only, as
   199.9 + * published by the Free Software Foundation.  Oracle designates this
  199.10 + * particular file as subject to the "Classpath" exception as provided
  199.11 + * by Oracle in the LICENSE file that accompanied this code.
  199.12 + *
  199.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  199.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  199.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  199.16 + * version 2 for more details (a copy is included in the LICENSE file that
  199.17 + * accompanied this code).
  199.18 + *
  199.19 + * You should have received a copy of the GNU General Public License version
  199.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  199.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  199.22 + *
  199.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  199.24 + * or visit www.oracle.com if you need additional information or have any
  199.25 + * questions.
  199.26 + */
  199.27 +
  199.28 +// This file is available under and governed by the GNU General Public
  199.29 +// License version 2 only, as published by the Free Software Foundation.
  199.30 +// However, the following notice accompanied the original version of this
  199.31 +// file:
  199.32 +//
  199.33 +//---------------------------------------------------------------------------------
  199.34 +//
  199.35 +//  Little Color Management System
  199.36 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  199.37 +//
  199.38 +// Permission is hereby granted, free of charge, to any person obtaining
  199.39 +// a copy of this software and associated documentation files (the "Software"),
  199.40 +// to deal in the Software without restriction, including without limitation
  199.41 +// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  199.42 +// and/or sell copies of the Software, and to permit persons to whom the Software
  199.43 +// is furnished to do so, subject to the following conditions:
  199.44 +//
  199.45 +// The above copyright notice and this permission notice shall be included in
  199.46 +// all copies or substantial portions of the Software.
  199.47 +//
  199.48 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  199.49 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  199.50 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  199.51 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  199.52 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  199.53 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  199.54 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  199.55 +//
  199.56 +//---------------------------------------------------------------------------------
  199.57 +//
  199.58 +
  199.59 +#include "lcms2_internal.h"
  199.60 +
  199.61 +
  199.62 +// ------------------------------------------------------------------------
  199.63 +
  199.64 +// Gamut boundary description by using Jan Morovic's Segment maxima method
  199.65 +// Many thanks to Jan for allowing me to use his algorithm.
  199.66 +
  199.67 +// r = C*
  199.68 +// alpha = Hab
  199.69 +// theta = L*
  199.70 +
  199.71 +#define SECTORS 16      // number of divisions in alpha and theta
  199.72 +
  199.73 +// Spherical coordinates
  199.74 +typedef struct {
  199.75 +
  199.76 +    cmsFloat64Number r;
  199.77 +    cmsFloat64Number alpha;
  199.78 +    cmsFloat64Number theta;
  199.79 +
  199.80 +} cmsSpherical;
  199.81 +
  199.82 +typedef  enum {
  199.83 +        GP_EMPTY,
  199.84 +        GP_SPECIFIED,
  199.85 +        GP_MODELED
  199.86 +
  199.87 +    } GDBPointType;
  199.88 +
  199.89 +
  199.90 +typedef struct {
  199.91 +
  199.92 +    GDBPointType Type;
  199.93 +    cmsSpherical p;         // Keep also alpha & theta of maximum
  199.94 +
  199.95 +} cmsGDBPoint;
  199.96 +
  199.97 +
  199.98 +typedef struct {
  199.99 +
 199.100 +    cmsContext ContextID;
 199.101 +    cmsGDBPoint Gamut[SECTORS][SECTORS];
 199.102 +
 199.103 +} cmsGDB;
 199.104 +
 199.105 +
 199.106 +// A line using the parametric form
 199.107 +// P = a + t*u
 199.108 +typedef struct {
 199.109 +
 199.110 +    cmsVEC3 a;
 199.111 +    cmsVEC3 u;
 199.112 +
 199.113 +} cmsLine;
 199.114 +
 199.115 +
 199.116 +// A plane using the parametric form
 199.117 +// Q = b + r*v + s*w
 199.118 +typedef struct {
 199.119 +
 199.120 +    cmsVEC3 b;
 199.121 +    cmsVEC3 v;
 199.122 +    cmsVEC3 w;
 199.123 +
 199.124 +} cmsPlane;
 199.125 +
 199.126 +
 199.127 +
 199.128 +// --------------------------------------------------------------------------------------------
 199.129 +
 199.130 +// ATAN2() which always returns degree positive numbers
 199.131 +
 199.132 +static
 199.133 +cmsFloat64Number _cmsAtan2(cmsFloat64Number y, cmsFloat64Number x)
 199.134 +{
 199.135 +    cmsFloat64Number a;
 199.136 +
 199.137 +    // Deal with undefined case
 199.138 +    if (x == 0.0 && y == 0.0) return 0;
 199.139 +
 199.140 +    a = (atan2(y, x) * 180.0) / M_PI;
 199.141 +
 199.142 +    while (a < 0) {
 199.143 +        a += 360;
 199.144 +    }
 199.145 +
 199.146 +    return a;
 199.147 +}
 199.148 +
 199.149 +// Convert to spherical coordinates
 199.150 +static
 199.151 +void ToSpherical(cmsSpherical* sp, const cmsVEC3* v)
 199.152 +{
 199.153 +
 199.154 +    cmsFloat64Number L, a, b;
 199.155 +
 199.156 +    L = v ->n[VX];
 199.157 +    a = v ->n[VY];
 199.158 +    b = v ->n[VZ];
 199.159 +
 199.160 +    sp ->r = sqrt( L*L + a*a + b*b );
 199.161 +
 199.162 +   if (sp ->r == 0) {
 199.163 +        sp ->alpha = sp ->theta = 0;
 199.164 +        return;
 199.165 +    }
 199.166 +
 199.167 +    sp ->alpha = _cmsAtan2(a, b);
 199.168 +    sp ->theta = _cmsAtan2(sqrt(a*a + b*b), L);
 199.169 +}
 199.170 +
 199.171 +
 199.172 +// Convert to cartesian from spherical
 199.173 +static
 199.174 +void ToCartesian(cmsVEC3* v, const cmsSpherical* sp)
 199.175 +{
 199.176 +    cmsFloat64Number sin_alpha;
 199.177 +    cmsFloat64Number cos_alpha;
 199.178 +    cmsFloat64Number sin_theta;
 199.179 +    cmsFloat64Number cos_theta;
 199.180 +    cmsFloat64Number L, a, b;
 199.181 +
 199.182 +    sin_alpha = sin((M_PI * sp ->alpha) / 180.0);
 199.183 +    cos_alpha = cos((M_PI * sp ->alpha) / 180.0);
 199.184 +    sin_theta = sin((M_PI * sp ->theta) / 180.0);
 199.185 +    cos_theta = cos((M_PI * sp ->theta) / 180.0);
 199.186 +
 199.187 +    a = sp ->r * sin_theta * sin_alpha;
 199.188 +    b = sp ->r * sin_theta * cos_alpha;
 199.189 +    L = sp ->r * cos_theta;
 199.190 +
 199.191 +    v ->n[VX] = L;
 199.192 +    v ->n[VY] = a;
 199.193 +    v ->n[VZ] = b;
 199.194 +}
 199.195 +
 199.196 +
 199.197 +// Quantize sector of a spherical coordinate. Saturate 360, 180 to last sector
 199.198 +// The limits are the centers of each sector, so
 199.199 +static
 199.200 +void QuantizeToSector(const cmsSpherical* sp, int* alpha, int* theta)
 199.201 +{
 199.202 +    *alpha = (int) floor(((sp->alpha * (SECTORS)) / 360.0) );
 199.203 +    *theta = (int) floor(((sp->theta * (SECTORS)) / 180.0) );
 199.204 +
 199.205 +    if (*alpha >= SECTORS)
 199.206 +        *alpha = SECTORS-1;
 199.207 +    if (*theta >= SECTORS)
 199.208 +        *theta = SECTORS-1;
 199.209 +}
 199.210 +
 199.211 +
 199.212 +// Line determined by 2 points
 199.213 +static
 199.214 +void LineOf2Points(cmsLine* line, cmsVEC3* a, cmsVEC3* b)
 199.215 +{
 199.216 +
 199.217 +    _cmsVEC3init(&line ->a, a ->n[VX], a ->n[VY], a ->n[VZ]);
 199.218 +    _cmsVEC3init(&line ->u, b ->n[VX] - a ->n[VX],
 199.219 +                            b ->n[VY] - a ->n[VY],
 199.220 +                            b ->n[VZ] - a ->n[VZ]);
 199.221 +}
 199.222 +
 199.223 +
 199.224 +// Evaluate parametric line
 199.225 +static
 199.226 +void GetPointOfLine(cmsVEC3* p, const cmsLine* line, cmsFloat64Number t)
 199.227 +{
 199.228 +    p ->n[VX] = line ->a.n[VX] + t * line->u.n[VX];
 199.229 +    p ->n[VY] = line ->a.n[VY] + t * line->u.n[VY];
 199.230 +    p ->n[VZ] = line ->a.n[VZ] + t * line->u.n[VZ];
 199.231 +}
 199.232 +
 199.233 +
 199.234 +
 199.235 +/*
 199.236 +    Closest point in sector line1 to sector line2 (both are defined as 0 <=t <= 1)
 199.237 +    http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
 199.238 +
 199.239 +    Copyright 2001, softSurfer (www.softsurfer.com)
 199.240 +    This code may be freely used and modified for any purpose
 199.241 +    providing that this copyright notice is included with it.
 199.242 +    SoftSurfer makes no warranty for this code, and cannot be held
 199.243 +    liable for any real or imagined damage resulting from its use.
 199.244 +    Users of this code must verify correctness for their application.
 199.245 +
 199.246 +*/
 199.247 +
 199.248 +static
 199.249 +cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2)
 199.250 +{
 199.251 +    cmsFloat64Number a, b, c, d, e, D;
 199.252 +    cmsFloat64Number sc, sN, sD;
 199.253 +    cmsFloat64Number tc, tN, tD;
 199.254 +    cmsVEC3 w0;
 199.255 +
 199.256 +    _cmsVEC3minus(&w0, &line1 ->a, &line2 ->a);
 199.257 +
 199.258 +    a  = _cmsVEC3dot(&line1 ->u, &line1 ->u);
 199.259 +    b  = _cmsVEC3dot(&line1 ->u, &line2 ->u);
 199.260 +    c  = _cmsVEC3dot(&line2 ->u, &line2 ->u);
 199.261 +    d  = _cmsVEC3dot(&line1 ->u, &w0);
 199.262 +    e  = _cmsVEC3dot(&line2 ->u, &w0);
 199.263 +
 199.264 +    D  = a*c - b * b;      // Denominator
 199.265 +    sD = tD = D;           // default sD = D >= 0
 199.266 +
 199.267 +    if (D <  MATRIX_DET_TOLERANCE) {   // the lines are almost parallel
 199.268 +
 199.269 +        sN = 0.0;        // force using point P0 on segment S1
 199.270 +        sD = 1.0;        // to prevent possible division by 0.0 later
 199.271 +        tN = e;
 199.272 +        tD = c;
 199.273 +    }
 199.274 +    else {                // get the closest points on the infinite lines
 199.275 +
 199.276 +        sN = (b*e - c*d);
 199.277 +        tN = (a*e - b*d);
 199.278 +
 199.279 +        if (sN < 0.0) {       // sc < 0 => the s=0 edge is visible
 199.280 +
 199.281 +            sN = 0.0;
 199.282 +            tN = e;
 199.283 +            tD = c;
 199.284 +        }
 199.285 +        else if (sN > sD) {   // sc > 1 => the s=1 edge is visible
 199.286 +            sN = sD;
 199.287 +            tN = e + b;
 199.288 +            tD = c;
 199.289 +        }
 199.290 +    }
 199.291 +
 199.292 +    if (tN < 0.0) {           // tc < 0 => the t=0 edge is visible
 199.293 +
 199.294 +        tN = 0.0;
 199.295 +        // recompute sc for this edge
 199.296 +        if (-d < 0.0)
 199.297 +            sN = 0.0;
 199.298 +        else if (-d > a)
 199.299 +            sN = sD;
 199.300 +        else {
 199.301 +            sN = -d;
 199.302 +            sD = a;
 199.303 +        }
 199.304 +    }
 199.305 +    else if (tN > tD) {      // tc > 1 => the t=1 edge is visible
 199.306 +
 199.307 +        tN = tD;
 199.308 +
 199.309 +        // recompute sc for this edge
 199.310 +        if ((-d + b) < 0.0)
 199.311 +            sN = 0;
 199.312 +        else if ((-d + b) > a)
 199.313 +            sN = sD;
 199.314 +        else {
 199.315 +            sN = (-d + b);
 199.316 +            sD = a;
 199.317 +        }
 199.318 +    }
 199.319 +    // finally do the division to get sc and tc
 199.320 +    sc = (fabs(sN) < MATRIX_DET_TOLERANCE ? 0.0 : sN / sD);
 199.321 +    tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD);
 199.322 +
 199.323 +    GetPointOfLine(r, line1, sc);
 199.324 +    return TRUE;
 199.325 +}
 199.326 +
 199.327 +
 199.328 +
 199.329 +// ------------------------------------------------------------------ Wrapper
 199.330 +
 199.331 +
 199.332 +// Allocate & free structure
 199.333 +cmsHANDLE  CMSEXPORT cmsGBDAlloc(cmsContext ContextID)
 199.334 +{
 199.335 +    cmsGDB* gbd = (cmsGDB*) _cmsMallocZero(ContextID, sizeof(cmsGDB));
 199.336 +    if (gbd == NULL) return NULL;
 199.337 +
 199.338 +    gbd -> ContextID = ContextID;
 199.339 +
 199.340 +    return (cmsHANDLE) gbd;
 199.341 +}
 199.342 +
 199.343 +
 199.344 +void CMSEXPORT cmsGBDFree(cmsHANDLE hGBD)
 199.345 +{
 199.346 +    cmsGDB* gbd = (cmsGDB*) hGBD;
 199.347 +    if (hGBD != NULL)
 199.348 +        _cmsFree(gbd->ContextID, (void*) gbd);
 199.349 +}
 199.350 +
 199.351 +
 199.352 +// Auxiliar to retrieve a pointer to the segmentr containing the Lab value
 199.353 +static
 199.354 +cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp)
 199.355 +{
 199.356 +    cmsVEC3 v;
 199.357 +    int alpha, theta;
 199.358 +
 199.359 +    // Housekeeping
 199.360 +    _cmsAssert(gbd != NULL);
 199.361 +    _cmsAssert(Lab != NULL);
 199.362 +    _cmsAssert(sp != NULL);
 199.363 +
 199.364 +    // Center L* by substracting half of its domain, that's 50
 199.365 +    _cmsVEC3init(&v, Lab ->L - 50.0, Lab ->a, Lab ->b);
 199.366 +
 199.367 +    // Convert to spherical coordinates
 199.368 +    ToSpherical(sp, &v);
 199.369 +
 199.370 +    if (sp ->r < 0 || sp ->alpha < 0 || sp->theta < 0) {
 199.371 +         cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, "spherical value out of range");
 199.372 +         return NULL;
 199.373 +    }
 199.374 +
 199.375 +    // On which sector it falls?
 199.376 +    QuantizeToSector(sp, &alpha, &theta);
 199.377 +
 199.378 +    if (alpha < 0 || theta < 0 || alpha >= SECTORS || theta >= SECTORS) {
 199.379 +         cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, " quadrant out of range");
 199.380 +         return NULL;
 199.381 +    }
 199.382 +
 199.383 +    // Get pointer to the sector
 199.384 +    return &gbd ->Gamut[theta][alpha];
 199.385 +}
 199.386 +
 199.387 +// Add a point to gamut descriptor. Point to add is in Lab color space.
 199.388 +// GBD is centered on a=b=0 and L*=50
 199.389 +cmsBool CMSEXPORT cmsGDBAddPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
 199.390 +{
 199.391 +    cmsGDB* gbd = (cmsGDB*) hGBD;
 199.392 +    cmsGDBPoint* ptr;
 199.393 +    cmsSpherical sp;
 199.394 +
 199.395 +
 199.396 +    // Get pointer to the sector
 199.397 +    ptr = GetPoint(gbd, Lab, &sp);
 199.398 +    if (ptr == NULL) return FALSE;
 199.399 +
 199.400 +    // If no samples at this sector, add it
 199.401 +    if (ptr ->Type == GP_EMPTY) {
 199.402 +
 199.403 +        ptr -> Type = GP_SPECIFIED;
 199.404 +        ptr -> p    = sp;
 199.405 +    }
 199.406 +    else {
 199.407 +
 199.408 +
 199.409 +        // Substitute only if radius is greater
 199.410 +        if (sp.r > ptr -> p.r) {
 199.411 +
 199.412 +                ptr -> Type = GP_SPECIFIED;
 199.413 +                ptr -> p    = sp;
 199.414 +        }
 199.415 +    }
 199.416 +
 199.417 +    return TRUE;
 199.418 +}
 199.419 +
 199.420 +// Check if a given point falls inside gamut
 199.421 +cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
 199.422 +{
 199.423 +    cmsGDB* gbd = (cmsGDB*) hGBD;
 199.424 +    cmsGDBPoint* ptr;
 199.425 +    cmsSpherical sp;
 199.426 +
 199.427 +    // Get pointer to the sector
 199.428 +    ptr = GetPoint(gbd, Lab, &sp);
 199.429 +    if (ptr == NULL) return FALSE;
 199.430 +
 199.431 +    // If no samples at this sector, return no data
 199.432 +    if (ptr ->Type == GP_EMPTY) return FALSE;
 199.433 +
 199.434 +    // In gamut only if radius is greater
 199.435 +
 199.436 +    return (sp.r <= ptr -> p.r);
 199.437 +}
 199.438 +
 199.439 +// -----------------------------------------------------------------------------------------------------------------------
 199.440 +
 199.441 +// Find near sectors. The list of sectors found is returned on Close[].
 199.442 +// The function returns the number of sectors as well.
 199.443 +
 199.444 +// 24   9  10  11  12
 199.445 +// 23   8   1   2  13
 199.446 +// 22   7   *   3  14
 199.447 +// 21   6   5   4  15
 199.448 +// 20  19  18  17  16
 199.449 +//
 199.450 +// Those are the relative movements
 199.451 +// {-2,-2}, {-1, -2}, {0, -2}, {+1, -2}, {+2,  -2},
 199.452 +// {-2,-1}, {-1, -1}, {0, -1}, {+1, -1}, {+2,  -1},
 199.453 +// {-2, 0}, {-1,  0}, {0,  0}, {+1,  0}, {+2,   0},
 199.454 +// {-2,+1}, {-1, +1}, {0, +1}, {+1,  +1}, {+2,  +1},
 199.455 +// {-2,+2}, {-1, +2}, {0, +2}, {+1,  +2}, {+2,  +2}};
 199.456 +
 199.457 +
 199.458 +static
 199.459 +const struct _spiral {
 199.460 +
 199.461 +    int AdvX, AdvY;
 199.462 +
 199.463 +    } Spiral[] = { {0,  -1}, {+1, -1}, {+1,  0}, {+1, +1}, {0,  +1}, {-1, +1},
 199.464 +                   {-1,  0}, {-1, -1}, {-1, -2}, {0,  -2}, {+1, -2}, {+2, -2},
 199.465 +                   {+2, -1}, {+2,  0}, {+2, +1}, {+2, +2}, {+1, +2}, {0,  +2},
 199.466 +                   {-1, +2}, {-2, +2}, {-2, +1}, {-2, 0},  {-2, -1}, {-2, -2} };
 199.467 +
 199.468 +#define NSTEPS (sizeof(Spiral) / sizeof(struct _spiral))
 199.469 +
 199.470 +static
 199.471 +int FindNearSectors(cmsGDB* gbd, int alpha, int theta, cmsGDBPoint* Close[])
 199.472 +{
 199.473 +    int nSectors = 0;
 199.474 +    int i, a, t;
 199.475 +    cmsGDBPoint* pt;
 199.476 +
 199.477 +    for (i=0; i < NSTEPS; i++) {
 199.478 +
 199.479 +        a = alpha + Spiral[i].AdvX;
 199.480 +        t = theta + Spiral[i].AdvY;
 199.481 +
 199.482 +        // Cycle at the end
 199.483 +        a %= SECTORS;
 199.484 +        t %= SECTORS;
 199.485 +
 199.486 +        // Cycle at the begin
 199.487 +        if (a < 0) a = SECTORS + a;
 199.488 +        if (t < 0) t = SECTORS + t;
 199.489 +
 199.490 +        pt = &gbd ->Gamut[t][a];
 199.491 +
 199.492 +        if (pt -> Type != GP_EMPTY) {
 199.493 +
 199.494 +            Close[nSectors++] = pt;
 199.495 +        }
 199.496 +    }
 199.497 +
 199.498 +    return nSectors;
 199.499 +}
 199.500 +
 199.501 +
 199.502 +// Interpolate a missing sector. Method identifies whatever this is top, bottom or mid
 199.503 +static
 199.504 +cmsBool InterpolateMissingSector(cmsGDB* gbd, int alpha, int theta)
 199.505 +{
 199.506 +    cmsSpherical sp;
 199.507 +    cmsVEC3 Lab;
 199.508 +    cmsVEC3 Centre;
 199.509 +    cmsLine ray;
 199.510 +    int nCloseSectors;
 199.511 +    cmsGDBPoint* Close[NSTEPS];
 199.512 +    cmsSpherical closel, templ;
 199.513 +    cmsLine edge;
 199.514 +    int k, m;
 199.515 +
 199.516 +    // Is that point already specified?
 199.517 +    if (gbd ->Gamut[theta][alpha].Type != GP_EMPTY) return TRUE;
 199.518 +
 199.519 +    // Fill close points
 199.520 +    nCloseSectors = FindNearSectors(gbd, alpha, theta, Close);
 199.521 +
 199.522 +
 199.523 +    // Find a central point on the sector
 199.524 +    sp.alpha = (cmsFloat64Number) ((alpha + 0.5) * 360.0) / (SECTORS);
 199.525 +    sp.theta = (cmsFloat64Number) ((theta + 0.5) * 180.0) / (SECTORS);
 199.526 +    sp.r     = 50.0;
 199.527 +
 199.528 +    // Convert to Cartesian
 199.529 +    ToCartesian(&Lab, &sp);
 199.530 +
 199.531 +    // Create a ray line from centre to this point
 199.532 +    _cmsVEC3init(&Centre, 50.0, 0, 0);
 199.533 +    LineOf2Points(&ray, &Lab, &Centre);
 199.534 +
 199.535 +    // For all close sectors
 199.536 +    closel.r = 0.0;
 199.537 +    closel.alpha = 0;
 199.538 +    closel.theta = 0;
 199.539 +
 199.540 +    for (k=0; k < nCloseSectors; k++) {
 199.541 +
 199.542 +        for(m = k+1; m < nCloseSectors; m++) {
 199.543 +
 199.544 +            cmsVEC3 temp, a1, a2;
 199.545 +
 199.546 +            // A line from sector to sector
 199.547 +            ToCartesian(&a1, &Close[k]->p);
 199.548 +            ToCartesian(&a2, &Close[m]->p);
 199.549 +
 199.550 +            LineOf2Points(&edge, &a1, &a2);
 199.551 +
 199.552 +            // Find a line
 199.553 +            ClosestLineToLine(&temp, &ray, &edge);
 199.554 +
 199.555 +            // Convert to spherical
 199.556 +            ToSpherical(&templ, &temp);
 199.557 +
 199.558 +
 199.559 +            if ( templ.r > closel.r &&
 199.560 +                 templ.theta >= (theta*180.0/SECTORS) &&
 199.561 +                 templ.theta <= ((theta+1)*180.0/SECTORS) &&
 199.562 +                 templ.alpha >= (alpha*360.0/SECTORS) &&
 199.563 +                 templ.alpha <= ((alpha+1)*360.0/SECTORS)) {
 199.564 +
 199.565 +                closel = templ;
 199.566 +            }
 199.567 +        }
 199.568 +    }
 199.569 +
 199.570 +    gbd ->Gamut[theta][alpha].p = closel;
 199.571 +    gbd ->Gamut[theta][alpha].Type = GP_MODELED;
 199.572 +
 199.573 +    return TRUE;
 199.574 +
 199.575 +}
 199.576 +
 199.577 +
 199.578 +// Interpolate missing parts. The algorithm fist computes slices at
 199.579 +// theta=0 and theta=Max.
 199.580 +cmsBool CMSEXPORT cmsGDBCompute(cmsHANDLE hGBD, cmsUInt32Number dwFlags)
 199.581 +{
 199.582 +    int alpha, theta;
 199.583 +    cmsGDB* gbd = (cmsGDB*) hGBD;
 199.584 +
 199.585 +    _cmsAssert(hGBD != NULL);
 199.586 +
 199.587 +    // Interpolate black
 199.588 +    for (alpha = 0; alpha <= SECTORS; alpha++) {
 199.589 +
 199.590 +        if (!InterpolateMissingSector(gbd, alpha, 0)) return FALSE;
 199.591 +    }
 199.592 +
 199.593 +    // Interpolate white
 199.594 +    for (alpha = 0; alpha <= SECTORS; alpha++) {
 199.595 +
 199.596 +        if (!InterpolateMissingSector(gbd, alpha, SECTORS-1)) return FALSE;
 199.597 +    }
 199.598 +
 199.599 +
 199.600 +    // Interpolate Mid
 199.601 +    for (theta = 1; theta < SECTORS; theta++) {
 199.602 +        for (alpha = 0; alpha <= SECTORS; alpha++) {
 199.603 +
 199.604 +            if (!InterpolateMissingSector(gbd, alpha, theta)) return FALSE;
 199.605 +        }
 199.606 +    }
 199.607 +
 199.608 +    // Done
 199.609 +    return TRUE;
 199.610 +
 199.611 +    cmsUNUSED_PARAMETER(dwFlags);
 199.612 +}
 199.613 +
 199.614 +
 199.615 +
 199.616 +
 199.617 +// --------------------------------------------------------------------------------------------------------
 199.618 +
 199.619 +// Great for debug, but not suitable for real use
 199.620 +
 199.621 +#if 0
 199.622 +cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
 199.623 +{
 199.624 +    FILE* fp;
 199.625 +    int   i, j;
 199.626 +    cmsGDB* gbd = (cmsGDB*) hGBD;
 199.627 +    cmsGDBPoint* pt;
 199.628 +
 199.629 +    fp = fopen (fname, "wt");
 199.630 +    if (fp == NULL)
 199.631 +        return FALSE;
 199.632 +
 199.633 +    fprintf (fp, "#VRML V2.0 utf8\n");
 199.634 +
 199.635 +    // set the viewing orientation and distance
 199.636 +    fprintf (fp, "DEF CamTest Group {\n");
 199.637 +    fprintf (fp, "\tchildren [\n");
 199.638 +    fprintf (fp, "\t\tDEF Cameras Group {\n");
 199.639 +    fprintf (fp, "\t\t\tchildren [\n");
 199.640 +    fprintf (fp, "\t\t\t\tDEF DefaultView Viewpoint {\n");
 199.641 +    fprintf (fp, "\t\t\t\t\tposition 0 0 340\n");
 199.642 +    fprintf (fp, "\t\t\t\t\torientation 0 0 1 0\n");
 199.643 +    fprintf (fp, "\t\t\t\t\tdescription \"default view\"\n");
 199.644 +    fprintf (fp, "\t\t\t\t}\n");
 199.645 +    fprintf (fp, "\t\t\t]\n");
 199.646 +    fprintf (fp, "\t\t},\n");
 199.647 +    fprintf (fp, "\t]\n");
 199.648 +    fprintf (fp, "}\n");
 199.649 +
 199.650 +    // Output the background stuff
 199.651 +    fprintf (fp, "Background {\n");
 199.652 +    fprintf (fp, "\tskyColor [\n");
 199.653 +    fprintf (fp, "\t\t.5 .5 .5\n");
 199.654 +    fprintf (fp, "\t]\n");
 199.655 +    fprintf (fp, "}\n");
 199.656 +
 199.657 +    // Output the shape stuff
 199.658 +    fprintf (fp, "Transform {\n");
 199.659 +    fprintf (fp, "\tscale .3 .3 .3\n");
 199.660 +    fprintf (fp, "\tchildren [\n");
 199.661 +
 199.662 +    // Draw the axes as a shape:
 199.663 +    fprintf (fp, "\t\tShape {\n");
 199.664 +    fprintf (fp, "\t\t\tappearance Appearance {\n");
 199.665 +    fprintf (fp, "\t\t\t\tmaterial Material {\n");
 199.666 +    fprintf (fp, "\t\t\t\t\tdiffuseColor 0 0.8 0\n");
 199.667 +    fprintf (fp, "\t\t\t\t\temissiveColor 1.0 1.0 1.0\n");
 199.668 +    fprintf (fp, "\t\t\t\t\tshininess 0.8\n");
 199.669 +    fprintf (fp, "\t\t\t\t}\n");
 199.670 +    fprintf (fp, "\t\t\t}\n");
 199.671 +    fprintf (fp, "\t\t\tgeometry IndexedLineSet {\n");
 199.672 +    fprintf (fp, "\t\t\t\tcoord Coordinate {\n");
 199.673 +    fprintf (fp, "\t\t\t\t\tpoint [\n");
 199.674 +    fprintf (fp, "\t\t\t\t\t0.0 0.0 0.0,\n");
 199.675 +    fprintf (fp, "\t\t\t\t\t%f 0.0 0.0,\n",  255.0);
 199.676 +    fprintf (fp, "\t\t\t\t\t0.0 %f 0.0,\n",  255.0);
 199.677 +    fprintf (fp, "\t\t\t\t\t0.0 0.0 %f]\n",  255.0);
 199.678 +    fprintf (fp, "\t\t\t\t}\n");
 199.679 +    fprintf (fp, "\t\t\t\tcoordIndex [\n");
 199.680 +    fprintf (fp, "\t\t\t\t\t0, 1, -1\n");
 199.681 +    fprintf (fp, "\t\t\t\t\t0, 2, -1\n");
 199.682 +    fprintf (fp, "\t\t\t\t\t0, 3, -1]\n");
 199.683 +    fprintf (fp, "\t\t\t}\n");
 199.684 +    fprintf (fp, "\t\t}\n");
 199.685 +
 199.686 +
 199.687 +    fprintf (fp, "\t\tShape {\n");
 199.688 +    fprintf (fp, "\t\t\tappearance Appearance {\n");
 199.689 +    fprintf (fp, "\t\t\t\tmaterial Material {\n");
 199.690 +    fprintf (fp, "\t\t\t\t\tdiffuseColor 0 0.8 0\n");
 199.691 +    fprintf (fp, "\t\t\t\t\temissiveColor 1 1 1\n");
 199.692 +    fprintf (fp, "\t\t\t\t\tshininess 0.8\n");
 199.693 +    fprintf (fp, "\t\t\t\t}\n");
 199.694 +    fprintf (fp, "\t\t\t}\n");
 199.695 +    fprintf (fp, "\t\t\tgeometry PointSet {\n");
 199.696 +
 199.697 +    // fill in the points here
 199.698 +    fprintf (fp, "\t\t\t\tcoord Coordinate {\n");
 199.699 +    fprintf (fp, "\t\t\t\t\tpoint [\n");
 199.700 +
 199.701 +    // We need to transverse all gamut hull.
 199.702 +    for (i=0; i < SECTORS; i++)
 199.703 +        for (j=0; j < SECTORS; j++) {
 199.704 +
 199.705 +            cmsVEC3 v;
 199.706 +
 199.707 +            pt = &gbd ->Gamut[i][j];
 199.708 +            ToCartesian(&v, &pt ->p);
 199.709 +
 199.710 +            fprintf (fp, "\t\t\t\t\t%g %g %g", v.n[0]+50, v.n[1], v.n[2]);
 199.711 +
 199.712 +            if ((j == SECTORS - 1) && (i == SECTORS - 1))
 199.713 +                fprintf (fp, "]\n");
 199.714 +            else
 199.715 +                fprintf (fp, ",\n");
 199.716 +
 199.717 +        }
 199.718 +
 199.719 +        fprintf (fp, "\t\t\t\t}\n");
 199.720 +
 199.721 +
 199.722 +
 199.723 +    // fill in the face colors
 199.724 +    fprintf (fp, "\t\t\t\tcolor Color {\n");
 199.725 +    fprintf (fp, "\t\t\t\t\tcolor [\n");
 199.726 +
 199.727 +    for (i=0; i < SECTORS; i++)
 199.728 +        for (j=0; j < SECTORS; j++) {
 199.729 +
 199.730 +           cmsVEC3 v;
 199.731 +
 199.732 +            pt = &gbd ->Gamut[i][j];
 199.733 +
 199.734 +
 199.735 +            ToCartesian(&v, &pt ->p);
 199.736 +
 199.737 +
 199.738 +        if (pt ->Type == GP_EMPTY)
 199.739 +            fprintf (fp, "\t\t\t\t\t%g %g %g", 0.0, 0.0, 0.0);
 199.740 +        else
 199.741 +            if (pt ->Type == GP_MODELED)
 199.742 +                fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, .5, .5);
 199.743 +            else {
 199.744 +                fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, 1.0, 1.0);
 199.745 +
 199.746 +            }
 199.747 +
 199.748 +        if ((j == SECTORS - 1) && (i == SECTORS - 1))
 199.749 +                fprintf (fp, "]\n");
 199.750 +            else
 199.751 +                fprintf (fp, ",\n");
 199.752 +    }
 199.753 +    fprintf (fp, "\t\t\t}\n");
 199.754 +
 199.755 +
 199.756 +    fprintf (fp, "\t\t\t}\n");
 199.757 +    fprintf (fp, "\t\t}\n");
 199.758 +    fprintf (fp, "\t]\n");
 199.759 +    fprintf (fp, "}\n");
 199.760 +
 199.761 +    fclose (fp);
 199.762 +
 199.763 +    return TRUE;
 199.764 +}
 199.765 +#endif
   200.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmstypes.c	Fri Sep 24 16:41:32 2010 -0700
   200.3 @@ -0,0 +1,4863 @@
   200.4 +/*
   200.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   200.6 + *
   200.7 + * This code is free software; you can redistribute it and/or modify it
   200.8 + * under the terms of the GNU General Public License version 2 only, as
   200.9 + * published by the Free Software Foundation.  Oracle designates this
  200.10 + * particular file as subject to the "Classpath" exception as provided
  200.11 + * by Oracle in the LICENSE file that accompanied this code.
  200.12 + *
  200.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  200.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  200.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  200.16 + * version 2 for more details (a copy is included in the LICENSE file that
  200.17 + * accompanied this code).
  200.18 + *
  200.19 + * You should have received a copy of the GNU General Public License version
  200.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  200.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  200.22 + *
  200.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  200.24 + * or visit www.oracle.com if you need additional information or have any
  200.25 + * questions.
  200.26 + */
  200.27 +
  200.28 +// This file is available under and governed by the GNU General Public
  200.29 +// License version 2 only, as published by the Free Software Foundation.
  200.30 +// However, the following notice accompanied the original version of this
  200.31 +// file:
  200.32 +//
  200.33 +//---------------------------------------------------------------------------------
  200.34 +//
  200.35 +//  Little Color Management System
  200.36 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  200.37 +//
  200.38 +// Permission is hereby granted, free of charge, to any person obtaining
  200.39 +// a copy of this software and associated documentation files (the "Software"),
  200.40 +// to deal in the Software without restriction, including without limitation
  200.41 +// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  200.42 +// and/or sell copies of the Software, and to permit persons to whom the Software
  200.43 +// is furnished to do so, subject to the following conditions:
  200.44 +//
  200.45 +// The above copyright notice and this permission notice shall be included in
  200.46 +// all copies or substantial portions of the Software.
  200.47 +//
  200.48 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  200.49 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  200.50 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  200.51 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  200.52 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  200.53 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  200.54 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  200.55 +//
  200.56 +//---------------------------------------------------------------------------------
  200.57 +//
  200.58 +
  200.59 +#include "lcms2_internal.h"
  200.60 +
  200.61 +// Tag Serialization  -----------------------------------------------------------------------------
  200.62 +// This file implements every single tag and tag type as described in the ICC spec. Some types
  200.63 +// have been deprecated, like ncl and Data. There is no implementation for those types as there
  200.64 +// are no profiles holding them. The programmer can also extend this list by defining his own types
  200.65 +// by using the appropiate plug-in. There are three types of plug ins regarding that. First type
  200.66 +// allows to define new tags using any existing type. Next plug-in type allows to define new types
  200.67 +// and the third one is very specific: allows to extend the number of elements in the multiprofile
  200.68 +// elements special type.
  200.69 +//--------------------------------------------------------------------------------------------------
  200.70 +
  200.71 +// Some broken types
  200.72 +#define cmsCorbisBrokenXYZtype    ((cmsTagTypeSignature) 0x17A505B8)
  200.73 +#define cmsMonacoBrokenCurveType  ((cmsTagTypeSignature) 0x9478ee00)
  200.74 +
  200.75 +// This is the linked list that keeps track of the defined types
  200.76 +typedef struct _cmsTagTypeLinkedList_st {
  200.77 +
  200.78 +    cmsTagTypeHandler Handler;
  200.79 +    struct _cmsTagTypeLinkedList_st* Next;
  200.80 +
  200.81 +} _cmsTagTypeLinkedList;
  200.82 +
  200.83 +// Some macros to define callbacks.
  200.84 +#define READ_FN(x)  Type_##x##_Read
  200.85 +#define WRITE_FN(x) Type_##x##_Write
  200.86 +#define FREE_FN(x)  Type_##x##_Free
  200.87 +#define DUP_FN(x)   Type_##x##_Dup
  200.88 +
  200.89 +// Helper macro to define a handler. Callbacks do have a fixed naming convention.
  200.90 +#define TYPE_HANDLER(t, x)  { (t), READ_FN(x), WRITE_FN(x), DUP_FN(x), FREE_FN(x) }
  200.91 +
  200.92 +// Helper macro to define a MPE handler. Callbacks do have a fixed naming convention
  200.93 +#define TYPE_MPE_HANDLER(t, x)  { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree }
  200.94 +
  200.95 +// Register a new type handler. This routine is shared between normal types and MPE
  200.96 +static
  200.97 +cmsBool RegisterTypesPlugin(cmsPluginBase* Data, _cmsTagTypeLinkedList* LinkedList, cmsUInt32Number DefaultListCount)
  200.98 +{
  200.99 +    cmsPluginTagType* Plugin = (cmsPluginTagType*) Data;
 200.100 +    _cmsTagTypeLinkedList *pt, *Anterior = NULL;
 200.101 +
 200.102 +    // Calling the function with NULL as plug-in would unregister the plug in.
 200.103 +    if (Data == NULL) {
 200.104 +
 200.105 +        LinkedList[DefaultListCount-1].Next = NULL;
 200.106 +        return TRUE;
 200.107 +    }
 200.108 +
 200.109 +    pt = Anterior = LinkedList;
 200.110 +    while (pt != NULL) {
 200.111 +
 200.112 +        if (Plugin->Handler.Signature == pt -> Handler.Signature) {
 200.113 +            pt ->Handler = Plugin ->Handler;    // Replace old behaviour.
 200.114 +            // Note that since no memory is allocated, unregister does not
 200.115 +            // reset this action.
 200.116 +            return TRUE;
 200.117 +        }
 200.118 +
 200.119 +        Anterior = pt;
 200.120 +        pt = pt ->Next;
 200.121 +    }
 200.122 +
 200.123 +    // Registering happens in plug-in memory pool
 200.124 +    pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(sizeof(_cmsTagTypeLinkedList));
 200.125 +    if (pt == NULL) return FALSE;
 200.126 +
 200.127 +    pt ->Handler   = Plugin ->Handler;
 200.128 +    pt ->Next      = NULL;
 200.129 +
 200.130 +    if (Anterior)
 200.131 +        Anterior -> Next = pt;
 200.132 +
 200.133 +    return TRUE;
 200.134 +}
 200.135 +
 200.136 +// Return handler for a given type or NULL if not found. Shared between normal types and MPE
 200.137 +static
 200.138 +cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* LinkedList)
 200.139 +{
 200.140 +    _cmsTagTypeLinkedList* pt;
 200.141 +
 200.142 +    for (pt = LinkedList;
 200.143 +         pt != NULL;
 200.144 +         pt = pt ->Next) {
 200.145 +
 200.146 +            if (sig == pt -> Handler.Signature) return &pt ->Handler;
 200.147 +    }
 200.148 +
 200.149 +    return NULL;
 200.150 +}
 200.151 +
 200.152 +
 200.153 +// Auxiliar to convert UTF-32 to UTF-16 in some cases
 200.154 +static
 200.155 +cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* Array)
 200.156 +{
 200.157 +    cmsUInt32Number i;
 200.158 +
 200.159 +    _cmsAssert(io != NULL);
 200.160 +    _cmsAssert(Array != NULL);
 200.161 +
 200.162 +    for (i=0; i < n; i++) {
 200.163 +        if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Array[i])) return FALSE;
 200.164 +    }
 200.165 +
 200.166 +    return TRUE;
 200.167 +}
 200.168 +
 200.169 +
 200.170 +// To deal with position tables
 200.171 +typedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self,
 200.172 +                                             cmsIOHANDLER* io,
 200.173 +                                             void* Cargo,
 200.174 +                                             cmsUInt32Number n,
 200.175 +                                             cmsUInt32Number SizeOfTag);
 200.176 +
 200.177 +// Helper function to deal with position tables as decribed in several addendums to ICC spec 4.2
 200.178 +// A table of n elements is written, where first comes n records containing offsets and sizes and
 200.179 +// then a block containing the data itself. This allows to reuse same data in more than one entry
 200.180 +static
 200.181 +cmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
 200.182 +                              cmsIOHANDLER* io,
 200.183 +                              cmsUInt32Number Count,
 200.184 +                              cmsUInt32Number BaseOffset,
 200.185 +                              void *Cargo,
 200.186 +                              PositionTableEntryFn ElementFn)
 200.187 +{
 200.188 +    cmsUInt32Number i;
 200.189 +    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
 200.190 +
 200.191 +    // Let's take the offsets to each element
 200.192 +    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
 200.193 +    if (ElementOffsets == NULL) goto Error;
 200.194 +
 200.195 +    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
 200.196 +    if (ElementSizes == NULL) goto Error;
 200.197 +
 200.198 +    for (i=0; i < Count; i++) {
 200.199 +
 200.200 +        if (!_cmsReadUInt32Number(io, &ElementOffsets[i])) goto Error;
 200.201 +        if (!_cmsReadUInt32Number(io, &ElementSizes[i])) goto Error;
 200.202 +
 200.203 +        ElementOffsets[i] += BaseOffset;
 200.204 +    }
 200.205 +
 200.206 +    // Seek to each element and read it
 200.207 +    for (i=0; i < Count; i++) {
 200.208 +
 200.209 +        if (!io -> Seek(io, ElementOffsets[i])) goto Error;
 200.210 +
 200.211 +        // This is the reader callback
 200.212 +        if (!ElementFn(self, io, Cargo, i, ElementSizes[i])) goto Error;
 200.213 +    }
 200.214 +
 200.215 +    // Success
 200.216 +    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
 200.217 +    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
 200.218 +    return TRUE;
 200.219 +
 200.220 +Error:
 200.221 +    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
 200.222 +    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
 200.223 +    return FALSE;
 200.224 +}
 200.225 +
 200.226 +// Same as anterior, but for write position tables
 200.227 +static
 200.228 +cmsBool WritePositionTable(struct _cms_typehandler_struct* self,
 200.229 +                               cmsIOHANDLER* io,
 200.230 +                                cmsUInt32Number SizeOfTag,
 200.231 +                               cmsUInt32Number Count,
 200.232 +                               cmsUInt32Number BaseOffset,
 200.233 +                               void *Cargo,
 200.234 +                               PositionTableEntryFn ElementFn)
 200.235 +{
 200.236 +    cmsUInt32Number i;
 200.237 +    cmsUInt32Number DirectoryPos, CurrentPos, Before;
 200.238 +    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
 200.239 +
 200.240 +     // Create table
 200.241 +    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
 200.242 +    if (ElementOffsets == NULL) goto Error;
 200.243 +
 200.244 +    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number *));
 200.245 +    if (ElementSizes == NULL) goto Error;
 200.246 +
 200.247 +    // Keep starting position of curve offsets
 200.248 +    DirectoryPos = io ->Tell(io);
 200.249 +
 200.250 +    // Write a fake directory to be filled latter on
 200.251 +    for (i=0; i < Count; i++) {
 200.252 +
 200.253 +        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // Offset
 200.254 +        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // size
 200.255 +    }
 200.256 +
 200.257 +    // Write each element. Keep track of the size as well.
 200.258 +    for (i=0; i < Count; i++) {
 200.259 +
 200.260 +        Before = io ->Tell(io);
 200.261 +        ElementOffsets[i] = Before - BaseOffset;
 200.262 +
 200.263 +        // Callback to write...
 200.264 +        if (!ElementFn(self, io, Cargo, i, SizeOfTag)) goto Error;
 200.265 +
 200.266 +        // Now the size
 200.267 +        ElementSizes[i] = io ->Tell(io) - Before;
 200.268 +    }
 200.269 +
 200.270 +    // Write the directory
 200.271 +    CurrentPos = io ->Tell(io);
 200.272 +    if (!io ->Seek(io, DirectoryPos)) goto Error;
 200.273 +
 200.274 +    for (i=0; i <  Count; i++) {
 200.275 +        if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error;
 200.276 +        if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error;
 200.277 +    }
 200.278 +
 200.279 +    if (!io ->Seek(io, CurrentPos)) goto Error;
 200.280 +
 200.281 +    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
 200.282 +    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
 200.283 +    return TRUE;
 200.284 +
 200.285 +Error:
 200.286 +    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
 200.287 +    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
 200.288 +    return FALSE;
 200.289 +}
 200.290 +
 200.291 +
 200.292 +// ********************************************************************************
 200.293 +// Type XYZ. Only one value is allowed
 200.294 +// ********************************************************************************
 200.295 +
 200.296 +//The XYZType contains an array of three encoded values for the XYZ tristimulus
 200.297 +//values. Tristimulus values must be non-negative. The signed encoding allows for
 200.298 +//implementation optimizations by minimizing the number of fixed formats.
 200.299 +
 200.300 +
 200.301 +static
 200.302 +void *Type_XYZ_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.303 +{
 200.304 +    cmsCIEXYZ* xyz;
 200.305 +
 200.306 +    *nItems = 0;
 200.307 +    xyz = (cmsCIEXYZ*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIEXYZ));
 200.308 +    if (xyz == NULL) return NULL;
 200.309 +
 200.310 +    if (!_cmsReadXYZNumber(io, xyz)) {
 200.311 +        _cmsFree(self ->ContextID, xyz);
 200.312 +        return NULL;
 200.313 +    }
 200.314 +
 200.315 +    *nItems = 1;
 200.316 +    return (void*) xyz;
 200.317 +
 200.318 +    cmsUNUSED_PARAMETER(SizeOfTag);
 200.319 +}
 200.320 +
 200.321 +static
 200.322 +cmsBool  Type_XYZ_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.323 +{
 200.324 +    return _cmsWriteXYZNumber(io, (cmsCIEXYZ*) Ptr);
 200.325 +
 200.326 +    cmsUNUSED_PARAMETER(nItems);
 200.327 +    cmsUNUSED_PARAMETER(self);
 200.328 +}
 200.329 +
 200.330 +static
 200.331 +void* Type_XYZ_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 200.332 +{
 200.333 +    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIEXYZ));
 200.334 +
 200.335 +    cmsUNUSED_PARAMETER(n);
 200.336 +}
 200.337 +
 200.338 +static
 200.339 +void Type_XYZ_Free(struct _cms_typehandler_struct* self, void *Ptr)
 200.340 +{
 200.341 +    _cmsFree(self ->ContextID, Ptr);
 200.342 +}
 200.343 +
 200.344 +
 200.345 +static
 200.346 +cmsTagTypeSignature DecideXYZtype(cmsFloat64Number ICCVersion, const void *Data)
 200.347 +{
 200.348 +    return cmsSigXYZType;
 200.349 +
 200.350 +    cmsUNUSED_PARAMETER(ICCVersion);
 200.351 +    cmsUNUSED_PARAMETER(Data);
 200.352 +}
 200.353 +
 200.354 +
 200.355 +// ********************************************************************************
 200.356 +// Type chromaticity. Only one value is allowed
 200.357 +// ********************************************************************************
 200.358 +// The chromaticity tag type provides basic chromaticity data and type of
 200.359 +// phosphors or colorants of a monitor to applications and utilities.
 200.360 +
 200.361 +static
 200.362 +void *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.363 +{
 200.364 +    cmsCIExyYTRIPLE* chrm;
 200.365 +    cmsUInt16Number nChans, Table;
 200.366 +
 200.367 +    *nItems = 0;
 200.368 +    chrm =  (cmsCIExyYTRIPLE*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIExyYTRIPLE));
 200.369 +    if (chrm == NULL) return NULL;
 200.370 +
 200.371 +    if (!_cmsReadUInt16Number(io, &nChans)) goto Error;
 200.372 +
 200.373 +    // Let's recover from a bug introduced in early versions of lcms1
 200.374 +    if (nChans == 0 && SizeOfTag == 32) {
 200.375 +
 200.376 +        if (!_cmsReadUInt16Number(io, NULL)) goto Error;
 200.377 +        if (!_cmsReadUInt16Number(io, &nChans)) goto Error;
 200.378 +    }
 200.379 +
 200.380 +    if (nChans != 3) goto Error;
 200.381 +
 200.382 +    if (!_cmsReadUInt16Number(io, &Table)) goto Error;
 200.383 +
 200.384 +    if (!_cmsRead15Fixed16Number(io, &chrm ->Red.x)) goto Error;
 200.385 +    if (!_cmsRead15Fixed16Number(io, &chrm ->Red.y)) goto Error;
 200.386 +
 200.387 +    chrm ->Red.Y = 1.0;
 200.388 +
 200.389 +    if (!_cmsRead15Fixed16Number(io, &chrm ->Green.x)) goto Error;
 200.390 +    if (!_cmsRead15Fixed16Number(io, &chrm ->Green.y)) goto Error;
 200.391 +
 200.392 +    chrm ->Green.Y = 1.0;
 200.393 +
 200.394 +    if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.x)) goto Error;
 200.395 +    if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.y)) goto Error;
 200.396 +
 200.397 +    chrm ->Blue.Y = 1.0;
 200.398 +
 200.399 +    *nItems = 1;
 200.400 +    return (void*) chrm;
 200.401 +
 200.402 +Error:
 200.403 +    _cmsFree(self ->ContextID, (void*) chrm);
 200.404 +    return NULL;
 200.405 +
 200.406 +    cmsUNUSED_PARAMETER(SizeOfTag);
 200.407 +}
 200.408 +
 200.409 +static
 200.410 +cmsBool  SaveOneChromaticity(cmsFloat64Number x, cmsFloat64Number y, cmsIOHANDLER* io)
 200.411 +{
 200.412 +    if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(x))) return FALSE;
 200.413 +    if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(y))) return FALSE;
 200.414 +
 200.415 +    return TRUE;
 200.416 +}
 200.417 +
 200.418 +static
 200.419 +cmsBool  Type_Chromaticity_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.420 +{
 200.421 +    cmsCIExyYTRIPLE* chrm = (cmsCIExyYTRIPLE*) Ptr;
 200.422 +
 200.423 +    if (!_cmsWriteUInt16Number(io, 3)) return FALSE;        // nChannels
 200.424 +    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;        // Table
 200.425 +
 200.426 +    if (!SaveOneChromaticity(chrm -> Red.x,   chrm -> Red.y, io)) return FALSE;
 200.427 +    if (!SaveOneChromaticity(chrm -> Green.x, chrm -> Green.y, io)) return FALSE;
 200.428 +    if (!SaveOneChromaticity(chrm -> Blue.x,  chrm -> Blue.y, io)) return FALSE;
 200.429 +
 200.430 +    return TRUE;
 200.431 +
 200.432 +    cmsUNUSED_PARAMETER(nItems);
 200.433 +    cmsUNUSED_PARAMETER(self);
 200.434 +}
 200.435 +
 200.436 +static
 200.437 +void* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 200.438 +{
 200.439 +    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE));
 200.440 +    cmsUNUSED_PARAMETER(n);
 200.441 +}
 200.442 +
 200.443 +static
 200.444 +void Type_Chromaticity_Free(struct _cms_typehandler_struct* self, void* Ptr)
 200.445 +{
 200.446 +    _cmsFree(self ->ContextID, Ptr);
 200.447 +}
 200.448 +
 200.449 +
 200.450 +// ********************************************************************************
 200.451 +// Type cmsSigColorantOrderType
 200.452 +// ********************************************************************************
 200.453 +
 200.454 +// This is an optional tag which specifies the laydown order in which colorants will
 200.455 +// be printed on an n-colorant device. The laydown order may be the same as the
 200.456 +// channel generation order listed in the colorantTableTag or the channel order of a
 200.457 +// colour space such as CMYK, in which case this tag is not needed. When this is not
 200.458 +// the case (for example, ink-towers sometimes use the order KCMY), this tag may be
 200.459 +// used to specify the laydown order of the colorants.
 200.460 +
 200.461 +
 200.462 +static
 200.463 +void *Type_ColorantOrderType_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.464 +{
 200.465 +    cmsUInt8Number* ColorantOrder;
 200.466 +    cmsUInt32Number Count;
 200.467 +
 200.468 +    *nItems = 0;
 200.469 +    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
 200.470 +    if (Count > cmsMAXCHANNELS) return NULL;
 200.471 +
 200.472 +    ColorantOrder = (cmsUInt8Number*) _cmsCalloc(self ->ContextID, cmsMAXCHANNELS, sizeof(cmsUInt8Number));
 200.473 +    if (ColorantOrder == NULL) return NULL;
 200.474 +
 200.475 +    // We use FF as end marker
 200.476 +    memset(ColorantOrder, 0xFF, cmsMAXCHANNELS * sizeof(cmsUInt8Number));
 200.477 +
 200.478 +    if (io ->Read(io, ColorantOrder, sizeof(cmsUInt8Number), Count) != Count) {
 200.479 +
 200.480 +        _cmsFree(self ->ContextID, (void*) ColorantOrder);
 200.481 +        return NULL;
 200.482 +    }
 200.483 +
 200.484 +    *nItems = 1;
 200.485 +    return (void*) ColorantOrder;
 200.486 +
 200.487 +    cmsUNUSED_PARAMETER(SizeOfTag);
 200.488 +}
 200.489 +
 200.490 +static
 200.491 +cmsBool Type_ColorantOrderType_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.492 +{
 200.493 +    cmsUInt8Number*  ColorantOrder = (cmsUInt8Number*) Ptr;
 200.494 +    cmsUInt32Number i, sz, Count;
 200.495 +
 200.496 +    // Get the length
 200.497 +    for (Count=i=0; i < cmsMAXCHANNELS; i++) {
 200.498 +        if (ColorantOrder[i] != 0xFF) Count++;
 200.499 +    }
 200.500 +
 200.501 +    if (!_cmsWriteUInt32Number(io, Count)) return FALSE;
 200.502 +
 200.503 +    sz = Count * sizeof(cmsUInt8Number);
 200.504 +    if (!io -> Write(io, sz, ColorantOrder)) return FALSE;
 200.505 +
 200.506 +    return TRUE;
 200.507 +
 200.508 +    cmsUNUSED_PARAMETER(nItems);
 200.509 +    cmsUNUSED_PARAMETER(self);
 200.510 +}
 200.511 +
 200.512 +static
 200.513 +void* Type_ColorantOrderType_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 200.514 +{
 200.515 +    return _cmsDupMem(self ->ContextID, Ptr, cmsMAXCHANNELS * sizeof(cmsUInt8Number));
 200.516 +
 200.517 +    cmsUNUSED_PARAMETER(n);
 200.518 +}
 200.519 +
 200.520 +
 200.521 +static
 200.522 +void Type_ColorantOrderType_Free(struct _cms_typehandler_struct* self, void* Ptr)
 200.523 +{
 200.524 +    _cmsFree(self ->ContextID, Ptr);
 200.525 +}
 200.526 +
 200.527 +// ********************************************************************************
 200.528 +// Type cmsSigS15Fixed16ArrayType
 200.529 +// ********************************************************************************
 200.530 +// This type represents an array of generic 4-byte/32-bit fixed point quantity.
 200.531 +// The number of values is determined from the size of the tag.
 200.532 +
 200.533 +static
 200.534 +void *Type_S15Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.535 +{
 200.536 +    cmsFloat64Number*  array_double;
 200.537 +    cmsUInt32Number i, n;
 200.538 +
 200.539 +    *nItems = 0;
 200.540 +    n = SizeOfTag / sizeof(cmsUInt32Number);
 200.541 +    array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number));
 200.542 +    if (array_double == NULL) return NULL;
 200.543 +
 200.544 +    for (i=0; i < n; i++) {
 200.545 +
 200.546 +        if (!_cmsRead15Fixed16Number(io, &array_double[i])) {
 200.547 +
 200.548 +            _cmsFree(self ->ContextID, array_double);
 200.549 +            return NULL;
 200.550 +        }
 200.551 +    }
 200.552 +
 200.553 +    *nItems = n;
 200.554 +    return (void*) array_double;
 200.555 +}
 200.556 +
 200.557 +static
 200.558 +cmsBool Type_S15Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.559 +{
 200.560 +    cmsFloat64Number* Value = (cmsFloat64Number*) Ptr;
 200.561 +    cmsUInt32Number i;
 200.562 +
 200.563 +    for (i=0; i < nItems; i++) {
 200.564 +
 200.565 +        if (!_cmsWrite15Fixed16Number(io, Value[i])) return FALSE;
 200.566 +    }
 200.567 +
 200.568 +    return TRUE;
 200.569 +
 200.570 +    cmsUNUSED_PARAMETER(self);
 200.571 +}
 200.572 +
 200.573 +static
 200.574 +void* Type_S15Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 200.575 +{
 200.576 +    return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number));
 200.577 +}
 200.578 +
 200.579 +
 200.580 +static
 200.581 +void Type_S15Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr)
 200.582 +{
 200.583 +    _cmsFree(self ->ContextID, Ptr);
 200.584 +}
 200.585 +
 200.586 +// ********************************************************************************
 200.587 +// Type cmsSigU16Fixed16ArrayType
 200.588 +// ********************************************************************************
 200.589 +// This type represents an array of generic 4-byte/32-bit quantity.
 200.590 +// The number of values is determined from the size of the tag.
 200.591 +
 200.592 +
 200.593 +static
 200.594 +void *Type_U16Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.595 +{
 200.596 +    cmsFloat64Number*  array_double;
 200.597 +    cmsUInt32Number v;
 200.598 +    cmsUInt32Number i, n;
 200.599 +
 200.600 +    *nItems = 0;
 200.601 +    n = SizeOfTag / sizeof(cmsUInt32Number);
 200.602 +    array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number));
 200.603 +    if (array_double == NULL) return NULL;
 200.604 +
 200.605 +    for (i=0; i < n; i++) {
 200.606 +
 200.607 +        if (!_cmsReadUInt32Number(io, &v)) {
 200.608 +            _cmsFree(self ->ContextID, (void*) array_double);
 200.609 +            return NULL;
 200.610 +        }
 200.611 +
 200.612 +        // Convert to cmsFloat64Number
 200.613 +        array_double[i] =  (cmsFloat64Number) (v / 65536.0);
 200.614 +    }
 200.615 +
 200.616 +    *nItems = n;
 200.617 +    return (void*) array_double;
 200.618 +}
 200.619 +
 200.620 +static
 200.621 +cmsBool Type_U16Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.622 +{
 200.623 +    cmsFloat64Number* Value = (cmsFloat64Number*) Ptr;
 200.624 +    cmsUInt32Number i;
 200.625 +
 200.626 +    for (i=0; i < nItems; i++) {
 200.627 +
 200.628 +        cmsUInt32Number v = (cmsUInt32Number) floor(Value[i]*65536.0 + 0.5);
 200.629 +
 200.630 +        if (!_cmsWriteUInt32Number(io, v)) return FALSE;
 200.631 +    }
 200.632 +
 200.633 +    return TRUE;
 200.634 +
 200.635 +    cmsUNUSED_PARAMETER(self);
 200.636 +}
 200.637 +
 200.638 +
 200.639 +static
 200.640 +void* Type_U16Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 200.641 +{
 200.642 +    return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number));
 200.643 +}
 200.644 +
 200.645 +static
 200.646 +void Type_U16Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr)
 200.647 +{
 200.648 +    _cmsFree(self ->ContextID, Ptr);
 200.649 +}
 200.650 +
 200.651 +// ********************************************************************************
 200.652 +// Type cmsSigSignatureType
 200.653 +// ********************************************************************************
 200.654 +//
 200.655 +// The signatureType contains a four-byte sequence, Sequences of less than four
 200.656 +// characters are padded at the end with spaces, 20h.
 200.657 +// Typically this type is used for registered tags that can be displayed on many
 200.658 +// development systems as a sequence of four characters.
 200.659 +
 200.660 +static
 200.661 +void *Type_Signature_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.662 +{
 200.663 +    cmsSignature* SigPtr = (cmsSignature*) _cmsMalloc(self ->ContextID, sizeof(cmsSignature));
 200.664 +    if (SigPtr == NULL) return NULL;
 200.665 +
 200.666 +     if (!_cmsReadUInt32Number(io, SigPtr)) return NULL;
 200.667 +     *nItems = 1;
 200.668 +
 200.669 +     return SigPtr;
 200.670 +
 200.671 +     cmsUNUSED_PARAMETER(SizeOfTag);
 200.672 +}
 200.673 +
 200.674 +static
 200.675 +cmsBool  Type_Signature_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.676 +{
 200.677 +    cmsSignature* SigPtr = (cmsSignature*) Ptr;
 200.678 +
 200.679 +    return _cmsWriteUInt32Number(io, *SigPtr);
 200.680 +
 200.681 +    cmsUNUSED_PARAMETER(nItems);
 200.682 +    cmsUNUSED_PARAMETER(self);
 200.683 +}
 200.684 +
 200.685 +static
 200.686 +void* Type_Signature_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 200.687 +{
 200.688 +    return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsSignature));
 200.689 +}
 200.690 +
 200.691 +static
 200.692 +void Type_Signature_Free(struct _cms_typehandler_struct* self, void* Ptr)
 200.693 +{
 200.694 +    _cmsFree(self ->ContextID, Ptr);
 200.695 +}
 200.696 +
 200.697 +
 200.698 +// ********************************************************************************
 200.699 +// Type cmsSigTextType
 200.700 +// ********************************************************************************
 200.701 +//
 200.702 +// The textType is a simple text structure that contains a 7-bit ASCII text string.
 200.703 +// The length of the string is obtained by subtracting 8 from the element size portion
 200.704 +// of the tag itself. This string must be terminated with a 00h byte.
 200.705 +
 200.706 +static
 200.707 +void *Type_Text_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.708 +{
 200.709 +    char* Text = NULL;
 200.710 +    cmsMLU* mlu = NULL;
 200.711 +
 200.712 +    // Create a container
 200.713 +    mlu = cmsMLUalloc(self ->ContextID, 1);
 200.714 +    if (mlu == NULL) return NULL;
 200.715 +
 200.716 +    *nItems = 0;
 200.717 +
 200.718 +    // We need to store the "\0" at the end, so +1
 200.719 +    Text = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
 200.720 +    if (Text == NULL) goto Error;
 200.721 +
 200.722 +    if (io -> Read(io, Text, sizeof(char), SizeOfTag) != SizeOfTag) goto Error;
 200.723 +
 200.724 +    // Make sure text is properly ended
 200.725 +    Text[SizeOfTag] = 0;
 200.726 +    *nItems = 1;
 200.727 +
 200.728 +    // Keep the result
 200.729 +    if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error;
 200.730 +
 200.731 +    _cmsFree(self ->ContextID, Text);
 200.732 +    return (void*) mlu;
 200.733 +
 200.734 +Error:
 200.735 +    if (mlu != NULL)
 200.736 +        cmsMLUfree(mlu);
 200.737 +    if (Text != NULL)
 200.738 +        _cmsFree(self ->ContextID, Text);
 200.739 +
 200.740 +    return NULL;
 200.741 +}
 200.742 +
 200.743 +// The conversion implies to choose a language. So, we choose the actual language.
 200.744 +static
 200.745 +cmsBool Type_Text_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.746 +{
 200.747 +    cmsMLU* mlu = (cmsMLU*) Ptr;
 200.748 +    cmsUInt32Number size;
 200.749 +    cmsBool  rc;
 200.750 +    char* Text;
 200.751 +
 200.752 +    // Get the size of the string. Note there is an extra "\0" at the end
 200.753 +    size = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
 200.754 +    if (size == 0) return FALSE;       // Cannot be zero!
 200.755 +
 200.756 +    // Create memory
 200.757 +    Text = (char*) _cmsMalloc(self ->ContextID, size);
 200.758 +    cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size);
 200.759 +
 200.760 +    // Write it, including separator
 200.761 +    rc = io ->Write(io, size, Text);
 200.762 +
 200.763 +    _cmsFree(self ->ContextID, Text);
 200.764 +    return rc;
 200.765 +
 200.766 +    cmsUNUSED_PARAMETER(nItems);
 200.767 +}
 200.768 +
 200.769 +static
 200.770 +void* Type_Text_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 200.771 +{
 200.772 +    return (void*) cmsMLUdup((cmsMLU*) Ptr);
 200.773 +
 200.774 +    cmsUNUSED_PARAMETER(n);
 200.775 +    cmsUNUSED_PARAMETER(self);
 200.776 +}
 200.777 +
 200.778 +
 200.779 +static
 200.780 +void Type_Text_Free(struct _cms_typehandler_struct* self, void* Ptr)
 200.781 +{
 200.782 +    cmsMLU* mlu = (cmsMLU*) Ptr;
 200.783 +    cmsMLUfree(mlu);
 200.784 +    return;
 200.785 +
 200.786 +    cmsUNUSED_PARAMETER(self);
 200.787 +}
 200.788 +
 200.789 +static
 200.790 +cmsTagTypeSignature DecideTextType(cmsFloat64Number ICCVersion, const void *Data)
 200.791 +{
 200.792 +    if (ICCVersion >= 4.0)
 200.793 +        return cmsSigMultiLocalizedUnicodeType;
 200.794 +
 200.795 +    return cmsSigTextType;
 200.796 +
 200.797 +    cmsUNUSED_PARAMETER(Data);
 200.798 +}
 200.799 +
 200.800 +
 200.801 +// ********************************************************************************
 200.802 +// Type cmsSigDataType
 200.803 +// ********************************************************************************
 200.804 +
 200.805 +// General purpose data type
 200.806 +static
 200.807 +void *Type_Data_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.808 +{
 200.809 +    cmsICCData* BinData;
 200.810 +    cmsUInt32Number LenOfData;
 200.811 +
 200.812 +    *nItems = 0;
 200.813 +    LenOfData = SizeOfTag - sizeof(cmsUInt32Number);
 200.814 +
 200.815 +    BinData = (cmsICCData*) _cmsMalloc(self ->ContextID, sizeof(cmsICCData) + LenOfData - 1);
 200.816 +    if (BinData == NULL) return NULL;
 200.817 +
 200.818 +    BinData ->len = LenOfData;
 200.819 +    if (!_cmsReadUInt32Number(io, &BinData->flag)) return NULL;
 200.820 +
 200.821 +    if (io -> Read(io, BinData ->data, sizeof(cmsUInt8Number), LenOfData) != LenOfData) {
 200.822 +
 200.823 +        _cmsFree(self ->ContextID, BinData);
 200.824 +        return NULL;
 200.825 +    }
 200.826 +
 200.827 +    *nItems = 1;
 200.828 +
 200.829 +    return (void*) BinData;
 200.830 +}
 200.831 +
 200.832 +
 200.833 +static
 200.834 +cmsBool Type_Data_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.835 +{
 200.836 +   cmsICCData* BinData = (cmsICCData*) Ptr;
 200.837 +
 200.838 +   if (!_cmsWriteUInt32Number(io, BinData ->flag)) return FALSE;
 200.839 +
 200.840 +   return io ->Write(io, BinData ->len, BinData ->data);
 200.841 +
 200.842 +   cmsUNUSED_PARAMETER(nItems);
 200.843 +   cmsUNUSED_PARAMETER(self);
 200.844 +}
 200.845 +
 200.846 +
 200.847 +static
 200.848 +void* Type_Data_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
 200.849 +{
 200.850 +    cmsICCData* BinData = (cmsICCData*) Ptr;
 200.851 +
 200.852 +    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCData) + BinData ->len - 1);
 200.853 +
 200.854 +    cmsUNUSED_PARAMETER(n);
 200.855 +}
 200.856 +
 200.857 +static
 200.858 +void Type_Data_Free(struct _cms_typehandler_struct* self, void* Ptr)
 200.859 +{
 200.860 +    _cmsFree(self ->ContextID, Ptr);
 200.861 +}
 200.862 +
 200.863 +// ********************************************************************************
 200.864 +// Type cmsSigTextDescriptionType
 200.865 +// ********************************************************************************
 200.866 +
 200.867 +static
 200.868 +void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 200.869 +{
 200.870 +    char* Text = NULL;
 200.871 +    cmsMLU* mlu = NULL;
 200.872 +    cmsUInt32Number  AsciiCount;
 200.873 +    cmsUInt32Number  i, UnicodeCode, UnicodeCount;
 200.874 +    cmsUInt16Number  ScriptCodeCode, Dummy;
 200.875 +    cmsUInt8Number   ScriptCodeCount;
 200.876 +
 200.877 +    *nItems = 0;
 200.878 +
 200.879 +    //  One dword should be there
 200.880 +    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
 200.881 +
 200.882 +    // Read len of ASCII
 200.883 +    if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL;
 200.884 +    SizeOfTag -= sizeof(cmsUInt32Number);
 200.885 +
 200.886 +    // Check for size
 200.887 +    if (SizeOfTag < AsciiCount) return NULL;
 200.888 +
 200.889 +    // All seems Ok, allocate the container
 200.890 +    mlu = cmsMLUalloc(self ->ContextID, 1);
 200.891 +    if (mlu == NULL) return NULL;
 200.892 +
 200.893 +    // As many memory as size of tag
 200.894 +    Text = (char*) _cmsMalloc(self ->ContextID, AsciiCount + 1);
 200.895 +    if (Text == NULL) goto Error;
 200.896 +
 200.897 +    // Read it
 200.898 +    if (io ->Read(io, Text, sizeof(char), AsciiCount) != AsciiCount) goto Error;
 200.899 +    SizeOfTag -= AsciiCount;
 200.900 +
 200.901 +    // Make sure there is a terminator
 200.902 +    Text[AsciiCount] = 0;
 200.903 +
 200.904 +    // Set the MLU entry. From here we can be tolerant to wrong types
 200.905 +    if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error;
 200.906 +    _cmsFree(self ->ContextID, (void*) Text);
 200.907 +    Text = NULL;
 200.908 +
 200.909 +    // Skip Unicode code
 200.910 +    if (SizeOfTag < 2* sizeof(cmsUInt32Number)) goto Done;
 200.911 +    if (!_cmsReadUInt32Number(io, &UnicodeCode)) goto Done;
 200.912 +    if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
 200.913 +    SizeOfTag -= 2* sizeof(cmsUInt32Number);
 200.914 +
 200.915 +    if (SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
 200.916 +
 200.917 +    for (i=0; i < UnicodeCount; i++) {
 200.918 +        if (!io ->Read(io, &Dummy, sizeof(cmsUInt16Number), 1)) goto Done;
 200.919 +    }
 200.920 +    SizeOfTag -= UnicodeCount*sizeof(cmsUInt16Number);
 200.921 +
 200.922 +    // Skip ScriptCode code if present. Some buggy profiles does have less
 200.923 +    // data that stricttly required. We need to skip it as this type may come
 200.924 +    // embedded in other types.
 200.925 +
 200.926 +    if (SizeOfTag >= sizeof(cmsUInt16Number) + sizeof(cmsUInt8Number) + 67) {
 200.927 +
 200.928 +        if (!_cmsReadUInt16Number(io, &ScriptCodeCode)) goto Done;
 200.929 +        if (!_cmsReadUInt8Number(io,  &ScriptCodeCount)) goto Done;
 200.930 +
 200.931 +        // Skip rest of tag
 200.932 +        for (i=0; i < 67; i++) {
 200.933 +            if (!io ->Read(io, &Dummy, sizeof(cmsUInt8Number), 1)) goto Error;
 200.934 +        }
 200.935 +    }
 200.936 +
 200.937 +Done:
 200.938 +
 200.939 +    *nItems = 1;
 200.940 +    return mlu;
 200.941 +
 200.942 +Error:
 200.943 +    if (Text) _cmsFree(self ->ContextID, (void*) Text);
 200.944 +    if (mlu) cmsMLUfree(mlu);
 200.945 +    return NULL;
 200.946 +}
 200.947 +
 200.948 +
 200.949 +// This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
 200.950 +static
 200.951 +cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 200.952 +{
 200.953 +    cmsMLU* mlu = (cmsMLU*) Ptr;
 200.954 +    char *Text = NULL;
 200.955 +    wchar_t *Wide = NULL;
 200.956 +    cmsUInt32Number len, len_aligned, len_filler_alignment;
 200.957 +    cmsBool  rc = FALSE;
 200.958 +    char Filler[68];
 200.959 +
 200.960 +    // Used below for writting zeroes
 200.961 +    memset(Filler, 0, sizeof(Filler));
 200.962 +
 200.963 +    // Get the len of string
 200.964 +    len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
 200.965 +
 200.966 +    // From ICC3.4: It has been found that textDescriptionType can contain misaligned data
 200.967 +    //(see clause 4.1 for the definition of “aligned”). Because the Unicode language
 200.968 +    // code and Unicode count immediately follow the ASCII description, their
 200.969 +    // alignment is not correct if the ASCII count is not a multiple of four. The
 200.970 +    // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and
 200.971 +    // writing software must be written carefully in order to handle these alignment
 200.972 +    // problems.
 200.973 +
 200.974 +    // Compute an aligned size
 200.975 +    len_aligned = _cmsALIGNLONG(len);
 200.976 +    len_filler_alignment = len_aligned - len;
 200.977 +
 200.978 +    // Null strings
 200.979 +    if (len <= 0) {
 200.980 +
 200.981 +        Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
 200.982 +        Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
 200.983 +    }
 200.984 +    else {
 200.985 +        // Create independent buffers
 200.986 +        Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));
 200.987 +        if (Text == NULL) goto Error;
 200.988 +
 200.989 +        Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t));
 200.990 +        if (Wide == NULL) goto Error;
 200.991 +
 200.992 +        // Get both representations.
 200.993 +        cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry,  Text, len * sizeof(char));
 200.994 +        cmsMLUgetWide(mlu,  cmsNoLanguage, cmsNoCountry,  Wide, len * sizeof(wchar_t));
 200.995 +    }
 200.996 +
 200.997 +  // * cmsUInt32Number       count;          * Description length
 200.998 +  // * cmsInt8Number         desc[count]     * NULL terminated ascii string
 200.999 +  // * cmsUInt32Number       ucLangCode;     * UniCode language code
200.1000 +  // * cmsUInt32Number       ucCount;        * UniCode description length
200.1001 +  // * cmsInt16Number        ucDesc[ucCount];* The UniCode description
200.1002 +  // * cmsUInt16Number       scCode;         * ScriptCode code
200.1003 +  // * cmsUInt8Number        scCount;        * ScriptCode count
200.1004 +  // * cmsInt8Number         scDesc[67];     * ScriptCode Description
200.1005 +
200.1006 +    if (!_cmsWriteUInt32Number(io, len_aligned)) goto Error;
200.1007 +    if (!io ->Write(io, len, Text)) goto Error;
200.1008 +    if (!io ->Write(io, len_filler_alignment, Filler)) goto Error;
200.1009 +
200.1010 +    if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // ucLanguageCode
200.1011 +
200.1012 +    // This part is tricky: we need an aligned tag size, and the ScriptCode part
200.1013 +    // takes 70 bytes, so we need 2 extra bytes to do the alignment
200.1014 +
200.1015 +    if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error;
200.1016 +
200.1017 +    // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
200.1018 +    if (!_cmsWriteWCharArray(io, len, Wide)) goto Error;
200.1019 +    if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error;
200.1020 +
200.1021 +    // ScriptCode Code & count (unused)
200.1022 +    if (!_cmsWriteUInt16Number(io, 0)) goto Error;
200.1023 +    if (!_cmsWriteUInt8Number(io, 0)) goto Error;
200.1024 +
200.1025 +    if (!io ->Write(io, 67, Filler)) goto Error;
200.1026 +
200.1027 +    rc = TRUE;
200.1028 +
200.1029 +Error:
200.1030 +    if (Text) _cmsFree(self ->ContextID, Text);
200.1031 +    if (Wide) _cmsFree(self ->ContextID, Wide);
200.1032 +
200.1033 +    return rc;
200.1034 +
200.1035 +    cmsUNUSED_PARAMETER(nItems);
200.1036 +}
200.1037 +
200.1038 +
200.1039 +static
200.1040 +void* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.1041 +{
200.1042 +    return (void*) cmsMLUdup((cmsMLU*) Ptr);
200.1043 +
200.1044 +    cmsUNUSED_PARAMETER(n);
200.1045 +    cmsUNUSED_PARAMETER(self);
200.1046 +}
200.1047 +
200.1048 +static
200.1049 +void Type_Text_Description_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.1050 +{
200.1051 +    cmsMLU* mlu = (cmsMLU*) Ptr;
200.1052 +
200.1053 +    cmsMLUfree(mlu);
200.1054 +    return;
200.1055 +
200.1056 +    cmsUNUSED_PARAMETER(self);
200.1057 +}
200.1058 +
200.1059 +
200.1060 +static
200.1061 +cmsTagTypeSignature DecideTextDescType(cmsFloat64Number ICCVersion, const void *Data)
200.1062 +{
200.1063 +    if (ICCVersion >= 4.0)
200.1064 +        return cmsSigMultiLocalizedUnicodeType;
200.1065 +
200.1066 +    return cmsSigTextDescriptionType;
200.1067 +
200.1068 +    cmsUNUSED_PARAMETER(Data);
200.1069 +}
200.1070 +
200.1071 +
200.1072 +// ********************************************************************************
200.1073 +// Type cmsSigCurveType
200.1074 +// ********************************************************************************
200.1075 +
200.1076 +static
200.1077 +void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.1078 +{
200.1079 +    cmsUInt32Number Count;
200.1080 +    cmsToneCurve* NewGamma;
200.1081 +    cmsUInt16Number Linear[2] = { 0, 0xffff };
200.1082 +
200.1083 +
200.1084 +    *nItems = 0;
200.1085 +    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
200.1086 +
200.1087 +    switch (Count) {
200.1088 +
200.1089 +           case 0:   // Linear.
200.1090 +
200.1091 +               NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, 2, Linear);
200.1092 +               if (!NewGamma) return NULL;
200.1093 +               *nItems = 1;
200.1094 +               return NewGamma;
200.1095 +
200.1096 +           case 1:  // Specified as the exponent of gamma function
200.1097 +               {
200.1098 +                   cmsUInt16Number SingleGammaFixed;
200.1099 +                   cmsFloat64Number SingleGamma;
200.1100 +
200.1101 +                   if (!_cmsReadUInt16Number(io, &SingleGammaFixed)) return NULL;
200.1102 +                   SingleGamma = _cms8Fixed8toDouble(SingleGammaFixed);
200.1103 +
200.1104 +                   *nItems = 1;
200.1105 +                   return cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
200.1106 +               }
200.1107 +
200.1108 +           default:  // Curve
200.1109 +
200.1110 +               NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL);
200.1111 +               if (!NewGamma) return NULL;
200.1112 +
200.1113 +               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL;
200.1114 +
200.1115 +               *nItems = 1;
200.1116 +               return NewGamma;
200.1117 +    }
200.1118 +
200.1119 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.1120 +}
200.1121 +
200.1122 +
200.1123 +static
200.1124 +cmsBool  Type_Curve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.1125 +{
200.1126 +    cmsToneCurve* Curve = (cmsToneCurve*) Ptr;
200.1127 +
200.1128 +    if (Curve ->nSegments == 1 && Curve ->Segments[0].Type == 1) {
200.1129 +
200.1130 +            // Single gamma, preserve number
200.1131 +            cmsUInt16Number SingleGammaFixed = _cmsDoubleTo8Fixed8(Curve ->Segments[0].Params[0]);
200.1132 +
200.1133 +            if (!_cmsWriteUInt32Number(io, 1)) return FALSE;
200.1134 +            if (!_cmsWriteUInt16Number(io, SingleGammaFixed)) return FALSE;
200.1135 +            return TRUE;
200.1136 +
200.1137 +    }
200.1138 +
200.1139 +    if (!_cmsWriteUInt32Number(io, Curve ->nEntries)) return FALSE;
200.1140 +    return _cmsWriteUInt16Array(io, Curve ->nEntries, Curve ->Table16);
200.1141 +
200.1142 +    cmsUNUSED_PARAMETER(nItems);
200.1143 +    cmsUNUSED_PARAMETER(self);
200.1144 +}
200.1145 +
200.1146 +
200.1147 +static
200.1148 +void* Type_Curve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.1149 +{
200.1150 +    return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr);
200.1151 +
200.1152 +    cmsUNUSED_PARAMETER(n);
200.1153 +    cmsUNUSED_PARAMETER(self);
200.1154 +}
200.1155 +
200.1156 +static
200.1157 +void Type_Curve_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.1158 +{
200.1159 +    cmsToneCurve* gamma = (cmsToneCurve*) Ptr;
200.1160 +
200.1161 +    cmsFreeToneCurve(gamma);
200.1162 +    return;
200.1163 +
200.1164 +    cmsUNUSED_PARAMETER(self);
200.1165 +}
200.1166 +
200.1167 +
200.1168 +// ********************************************************************************
200.1169 +// Type cmsSigParametricCurveType
200.1170 +// ********************************************************************************
200.1171 +
200.1172 +
200.1173 +// Decide which curve type to use on writting
200.1174 +static
200.1175 +cmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Data)
200.1176 +{
200.1177 +    cmsToneCurve* Curve = (cmsToneCurve*) Data;
200.1178 +
200.1179 +    if (ICCVersion < 4.0) return cmsSigCurveType;
200.1180 +    if (Curve ->nSegments != 1) return cmsSigCurveType;          // Only 1-segment curves can be saved as parametric
200.1181 +    if (Curve ->Segments[0].Type < 0) return cmsSigCurveType;    // Only non-inverted curves
200.1182 +
200.1183 +    return cmsSigParametricCurveType;
200.1184 +}
200.1185 +
200.1186 +static
200.1187 +void *Type_ParametricCurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.1188 +{
200.1189 +    static const int ParamsByType[] = { 1, 3, 4, 5, 7 };
200.1190 +    cmsFloat64Number Params[10];
200.1191 +    cmsUInt16Number Type;
200.1192 +    int i, n;
200.1193 +    cmsToneCurve* NewGamma;
200.1194 +
200.1195 +    if (!_cmsReadUInt16Number(io, &Type)) return NULL;
200.1196 +    if (!_cmsReadUInt16Number(io, NULL)) return NULL;   // Reserved
200.1197 +
200.1198 +    if (Type > 4) {
200.1199 +
200.1200 +        cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown parametric curve type '%d'", Type);
200.1201 +        return NULL;
200.1202 +    }
200.1203 +
200.1204 +    memset(Params, 0, sizeof(Params));
200.1205 +    n = ParamsByType[Type];
200.1206 +
200.1207 +    for (i=0; i < n; i++) {
200.1208 +
200.1209 +        if (!_cmsRead15Fixed16Number(io, &Params[i])) return NULL;
200.1210 +    }
200.1211 +
200.1212 +    NewGamma = cmsBuildParametricToneCurve(self ->ContextID, Type+1, Params);
200.1213 +
200.1214 +    *nItems = 1;
200.1215 +    return NewGamma;
200.1216 +
200.1217 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.1218 +}
200.1219 +
200.1220 +
200.1221 +static
200.1222 +cmsBool  Type_ParametricCurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.1223 +{
200.1224 +    cmsToneCurve* Curve = (cmsToneCurve*) Ptr;
200.1225 +    int i, nParams;
200.1226 +    static const int ParamsByType[] = { 0, 1, 3, 4, 5, 7 };
200.1227 +
200.1228 +
200.1229 +    if (Curve ->nSegments > 1 || Curve -> Segments[0].Type < 1) {
200.1230 +
200.1231 +        cmsSignalError(self->ContextID, 0, "Multisegment or Inverted parametric curves cannot be written");
200.1232 +        return FALSE;
200.1233 +    }
200.1234 +
200.1235 +    nParams = ParamsByType[Curve ->Segments[0].Type];
200.1236 +
200.1237 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) (Curve ->Segments[0].Type - 1))) return FALSE;
200.1238 +    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;        // Reserved
200.1239 +
200.1240 +    for (i=0; i < nParams; i++) {
200.1241 +
200.1242 +        if (!_cmsWrite15Fixed16Number(io, Curve -> Segments[0].Params[i])) return FALSE;
200.1243 +    }
200.1244 +
200.1245 +    return TRUE;
200.1246 +
200.1247 +    cmsUNUSED_PARAMETER(nItems);
200.1248 +}
200.1249 +
200.1250 +static
200.1251 +void* Type_ParametricCurve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.1252 +{
200.1253 +    return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr);
200.1254 +
200.1255 +    cmsUNUSED_PARAMETER(n);
200.1256 +    cmsUNUSED_PARAMETER(self);
200.1257 +}
200.1258 +
200.1259 +static
200.1260 +void Type_ParametricCurve_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.1261 +{
200.1262 +    cmsToneCurve* gamma = (cmsToneCurve*) Ptr;
200.1263 +
200.1264 +    cmsFreeToneCurve(gamma);
200.1265 +    return;
200.1266 +
200.1267 +    cmsUNUSED_PARAMETER(self);
200.1268 +}
200.1269 +
200.1270 +
200.1271 +// ********************************************************************************
200.1272 +// Type cmsSigDateTimeType
200.1273 +// ********************************************************************************
200.1274 +
200.1275 +// A 12-byte value representation of the time and date, where the byte usage is assigned
200.1276 +// as specified in table 1. The actual values are encoded as 16-bit unsigned integers
200.1277 +// (uInt16Number - see 5.1.6).
200.1278 +//
200.1279 +// All the dateTimeNumber values in a profile shall be in Coordinated Universal Time
200.1280 +// (UTC, also known as GMT or ZULU Time). Profile writers are required to convert local
200.1281 +// time to UTC when setting these values. Programmes that display these values may show
200.1282 +// the dateTimeNumber as UTC, show the equivalent local time (at current locale), or
200.1283 +// display both UTC and local versions of the dateTimeNumber.
200.1284 +
200.1285 +static
200.1286 +void *Type_DateTime_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.1287 +{
200.1288 +    cmsDateTimeNumber timestamp;
200.1289 +    struct tm * NewDateTime;
200.1290 +
200.1291 +    *nItems = 0;
200.1292 +    NewDateTime = (struct tm*) _cmsMalloc(self ->ContextID, sizeof(struct tm));
200.1293 +    if (NewDateTime == NULL) return NULL;
200.1294 +
200.1295 +    if (io->Read(io, &timestamp, sizeof(cmsDateTimeNumber), 1) != 1) return NULL;
200.1296 +
200.1297 +     _cmsDecodeDateTimeNumber(&timestamp, NewDateTime);
200.1298 +
200.1299 +     *nItems = 1;
200.1300 +     return NewDateTime;
200.1301 +
200.1302 +     cmsUNUSED_PARAMETER(SizeOfTag);
200.1303 +}
200.1304 +
200.1305 +
200.1306 +static
200.1307 +cmsBool  Type_DateTime_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.1308 +{
200.1309 +    struct tm * DateTime = (struct tm*) Ptr;
200.1310 +    cmsDateTimeNumber timestamp;
200.1311 +
200.1312 +    _cmsEncodeDateTimeNumber(&timestamp, DateTime);
200.1313 +    if (!io ->Write(io, sizeof(cmsDateTimeNumber), &timestamp)) return FALSE;
200.1314 +
200.1315 +    return TRUE;
200.1316 +
200.1317 +    cmsUNUSED_PARAMETER(nItems);
200.1318 +    cmsUNUSED_PARAMETER(self);
200.1319 +}
200.1320 +
200.1321 +static
200.1322 +void* Type_DateTime_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.1323 +{
200.1324 +    return _cmsDupMem(self ->ContextID, Ptr, sizeof(struct tm));
200.1325 +
200.1326 +    cmsUNUSED_PARAMETER(n);
200.1327 +}
200.1328 +
200.1329 +static
200.1330 +void Type_DateTime_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.1331 +{
200.1332 +    _cmsFree(self ->ContextID, Ptr);
200.1333 +}
200.1334 +
200.1335 +
200.1336 +
200.1337 +// ********************************************************************************
200.1338 +// Type icMeasurementType
200.1339 +// ********************************************************************************
200.1340 +
200.1341 +/*
200.1342 +The measurementType information refers only to the internal profile data and is
200.1343 +meant to provide profile makers an alternative to the default measurement
200.1344 +specifications.
200.1345 +*/
200.1346 +
200.1347 +static
200.1348 +void *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.1349 +{
200.1350 +    cmsICCMeasurementConditions mc;
200.1351 +
200.1352 +    if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL;
200.1353 +    if (!_cmsReadXYZNumber(io,    &mc.Backing)) return NULL;
200.1354 +    if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL;
200.1355 +    if (!_cmsRead15Fixed16Number(io, &mc.Flare)) return NULL;
200.1356 +    if (!_cmsReadUInt32Number(io, &mc.IlluminantType)) return NULL;
200.1357 +
200.1358 +    *nItems = 1;
200.1359 +    return _cmsDupMem(self ->ContextID, &mc, sizeof(cmsICCMeasurementConditions));
200.1360 +
200.1361 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.1362 +}
200.1363 +
200.1364 +
200.1365 +static
200.1366 +cmsBool  Type_Measurement_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.1367 +{
200.1368 +    cmsICCMeasurementConditions* mc =(cmsICCMeasurementConditions*) Ptr;
200.1369 +
200.1370 +    if (!_cmsWriteUInt32Number(io, mc->Observer)) return FALSE;
200.1371 +    if (!_cmsWriteXYZNumber(io,    &mc->Backing)) return FALSE;
200.1372 +    if (!_cmsWriteUInt32Number(io, mc->Geometry)) return FALSE;
200.1373 +    if (!_cmsWrite15Fixed16Number(io, mc->Flare)) return FALSE;
200.1374 +    if (!_cmsWriteUInt32Number(io, mc->IlluminantType)) return FALSE;
200.1375 +
200.1376 +    return TRUE;
200.1377 +
200.1378 +    cmsUNUSED_PARAMETER(nItems);
200.1379 +    cmsUNUSED_PARAMETER(self);
200.1380 +}
200.1381 +
200.1382 +static
200.1383 +void* Type_Measurement_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.1384 +{
200.1385 +     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCMeasurementConditions));
200.1386 +
200.1387 +     cmsUNUSED_PARAMETER(n);
200.1388 +}
200.1389 +
200.1390 +static
200.1391 +void Type_Measurement_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.1392 +{
200.1393 +   _cmsFree(self ->ContextID, Ptr);
200.1394 +}
200.1395 +
200.1396 +
200.1397 +// ********************************************************************************
200.1398 +// Type cmsSigMultiLocalizedUnicodeType
200.1399 +// ********************************************************************************
200.1400 +
200.1401 +//
200.1402 +//   Do NOT trust SizeOfTag as there is an issue on the definition of profileSequenceDescTag. See the TechNote from
200.1403 +//   Max Derhak and Rohit Patil about this: basically the size of the string table should be guessed and cannot be
200.1404 +//   taken from the size of tag if this tag is embedded as part of bigger structures (profileSequenceDescTag, for instance)
200.1405 +//
200.1406 +// FIXME: this doesn't work if sizeof(wchat_t) != 2  !!!
200.1407 +
200.1408 +static
200.1409 +void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.1410 +{
200.1411 +    cmsMLU* mlu;
200.1412 +    cmsUInt32Number Count, RecLen, NumOfWchar;
200.1413 +    cmsUInt32Number SizeOfHeader;
200.1414 +    cmsUInt32Number  Len, Offset;
200.1415 +    cmsUInt32Number  i;
200.1416 +    cmsUInt16Number* Block;
200.1417 +    cmsUInt32Number  BeginOfThisString, EndOfThisString, LargestPosition;
200.1418 +
200.1419 +    *nItems = 0;
200.1420 +    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
200.1421 +    if (!_cmsReadUInt32Number(io, &RecLen)) return NULL;
200.1422 +
200.1423 +    if (RecLen != 12) {
200.1424 +
200.1425 +        cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "multiLocalizedUnicodeType of len != 12 is not supported.");
200.1426 +        return NULL;
200.1427 +    }
200.1428 +
200.1429 +    mlu = cmsMLUalloc(self ->ContextID, Count);
200.1430 +    if (mlu == NULL) return NULL;
200.1431 +
200.1432 +    mlu ->UsedEntries = Count;
200.1433 +
200.1434 +    SizeOfHeader = 12 * Count + sizeof(_cmsTagBase);
200.1435 +    LargestPosition = 0;
200.1436 +
200.1437 +    for (i=0; i < Count; i++) {
200.1438 +
200.1439 +        if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Language)) goto Error;
200.1440 +        if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Country))  goto Error;
200.1441 +
200.1442 +        // Now deal with Len and offset.
200.1443 +        if (!_cmsReadUInt32Number(io, &Len)) goto Error;
200.1444 +        mlu ->Entries[i].Len = Len;
200.1445 +
200.1446 +        if (!_cmsReadUInt32Number(io, &Offset)) goto Error;
200.1447 +
200.1448 +        BeginOfThisString = Offset - SizeOfHeader - 8;
200.1449 +        mlu ->Entries[i].StrW = BeginOfThisString;
200.1450 +
200.1451 +        // To guess maximum size, add offset + len
200.1452 +        EndOfThisString = BeginOfThisString + Len;
200.1453 +        if (EndOfThisString > LargestPosition)
200.1454 +            LargestPosition = EndOfThisString;
200.1455 +    }
200.1456 +
200.1457 +    // Now read the remaining of tag and fill all strings. Substract the directory
200.1458 +    SizeOfTag   = LargestPosition;
200.1459 +
200.1460 +    Block = (cmsUInt16Number*) _cmsMalloc(self ->ContextID, SizeOfTag);
200.1461 +    if (Block == NULL) goto Error;
200.1462 +
200.1463 +    NumOfWchar = SizeOfTag / sizeof(cmsUInt16Number);
200.1464 +
200.1465 +    if (!_cmsReadUInt16Array(io, NumOfWchar, Block)) goto Error;
200.1466 +    mlu ->MemPool = Block;
200.1467 +    mlu ->PoolSize = SizeOfTag;
200.1468 +    mlu ->PoolUsed = SizeOfTag;
200.1469 +
200.1470 +    *nItems = 1;
200.1471 +    return (void*) mlu;
200.1472 +
200.1473 +Error:
200.1474 +    if (mlu) cmsMLUfree(mlu);
200.1475 +    return NULL;
200.1476 +}
200.1477 +
200.1478 +static
200.1479 +cmsBool  Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.1480 +{
200.1481 +    cmsMLU* mlu =(cmsMLU*) Ptr;
200.1482 +    cmsUInt32Number HeaderSize, Offset;
200.1483 +    int i;
200.1484 +
200.1485 +    if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE;
200.1486 +    if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
200.1487 +
200.1488 +    HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase);
200.1489 +
200.1490 +    for (i=0; i < mlu ->UsedEntries; i++) {
200.1491 +
200.1492 +        if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Language)) return FALSE;
200.1493 +        if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Country))  return FALSE;
200.1494 +        if (!_cmsWriteUInt32Number(io, mlu ->Entries[i].Len)) return FALSE;
200.1495 +
200.1496 +        Offset =  mlu ->Entries[i].StrW + HeaderSize + 8;
200.1497 +
200.1498 +        if (!_cmsWriteUInt32Number(io, Offset)) return FALSE;
200.1499 +    }
200.1500 +
200.1501 +    if (!_cmsWriteUInt16Array(io, mlu ->PoolUsed / sizeof(cmsUInt16Number), (cmsUInt16Number*)  mlu ->MemPool)) return FALSE;
200.1502 +
200.1503 +    return TRUE;
200.1504 +
200.1505 +    cmsUNUSED_PARAMETER(nItems);
200.1506 +    cmsUNUSED_PARAMETER(self);
200.1507 +}
200.1508 +
200.1509 +
200.1510 +static
200.1511 +void* Type_MLU_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.1512 +{
200.1513 +    return (void*) cmsMLUdup((cmsMLU*) Ptr);
200.1514 +
200.1515 +    cmsUNUSED_PARAMETER(n);
200.1516 +    cmsUNUSED_PARAMETER(self);
200.1517 +}
200.1518 +
200.1519 +static
200.1520 +void Type_MLU_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.1521 +{
200.1522 +    cmsMLUfree((cmsMLU*) Ptr);
200.1523 +    return;
200.1524 +
200.1525 +    cmsUNUSED_PARAMETER(self);
200.1526 +}
200.1527 +
200.1528 +
200.1529 +// ********************************************************************************
200.1530 +// Type cmsSigLut8Type
200.1531 +// ********************************************************************************
200.1532 +
200.1533 +// Decide which LUT type to use on writting
200.1534 +static
200.1535 +cmsTagTypeSignature DecideLUTtypeA2B(cmsFloat64Number ICCVersion, const void *Data)
200.1536 +{
200.1537 +    cmsPipeline* Lut = (cmsPipeline*) Data;
200.1538 +
200.1539 +    if (ICCVersion < 4.0) {
200.1540 +        if (Lut ->SaveAs8Bits) return cmsSigLut8Type;
200.1541 +        return cmsSigLut16Type;
200.1542 +    }
200.1543 +    else {
200.1544 +         return cmsSigLutAtoBType;
200.1545 +    }
200.1546 +}
200.1547 +
200.1548 +static
200.1549 +cmsTagTypeSignature DecideLUTtypeB2A(cmsFloat64Number ICCVersion, const void *Data)
200.1550 +{
200.1551 +    cmsPipeline* Lut = (cmsPipeline*) Data;
200.1552 +
200.1553 +    if (ICCVersion < 4.0) {
200.1554 +        if (Lut ->SaveAs8Bits) return cmsSigLut8Type;
200.1555 +        return cmsSigLut16Type;
200.1556 +    }
200.1557 +    else {
200.1558 +         return cmsSigLutBtoAType;
200.1559 +    }
200.1560 +}
200.1561 +
200.1562 +/*
200.1563 +This structure represents a colour transform using tables of 8-bit precision.
200.1564 +This type contains four processing elements: a 3 by 3 matrix (which shall be
200.1565 +the identity matrix unless the input colour space is XYZ), a set of one dimensional
200.1566 +input tables, a multidimensional lookup table, and a set of one dimensional output
200.1567 +tables. Data is processed using these elements via the following sequence:
200.1568 +(matrix) -> (1d input tables)  -> (multidimensional lookup table - CLUT) -> (1d output tables)
200.1569 +
200.1570 +Byte Position   Field Length (bytes)  Content Encoded as...
200.1571 +8                  1          Number of Input Channels (i)    uInt8Number
200.1572 +9                  1          Number of Output Channels (o)   uInt8Number
200.1573 +10                 1          Number of CLUT grid points (identical for each side) (g) uInt8Number
200.1574 +11                 1          Reserved for padding (fill with 00h)
200.1575 +
200.1576 +12..15             4          Encoded e00 parameter   s15Fixed16Number
200.1577 +*/
200.1578 +
200.1579 +
200.1580 +// Read 8 bit tables as gamma functions
200.1581 +static
200.1582 +cmsBool  Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels)
200.1583 +{
200.1584 +    cmsStage* mpe;
200.1585 +    cmsUInt8Number* Temp = NULL;
200.1586 +    int i, j;
200.1587 +    cmsToneCurve* Tables[cmsMAXCHANNELS];
200.1588 +
200.1589 +    if (nChannels > cmsMAXCHANNELS) return FALSE;
200.1590 +
200.1591 +    memset(Tables, 0, sizeof(Tables));
200.1592 +
200.1593 +    Temp = (cmsUInt8Number*) _cmsMalloc(ContextID, 256);
200.1594 +    if (Temp == NULL) return FALSE;
200.1595 +
200.1596 +    for (i=0; i < nChannels; i++) {
200.1597 +        Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL);
200.1598 +        if (Tables[i] == NULL) goto Error;
200.1599 +    }
200.1600 +
200.1601 +    for (i=0; i < nChannels; i++) {
200.1602 +
200.1603 +        if (io ->Read(io, Temp, 256, 1) != 1) goto Error;
200.1604 +
200.1605 +        for (j=0; j < 256; j++)
200.1606 +            Tables[i]->Table16[j] = (cmsUInt16Number) FROM_8_TO_16(Temp[j]);
200.1607 +    }
200.1608 +
200.1609 +    _cmsFree(ContextID, Temp);
200.1610 +
200.1611 +
200.1612 +    mpe = cmsStageAllocToneCurves(ContextID, nChannels, Tables);
200.1613 +    if (mpe == NULL) goto Error;
200.1614 +
200.1615 +    cmsPipelineInsertStage(lut, cmsAT_END, mpe);
200.1616 +
200.1617 +    for (i=0; i < nChannels; i++)
200.1618 +        cmsFreeToneCurve(Tables[i]);
200.1619 +
200.1620 +    return TRUE;
200.1621 +
200.1622 +Error:
200.1623 +    for (i=0; i < nChannels; i++) {
200.1624 +        if (Tables[i]) cmsFreeToneCurve(Tables[i]);
200.1625 +    }
200.1626 +
200.1627 +    if (Temp) _cmsFree(ContextID, Temp);
200.1628 +    return FALSE;
200.1629 +}
200.1630 +
200.1631 +
200.1632 +static
200.1633 +cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number n, _cmsStageToneCurvesData* Tables)
200.1634 +{
200.1635 +    int j;
200.1636 +    cmsUInt32Number i;
200.1637 +    cmsUInt8Number val;
200.1638 +
200.1639 +    for (i=0; i < n; i++) {
200.1640 +
200.1641 +        if (Tables) {
200.1642 +
200.1643 +            if (Tables ->TheCurves[i]->nEntries != 256) {
200.1644 +                cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization");
200.1645 +                return FALSE;
200.1646 +            }
200.1647 +
200.1648 +        }
200.1649 +
200.1650 +        for (j=0; j < 256; j++) {
200.1651 +
200.1652 +            if (Tables != NULL)
200.1653 +                val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
200.1654 +            else
200.1655 +                val = (cmsUInt8Number) j;
200.1656 +
200.1657 +            if (!_cmsWriteUInt8Number(io, val)) return FALSE;
200.1658 +        }
200.1659 +    }
200.1660 +    return TRUE;
200.1661 +}
200.1662 +
200.1663 +
200.1664 +static
200.1665 +unsigned int uipow(cmsUInt32Number a, cmsUInt32Number b) {
200.1666 +    cmsUInt32Number rv = 1;
200.1667 +    for (; b > 0; b--)
200.1668 +        rv *= a;
200.1669 +    return rv;
200.1670 +}
200.1671 +
200.1672 +
200.1673 +// That will create a MPE LUT with Matrix, pre tables, CLUT and post tables.
200.1674 +// 8 bit lut may be scaled easely to v4 PCS, but we need also to properly adjust
200.1675 +// PCS on BToAxx tags and AtoB if abstract. We need to fix input direction.
200.1676 +
200.1677 +static
200.1678 +void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.1679 +{
200.1680 +    cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
200.1681 +    cmsUInt8Number* Temp = NULL;
200.1682 +    cmsPipeline* NewLUT = NULL;
200.1683 +    cmsStage *mpemat, *mpeclut;
200.1684 +    cmsUInt32Number nTabSize, i;
200.1685 +    cmsFloat64Number Matrix[3*3];
200.1686 +
200.1687 +    *nItems = 0;
200.1688 +
200.1689 +    if (!_cmsReadUInt8Number(io, &InputChannels)) goto Error;
200.1690 +    if (!_cmsReadUInt8Number(io, &OutputChannels)) goto Error;
200.1691 +    if (!_cmsReadUInt8Number(io, &CLUTpoints)) goto Error;
200.1692 +
200.1693 +    // Padding
200.1694 +    if (!_cmsReadUInt8Number(io, NULL)) goto Error;
200.1695 +
200.1696 +    // Do some checking
200.1697 +
200.1698 +    if (InputChannels > cmsMAXCHANNELS)  goto Error;
200.1699 +    if (OutputChannels > cmsMAXCHANNELS) goto Error;
200.1700 +
200.1701 +   // Allocates an empty Pipeline
200.1702 +    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels);
200.1703 +    if (NewLUT == NULL) goto Error;
200.1704 +
200.1705 +    // Read the Matrix
200.1706 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[0])) goto Error;
200.1707 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[1])) goto Error;
200.1708 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[2])) goto Error;
200.1709 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[3])) goto Error;
200.1710 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[4])) goto Error;
200.1711 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[5])) goto Error;
200.1712 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[6])) goto Error;
200.1713 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[7])) goto Error;
200.1714 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[8])) goto Error;
200.1715 +
200.1716 +
200.1717 +    // Only operates if not identity...
200.1718 +    if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
200.1719 +
200.1720 +        mpemat = cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL);
200.1721 +        if (mpemat == NULL) goto Error;
200.1722 +        cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, mpemat);
200.1723 +    }
200.1724 +
200.1725 +    // Get input tables
200.1726 +    if (!Read8bitTables(self ->ContextID, io,  NewLUT, InputChannels)) goto Error;
200.1727 +
200.1728 +    // Get 3D CLUT
200.1729 +    nTabSize = (OutputChannels * uipow(CLUTpoints, InputChannels));
200.1730 +    if (nTabSize > 0) {
200.1731 +
200.1732 +        cmsUInt16Number *PtrW, *T;
200.1733 +        cmsUInt32Number Tsize;
200.1734 +
200.1735 +        Tsize = (cmsUInt32Number) nTabSize * sizeof(cmsUInt16Number);
200.1736 +
200.1737 +        PtrW = T  = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
200.1738 +        if (T  == NULL) goto Error;
200.1739 +
200.1740 +        Temp = (cmsUInt8Number*) _cmsMalloc(self ->ContextID, nTabSize);
200.1741 +        if (Temp == NULL) goto Error;
200.1742 +
200.1743 +        if (io ->Read(io, Temp, nTabSize, 1) != 1) goto Error;
200.1744 +
200.1745 +        for (i = 0; i < nTabSize; i++) {
200.1746 +
200.1747 +            *PtrW++ = FROM_8_TO_16(Temp[i]);
200.1748 +        }
200.1749 +        _cmsFree(self ->ContextID, Temp);
200.1750 +        Temp = NULL;
200.1751 +
200.1752 +
200.1753 +        mpeclut = cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T);
200.1754 +        if (mpeclut == NULL) goto Error;
200.1755 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpeclut);
200.1756 +        _cmsFree(self ->ContextID, T);
200.1757 +    }
200.1758 +
200.1759 +
200.1760 +    // Get output tables
200.1761 +    if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;
200.1762 +
200.1763 +    *nItems = 1;
200.1764 +    return NewLUT;
200.1765 +
200.1766 +Error:
200.1767 +    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
200.1768 +    return NULL;
200.1769 +
200.1770 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.1771 +}
200.1772 +
200.1773 +// We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
200.1774 +static
200.1775 +cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.1776 +{
200.1777 +    cmsUInt32Number j, nTabSize;
200.1778 +    cmsUInt8Number  val;
200.1779 +    cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
200.1780 +    cmsStage* mpe;
200.1781 +    _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
200.1782 +    _cmsStageMatrixData* MatMPE = NULL;
200.1783 +    _cmsStageCLutData* clut = NULL;
200.1784 +    int clutPoints;
200.1785 +
200.1786 +    // Disassemble the LUT into components.
200.1787 +    mpe = NewLUT -> Elements;
200.1788 +    if (mpe ->Type == cmsSigMatrixElemType) {
200.1789 +
200.1790 +        MatMPE = (_cmsStageMatrixData*) mpe ->Data;
200.1791 +        mpe = mpe -> Next;
200.1792 +    }
200.1793 +
200.1794 +    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
200.1795 +        PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
200.1796 +        mpe = mpe -> Next;
200.1797 +    }
200.1798 +
200.1799 +    if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
200.1800 +        clut  = (_cmsStageCLutData*) mpe -> Data;
200.1801 +        mpe = mpe ->Next;
200.1802 +    }
200.1803 +
200.1804 +    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
200.1805 +        PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
200.1806 +        mpe = mpe -> Next;
200.1807 +    }
200.1808 +
200.1809 +    // That should be all
200.1810 +    if (mpe != NULL) {
200.1811 +        cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8");
200.1812 +        return FALSE;
200.1813 +    }
200.1814 +
200.1815 +
200.1816 +    if (clut == NULL)
200.1817 +        clutPoints = 0;
200.1818 +    else
200.1819 +        clutPoints    = clut->Params->nSamples[0];
200.1820 +
200.1821 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->InputChannels)) return FALSE;
200.1822 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->OutputChannels)) return FALSE;
200.1823 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
200.1824 +    if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
200.1825 +
200.1826 +
200.1827 +    if (MatMPE != NULL) {
200.1828 +
200.1829 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE;
200.1830 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE;
200.1831 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE;
200.1832 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE;
200.1833 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE;
200.1834 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE;
200.1835 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE;
200.1836 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE;
200.1837 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE;
200.1838 +
200.1839 +    }
200.1840 +    else {
200.1841 +
200.1842 +        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
200.1843 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.1844 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.1845 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.1846 +        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
200.1847 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.1848 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.1849 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.1850 +        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
200.1851 +    }
200.1852 +
200.1853 +    // The prelinearization table
200.1854 +    if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
200.1855 +
200.1856 +    nTabSize = (NewLUT->OutputChannels * uipow(clutPoints, NewLUT ->InputChannels));
200.1857 +
200.1858 +    // The 3D CLUT.
200.1859 +    if (clut != NULL) {
200.1860 +
200.1861 +        for (j=0; j < nTabSize; j++) {
200.1862 +
200.1863 +            val = (cmsUInt8Number) FROM_16_TO_8(clut ->Tab.T[j]);
200.1864 +            if (!_cmsWriteUInt8Number(io, val)) return FALSE;
200.1865 +        }
200.1866 +    }
200.1867 +
200.1868 +    // The postlinearization table
200.1869 +    if (!Write8bitTables(self ->ContextID, io, NewLUT ->OutputChannels, PostMPE)) return FALSE;
200.1870 +
200.1871 +    return TRUE;
200.1872 +
200.1873 +    cmsUNUSED_PARAMETER(nItems);
200.1874 +}
200.1875 +
200.1876 +
200.1877 +static
200.1878 +void* Type_LUT8_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.1879 +{
200.1880 +    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
200.1881 +
200.1882 +    cmsUNUSED_PARAMETER(n);
200.1883 +    cmsUNUSED_PARAMETER(self);
200.1884 +}
200.1885 +
200.1886 +static
200.1887 +void Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.1888 +{
200.1889 +    cmsPipelineFree((cmsPipeline*) Ptr);
200.1890 +    return;
200.1891 +
200.1892 +    cmsUNUSED_PARAMETER(self);
200.1893 +}
200.1894 +
200.1895 +// ********************************************************************************
200.1896 +// Type cmsSigLut16Type
200.1897 +// ********************************************************************************
200.1898 +
200.1899 +// Read 16 bit tables as gamma functions
200.1900 +static
200.1901 +cmsBool  Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
200.1902 +{
200.1903 +    cmsStage* mpe;
200.1904 +    int i;
200.1905 +    cmsToneCurve* Tables[cmsMAXCHANNELS];
200.1906 +
200.1907 +    // Maybe an empty table? (this is a lcms extension)
200.1908 +    if (nEntries <= 0) return TRUE;
200.1909 +
200.1910 +    // Check for malicious profiles
200.1911 +    if (nChannels > cmsMAXCHANNELS) return FALSE;
200.1912 +
200.1913 +    // Init table to zero
200.1914 +    memset(Tables, 0, sizeof(Tables));
200.1915 +
200.1916 +    for (i=0; i < nChannels; i++) {
200.1917 +
200.1918 +        Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, nEntries, NULL);
200.1919 +        if (Tables[i] == NULL) goto Error;
200.1920 +
200.1921 +        if (!_cmsReadUInt16Array(io, nEntries, Tables[i]->Table16)) goto Error;
200.1922 +    }
200.1923 +
200.1924 +
200.1925 +    // Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code)
200.1926 +    mpe = cmsStageAllocToneCurves(ContextID, nChannels, Tables);
200.1927 +    if (mpe == NULL) goto Error;
200.1928 +
200.1929 +    cmsPipelineInsertStage(lut, cmsAT_END, mpe);
200.1930 +
200.1931 +    for (i=0; i < nChannels; i++)
200.1932 +        cmsFreeToneCurve(Tables[i]);
200.1933 +
200.1934 +    return TRUE;
200.1935 +
200.1936 +Error:
200.1937 +    for (i=0; i < nChannels; i++) {
200.1938 +        if (Tables[i]) cmsFreeToneCurve(Tables[i]);
200.1939 +    }
200.1940 +
200.1941 +    return FALSE;
200.1942 +}
200.1943 +
200.1944 +static
200.1945 +cmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCurvesData* Tables)
200.1946 +{
200.1947 +    int j;
200.1948 +    cmsUInt32Number i;
200.1949 +    cmsUInt16Number val;
200.1950 +    int nEntries = 256;
200.1951 +
200.1952 +    nEntries = Tables->TheCurves[0]->nEntries;
200.1953 +
200.1954 +    for (i=0; i < Tables ->nCurves; i++) {
200.1955 +
200.1956 +        for (j=0; j < nEntries; j++) {
200.1957 +
200.1958 +            if (Tables != NULL)
200.1959 +                val = Tables->TheCurves[i]->Table16[j];
200.1960 +            else
200.1961 +                val = _cmsQuantizeVal(j, nEntries);
200.1962 +
200.1963 +            if (!_cmsWriteUInt16Number(io, val)) return FALSE;
200.1964 +        }
200.1965 +    }
200.1966 +    return TRUE;
200.1967 +
200.1968 +    cmsUNUSED_PARAMETER(ContextID);
200.1969 +}
200.1970 +
200.1971 +static
200.1972 +void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.1973 +{
200.1974 +    cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
200.1975 +    cmsPipeline* NewLUT = NULL;
200.1976 +    cmsStage *mpemat,  *mpeclut;
200.1977 +    cmsUInt32Number nTabSize;
200.1978 +    cmsFloat64Number Matrix[3*3];
200.1979 +    cmsUInt16Number InputEntries, OutputEntries;
200.1980 +
200.1981 +    *nItems = 0;
200.1982 +
200.1983 +    if (!_cmsReadUInt8Number(io, &InputChannels)) return NULL;
200.1984 +    if (!_cmsReadUInt8Number(io, &OutputChannels)) return NULL;
200.1985 +    if (!_cmsReadUInt8Number(io, &CLUTpoints)) return NULL;
200.1986 +
200.1987 +    // Padding
200.1988 +    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
200.1989 +
200.1990 +    // Do some checking
200.1991 +    if (CLUTpoints > 100) goto Error;
200.1992 +    if (InputChannels > cmsMAXCHANNELS)  goto Error;
200.1993 +    if (OutputChannels > cmsMAXCHANNELS) goto Error;
200.1994 +
200.1995 +    // Allocates an empty LUT
200.1996 +    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels);
200.1997 +    if (NewLUT == NULL) goto Error;
200.1998 +
200.1999 +    // Read the Matrix
200.2000 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[0])) goto Error;
200.2001 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[1])) goto Error;
200.2002 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[2])) goto Error;
200.2003 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[3])) goto Error;
200.2004 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[4])) goto Error;
200.2005 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[5])) goto Error;
200.2006 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[6])) goto Error;
200.2007 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[7])) goto Error;
200.2008 +    if (!_cmsRead15Fixed16Number(io,  &Matrix[8])) goto Error;
200.2009 +
200.2010 +
200.2011 +    // Only operates on 3 channels
200.2012 +
200.2013 +    if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
200.2014 +
200.2015 +        mpemat = cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL);
200.2016 +        if (mpemat == NULL) goto Error;
200.2017 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpemat);
200.2018 +    }
200.2019 +
200.2020 +    if (!_cmsReadUInt16Number(io, &InputEntries)) return NULL;
200.2021 +    if (!_cmsReadUInt16Number(io, &OutputEntries)) return NULL;
200.2022 +
200.2023 +
200.2024 +    // Get input tables
200.2025 +    if (!Read16bitTables(self ->ContextID, io,  NewLUT, InputChannels, InputEntries)) goto Error;
200.2026 +
200.2027 +    // Get 3D CLUT
200.2028 +    nTabSize = (OutputChannels * uipow(CLUTpoints, InputChannels));
200.2029 +    if (nTabSize > 0) {
200.2030 +
200.2031 +        cmsUInt16Number *T;
200.2032 +
200.2033 +        T  = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
200.2034 +        if (T  == NULL) goto Error;
200.2035 +
200.2036 +        if (!_cmsReadUInt16Array(io, nTabSize, T)) goto Error;
200.2037 +
200.2038 +        mpeclut = cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T);
200.2039 +        if (mpeclut == NULL) goto Error;
200.2040 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpeclut);
200.2041 +        _cmsFree(self ->ContextID, T);
200.2042 +    }
200.2043 +
200.2044 +
200.2045 +    // Get output tables
200.2046 +    if (!Read16bitTables(self ->ContextID, io,  NewLUT, OutputChannels, OutputEntries)) goto Error;
200.2047 +
200.2048 +    *nItems = 1;
200.2049 +    return NewLUT;
200.2050 +
200.2051 +Error:
200.2052 +    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
200.2053 +    return NULL;
200.2054 +
200.2055 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.2056 +}
200.2057 +
200.2058 +// We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin.
200.2059 +// Some empty defaults are created for missing parts
200.2060 +
200.2061 +static
200.2062 +cmsBool  Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.2063 +{
200.2064 +    cmsUInt32Number nTabSize;
200.2065 +    cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
200.2066 +    cmsStage* mpe;
200.2067 +    _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
200.2068 +    _cmsStageMatrixData* MatMPE = NULL;
200.2069 +    _cmsStageCLutData* clut = NULL;
200.2070 +    int InputChannels, OutputChannels, clutPoints;
200.2071 +
200.2072 +    // Disassemble the LUT into components.
200.2073 +    mpe = NewLUT -> Elements;
200.2074 +    if (mpe != NULL && mpe ->Type == cmsSigMatrixElemType) {
200.2075 +
200.2076 +        MatMPE = (_cmsStageMatrixData*) mpe ->Data;
200.2077 +        mpe = mpe -> Next;
200.2078 +    }
200.2079 +
200.2080 +
200.2081 +    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
200.2082 +        PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
200.2083 +        mpe = mpe -> Next;
200.2084 +    }
200.2085 +
200.2086 +    if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
200.2087 +        clut  = (_cmsStageCLutData*) mpe -> Data;
200.2088 +        mpe = mpe ->Next;
200.2089 +    }
200.2090 +
200.2091 +    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
200.2092 +        PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
200.2093 +        mpe = mpe -> Next;
200.2094 +    }
200.2095 +
200.2096 +    // That should be all
200.2097 +    if (mpe != NULL) {
200.2098 +        cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16");
200.2099 +        return FALSE;
200.2100 +    }
200.2101 +
200.2102 +    InputChannels  = cmsPipelineInputChannels(NewLUT);
200.2103 +    OutputChannels = cmsPipelineOutputChannels(NewLUT);
200.2104 +
200.2105 +    if (clut == NULL)
200.2106 +        clutPoints = 0;
200.2107 +    else
200.2108 +        clutPoints    = clut->Params->nSamples[0];
200.2109 +
200.2110 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) InputChannels)) return FALSE;
200.2111 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) OutputChannels)) return FALSE;
200.2112 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
200.2113 +    if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
200.2114 +
200.2115 +
200.2116 +    if (MatMPE != NULL) {
200.2117 +
200.2118 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE;
200.2119 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE;
200.2120 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE;
200.2121 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE;
200.2122 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE;
200.2123 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE;
200.2124 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE;
200.2125 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE;
200.2126 +        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE;
200.2127 +    }
200.2128 +    else {
200.2129 +
200.2130 +        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
200.2131 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.2132 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.2133 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.2134 +        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
200.2135 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.2136 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.2137 +        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
200.2138 +        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
200.2139 +    }
200.2140 +
200.2141 +
200.2142 +    if (PreMPE != NULL) {
200.2143 +        if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE;
200.2144 +    } else {
200.2145 +            if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
200.2146 +    }
200.2147 +
200.2148 +    if (PostMPE != NULL) {
200.2149 +        if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE;
200.2150 +    } else {
200.2151 +        if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
200.2152 +
200.2153 +    }
200.2154 +
200.2155 +    // The prelinearization table
200.2156 +
200.2157 +    if (PreMPE != NULL) {
200.2158 +        if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE;
200.2159 +    }
200.2160 +
200.2161 +    nTabSize = (OutputChannels * uipow(clutPoints, InputChannels));
200.2162 +
200.2163 +    // The 3D CLUT.
200.2164 +    if (clut != NULL) {
200.2165 +        if (!_cmsWriteUInt16Array(io, nTabSize, clut->Tab.T)) return FALSE;
200.2166 +    }
200.2167 +
200.2168 +    // The postlinearization table
200.2169 +    if (PostMPE != NULL) {
200.2170 +        if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE;
200.2171 +    }
200.2172 +
200.2173 +
200.2174 +    return TRUE;
200.2175 +
200.2176 +    cmsUNUSED_PARAMETER(nItems);
200.2177 +}
200.2178 +
200.2179 +static
200.2180 +void* Type_LUT16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.2181 +{
200.2182 +    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
200.2183 +
200.2184 +    cmsUNUSED_PARAMETER(n);
200.2185 +    cmsUNUSED_PARAMETER(self);
200.2186 +}
200.2187 +
200.2188 +static
200.2189 +void Type_LUT16_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.2190 +{
200.2191 +    cmsPipelineFree((cmsPipeline*) Ptr);
200.2192 +    return;
200.2193 +
200.2194 +    cmsUNUSED_PARAMETER(self);
200.2195 +}
200.2196 +
200.2197 +
200.2198 +// ********************************************************************************
200.2199 +// Type cmsSigLutAToBType
200.2200 +// ********************************************************************************
200.2201 +
200.2202 +
200.2203 +// V4 stuff. Read matrix for LutAtoB and LutBtoA
200.2204 +
200.2205 +static
200.2206 +cmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset)
200.2207 +{
200.2208 +    cmsFloat64Number dMat[3*3];
200.2209 +    cmsFloat64Number dOff[3];
200.2210 +    cmsStage* Mat;
200.2211 +
200.2212 +    // Go to address
200.2213 +    if (!io -> Seek(io, Offset)) return NULL;
200.2214 +
200.2215 +    // Read the Matrix
200.2216 +    if (!_cmsRead15Fixed16Number(io, &dMat[0])) return NULL;
200.2217 +    if (!_cmsRead15Fixed16Number(io, &dMat[1])) return NULL;
200.2218 +    if (!_cmsRead15Fixed16Number(io, &dMat[2])) return NULL;
200.2219 +    if (!_cmsRead15Fixed16Number(io, &dMat[3])) return NULL;
200.2220 +    if (!_cmsRead15Fixed16Number(io, &dMat[4])) return NULL;
200.2221 +    if (!_cmsRead15Fixed16Number(io, &dMat[5])) return NULL;
200.2222 +    if (!_cmsRead15Fixed16Number(io, &dMat[6])) return NULL;
200.2223 +    if (!_cmsRead15Fixed16Number(io, &dMat[7])) return NULL;
200.2224 +    if (!_cmsRead15Fixed16Number(io, &dMat[8])) return NULL;
200.2225 +
200.2226 +    if (!_cmsRead15Fixed16Number(io, &dOff[0])) return NULL;
200.2227 +    if (!_cmsRead15Fixed16Number(io, &dOff[1])) return NULL;
200.2228 +    if (!_cmsRead15Fixed16Number(io, &dOff[2])) return NULL;
200.2229 +
200.2230 +    Mat = cmsStageAllocMatrix(self ->ContextID, 3, 3, dMat, dOff);
200.2231 +
200.2232 +     return Mat;
200.2233 +}
200.2234 +
200.2235 +
200.2236 +
200.2237 +
200.2238 +//  V4 stuff. Read CLUT part for LutAtoB and LutBtoA
200.2239 +
200.2240 +static
200.2241 +cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, int InputChannels, int OutputChannels)
200.2242 +{
200.2243 +    cmsUInt8Number  gridPoints8[cmsMAXCHANNELS]; // Number of grid points in each dimension.
200.2244 +    cmsUInt32Number GridPoints[cmsMAXCHANNELS], i;
200.2245 +    cmsUInt8Number  Precision;
200.2246 +    cmsStage* CLUT;
200.2247 +    _cmsStageCLutData* Data;
200.2248 +
200.2249 +    if (!io -> Seek(io, Offset)) return NULL;
200.2250 +    if (io -> Read(io, gridPoints8, cmsMAXCHANNELS, 1) != 1) return NULL;
200.2251 +
200.2252 +    for (i=0; i < cmsMAXCHANNELS; i++)
200.2253 +        GridPoints[i] = gridPoints8[i];
200.2254 +
200.2255 +    if (!_cmsReadUInt8Number(io, &Precision)) return NULL;
200.2256 +
200.2257 +    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
200.2258 +    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
200.2259 +    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
200.2260 +
200.2261 +    CLUT = cmsStageAllocCLut16bitGranular(self ->ContextID, GridPoints, InputChannels, OutputChannels, NULL);
200.2262 +    Data = (_cmsStageCLutData*) CLUT ->Data;
200.2263 +
200.2264 +    // Precision can be 1 or 2 bytes
200.2265 +    if (Precision == 1) {
200.2266 +
200.2267 +       cmsUInt8Number  v;
200.2268 +
200.2269 +        for (i=0; i < Data ->nEntries; i++) {
200.2270 +
200.2271 +                if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL;
200.2272 +                Data ->Tab.T[i] = FROM_8_TO_16(v);
200.2273 +        }
200.2274 +
200.2275 +    }
200.2276 +    else
200.2277 +        if (Precision == 2) {
200.2278 +
200.2279 +            if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) return NULL;
200.2280 +    }
200.2281 +    else {
200.2282 +        cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknow precision of '%d'", Precision);
200.2283 +        return NULL;
200.2284 +    }
200.2285 +
200.2286 +
200.2287 +    return CLUT;
200.2288 +}
200.2289 +
200.2290 +static
200.2291 +cmsToneCurve* ReadEmbeddedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
200.2292 +{
200.2293 +    cmsTagTypeSignature  BaseType;
200.2294 +    cmsUInt32Number nItems;
200.2295 +
200.2296 +    BaseType = _cmsReadTypeBase(io);
200.2297 +    switch (BaseType) {
200.2298 +
200.2299 +            case cmsSigCurveType:
200.2300 +                return (cmsToneCurve*) Type_Curve_Read(self, io, &nItems, 0);
200.2301 +
200.2302 +            case cmsSigParametricCurveType:
200.2303 +                return (cmsToneCurve*) Type_ParametricCurve_Read(self, io, &nItems, 0);
200.2304 +
200.2305 +            default:
200.2306 +                {
200.2307 +                    char String[5];
200.2308 +
200.2309 +                    _cmsTagSignature2String(String, (cmsTagSignature) BaseType);
200.2310 +                    cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknow curve type '%s'", String);
200.2311 +                }
200.2312 +                return NULL;
200.2313 +    }
200.2314 +}
200.2315 +
200.2316 +
200.2317 +// Read a set of curves from specific offset
200.2318 +static
200.2319 +cmsStage* ReadSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, int nCurves)
200.2320 +{
200.2321 +    cmsToneCurve* Curves[cmsMAXCHANNELS];
200.2322 +   int i;
200.2323 +    cmsStage* Lin;
200.2324 +
200.2325 +
200.2326 +    if (nCurves > cmsMAXCHANNELS) return FALSE;
200.2327 +
200.2328 +    if (!io -> Seek(io, Offset)) return FALSE;
200.2329 +
200.2330 +    for (i=0; i < nCurves; i++) {
200.2331 +
200.2332 +        Curves[i] = ReadEmbeddedCurve(self, io);
200.2333 +        if (Curves[i] == NULL) return FALSE;
200.2334 +        if (!_cmsReadAlignment(io)) return FALSE;
200.2335 +    }
200.2336 +
200.2337 +    Lin = cmsStageAllocToneCurves(self ->ContextID, nCurves, Curves);
200.2338 +
200.2339 +    for (i=0; i < nCurves; i++)
200.2340 +        cmsFreeToneCurve(Curves[i]);
200.2341 +
200.2342 +    return Lin;
200.2343 +}
200.2344 +
200.2345 +
200.2346 +// LutAtoB type
200.2347 +
200.2348 +// This structure represents a colour transform. The type contains up to five processing
200.2349 +// elements which are stored in the AtoBTag tag in the following order: a set of one
200.2350 +// dimensional curves, a 3 by 3 matrix with offset terms, a set of one dimensional curves,
200.2351 +// a multidimensional lookup table, and a set of one dimensional output curves.
200.2352 +// Data are processed using these elements via the following sequence:
200.2353 +//
200.2354 +//("A" curves) -> (multidimensional lookup table - CLUT) -> ("M" curves) -> (matrix) -> ("B" curves).
200.2355 +//
200.2356 +/*
200.2357 +It is possible to use any or all of these processing elements. At least one processing element
200.2358 +must be included.Only the following combinations are allowed:
200.2359 +
200.2360 +B
200.2361 +M - Matrix - B
200.2362 +A - CLUT - B
200.2363 +A - CLUT - M - Matrix - B
200.2364 +
200.2365 +*/
200.2366 +
200.2367 +static
200.2368 +void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.2369 +{
200.2370 +    cmsUInt32Number      BaseOffset;
200.2371 +    cmsUInt8Number       inputChan;      // Number of input channels
200.2372 +    cmsUInt8Number       outputChan;     // Number of output channels
200.2373 +    cmsUInt32Number      offsetB;        // Offset to first "B" curve
200.2374 +    cmsUInt32Number      offsetMat;      // Offset to matrix
200.2375 +    cmsUInt32Number      offsetM;        // Offset to first "M" curve
200.2376 +    cmsUInt32Number      offsetC;        // Offset to CLUT
200.2377 +    cmsUInt32Number      offsetA;        // Offset to first "A" curve
200.2378 +    cmsStage* mpe;
200.2379 +    cmsPipeline* NewLUT = NULL;
200.2380 +
200.2381 +
200.2382 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.2383 +
200.2384 +    if (!_cmsReadUInt8Number(io, &inputChan)) return NULL;
200.2385 +    if (!_cmsReadUInt8Number(io, &outputChan)) return NULL;
200.2386 +
200.2387 +    if (!_cmsReadUInt16Number(io, NULL)) return NULL;
200.2388 +
200.2389 +    if (!_cmsReadUInt32Number(io, &offsetB)) return NULL;
200.2390 +    if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL;
200.2391 +    if (!_cmsReadUInt32Number(io, &offsetM)) return NULL;
200.2392 +    if (!_cmsReadUInt32Number(io, &offsetC)) return NULL;
200.2393 +    if (!_cmsReadUInt32Number(io, &offsetA)) return NULL;
200.2394 +
200.2395 +   // Allocates an empty LUT
200.2396 +    NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan);
200.2397 +    if (NewLUT == NULL) return NULL;
200.2398 +
200.2399 +    if (offsetA!= 0) {
200.2400 +        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan);
200.2401 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2402 +    }
200.2403 +
200.2404 +    if (offsetC != 0) {
200.2405 +        mpe = ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan);
200.2406 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2407 +    }
200.2408 +
200.2409 +    if (offsetM != 0) {
200.2410 +        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan);
200.2411 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2412 +    }
200.2413 +
200.2414 +    if (offsetMat != 0) {
200.2415 +        mpe = ReadMatrix(self, io, BaseOffset + offsetMat);
200.2416 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2417 +    }
200.2418 +
200.2419 +    if (offsetB != 0) {
200.2420 +        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan);
200.2421 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2422 +    }
200.2423 +
200.2424 +    *nItems = 1;
200.2425 +    return NewLUT;
200.2426 +
200.2427 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.2428 +}
200.2429 +
200.2430 +// Write a set of curves
200.2431 +static
200.2432 +cmsBool  WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe)
200.2433 +{
200.2434 +    _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data;
200.2435 +
200.2436 +    // Write the Matrix
200.2437 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[0])) return FALSE;
200.2438 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[1])) return FALSE;
200.2439 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[2])) return FALSE;
200.2440 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[3])) return FALSE;
200.2441 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[4])) return FALSE;
200.2442 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[5])) return FALSE;
200.2443 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[6])) return FALSE;
200.2444 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[7])) return FALSE;
200.2445 +    if (!_cmsWrite15Fixed16Number(io, m -> Double[8])) return FALSE;
200.2446 +
200.2447 +    if (!_cmsWrite15Fixed16Number(io, m -> Offset[0])) return FALSE;
200.2448 +    if (!_cmsWrite15Fixed16Number(io, m -> Offset[1])) return FALSE;
200.2449 +    if (!_cmsWrite15Fixed16Number(io, m -> Offset[2])) return FALSE;
200.2450 +
200.2451 +    return TRUE;
200.2452 +
200.2453 +    cmsUNUSED_PARAMETER(self);
200.2454 +}
200.2455 +
200.2456 +
200.2457 +// Write a set of curves
200.2458 +static
200.2459 +cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
200.2460 +{
200.2461 +    cmsUInt32Number i, n;
200.2462 +    cmsTagTypeSignature CurrentType;
200.2463 +    cmsToneCurve** Curves;
200.2464 +
200.2465 +
200.2466 +    n      = cmsStageOutputChannels(mpe);
200.2467 +    Curves = _cmsStageGetPtrToCurveSet(mpe);
200.2468 +
200.2469 +    for (i=0; i < n; i++) {
200.2470 +
200.2471 +        // If this is a table-based curve, use curve type even on V4
200.2472 +        CurrentType = Type;
200.2473 +
200.2474 +        if (Curves[i] ->nSegments == 0)
200.2475 +            CurrentType = cmsSigCurveType;
200.2476 +        else
200.2477 +        if (Curves[i] ->Segments[0].Type < 0)
200.2478 +            CurrentType = cmsSigCurveType;
200.2479 +
200.2480 +        if (!_cmsWriteTypeBase(io, CurrentType)) return FALSE;
200.2481 +
200.2482 +        switch (CurrentType) {
200.2483 +
200.2484 +            case cmsSigCurveType:
200.2485 +                if (!Type_Curve_Write(self, io, Curves[i], 1)) return FALSE;
200.2486 +                break;
200.2487 +
200.2488 +            case cmsSigParametricCurveType:
200.2489 +                if (!Type_ParametricCurve_Write(self, io, Curves[i], 1)) return FALSE;
200.2490 +                break;
200.2491 +
200.2492 +            default:
200.2493 +                {
200.2494 +                    char String[5];
200.2495 +
200.2496 +                    _cmsTagSignature2String(String, (cmsTagSignature) Type);
200.2497 +                    cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknow curve type '%s'", String);
200.2498 +                }
200.2499 +                return FALSE;
200.2500 +        }
200.2501 +
200.2502 +        if (!_cmsWriteAlignment(io)) return FALSE;
200.2503 +    }
200.2504 +
200.2505 +
200.2506 +    return TRUE;
200.2507 +}
200.2508 +
200.2509 +
200.2510 +static
200.2511 +cmsBool WriteCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt8Number  Precision, cmsStage* mpe)
200.2512 +{
200.2513 +    cmsUInt8Number  gridPoints[cmsMAXCHANNELS]; // Number of grid points in each dimension.
200.2514 +    cmsUInt32Number i;
200.2515 +    _cmsStageCLutData* CLUT = ( _cmsStageCLutData*) mpe -> Data;
200.2516 +
200.2517 +    memset(gridPoints, 0, sizeof(gridPoints));
200.2518 +    for (i=0; i < (cmsUInt32Number) CLUT ->Params ->nInputs; i++)
200.2519 +        gridPoints[i] = (cmsUInt8Number) CLUT ->Params ->nSamples[i];
200.2520 +
200.2521 +    if (!io -> Write(io, cmsMAXCHANNELS*sizeof(cmsUInt8Number), gridPoints)) return FALSE;
200.2522 +
200.2523 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) Precision)) return FALSE;
200.2524 +    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;
200.2525 +    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;
200.2526 +    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;
200.2527 +
200.2528 +    // Precision can be 1 or 2 bytes
200.2529 +    if (Precision == 1) {
200.2530 +
200.2531 +        for (i=0; i < CLUT->nEntries; i++) {
200.2532 +
200.2533 +            if (!_cmsWriteUInt8Number(io, FROM_16_TO_8(CLUT->Tab.T[i]))) return FALSE;
200.2534 +        }
200.2535 +    }
200.2536 +    else
200.2537 +        if (Precision == 2) {
200.2538 +
200.2539 +            if (!_cmsWriteUInt16Array(io, CLUT->nEntries, CLUT ->Tab.T)) return FALSE;
200.2540 +        }
200.2541 +        else {
200.2542 +             cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknow precision of '%d'", Precision);
200.2543 +            return FALSE;
200.2544 +        }
200.2545 +
200.2546 +        if (!_cmsWriteAlignment(io)) return FALSE;
200.2547 +
200.2548 +        return TRUE;
200.2549 +}
200.2550 +
200.2551 +
200.2552 +
200.2553 +
200.2554 +static
200.2555 +cmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.2556 +{
200.2557 +    cmsPipeline* Lut = (cmsPipeline*) Ptr;
200.2558 +    int inputChan, outputChan;
200.2559 +    cmsStage *A = NULL, *B = NULL, *M = NULL;
200.2560 +    cmsStage * Matrix = NULL;
200.2561 +    cmsStage * CLUT = NULL;
200.2562 +    cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0;
200.2563 +    cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos;
200.2564 +
200.2565 +    // Get the base for all offsets
200.2566 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.2567 +
200.2568 +    if (Lut ->Elements != NULL)
200.2569 +        if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B))
200.2570 +            if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &M, &Matrix, &B))
200.2571 +                if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &A, &CLUT, &B))
200.2572 +                    if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType,
200.2573 +                        cmsSigMatrixElemType, cmsSigCurveSetElemType, &A, &CLUT, &M, &Matrix, &B)) {
200.2574 +
200.2575 +                            cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutAToB");
200.2576 +                            return FALSE;
200.2577 +                    }
200.2578 +
200.2579 +    // Get input, output channels
200.2580 +    inputChan  = cmsPipelineInputChannels(Lut);
200.2581 +    outputChan = cmsPipelineOutputChannels(Lut);
200.2582 +
200.2583 +    // Write channel count
200.2584 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE;
200.2585 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE;
200.2586 +    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
200.2587 +
200.2588 +    // Keep directory to be filled latter
200.2589 +    DirectoryPos = io ->Tell(io);
200.2590 +
200.2591 +    // Write the directory
200.2592 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2593 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2594 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2595 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2596 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2597 +
200.2598 +    if (A != NULL) {
200.2599 +
200.2600 +        offsetA = io ->Tell(io) - BaseOffset;
200.2601 +        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE;
200.2602 +    }
200.2603 +
200.2604 +    if (CLUT != NULL) {
200.2605 +        offsetC = io ->Tell(io) - BaseOffset;
200.2606 +        if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE;
200.2607 +
200.2608 +    }
200.2609 +    if (M != NULL) {
200.2610 +
200.2611 +        offsetM = io ->Tell(io) - BaseOffset;
200.2612 +        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE;
200.2613 +    }
200.2614 +
200.2615 +    if (Matrix != NULL) {
200.2616 +        offsetMat = io ->Tell(io) - BaseOffset;
200.2617 +        if (!WriteMatrix(self, io, Matrix)) return FALSE;
200.2618 +    }
200.2619 +
200.2620 +    if (B != NULL) {
200.2621 +
200.2622 +        offsetB = io ->Tell(io) - BaseOffset;
200.2623 +        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
200.2624 +    }
200.2625 +
200.2626 +    CurrentPos = io ->Tell(io);
200.2627 +
200.2628 +    if (!io ->Seek(io, DirectoryPos)) return FALSE;
200.2629 +
200.2630 +    if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
200.2631 +    if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
200.2632 +    if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
200.2633 +    if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
200.2634 +    if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;
200.2635 +
200.2636 +    if (!io ->Seek(io, CurrentPos)) return FALSE;
200.2637 +
200.2638 +    return TRUE;
200.2639 +
200.2640 +    cmsUNUSED_PARAMETER(nItems);
200.2641 +}
200.2642 +
200.2643 +
200.2644 +static
200.2645 +void* Type_LUTA2B_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.2646 +{
200.2647 +    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
200.2648 +
200.2649 +    cmsUNUSED_PARAMETER(n);
200.2650 +    cmsUNUSED_PARAMETER(self);
200.2651 +}
200.2652 +
200.2653 +static
200.2654 +void Type_LUTA2B_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.2655 +{
200.2656 +    cmsPipelineFree((cmsPipeline*) Ptr);
200.2657 +    return;
200.2658 +
200.2659 +    cmsUNUSED_PARAMETER(self);
200.2660 +}
200.2661 +
200.2662 +
200.2663 +// LutBToA type
200.2664 +
200.2665 +static
200.2666 +void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.2667 +{
200.2668 +    cmsUInt8Number       inputChan;      // Number of input channels
200.2669 +    cmsUInt8Number       outputChan;     // Number of output channels
200.2670 +    cmsUInt32Number      BaseOffset;     // Actual position in file
200.2671 +    cmsUInt32Number      offsetB;        // Offset to first "B" curve
200.2672 +    cmsUInt32Number      offsetMat;      // Offset to matrix
200.2673 +    cmsUInt32Number      offsetM;        // Offset to first "M" curve
200.2674 +    cmsUInt32Number      offsetC;        // Offset to CLUT
200.2675 +    cmsUInt32Number      offsetA;        // Offset to first "A" curve
200.2676 +    cmsStage* mpe;
200.2677 +    cmsPipeline* NewLUT = NULL;
200.2678 +
200.2679 +
200.2680 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.2681 +
200.2682 +    if (!_cmsReadUInt8Number(io, &inputChan)) return NULL;
200.2683 +    if (!_cmsReadUInt8Number(io, &outputChan)) return NULL;
200.2684 +
200.2685 +    // Padding
200.2686 +    if (!_cmsReadUInt16Number(io, NULL)) return NULL;
200.2687 +
200.2688 +    if (!_cmsReadUInt32Number(io, &offsetB)) return NULL;
200.2689 +    if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL;
200.2690 +    if (!_cmsReadUInt32Number(io, &offsetM)) return NULL;
200.2691 +    if (!_cmsReadUInt32Number(io, &offsetC)) return NULL;
200.2692 +    if (!_cmsReadUInt32Number(io, &offsetA)) return NULL;
200.2693 +
200.2694 +    // Allocates an empty LUT
200.2695 +    NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan);
200.2696 +    if (NewLUT == NULL) return NULL;
200.2697 +
200.2698 +    if (offsetB != 0) {
200.2699 +        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan);
200.2700 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2701 +    }
200.2702 +
200.2703 +    if (offsetMat != 0) {
200.2704 +        mpe = ReadMatrix(self, io, BaseOffset + offsetMat);
200.2705 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2706 +    }
200.2707 +
200.2708 +    if (offsetM != 0) {
200.2709 +        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan);
200.2710 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2711 +    }
200.2712 +
200.2713 +    if (offsetC != 0) {
200.2714 +        mpe = ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan);
200.2715 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2716 +    }
200.2717 +
200.2718 +    if (offsetA!= 0) {
200.2719 +        mpe = ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan);
200.2720 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.2721 +    }
200.2722 +
200.2723 +    *nItems = 1;
200.2724 +    return NewLUT;
200.2725 +
200.2726 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.2727 +}
200.2728 +
200.2729 +
200.2730 +/*
200.2731 +B
200.2732 +B - Matrix - M
200.2733 +B - CLUT - A
200.2734 +B - Matrix - M - CLUT - A
200.2735 +*/
200.2736 +
200.2737 +static
200.2738 +cmsBool  Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.2739 +{
200.2740 +    cmsPipeline* Lut = (cmsPipeline*) Ptr;
200.2741 +    int inputChan, outputChan;
200.2742 +    cmsStage *A = NULL, *B = NULL, *M = NULL;
200.2743 +    cmsStage *Matrix = NULL;
200.2744 +    cmsStage *CLUT = NULL;
200.2745 +    cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0;
200.2746 +    cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos;
200.2747 +
200.2748 +
200.2749 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.2750 +
200.2751 +    if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B))
200.2752 +        if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &B, &Matrix, &M))
200.2753 +            if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &CLUT, &A))
200.2754 +                if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
200.2755 +                    cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &Matrix, &M, &CLUT, &A)) {
200.2756 +                        cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutBToA");
200.2757 +                        return FALSE;
200.2758 +                }
200.2759 +
200.2760 +    inputChan  = cmsPipelineInputChannels(Lut);
200.2761 +    outputChan = cmsPipelineOutputChannels(Lut);
200.2762 +
200.2763 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE;
200.2764 +    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE;
200.2765 +    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
200.2766 +
200.2767 +    DirectoryPos = io ->Tell(io);
200.2768 +
200.2769 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2770 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2771 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2772 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2773 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.2774 +
200.2775 +    if (A != NULL) {
200.2776 +
200.2777 +        offsetA = io ->Tell(io) - BaseOffset;
200.2778 +        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE;
200.2779 +    }
200.2780 +
200.2781 +    if (CLUT != NULL) {
200.2782 +        offsetC = io ->Tell(io) - BaseOffset;
200.2783 +        if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE;
200.2784 +
200.2785 +    }
200.2786 +    if (M != NULL) {
200.2787 +
200.2788 +        offsetM = io ->Tell(io) - BaseOffset;
200.2789 +        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE;
200.2790 +    }
200.2791 +
200.2792 +    if (Matrix != NULL) {
200.2793 +        offsetMat = io ->Tell(io) - BaseOffset;
200.2794 +        if (!WriteMatrix(self, io, Matrix)) return FALSE;
200.2795 +    }
200.2796 +
200.2797 +    if (B != NULL) {
200.2798 +
200.2799 +        offsetB = io ->Tell(io) - BaseOffset;
200.2800 +        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
200.2801 +    }
200.2802 +
200.2803 +    CurrentPos = io ->Tell(io);
200.2804 +
200.2805 +    if (!io ->Seek(io, DirectoryPos)) return FALSE;
200.2806 +
200.2807 +    if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
200.2808 +    if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
200.2809 +    if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
200.2810 +    if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
200.2811 +    if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;
200.2812 +
200.2813 +    if (!io ->Seek(io, CurrentPos)) return FALSE;
200.2814 +
200.2815 +    return TRUE;
200.2816 +
200.2817 +    cmsUNUSED_PARAMETER(nItems);
200.2818 +}
200.2819 +
200.2820 +
200.2821 +
200.2822 +static
200.2823 +void* Type_LUTB2A_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.2824 +{
200.2825 +    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
200.2826 +
200.2827 +    cmsUNUSED_PARAMETER(n);
200.2828 +    cmsUNUSED_PARAMETER(self);
200.2829 +}
200.2830 +
200.2831 +static
200.2832 +void Type_LUTB2A_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.2833 +{
200.2834 +    cmsPipelineFree((cmsPipeline*) Ptr);
200.2835 +    return;
200.2836 +
200.2837 +    cmsUNUSED_PARAMETER(self);
200.2838 +}
200.2839 +
200.2840 +
200.2841 +
200.2842 +// ********************************************************************************
200.2843 +// Type cmsSigColorantTableType
200.2844 +// ********************************************************************************
200.2845 +/*
200.2846 +The purpose of this tag is to identify the colorants used in the profile by a
200.2847 +unique name and set of XYZ or L*a*b* values to give the colorant an unambiguous
200.2848 +value. The first colorant listed is the colorant of the first device channel of
200.2849 +a lut tag. The second colorant listed is the colorant of the second device channel
200.2850 +of a lut tag, and so on.
200.2851 +*/
200.2852 +
200.2853 +static
200.2854 +void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.2855 +{
200.2856 +    cmsUInt32Number i, Count;
200.2857 +    cmsNAMEDCOLORLIST* List;
200.2858 +    char Name[34];
200.2859 +    cmsUInt16Number PCS[3];
200.2860 +
200.2861 +
200.2862 +    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
200.2863 +
200.2864 +    if (Count > cmsMAXCHANNELS) {
200.2865 +        cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many colorants '%d'", Count);
200.2866 +        return NULL;
200.2867 +    }
200.2868 +
200.2869 +    List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", "");
200.2870 +    for (i=0; i < Count; i++) {
200.2871 +
200.2872 +        if (io ->Read(io, Name, 32, 1) != 1) goto Error;
200.2873 +        Name[33] = 0;
200.2874 +
200.2875 +        if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
200.2876 +
200.2877 +        if (!cmsAppendNamedColor(List, Name, PCS, NULL)) goto Error;
200.2878 +
200.2879 +    }
200.2880 +
200.2881 +    *nItems = 1;
200.2882 +    return List;
200.2883 +
200.2884 +Error:
200.2885 +    *nItems = 0;
200.2886 +    cmsFreeNamedColorList(List);
200.2887 +    return NULL;
200.2888 +
200.2889 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.2890 +}
200.2891 +
200.2892 +
200.2893 +
200.2894 +// Saves a colorant table. It is using the named color structure for simplicity sake
200.2895 +static
200.2896 +cmsBool  Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.2897 +{
200.2898 +    cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
200.2899 +    int i, nColors;
200.2900 +
200.2901 +    nColors = cmsNamedColorCount(NamedColorList);
200.2902 +
200.2903 +    if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
200.2904 +
200.2905 +    for (i=0; i < nColors; i++) {
200.2906 +
200.2907 +        char root[33];
200.2908 +        cmsUInt16Number PCS[3];
200.2909 +
200.2910 +        if (!cmsNamedColorInfo(NamedColorList, i, root, NULL, NULL, PCS, NULL)) return 0;
200.2911 +        root[32] = 0;
200.2912 +
200.2913 +        if (!io ->Write(io, 32, root)) return FALSE;
200.2914 +        if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
200.2915 +    }
200.2916 +
200.2917 +    return TRUE;
200.2918 +
200.2919 +    cmsUNUSED_PARAMETER(nItems);
200.2920 +    cmsUNUSED_PARAMETER(self);
200.2921 +}
200.2922 +
200.2923 +
200.2924 +static
200.2925 +void* Type_ColorantTable_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
200.2926 +{
200.2927 +    cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
200.2928 +    return (void*) cmsDupNamedColorList(nc);
200.2929 +
200.2930 +    cmsUNUSED_PARAMETER(n);
200.2931 +    cmsUNUSED_PARAMETER(self);
200.2932 +}
200.2933 +
200.2934 +
200.2935 +static
200.2936 +void Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.2937 +{
200.2938 +    cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);
200.2939 +    return;
200.2940 +
200.2941 +    cmsUNUSED_PARAMETER(self);
200.2942 +}
200.2943 +
200.2944 +
200.2945 +// ********************************************************************************
200.2946 +// Type cmsSigNamedColor2Type
200.2947 +// ********************************************************************************
200.2948 +//
200.2949 +//The namedColor2Type is a count value and array of structures that provide color
200.2950 +//coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
200.2951 +//device representation of the color are given. Both representations are 16-bit values.
200.2952 +//The device representation corresponds to the header’s “color space of data” field.
200.2953 +//This representation should be consistent with the “number of device components”
200.2954 +//field in the namedColor2Type. If this field is 0, device coordinates are not provided.
200.2955 +//The PCS representation corresponds to the header’s PCS field. The PCS representation
200.2956 +//is always provided. Color names are fixed-length, 32-byte fields including null
200.2957 +//termination. In order to maintain maximum portability, it is strongly recommended
200.2958 +//that special characters of the 7-bit ASCII set not be used.
200.2959 +
200.2960 +static
200.2961 +void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.2962 +{
200.2963 +
200.2964 +    cmsUInt32Number      vendorFlag;     // Bottom 16 bits for ICC use
200.2965 +    cmsUInt32Number      count;          // Count of named colors
200.2966 +    cmsUInt32Number      nDeviceCoords;  // Num of device coordinates
200.2967 +    char                 prefix[32];     // Prefix for each color name
200.2968 +    char                 suffix[32];     // Suffix for each color name
200.2969 +    cmsNAMEDCOLORLIST*  v;
200.2970 +    cmsUInt32Number i;
200.2971 +
200.2972 +
200.2973 +    *nItems = 0;
200.2974 +    if (!_cmsReadUInt32Number(io, &vendorFlag)) return NULL;
200.2975 +    if (!_cmsReadUInt32Number(io, &count)) return NULL;
200.2976 +    if (!_cmsReadUInt32Number(io, &nDeviceCoords)) return NULL;
200.2977 +
200.2978 +    if (io -> Read(io, prefix, 32, 1) != 1) return NULL;
200.2979 +    if (io -> Read(io, suffix, 32, 1) != 1) return NULL;
200.2980 +
200.2981 +    prefix[31] = suffix[31] = 0;
200.2982 +
200.2983 +    v = cmsAllocNamedColorList(self ->ContextID, count, nDeviceCoords, prefix, suffix);
200.2984 +    if (v == NULL) return NULL;
200.2985 +
200.2986 +    if (nDeviceCoords > cmsMAXCHANNELS) {
200.2987 +        cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords);
200.2988 +        return 0;
200.2989 +    }
200.2990 +    for (i=0; i < count; i++) {
200.2991 +
200.2992 +        cmsUInt16Number PCS[3];
200.2993 +        cmsUInt16Number Colorant[cmsMAXCHANNELS];
200.2994 +        char Root[33];
200.2995 +
200.2996 +        memset(Colorant, 0, sizeof(Colorant));
200.2997 +        if (io -> Read(io, Root, 32, 1) != 1) return NULL;
200.2998 +        if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
200.2999 +        if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
200.3000 +
200.3001 +        if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error;
200.3002 +    }
200.3003 +
200.3004 +    *nItems = 1;
200.3005 +    return (void*) v ;
200.3006 +
200.3007 +Error:
200.3008 +    cmsFreeNamedColorList(v);
200.3009 +    return NULL;
200.3010 +
200.3011 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.3012 +}
200.3013 +
200.3014 +
200.3015 +// Saves a named color list into a named color profile
200.3016 +static
200.3017 +cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.3018 +{
200.3019 +    cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
200.3020 +    char                prefix[32];     // Prefix for each color name
200.3021 +    char                suffix[32];     // Suffix for each color name
200.3022 +    int i, nColors;
200.3023 +
200.3024 +    nColors = cmsNamedColorCount(NamedColorList);
200.3025 +
200.3026 +    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
200.3027 +    if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
200.3028 +    if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE;
200.3029 +
200.3030 +    strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
200.3031 +    strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
200.3032 +
200.3033 +    suffix[31] = prefix[31] = 0;
200.3034 +
200.3035 +    if (!io ->Write(io, 32, prefix)) return FALSE;
200.3036 +    if (!io ->Write(io, 32, suffix)) return FALSE;
200.3037 +
200.3038 +    for (i=0; i < nColors; i++) {
200.3039 +
200.3040 +       cmsUInt16Number PCS[3];
200.3041 +       cmsUInt16Number Colorant[cmsMAXCHANNELS];
200.3042 +       char Root[33];
200.3043 +
200.3044 +        if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;
200.3045 +        if (!io ->Write(io, 32 , Root)) return FALSE;
200.3046 +        if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
200.3047 +        if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE;
200.3048 +    }
200.3049 +
200.3050 +    return TRUE;
200.3051 +
200.3052 +    cmsUNUSED_PARAMETER(nItems);
200.3053 +    cmsUNUSED_PARAMETER(self);
200.3054 +}
200.3055 +
200.3056 +static
200.3057 +void* Type_NamedColor_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
200.3058 +{
200.3059 +    cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
200.3060 +
200.3061 +    return (void*) cmsDupNamedColorList(nc);
200.3062 +
200.3063 +    cmsUNUSED_PARAMETER(n);
200.3064 +    cmsUNUSED_PARAMETER(self);
200.3065 +}
200.3066 +
200.3067 +
200.3068 +static
200.3069 +void Type_NamedColor_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.3070 +{
200.3071 +    cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);
200.3072 +    return;
200.3073 +
200.3074 +    cmsUNUSED_PARAMETER(self);
200.3075 +}
200.3076 +
200.3077 +
200.3078 +// ********************************************************************************
200.3079 +// Type cmsSigProfileSequenceDescType
200.3080 +// ********************************************************************************
200.3081 +
200.3082 +static
200.3083 +cmsBool ReadEmbeddedText(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU** mlu, cmsUInt32Number SizeOfTag)
200.3084 +{
200.3085 +    cmsTagTypeSignature  BaseType;
200.3086 +    cmsUInt32Number nItems;
200.3087 +
200.3088 +    BaseType = _cmsReadTypeBase(io);
200.3089 +
200.3090 +    switch (BaseType) {
200.3091 +
200.3092 +       case cmsSigTextType:
200.3093 +           if (*mlu) cmsMLUfree(*mlu);
200.3094 +           *mlu = (cmsMLU*)Type_Text_Read(self, io, &nItems, SizeOfTag);
200.3095 +           return (*mlu != NULL);
200.3096 +
200.3097 +       case cmsSigTextDescriptionType:
200.3098 +           if (*mlu) cmsMLUfree(*mlu);
200.3099 +           *mlu =  (cmsMLU*) Type_Text_Description_Read(self, io, &nItems, SizeOfTag);
200.3100 +           return (*mlu != NULL);
200.3101 +
200.3102 +           /*
200.3103 +           TBD: Size is needed for MLU, and we have no idea on which is the available size
200.3104 +           */
200.3105 +
200.3106 +       case cmsSigMultiLocalizedUnicodeType:
200.3107 +           if (*mlu) cmsMLUfree(*mlu);
200.3108 +           *mlu =  (cmsMLU*) Type_MLU_Read(self, io, &nItems, SizeOfTag);
200.3109 +           return (*mlu != NULL);
200.3110 +
200.3111 +       default: return FALSE;
200.3112 +    }
200.3113 +}
200.3114 +
200.3115 +
200.3116 +static
200.3117 +void *Type_ProfileSequenceDesc_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.3118 +{
200.3119 +    cmsSEQ* OutSeq;
200.3120 +    cmsUInt32Number i, Count;
200.3121 +
200.3122 +    *nItems = 0;
200.3123 +
200.3124 +    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
200.3125 +    SizeOfTag -= sizeof(cmsUInt32Number);
200.3126 +
200.3127 +
200.3128 +    OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count);
200.3129 +    if (OutSeq == NULL) return NULL;
200.3130 +
200.3131 +    OutSeq ->n = Count;
200.3132 +
200.3133 +    // Get structures as well
200.3134 +
200.3135 +    for (i=0; i < Count; i++) {
200.3136 +
200.3137 +        cmsPSEQDESC* sec = &OutSeq -> seq[i];
200.3138 +
200.3139 +        if (!_cmsReadUInt32Number(io, &sec ->deviceMfg)) return NULL;
200.3140 +        SizeOfTag -= sizeof(cmsUInt32Number);
200.3141 +
200.3142 +        if (!_cmsReadUInt32Number(io, &sec ->deviceModel)) return NULL;
200.3143 +        SizeOfTag -= sizeof(cmsUInt32Number);
200.3144 +
200.3145 +        if (!_cmsReadUInt64Number(io, &sec ->attributes)) return NULL;
200.3146 +        SizeOfTag -= sizeof(cmsUInt64Number);
200.3147 +
200.3148 +        if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) return NULL;
200.3149 +        SizeOfTag -= sizeof(cmsUInt32Number);
200.3150 +
200.3151 +        if (!ReadEmbeddedText(self, io, &sec ->Manufacturer, SizeOfTag)) return NULL;
200.3152 +        if (!ReadEmbeddedText(self, io, &sec ->Model, SizeOfTag)) return NULL;
200.3153 +    }
200.3154 +
200.3155 +    *nItems = 1;
200.3156 +    return OutSeq;
200.3157 +}
200.3158 +
200.3159 +
200.3160 +// Aux--Embed a text description type. It can be of type text description or multilocalized unicode
200.3161 +static
200.3162 +cmsBool  SaveDescription(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* Text)
200.3163 +{
200.3164 +    if (Text == NULL) {
200.3165 +
200.3166 +        // Placeholder for a null entry
200.3167 +        if (!_cmsWriteTypeBase(io, cmsSigTextDescriptionType)) return FALSE;
200.3168 +        return Type_Text_Description_Write(self, io, NULL, 1);
200.3169 +
200.3170 +    }
200.3171 +
200.3172 +    if (Text->UsedEntries <= 1) {
200.3173 +        if (!_cmsWriteTypeBase(io, cmsSigTextDescriptionType)) return FALSE;
200.3174 +        return Type_Text_Description_Write(self, io, Text, 1);
200.3175 +    }
200.3176 +    else {
200.3177 +        if (!_cmsWriteTypeBase(io, cmsSigMultiLocalizedUnicodeType)) return FALSE;
200.3178 +        return Type_MLU_Write(self, io, Text, 1);
200.3179 +    }
200.3180 +}
200.3181 +
200.3182 +
200.3183 +static
200.3184 +cmsBool  Type_ProfileSequenceDesc_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.3185 +{
200.3186 +    cmsSEQ* Seq = (cmsSEQ*) Ptr;
200.3187 +    cmsUInt32Number i;
200.3188 +
200.3189 +    if (!_cmsWriteUInt32Number(io, Seq->n)) return FALSE;
200.3190 +
200.3191 +    for (i=0; i < Seq ->n; i++) {
200.3192 +
200.3193 +        cmsPSEQDESC* sec = &Seq -> seq[i];
200.3194 +
200.3195 +        if (!_cmsWriteUInt32Number(io, sec ->deviceMfg)) return FALSE;
200.3196 +        if (!_cmsWriteUInt32Number(io, sec ->deviceModel)) return FALSE;
200.3197 +        if (!_cmsWriteUInt64Number(io, sec ->attributes)) return FALSE;
200.3198 +        if (!_cmsWriteUInt32Number(io, sec ->technology)) return FALSE;
200.3199 +
200.3200 +        if (!SaveDescription(self, io, sec ->Manufacturer)) return FALSE;
200.3201 +        if (!SaveDescription(self, io, sec ->Model)) return FALSE;
200.3202 +    }
200.3203 +
200.3204 +     return TRUE;
200.3205 +
200.3206 +     cmsUNUSED_PARAMETER(nItems);
200.3207 +}
200.3208 +
200.3209 +
200.3210 +static
200.3211 +void* Type_ProfileSequenceDesc_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
200.3212 +{
200.3213 +    return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr);
200.3214 +
200.3215 +    cmsUNUSED_PARAMETER(n);
200.3216 +    cmsUNUSED_PARAMETER(self);
200.3217 +}
200.3218 +
200.3219 +static
200.3220 +void Type_ProfileSequenceDesc_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.3221 +{
200.3222 +    cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr);
200.3223 +    return;
200.3224 +
200.3225 +    cmsUNUSED_PARAMETER(self);
200.3226 +}
200.3227 +
200.3228 +
200.3229 +// ********************************************************************************
200.3230 +// Type cmsSigProfileSequenceIdType
200.3231 +// ********************************************************************************
200.3232 +/*
200.3233 +In certain workflows using ICC Device Link Profiles, it is necessary to identify the
200.3234 +original profiles that were combined to create the Device Link Profile.
200.3235 +This type is an array of structures, each of which contains information for
200.3236 +identification of a profile used in a sequence
200.3237 +*/
200.3238 +
200.3239 +
200.3240 +static
200.3241 +cmsBool ReadSeqID(struct _cms_typehandler_struct* self,
200.3242 +                                             cmsIOHANDLER* io,
200.3243 +                                             void* Cargo,
200.3244 +                                             cmsUInt32Number n,
200.3245 +                                             cmsUInt32Number SizeOfTag)
200.3246 +{
200.3247 +    cmsSEQ* OutSeq = (cmsSEQ*) Cargo;
200.3248 +    cmsPSEQDESC* seq = &OutSeq ->seq[n];
200.3249 +
200.3250 +    if (io -> Read(io, seq ->ProfileID.ID8, 16, 1) != 1) return FALSE;
200.3251 +    if (!ReadEmbeddedText(self, io, &seq ->Description, SizeOfTag)) return FALSE;
200.3252 +
200.3253 +    return TRUE;
200.3254 +}
200.3255 +
200.3256 +
200.3257 +
200.3258 +static
200.3259 +void *Type_ProfileSequenceId_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.3260 +{
200.3261 +    cmsSEQ* OutSeq;
200.3262 +    cmsUInt32Number Count;
200.3263 +    cmsUInt32Number BaseOffset;
200.3264 +
200.3265 +    *nItems = 0;
200.3266 +
200.3267 +    // Get actual position as a basis for element offsets
200.3268 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.3269 +
200.3270 +    // Get table count
200.3271 +    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
200.3272 +    SizeOfTag -= sizeof(cmsUInt32Number);
200.3273 +
200.3274 +    // Allocate an empty structure
200.3275 +    OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count);
200.3276 +    if (OutSeq == NULL) return NULL;
200.3277 +
200.3278 +
200.3279 +    // Read the position table
200.3280 +    if (!ReadPositionTable(self, io, Count, BaseOffset, OutSeq, ReadSeqID)) {
200.3281 +
200.3282 +        cmsFreeProfileSequenceDescription(OutSeq);
200.3283 +        return NULL;
200.3284 +    }
200.3285 +
200.3286 +    // Success
200.3287 +    *nItems = 1;
200.3288 +    return OutSeq;
200.3289 +
200.3290 +}
200.3291 +
200.3292 +
200.3293 +static
200.3294 +cmsBool WriteSeqID(struct _cms_typehandler_struct* self,
200.3295 +                                             cmsIOHANDLER* io,
200.3296 +                                             void* Cargo,
200.3297 +                                             cmsUInt32Number n,
200.3298 +                                             cmsUInt32Number SizeOfTag)
200.3299 +{
200.3300 +    cmsSEQ* Seq = (cmsSEQ*) Cargo;
200.3301 +
200.3302 +    if (!io ->Write(io, 16, Seq ->seq[n].ProfileID.ID8)) return FALSE;
200.3303 +
200.3304 +    // Store here the MLU
200.3305 +    if (!SaveDescription(self, io, Seq ->seq[n].Description)) return FALSE;
200.3306 +
200.3307 +    return TRUE;
200.3308 +
200.3309 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.3310 +}
200.3311 +
200.3312 +static
200.3313 +cmsBool  Type_ProfileSequenceId_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.3314 +{
200.3315 +    cmsSEQ* Seq = (cmsSEQ*) Ptr;
200.3316 +    cmsUInt32Number BaseOffset;
200.3317 +
200.3318 +    // Keep the base offset
200.3319 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.3320 +
200.3321 +    // This is the table count
200.3322 +    if (!_cmsWriteUInt32Number(io, Seq ->n)) return FALSE;
200.3323 +
200.3324 +    // This is the position table and content
200.3325 +    if (!WritePositionTable(self, io, 0, Seq ->n, BaseOffset, Seq, WriteSeqID)) return FALSE;
200.3326 +
200.3327 +    return TRUE;
200.3328 +
200.3329 +    cmsUNUSED_PARAMETER(nItems);
200.3330 +}
200.3331 +
200.3332 +static
200.3333 +void* Type_ProfileSequenceId_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
200.3334 +{
200.3335 +    return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr);
200.3336 +
200.3337 +    cmsUNUSED_PARAMETER(n);
200.3338 +    cmsUNUSED_PARAMETER(self);
200.3339 +}
200.3340 +
200.3341 +static
200.3342 +void Type_ProfileSequenceId_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.3343 +{
200.3344 +    cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr);
200.3345 +    return;
200.3346 +
200.3347 +    cmsUNUSED_PARAMETER(self);
200.3348 +}
200.3349 +
200.3350 +
200.3351 +// ********************************************************************************
200.3352 +// Type cmsSigUcrBgType
200.3353 +// ********************************************************************************
200.3354 +/*
200.3355 +This type contains curves representing the under color removal and black
200.3356 +generation and a text string which is a general description of the method used
200.3357 +for the ucr/bg.
200.3358 +*/
200.3359 +
200.3360 +static
200.3361 +void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.3362 +{
200.3363 +    cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
200.3364 +    cmsUInt32Number CountUcr, CountBg;
200.3365 +    char* ASCIIString;
200.3366 +
200.3367 +    *nItems = 0;
200.3368 +    if (n == NULL) return NULL;
200.3369 +
200.3370 +    // First curve is Under color removal
200.3371 +    if (!_cmsReadUInt32Number(io, &CountUcr)) return NULL;
200.3372 +    SizeOfTag -= sizeof(cmsUInt32Number);
200.3373 +
200.3374 +    n ->Ucr = cmsBuildTabulatedToneCurve16(self ->ContextID, CountUcr, NULL);
200.3375 +    if (n ->Ucr == NULL) return NULL;
200.3376 +
200.3377 +    if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) return NULL;
200.3378 +    SizeOfTag -= CountUcr * sizeof(cmsUInt16Number);
200.3379 +
200.3380 +    // Second curve is Black generation
200.3381 +    if (!_cmsReadUInt32Number(io, &CountBg)) return NULL;
200.3382 +    SizeOfTag -= sizeof(cmsUInt32Number);
200.3383 +
200.3384 +    n ->Bg = cmsBuildTabulatedToneCurve16(self ->ContextID, CountBg, NULL);
200.3385 +    if (n ->Bg == NULL) return NULL;
200.3386 +    if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) return NULL;
200.3387 +    SizeOfTag -= CountBg * sizeof(cmsUInt16Number);
200.3388 +
200.3389 +    // Now comes the text. The length is specified by the tag size
200.3390 +    n ->Desc = cmsMLUalloc(self ->ContextID, 1);
200.3391 +    ASCIIString = (char*) _cmsMalloc(self ->ContextID, sizeof(cmsUInt8Number)*(SizeOfTag + 1));
200.3392 +    if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL;
200.3393 +    ASCIIString[SizeOfTag] = 0;
200.3394 +    cmsMLUsetASCII(n ->Desc, cmsNoLanguage, cmsNoCountry, ASCIIString);
200.3395 +    _cmsFree(self ->ContextID, ASCIIString);
200.3396 +
200.3397 +    *nItems = 1;
200.3398 +    return (void*) n;
200.3399 +}
200.3400 +
200.3401 +static
200.3402 +cmsBool  Type_UcrBg_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.3403 +{
200.3404 +    cmsUcrBg* Value = (cmsUcrBg*) Ptr;
200.3405 +    cmsUInt32Number TextSize;
200.3406 +    char* Text;
200.3407 +
200.3408 +    // First curve is Under color removal
200.3409 +    if (!_cmsWriteUInt32Number(io, Value ->Ucr ->nEntries)) return FALSE;
200.3410 +    if (!_cmsWriteUInt16Array(io, Value ->Ucr ->nEntries, Value ->Ucr ->Table16)) return FALSE;
200.3411 +
200.3412 +    // Then black generation
200.3413 +    if (!_cmsWriteUInt32Number(io, Value ->Bg ->nEntries)) return FALSE;
200.3414 +    if (!_cmsWriteUInt16Array(io, Value ->Bg ->nEntries, Value ->Bg ->Table16)) return FALSE;
200.3415 +
200.3416 +    // Now comes the text. The length is specified by the tag size
200.3417 +    TextSize = cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, NULL, 0);
200.3418 +    Text     = (char*) _cmsMalloc(self ->ContextID, TextSize);
200.3419 +    if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, Text, TextSize) != TextSize) return FALSE;
200.3420 +
200.3421 +    if (!io ->Write(io, TextSize, Text)) return FALSE;
200.3422 +    _cmsFree(self ->ContextID, Text);
200.3423 +
200.3424 +    return TRUE;
200.3425 +
200.3426 +    cmsUNUSED_PARAMETER(nItems);
200.3427 +}
200.3428 +
200.3429 +static
200.3430 +void* Type_UcrBg_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.3431 +{
200.3432 +    cmsUcrBg* Src = (cmsUcrBg*) Ptr;
200.3433 +    cmsUcrBg* NewUcrBg = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
200.3434 +
200.3435 +    if (NewUcrBg == NULL) return NULL;
200.3436 +
200.3437 +    NewUcrBg ->Bg   = cmsDupToneCurve(Src ->Bg);
200.3438 +    NewUcrBg ->Ucr  = cmsDupToneCurve(Src ->Ucr);
200.3439 +    NewUcrBg ->Desc = cmsMLUdup(Src ->Desc);
200.3440 +
200.3441 +    return (void*) NewUcrBg;
200.3442 +
200.3443 +    cmsUNUSED_PARAMETER(n);
200.3444 +}
200.3445 +
200.3446 +static
200.3447 +void Type_UcrBg_Free(struct _cms_typehandler_struct* self, void *Ptr)
200.3448 +{
200.3449 +   cmsUcrBg* Src = (cmsUcrBg*) Ptr;
200.3450 +
200.3451 +   if (Src ->Ucr) cmsFreeToneCurve(Src ->Ucr);
200.3452 +   if (Src ->Bg)  cmsFreeToneCurve(Src ->Bg);
200.3453 +   if (Src ->Desc) cmsMLUfree(Src ->Desc);
200.3454 +
200.3455 +   _cmsFree(self ->ContextID, Ptr);
200.3456 +}
200.3457 +
200.3458 +// ********************************************************************************
200.3459 +// Type cmsSigCrdInfoType
200.3460 +// ********************************************************************************
200.3461 +
200.3462 +/*
200.3463 +This type contains the PostScript product name to which this profile corresponds
200.3464 +and the names of the companion CRDs. Recall that a single profile can generate
200.3465 +multiple CRDs. It is implemented as a MLU being the language code "PS" and then
200.3466 +country varies for each element:
200.3467 +
200.3468 +                nm: PostScript product name
200.3469 +                #0: Rendering intent 0 CRD name
200.3470 +                #1: Rendering intent 1 CRD name
200.3471 +                #2: Rendering intent 2 CRD name
200.3472 +                #3: Rendering intent 3 CRD name
200.3473 +*/
200.3474 +
200.3475 +
200.3476 +
200.3477 +// Auxiliar, read an string specified as count + string
200.3478 +static
200.3479 +cmsBool  ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section)
200.3480 +{
200.3481 +    cmsUInt32Number Count;
200.3482 +    char* Text;
200.3483 +
200.3484 +    if (*SizeOfTag < sizeof(cmsUInt32Number)) return FALSE;
200.3485 +
200.3486 +    if (!_cmsReadUInt32Number(io, &Count)) return FALSE;
200.3487 +
200.3488 +    if (*SizeOfTag < Count + sizeof(cmsUInt32Number)) return FALSE;
200.3489 +    Text     = (char*) _cmsMalloc(self ->ContextID, Count+1);
200.3490 +    if (Text == NULL) return FALSE;
200.3491 +
200.3492 +    if (io ->Read(io, Text, sizeof(cmsUInt8Number), Count) != Count) {
200.3493 +        _cmsFree(self ->ContextID, Text);
200.3494 +        return FALSE;
200.3495 +    }
200.3496 +
200.3497 +    Text[Count] = 0;
200.3498 +
200.3499 +    cmsMLUsetASCII(mlu, "PS", Section, Text);
200.3500 +    _cmsFree(self ->ContextID, Text);
200.3501 +
200.3502 +    *SizeOfTag -= (Count + sizeof(cmsUInt32Number));
200.3503 +    return TRUE;
200.3504 +}
200.3505 +
200.3506 +static
200.3507 +cmsBool  WriteCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, const char* Section)
200.3508 +{
200.3509 + cmsUInt32Number TextSize;
200.3510 + char* Text;
200.3511 +
200.3512 +    TextSize = cmsMLUgetASCII(mlu, "PS", Section, NULL, 0);
200.3513 +    Text     = (char*) _cmsMalloc(self ->ContextID, TextSize);
200.3514 +
200.3515 +    if (!_cmsWriteUInt32Number(io, TextSize)) return FALSE;
200.3516 +
200.3517 +    if (cmsMLUgetASCII(mlu, "PS", Section, Text, TextSize) == 0) return FALSE;
200.3518 +
200.3519 +    if (!io ->Write(io, TextSize, Text)) return FALSE;
200.3520 +    _cmsFree(self ->ContextID, Text);
200.3521 +
200.3522 +    return TRUE;
200.3523 +}
200.3524 +
200.3525 +static
200.3526 +void *Type_CrdInfo_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.3527 +{
200.3528 +    cmsMLU* mlu = cmsMLUalloc(self ->ContextID, 5);
200.3529 +
200.3530 +    *nItems = 0;
200.3531 +    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "nm")) goto Error;
200.3532 +    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#0")) goto Error;
200.3533 +    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#1")) goto Error;
200.3534 +    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#2")) goto Error;
200.3535 +    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#3")) goto Error;
200.3536 +
200.3537 +    *nItems = 1;
200.3538 +    return (void*) mlu;
200.3539 +
200.3540 +Error:
200.3541 +    cmsMLUfree(mlu);
200.3542 +    return NULL;
200.3543 +
200.3544 +}
200.3545 +
200.3546 +static
200.3547 +cmsBool  Type_CrdInfo_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.3548 +{
200.3549 +
200.3550 +    cmsMLU* mlu = (cmsMLU*) Ptr;
200.3551 +
200.3552 +    if (!WriteCountAndSting(self, io, mlu, "nm")) goto Error;
200.3553 +    if (!WriteCountAndSting(self, io, mlu, "#0")) goto Error;
200.3554 +    if (!WriteCountAndSting(self, io, mlu, "#1")) goto Error;
200.3555 +    if (!WriteCountAndSting(self, io, mlu, "#2")) goto Error;
200.3556 +    if (!WriteCountAndSting(self, io, mlu, "#3")) goto Error;
200.3557 +
200.3558 +    return TRUE;
200.3559 +
200.3560 +Error:
200.3561 +    return FALSE;
200.3562 +
200.3563 +    cmsUNUSED_PARAMETER(nItems);
200.3564 +}
200.3565 +
200.3566 +
200.3567 +static
200.3568 +void* Type_CrdInfo_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.3569 +{
200.3570 +    return (void*) cmsMLUdup((cmsMLU*) Ptr);
200.3571 +
200.3572 +    cmsUNUSED_PARAMETER(n);
200.3573 +    cmsUNUSED_PARAMETER(self);
200.3574 +}
200.3575 +
200.3576 +static
200.3577 +void Type_CrdInfo_Free(struct _cms_typehandler_struct* self, void *Ptr)
200.3578 +{
200.3579 +    cmsMLUfree((cmsMLU*) Ptr);
200.3580 +    return;
200.3581 +
200.3582 +    cmsUNUSED_PARAMETER(self);
200.3583 +}
200.3584 +
200.3585 +// ********************************************************************************
200.3586 +// Type cmsSigScreeningType
200.3587 +// ********************************************************************************
200.3588 +//
200.3589 +//The screeningType describes various screening parameters including screen
200.3590 +//frequency, screening angle, and spot shape.
200.3591 +
200.3592 +static
200.3593 +void *Type_Screening_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.3594 +{
200.3595 +    cmsScreening* sc = NULL;
200.3596 +    cmsUInt32Number i;
200.3597 +
200.3598 +    sc = (cmsScreening*) _cmsMallocZero(self ->ContextID, sizeof(cmsScreening));
200.3599 +    if (sc == NULL) return NULL;
200.3600 +
200.3601 +    *nItems = 0;
200.3602 +
200.3603 +    if (!_cmsReadUInt32Number(io, &sc ->Flag)) goto Error;
200.3604 +    if (!_cmsReadUInt32Number(io, &sc ->nChannels)) goto Error;
200.3605 +
200.3606 +    for (i=0; i < sc ->nChannels; i++) {
200.3607 +
200.3608 +        if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].Frequency)) goto Error;
200.3609 +        if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].ScreenAngle)) goto Error;
200.3610 +        if (!_cmsReadUInt32Number(io, &sc ->Channels[i].SpotShape)) goto Error;
200.3611 +    }
200.3612 +
200.3613 +
200.3614 +    *nItems = 1;
200.3615 +
200.3616 +    return (void*) sc;
200.3617 +
200.3618 +Error:
200.3619 +    if (sc != NULL)
200.3620 +        _cmsFree(self ->ContextID, sc);
200.3621 +
200.3622 +    return NULL;
200.3623 +
200.3624 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.3625 +}
200.3626 +
200.3627 +
200.3628 +static
200.3629 +cmsBool Type_Screening_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.3630 +{
200.3631 +    cmsScreening* sc = (cmsScreening* ) Ptr;
200.3632 +    cmsUInt32Number i;
200.3633 +
200.3634 +    if (!_cmsWriteUInt32Number(io, sc ->Flag)) return FALSE;
200.3635 +    if (!_cmsWriteUInt32Number(io, sc ->nChannels)) return FALSE;
200.3636 +
200.3637 +    for (i=0; i < sc ->nChannels; i++) {
200.3638 +
200.3639 +        if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].Frequency)) return FALSE;
200.3640 +        if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].ScreenAngle)) return FALSE;
200.3641 +        if (!_cmsWriteUInt32Number(io, sc ->Channels[i].SpotShape)) return FALSE;
200.3642 +    }
200.3643 +
200.3644 +    return TRUE;
200.3645 +
200.3646 +    cmsUNUSED_PARAMETER(nItems);
200.3647 +    cmsUNUSED_PARAMETER(self);
200.3648 +}
200.3649 +
200.3650 +
200.3651 +static
200.3652 +void* Type_Screening_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.3653 +{
200.3654 +   return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
200.3655 +
200.3656 +   cmsUNUSED_PARAMETER(n);
200.3657 +}
200.3658 +
200.3659 +
200.3660 +static
200.3661 +void Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.3662 +{
200.3663 +   _cmsFree(self ->ContextID, Ptr);
200.3664 +}
200.3665 +
200.3666 +// ********************************************************************************
200.3667 +// Type cmsSigViewingConditionsType
200.3668 +// ********************************************************************************
200.3669 +//
200.3670 +//This type represents a set of viewing condition parameters including:
200.3671 +//CIE ’absolute’ illuminant white point tristimulus values and CIE ’absolute’
200.3672 +//surround tristimulus values.
200.3673 +
200.3674 +static
200.3675 +void *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.3676 +{
200.3677 +    cmsICCViewingConditions* vc = NULL;
200.3678 +
200.3679 +    vc = (cmsICCViewingConditions*) _cmsMallocZero(self ->ContextID, sizeof(cmsICCViewingConditions));
200.3680 +    if (vc == NULL) return NULL;
200.3681 +
200.3682 +    *nItems = 0;
200.3683 +
200.3684 +    if (!_cmsReadXYZNumber(io, &vc ->IlluminantXYZ)) goto Error;
200.3685 +    if (!_cmsReadXYZNumber(io, &vc ->SurroundXYZ)) goto Error;
200.3686 +    if (!_cmsReadUInt32Number(io, &vc ->IlluminantType)) goto Error;
200.3687 +
200.3688 +    *nItems = 1;
200.3689 +
200.3690 +    return (void*) vc;
200.3691 +
200.3692 +Error:
200.3693 +    if (vc != NULL)
200.3694 +        _cmsFree(self ->ContextID, vc);
200.3695 +
200.3696 +    return NULL;
200.3697 +
200.3698 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.3699 +}
200.3700 +
200.3701 +
200.3702 +static
200.3703 +cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.3704 +{
200.3705 +    cmsICCViewingConditions* sc = (cmsICCViewingConditions* ) Ptr;
200.3706 +
200.3707 +    if (!_cmsWriteXYZNumber(io, &sc ->IlluminantXYZ)) return FALSE;
200.3708 +    if (!_cmsWriteXYZNumber(io, &sc ->SurroundXYZ)) return FALSE;
200.3709 +    if (!_cmsWriteUInt32Number(io, sc ->IlluminantType)) return FALSE;
200.3710 +
200.3711 +    return TRUE;
200.3712 +
200.3713 +    cmsUNUSED_PARAMETER(nItems);
200.3714 +    cmsUNUSED_PARAMETER(self);
200.3715 +}
200.3716 +
200.3717 +
200.3718 +static
200.3719 +void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.3720 +{
200.3721 +   return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
200.3722 +
200.3723 +   cmsUNUSED_PARAMETER(n);
200.3724 +}
200.3725 +
200.3726 +
200.3727 +static
200.3728 +void Type_ViewingConditions_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.3729 +{
200.3730 +   _cmsFree(self ->ContextID, Ptr);
200.3731 +}
200.3732 +
200.3733 +
200.3734 +// ********************************************************************************
200.3735 +// Type cmsSigMultiProcessElementType
200.3736 +// ********************************************************************************
200.3737 +
200.3738 +
200.3739 +static
200.3740 +void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.3741 +{
200.3742 +    return (void*) cmsStageDup((cmsStage*) Ptr);
200.3743 +
200.3744 +    cmsUNUSED_PARAMETER(n);
200.3745 +    cmsUNUSED_PARAMETER(self);
200.3746 +}
200.3747 +
200.3748 +static
200.3749 +void GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr)
200.3750 +{
200.3751 +    cmsStageFree((cmsStage*) Ptr);
200.3752 +    return;
200.3753 +
200.3754 +    cmsUNUSED_PARAMETER(self);
200.3755 +}
200.3756 +
200.3757 +// Each curve is stored in one or more curve segments, with break-points specified between curve segments.
200.3758 +// The first curve segment always starts at –Infinity, and the last curve segment always ends at +Infinity. The
200.3759 +// first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be
200.3760 +// specified either in terms of a formula, or by a sampled curve.
200.3761 +
200.3762 +
200.3763 +// Read an embedded segmented curve
200.3764 +static
200.3765 +cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
200.3766 +{
200.3767 +    cmsCurveSegSignature ElementSig;
200.3768 +    cmsUInt32Number i, j;
200.3769 +    cmsUInt16Number nSegments;
200.3770 +    cmsCurveSegment*  Segments;
200.3771 +    cmsToneCurve* Curve;
200.3772 +    cmsFloat32Number PrevBreak = -1E22F;    // - infinite
200.3773 +
200.3774 +    // Take signature and channels for each element.
200.3775 +     if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL;
200.3776 +
200.3777 +     // That should be a segmented curve
200.3778 +     if (ElementSig != cmsSigSegmentedCurve) return NULL;
200.3779 +
200.3780 +     if (!_cmsReadUInt32Number(io, NULL)) return NULL;
200.3781 +     if (!_cmsReadUInt16Number(io, &nSegments)) return NULL;
200.3782 +     if (!_cmsReadUInt16Number(io, NULL)) return NULL;
200.3783 +
200.3784 +     Segments = (cmsCurveSegment*) _cmsCalloc(self ->ContextID, nSegments, sizeof(cmsCurveSegment));
200.3785 +     if (Segments == NULL) return NULL;
200.3786 +
200.3787 +     // Read breakpoints
200.3788 +     for (i=0; i < (cmsUInt32Number) nSegments - 1; i++) {
200.3789 +
200.3790 +         Segments[i].x0 = PrevBreak;
200.3791 +         if (!_cmsReadFloat32Number(io, &Segments[i].x1)) goto Error;
200.3792 +         PrevBreak = Segments[i].x1;
200.3793 +     }
200.3794 +
200.3795 +     Segments[nSegments-1].x0 = PrevBreak;
200.3796 +     Segments[nSegments-1].x1 = 1E22F;     // A big cmsFloat32Number number
200.3797 +
200.3798 +     // Read segments
200.3799 +     for (i=0; i < nSegments; i++) {
200.3800 +
200.3801 +          if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) goto Error;
200.3802 +          if (!_cmsReadUInt32Number(io, NULL)) goto Error;
200.3803 +
200.3804 +           switch (ElementSig) {
200.3805 +
200.3806 +            case cmsSigFormulaCurveSeg: {
200.3807 +
200.3808 +                cmsUInt16Number Type;
200.3809 +                cmsUInt32Number ParamsByType[] = {4, 5, 5 };
200.3810 +
200.3811 +                if (!_cmsReadUInt16Number(io, &Type)) goto Error;
200.3812 +                if (!_cmsReadUInt16Number(io, NULL)) goto Error;
200.3813 +
200.3814 +                Segments[i].Type = Type + 6;
200.3815 +                if (Type > 2) goto Error;
200.3816 +
200.3817 +                for (j=0; j < ParamsByType[Type]; j++) {
200.3818 +
200.3819 +                    cmsFloat32Number f;
200.3820 +                    if (!_cmsReadFloat32Number(io, &f)) goto Error;
200.3821 +                    Segments[i].Params[j] = f;
200.3822 +                }
200.3823 +                }
200.3824 +                break;
200.3825 +
200.3826 +
200.3827 +            case cmsSigSampledCurveSeg: {
200.3828 +                cmsUInt32Number Count;
200.3829 +
200.3830 +                if (!_cmsReadUInt32Number(io, &Count)) return NULL;
200.3831 +
200.3832 +                Segments[i].nGridPoints = Count;
200.3833 +                Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number));
200.3834 +                if (Segments[i].SampledPoints == NULL) goto Error;
200.3835 +
200.3836 +                for (j=0; j < Count; j++) {
200.3837 +                    if (!_cmsReadFloat32Number(io, &Segments[i].SampledPoints[j])) goto Error;
200.3838 +                }
200.3839 +                }
200.3840 +                break;
200.3841 +
200.3842 +            default:
200.3843 +                {
200.3844 +                char String[5];
200.3845 +
200.3846 +                _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
200.3847 +                cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String);
200.3848 +                }
200.3849 +                return NULL;
200.3850 +
200.3851 +         }
200.3852 +     }
200.3853 +
200.3854 +     Curve = cmsBuildSegmentedToneCurve(self ->ContextID, nSegments, Segments);
200.3855 +
200.3856 +     for (i=0; i < nSegments; i++) {
200.3857 +         if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints);
200.3858 +     }
200.3859 +     _cmsFree(self ->ContextID, Segments);
200.3860 +     return Curve;
200.3861 +
200.3862 +Error:
200.3863 +     if (Segments) _cmsFree(self ->ContextID, Segments);
200.3864 +     return NULL;
200.3865 +}
200.3866 +
200.3867 +
200.3868 +static
200.3869 +cmsBool ReadMPECurve(struct _cms_typehandler_struct* self,
200.3870 +                     cmsIOHANDLER* io,
200.3871 +                     void* Cargo,
200.3872 +                     cmsUInt32Number n,
200.3873 +                     cmsUInt32Number SizeOfTag)
200.3874 +{
200.3875 +      cmsToneCurve** GammaTables = ( cmsToneCurve**) Cargo;
200.3876 +
200.3877 +      GammaTables[n] = ReadSegmentedCurve(self, io);
200.3878 +      return (GammaTables[n] != NULL);
200.3879 +
200.3880 +      cmsUNUSED_PARAMETER(SizeOfTag);
200.3881 +}
200.3882 +
200.3883 +static
200.3884 +void *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.3885 +{
200.3886 +    cmsStage* mpe = NULL;
200.3887 +    cmsUInt16Number InputChans, OutputChans;
200.3888 +    cmsUInt32Number i, BaseOffset;
200.3889 +    cmsToneCurve** GammaTables;
200.3890 +
200.3891 +    *nItems = 0;
200.3892 +
200.3893 +    // Get actual position as a basis for element offsets
200.3894 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.3895 +
200.3896 +    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
200.3897 +    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
200.3898 +
200.3899 +    if (InputChans != OutputChans) return NULL;
200.3900 +
200.3901 +    GammaTables = (cmsToneCurve**) _cmsCalloc(self ->ContextID, InputChans, sizeof(cmsToneCurve*));
200.3902 +    if (GammaTables == NULL) return NULL;
200.3903 +
200.3904 +    if (ReadPositionTable(self, io, InputChans, BaseOffset, GammaTables, ReadMPECurve)) {
200.3905 +
200.3906 +        mpe = cmsStageAllocToneCurves(self ->ContextID, InputChans, GammaTables);
200.3907 +    }
200.3908 +    else {
200.3909 +        mpe = NULL;
200.3910 +    }
200.3911 +
200.3912 +    for (i=0; i < InputChans; i++) {
200.3913 +        if (GammaTables[i]) cmsFreeToneCurve(GammaTables[i]);
200.3914 +    }
200.3915 +
200.3916 +    _cmsFree(self ->ContextID, GammaTables);
200.3917 +    *nItems = (mpe != NULL) ? 1 : 0;
200.3918 +    return mpe;
200.3919 +
200.3920 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.3921 +}
200.3922 +
200.3923 +
200.3924 +// Write a single segmented curve. NO CHECK IS PERFORMED ON VALIDITY
200.3925 +static
200.3926 +cmsBool WriteSegmentedCurve(cmsIOHANDLER* io, cmsToneCurve* g)
200.3927 +{
200.3928 +    cmsUInt32Number i, j;
200.3929 +    cmsCurveSegment* Segments = g ->Segments;
200.3930 +    cmsUInt32Number nSegments = g ->nSegments;
200.3931 +
200.3932 +    if (!_cmsWriteUInt32Number(io, cmsSigSegmentedCurve)) goto Error;
200.3933 +    if (!_cmsWriteUInt32Number(io, 0)) goto Error;
200.3934 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) nSegments)) goto Error;
200.3935 +    if (!_cmsWriteUInt16Number(io, 0)) goto Error;
200.3936 +
200.3937 +    // Write the break-points
200.3938 +    for (i=0; i < nSegments - 1; i++) {
200.3939 +        if (!_cmsWriteFloat32Number(io, Segments[i].x1)) goto Error;
200.3940 +    }
200.3941 +
200.3942 +    // Write the segments
200.3943 +    for (i=0; i < g ->nSegments; i++) {
200.3944 +
200.3945 +        cmsCurveSegment* ActualSeg = Segments + i;
200.3946 +
200.3947 +        if (ActualSeg -> Type == 0) {
200.3948 +
200.3949 +            // This is a sampled curve
200.3950 +            if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigSampledCurveSeg)) goto Error;
200.3951 +            if (!_cmsWriteUInt32Number(io, 0)) goto Error;
200.3952 +            if (!_cmsWriteUInt32Number(io, ActualSeg -> nGridPoints)) goto Error;
200.3953 +
200.3954 +            for (j=0; j < g ->Segments[i].nGridPoints; j++) {
200.3955 +                if (!_cmsWriteFloat32Number(io, ActualSeg -> SampledPoints[j])) goto Error;
200.3956 +            }
200.3957 +
200.3958 +        }
200.3959 +        else {
200.3960 +            int Type;
200.3961 +            cmsUInt32Number ParamsByType[] = { 4, 5, 5 };
200.3962 +
200.3963 +            // This is a formula-based
200.3964 +            if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigFormulaCurveSeg)) goto Error;
200.3965 +            if (!_cmsWriteUInt32Number(io, 0)) goto Error;
200.3966 +
200.3967 +            // We only allow 1, 2 and 3 as types
200.3968 +            Type = ActualSeg ->Type - 6;
200.3969 +            if (Type > 2 || Type < 0) goto Error;
200.3970 +
200.3971 +            if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Type)) goto Error;
200.3972 +            if (!_cmsWriteUInt16Number(io, 0)) goto Error;
200.3973 +
200.3974 +            for (j=0; j < ParamsByType[Type]; j++) {
200.3975 +                if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) ActualSeg ->Params[j])) goto Error;
200.3976 +            }
200.3977 +        }
200.3978 +
200.3979 +        // It seems there is no need to align. Code is here, and for safety commented out
200.3980 +        // if (!_cmsWriteAlignment(io)) goto Error;
200.3981 +    }
200.3982 +
200.3983 +    return TRUE;
200.3984 +
200.3985 +Error:
200.3986 +    return FALSE;
200.3987 +}
200.3988 +
200.3989 +
200.3990 +static
200.3991 +cmsBool WriteMPECurve(struct _cms_typehandler_struct* self,
200.3992 +                      cmsIOHANDLER* io,
200.3993 +                      void* Cargo,
200.3994 +                      cmsUInt32Number n,
200.3995 +                      cmsUInt32Number SizeOfTag)
200.3996 +{
200.3997 +    _cmsStageToneCurvesData* Curves  = (_cmsStageToneCurvesData*) Cargo;
200.3998 +
200.3999 +    return WriteSegmentedCurve(io, Curves ->TheCurves[n]);
200.4000 +
200.4001 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.4002 +    cmsUNUSED_PARAMETER(self);
200.4003 +}
200.4004 +
200.4005 +// Write a curve, checking first for validity
200.4006 +static
200.4007 +cmsBool  Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.4008 +{
200.4009 +    cmsUInt32Number BaseOffset;
200.4010 +    cmsStage* mpe = (cmsStage*) Ptr;
200.4011 +    _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) mpe ->Data;
200.4012 +
200.4013 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.4014 +
200.4015 +    // Write the header. Since those are curves, input and output channels are same
200.4016 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
200.4017 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
200.4018 +
200.4019 +    if (!WritePositionTable(self, io, 0,
200.4020 +                                mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE;
200.4021 +
200.4022 +
200.4023 +    return TRUE;
200.4024 +
200.4025 +    cmsUNUSED_PARAMETER(nItems);
200.4026 +}
200.4027 +
200.4028 +
200.4029 +
200.4030 +// The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
200.4031 +// matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
200.4032 +// is organized as follows:
200.4033 +// array = [e11, e12, …, e1P, e21, e22, …, e2P, …, eQ1, eQ2, …, eQP, e1, e2, …, eQ]
200.4034 +
200.4035 +static
200.4036 +void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.4037 +{
200.4038 +    cmsStage* mpe;
200.4039 +    cmsUInt16Number   InputChans, OutputChans;
200.4040 +    cmsUInt32Number   nElems, i;
200.4041 +    cmsFloat64Number* Matrix;
200.4042 +    cmsFloat64Number* Offsets;
200.4043 +
200.4044 +    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
200.4045 +    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
200.4046 +
200.4047 +
200.4048 +    nElems = InputChans * OutputChans;
200.4049 +
200.4050 +    // Input and output chans may be ANY (up to 0xffff)
200.4051 +    Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number));
200.4052 +    if (Matrix == NULL) return NULL;
200.4053 +
200.4054 +    Offsets = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, OutputChans, sizeof(cmsFloat64Number));
200.4055 +    if (Offsets == NULL) {
200.4056 +
200.4057 +        _cmsFree(self ->ContextID, Matrix);
200.4058 +        return NULL;
200.4059 +    }
200.4060 +
200.4061 +    for (i=0; i < nElems; i++) {
200.4062 +
200.4063 +        cmsFloat32Number v;
200.4064 +
200.4065 +        if (!_cmsReadFloat32Number(io, &v)) return NULL;
200.4066 +        Matrix[i] = v;
200.4067 +    }
200.4068 +
200.4069 +
200.4070 +    for (i=0; i < OutputChans; i++) {
200.4071 +
200.4072 +        cmsFloat32Number v;
200.4073 +
200.4074 +        if (!_cmsReadFloat32Number(io, &v)) return NULL;
200.4075 +        Offsets[i] = v;
200.4076 +    }
200.4077 +
200.4078 +
200.4079 +    mpe = cmsStageAllocMatrix(self ->ContextID, OutputChans, InputChans, Matrix, Offsets);
200.4080 +    _cmsFree(self ->ContextID, Matrix);
200.4081 +    _cmsFree(self ->ContextID, Offsets);
200.4082 +
200.4083 +    *nItems = 1;
200.4084 +
200.4085 +    return mpe;
200.4086 +
200.4087 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.4088 +}
200.4089 +
200.4090 +static
200.4091 +cmsBool  Type_MPEmatrix_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.4092 +{
200.4093 +    cmsUInt32Number i, nElems;
200.4094 +    cmsStage* mpe = (cmsStage*) Ptr;
200.4095 +    _cmsStageMatrixData* Matrix = (_cmsStageMatrixData*) mpe ->Data;
200.4096 +
200.4097 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
200.4098 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
200.4099 +
200.4100 +    nElems = mpe ->InputChannels * mpe ->OutputChannels;
200.4101 +
200.4102 +    for (i=0; i < nElems; i++) {
200.4103 +        if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Double[i])) return FALSE;
200.4104 +    }
200.4105 +
200.4106 +
200.4107 +    for (i=0; i < mpe ->OutputChannels; i++) {
200.4108 +
200.4109 +        if (Matrix ->Offset == NULL) {
200.4110 +
200.4111 +               if (!_cmsWriteFloat32Number(io, 0)) return FALSE;
200.4112 +        }
200.4113 +        else {
200.4114 +               if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Offset[i])) return FALSE;
200.4115 +        }
200.4116 +    }
200.4117 +
200.4118 +    return TRUE;
200.4119 +
200.4120 +    cmsUNUSED_PARAMETER(nItems);
200.4121 +    cmsUNUSED_PARAMETER(self);
200.4122 +}
200.4123 +
200.4124 +
200.4125 +
200.4126 +static
200.4127 +void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.4128 +{
200.4129 +    cmsStage* mpe = NULL;
200.4130 +    cmsUInt16Number InputChans, OutputChans;
200.4131 +    cmsUInt8Number Dimensions8[16];
200.4132 +    cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS];
200.4133 +    _cmsStageCLutData* clut;
200.4134 +
200.4135 +    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
200.4136 +    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
200.4137 +
200.4138 +    if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
200.4139 +        goto Error;
200.4140 +
200.4141 +    // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number
200.4142 +    nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans;
200.4143 +    for (i=0; i < nMaxGrids; i++) GridPoints[i] = Dimensions8[i];
200.4144 +
200.4145 +    // Allocate the true CLUT
200.4146 +    mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
200.4147 +    if (mpe == NULL) goto Error;
200.4148 +
200.4149 +    // Read the data
200.4150 +    clut = (_cmsStageCLutData*) mpe ->Data;
200.4151 +    for (i=0; i < clut ->nEntries; i++) {
200.4152 +
200.4153 +        if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error;
200.4154 +    }
200.4155 +
200.4156 +    *nItems = 1;
200.4157 +    return mpe;
200.4158 +
200.4159 +Error:
200.4160 +    *nItems = 0;
200.4161 +    if (mpe != NULL) cmsStageFree(mpe);
200.4162 +    return NULL;
200.4163 +
200.4164 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.4165 +}
200.4166 +
200.4167 +// Write a CLUT in floating point
200.4168 +static
200.4169 +cmsBool  Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.4170 +{
200.4171 +    cmsUInt8Number Dimensions8[16];
200.4172 +    cmsUInt32Number i;
200.4173 +    cmsStage* mpe = (cmsStage*) Ptr;
200.4174 +    _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data;
200.4175 +
200.4176 +    // Check for maximum number of channels
200.4177 +    if (mpe -> InputChannels > 15) return FALSE;
200.4178 +
200.4179 +    // Only floats are supported in MPE
200.4180 +    if (clut ->HasFloatValues == FALSE) return FALSE;
200.4181 +
200.4182 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
200.4183 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
200.4184 +
200.4185 +    memset(Dimensions8, 0, sizeof(Dimensions8));
200.4186 +
200.4187 +    for (i=0; i < mpe ->InputChannels; i++)
200.4188 +        Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i];
200.4189 +
200.4190 +    if (!io ->Write(io, 16, Dimensions8)) return FALSE;
200.4191 +
200.4192 +    for (i=0; i < clut ->nEntries; i++) {
200.4193 +
200.4194 +        if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE;
200.4195 +    }
200.4196 +
200.4197 +    return TRUE;
200.4198 +
200.4199 +    cmsUNUSED_PARAMETER(nItems);
200.4200 +    cmsUNUSED_PARAMETER(self);
200.4201 +}
200.4202 +
200.4203 +
200.4204 +
200.4205 +// This is the list of built-in MPE types
200.4206 +static _cmsTagTypeLinkedList SupportedMPEtypes[] = {
200.4207 +
200.4208 +{{ (cmsTagTypeSignature) cmsSigBAcsElemType, NULL, NULL, NULL, NULL }, &SupportedMPEtypes[1] },   // Ignore those elements for now
200.4209 +{{ (cmsTagTypeSignature) cmsSigEAcsElemType, NULL, NULL, NULL, NULL }, &SupportedMPEtypes[2] },   // (That's what the spec says)
200.4210 +
200.4211 +{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCurveSetElemType,     MPEcurve),      &SupportedMPEtypes[3] },
200.4212 +{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigMatrixElemType,       MPEmatrix),     &SupportedMPEtypes[4] },
200.4213 +{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType,         MPEclut),        NULL },
200.4214 +};
200.4215 +
200.4216 +#define DEFAULT_MPE_TYPE_COUNT  (sizeof(SupportedMPEtypes) / sizeof(_cmsTagTypeLinkedList))
200.4217 +
200.4218 +static
200.4219 +cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
200.4220 +                    cmsIOHANDLER* io,
200.4221 +                    void* Cargo,
200.4222 +                    cmsUInt32Number n,
200.4223 +                    cmsUInt32Number SizeOfTag)
200.4224 +{
200.4225 +    cmsStageSignature ElementSig;
200.4226 +    cmsTagTypeHandler* TypeHandler;
200.4227 +    cmsStage *mpe = NULL;
200.4228 +    cmsUInt32Number nItems;
200.4229 +    cmsPipeline *NewLUT = (cmsPipeline *) Cargo;
200.4230 +
200.4231 +    // Take signature and channels for each element.
200.4232 +    if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE;
200.4233 +
200.4234 +    // The reserved placeholder
200.4235 +    if (!_cmsReadUInt32Number(io, NULL)) return FALSE;
200.4236 +
200.4237 +    // Read diverse MPE types
200.4238 +    TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes);
200.4239 +    if (TypeHandler == NULL)  {
200.4240 +
200.4241 +        char String[5];
200.4242 +
200.4243 +        _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
200.4244 +
200.4245 +        // An unknown element was found.
200.4246 +        cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown MPE type '%s' found.", String);
200.4247 +        return FALSE;
200.4248 +    }
200.4249 +
200.4250 +    // If no read method, just ignore the element (valid for cmsSigBAcsElemType and cmsSigEAcsElemType)
200.4251 +    // Read the MPE. No size is given
200.4252 +    if (TypeHandler ->ReadPtr != NULL) {
200.4253 +
200.4254 +        // This is a real element which should be read and processed
200.4255 +        mpe = (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag);
200.4256 +        if (mpe == NULL) return FALSE;
200.4257 +
200.4258 +        // All seems ok, insert element
200.4259 +        cmsPipelineInsertStage(NewLUT, cmsAT_END, mpe);
200.4260 +    }
200.4261 +
200.4262 +    return TRUE;
200.4263 +
200.4264 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.4265 +    cmsUNUSED_PARAMETER(n);
200.4266 +}
200.4267 +
200.4268 +
200.4269 +// This is the main dispatcher for MPE
200.4270 +static
200.4271 +void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
200.4272 +{
200.4273 +    cmsUInt16Number InputChans, OutputChans;
200.4274 +    cmsUInt32Number ElementCount;
200.4275 +    cmsPipeline *NewLUT = NULL;
200.4276 +    cmsUInt32Number BaseOffset;
200.4277 +
200.4278 +    // Get actual position as a basis for element offsets
200.4279 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.4280 +
200.4281 +    // Read channels and element count
200.4282 +    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
200.4283 +    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
200.4284 +
200.4285 +    // Allocates an empty LUT
200.4286 +    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
200.4287 +    if (NewLUT == NULL) return NULL;
200.4288 +
200.4289 +    if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL;
200.4290 +
200.4291 +    if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) {
200.4292 +        if (NewLUT != NULL) cmsPipelineFree(NewLUT);
200.4293 +        *nItems = 0;
200.4294 +        return NULL;
200.4295 +    }
200.4296 +
200.4297 +    // Success
200.4298 +    *nItems = 1;
200.4299 +    return NewLUT;
200.4300 +
200.4301 +    cmsUNUSED_PARAMETER(SizeOfTag);
200.4302 +}
200.4303 +
200.4304 +
200.4305 +
200.4306 +// This one is a liitle bit more complex, so we don't use position tables this time.
200.4307 +static
200.4308 +cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.4309 +{
200.4310 +    cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos;
200.4311 +    int inputChan, outputChan;
200.4312 +    cmsUInt32Number ElemCount;
200.4313 +    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL, Before;
200.4314 +    cmsStageSignature ElementSig;
200.4315 +    cmsPipeline* Lut = (cmsPipeline*) Ptr;
200.4316 +    cmsStage* Elem = Lut ->Elements;
200.4317 +    cmsTagTypeHandler* TypeHandler;
200.4318 +
200.4319 +    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
200.4320 +
200.4321 +    inputChan  = cmsPipelineInputChannels(Lut);
200.4322 +    outputChan = cmsPipelineOutputChannels(Lut);
200.4323 +    ElemCount  = cmsPipelineStageCount(Lut);
200.4324 +
200.4325 +    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *));
200.4326 +    if (ElementOffsets == NULL) goto Error;
200.4327 +
200.4328 +    ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number *));
200.4329 +    if (ElementSizes == NULL) goto Error;
200.4330 +
200.4331 +    // Write the head
200.4332 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) inputChan)) goto Error;
200.4333 +    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) outputChan)) goto Error;
200.4334 +    if (!_cmsWriteUInt32Number(io, (cmsUInt16Number) ElemCount)) goto Error;
200.4335 +
200.4336 +    DirectoryPos = io ->Tell(io);
200.4337 +
200.4338 +    // Write a fake directory to be filled latter on
200.4339 +    for (i=0; i < ElemCount; i++) {
200.4340 +        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // Offset
200.4341 +        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // size
200.4342 +    }
200.4343 +
200.4344 +    // Write each single tag. Keep track of the size as well.
200.4345 +    for (i=0; i < ElemCount; i++) {
200.4346 +
200.4347 +        ElementOffsets[i] = io ->Tell(io) - BaseOffset;
200.4348 +
200.4349 +        ElementSig = Elem ->Type;
200.4350 +
200.4351 +        TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, SupportedMPEtypes);
200.4352 +        if (TypeHandler == NULL)  {
200.4353 +
200.4354 +                char String[5];
200.4355 +
200.4356 +                _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
200.4357 +
200.4358 +                 // An unknow element was found.
200.4359 +                 cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Found unknown MPE type '%s'", String);
200.4360 +                 goto Error;
200.4361 +        }
200.4362 +
200.4363 +        if (!_cmsWriteUInt32Number(io, ElementSig)) goto Error;
200.4364 +        if (!_cmsWriteUInt32Number(io, 0)) goto Error;
200.4365 +        Before = io ->Tell(io);
200.4366 +        if (!TypeHandler ->WritePtr(self, io, Elem, 1)) goto Error;
200.4367 +        if (!_cmsWriteAlignment(io)) goto Error;
200.4368 +
200.4369 +        ElementSizes[i] = io ->Tell(io) - Before;
200.4370 +
200.4371 +        Elem = Elem ->Next;
200.4372 +    }
200.4373 +
200.4374 +    // Write the directory
200.4375 +    CurrentPos = io ->Tell(io);
200.4376 +
200.4377 +    if (!io ->Seek(io, DirectoryPos)) goto Error;
200.4378 +
200.4379 +    for (i=0; i < ElemCount; i++) {
200.4380 +        if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error;
200.4381 +        if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error;
200.4382 +    }
200.4383 +
200.4384 +    if (!io ->Seek(io, CurrentPos)) goto Error;
200.4385 +
200.4386 +    if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
200.4387 +    if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
200.4388 +    return TRUE;
200.4389 +
200.4390 +Error:
200.4391 +    if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
200.4392 +    if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
200.4393 +    return FALSE;
200.4394 +
200.4395 +    cmsUNUSED_PARAMETER(nItems);
200.4396 +}
200.4397 +
200.4398 +
200.4399 +static
200.4400 +void* Type_MPE_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.4401 +{
200.4402 +    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
200.4403 +
200.4404 +    cmsUNUSED_PARAMETER(n);
200.4405 +    cmsUNUSED_PARAMETER(self);
200.4406 +}
200.4407 +
200.4408 +static
200.4409 +void Type_MPE_Free(struct _cms_typehandler_struct* self, void *Ptr)
200.4410 +{
200.4411 +    cmsPipelineFree((cmsPipeline*) Ptr);
200.4412 +    return;
200.4413 +
200.4414 +    cmsUNUSED_PARAMETER(self);
200.4415 +}
200.4416 +
200.4417 +
200.4418 +// ********************************************************************************
200.4419 +// Type cmsSigVcgtType
200.4420 +// ********************************************************************************
200.4421 +
200.4422 +
200.4423 +#define cmsVideoCardGammaTableType    0
200.4424 +#define cmsVideoCardGammaFormulaType  1
200.4425 +
200.4426 +// Used internally
200.4427 +typedef struct {
200.4428 +    double Gamma;
200.4429 +    double Min;
200.4430 +    double Max;
200.4431 +} _cmsVCGTGAMMA;
200.4432 +
200.4433 +
200.4434 +static
200.4435 +void *Type_vcgt_Read(struct _cms_typehandler_struct* self,
200.4436 +                     cmsIOHANDLER* io,
200.4437 +                     cmsUInt32Number* nItems,
200.4438 +                     cmsUInt32Number SizeOfTag)
200.4439 +{
200.4440 +    cmsUInt32Number TagType, n, i;
200.4441 +    cmsToneCurve** Curves;
200.4442 +
200.4443 +    *nItems = 0;
200.4444 +
200.4445 +    // Read tag type
200.4446 +    if (!_cmsReadUInt32Number(io, &TagType)) return NULL;
200.4447 +
200.4448 +    // Allocate space for the array
200.4449 +    Curves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*));
200.4450 +    if (Curves == NULL) return NULL;
200.4451 +
200.4452 +    // There are two possible flavors
200.4453 +    switch (TagType) {
200.4454 +
200.4455 +    // Gamma is stored as a table
200.4456 +    case cmsVideoCardGammaTableType:
200.4457 +    {
200.4458 +       cmsUInt16Number nChannels, nElems, nBytes;
200.4459 +
200.4460 +       // Check channel count, which should be 3 (we don't support monochrome this time)
200.4461 +       if (!_cmsReadUInt16Number(io, &nChannels)) goto Error;
200.4462 +
200.4463 +       if (nChannels != 3) {
200.4464 +           cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported number of channels for VCGT '%d'", nChannels);
200.4465 +           goto Error;
200.4466 +       }
200.4467 +
200.4468 +       // Get Table element count and bytes per element
200.4469 +       if (!_cmsReadUInt16Number(io, &nElems)) goto Error;
200.4470 +       if (!_cmsReadUInt16Number(io, &nBytes)) goto Error;
200.4471 +
200.4472 +       // Populate tone curves
200.4473 +       for (n=0; n < 3; n++) {
200.4474 +
200.4475 +           Curves[n] = cmsBuildTabulatedToneCurve16(self ->ContextID, nElems, NULL);
200.4476 +           if (Curves[n] == NULL) goto Error;
200.4477 +
200.4478 +           // On depending on byte depth
200.4479 +           switch (nBytes) {
200.4480 +
200.4481 +           // One byte, 0..255
200.4482 +           case 1:
200.4483 +               for (i=0; i < nElems; i++) {
200.4484 +
200.4485 +                   cmsUInt8Number v;
200.4486 +
200.4487 +                      if (!_cmsReadUInt8Number(io, &v)) goto Error;
200.4488 +                      Curves[n] ->Table16[i] = FROM_8_TO_16(v);
200.4489 +               }
200.4490 +               break;
200.4491 +
200.4492 +           // One word 0..65535
200.4493 +           case 2:
200.4494 +              if (!_cmsReadUInt16Array(io, nElems, Curves[n]->Table16)) goto Error;
200.4495 +              break;
200.4496 +
200.4497 +          // Unsupported
200.4498 +           default:
200.4499 +              cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported bit depth for VCGT '%d'", nBytes * 8);
200.4500 +              goto Error;
200.4501 +           }
200.4502 +       } // For all 3 channels
200.4503 +    }
200.4504 +    break;
200.4505 +
200.4506 +   // In this case, gamma is stored as a formula
200.4507 +   case cmsVideoCardGammaFormulaType:
200.4508 +   {
200.4509 +       _cmsVCGTGAMMA Colorant[3];
200.4510 +
200.4511 +        // Populate tone curves
200.4512 +       for (n=0; n < 3; n++) {
200.4513 +
200.4514 +           double Params[10];
200.4515 +
200.4516 +           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Gamma)) goto Error;
200.4517 +           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Min)) goto Error;
200.4518 +           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Max)) goto Error;
200.4519 +
200.4520 +            // Parametric curve type 5 is:
200.4521 +            // Y = (aX + b)^Gamma + e | X >= d
200.4522 +            // Y = cX + f             | X < d
200.4523 +
200.4524 +            // vcgt formula is:
200.4525 +            // Y = (Max – Min) * (X ^ Gamma) + Min
200.4526 +
200.4527 +            // So, the translation is
200.4528 +            // a = (Max – Min) ^ ( 1 / Gamma)
200.4529 +            // e = Min
200.4530 +            // b=c=d=f=0
200.4531 +
200.4532 +           Params[0] = Colorant[n].Gamma;
200.4533 +           Params[1] = pow((Colorant[n].Max - Colorant[n].Min), (1.0 / Colorant[n].Gamma));
200.4534 +           Params[2] = 0;
200.4535 +           Params[3] = 0;
200.4536 +           Params[4] = 0;
200.4537 +           Params[5] = Colorant[n].Min;
200.4538 +           Params[6] = 0;
200.4539 +
200.4540 +           Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params);
200.4541 +           if (Curves[n] == NULL) goto Error;
200.4542 +       }
200.4543 +   }
200.4544 +   break;
200.4545 +
200.4546 +   // Unsupported
200.4547 +   default:
200.4548 +      cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType);
200.4549 +      goto Error;
200.4550 +   }
200.4551 +
200.4552 +   *nItems = 1;
200.4553 +   return (void*) Curves;
200.4554 +
200.4555 +// Regret,  free all resources
200.4556 +Error:
200.4557 +
200.4558 +    cmsFreeToneCurveTriple(Curves);
200.4559 +    _cmsFree(self ->ContextID, Curves);
200.4560 +    return NULL;
200.4561 +
200.4562 +     cmsUNUSED_PARAMETER(SizeOfTag);
200.4563 +}
200.4564 +
200.4565 +
200.4566 +// We don't support all flavors, only 16bits tables and formula
200.4567 +static
200.4568 +cmsBool Type_vcgt_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
200.4569 +{
200.4570 +    cmsToneCurve** Curves =  (cmsToneCurve**) Ptr;
200.4571 +    cmsUInt32Number i, j;
200.4572 +
200.4573 +    if (cmsGetToneCurveParametricType(Curves[0]) == 5 &&
200.4574 +        cmsGetToneCurveParametricType(Curves[1]) == 5 &&
200.4575 +        cmsGetToneCurveParametricType(Curves[2]) == 5) {
200.4576 +
200.4577 +        if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaFormulaType)) return FALSE;
200.4578 +
200.4579 +        // Save parameters
200.4580 +        for (i=0; i < 3; i++) {
200.4581 +
200.4582 +            _cmsVCGTGAMMA v;
200.4583 +
200.4584 +            v.Gamma = Curves[i] ->Segments[0].Params[0];
200.4585 +            v.Min   = Curves[i] ->Segments[0].Params[5];
200.4586 +            v.Max   = pow(Curves[i] ->Segments[0].Params[1], v.Gamma) + v.Min;
200.4587 +
200.4588 +            if (!_cmsWrite15Fixed16Number(io, v.Gamma)) return FALSE;
200.4589 +            if (!_cmsWrite15Fixed16Number(io, v.Min)) return FALSE;
200.4590 +            if (!_cmsWrite15Fixed16Number(io, v.Max)) return FALSE;
200.4591 +        }
200.4592 +    }
200.4593 +
200.4594 +    else {
200.4595 +
200.4596 +        // Always store as a table of 256 words
200.4597 +        if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaTableType)) return FALSE;
200.4598 +        if (!_cmsWriteUInt16Number(io, 3)) return FALSE;
200.4599 +        if (!_cmsWriteUInt16Number(io, 256)) return FALSE;
200.4600 +        if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
200.4601 +
200.4602 +        for (i=0; i < 3; i++) {
200.4603 +            for (j=0; j < 256; j++) {
200.4604 +
200.4605 +                cmsFloat32Number v = cmsEvalToneCurveFloat(Curves[i], (cmsFloat32Number) (j / 255.0));
200.4606 +                cmsUInt16Number  n = _cmsQuickSaturateWord(v * 65535.0);
200.4607 +
200.4608 +                if (!_cmsWriteUInt16Number(io, n)) return FALSE;
200.4609 +            }
200.4610 +        }
200.4611 +    }
200.4612 +
200.4613 +    return TRUE;
200.4614 +
200.4615 +    cmsUNUSED_PARAMETER(self);
200.4616 +    cmsUNUSED_PARAMETER(nItems);
200.4617 +}
200.4618 +
200.4619 +static
200.4620 +void* Type_vcgt_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
200.4621 +{
200.4622 +    cmsToneCurve** OldCurves =  (cmsToneCurve**) Ptr;
200.4623 +    cmsToneCurve** NewCurves;
200.4624 +
200.4625 +    NewCurves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*));
200.4626 +    if (NewCurves == NULL) return NULL;
200.4627 +
200.4628 +    NewCurves[0] = cmsDupToneCurve(OldCurves[0]);
200.4629 +    NewCurves[1] = cmsDupToneCurve(OldCurves[1]);
200.4630 +    NewCurves[2] = cmsDupToneCurve(OldCurves[2]);
200.4631 +
200.4632 +    return (void*) NewCurves;
200.4633 +
200.4634 +    cmsUNUSED_PARAMETER(n);
200.4635 +}
200.4636 +
200.4637 +
200.4638 +static
200.4639 +void Type_vcgt_Free(struct _cms_typehandler_struct* self, void* Ptr)
200.4640 +{
200.4641 +    cmsFreeToneCurveTriple((cmsToneCurve**) Ptr);
200.4642 +    _cmsFree(self ->ContextID, Ptr);
200.4643 +}
200.4644 +
200.4645 +// ********************************************************************************
200.4646 +// Type support main routines
200.4647 +// ********************************************************************************
200.4648 +
200.4649 +
200.4650 +// This is the list of built-in types
200.4651 +static _cmsTagTypeLinkedList SupportedTagTypes[] = {
200.4652 +
200.4653 +{TYPE_HANDLER(cmsSigChromaticityType,          Chromaticity),        &SupportedTagTypes[1] },
200.4654 +{TYPE_HANDLER(cmsSigColorantOrderType,         ColorantOrderType),   &SupportedTagTypes[2] },
200.4655 +{TYPE_HANDLER(cmsSigS15Fixed16ArrayType,       S15Fixed16),          &SupportedTagTypes[3] },
200.4656 +{TYPE_HANDLER(cmsSigU16Fixed16ArrayType,       U16Fixed16),          &SupportedTagTypes[4] },
200.4657 +{TYPE_HANDLER(cmsSigTextType,                  Text),                &SupportedTagTypes[5] },
200.4658 +{TYPE_HANDLER(cmsSigTextDescriptionType,       Text_Description),    &SupportedTagTypes[6] },
200.4659 +{TYPE_HANDLER(cmsSigCurveType,                 Curve),               &SupportedTagTypes[7] },
200.4660 +{TYPE_HANDLER(cmsSigParametricCurveType,       ParametricCurve),     &SupportedTagTypes[8] },
200.4661 +{TYPE_HANDLER(cmsSigDateTimeType,              DateTime),            &SupportedTagTypes[9] },
200.4662 +{TYPE_HANDLER(cmsSigLut8Type,                  LUT8),                &SupportedTagTypes[10] },
200.4663 +{TYPE_HANDLER(cmsSigLut16Type,                 LUT16),               &SupportedTagTypes[11] },
200.4664 +{TYPE_HANDLER(cmsSigColorantTableType,         ColorantTable),       &SupportedTagTypes[12] },
200.4665 +{TYPE_HANDLER(cmsSigNamedColor2Type,           NamedColor),          &SupportedTagTypes[13] },
200.4666 +{TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU),                 &SupportedTagTypes[14] },
200.4667 +{TYPE_HANDLER(cmsSigProfileSequenceDescType,   ProfileSequenceDesc), &SupportedTagTypes[15] },
200.4668 +{TYPE_HANDLER(cmsSigSignatureType,             Signature),           &SupportedTagTypes[16] },
200.4669 +{TYPE_HANDLER(cmsSigMeasurementType,           Measurement),         &SupportedTagTypes[17] },
200.4670 +{TYPE_HANDLER(cmsSigDataType,                  Data),                &SupportedTagTypes[18] },
200.4671 +{TYPE_HANDLER(cmsSigLutAtoBType,               LUTA2B),              &SupportedTagTypes[19] },
200.4672 +{TYPE_HANDLER(cmsSigLutBtoAType,               LUTB2A),              &SupportedTagTypes[20] },
200.4673 +{TYPE_HANDLER(cmsSigUcrBgType,                 UcrBg),               &SupportedTagTypes[21] },
200.4674 +{TYPE_HANDLER(cmsSigCrdInfoType,               CrdInfo),             &SupportedTagTypes[22] },
200.4675 +{TYPE_HANDLER(cmsSigMultiProcessElementType,   MPE),                 &SupportedTagTypes[23] },
200.4676 +{TYPE_HANDLER(cmsSigScreeningType,             Screening),           &SupportedTagTypes[24] },
200.4677 +{TYPE_HANDLER(cmsSigViewingConditionsType,     ViewingConditions),   &SupportedTagTypes[25] },
200.4678 +{TYPE_HANDLER(cmsSigXYZType,                   XYZ),                 &SupportedTagTypes[26] },
200.4679 +{TYPE_HANDLER(cmsCorbisBrokenXYZtype,          XYZ),                 &SupportedTagTypes[27] },
200.4680 +{TYPE_HANDLER(cmsMonacoBrokenCurveType,        Curve),               &SupportedTagTypes[28] },
200.4681 +{TYPE_HANDLER(cmsSigProfileSequenceIdType,     ProfileSequenceId),   &SupportedTagTypes[29] },
200.4682 +{TYPE_HANDLER(cmsSigVcgtType,                  vcgt),                NULL }
200.4683 +};
200.4684 +
200.4685 +#define DEFAULT_TAG_TYPE_COUNT  (sizeof(SupportedTagTypes) / sizeof(_cmsTagTypeLinkedList))
200.4686 +
200.4687 +// Both kind of plug-ins share same structure
200.4688 +cmsBool  _cmsRegisterTagTypePlugin(cmsPluginBase* Data)
200.4689 +{
200.4690 +    return RegisterTypesPlugin(Data, SupportedTagTypes, DEFAULT_TAG_TYPE_COUNT);
200.4691 +}
200.4692 +
200.4693 +cmsBool  _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Data)
200.4694 +{
200.4695 +    return RegisterTypesPlugin(Data, SupportedMPEtypes, DEFAULT_MPE_TYPE_COUNT);
200.4696 +}
200.4697 +
200.4698 +
200.4699 +// Wrapper for tag types
200.4700 +cmsTagTypeHandler* _cmsGetTagTypeHandler(cmsTagTypeSignature sig)
200.4701 +{
200.4702 +    return GetHandler(sig, SupportedTagTypes);
200.4703 +}
200.4704 +
200.4705 +// ********************************************************************************
200.4706 +// Tag support main routines
200.4707 +// ********************************************************************************
200.4708 +
200.4709 +typedef struct _cmsTagLinkedList_st {
200.4710 +
200.4711 +            cmsTagSignature Signature;
200.4712 +            cmsTagDescriptor Descriptor;
200.4713 +            struct _cmsTagLinkedList_st* Next;
200.4714 +
200.4715 +} _cmsTagLinkedList;
200.4716 +
200.4717 +// This is the list of built-in tags
200.4718 +static _cmsTagLinkedList SupportedTags[] = {
200.4719 +
200.4720 +    { cmsSigAToB0Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[1]},
200.4721 +    { cmsSigAToB1Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[2]},
200.4722 +    { cmsSigAToB2Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[3]},
200.4723 +    { cmsSigBToA0Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[4]},
200.4724 +    { cmsSigBToA1Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[5]},
200.4725 +    { cmsSigBToA2Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[6]},
200.4726 +
200.4727 +    // Allow corbis  and its broken XYZ type
200.4728 +    { cmsSigRedColorantTag,         { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[7]},
200.4729 +    { cmsSigGreenColorantTag,       { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[8]},
200.4730 +    { cmsSigBlueColorantTag,        { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[9]},
200.4731 +
200.4732 +    { cmsSigRedTRCTag,              { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[10]},
200.4733 +    { cmsSigGreenTRCTag,            { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[11]},
200.4734 +    { cmsSigBlueTRCTag,             { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[12]},
200.4735 +
200.4736 +    { cmsSigCalibrationDateTimeTag, { 1, 1, { cmsSigDateTimeType }, NULL}, &SupportedTags[13]},
200.4737 +    { cmsSigCharTargetTag,          { 1, 1, { cmsSigTextType },     NULL}, &SupportedTags[14]},
200.4738 +
200.4739 +    { cmsSigChromaticAdaptationTag, { 9, 1, { cmsSigS15Fixed16ArrayType }, NULL}, &SupportedTags[15]},
200.4740 +    { cmsSigChromaticityTag,        { 1, 1, { cmsSigChromaticityType    }, NULL}, &SupportedTags[16]},
200.4741 +    { cmsSigColorantOrderTag,       { 1, 1, { cmsSigColorantOrderType   }, NULL}, &SupportedTags[17]},
200.4742 +    { cmsSigColorantTableTag,       { 1, 1, { cmsSigColorantTableType   }, NULL}, &SupportedTags[18]},
200.4743 +    { cmsSigColorantTableOutTag,    { 1, 1, { cmsSigColorantTableType   }, NULL}, &SupportedTags[19]},
200.4744 +
200.4745 +    { cmsSigCopyrightTag,           { 1, 3, { cmsSigTextType,  cmsSigMultiLocalizedUnicodeType, cmsSigTextDescriptionType}, DecideTextType}, &SupportedTags[20]},
200.4746 +    { cmsSigDateTimeTag,            { 1, 1, { cmsSigDateTimeType }, NULL}, &SupportedTags[21]},
200.4747 +
200.4748 +    { cmsSigDeviceMfgDescTag,       { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[22]},
200.4749 +    { cmsSigDeviceModelDescTag,     { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[23]},
200.4750 +
200.4751 +    { cmsSigGamutTag,               { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[24]},
200.4752 +
200.4753 +    { cmsSigGrayTRCTag,             { 1, 2, { cmsSigCurveType, cmsSigParametricCurveType }, DecideCurveType}, &SupportedTags[25]},
200.4754 +    { cmsSigLuminanceTag,           { 1, 1, { cmsSigXYZType }, NULL}, &SupportedTags[26]},
200.4755 +
200.4756 +    { cmsSigMediaBlackPointTag,     { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, NULL}, &SupportedTags[27]},
200.4757 +    { cmsSigMediaWhitePointTag,     { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, NULL}, &SupportedTags[28]},
200.4758 +
200.4759 +    { cmsSigNamedColor2Tag,         { 1, 1, { cmsSigNamedColor2Type }, NULL}, &SupportedTags[29]},
200.4760 +
200.4761 +    { cmsSigPreview0Tag,            { 1, 3,  { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[30]},
200.4762 +    { cmsSigPreview1Tag,            { 1, 3,  { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[31]},
200.4763 +    { cmsSigPreview2Tag,            { 1, 3,  { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[32]},
200.4764 +
200.4765 +    { cmsSigProfileDescriptionTag,  { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[33]},
200.4766 +    { cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL}, &SupportedTags[34]},
200.4767 +    { cmsSigTechnologyTag,          { 1, 1, { cmsSigSignatureType }, NULL},  &SupportedTags[35]},
200.4768 +
200.4769 +    { cmsSigColorimetricIntentImageStateTag,   { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[36]},
200.4770 +    { cmsSigPerceptualRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[37]},
200.4771 +    { cmsSigSaturationRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[38]},
200.4772 +
200.4773 +    { cmsSigMeasurementTag,         { 1, 1, { cmsSigMeasurementType }, NULL}, &SupportedTags[39]},
200.4774 +
200.4775 +    { cmsSigPs2CRD0Tag,             { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[40]},
200.4776 +    { cmsSigPs2CRD1Tag,             { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[41]},
200.4777 +    { cmsSigPs2CRD2Tag,             { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[42]},
200.4778 +    { cmsSigPs2CRD3Tag,             { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[43]},
200.4779 +    { cmsSigPs2CSATag,              { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[44]},
200.4780 +    { cmsSigPs2RenderingIntentTag,  { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[45]},
200.4781 +
200.4782 +    { cmsSigViewingCondDescTag,     { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[46]},
200.4783 +
200.4784 +    { cmsSigUcrBgTag,               { 1, 1, { cmsSigUcrBgType}, NULL},    &SupportedTags[47]},
200.4785 +    { cmsSigCrdInfoTag,             { 1, 1, { cmsSigCrdInfoType}, NULL},  &SupportedTags[48]},
200.4786 +
200.4787 +    { cmsSigDToB0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[49]},
200.4788 +    { cmsSigDToB1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[50]},
200.4789 +    { cmsSigDToB2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[51]},
200.4790 +    { cmsSigDToB3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[52]},
200.4791 +    { cmsSigBToD0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[53]},
200.4792 +    { cmsSigBToD1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[54]},
200.4793 +    { cmsSigBToD2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[55]},
200.4794 +    { cmsSigBToD3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[56]},
200.4795 +
200.4796 +    { cmsSigScreeningDescTag,       { 1, 1, { cmsSigTextDescriptionType },    NULL}, &SupportedTags[57]},
200.4797 +    { cmsSigViewingConditionsTag,   { 1, 1, { cmsSigViewingConditionsType },  NULL}, &SupportedTags[58]},
200.4798 +
200.4799 +    { cmsSigScreeningTag,           { 1, 1, { cmsSigScreeningType},          NULL }, &SupportedTags[59]},
200.4800 +    { cmsSigVcgtTag,                { 1, 1, { cmsSigVcgtType},               NULL }, &SupportedTags[60]},
200.4801 +    { cmsSigProfileSequenceIdTag,   { 1, 1, { cmsSigProfileSequenceIdType},  NULL},  NULL}
200.4802 +
200.4803 +};
200.4804 +
200.4805 +/*
200.4806 +    Not supported                 Why
200.4807 +    =======================       =========================================
200.4808 +    cmsSigOutputResponseTag   ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT!
200.4809 +    cmsSigNamedColorTag       ==> Deprecated
200.4810 +    cmsSigDataTag             ==> Ancient, unused
200.4811 +    cmsSigDeviceSettingsTag   ==> Deprecated, useless
200.4812 +*/
200.4813 +
200.4814 +#define DEFAULT_TAG_COUNT  (sizeof(SupportedTags) / sizeof(_cmsTagLinkedList))
200.4815 +
200.4816 +cmsBool  _cmsRegisterTagPlugin(cmsPluginBase* Data)
200.4817 +{
200.4818 +    cmsPluginTag* Plugin = (cmsPluginTag*) Data;
200.4819 +    _cmsTagLinkedList *pt, *Anterior;
200.4820 +
200.4821 +
200.4822 +    if (Data == NULL) {
200.4823 +
200.4824 +        SupportedTags[DEFAULT_TAG_COUNT-1].Next = NULL;
200.4825 +        return TRUE;
200.4826 +    }
200.4827 +
200.4828 +    pt = Anterior = SupportedTags;
200.4829 +    while (pt != NULL) {
200.4830 +
200.4831 +        if (Plugin->Signature == pt -> Signature) {
200.4832 +            pt ->Descriptor = Plugin ->Descriptor;  // Replace old behaviour
200.4833 +            return TRUE;
200.4834 +        }
200.4835 +
200.4836 +        Anterior = pt;
200.4837 +        pt = pt ->Next;
200.4838 +    }
200.4839 +
200.4840 +    pt = (_cmsTagLinkedList*) _cmsPluginMalloc(sizeof(_cmsTagLinkedList));
200.4841 +    if (pt == NULL) return FALSE;
200.4842 +
200.4843 +    pt ->Signature  = Plugin ->Signature;
200.4844 +    pt ->Descriptor = Plugin ->Descriptor;
200.4845 +    pt ->Next       = NULL;
200.4846 +
200.4847 +    if (Anterior != NULL) Anterior -> Next = pt;
200.4848 +
200.4849 +    return TRUE;
200.4850 +}
200.4851 +
200.4852 +// Return a descriptor for a given tag or NULL
200.4853 +cmsTagDescriptor* _cmsGetTagDescriptor(cmsTagSignature sig)
200.4854 +{
200.4855 +    _cmsTagLinkedList* pt;
200.4856 +
200.4857 +    for (pt = SupportedTags;
200.4858 +            pt != NULL;
200.4859 +            pt = pt ->Next) {
200.4860 +
200.4861 +                if (sig == pt -> Signature) return &pt ->Descriptor;
200.4862 +    }
200.4863 +
200.4864 +    return NULL;
200.4865 +}
200.4866 +
   201.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c	Thu Sep 23 17:33:40 2010 -0700
   201.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsvirt.c	Fri Sep 24 16:41:32 2010 -0700
   201.3 @@ -27,9 +27,10 @@
   201.4  // However, the following notice accompanied the original version of this
   201.5  // file:
   201.6  //
   201.7 +//---------------------------------------------------------------------------------
   201.8  //
   201.9 -//  Little cms
  201.10 -//  Copyright (C) 1998-2007 Marti Maria
  201.11 +//  Little Color Management System
  201.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  201.13  //
  201.14  // Permission is hereby granted, free of charge, to any person obtaining
  201.15  // a copy of this software and associated documentation files (the "Software"),
  201.16 @@ -48,426 +49,314 @@
  201.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  201.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  201.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  201.20 +//
  201.21 +//---------------------------------------------------------------------------------
  201.22 +//
  201.23  
  201.24 -
  201.25 -#include "lcms.h"
  201.26 -
  201.27 +#include "lcms2_internal.h"
  201.28  
  201.29  // Virtual (built-in) profiles
  201.30  // -----------------------------------------------------------------------------------
  201.31  
  201.32 +static
  201.33 +cmsBool SetTextTags(cmsHPROFILE hProfile, const wchar_t* Description)
  201.34 +{
  201.35 +    cmsMLU *DescriptionMLU, *CopyrightMLU;
  201.36 +    cmsBool  rc = FALSE;
  201.37 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
  201.38 +
  201.39 +    DescriptionMLU  = cmsMLUalloc(ContextID, 1);
  201.40 +    CopyrightMLU    = cmsMLUalloc(ContextID, 1);
  201.41 +
  201.42 +    if (DescriptionMLU == NULL || CopyrightMLU == NULL) goto Error;
  201.43 +
  201.44 +    if (!cmsMLUsetWide(DescriptionMLU,  "en", "US", Description)) goto Error;
  201.45 +    if (!cmsMLUsetWide(CopyrightMLU,    "en", "US", L"No copyright, use freely")) goto Error;
  201.46 +
  201.47 +    if (!cmsWriteTag(hProfile, cmsSigProfileDescriptionTag,  DescriptionMLU)) goto Error;
  201.48 +    if (!cmsWriteTag(hProfile, cmsSigCopyrightTag,           CopyrightMLU)) goto Error;
  201.49 +
  201.50 +    rc = TRUE;
  201.51 +
  201.52 +Error:
  201.53 +
  201.54 +    if (DescriptionMLU)
  201.55 +        cmsMLUfree(DescriptionMLU);
  201.56 +    if (CopyrightMLU)
  201.57 +        cmsMLUfree(CopyrightMLU);
  201.58 +    return rc;
  201.59 +}
  201.60 +
  201.61 +
  201.62 +static
  201.63 +cmsBool  SetSeqDescTag(cmsHPROFILE hProfile, const char* Model)
  201.64 +{
  201.65 +    cmsBool  rc = FALSE;
  201.66 +    cmsContext ContextID = cmsGetProfileContextID(hProfile);
  201.67 +    cmsSEQ* Seq = cmsAllocProfileSequenceDescription(ContextID, 1);
  201.68 +
  201.69 +    if (Seq == NULL) return FALSE;
  201.70 +
  201.71 +    Seq->seq[0].deviceMfg = (cmsSignature) 0;
  201.72 +    Seq->seq[0].deviceModel = (cmsSignature) 0;
  201.73 +
  201.74 +#ifdef CMS_DONT_USE_INT64
  201.75 +    Seq->seq[0].attributes[0] = 0;
  201.76 +    Seq->seq[0].attributes[1] = 0;
  201.77 +#else
  201.78 +    Seq->seq[0].attributes = 0;
  201.79 +#endif
  201.80 +
  201.81 +    Seq->seq[0].technology = (cmsTechnologySignature) 0;
  201.82 +
  201.83 +    cmsMLUsetASCII( Seq->seq[0].Manufacturer, cmsNoLanguage, cmsNoCountry, "Little CMS");
  201.84 +    cmsMLUsetASCII( Seq->seq[0].Model,        cmsNoLanguage, cmsNoCountry, Model);
  201.85 +
  201.86 +    if (!_cmsWriteProfileSequence(hProfile, Seq)) goto Error;
  201.87 +
  201.88 +    rc = TRUE;
  201.89 +
  201.90 +Error:
  201.91 +    if (Seq)
  201.92 +        cmsFreeProfileSequenceDescription(Seq);
  201.93 +
  201.94 +    return rc;
  201.95 +}
  201.96 +
  201.97 +
  201.98  
  201.99  // This function creates a profile based on White point, primaries and
 201.100  // transfer functions.
 201.101 +cmsHPROFILE CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
 201.102 +                                          const cmsCIExyY* WhitePoint,
 201.103 +                                          const cmsCIExyYTRIPLE* Primaries,
 201.104 +                                          cmsToneCurve* const TransferFunction[3])
 201.105 +{
 201.106 +    cmsHPROFILE hICC;
 201.107 +    cmsMAT3 MColorants;
 201.108 +    cmsCIEXYZTRIPLE Colorants;
 201.109 +    cmsCIExyY MaxWhite;
 201.110 +    cmsMAT3 CHAD;
 201.111 +    cmsCIEXYZ WhitePointXYZ;
 201.112  
 201.113 +    hICC = cmsCreateProfilePlaceholder(ContextID);
 201.114 +    if (!hICC)                          // can't allocate
 201.115 +        return NULL;
 201.116  
 201.117 -cmsHPROFILE LCMSEXPORT cmsCreateRGBProfile(LPcmsCIExyY WhitePoint,
 201.118 -                                LPcmsCIExyYTRIPLE Primaries,
 201.119 -                                LPGAMMATABLE TransferFunction[3])
 201.120 -{
 201.121 -       cmsHPROFILE hICC;
 201.122 -       cmsCIEXYZ tmp;
 201.123 -       MAT3 MColorants;
 201.124 -       cmsCIEXYZTRIPLE Colorants;
 201.125 -       cmsCIExyY MaxWhite;
 201.126 +    cmsSetProfileVersion(hICC, 4.2);
 201.127  
 201.128 +    cmsSetDeviceClass(hICC,      cmsSigDisplayClass);
 201.129 +    cmsSetColorSpace(hICC,       cmsSigRgbData);
 201.130 +    cmsSetPCS(hICC,              cmsSigXYZData);
 201.131  
 201.132 -       hICC = _cmsCreateProfilePlaceholder();
 201.133 -       if (!hICC)                          // can't allocate
 201.134 -            return NULL;
 201.135 +    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 201.136  
 201.137  
 201.138 -       cmsSetDeviceClass(hICC,      icSigDisplayClass);
 201.139 -       cmsSetColorSpace(hICC,       icSigRgbData);
 201.140 -       cmsSetPCS(hICC,              icSigXYZData);
 201.141 -       cmsSetRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 201.142 +    // Implement profile using following tags:
 201.143 +    //
 201.144 +    //  1 cmsSigProfileDescriptionTag
 201.145 +    //  2 cmsSigMediaWhitePointTag
 201.146 +    //  3 cmsSigRedColorantTag
 201.147 +    //  4 cmsSigGreenColorantTag
 201.148 +    //  5 cmsSigBlueColorantTag
 201.149 +    //  6 cmsSigRedTRCTag
 201.150 +    //  7 cmsSigGreenTRCTag
 201.151 +    //  8 cmsSigBlueTRCTag
 201.152 +    //  9 Chromatic adaptation Tag
 201.153 +    // This conforms a standard RGB DisplayProfile as says ICC, and then I add (As per addendum II)
 201.154 +    // 10 cmsSigChromaticityTag
 201.155  
 201.156  
 201.157 -       // Implement profile using following tags:
 201.158 -       //
 201.159 -       //  1 icSigProfileDescriptionTag
 201.160 -       //  2 icSigMediaWhitePointTag
 201.161 -       //  3 icSigRedColorantTag
 201.162 -       //  4 icSigGreenColorantTag
 201.163 -       //  5 icSigBlueColorantTag
 201.164 -       //  6 icSigRedTRCTag
 201.165 -       //  7 icSigGreenTRCTag
 201.166 -       //  8 icSigBlueTRCTag
 201.167 +    if (!SetTextTags(hICC, L"RGB built-in")) goto Error;
 201.168  
 201.169 -       // This conforms a standard RGB DisplayProfile as says ICC, and then I add
 201.170 +    if (WhitePoint) {
 201.171  
 201.172 -       // 9 icSigChromaticityTag
 201.173 +        if (!cmsWriteTag(hICC, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;
 201.174  
 201.175 -       // As addendum II
 201.176 +        cmsxyY2XYZ(&WhitePointXYZ, WhitePoint);
 201.177 +        _cmsAdaptationMatrix(&CHAD, NULL, &WhitePointXYZ, cmsD50_XYZ());
 201.178  
 201.179 +        // This is a V4 tag, but many CMM does read and understand it no matter which version
 201.180 +        if (!cmsWriteTag(hICC, cmsSigChromaticAdaptationTag, (void*) &CHAD)) goto Error;
 201.181 +    }
 201.182  
 201.183 -       // Fill-in the tags
 201.184 -
 201.185 -       cmsAddTag(hICC, icSigDeviceMfgDescTag,       (LPVOID) "(lcms internal)");
 201.186 -       cmsAddTag(hICC, icSigProfileDescriptionTag,  (LPVOID) "lcms RGB virtual profile");
 201.187 -       cmsAddTag(hICC, icSigDeviceModelDescTag,     (LPVOID) "rgb built-in");
 201.188 -
 201.189 -
 201.190 -       if (WhitePoint) {
 201.191 -
 201.192 -       cmsxyY2XYZ(&tmp, WhitePoint);
 201.193 -       cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) &tmp);
 201.194 -       }
 201.195 -
 201.196 -       if (WhitePoint && Primaries) {
 201.197 +    if (WhitePoint && Primaries) {
 201.198  
 201.199          MaxWhite.x =  WhitePoint -> x;
 201.200          MaxWhite.y =  WhitePoint -> y;
 201.201          MaxWhite.Y =  1.0;
 201.202  
 201.203 -       if (!cmsBuildRGB2XYZtransferMatrix(&MColorants, &MaxWhite, Primaries))
 201.204 -       {
 201.205 -              cmsCloseProfile(hICC);
 201.206 -              return NULL;
 201.207 -       }
 201.208 +        if (!_cmsBuildRGB2XYZtransferMatrix(&MColorants, &MaxWhite, Primaries)) goto Error;
 201.209  
 201.210 -       cmsAdaptMatrixToD50(&MColorants, &MaxWhite);
 201.211 +        Colorants.Red.X   = MColorants.v[0].n[0];
 201.212 +        Colorants.Red.Y   = MColorants.v[1].n[0];
 201.213 +        Colorants.Red.Z   = MColorants.v[2].n[0];
 201.214  
 201.215 -       Colorants.Red.X = MColorants.v[0].n[0];
 201.216 -       Colorants.Red.Y = MColorants.v[1].n[0];
 201.217 -       Colorants.Red.Z = MColorants.v[2].n[0];
 201.218 +        Colorants.Green.X = MColorants.v[0].n[1];
 201.219 +        Colorants.Green.Y = MColorants.v[1].n[1];
 201.220 +        Colorants.Green.Z = MColorants.v[2].n[1];
 201.221  
 201.222 -       Colorants.Green.X = MColorants.v[0].n[1];
 201.223 -       Colorants.Green.Y = MColorants.v[1].n[1];
 201.224 -       Colorants.Green.Z = MColorants.v[2].n[1];
 201.225 +        Colorants.Blue.X  = MColorants.v[0].n[2];
 201.226 +        Colorants.Blue.Y  = MColorants.v[1].n[2];
 201.227 +        Colorants.Blue.Z  = MColorants.v[2].n[2];
 201.228  
 201.229 -       Colorants.Blue.X = MColorants.v[0].n[2];
 201.230 -       Colorants.Blue.Y = MColorants.v[1].n[2];
 201.231 -       Colorants.Blue.Z = MColorants.v[2].n[2];
 201.232 -
 201.233 -       cmsAddTag(hICC, icSigRedColorantTag,   (LPVOID) &Colorants.Red);
 201.234 -       cmsAddTag(hICC, icSigBlueColorantTag,  (LPVOID) &Colorants.Blue);
 201.235 -       cmsAddTag(hICC, icSigGreenColorantTag, (LPVOID) &Colorants.Green);
 201.236 -       }
 201.237 -
 201.238 -
 201.239 -       if (TransferFunction) {
 201.240 -
 201.241 -       // In case of gamma, we must dup' the table pointer
 201.242 -
 201.243 -        cmsAddTag(hICC, icSigRedTRCTag,   (LPVOID) TransferFunction[0]);
 201.244 -        cmsAddTag(hICC, icSigGreenTRCTag, (LPVOID) TransferFunction[1]);
 201.245 -        cmsAddTag(hICC, icSigBlueTRCTag,  (LPVOID) TransferFunction[2]);
 201.246 -       }
 201.247 -
 201.248 -       if (Primaries) {
 201.249 -            cmsAddTag(hICC, icSigChromaticityTag, (LPVOID) Primaries);
 201.250 -       }
 201.251 -
 201.252 -       return hICC;
 201.253 -}
 201.254 -
 201.255 -
 201.256 -
 201.257 -// This function creates a profile based on White point and transfer function.
 201.258 -
 201.259 -cmsHPROFILE   LCMSEXPORT cmsCreateGrayProfile(LPcmsCIExyY WhitePoint,
 201.260 -                                              LPGAMMATABLE TransferFunction)
 201.261 -{
 201.262 -       cmsHPROFILE hICC;
 201.263 -       cmsCIEXYZ tmp;
 201.264 -
 201.265 -
 201.266 -       hICC = _cmsCreateProfilePlaceholder();
 201.267 -       if (!hICC)                          // can't allocate
 201.268 -            return NULL;
 201.269 -
 201.270 -
 201.271 -       cmsSetDeviceClass(hICC,      icSigDisplayClass);
 201.272 -       cmsSetColorSpace(hICC,       icSigGrayData);
 201.273 -       cmsSetPCS(hICC,              icSigXYZData);
 201.274 -       cmsSetRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 201.275 -
 201.276 -
 201.277 -
 201.278 -       // Implement profile using following tags:
 201.279 -       //
 201.280 -       //  1 icSigProfileDescriptionTag
 201.281 -       //  2 icSigMediaWhitePointTag
 201.282 -       //  6 icSigGrayTRCTag
 201.283 -
 201.284 -       // This conforms a standard Gray DisplayProfile
 201.285 -
 201.286 -       // Fill-in the tags
 201.287 -
 201.288 -
 201.289 -       cmsAddTag(hICC, icSigDeviceMfgDescTag,       (LPVOID) "(lcms internal)");
 201.290 -       cmsAddTag(hICC, icSigProfileDescriptionTag,  (LPVOID) "lcms gray virtual profile");
 201.291 -       cmsAddTag(hICC, icSigDeviceModelDescTag,     (LPVOID) "gray built-in");
 201.292 -
 201.293 -
 201.294 -       if (WhitePoint) {
 201.295 -
 201.296 -       cmsxyY2XYZ(&tmp, WhitePoint);
 201.297 -       cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) &tmp);
 201.298 -       }
 201.299 -
 201.300 -
 201.301 -       if (TransferFunction) {
 201.302 -
 201.303 -       // In case of gamma, we must dup' the table pointer
 201.304 -
 201.305 -       cmsAddTag(hICC, icSigGrayTRCTag, (LPVOID) TransferFunction);
 201.306 -       }
 201.307 -
 201.308 -       return hICC;
 201.309 -
 201.310 -}
 201.311 -
 201.312 -
 201.313 -static
 201.314 -int IsPCS(icColorSpaceSignature ColorSpace)
 201.315 -{
 201.316 -    return (ColorSpace == icSigXYZData ||
 201.317 -            ColorSpace == icSigLabData);
 201.318 -}
 201.319 -
 201.320 -static
 201.321 -void FixColorSpaces(cmsHPROFILE hProfile,
 201.322 -                              icColorSpaceSignature ColorSpace,
 201.323 -                              icColorSpaceSignature PCS,
 201.324 -                              DWORD dwFlags)
 201.325 -{
 201.326 -
 201.327 -    if (dwFlags & cmsFLAGS_GUESSDEVICECLASS) {
 201.328 -
 201.329 -            if (IsPCS(ColorSpace) && IsPCS(PCS)) {
 201.330 -
 201.331 -                    cmsSetDeviceClass(hProfile,      icSigAbstractClass);
 201.332 -                    cmsSetColorSpace(hProfile,       ColorSpace);
 201.333 -                    cmsSetPCS(hProfile,              PCS);
 201.334 -                    return;
 201.335 -            }
 201.336 -
 201.337 -            if (IsPCS(ColorSpace) && !IsPCS(PCS)) {
 201.338 -
 201.339 -                    cmsSetDeviceClass(hProfile, icSigOutputClass);
 201.340 -                    cmsSetPCS(hProfile,         ColorSpace);
 201.341 -                    cmsSetColorSpace(hProfile,  PCS);
 201.342 -                    return;
 201.343 -            }
 201.344 -
 201.345 -            if (IsPCS(PCS) && !IsPCS(ColorSpace)) {
 201.346 -
 201.347 -                   cmsSetDeviceClass(hProfile,  icSigInputClass);
 201.348 -                   cmsSetColorSpace(hProfile,   ColorSpace);
 201.349 -                   cmsSetPCS(hProfile,          PCS);
 201.350 -                   return;
 201.351 -            }
 201.352 +        if (!cmsWriteTag(hICC, cmsSigRedColorantTag,   (void*) &Colorants.Red)) goto Error;
 201.353 +        if (!cmsWriteTag(hICC, cmsSigBlueColorantTag,  (void*) &Colorants.Blue)) goto Error;
 201.354 +        if (!cmsWriteTag(hICC, cmsSigGreenColorantTag, (void*) &Colorants.Green)) goto Error;
 201.355      }
 201.356  
 201.357 -    cmsSetDeviceClass(hProfile,      icSigLinkClass);
 201.358 -    cmsSetColorSpace(hProfile,       ColorSpace);
 201.359 -    cmsSetPCS(hProfile,              PCS);
 201.360  
 201.361 -}
 201.362 +    if (TransferFunction) {
 201.363  
 201.364 -
 201.365 -static
 201.366 -cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
 201.367 -{
 201.368 -    _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) xform;
 201.369 -    cmsHPROFILE hICC;
 201.370 -    cmsCIEXYZ WhitePoint;
 201.371 -    int i, nColors;
 201.372 -    size_t Size;
 201.373 -    LPcmsNAMEDCOLORLIST nc2;
 201.374 -
 201.375 -
 201.376 -    hICC = _cmsCreateProfilePlaceholder();
 201.377 -    if (hICC == NULL) return NULL;
 201.378 -
 201.379 -    cmsSetRenderingIntent(hICC, v -> Intent);
 201.380 -    cmsSetDeviceClass(hICC, icSigNamedColorClass);
 201.381 -    cmsSetColorSpace(hICC, v ->ExitColorSpace);
 201.382 -    cmsSetPCS(hICC, cmsGetPCS(v ->InputProfile));
 201.383 -    cmsTakeMediaWhitePoint(&WhitePoint, v ->InputProfile);
 201.384 -
 201.385 -    cmsAddTag(hICC, icSigMediaWhitePointTag,  &WhitePoint);
 201.386 -    cmsAddTag(hICC, icSigDeviceMfgDescTag,       (LPVOID) "LittleCMS");
 201.387 -    cmsAddTag(hICC, icSigProfileDescriptionTag,  (LPVOID) "Named color Device link");
 201.388 -    cmsAddTag(hICC, icSigDeviceModelDescTag,     (LPVOID) "Named color Device link");
 201.389 -
 201.390 -
 201.391 -    nColors = cmsNamedColorCount(xform);
 201.392 -    nc2     = cmsAllocNamedColorList(nColors);
 201.393 -
 201.394 -    Size = sizeof(cmsNAMEDCOLORLIST) + (sizeof(cmsNAMEDCOLOR) * (nColors-1));
 201.395 -
 201.396 -    CopyMemory(nc2, v->NamedColorList, Size);
 201.397 -    nc2 ->ColorantCount = _cmsChannelsOf(v ->ExitColorSpace);
 201.398 -
 201.399 -    for (i=0; i < nColors; i++) {
 201.400 -        cmsDoTransform(xform, &i, nc2 ->List[i].DeviceColorant, 1);
 201.401 +        if (!cmsWriteTag(hICC, cmsSigRedTRCTag,   (void*) TransferFunction[0])) goto Error;
 201.402 +        if (!cmsWriteTag(hICC, cmsSigGreenTRCTag, (void*) TransferFunction[1])) goto Error;
 201.403 +        if (!cmsWriteTag(hICC, cmsSigBlueTRCTag,  (void*) TransferFunction[2])) goto Error;
 201.404      }
 201.405  
 201.406 -    cmsAddTag(hICC, icSigNamedColor2Tag, (void*) nc2);
 201.407 -    cmsFreeNamedColorList(nc2);
 201.408 -
 201.409 -    return hICC;
 201.410 -}
 201.411 -
 201.412 -
 201.413 -// Does convert a transform into a device link profile
 201.414 -
 201.415 -cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD dwFlags)
 201.416 -{
 201.417 -    cmsHPROFILE hICC;
 201.418 -    _LPcmsTRANSFORM v = (_LPcmsTRANSFORM) hTransform;
 201.419 -    LPLUT Lut;
 201.420 -    LCMSBOOL MustFreeLUT;
 201.421 -    LPcmsNAMEDCOLORLIST InputColorant = NULL;
 201.422 -    LPcmsNAMEDCOLORLIST OutputColorant = NULL;
 201.423 -
 201.424 -
 201.425 -    // Check if is a named color transform
 201.426 -
 201.427 -    if (cmsGetDeviceClass(v ->InputProfile) == icSigNamedColorClass) {
 201.428 -
 201.429 -        return CreateNamedColorDevicelink(hTransform);
 201.430 -
 201.431 +    if (Primaries) {
 201.432 +        if (!cmsWriteTag(hICC, cmsSigChromaticityTag, (void*) Primaries)) goto Error;
 201.433      }
 201.434  
 201.435 -    if (v ->DeviceLink) {
 201.436 -
 201.437 -        Lut = v -> DeviceLink;
 201.438 -        MustFreeLUT = FALSE;
 201.439 -    }
 201.440 -    else {
 201.441 -
 201.442 -        Lut = _cmsPrecalculateDeviceLink(hTransform, dwFlags);
 201.443 -        if (!Lut) return NULL;
 201.444 -        MustFreeLUT = TRUE;
 201.445 -    }
 201.446 -
 201.447 -    hICC = _cmsCreateProfilePlaceholder();
 201.448 -    if (!hICC) {                          // can't allocate
 201.449 -
 201.450 -        if (MustFreeLUT) cmsFreeLUT(Lut);
 201.451 -        return NULL;
 201.452 -    }
 201.453 -
 201.454 -
 201.455 -    FixColorSpaces(hICC, v -> EntryColorSpace, v -> ExitColorSpace, dwFlags);
 201.456 -
 201.457 -    cmsSetRenderingIntent(hICC,  v -> Intent);
 201.458 -
 201.459 -    // Implement devicelink profile using following tags:
 201.460 -    //
 201.461 -    //  1 icSigProfileDescriptionTag
 201.462 -    //  2 icSigMediaWhitePointTag
 201.463 -    //  3 icSigAToB0Tag
 201.464 -
 201.465 -
 201.466 -    cmsAddTag(hICC, icSigDeviceMfgDescTag,       (LPVOID) "LittleCMS");
 201.467 -    cmsAddTag(hICC, icSigProfileDescriptionTag,  (LPVOID) "Device link");
 201.468 -    cmsAddTag(hICC, icSigDeviceModelDescTag,     (LPVOID) "Device link");
 201.469 -
 201.470 -
 201.471 -    cmsAddTag(hICC, icSigMediaWhitePointTag,  (LPVOID) cmsD50_XYZ());
 201.472 -
 201.473 -    if (cmsGetDeviceClass(hICC) == icSigOutputClass) {
 201.474 -
 201.475 -        cmsAddTag(hICC, icSigBToA0Tag, (LPVOID) Lut);
 201.476 -    }
 201.477 -    else
 201.478 -        cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut);
 201.479 -
 201.480 -
 201.481 -
 201.482 -    // Try to read input and output colorant table
 201.483 -    if (cmsIsTag(v ->InputProfile, icSigColorantTableTag)) {
 201.484 -
 201.485 -        // Input table can only come in this way.
 201.486 -        InputColorant = cmsReadColorantTable(v ->InputProfile, icSigColorantTableTag);
 201.487 -    }
 201.488 -
 201.489 -    // Output is a little bit more complex.
 201.490 -    if (cmsGetDeviceClass(v ->OutputProfile) == icSigLinkClass) {
 201.491 -
 201.492 -        // This tag may exist only on devicelink profiles.
 201.493 -        if (cmsIsTag(v ->OutputProfile, icSigColorantTableOutTag)) {
 201.494 -
 201.495 -            OutputColorant = cmsReadColorantTable(v ->OutputProfile, icSigColorantTableOutTag);
 201.496 -        }
 201.497 -
 201.498 -    } else {
 201.499 -
 201.500 -        if (cmsIsTag(v ->OutputProfile, icSigColorantTableTag)) {
 201.501 -
 201.502 -            OutputColorant = cmsReadColorantTable(v ->OutputProfile, icSigColorantTableTag);
 201.503 -        }
 201.504 -    }
 201.505 -
 201.506 -    if (InputColorant)
 201.507 -           cmsAddTag(hICC, icSigColorantTableTag, InputColorant);
 201.508 -
 201.509 -    if (OutputColorant)
 201.510 -           cmsAddTag(hICC, icSigColorantTableOutTag, OutputColorant);
 201.511 -
 201.512 -
 201.513 -
 201.514 -    if (MustFreeLUT) cmsFreeLUT(Lut);
 201.515 -    if (InputColorant) cmsFreeNamedColorList(InputColorant);
 201.516 -    if (OutputColorant) cmsFreeNamedColorList(OutputColorant);
 201.517  
 201.518      return hICC;
 201.519  
 201.520 +Error:
 201.521 +    if (hICC)
 201.522 +        cmsCloseProfile(hICC);
 201.523 +    return NULL;
 201.524  }
 201.525  
 201.526 -
 201.527 -// This is a devicelink operating in the target colorspace with as many transfer
 201.528 -// functions as components
 201.529 -
 201.530 -cmsHPROFILE LCMSEXPORT cmsCreateLinearizationDeviceLink(icColorSpaceSignature ColorSpace,
 201.531 -                                                        LPGAMMATABLE TransferFunctions[])
 201.532 +cmsHPROFILE CMSEXPORT cmsCreateRGBProfile(const cmsCIExyY* WhitePoint,
 201.533 +                                          const cmsCIExyYTRIPLE* Primaries,
 201.534 +                                          cmsToneCurve* const TransferFunction[3])
 201.535  {
 201.536 -       cmsHPROFILE hICC;
 201.537 -       LPLUT Lut;
 201.538 -
 201.539 -
 201.540 -       hICC = _cmsCreateProfilePlaceholder();
 201.541 -       if (!hICC)                          // can't allocate
 201.542 -            return NULL;
 201.543 -
 201.544 -
 201.545 -       cmsSetDeviceClass(hICC,      icSigLinkClass);
 201.546 -       cmsSetColorSpace(hICC,       ColorSpace);
 201.547 -       cmsSetPCS(hICC,              ColorSpace);
 201.548 -       cmsSetRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 201.549 -
 201.550 -
 201.551 -       // Creates a LUT with prelinearization step only
 201.552 -       Lut = cmsAllocLUT();
 201.553 -       if (Lut == NULL) return NULL;
 201.554 -
 201.555 -       // Set up channels
 201.556 -       Lut ->InputChan = Lut ->OutputChan = _cmsChannelsOf(ColorSpace);
 201.557 -
 201.558 -       // Copy tables to LUT
 201.559 -       cmsAllocLinearTable(Lut, TransferFunctions, 1);
 201.560 -
 201.561 -       // Create tags
 201.562 -       cmsAddTag(hICC, icSigDeviceMfgDescTag,       (LPVOID) "(lcms internal)");
 201.563 -       cmsAddTag(hICC, icSigProfileDescriptionTag,  (LPVOID) "lcms linearization device link");
 201.564 -       cmsAddTag(hICC, icSigDeviceModelDescTag,     (LPVOID) "linearization built-in");
 201.565 -
 201.566 -       cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ());
 201.567 -       cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut);
 201.568 -
 201.569 -       // LUT is already on virtual profile
 201.570 -       cmsFreeLUT(Lut);
 201.571 -
 201.572 -       // Ok, done
 201.573 -       return hICC;
 201.574 +    return cmsCreateRGBProfileTHR(NULL, WhitePoint, Primaries, TransferFunction);
 201.575  }
 201.576  
 201.577  
 201.578 +
 201.579 +// This function creates a profile based on White point and transfer function.
 201.580 +cmsHPROFILE CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID,
 201.581 +                                           const cmsCIExyY* WhitePoint,
 201.582 +                                           const cmsToneCurve* TransferFunction)
 201.583 +{
 201.584 +    cmsHPROFILE hICC;
 201.585 +    cmsCIEXYZ tmp;
 201.586 +
 201.587 +    hICC = cmsCreateProfilePlaceholder(ContextID);
 201.588 +    if (!hICC)                          // can't allocate
 201.589 +        return NULL;
 201.590 +
 201.591 +    cmsSetProfileVersion(hICC, 4.2);
 201.592 +
 201.593 +    cmsSetDeviceClass(hICC,      cmsSigDisplayClass);
 201.594 +    cmsSetColorSpace(hICC,       cmsSigGrayData);
 201.595 +    cmsSetPCS(hICC,              cmsSigXYZData);
 201.596 +    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 201.597 +
 201.598 +
 201.599 +    // Implement profile using following tags:
 201.600 +    //
 201.601 +    //  1 cmsSigProfileDescriptionTag
 201.602 +    //  2 cmsSigMediaWhitePointTag
 201.603 +    //  3 cmsSigGrayTRCTag
 201.604 +
 201.605 +    // This conforms a standard Gray DisplayProfile
 201.606 +
 201.607 +    // Fill-in the tags
 201.608 +
 201.609 +    if (!SetTextTags(hICC, L"gray built-in")) goto Error;
 201.610 +
 201.611 +
 201.612 +    if (WhitePoint) {
 201.613 +
 201.614 +        cmsxyY2XYZ(&tmp, WhitePoint);
 201.615 +        if (!cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) &tmp)) goto Error;
 201.616 +    }
 201.617 +
 201.618 +    if (TransferFunction) {
 201.619 +
 201.620 +        if (!cmsWriteTag(hICC, cmsSigGrayTRCTag, (void*) TransferFunction)) goto Error;
 201.621 +    }
 201.622 +
 201.623 +    return hICC;
 201.624 +
 201.625 +Error:
 201.626 +    if (hICC)
 201.627 +        cmsCloseProfile(hICC);
 201.628 +    return NULL;
 201.629 +}
 201.630 +
 201.631 +
 201.632 +
 201.633 +cmsHPROFILE CMSEXPORT cmsCreateGrayProfile(const cmsCIExyY* WhitePoint,
 201.634 +                                                    const cmsToneCurve* TransferFunction)
 201.635 +{
 201.636 +    return cmsCreateGrayProfileTHR(NULL, WhitePoint, TransferFunction);
 201.637 +}
 201.638 +
 201.639 +// This is a devicelink operating in the target colorspace with as many transfer functions as components
 201.640 +
 201.641 +cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
 201.642 +                                                          cmsColorSpaceSignature ColorSpace,
 201.643 +                                                          cmsToneCurve* const TransferFunctions[])
 201.644 +{
 201.645 +    cmsHPROFILE hICC;
 201.646 +    cmsPipeline* Pipeline;
 201.647 +    cmsStage* Lin;
 201.648 +    int nChannels;
 201.649 +
 201.650 +    hICC = cmsCreateProfilePlaceholder(ContextID);
 201.651 +    if (!hICC)
 201.652 +        return NULL;
 201.653 +
 201.654 +    cmsSetProfileVersion(hICC, 4.2);
 201.655 +
 201.656 +    cmsSetDeviceClass(hICC,      cmsSigLinkClass);
 201.657 +    cmsSetColorSpace(hICC,       ColorSpace);
 201.658 +    cmsSetPCS(hICC,              ColorSpace);
 201.659 +
 201.660 +    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 201.661 +
 201.662 +    // Set up channels
 201.663 +    nChannels = cmsChannelsOf(ColorSpace);
 201.664 +
 201.665 +    // Creates a Pipeline with prelinearization step only
 201.666 +    Pipeline = cmsPipelineAlloc(ContextID, nChannels, nChannels);
 201.667 +    if (Pipeline == NULL) goto Error;
 201.668 +
 201.669 +
 201.670 +    // Copy tables to Pipeline
 201.671 +    Lin = cmsStageAllocToneCurves(ContextID, nChannels, TransferFunctions);
 201.672 +    if (Lin == NULL) goto Error;
 201.673 +
 201.674 +    cmsPipelineInsertStage(Pipeline, cmsAT_BEGIN, Lin);
 201.675 +
 201.676 +    // Create tags
 201.677 +    if (!SetTextTags(hICC, L"Linearization built-in")) goto Error;
 201.678 +    if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline)) goto Error;
 201.679 +    if (!SetSeqDescTag(hICC, "Linearization built-in")) goto Error;
 201.680 +
 201.681 +    // Pipeline is already on virtual profile
 201.682 +    cmsPipelineFree(Pipeline);
 201.683 +
 201.684 +    // Ok, done
 201.685 +    return hICC;
 201.686 +
 201.687 +Error:
 201.688 +    if (hICC)
 201.689 +        cmsCloseProfile(hICC);
 201.690 +
 201.691 +
 201.692 +    return NULL;
 201.693 +}
 201.694 +
 201.695 +cmsHPROFILE CMSEXPORT cmsCreateLinearizationDeviceLink(cmsColorSpaceSignature ColorSpace,
 201.696 +                                                                 cmsToneCurve* const TransferFunctions[])
 201.697 +{
 201.698 +    return cmsCreateLinearizationDeviceLinkTHR(NULL, ColorSpace, TransferFunctions);
 201.699 +}
 201.700 +
 201.701  // Ink-limiting algorithm
 201.702  //
 201.703  //  Sum = C + M + Y + K
 201.704 @@ -486,257 +375,282 @@
 201.705  //     K: Does not change
 201.706  
 201.707  static
 201.708 -int InkLimitingSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
 201.709 +int InkLimitingSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
 201.710  {
 201.711 -        double InkLimit = *(double *) Cargo;
 201.712 -        double SumCMY, SumCMYK, Ratio;
 201.713 +    cmsFloat64Number InkLimit = *(cmsFloat64Number *) Cargo;
 201.714 +    cmsFloat64Number SumCMY, SumCMYK, Ratio;
 201.715  
 201.716 -        InkLimit = (InkLimit * 655.35);
 201.717 +    InkLimit = (InkLimit * 655.35);
 201.718  
 201.719 -        SumCMY   = In[0]  + In[1] + In[2];
 201.720 -        SumCMYK  = SumCMY + In[3];
 201.721 +    SumCMY   = In[0]  + In[1] + In[2];
 201.722 +    SumCMYK  = SumCMY + In[3];
 201.723  
 201.724 -        if (SumCMYK > InkLimit) {
 201.725 +    if (SumCMYK > InkLimit) {
 201.726  
 201.727 -                Ratio = 1 - ((SumCMYK - InkLimit) / SumCMY);
 201.728 -                if (Ratio < 0)
 201.729 -                        Ratio = 0;
 201.730 -        }
 201.731 -        else Ratio = 1;
 201.732 +        Ratio = 1 - ((SumCMYK - InkLimit) / SumCMY);
 201.733 +        if (Ratio < 0)
 201.734 +            Ratio = 0;
 201.735 +    }
 201.736 +    else Ratio = 1;
 201.737  
 201.738 -        Out[0] = (WORD) floor(In[0] * Ratio + 0.5);     // C
 201.739 -        Out[1] = (WORD) floor(In[1] * Ratio + 0.5);     // M
 201.740 -        Out[2] = (WORD) floor(In[2] * Ratio + 0.5);     // Y
 201.741 +    Out[0] = _cmsQuickSaturateWord(In[0] * Ratio);     // C
 201.742 +    Out[1] = _cmsQuickSaturateWord(In[1] * Ratio);     // M
 201.743 +    Out[2] = _cmsQuickSaturateWord(In[2] * Ratio);     // Y
 201.744  
 201.745 -        Out[3] = In[3];                                 // K (untouched)
 201.746 +    Out[3] = In[3];                                 // K (untouched)
 201.747  
 201.748 -        return TRUE;
 201.749 +    return TRUE;
 201.750  }
 201.751  
 201.752  // This is a devicelink operating in CMYK for ink-limiting
 201.753  
 201.754 -cmsHPROFILE LCMSEXPORT cmsCreateInkLimitingDeviceLink(icColorSpaceSignature ColorSpace,
 201.755 -                                                        double Limit)
 201.756 +cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
 201.757 +                                                     cmsColorSpaceSignature ColorSpace,
 201.758 +                                                     cmsFloat64Number Limit)
 201.759  {
 201.760 -       cmsHPROFILE hICC;
 201.761 -       LPLUT Lut;
 201.762 +    cmsHPROFILE hICC;
 201.763 +    cmsPipeline* LUT;
 201.764 +    cmsStage* CLUT;
 201.765 +    int nChannels;
 201.766  
 201.767 -       if (ColorSpace != icSigCmykData) {
 201.768 -            cmsSignalError(LCMS_ERRC_ABORTED, "InkLimiting: Only CMYK currently supported");
 201.769 -            return NULL;
 201.770 -       }
 201.771 +    if (ColorSpace != cmsSigCmykData) {
 201.772 +        cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported");
 201.773 +        return NULL;
 201.774 +    }
 201.775  
 201.776 -       if (Limit < 0.0 || Limit > 400) {
 201.777 +    if (Limit < 0.0 || Limit > 400) {
 201.778  
 201.779 -           cmsSignalError(LCMS_ERRC_WARNING, "InkLimiting: Limit should be between 0..400");
 201.780 -           if (Limit < 0) Limit = 0;
 201.781 -           if (Limit > 400) Limit = 400;
 201.782 +        cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 0..400");
 201.783 +        if (Limit < 0) Limit = 0;
 201.784 +        if (Limit > 400) Limit = 400;
 201.785  
 201.786 -       }
 201.787 +    }
 201.788  
 201.789 -      hICC = _cmsCreateProfilePlaceholder();
 201.790 -       if (!hICC)                          // can't allocate
 201.791 -            return NULL;
 201.792 +    hICC = cmsCreateProfilePlaceholder(ContextID);
 201.793 +    if (!hICC)                          // can't allocate
 201.794 +        return NULL;
 201.795  
 201.796 +    cmsSetProfileVersion(hICC, 4.2);
 201.797  
 201.798 -       cmsSetDeviceClass(hICC,      icSigLinkClass);
 201.799 -       cmsSetColorSpace(hICC,       ColorSpace);
 201.800 -       cmsSetPCS(hICC,              ColorSpace);
 201.801 -       cmsSetRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 201.802 +    cmsSetDeviceClass(hICC,      cmsSigLinkClass);
 201.803 +    cmsSetColorSpace(hICC,       ColorSpace);
 201.804 +    cmsSetPCS(hICC,              ColorSpace);
 201.805  
 201.806 +    cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 201.807  
 201.808 -       // Creates a LUT with 3D grid only
 201.809 -       Lut = cmsAllocLUT();
 201.810 -       if (Lut == NULL) {
 201.811 -           cmsCloseProfile(hICC);
 201.812 -           return NULL;
 201.813 -           }
 201.814  
 201.815 +    // Creates a Pipeline with 3D grid only
 201.816 +    LUT = cmsPipelineAlloc(ContextID, 4, 4);
 201.817 +    if (LUT == NULL) goto Error;
 201.818  
 201.819 -       cmsAlloc3DGrid(Lut, 17, _cmsChannelsOf(ColorSpace),
 201.820 -                               _cmsChannelsOf(ColorSpace));
 201.821  
 201.822 -       if (!cmsSample3DGrid(Lut, InkLimitingSampler, (LPVOID) &Limit, 0)) {
 201.823 +    nChannels = cmsChannelsOf(ColorSpace);
 201.824  
 201.825 -                // Shouldn't reach here
 201.826 -                cmsFreeLUT(Lut);
 201.827 -                cmsCloseProfile(hICC);
 201.828 -                return NULL;
 201.829 -       }
 201.830 +    CLUT = cmsStageAllocCLut16bit(ContextID, 17, nChannels, nChannels, NULL);
 201.831 +    if (CLUT == NULL) goto Error;
 201.832  
 201.833 -       // Create tags
 201.834 +    if (!cmsStageSampleCLut16bit(CLUT, InkLimitingSampler, (void*) &Limit, 0)) goto Error;
 201.835  
 201.836 -       cmsAddTag(hICC, icSigDeviceMfgDescTag,      (LPVOID) "(lcms internal)");
 201.837 -       cmsAddTag(hICC, icSigProfileDescriptionTag, (LPVOID) "lcms ink limiting device link");
 201.838 -       cmsAddTag(hICC, icSigDeviceModelDescTag,    (LPVOID) "ink limiting built-in");
 201.839 +    cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, nChannels));
 201.840 +    cmsPipelineInsertStage(LUT, cmsAT_END, CLUT);
 201.841 +    cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocIdentityCurves(ContextID, nChannels));
 201.842  
 201.843 -       cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ());
 201.844 +    // Create tags
 201.845 +    if (!SetTextTags(hICC, L"ink-limiting built-in")) goto Error;
 201.846  
 201.847 -       cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut);
 201.848 +    if (!cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) LUT))  goto Error;
 201.849 +    if (!SetSeqDescTag(hICC, "ink-limiting built-in")) goto Error;
 201.850  
 201.851 -       // LUT is already on virtual profile
 201.852 -       cmsFreeLUT(Lut);
 201.853 +    // cmsPipeline is already on virtual profile
 201.854 +    cmsPipelineFree(LUT);
 201.855  
 201.856 -       // Ok, done
 201.857 -       return hICC;
 201.858 +    // Ok, done
 201.859 +    return hICC;
 201.860 +
 201.861 +Error:
 201.862 +    if (LUT != NULL)
 201.863 +        cmsPipelineFree(LUT);
 201.864 +
 201.865 +    if (hICC != NULL)
 201.866 +        cmsCloseProfile(hICC);
 201.867 +
 201.868 +    return NULL;
 201.869  }
 201.870  
 201.871 +cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLink(cmsColorSpaceSignature ColorSpace, cmsFloat64Number Limit)
 201.872 +{
 201.873 +    return cmsCreateInkLimitingDeviceLinkTHR(NULL, ColorSpace, Limit);
 201.874 +}
 201.875  
 201.876  
 201.877 +// Creates a fake Lab identity.
 201.878 +cmsHPROFILE CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint)
 201.879 +{
 201.880 +    cmsHPROFILE hProfile;
 201.881 +    cmsPipeline* LUT = NULL;
 201.882 +
 201.883 +    hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
 201.884 +    if (hProfile == NULL) return NULL;
 201.885 +
 201.886 +    cmsSetProfileVersion(hProfile, 2.1);
 201.887 +
 201.888 +    cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
 201.889 +    cmsSetColorSpace(hProfile,  cmsSigLabData);
 201.890 +    cmsSetPCS(hProfile,         cmsSigLabData);
 201.891 +
 201.892 +    if (!SetTextTags(hProfile, L"Lab identity built-in")) return NULL;
 201.893 +
 201.894 +    // An identity LUT is all we need
 201.895 +    LUT = cmsPipelineAlloc(ContextID, 3, 3);
 201.896 +    if (LUT == NULL) goto Error;
 201.897 +
 201.898 +    cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCLut(ContextID, 3));
 201.899 +
 201.900 +    if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
 201.901 +    cmsPipelineFree(LUT);
 201.902 +
 201.903 +    return hProfile;
 201.904 +
 201.905 +Error:
 201.906 +
 201.907 +    if (LUT != NULL)
 201.908 +        cmsPipelineFree(LUT);
 201.909 +
 201.910 +    if (hProfile != NULL)
 201.911 +        cmsCloseProfile(hProfile);
 201.912 +
 201.913 +    return NULL;
 201.914 +}
 201.915 +
 201.916 +
 201.917 +cmsHPROFILE CMSEXPORT cmsCreateLab2Profile(const cmsCIExyY* WhitePoint)
 201.918 +{
 201.919 +    return cmsCreateLab2ProfileTHR(NULL, WhitePoint);
 201.920 +}
 201.921 +
 201.922 +
 201.923 +// Creates a fake Lab V4 identity.
 201.924 +cmsHPROFILE CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint)
 201.925 +{
 201.926 +    cmsHPROFILE hProfile;
 201.927 +    cmsPipeline* LUT = NULL;
 201.928 +
 201.929 +    hProfile = cmsCreateRGBProfileTHR(ContextID, WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
 201.930 +    if (hProfile == NULL) return NULL;
 201.931 +
 201.932 +    cmsSetProfileVersion(hProfile, 4.2);
 201.933 +
 201.934 +    cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
 201.935 +    cmsSetColorSpace(hProfile,  cmsSigLabData);
 201.936 +    cmsSetPCS(hProfile,         cmsSigLabData);
 201.937 +
 201.938 +    if (!SetTextTags(hProfile, L"Lab identity built-in")) goto Error;
 201.939 +
 201.940 +    // An empty LUTs is all we need
 201.941 +    LUT = cmsPipelineAlloc(ContextID, 3, 3);
 201.942 +    if (LUT == NULL) goto Error;
 201.943 +
 201.944 +    cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3));
 201.945 +
 201.946 +    if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
 201.947 +    cmsPipelineFree(LUT);
 201.948 +
 201.949 +    return hProfile;
 201.950 +
 201.951 +Error:
 201.952 +
 201.953 +    if (LUT != NULL)
 201.954 +        cmsPipelineFree(LUT);
 201.955 +
 201.956 +    if (hProfile != NULL)
 201.957 +        cmsCloseProfile(hProfile);
 201.958 +
 201.959 +    return NULL;
 201.960 +}
 201.961 +
 201.962 +cmsHPROFILE CMSEXPORT cmsCreateLab4Profile(const cmsCIExyY* WhitePoint)
 201.963 +{
 201.964 +    return cmsCreateLab4ProfileTHR(NULL, WhitePoint);
 201.965 +}
 201.966 +
 201.967 +
 201.968 +// Creates a fake XYZ identity
 201.969 +cmsHPROFILE CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID)
 201.970 +{
 201.971 +    cmsHPROFILE hProfile;
 201.972 +    cmsPipeline* LUT = NULL;
 201.973 +
 201.974 +    hProfile = cmsCreateRGBProfileTHR(ContextID, cmsD50_xyY(), NULL, NULL);
 201.975 +    if (hProfile == NULL) return NULL;
 201.976 +
 201.977 +    cmsSetProfileVersion(hProfile, 4.2);
 201.978 +
 201.979 +    cmsSetDeviceClass(hProfile, cmsSigAbstractClass);
 201.980 +    cmsSetColorSpace(hProfile,  cmsSigXYZData);
 201.981 +    cmsSetPCS(hProfile,         cmsSigXYZData);
 201.982 +
 201.983 +    if (!SetTextTags(hProfile, L"XYZ identity built-in")) goto Error;
 201.984 +
 201.985 +    // An identity LUT is all we need
 201.986 +    LUT = cmsPipelineAlloc(ContextID, 3, 3);
 201.987 +    if (LUT == NULL) goto Error;
 201.988 +
 201.989 +    cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, 3));
 201.990 +
 201.991 +    if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
 201.992 +    cmsPipelineFree(LUT);
 201.993 +
 201.994 +    return hProfile;
 201.995 +
 201.996 +Error:
 201.997 +
 201.998 +    if (LUT != NULL)
 201.999 +        cmsPipelineFree(LUT);
201.1000 +
201.1001 +    if (hProfile != NULL)
201.1002 +        cmsCloseProfile(hProfile);
201.1003 +
201.1004 +    return NULL;
201.1005 +}
201.1006 +
201.1007 +
201.1008 +cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void)
201.1009 +{
201.1010 +    return cmsCreateXYZProfileTHR(NULL);
201.1011 +}
201.1012 +
201.1013 +
201.1014 +//sRGB Curves are defined by:
201.1015 +//
201.1016 +//If  R’sRGB,G’sRGB, B’sRGB < 0.04045
201.1017 +//
201.1018 +//    R =  R’sRGB / 12.92
201.1019 +//    G =  G’sRGB / 12.92
201.1020 +//    B =  B’sRGB / 12.92
201.1021 +//
201.1022 +//
201.1023 +//else if  R’sRGB,G’sRGB, B’sRGB >= 0.04045
201.1024 +//
201.1025 +//    R = ((R’sRGB + 0.055) / 1.055)^2.4
201.1026 +//    G = ((G’sRGB + 0.055) / 1.055)^2.4
201.1027 +//    B = ((B’sRGB + 0.055) / 1.055)^2.4
201.1028 +
201.1029  static
201.1030 -LPLUT Create3x3EmptyLUT(void)
201.1031 +cmsToneCurve* Build_sRGBGamma(cmsContext ContextID)
201.1032  {
201.1033 -        LPLUT AToB0 = cmsAllocLUT();
201.1034 -        if (AToB0 == NULL) return NULL;
201.1035 -
201.1036 -        AToB0 -> InputChan = AToB0 -> OutputChan = 3;
201.1037 -        return AToB0;
201.1038 -}
201.1039 -
201.1040 -
201.1041 -
201.1042 -// Creates a fake Lab identity.
201.1043 -cmsHPROFILE LCMSEXPORT cmsCreateLabProfile(LPcmsCIExyY WhitePoint)
201.1044 -{
201.1045 -        cmsHPROFILE hProfile;
201.1046 -        LPLUT Lut;
201.1047 -
201.1048 -        hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
201.1049 -        if (hProfile == NULL) return NULL;
201.1050 -
201.1051 -        cmsSetDeviceClass(hProfile, icSigAbstractClass);
201.1052 -        cmsSetColorSpace(hProfile,  icSigLabData);
201.1053 -        cmsSetPCS(hProfile,         icSigLabData);
201.1054 -
201.1055 -        cmsAddTag(hProfile, icSigDeviceMfgDescTag,     (LPVOID) "(lcms internal)");
201.1056 -        cmsAddTag(hProfile, icSigProfileDescriptionTag, (LPVOID) "lcms Lab identity");
201.1057 -        cmsAddTag(hProfile, icSigDeviceModelDescTag,    (LPVOID) "Lab built-in");
201.1058 -
201.1059 -
201.1060 -       // An empty LUTs is all we need
201.1061 -       Lut = Create3x3EmptyLUT();
201.1062 -       if (Lut == NULL) {
201.1063 -           cmsCloseProfile(hProfile);
201.1064 -           return NULL;
201.1065 -           }
201.1066 -
201.1067 -       cmsAddTag(hProfile, icSigAToB0Tag,    (LPVOID) Lut);
201.1068 -       cmsAddTag(hProfile, icSigBToA0Tag,    (LPVOID) Lut);
201.1069 -
201.1070 -       cmsFreeLUT(Lut);
201.1071 -
201.1072 -       return hProfile;
201.1073 -}
201.1074 -
201.1075 -
201.1076 -// Creates a fake Lab identity.
201.1077 -cmsHPROFILE LCMSEXPORT cmsCreateLab4Profile(LPcmsCIExyY WhitePoint)
201.1078 -{
201.1079 -        cmsHPROFILE hProfile;
201.1080 -        LPLUT Lut;
201.1081 -
201.1082 -        hProfile = cmsCreateRGBProfile(WhitePoint == NULL ? cmsD50_xyY() : WhitePoint, NULL, NULL);
201.1083 -        if (hProfile == NULL) return NULL;
201.1084 -
201.1085 -        cmsSetProfileICCversion(hProfile, 0x4000000);
201.1086 -
201.1087 -        cmsSetDeviceClass(hProfile, icSigAbstractClass);
201.1088 -        cmsSetColorSpace(hProfile,  icSigLabData);
201.1089 -        cmsSetPCS(hProfile,         icSigLabData);
201.1090 -
201.1091 -        cmsAddTag(hProfile, icSigDeviceMfgDescTag,     (LPVOID) "(lcms internal)");
201.1092 -        cmsAddTag(hProfile, icSigProfileDescriptionTag, (LPVOID) "lcms Lab identity v4");
201.1093 -        cmsAddTag(hProfile, icSigDeviceModelDescTag,    (LPVOID) "Lab v4 built-in");
201.1094 -
201.1095 -
201.1096 -       // An empty LUTs is all we need
201.1097 -       Lut = Create3x3EmptyLUT();
201.1098 -       if (Lut == NULL) {
201.1099 -           cmsCloseProfile(hProfile);
201.1100 -           return NULL;
201.1101 -           }
201.1102 -
201.1103 -       Lut -> wFlags |= LUT_V4_INPUT_EMULATE_V2;
201.1104 -       cmsAddTag(hProfile, icSigAToB0Tag,    (LPVOID) Lut);
201.1105 -
201.1106 -       Lut -> wFlags |= LUT_V4_OUTPUT_EMULATE_V2;
201.1107 -       cmsAddTag(hProfile, icSigBToA0Tag,    (LPVOID) Lut);
201.1108 -
201.1109 -       cmsFreeLUT(Lut);
201.1110 -
201.1111 -       return hProfile;
201.1112 -}
201.1113 -
201.1114 -
201.1115 -
201.1116 -// Creates a fake XYZ identity
201.1117 -cmsHPROFILE LCMSEXPORT cmsCreateXYZProfile(void)
201.1118 -{
201.1119 -        cmsHPROFILE hProfile;
201.1120 -        LPLUT Lut;
201.1121 -
201.1122 -        hProfile = cmsCreateRGBProfile(cmsD50_xyY(), NULL, NULL);
201.1123 -        if (hProfile == NULL) return NULL;
201.1124 -
201.1125 -        cmsSetDeviceClass(hProfile, icSigAbstractClass);
201.1126 -        cmsSetColorSpace(hProfile, icSigXYZData);
201.1127 -        cmsSetPCS(hProfile,  icSigXYZData);
201.1128 -
201.1129 -        cmsAddTag(hProfile, icSigDeviceMfgDescTag,      (LPVOID) "(lcms internal)");
201.1130 -        cmsAddTag(hProfile, icSigProfileDescriptionTag, (LPVOID) "lcms XYZ identity");
201.1131 -        cmsAddTag(hProfile, icSigDeviceModelDescTag,    (LPVOID)  "XYZ built-in");
201.1132 -
201.1133 -       // An empty LUTs is all we need
201.1134 -       Lut = Create3x3EmptyLUT();
201.1135 -       if (Lut == NULL) {
201.1136 -           cmsCloseProfile(hProfile);
201.1137 -           return NULL;
201.1138 -           }
201.1139 -
201.1140 -       cmsAddTag(hProfile, icSigAToB0Tag,    (LPVOID) Lut);
201.1141 -       cmsAddTag(hProfile, icSigBToA0Tag,    (LPVOID) Lut);
201.1142 -       cmsAddTag(hProfile, icSigPreview0Tag, (LPVOID) Lut);
201.1143 -
201.1144 -       cmsFreeLUT(Lut);
201.1145 -       return hProfile;
201.1146 -}
201.1147 -
201.1148 -
201.1149 -
201.1150 -/*
201.1151 -
201.1152 -If  R’sRGB,G’sRGB, B’sRGB < 0.04045
201.1153 -
201.1154 -    R =  R’sRGB / 12.92
201.1155 -    G =  G’sRGB / 12.92
201.1156 -    B =  B’sRGB / 12.92
201.1157 -
201.1158 -
201.1159 -
201.1160 -else if  R’sRGB,G’sRGB, B’sRGB >= 0.04045
201.1161 -
201.1162 -    R = ((R’sRGB + 0.055) / 1.055)^2.4
201.1163 -    G = ((G’sRGB + 0.055) / 1.055)^2.4
201.1164 -    B = ((B’sRGB + 0.055) / 1.055)^2.4
201.1165 -
201.1166 -  */
201.1167 -
201.1168 -static
201.1169 -LPGAMMATABLE Build_sRGBGamma(void)
201.1170 -{
201.1171 -    double Parameters[5];
201.1172 +    cmsFloat64Number Parameters[5];
201.1173  
201.1174      Parameters[0] = 2.4;
201.1175      Parameters[1] = 1. / 1.055;
201.1176      Parameters[2] = 0.055 / 1.055;
201.1177      Parameters[3] = 1. / 12.92;
201.1178 -    Parameters[4] = 0.04045;    // d
201.1179 +    Parameters[4] = 0.04045;
201.1180  
201.1181 -    return cmsBuildParametricGamma(1024, 4, Parameters);
201.1182 +    return cmsBuildParametricToneCurve(ContextID, 4, Parameters);
201.1183  }
201.1184  
201.1185  // Create the ICC virtual profile for sRGB space
201.1186 -cmsHPROFILE LCMSEXPORT cmsCreate_sRGBProfile(void)
201.1187 +cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
201.1188  {
201.1189         cmsCIExyY       D65;
201.1190         cmsCIExyYTRIPLE Rec709Primaries = {
201.1191 @@ -744,38 +658,44 @@
201.1192                                     {0.3000, 0.6000, 1.0},
201.1193                                     {0.1500, 0.0600, 1.0}
201.1194                                     };
201.1195 -       LPGAMMATABLE Gamma22[3];
201.1196 +       cmsToneCurve* Gamma22[3];
201.1197         cmsHPROFILE  hsRGB;
201.1198  
201.1199 -       cmsWhitePointFromTemp(6504, &D65);
201.1200 -       Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma();
201.1201 +       cmsWhitePointFromTemp(&D65, 6504);
201.1202 +       Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID);
201.1203 +       if (Gamma22[0] == NULL) return NULL;
201.1204  
201.1205 -       hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma22);
201.1206 -       cmsFreeGamma(Gamma22[0]);
201.1207 +       hsRGB = cmsCreateRGBProfileTHR(ContextID, &D65, &Rec709Primaries, Gamma22);
201.1208 +       cmsFreeToneCurve(Gamma22[0]);
201.1209         if (hsRGB == NULL) return NULL;
201.1210  
201.1211 -
201.1212 -       cmsAddTag(hsRGB, icSigDeviceMfgDescTag,      (LPVOID) "(lcms internal)");
201.1213 -       cmsAddTag(hsRGB, icSigDeviceModelDescTag,    (LPVOID) "sRGB built-in");
201.1214 -       cmsAddTag(hsRGB, icSigProfileDescriptionTag, (LPVOID) "sRGB built-in");
201.1215 +       if (!SetTextTags(hsRGB, L"sRGB built-in")) {
201.1216 +           cmsCloseProfile(hsRGB);
201.1217 +           return NULL;
201.1218 +       }
201.1219  
201.1220         return hsRGB;
201.1221  }
201.1222  
201.1223 +cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void)
201.1224 +{
201.1225 +    return cmsCreate_sRGBProfileTHR(NULL);
201.1226 +}
201.1227 +
201.1228  
201.1229  
201.1230  typedef struct {
201.1231 -                double Brightness;
201.1232 -                double Contrast;
201.1233 -                double Hue;
201.1234 -                double Saturation;
201.1235 +                cmsFloat64Number Brightness;
201.1236 +                cmsFloat64Number Contrast;
201.1237 +                cmsFloat64Number Hue;
201.1238 +                cmsFloat64Number Saturation;
201.1239                  cmsCIEXYZ WPsrc, WPdest;
201.1240  
201.1241  } BCHSWADJUSTS, *LPBCHSWADJUSTS;
201.1242  
201.1243  
201.1244  static
201.1245 -int bchswSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
201.1246 +int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
201.1247  {
201.1248      cmsCIELab LabIn, LabOut;
201.1249      cmsCIELCh LChIn, LChOut;
201.1250 @@ -813,116 +733,438 @@
201.1251  // Creates an abstract profile operating in Lab space for Brightness,
201.1252  // contrast, Saturation and white point displacement
201.1253  
201.1254 -cmsHPROFILE LCMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints,
201.1255 -                                                     double Bright,
201.1256 -                                                     double Contrast,
201.1257 -                                                     double Hue,
201.1258 -                                                     double Saturation,
201.1259 +cmsHPROFILE CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
201.1260 +                                                     int nLUTPoints,
201.1261 +                                                     cmsFloat64Number Bright,
201.1262 +                                                     cmsFloat64Number Contrast,
201.1263 +                                                     cmsFloat64Number Hue,
201.1264 +                                                     cmsFloat64Number Saturation,
201.1265                                                       int TempSrc,
201.1266                                                       int TempDest)
201.1267  {
201.1268       cmsHPROFILE hICC;
201.1269 -     LPLUT Lut;
201.1270 +     cmsPipeline* Pipeline;
201.1271       BCHSWADJUSTS bchsw;
201.1272       cmsCIExyY WhitePnt;
201.1273 +     cmsStage* CLUT;
201.1274 +     cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
201.1275 +     int i;
201.1276 +
201.1277  
201.1278       bchsw.Brightness = Bright;
201.1279       bchsw.Contrast   = Contrast;
201.1280       bchsw.Hue        = Hue;
201.1281       bchsw.Saturation = Saturation;
201.1282  
201.1283 -     cmsWhitePointFromTemp(TempSrc,  &WhitePnt);
201.1284 +     cmsWhitePointFromTemp(&WhitePnt, TempSrc );
201.1285       cmsxyY2XYZ(&bchsw.WPsrc, &WhitePnt);
201.1286  
201.1287 -     cmsWhitePointFromTemp(TempDest, &WhitePnt);
201.1288 +     cmsWhitePointFromTemp(&WhitePnt, TempDest);
201.1289       cmsxyY2XYZ(&bchsw.WPdest, &WhitePnt);
201.1290  
201.1291 -      hICC = _cmsCreateProfilePlaceholder();
201.1292 +      hICC = cmsCreateProfilePlaceholder(ContextID);
201.1293         if (!hICC)                          // can't allocate
201.1294              return NULL;
201.1295  
201.1296  
201.1297 -       cmsSetDeviceClass(hICC,      icSigAbstractClass);
201.1298 -       cmsSetColorSpace(hICC,       icSigLabData);
201.1299 -       cmsSetPCS(hICC,              icSigLabData);
201.1300 +       cmsSetDeviceClass(hICC,      cmsSigAbstractClass);
201.1301 +       cmsSetColorSpace(hICC,       cmsSigLabData);
201.1302 +       cmsSetPCS(hICC,              cmsSigLabData);
201.1303  
201.1304 -       cmsSetRenderingIntent(hICC,  INTENT_PERCEPTUAL);
201.1305 +       cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
201.1306  
201.1307  
201.1308 -       // Creates a LUT with 3D grid only
201.1309 -       Lut = cmsAllocLUT();
201.1310 -       if (Lut == NULL) {
201.1311 +       // Creates a Pipeline with 3D grid only
201.1312 +       Pipeline = cmsPipelineAlloc(ContextID, 3, 3);
201.1313 +       if (Pipeline == NULL) {
201.1314             cmsCloseProfile(hICC);
201.1315             return NULL;
201.1316             }
201.1317  
201.1318 -       cmsAlloc3DGrid(Lut, nLUTPoints, 3, 3);
201.1319 +       for (i=0; i < MAX_INPUT_DIMENSIONS; i++) Dimensions[i] = nLUTPoints;
201.1320 +       CLUT = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, 3, 3, NULL);
201.1321 +       if (CLUT == NULL) return NULL;
201.1322  
201.1323 -       if (!cmsSample3DGrid(Lut, bchswSampler, (LPVOID) &bchsw, 0)) {
201.1324 +
201.1325 +       if (!cmsStageSampleCLut16bit(CLUT, bchswSampler, (void*) &bchsw, 0)) {
201.1326  
201.1327                  // Shouldn't reach here
201.1328 -                cmsFreeLUT(Lut);
201.1329 +                cmsPipelineFree(Pipeline);
201.1330                  cmsCloseProfile(hICC);
201.1331                  return NULL;
201.1332         }
201.1333  
201.1334 +       cmsPipelineInsertStage(Pipeline, cmsAT_END, CLUT);
201.1335 +
201.1336         // Create tags
201.1337  
201.1338 -       cmsAddTag(hICC, icSigDeviceMfgDescTag,      (LPVOID) "(lcms internal)");
201.1339 -       cmsAddTag(hICC, icSigProfileDescriptionTag, (LPVOID) "lcms BCHSW abstract profile");
201.1340 -       cmsAddTag(hICC, icSigDeviceModelDescTag,    (LPVOID) "BCHSW built-in");
201.1341 +       if (!SetTextTags(hICC, L"BCHS built-in")) return NULL;
201.1342  
201.1343 -       cmsAddTag(hICC, icSigMediaWhitePointTag, (LPVOID) cmsD50_XYZ());
201.1344 +       cmsWriteTag(hICC, cmsSigMediaWhitePointTag, (void*) cmsD50_XYZ());
201.1345  
201.1346 -       cmsAddTag(hICC, icSigAToB0Tag, (LPVOID) Lut);
201.1347 +       cmsWriteTag(hICC, cmsSigAToB0Tag, (void*) Pipeline);
201.1348  
201.1349 -       // LUT is already on virtual profile
201.1350 -       cmsFreeLUT(Lut);
201.1351 +       // Pipeline is already on virtual profile
201.1352 +       cmsPipelineFree(Pipeline);
201.1353  
201.1354         // Ok, done
201.1355         return hICC;
201.1356 +}
201.1357  
201.1358 +
201.1359 +CMSAPI cmsHPROFILE   CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints,
201.1360 +                                                             cmsFloat64Number Bright,
201.1361 +                                                             cmsFloat64Number Contrast,
201.1362 +                                                             cmsFloat64Number Hue,
201.1363 +                                                             cmsFloat64Number Saturation,
201.1364 +                                                             int TempSrc,
201.1365 +                                                             int TempDest)
201.1366 +{
201.1367 +    return cmsCreateBCHSWabstractProfileTHR(NULL, nLUTPoints, Bright, Contrast, Hue, Saturation, TempSrc, TempDest);
201.1368  }
201.1369  
201.1370  
201.1371  // Creates a fake NULL profile. This profile return 1 channel as always 0.
201.1372  // Is useful only for gamut checking tricks
201.1373 +cmsHPROFILE CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID)
201.1374 +{
201.1375 +    cmsHPROFILE hProfile;
201.1376 +    cmsPipeline* LUT = NULL;
201.1377 +    cmsStage* PostLin;
201.1378 +    cmsToneCurve* EmptyTab;
201.1379 +    cmsUInt16Number Zero[2] = { 0, 0 };
201.1380  
201.1381 -cmsHPROFILE LCMSEXPORT cmsCreateNULLProfile(void)
201.1382 +    hProfile = cmsCreateProfilePlaceholder(ContextID);
201.1383 +    if (!hProfile)                          // can't allocate
201.1384 +        return NULL;
201.1385 +
201.1386 +    cmsSetProfileVersion(hProfile, 4.2);
201.1387 +
201.1388 +    if (!SetTextTags(hProfile, L"NULL profile built-in")) goto Error;
201.1389 +
201.1390 +
201.1391 +
201.1392 +    cmsSetDeviceClass(hProfile, cmsSigOutputClass);
201.1393 +    cmsSetColorSpace(hProfile,  cmsSigGrayData);
201.1394 +    cmsSetPCS(hProfile,         cmsSigLabData);
201.1395 +
201.1396 +    // An empty LUTs is all we need
201.1397 +    LUT = cmsPipelineAlloc(ContextID, 1, 1);
201.1398 +    if (LUT == NULL) goto Error;
201.1399 +
201.1400 +    EmptyTab = cmsBuildTabulatedToneCurve16(ContextID, 2, Zero);
201.1401 +    PostLin = cmsStageAllocToneCurves(ContextID, 1, &EmptyTab);
201.1402 +    cmsFreeToneCurve(EmptyTab);
201.1403 +
201.1404 +    cmsPipelineInsertStage(LUT, cmsAT_END, PostLin);
201.1405 +
201.1406 +    if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, (void*) LUT)) goto Error;
201.1407 +    if (!cmsWriteTag(hProfile, cmsSigMediaWhitePointTag, cmsD50_XYZ())) goto Error;
201.1408 +
201.1409 +    cmsPipelineFree(LUT);
201.1410 +    return hProfile;
201.1411 +
201.1412 +Error:
201.1413 +
201.1414 +    if (LUT != NULL)
201.1415 +        cmsPipelineFree(LUT);
201.1416 +
201.1417 +    if (hProfile != NULL)
201.1418 +        cmsCloseProfile(hProfile);
201.1419 +
201.1420 +    return NULL;
201.1421 +}
201.1422 +
201.1423 +cmsHPROFILE CMSEXPORT cmsCreateNULLProfile(void)
201.1424  {
201.1425 -        cmsHPROFILE hProfile;
201.1426 -        LPLUT Lut;
201.1427 -        LPGAMMATABLE EmptyTab;
201.1428 +    return cmsCreateNULLProfileTHR(NULL);
201.1429 +}
201.1430  
201.1431 -        hProfile = _cmsCreateProfilePlaceholder();
201.1432 -        if (!hProfile)                          // can't allocate
201.1433 -                return NULL;
201.1434  
201.1435 -        cmsSetDeviceClass(hProfile, icSigOutputClass);
201.1436 -        cmsSetColorSpace(hProfile,  icSigGrayData);
201.1437 -        cmsSetPCS(hProfile,         icSigLabData);
201.1438 +static
201.1439 +int IsPCS(cmsColorSpaceSignature ColorSpace)
201.1440 +{
201.1441 +    return (ColorSpace == cmsSigXYZData ||
201.1442 +            ColorSpace == cmsSigLabData);
201.1443 +}
201.1444  
201.1445  
201.1446 -       // An empty LUTs is all we need
201.1447 -       Lut = cmsAllocLUT();
201.1448 -       if (Lut == NULL) {
201.1449 -           cmsCloseProfile(hProfile);
201.1450 -           return NULL;
201.1451 -           }
201.1452 +static
201.1453 +void FixColorSpaces(cmsHPROFILE hProfile,
201.1454 +                              cmsColorSpaceSignature ColorSpace,
201.1455 +                              cmsColorSpaceSignature PCS,
201.1456 +                              cmsUInt32Number dwFlags)
201.1457 +{
201.1458 +    if (dwFlags & cmsFLAGS_GUESSDEVICECLASS) {
201.1459  
201.1460 -       Lut -> InputChan = 3;
201.1461 -       Lut -> OutputChan = 1;
201.1462 +            if (IsPCS(ColorSpace) && IsPCS(PCS)) {
201.1463  
201.1464 -       EmptyTab = cmsAllocGamma(2);
201.1465 -       EmptyTab ->GammaTable[0] = 0;
201.1466 -       EmptyTab ->GammaTable[1] = 0;
201.1467 +                    cmsSetDeviceClass(hProfile,      cmsSigAbstractClass);
201.1468 +                    cmsSetColorSpace(hProfile,       ColorSpace);
201.1469 +                    cmsSetPCS(hProfile,              PCS);
201.1470 +                    return;
201.1471 +            }
201.1472  
201.1473 -       cmsAllocLinearTable(Lut, &EmptyTab, 2);
201.1474 +            if (IsPCS(ColorSpace) && !IsPCS(PCS)) {
201.1475  
201.1476 -       cmsAddTag(hProfile, icSigBToA0Tag, (LPVOID) Lut);
201.1477 +                    cmsSetDeviceClass(hProfile, cmsSigOutputClass);
201.1478 +                    cmsSetPCS(hProfile,         ColorSpace);
201.1479 +                    cmsSetColorSpace(hProfile,  PCS);
201.1480 +                    return;
201.1481 +            }
201.1482  
201.1483 -       cmsFreeLUT(Lut);
201.1484 -       cmsFreeGamma(EmptyTab);
201.1485 +            if (IsPCS(PCS) && !IsPCS(ColorSpace)) {
201.1486  
201.1487 -       return hProfile;
201.1488 +                   cmsSetDeviceClass(hProfile,  cmsSigInputClass);
201.1489 +                   cmsSetColorSpace(hProfile,   ColorSpace);
201.1490 +                   cmsSetPCS(hProfile,          PCS);
201.1491 +                   return;
201.1492 +            }
201.1493 +    }
201.1494 +
201.1495 +    cmsSetDeviceClass(hProfile,      cmsSigLinkClass);
201.1496 +    cmsSetColorSpace(hProfile,       ColorSpace);
201.1497 +    cmsSetPCS(hProfile,              PCS);
201.1498  }
201.1499 +
201.1500 +
201.1501 +
201.1502 +// This function creates a named color profile dumping all the contents of transform to a single profile
201.1503 +// In this way, LittleCMS may be used to "group" several named color databases into a single profile.
201.1504 +// It has, however, several minor limitations. PCS is always Lab, which is not very critic since this
201.1505 +// is the normal PCS for named color profiles.
201.1506 +static
201.1507 +cmsHPROFILE CreateNamedColorDevicelink(cmsHTRANSFORM xform)
201.1508 +{
201.1509 +    _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
201.1510 +    cmsHPROFILE hICC = NULL;
201.1511 +    int i, nColors;
201.1512 +    cmsNAMEDCOLORLIST *nc2 = NULL, *Original = NULL;
201.1513 +
201.1514 +    // Create an empty placeholder
201.1515 +    hICC = cmsCreateProfilePlaceholder(v->ContextID);
201.1516 +    if (hICC == NULL) return NULL;
201.1517 +
201.1518 +    // Critical information
201.1519 +    cmsSetDeviceClass(hICC, cmsSigNamedColorClass);
201.1520 +    cmsSetColorSpace(hICC, v ->ExitColorSpace);
201.1521 +    cmsSetPCS(hICC, cmsSigLabData);
201.1522 +
201.1523 +    // Tag profile with information
201.1524 +    if (!SetTextTags(hICC, L"Named color devicelink")) goto Error;
201.1525 +
201.1526 +    Original = cmsGetNamedColorList(xform);
201.1527 +    if (Original == NULL) goto Error;
201.1528 +
201.1529 +    nColors = cmsNamedColorCount(Original);
201.1530 +    nc2     = cmsDupNamedColorList(Original);
201.1531 +    if (nc2 == NULL) goto Error;
201.1532 +
201.1533 +    // Colorant count now depends on the output space
201.1534 +    nc2 ->ColorantCount = cmsPipelineOutputChannels(v ->Lut);
201.1535 +
201.1536 +    // Apply the transfor to colorants.
201.1537 +    for (i=0; i < nColors; i++) {
201.1538 +        cmsDoTransform(xform, &i, nc2 ->List[i].DeviceColorant, 1);
201.1539 +    }
201.1540 +
201.1541 +    if (!cmsWriteTag(hICC, cmsSigNamedColor2Tag, (void*) nc2)) goto Error;
201.1542 +    cmsFreeNamedColorList(nc2);
201.1543 +
201.1544 +    return hICC;
201.1545 +
201.1546 +Error:
201.1547 +    if (hICC != NULL) cmsCloseProfile(hICC);
201.1548 +    return NULL;
201.1549 +}
201.1550 +
201.1551 +
201.1552 +// This structure holds information about which MPU can be stored on a profile based on the version
201.1553 +
201.1554 +typedef struct {
201.1555 +    cmsBool              IsV4;             // Is a V4 tag?
201.1556 +    cmsTagTypeSignature  LutType;          // The LUT type
201.1557 +    int                  nTypes;           // Number of types (up to 5)
201.1558 +    cmsStageSignature    MpeTypes[5];      // 5 is the maximum number
201.1559 +
201.1560 +} cmsAllowedLUT;
201.1561 +
201.1562 +static const cmsAllowedLUT AllowedLUTTypes[] = {
201.1563 +
201.1564 +    { FALSE, cmsSigLut16Type,    4,  { cmsSigMatrixElemType,  cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
201.1565 +    { FALSE, cmsSigLut16Type,    3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType}},
201.1566 +    { TRUE , cmsSigLutAtoBType,  1,  { cmsSigCurveSetElemType } },
201.1567 +    { TRUE , cmsSigLutAtoBType,  3,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
201.1568 +    { TRUE , cmsSigLutAtoBType,  3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType   } },
201.1569 +    { TRUE , cmsSigLutAtoBType,  5,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},
201.1570 +    { TRUE , cmsSigLutBtoAType,  1,  { cmsSigCurveSetElemType }},
201.1571 +    { TRUE , cmsSigLutBtoAType,  3,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},
201.1572 +    { TRUE , cmsSigLutBtoAType,  3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType }},
201.1573 +    { TRUE , cmsSigLutBtoAType,  5,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType }}
201.1574 +};
201.1575 +
201.1576 +#define SIZE_OF_ALLOWED_LUT (sizeof(AllowedLUTTypes)/sizeof(cmsAllowedLUT))
201.1577 +
201.1578 +// Check a single entry
201.1579 +static
201.1580 +cmsBool CheckOne(const cmsAllowedLUT* Tab, const cmsPipeline* Lut)
201.1581 +{
201.1582 +    cmsStage* mpe;
201.1583 +    int n;
201.1584 +
201.1585 +    for (n=0, mpe = Lut ->Elements; mpe != NULL; mpe = mpe ->Next, n++) {
201.1586 +
201.1587 +        if (n > Tab ->nTypes) return FALSE;
201.1588 +        if (cmsStageType(mpe) != Tab ->MpeTypes[n]) return FALSE;
201.1589 +    }
201.1590 +
201.1591 +    return (n == Tab ->nTypes);
201.1592 +}
201.1593 +
201.1594 +
201.1595 +static
201.1596 +const cmsAllowedLUT* FindCombination(const cmsPipeline* Lut, cmsBool IsV4)
201.1597 +{
201.1598 +    int n;
201.1599 +
201.1600 +    for (n=0; n < SIZE_OF_ALLOWED_LUT; n++) {
201.1601 +
201.1602 +        const cmsAllowedLUT* Tab = AllowedLUTTypes + n;
201.1603 +
201.1604 +        if (IsV4 ^ Tab -> IsV4) continue;
201.1605 +        if (CheckOne(Tab, Lut)) return Tab;
201.1606 +    }
201.1607 +
201.1608 +    return NULL;
201.1609 +}
201.1610 +
201.1611 +
201.1612 +// Does convert a transform into a device link profile
201.1613 +cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
201.1614 +{
201.1615 +    cmsHPROFILE hProfile = NULL;
201.1616 +    cmsUInt32Number FrmIn, FrmOut, ChansIn, ChansOut;
201.1617 +    cmsUInt32Number ColorSpaceBitsIn, ColorSpaceBitsOut;
201.1618 +    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
201.1619 +    cmsPipeline* LUT = NULL;
201.1620 +    cmsStage* mpe;
201.1621 +    cmsContext ContextID = cmsGetTransformContextID(hTransform);
201.1622 +    const cmsAllowedLUT* AllowedLUT;
201.1623 +
201.1624 +    _cmsAssert(hTransform != NULL);
201.1625 +
201.1626 +    // Get the first mpe to check for named color
201.1627 +    mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut);
201.1628 +
201.1629 +    // Check if is a named color transform
201.1630 +    if (mpe != NULL) {
201.1631 +
201.1632 +        if (cmsStageType(mpe) == cmsSigNamedColorElemType) {
201.1633 +            return CreateNamedColorDevicelink(hTransform);
201.1634 +        }
201.1635 +    }
201.1636 +
201.1637 +    // First thing to do is to get a copy of the transformation
201.1638 +    LUT = cmsPipelineDup(xform ->Lut);
201.1639 +    if (LUT == NULL) return NULL;
201.1640 +
201.1641 +    // Time to fix the Lab2/Lab4 issue.
201.1642 +    if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
201.1643 +
201.1644 +        cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID));
201.1645 +    }
201.1646 +
201.1647 +    // On the output side too
201.1648 +    if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {
201.1649 +
201.1650 +        cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID));
201.1651 +    }
201.1652 +
201.1653 +    // Optimize the LUT and precalculate a devicelink
201.1654 +
201.1655 +    ChansIn  = cmsChannelsOf(xform -> EntryColorSpace);
201.1656 +    ChansOut = cmsChannelsOf(xform -> ExitColorSpace);
201.1657 +
201.1658 +    ColorSpaceBitsIn  = _cmsLCMScolorSpace(xform -> EntryColorSpace);
201.1659 +    ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace);
201.1660 +
201.1661 +    FrmIn  = COLORSPACE_SH(ColorSpaceBitsIn) | CHANNELS_SH(ChansIn)|BYTES_SH(2);
201.1662 +    FrmOut = COLORSPACE_SH(ColorSpaceBitsOut) | CHANNELS_SH(ChansOut)|BYTES_SH(2);
201.1663 +
201.1664 +
201.1665 +    // Check if the profile/version can store the result
201.1666 +    if (dwFlags & cmsFLAGS_FORCE_CLUT)
201.1667 +        AllowedLUT = NULL;
201.1668 +    else
201.1669 +    AllowedLUT = FindCombination(LUT, Version >= 4.0);
201.1670 +
201.1671 +    if (AllowedLUT == NULL) {
201.1672 +
201.1673 +        // Try to optimize
201.1674 +        _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
201.1675 +        AllowedLUT = FindCombination(LUT, Version >= 4.0);
201.1676 +
201.1677 +    }
201.1678 +
201.1679 +    // If no way, then force CLUT that for sure can be written
201.1680 +    if (AllowedLUT == NULL) {
201.1681 +
201.1682 +        dwFlags |= cmsFLAGS_FORCE_CLUT;
201.1683 +        _cmsOptimizePipeline(&LUT, xform ->RenderingIntent, &FrmIn, &FrmOut, &dwFlags);
201.1684 +
201.1685 +        // Put identity curves if needed
201.1686 +        if (cmsPipelineStageCount(LUT) == 1) {
201.1687 +
201.1688 +            cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocIdentityCurves(ContextID, ChansIn));
201.1689 +            cmsPipelineInsertStage(LUT, cmsAT_END,   _cmsStageAllocIdentityCurves(ContextID, ChansOut));
201.1690 +        }
201.1691 +
201.1692 +        AllowedLUT = FindCombination(LUT, Version >= 4.0);
201.1693 +    }
201.1694 +
201.1695 +    // Somethings is wrong...
201.1696 +    if (AllowedLUT == NULL) {
201.1697 +        goto Error;
201.1698 +    }
201.1699 +
201.1700 +    hProfile = cmsCreateProfilePlaceholder(ContextID);
201.1701 +    if (!hProfile) goto Error;                    // can't allocate
201.1702 +
201.1703 +    cmsSetProfileVersion(hProfile, Version);
201.1704 +
201.1705 +    FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags);
201.1706 +
201.1707 +    if (dwFlags & cmsFLAGS_8BITS_DEVICELINK)
201.1708 +                     cmsPipelineSetSaveAs8bitsFlag(LUT, TRUE);
201.1709 +
201.1710 +    // Tag profile with information
201.1711 +    if (!SetTextTags(hProfile, L"devicelink")) return NULL;
201.1712 +
201.1713 +    if (cmsGetDeviceClass(hProfile) == cmsSigOutputClass) {
201.1714 +
201.1715 +        if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, LUT)) goto Error;
201.1716 +    }
201.1717 +    else
201.1718 +        if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, LUT)) goto Error;
201.1719 +
201.1720 +
201.1721 +    if (xform -> InputColorant != NULL) {
201.1722 +           if (!cmsWriteTag(hProfile, cmsSigColorantTableTag, xform->InputColorant)) goto Error;
201.1723 +    }
201.1724 +
201.1725 +    if (xform -> OutputColorant != NULL) {
201.1726 +           if (!cmsWriteTag(hProfile, cmsSigColorantTableOutTag, xform->OutputColorant)) goto Error;
201.1727 +    }
201.1728 +
201.1729 +    if (xform ->Sequence != NULL) {
201.1730 +        if (!_cmsWriteProfileSequence(hProfile, xform ->Sequence)) goto Error;
201.1731 +    }
201.1732 +
201.1733 +    cmsPipelineFree(LUT);
201.1734 +    return hProfile;
201.1735 +
201.1736 +Error:
201.1737 +    if (LUT != NULL) cmsPipelineFree(LUT);
201.1738 +    cmsCloseProfile(hProfile);
201.1739 +    return NULL;
201.1740 +}
   202.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c	Thu Sep 23 17:33:40 2010 -0700
   202.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmswtpnt.c	Fri Sep 24 16:41:32 2010 -0700
   202.3 @@ -27,9 +27,10 @@
   202.4  // However, the following notice accompanied the original version of this
   202.5  // file:
   202.6  //
   202.7 +//---------------------------------------------------------------------------------
   202.8  //
   202.9 -//  Little cms
  202.10 -//  Copyright (C) 1998-2007 Marti Maria
  202.11 +//  Little Color Management System
  202.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  202.13  //
  202.14  // Permission is hereby granted, free of charge, to any person obtaining
  202.15  // a copy of this software and associated documentation files (the "Software"),
  202.16 @@ -48,43 +49,38 @@
  202.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  202.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  202.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  202.20 +//
  202.21 +//---------------------------------------------------------------------------------
  202.22 +//
  202.23  
  202.24 -#include "lcms.h"
  202.25 +#include "lcms2_internal.h"
  202.26  
  202.27  
  202.28 -// Conversions
  202.29 +// D50 - Widely used
  202.30 +const cmsCIEXYZ* CMSEXPORT cmsD50_XYZ(void)
  202.31 +{
  202.32 +    static cmsCIEXYZ D50XYZ = {cmsD50X, cmsD50Y, cmsD50Z};
  202.33  
  202.34 -void LCMSEXPORT cmsXYZ2xyY(LPcmsCIExyY Dest, const cmsCIEXYZ* Source)
  202.35 -{
  202.36 -       double ISum;
  202.37 -
  202.38 -       ISum = 1./(Source -> X + Source -> Y + Source -> Z);
  202.39 -
  202.40 -       Dest -> x = (Source -> X) * ISum;
  202.41 -       Dest -> y = (Source -> Y) * ISum;
  202.42 -       Dest -> Y = Source -> Y;
  202.43 +    return &D50XYZ;
  202.44  }
  202.45  
  202.46 +const cmsCIExyY* CMSEXPORT cmsD50_xyY(void)
  202.47 +{
  202.48 +    static cmsCIExyY D50xyY;
  202.49  
  202.50 -void LCMSEXPORT cmsxyY2XYZ(LPcmsCIEXYZ Dest, const cmsCIExyY* Source)
  202.51 -{
  202.52 +    cmsXYZ2xyY(&D50xyY, cmsD50_XYZ());
  202.53  
  202.54 -        Dest -> X = (Source -> x / Source -> y) * Source -> Y;
  202.55 -        Dest -> Y = Source -> Y;
  202.56 -        Dest -> Z = ((1 - Source -> x - Source -> y) / Source -> y) * Source -> Y;
  202.57 +    return &D50xyY;
  202.58  }
  202.59  
  202.60 +// Obtains WhitePoint from Temperature
  202.61 +cmsBool  CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number TempK)
  202.62 +{
  202.63 +       cmsFloat64Number x, y;
  202.64 +       cmsFloat64Number T, T2, T3;
  202.65 +       // cmsFloat64Number M1, M2;
  202.66  
  202.67 -// Obtains WhitePoint from Temperature
  202.68 -
  202.69 -LCMSBOOL LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint)
  202.70 -{
  202.71 -       double x, y;
  202.72 -       double T, T2, T3;
  202.73 -       // double M1, M2;
  202.74 -
  202.75 -
  202.76 -       // No optimization provided.
  202.77 +       _cmsAssert(WhitePoint != NULL);
  202.78  
  202.79         T = TempK;
  202.80         T2 = T*T;            // Square
  202.81 @@ -104,7 +100,7 @@
  202.82                x = -2.0064*(1E9/T3) + 1.9018*(1E6/T2) + 0.24748*(1E3/T) + 0.237040;
  202.83         }
  202.84         else {
  202.85 -              cmsSignalError(LCMS_ERRC_ABORTED, "cmsWhitePointFromTemp: invalid temp");
  202.86 +              cmsSignalError(0, cmsERROR_RANGE, "cmsWhitePointFromTemp: invalid temp");
  202.87                return FALSE;
  202.88                }
  202.89  
  202.90 @@ -117,10 +113,6 @@
  202.91         // M1 = (-1.3515 - 1.7703*x + 5.9114 *y)/(0.0241 + 0.2562*x - 0.7341*y);
  202.92         // M2 = (0.0300 - 31.4424*x + 30.0717*y)/(0.0241 + 0.2562*x - 0.7341*y);
  202.93  
  202.94 -
  202.95 -
  202.96 -       // Fill WhitePoint struct
  202.97 -
  202.98         WhitePoint -> x = x;
  202.99         WhitePoint -> y = y;
 202.100         WhitePoint -> Y = 1.0;
 202.101 @@ -128,205 +120,16 @@
 202.102         return TRUE;
 202.103  }
 202.104  
 202.105 -// Build a White point, primary chromas transfer matrix from RGB to CIE XYZ
 202.106 -// This is just an approximation, I am not handling all the non-linear
 202.107 -// aspects of the RGB to XYZ process, and assumming that the gamma correction
 202.108 -// has transitive property in the tranformation chain.
 202.109 -//
 202.110 -// the alghoritm:
 202.111 -//
 202.112 -//            - First I build the absolute conversion matrix using
 202.113 -//              primaries in XYZ. This matrix is next inverted
 202.114 -//            - Then I eval the source white point across this matrix
 202.115 -//              obtaining the coeficients of the transformation
 202.116 -//            - Then, I apply these coeficients to the original matrix
 202.117 -
 202.118 -
 202.119 -LCMSBOOL LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r, LPcmsCIExyY WhitePt,
 202.120 -                                            LPcmsCIExyYTRIPLE Primrs)
 202.121 -{
 202.122 -        VEC3 WhitePoint, Coef;
 202.123 -        MAT3 Result, Primaries;
 202.124 -        double xn, yn;
 202.125 -        double xr, yr;
 202.126 -        double xg, yg;
 202.127 -        double xb, yb;
 202.128 -
 202.129 -
 202.130 -        xn = WhitePt -> x;
 202.131 -        yn = WhitePt -> y;
 202.132 -        xr = Primrs -> Red.x;
 202.133 -        yr = Primrs -> Red.y;
 202.134 -        xg = Primrs -> Green.x;
 202.135 -        yg = Primrs -> Green.y;
 202.136 -        xb = Primrs -> Blue.x;
 202.137 -        yb = Primrs -> Blue.y;
 202.138 -
 202.139 -
 202.140 -        // Build Primaries matrix
 202.141 -        VEC3init(&Primaries.v[0], xr,        xg,         xb);
 202.142 -        VEC3init(&Primaries.v[1], yr,        yg,         yb);
 202.143 -        VEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg),  (1-xb-yb));
 202.144 -
 202.145 -
 202.146 -        // Result = Primaries ^ (-1) inverse matrix
 202.147 -        if (!MAT3inverse(&Primaries, &Result))
 202.148 -                        return FALSE;
 202.149 -
 202.150 -
 202.151 -        VEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn);
 202.152 -
 202.153 -        // Across inverse primaries ...
 202.154 -        MAT3eval(&Coef, &Result, &WhitePoint);
 202.155 -
 202.156 -        // Give us the Coefs, then I build transformation matrix
 202.157 -        VEC3init(&r -> v[0], Coef.n[VX]*xr,          Coef.n[VY]*xg,          Coef.n[VZ]*xb);
 202.158 -        VEC3init(&r -> v[1], Coef.n[VX]*yr,          Coef.n[VY]*yg,          Coef.n[VZ]*yb);
 202.159 -        VEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb));
 202.160 -
 202.161 -
 202.162 -        return TRUE;
 202.163 -}
 202.164 -
 202.165 -
 202.166 -
 202.167 -// Compute chromatic adaptation matrix using Chad as cone matrix
 202.168 -
 202.169 -static
 202.170 -void ComputeChromaticAdaptation(LPMAT3 Conversion,
 202.171 -                                LPcmsCIEXYZ SourceWhitePoint,
 202.172 -                                LPcmsCIEXYZ DestWhitePoint,
 202.173 -                                LPMAT3 Chad)
 202.174 -
 202.175 -{
 202.176 -
 202.177 -        MAT3 Chad_Inv;
 202.178 -        VEC3 ConeSourceXYZ, ConeSourceRGB;
 202.179 -        VEC3 ConeDestXYZ, ConeDestRGB;
 202.180 -        MAT3 Cone, Tmp;
 202.181 -
 202.182 -
 202.183 -        Tmp = *Chad;
 202.184 -        MAT3inverse(&Tmp, &Chad_Inv);
 202.185 -
 202.186 -        VEC3init(&ConeSourceXYZ, SourceWhitePoint -> X,
 202.187 -                                 SourceWhitePoint -> Y,
 202.188 -                                 SourceWhitePoint -> Z);
 202.189 -
 202.190 -        VEC3init(&ConeDestXYZ,   DestWhitePoint -> X,
 202.191 -                                 DestWhitePoint -> Y,
 202.192 -                                 DestWhitePoint -> Z);
 202.193 -
 202.194 -        MAT3eval(&ConeSourceRGB, Chad, &ConeSourceXYZ);
 202.195 -        MAT3eval(&ConeDestRGB,   Chad, &ConeDestXYZ);
 202.196 -
 202.197 -        // Build matrix
 202.198 -
 202.199 -        VEC3init(&Cone.v[0], ConeDestRGB.n[0]/ConeSourceRGB.n[0],    0.0,  0.0);
 202.200 -        VEC3init(&Cone.v[1], 0.0,   ConeDestRGB.n[1]/ConeSourceRGB.n[1],   0.0);
 202.201 -        VEC3init(&Cone.v[2], 0.0,   0.0,   ConeDestRGB.n[2]/ConeSourceRGB.n[2]);
 202.202 -
 202.203 -
 202.204 -        // Normalize
 202.205 -        MAT3per(&Tmp, &Cone, Chad);
 202.206 -        MAT3per(Conversion, &Chad_Inv, &Tmp);
 202.207 -
 202.208 -}
 202.209 -
 202.210 -
 202.211 -// Returns the final chrmatic adaptation from illuminant FromIll to Illuminant ToIll
 202.212 -// The cone matrix can be specified in ConeMatrix. If NULL, Bradford is assumed
 202.213 -
 202.214 -LCMSBOOL cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll)
 202.215 -{
 202.216 -     MAT3 LamRigg   = {{ // Bradford matrix
 202.217 -                      {{  0.8951,  0.2664, -0.1614 }},
 202.218 -                      {{ -0.7502,  1.7135,  0.0367 }},
 202.219 -                      {{  0.0389, -0.0685,  1.0296 }}
 202.220 -                      }};
 202.221 -
 202.222 -
 202.223 -      if (ConeMatrix == NULL)
 202.224 -            ConeMatrix = &LamRigg;
 202.225 -
 202.226 -      ComputeChromaticAdaptation(r, FromIll, ToIll, ConeMatrix);
 202.227 -      return TRUE;
 202.228 -
 202.229 -}
 202.230 -
 202.231 -// Same as anterior, but assuming D50 destination. White point is given in xyY
 202.232 -
 202.233 -LCMSBOOL cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt)
 202.234 -{
 202.235 -        cmsCIEXYZ Dn;
 202.236 -        MAT3 Bradford;
 202.237 -        MAT3 Tmp;
 202.238 -
 202.239 -        cmsxyY2XYZ(&Dn, SourceWhitePt);
 202.240 -
 202.241 -        cmsAdaptationMatrix(&Bradford, NULL, &Dn, cmsD50_XYZ());
 202.242 -
 202.243 -        Tmp = *r;
 202.244 -        MAT3per(r, &Bradford, &Tmp);
 202.245 -
 202.246 -        return TRUE;
 202.247 -}
 202.248 -
 202.249 -
 202.250 -// Same as anterior, but assuming D50 source. White point is given in xyY
 202.251 -
 202.252 -LCMSBOOL cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt)
 202.253 -{
 202.254 -        cmsCIEXYZ Dn;
 202.255 -        MAT3 Bradford;
 202.256 -        MAT3 Tmp;
 202.257 -
 202.258 -        cmsxyY2XYZ(&Dn, DestWhitePt);
 202.259 -
 202.260 -        cmsAdaptationMatrix(&Bradford, NULL, cmsD50_XYZ(), &Dn);
 202.261 -
 202.262 -        Tmp = *r;
 202.263 -        MAT3per(r, &Bradford, &Tmp);
 202.264 -
 202.265 -        return TRUE;
 202.266 -}
 202.267 -
 202.268 -
 202.269 -// Adapts a color to a given illuminant. Original color is expected to have
 202.270 -// a SourceWhitePt white point.
 202.271 -
 202.272 -LCMSBOOL LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
 202.273 -                                     LPcmsCIEXYZ SourceWhitePt,
 202.274 -                                     LPcmsCIEXYZ Illuminant,
 202.275 -                                     LPcmsCIEXYZ Value)
 202.276 -{
 202.277 -        MAT3 Bradford;
 202.278 -        VEC3 In, Out;
 202.279 -
 202.280 -        // BradfordLamRiggChromaticAdaptation(&Bradford, SourceWhitePt, Illuminant);
 202.281 -
 202.282 -        cmsAdaptationMatrix(&Bradford, NULL, SourceWhitePt, Illuminant);
 202.283 -
 202.284 -        VEC3init(&In, Value -> X, Value -> Y, Value -> Z);
 202.285 -        MAT3eval(&Out, &Bradford, &In);
 202.286 -
 202.287 -        Result -> X = Out.n[0];
 202.288 -        Result -> Y = Out.n[1];
 202.289 -        Result -> Z = Out.n[2];
 202.290 -
 202.291 -        return TRUE;
 202.292 -}
 202.293 -
 202.294  
 202.295  
 202.296  typedef struct {
 202.297  
 202.298 -    double mirek;  // temp (in microreciprocal kelvin)
 202.299 -    double ut;     // u coord of intersection w/ blackbody locus
 202.300 -    double vt;     // v coord of intersection w/ blackbody locus
 202.301 -    double tt;     // slope of ISOTEMPERATURE. line
 202.302 +    cmsFloat64Number mirek;  // temp (in microreciprocal kelvin)
 202.303 +    cmsFloat64Number ut;     // u coord of intersection w/ blackbody locus
 202.304 +    cmsFloat64Number vt;     // v coord of intersection w/ blackbody locus
 202.305 +    cmsFloat64Number tt;     // slope of ISOTEMPERATURE. line
 202.306  
 202.307 -    } ISOTEMPERATURE,FAR* LPISOTEMPERATURE;
 202.308 +    } ISOTEMPERATURE;
 202.309  
 202.310  static ISOTEMPERATURE isotempdata[] = {
 202.311  //  {Mirek, Ut,       Vt,      Tt      }
 202.312 @@ -360,27 +163,28 @@
 202.313      {525,   0.31320,  0.35968,  -15.628 },
 202.314      {550,   0.32129,  0.36011,  -23.325 },
 202.315      {575,   0.32931,  0.36038,  -40.770 },
 202.316 -    {600,   0.33724,  0.36051, -116.45  }
 202.317 +    {600,   0.33724,  0.36051,  -116.45  }
 202.318  };
 202.319  
 202.320  #define NISO sizeof(isotempdata)/sizeof(ISOTEMPERATURE)
 202.321  
 202.322  
 202.323  // Robertson's method
 202.324 -
 202.325 -static
 202.326 -double Robertson(LPcmsCIExyY v)
 202.327 +cmsBool  CMSEXPORT cmsTempFromWhitePoint(cmsFloat64Number* TempK, const cmsCIExyY* WhitePoint)
 202.328  {
 202.329      int j;
 202.330 -    double us,vs;
 202.331 -    double uj,vj,tj,di,dj,mi,mj;
 202.332 -    double Tc = -1, xs, ys;
 202.333 +    cmsFloat64Number us,vs;
 202.334 +    cmsFloat64Number uj,vj,tj,di,dj,mi,mj;
 202.335 +    cmsFloat64Number xs, ys;
 202.336 +
 202.337 +    _cmsAssert(WhitePoint != NULL);
 202.338 +    _cmsAssert(TempK != NULL);
 202.339  
 202.340      di = mi = 0;
 202.341 -    xs = v -> x;
 202.342 -    ys = v -> y;
 202.343 +    xs = WhitePoint -> x;
 202.344 +    ys = WhitePoint -> y;
 202.345  
 202.346 -    // convert (x,y) to CIE 1960 (u,v)
 202.347 +    // convert (x,y) to CIE 1960 (u,WhitePoint)
 202.348  
 202.349      us = (2*xs) / (-xs + 6*ys + 1.5);
 202.350      vs = (3*ys) / (-xs + 6*ys + 1.5);
 202.351 @@ -393,332 +197,182 @@
 202.352          tj = isotempdata[j].tt;
 202.353          mj = isotempdata[j].mirek;
 202.354  
 202.355 -        dj = ((vs - vj) - tj * (us - uj)) / sqrt(1 + tj*tj);
 202.356 +        dj = ((vs - vj) - tj * (us - uj)) / sqrt(1.0 + tj * tj);
 202.357  
 202.358 -        if ((j!=0) && (di/dj < 0.0)) {
 202.359 -            Tc = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi));
 202.360 -            break;
 202.361 +        if ((j != 0) && (di/dj < 0.0)) {
 202.362 +
 202.363 +            // Found a match
 202.364 +            *TempK = 1000000.0 / (mi + (di / (di - dj)) * (mj - mi));
 202.365 +            return TRUE;
 202.366          }
 202.367  
 202.368          di = dj;
 202.369          mi = mj;
 202.370      }
 202.371  
 202.372 -
 202.373 -    if (j == NISO) return -1;
 202.374 -    return Tc;
 202.375 +    // Not found
 202.376 +    return FALSE;
 202.377  }
 202.378  
 202.379  
 202.380 +// Compute chromatic adaptation matrix using Chad as cone matrix
 202.381  
 202.382  static
 202.383 -LCMSBOOL InRange(LPcmsCIExyY a, LPcmsCIExyY b, double tolerance)
 202.384 +cmsBool ComputeChromaticAdaptation(cmsMAT3* Conversion,
 202.385 +                                const cmsCIEXYZ* SourceWhitePoint,
 202.386 +                                const cmsCIEXYZ* DestWhitePoint,
 202.387 +                                const cmsMAT3* Chad)
 202.388 +
 202.389  {
 202.390 -       double dist_x, dist_y;
 202.391  
 202.392 -       dist_x = fabs(a->x - b->x);
 202.393 -       dist_y = fabs(a->y - b->y);
 202.394 +    cmsMAT3 Chad_Inv;
 202.395 +    cmsVEC3 ConeSourceXYZ, ConeSourceRGB;
 202.396 +    cmsVEC3 ConeDestXYZ, ConeDestRGB;
 202.397 +    cmsMAT3 Cone, Tmp;
 202.398  
 202.399 -       return (tolerance >= dist_x * dist_x + dist_y * dist_y);
 202.400 +
 202.401 +    Tmp = *Chad;
 202.402 +    if (!_cmsMAT3inverse(&Tmp, &Chad_Inv)) return FALSE;
 202.403 +
 202.404 +    _cmsVEC3init(&ConeSourceXYZ, SourceWhitePoint -> X,
 202.405 +                             SourceWhitePoint -> Y,
 202.406 +                             SourceWhitePoint -> Z);
 202.407 +
 202.408 +    _cmsVEC3init(&ConeDestXYZ,   DestWhitePoint -> X,
 202.409 +                             DestWhitePoint -> Y,
 202.410 +                             DestWhitePoint -> Z);
 202.411 +
 202.412 +    _cmsMAT3eval(&ConeSourceRGB, Chad, &ConeSourceXYZ);
 202.413 +    _cmsMAT3eval(&ConeDestRGB,   Chad, &ConeDestXYZ);
 202.414 +
 202.415 +    // Build matrix
 202.416 +    _cmsVEC3init(&Cone.v[0], ConeDestRGB.n[0]/ConeSourceRGB.n[0],    0.0,  0.0);
 202.417 +    _cmsVEC3init(&Cone.v[1], 0.0,   ConeDestRGB.n[1]/ConeSourceRGB.n[1],   0.0);
 202.418 +    _cmsVEC3init(&Cone.v[2], 0.0,   0.0,   ConeDestRGB.n[2]/ConeSourceRGB.n[2]);
 202.419 +
 202.420 +
 202.421 +    // Normalize
 202.422 +    _cmsMAT3per(&Tmp, &Cone, Chad);
 202.423 +    _cmsMAT3per(Conversion, &Chad_Inv, &Tmp);
 202.424 +
 202.425 +    return TRUE;
 202.426 +}
 202.427 +
 202.428 +// Returns the final chrmatic adaptation from illuminant FromIll to Illuminant ToIll
 202.429 +// The cone matrix can be specified in ConeMatrix. If NULL, Bradford is assumed
 202.430 +cmsBool  _cmsAdaptationMatrix(cmsMAT3* r, const cmsMAT3* ConeMatrix, const cmsCIEXYZ* FromIll, const cmsCIEXYZ* ToIll)
 202.431 +{
 202.432 +    cmsMAT3 LamRigg   = {{ // Bradford matrix
 202.433 +            {{  0.8951,  0.2664, -0.1614 }},
 202.434 +            {{ -0.7502,  1.7135,  0.0367 }},
 202.435 +            {{  0.0389, -0.0685,  1.0296 }}
 202.436 +        }};
 202.437 +
 202.438 +    if (ConeMatrix == NULL)
 202.439 +        ConeMatrix = &LamRigg;
 202.440 +
 202.441 +    return ComputeChromaticAdaptation(r, FromIll, ToIll, ConeMatrix);
 202.442 +}
 202.443 +
 202.444 +// Same as anterior, but assuming D50 destination. White point is given in xyY
 202.445 +static
 202.446 +cmsBool _cmsAdaptMatrixToD50(cmsMAT3* r, const cmsCIExyY* SourceWhitePt)
 202.447 +{
 202.448 +    cmsCIEXYZ Dn;
 202.449 +    cmsMAT3 Bradford;
 202.450 +    cmsMAT3 Tmp;
 202.451 +
 202.452 +    cmsxyY2XYZ(&Dn, SourceWhitePt);
 202.453 +
 202.454 +    if (!_cmsAdaptationMatrix(&Bradford, NULL, &Dn, cmsD50_XYZ())) return FALSE;
 202.455 +
 202.456 +    Tmp = *r;
 202.457 +    _cmsMAT3per(r, &Bradford, &Tmp);
 202.458 +
 202.459 +    return TRUE;
 202.460 +}
 202.461 +
 202.462 +// Build a White point, primary chromas transfer matrix from RGB to CIE XYZ
 202.463 +// This is just an approximation, I am not handling all the non-linear
 202.464 +// aspects of the RGB to XYZ process, and assumming that the gamma correction
 202.465 +// has transitive property in the tranformation chain.
 202.466 +//
 202.467 +// the alghoritm:
 202.468 +//
 202.469 +//            - First I build the absolute conversion matrix using
 202.470 +//              primaries in XYZ. This matrix is next inverted
 202.471 +//            - Then I eval the source white point across this matrix
 202.472 +//              obtaining the coeficients of the transformation
 202.473 +//            - Then, I apply these coeficients to the original matrix
 202.474 +//
 202.475 +cmsBool _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePt, const cmsCIExyYTRIPLE* Primrs)
 202.476 +{
 202.477 +    cmsVEC3 WhitePoint, Coef;
 202.478 +    cmsMAT3 Result, Primaries;
 202.479 +    cmsFloat64Number xn, yn;
 202.480 +    cmsFloat64Number xr, yr;
 202.481 +    cmsFloat64Number xg, yg;
 202.482 +    cmsFloat64Number xb, yb;
 202.483 +
 202.484 +    xn = WhitePt -> x;
 202.485 +    yn = WhitePt -> y;
 202.486 +    xr = Primrs -> Red.x;
 202.487 +    yr = Primrs -> Red.y;
 202.488 +    xg = Primrs -> Green.x;
 202.489 +    yg = Primrs -> Green.y;
 202.490 +    xb = Primrs -> Blue.x;
 202.491 +    yb = Primrs -> Blue.y;
 202.492 +
 202.493 +    // Build Primaries matrix
 202.494 +    _cmsVEC3init(&Primaries.v[0], xr,        xg,         xb);
 202.495 +    _cmsVEC3init(&Primaries.v[1], yr,        yg,         yb);
 202.496 +    _cmsVEC3init(&Primaries.v[2], (1-xr-yr), (1-xg-yg),  (1-xb-yb));
 202.497 +
 202.498 +
 202.499 +    // Result = Primaries ^ (-1) inverse matrix
 202.500 +    if (!_cmsMAT3inverse(&Primaries, &Result))
 202.501 +        return FALSE;
 202.502 +
 202.503 +
 202.504 +    _cmsVEC3init(&WhitePoint, xn/yn, 1.0, (1.0-xn-yn)/yn);
 202.505 +
 202.506 +    // Across inverse primaries ...
 202.507 +    _cmsMAT3eval(&Coef, &Result, &WhitePoint);
 202.508 +
 202.509 +    // Give us the Coefs, then I build transformation matrix
 202.510 +    _cmsVEC3init(&r -> v[0], Coef.n[VX]*xr,          Coef.n[VY]*xg,          Coef.n[VZ]*xb);
 202.511 +    _cmsVEC3init(&r -> v[1], Coef.n[VX]*yr,          Coef.n[VY]*yg,          Coef.n[VZ]*yb);
 202.512 +    _cmsVEC3init(&r -> v[2], Coef.n[VX]*(1.0-xr-yr), Coef.n[VY]*(1.0-xg-yg), Coef.n[VZ]*(1.0-xb-yb));
 202.513 +
 202.514 +
 202.515 +    return _cmsAdaptMatrixToD50(r, WhitePt);
 202.516  
 202.517  }
 202.518  
 202.519  
 202.520 -typedef struct {
 202.521 -                char Name[30];
 202.522 -                cmsCIExyY Val;
 202.523 +// Adapts a color to a given illuminant. Original color is expected to have
 202.524 +// a SourceWhitePt white point.
 202.525 +cmsBool CMSEXPORT cmsAdaptToIlluminant(cmsCIEXYZ* Result,
 202.526 +                                       const cmsCIEXYZ* SourceWhitePt,
 202.527 +                                       const cmsCIEXYZ* Illuminant,
 202.528 +                                       const cmsCIEXYZ* Value)
 202.529 +{
 202.530 +    cmsMAT3 Bradford;
 202.531 +    cmsVEC3 In, Out;
 202.532  
 202.533 -              } WHITEPOINTS,FAR *LPWHITEPOINTS;
 202.534 +    _cmsAssert(Result != NULL);
 202.535 +    _cmsAssert(SourceWhitePt != NULL);
 202.536 +    _cmsAssert(Illuminant != NULL);
 202.537 +    _cmsAssert(Value != NULL);
 202.538  
 202.539 -static
 202.540 -int FromD40toD150(LPWHITEPOINTS pts)
 202.541 -{
 202.542 -       int i, n;
 202.543 +    if (!_cmsAdaptationMatrix(&Bradford, NULL, SourceWhitePt, Illuminant)) return FALSE;
 202.544  
 202.545 -       n = 0;
 202.546 -       for (i=40; i < 150; i ++)
 202.547 -       {
 202.548 -              sprintf(pts[n].Name, "D%d", i);
 202.549 -              cmsWhitePointFromTemp((int) (i*100.0), &pts[n].Val);
 202.550 -              n++;
 202.551 -       }
 202.552 +    _cmsVEC3init(&In, Value -> X, Value -> Y, Value -> Z);
 202.553 +    _cmsMAT3eval(&Out, &Bradford, &In);
 202.554  
 202.555 -   return n;
 202.556 +    Result -> X = Out.n[0];
 202.557 +    Result -> Y = Out.n[1];
 202.558 +    Result -> Z = Out.n[2];
 202.559 +
 202.560 +    return TRUE;
 202.561  }
 202.562 -
 202.563 -
 202.564 -// To be removed in future versions
 202.565 -void _cmsIdentifyWhitePoint(char *Buffer, LPcmsCIEXYZ WhitePt)
 202.566 -{
 202.567 -       int i, n;
 202.568 -       cmsCIExyY Val;
 202.569 -       double T;
 202.570 -       WHITEPOINTS SomeIlluminants[140] = {
 202.571 -
 202.572 -                                   {"CIE illuminant A", {0.4476, 0.4074, 1.0}},
 202.573 -                                   {"CIE illuminant C", {0.3101, 0.3162, 1.0}},
 202.574 -                                   {"D65 (daylight)",   {0.3127, 0.3291, 1.0}},
 202.575 -                                   };
 202.576 -
 202.577 -              n = FromD40toD150(&SomeIlluminants[3]) + 3;
 202.578 -
 202.579 -              cmsXYZ2xyY(&Val, WhitePt);
 202.580 -
 202.581 -              Val.Y = 1.;
 202.582 -              for (i=0; i < n; i++)
 202.583 -              {
 202.584 -
 202.585 -                            if (InRange(&Val, &SomeIlluminants[i].Val, 0.000005))
 202.586 -                            {
 202.587 -                                strcpy(Buffer, "WhitePoint : ");
 202.588 -                                strcat(Buffer, SomeIlluminants[i].Name);
 202.589 -                                return;
 202.590 -                            }
 202.591 -              }
 202.592 -
 202.593 -              T = Robertson(&Val);
 202.594 -
 202.595 -              if (T > 0)
 202.596 -                sprintf(Buffer, "White point near %dK", (int) T);
 202.597 -              else
 202.598 -              {
 202.599 -              sprintf(Buffer, "Unknown white point (X:%1.2g, Y:%1.2g, Z:%1.2g)",
 202.600 -                                          WhitePt -> X, WhitePt -> Y, WhitePt -> Z);
 202.601 -
 202.602 -              }
 202.603 -
 202.604 -}
 202.605 -
 202.606 -
 202.607 -// Use darker colorant to obtain black point
 202.608 -
 202.609 -static
 202.610 -int BlackPointAsDarkerColorant(cmsHPROFILE hInput,
 202.611 -                               int Intent,
 202.612 -                               LPcmsCIEXYZ BlackPoint,
 202.613 -                               DWORD dwFlags)
 202.614 -{
 202.615 -    WORD *Black, *White;
 202.616 -    cmsHTRANSFORM xform;
 202.617 -    icColorSpaceSignature Space;
 202.618 -    int nChannels;
 202.619 -    DWORD dwFormat;
 202.620 -    cmsHPROFILE hLab;
 202.621 -    cmsCIELab  Lab;
 202.622 -    cmsCIEXYZ  BlackXYZ, MediaWhite;
 202.623 -
 202.624 -    // If the profile does not support input direction, assume Black point 0
 202.625 -    if (!cmsIsIntentSupported(hInput, Intent, LCMS_USED_AS_INPUT)) {
 202.626 -
 202.627 -        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 202.628 -        return 0;
 202.629 -    }
 202.630 -
 202.631 -
 202.632 -    // Try to get black by using black colorant
 202.633 -    Space = cmsGetColorSpace(hInput);
 202.634 -
 202.635 -    if (!_cmsEndPointsBySpace(Space, &White, &Black, &nChannels)) {
 202.636 -
 202.637 -        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 202.638 -        return 0;
 202.639 -    }
 202.640 -
 202.641 -    dwFormat = CHANNELS_SH(nChannels)|BYTES_SH(2);
 202.642 -
 202.643 -    hLab = cmsCreateLabProfile(NULL);
 202.644 -
 202.645 -    xform = cmsCreateTransform(hInput, dwFormat,
 202.646 -                                hLab, TYPE_Lab_DBL, Intent, cmsFLAGS_NOTPRECALC);
 202.647 -
 202.648 -
 202.649 -    cmsDoTransform(xform, Black, &Lab, 1);
 202.650 -
 202.651 -    // Force it to be neutral, clip to max. L* of 50
 202.652 -
 202.653 -    Lab.a = Lab.b = 0;
 202.654 -    if (Lab.L > 50) Lab.L = 50;
 202.655 -
 202.656 -    cmsCloseProfile(hLab);
 202.657 -    cmsDeleteTransform(xform);
 202.658 -
 202.659 -    cmsLab2XYZ(NULL, &BlackXYZ, &Lab);
 202.660 -
 202.661 -    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC) {
 202.662 -
 202.663 -        *BlackPoint = BlackXYZ;
 202.664 -    }
 202.665 -    else {
 202.666 -
 202.667 -        if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED)) {
 202.668 -
 202.669 -            cmsTakeMediaWhitePoint(&MediaWhite, hInput);
 202.670 -            cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &BlackXYZ);
 202.671 -        }
 202.672 -        else
 202.673 -            *BlackPoint = BlackXYZ;
 202.674 -    }
 202.675 -
 202.676 -    return 1;
 202.677 -}
 202.678 -
 202.679 -
 202.680 -// Get a black point of output CMYK profile, discounting any ink-limiting embedded
 202.681 -// in the profile. For doing that, use perceptual intent in input direction:
 202.682 -// Lab (0, 0, 0) -> [Perceptual] Profile -> CMYK -> [Rel. colorimetric] Profile -> Lab
 202.683 -
 202.684 -static
 202.685 -int BlackPointUsingPerceptualBlack(LPcmsCIEXYZ BlackPoint,
 202.686 -                                   cmsHPROFILE hProfile,
 202.687 -                                   DWORD dwFlags)
 202.688 -{
 202.689 -    cmsHTRANSFORM hPercLab2CMYK, hRelColCMYK2Lab;
 202.690 -    cmsHPROFILE hLab;
 202.691 -    cmsCIELab LabIn, LabOut;
 202.692 -    WORD CMYK[MAXCHANNELS];
 202.693 -    cmsCIEXYZ  BlackXYZ, MediaWhite;
 202.694 -
 202.695 -
 202.696 -     if (!cmsIsIntentSupported(hProfile, INTENT_PERCEPTUAL, LCMS_USED_AS_INPUT)) {
 202.697 -
 202.698 -        BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
 202.699 -        return 0;
 202.700 -    }
 202.701 -
 202.702 -    hLab = cmsCreateLabProfile(NULL);
 202.703 -
 202.704 -    hPercLab2CMYK  = cmsCreateTransform(hLab, TYPE_Lab_DBL,
 202.705 -                                        hProfile, TYPE_CMYK_16,
 202.706 -                                        INTENT_PERCEPTUAL, cmsFLAGS_NOTPRECALC);
 202.707 -
 202.708 -    hRelColCMYK2Lab = cmsCreateTransform(hProfile, TYPE_CMYK_16,
 202.709 -                                         hLab, TYPE_Lab_DBL,
 202.710 -                                         INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOTPRECALC);
 202.711 -
 202.712 -    LabIn.L = LabIn.a = LabIn.b = 0;
 202.713 -
 202.714 -    cmsDoTransform(hPercLab2CMYK, &LabIn, CMYK, 1);
 202.715 -    cmsDoTransform(hRelColCMYK2Lab, CMYK, &LabOut, 1);
 202.716 -
 202.717 -    if (LabOut.L > 50) LabOut.L = 50;
 202.718 -    LabOut.a = LabOut.b = 0;
 202.719 -
 202.720 -    cmsDeleteTransform(hPercLab2CMYK);
 202.721 -    cmsDeleteTransform(hRelColCMYK2Lab);
 202.722 -    cmsCloseProfile(hLab);
 202.723 -
 202.724 -    cmsLab2XYZ(NULL, &BlackXYZ, &LabOut);
 202.725 -
 202.726 -    if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED)){
 202.727 -            cmsTakeMediaWhitePoint(&MediaWhite, hProfile);
 202.728 -            cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &BlackXYZ);
 202.729 -    }
 202.730 -    else
 202.731 -            *BlackPoint = BlackXYZ;
 202.732 -
 202.733 -    return 1;
 202.734 -
 202.735 -}
 202.736 -
 202.737 -
 202.738 -// Get Perceptual black of v4 profiles.
 202.739 -static
 202.740 -int GetV4PerceptualBlack(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, DWORD dwFlags)
 202.741 -{
 202.742 -        if (dwFlags & LCMS_BPFLAGS_D50_ADAPTED) {
 202.743 -
 202.744 -            BlackPoint->X = PERCEPTUAL_BLACK_X;
 202.745 -            BlackPoint->Y = PERCEPTUAL_BLACK_Y;
 202.746 -            BlackPoint->Z = PERCEPTUAL_BLACK_Z;
 202.747 -        }
 202.748 -        else {
 202.749 -
 202.750 -            cmsCIEXYZ D50BlackPoint, MediaWhite;
 202.751 -
 202.752 -            cmsTakeMediaWhitePoint(&MediaWhite, hProfile);
 202.753 -            D50BlackPoint.X = PERCEPTUAL_BLACK_X;
 202.754 -            D50BlackPoint.Y = PERCEPTUAL_BLACK_Y;
 202.755 -            D50BlackPoint.Z = PERCEPTUAL_BLACK_Z;
 202.756 -
 202.757 -            // Obtain the absolute XYZ. Adapt perceptual black back from D50 to whatever media white
 202.758 -            cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &D50BlackPoint);
 202.759 -        }
 202.760 -
 202.761 -
 202.762 -        return 1;
 202.763 -}
 202.764 -
 202.765 -
 202.766 -// This function shouldn't exist at all -- there is such quantity of broken
 202.767 -// profiles on black point tag, that we must somehow fix chromaticity to
 202.768 -// avoid huge tint when doing Black point compensation. This function does
 202.769 -// just that. There is a special flag for using black point tag, but turned
 202.770 -// off by default because it is bogus on most profiles. The detection algorithm
 202.771 -// involves to turn BP to neutral and to use only L component.
 202.772 -
 202.773 -int cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent, DWORD dwFlags)
 202.774 -{
 202.775 -
 202.776 -    // v4 + perceptual & saturation intents does have its own black point, and it is
 202.777 -    // well specified enough to use it.
 202.778 -
 202.779 -    if ((cmsGetProfileICCversion(hProfile) >= 0x4000000) &&
 202.780 -        (Intent == INTENT_PERCEPTUAL || Intent == INTENT_SATURATION)) {
 202.781 -
 202.782 -       // Matrix shaper share MRC & perceptual intents
 202.783 -       if (_cmsIsMatrixShaper(hProfile))
 202.784 -           return BlackPointAsDarkerColorant(hProfile, INTENT_RELATIVE_COLORIMETRIC, BlackPoint, cmsFLAGS_NOTPRECALC);
 202.785 -
 202.786 -       // CLUT based - Get perceptual black point (fixed value)
 202.787 -       return GetV4PerceptualBlack(BlackPoint, hProfile, dwFlags);
 202.788 -    }
 202.789 -
 202.790 -
 202.791 -#ifdef HONOR_BLACK_POINT_TAG
 202.792 -
 202.793 -    // v2, v4 rel/abs colorimetric
 202.794 -    if (cmsIsTag(hProfile, icSigMediaBlackPointTag) &&
 202.795 -                    Intent == INTENT_RELATIVE_COLORIMETRIC) {
 202.796 -
 202.797 -        cmsCIEXYZ BlackXYZ, UntrustedBlackPoint, TrustedBlackPoint, MediaWhite;
 202.798 -        cmsCIELab Lab;
 202.799 -
 202.800 -             // If black point is specified, then use it,
 202.801 -
 202.802 -             cmsTakeMediaBlackPoint(&BlackXYZ, hProfile);
 202.803 -             cmsTakeMediaWhitePoint(&MediaWhite, hProfile);
 202.804 -
 202.805 -             // Black point is absolute XYZ, so adapt to D50 to get PCS value
 202.806 -             cmsAdaptToIlluminant(&UntrustedBlackPoint, &MediaWhite, cmsD50_XYZ(), &BlackXYZ);
 202.807 -
 202.808 -             // Force a=b=0 to get rid of any chroma
 202.809 -
 202.810 -             cmsXYZ2Lab(NULL, &Lab, &UntrustedBlackPoint);
 202.811 -             Lab.a = Lab.b = 0;
 202.812 -             if (Lab.L > 50) Lab.L = 50; // Clip to L* <= 50
 202.813 -
 202.814 -             cmsLab2XYZ(NULL, &TrustedBlackPoint, &Lab);
 202.815 -
 202.816 -             // Return BP as D50 relative or absolute XYZ (depends on flags)
 202.817 -             if (!(dwFlags & LCMS_BPFLAGS_D50_ADAPTED))
 202.818 -                    cmsAdaptToIlluminant(BlackPoint, cmsD50_XYZ(), &MediaWhite, &TrustedBlackPoint);
 202.819 -             else
 202.820 -                    *BlackPoint = TrustedBlackPoint;
 202.821 -
 202.822 -             return 1;
 202.823 -    }
 202.824 -
 202.825 -#endif
 202.826 -
 202.827 -    // That is about v2 profiles.
 202.828 -
 202.829 -    // If output profile, discount ink-limiting and that's all
 202.830 -    if (Intent == INTENT_RELATIVE_COLORIMETRIC &&
 202.831 -            (cmsGetDeviceClass(hProfile) == icSigOutputClass) &&
 202.832 -            (cmsGetColorSpace(hProfile) == icSigCmykData))
 202.833 -                return BlackPointUsingPerceptualBlack(BlackPoint, hProfile, dwFlags);
 202.834 -
 202.835 -    // Nope, compute BP using current intent.
 202.836 -    return BlackPointAsDarkerColorant(hProfile, Intent, BlackPoint, dwFlags);
 202.837 -
 202.838 -}
   203.1 --- a/src/share/native/sun/java2d/cmm/lcms/cmsxform.c	Thu Sep 23 17:33:40 2010 -0700
   203.2 +++ b/src/share/native/sun/java2d/cmm/lcms/cmsxform.c	Fri Sep 24 16:41:32 2010 -0700
   203.3 @@ -27,9 +27,10 @@
   203.4  // However, the following notice accompanied the original version of this
   203.5  // file:
   203.6  //
   203.7 +//---------------------------------------------------------------------------------
   203.8  //
   203.9 -//  Little cms
  203.10 -//  Copyright (C) 1998-2007 Marti Maria
  203.11 +//  Little Color Management System
  203.12 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  203.13  //
  203.14  // Permission is hereby granted, free of charge, to any person obtaining
  203.15  // a copy of this software and associated documentation files (the "Software"),
  203.16 @@ -48,1863 +49,436 @@
  203.17  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  203.18  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  203.19  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  203.20 +//
  203.21 +//---------------------------------------------------------------------------------
  203.22 +//
  203.23  
  203.24 -
  203.25 -#include "lcms.h"
  203.26 -
  203.27 +#include "lcms2_internal.h"
  203.28  
  203.29  // Transformations stuff
  203.30  // -----------------------------------------------------------------------
  203.31  
  203.32 +// Alarm codes for 16-bit transformations, because the fixed range of containers there are
  203.33 +// no values left to mark out of gamut. volatile is C99 per 6.2.5
  203.34 +static volatile cmsUInt16Number Alarm[cmsMAXCHANNELS];
  203.35 +static volatile cmsFloat64Number GlobalAdaptationState = 0;
  203.36  
  203.37 -// Interface
  203.38 +// The adaptation state may be defaulted by this function. If you don't like it, use the extended transform routine
  203.39 +cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d)
  203.40 +{
  203.41 +    cmsFloat64Number OldVal = GlobalAdaptationState;
  203.42  
  203.43 -cmsHTRANSFORM LCMSEXPORT cmsCreateTransform(cmsHPROFILE Input,
  203.44 -                                       DWORD InputFormat,
  203.45 -                                       cmsHPROFILE Output,
  203.46 -                                       DWORD OutputFormat,
  203.47 -                                       int Intent,
  203.48 -                                       DWORD dwFlags);
  203.49 +    if (d >= 0)
  203.50 +        GlobalAdaptationState = d;
  203.51  
  203.52 -cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE Input,
  203.53 -                                               DWORD InputFormat,
  203.54 -                                               cmsHPROFILE Output,
  203.55 -                                               DWORD OutputFormat,
  203.56 -                                               cmsHPROFILE Proofing,
  203.57 -                                               int Intent,
  203.58 -                                               int ProofingIntent,
  203.59 -                                               DWORD dwFlags);
  203.60 -
  203.61 -
  203.62 -void         LCMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform);
  203.63 -
  203.64 -void         LCMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
  203.65 -                                  LPVOID InputBuffer,
  203.66 -                                  LPVOID OutputBuffer, unsigned int Size);
  203.67 -
  203.68 -void         LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b);
  203.69 -void         LCMSEXPORT cmsSetAlarmCodes(int r, int g, int b);
  203.70 -LCMSBOOL     LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
  203.71 -                                                int Intent, int UsedDirection);
  203.72 -
  203.73 -// -------------------------------------------------------------------------
  203.74 -
  203.75 -
  203.76 -// Alarm RGB codes
  203.77 -
  203.78 -static WORD AlarmR = 0x8fff, AlarmG = 0x8fff, AlarmB = 0x8fff;
  203.79 -
  203.80 -// Tag tables, soted by intents
  203.81 -
  203.82 -static icTagSignature Device2PCS[] = {icSigAToB0Tag,       // Perceptual
  203.83 -                                      icSigAToB1Tag,       // Relative colorimetric
  203.84 -                                      icSigAToB2Tag,       // Saturation
  203.85 -                                      icSigAToB1Tag };     // Absolute colorimetric
  203.86 -                                                           // (Relative/WhitePoint)
  203.87 -
  203.88 -static icTagSignature PCS2Device[] = {icSigBToA0Tag,       // Perceptual
  203.89 -                                      icSigBToA1Tag,       // Relative colorimetric
  203.90 -                                      icSigBToA2Tag,       // Saturation
  203.91 -                                      icSigBToA1Tag };     // Absolute colorimetric
  203.92 -                                                           // (Relative/WhitePoint)
  203.93 -
  203.94 -
  203.95 -static icTagSignature Preview[]    = {icSigPreview0Tag,
  203.96 -                                      icSigPreview1Tag,
  203.97 -                                      icSigPreview2Tag,
  203.98 -                                      icSigPreview1Tag };
  203.99 -
 203.100 -
 203.101 -
 203.102 -static volatile double GlobalAdaptationState = 0;
 203.103 -
 203.104 -// --------------------------------Stages--------------------------------------
 203.105 -
 203.106 -// Following routines does implement several kind of steps inside
 203.107 -// transform. On building the transform, code chooses adequate.
 203.108 -
 203.109 -
 203.110 -// From Shaper-Matrix to PCS
 203.111 -
 203.112 -static
 203.113 -void ShaperMatrixToPCS(struct _cmstransform_struct *p,
 203.114 -                     WORD In[3], WORD Out[3])
 203.115 -{
 203.116 -       cmsEvalMatShaper(p -> InMatShaper, In, Out);
 203.117 +    return OldVal;
 203.118  }
 203.119  
 203.120 -// From LUT to PCS
 203.121 +// Alarm codes are always global
 203.122 +void CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS])
 203.123 +{
 203.124 +    int i;
 203.125  
 203.126 -static
 203.127 -void LUTtoPCS(struct _cmstransform_struct *p,
 203.128 -                     WORD In[], WORD Out[3])
 203.129 -{
 203.130 -       cmsEvalLUT(p -> Device2PCS, In, Out);
 203.131 +    _cmsAssert(NewAlarm != NULL);
 203.132 +
 203.133 +    for (i=0; i < cmsMAXCHANNELS; i++)
 203.134 +        Alarm[i] = NewAlarm[i];
 203.135  }
 203.136  
 203.137 -// From indexed named color to PCS
 203.138 +// You can get the codes cas well
 203.139 +void CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number OldAlarm[cmsMAXCHANNELS])
 203.140 +{
 203.141 +    int i;
 203.142  
 203.143 -static
 203.144 -void NC2toPCS(struct _cmstransform_struct *p,
 203.145 -                     WORD In[], WORD Out[3])
 203.146 -{
 203.147 -    int index = In[0];
 203.148 +    _cmsAssert(OldAlarm != NULL);
 203.149  
 203.150 -    if (index >= p ->NamedColorList-> nColors)
 203.151 -        cmsSignalError(LCMS_ERRC_WARNING, "Color %d out of range", index);
 203.152 -    else
 203.153 -        CopyMemory(Out, p ->NamedColorList->List[index].PCS, 3 * sizeof(WORD));
 203.154 +    for (i=0; i < cmsMAXCHANNELS; i++)
 203.155 +        OldAlarm[i] = Alarm[i];
 203.156  }
 203.157  
 203.158 -// From PCS to Shaper-Matrix
 203.159 +// Get rid of transform resources
 203.160 +void CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform)
 203.161 +{
 203.162 +    _cmsTRANSFORM* p = (_cmsTRANSFORM*) hTransform;
 203.163  
 203.164 -static
 203.165 -void PCStoShaperMatrix(struct _cmstransform_struct *p,
 203.166 -                     WORD In[3], WORD Out[3])
 203.167 -{
 203.168 -       cmsEvalMatShaper(p -> OutMatShaper, In, Out);
 203.169 +    _cmsAssert(p != NULL);
 203.170 +
 203.171 +    if (p -> GamutCheck)
 203.172 +        cmsPipelineFree(p -> GamutCheck);
 203.173 +
 203.174 +    if (p -> Lut)
 203.175 +        cmsPipelineFree(p -> Lut);
 203.176 +
 203.177 +    if (p ->InputColorant)
 203.178 +        cmsFreeNamedColorList(p ->InputColorant);
 203.179 +
 203.180 +    if (p -> OutputColorant)
 203.181 +        cmsFreeNamedColorList(p ->OutputColorant);
 203.182 +
 203.183 +    if (p ->Sequence)
 203.184 +        cmsFreeProfileSequenceDescription(p ->Sequence);
 203.185 +
 203.186 +    LCMS_FREE_LOCK(&p->rwlock);
 203.187 +    _cmsFree(p ->ContextID, (void *) p);
 203.188  }
 203.189  
 203.190 -// From PCS to LUT
 203.191 +// Apply transform
 203.192 +void CMSEXPORT cmsDoTransform(cmsHTRANSFORM  Transform,
 203.193 +                              const void* InputBuffer,
 203.194 +                              void* OutputBuffer,
 203.195 +                              cmsUInt32Number Size)
 203.196  
 203.197 -static
 203.198 -void PCStoLUT(struct _cmstransform_struct *p,
 203.199 -                     WORD In[3], WORD Out[])
 203.200  {
 203.201 -       cmsEvalLUT(p -> PCS2Device, In, Out);
 203.202 +    _cmsTRANSFORM* p = (_cmsTRANSFORM*) Transform;
 203.203 +
 203.204 +    p -> xform(p, InputBuffer, OutputBuffer, Size);
 203.205  }
 203.206  
 203.207  
 203.208 +// Transform routines ----------------------------------------------------------------------------------------------------------
 203.209  
 203.210 +// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check.
 203.211 +// Note that because extended range, we can use a -1.0 value for out of gamut in this case.
 203.212 +static
 203.213 +void FloatXFORM(_cmsTRANSFORM* p,
 203.214 +                const void* in,
 203.215 +                void* out, cmsUInt32Number Size)
 203.216 +{
 203.217 +    cmsUInt8Number* accum;
 203.218 +    cmsUInt8Number* output;
 203.219 +    cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
 203.220 +    cmsFloat32Number OutOfGamut;
 203.221 +    cmsUInt32Number i, j;
 203.222  
 203.223 -// ----------------------- TRANSFORMATIONS --------------------------
 203.224 +    accum  = (cmsUInt8Number*)  in;
 203.225 +    output = (cmsUInt8Number*)  out;
 203.226  
 203.227 +    for (i=0; i < Size; i++) {
 203.228  
 203.229 -// Inlining some assignations
 203.230 +        accum = p -> FromInputFloat(p, fIn, accum, Size);
 203.231  
 203.232 -#define COPY_3CHANS(to, from) { to[0]=from[0]; to[1]=from[1]; to[2]=from[2]; }
 203.233 +        // Any gamut chack to do?
 203.234 +        if (p ->GamutCheck != NULL) {
 203.235  
 203.236 +            // Evaluate gamut marker.
 203.237 +            cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck);
 203.238  
 203.239 -// Null transformation, only hold channels
 203.240 +            // Is current color out of gamut?
 203.241 +            if (OutOfGamut > 0.0) {
 203.242  
 203.243 +                // Certainly, out of gamut
 203.244 +                for (j=0; j < cmsMAXCHANNELS; j++)
 203.245 +                    fOut[j] = -1.0;
 203.246 +
 203.247 +            }
 203.248 +            else {
 203.249 +                // No, proceed normally
 203.250 +                cmsPipelineEvalFloat(fIn, fOut, p -> Lut);
 203.251 +            }
 203.252 +        }
 203.253 +        else {
 203.254 +
 203.255 +            // No gamut check at all
 203.256 +            cmsPipelineEvalFloat(fIn, fOut, p -> Lut);
 203.257 +        }
 203.258 +
 203.259 +        // Back to asked representation
 203.260 +        output = p -> ToOutputFloat(p, fOut, output, Size);
 203.261 +    }
 203.262 +}
 203.263 +
 203.264 +// 16 bit precision -----------------------------------------------------------------------------------------------------------
 203.265 +
 203.266 +// Null transformation, only applies formatters. No caché
 203.267  static
 203.268 -void NullXFORM(_LPcmsTRANSFORM p,
 203.269 -                     LPVOID in,
 203.270 -                     LPVOID out, unsigned int Size)
 203.271 +void NullXFORM(_cmsTRANSFORM* p,
 203.272 +               const void* in,
 203.273 +               void* out, cmsUInt32Number Size)
 203.274  {
 203.275 -       register LPBYTE accum;
 203.276 -       register LPBYTE output;
 203.277 -       WORD wIn[MAXCHANNELS];
 203.278 -       register unsigned int i, n;
 203.279 +    cmsUInt8Number* accum;
 203.280 +    cmsUInt8Number* output;
 203.281 +    cmsUInt16Number wIn[cmsMAXCHANNELS];
 203.282 +    cmsUInt32Number i, n;
 203.283  
 203.284 +    accum  = (cmsUInt8Number*)  in;
 203.285 +    output = (cmsUInt8Number*)  out;
 203.286 +    n = Size;                    // Buffer len
 203.287  
 203.288 -       accum  = (LPBYTE) in;
 203.289 -       output = (LPBYTE) out;
 203.290 +    for (i=0; i < n; i++) {
 203.291 +
 203.292 +        accum  = p -> FromInput(p, wIn, accum, Size);
 203.293 +        output = p -> ToOutput(p, wIn, output, Size);
 203.294 +    }
 203.295 +}
 203.296 +
 203.297 +
 203.298 +// No gamut check, no cache, 16 bits
 203.299 +static
 203.300 +void PrecalculatedXFORM(_cmsTRANSFORM* p,
 203.301 +                        const void* in,
 203.302 +                        void* out, cmsUInt32Number Size)
 203.303 +{
 203.304 +    register cmsUInt8Number* accum;
 203.305 +    register cmsUInt8Number* output;
 203.306 +    cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 203.307 +    cmsUInt32Number i, n;
 203.308 +
 203.309 +    accum  = (cmsUInt8Number*)  in;
 203.310 +    output = (cmsUInt8Number*)  out;
 203.311 +    n = Size;
 203.312 +
 203.313 +    for (i=0; i < n; i++) {
 203.314 +
 203.315 +        accum = p -> FromInput(p, wIn, accum, Size);
 203.316 +        p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 203.317 +        output = p -> ToOutput(p, wOut, output, Size);
 203.318 +    }
 203.319 +}
 203.320 +
 203.321 +
 203.322 +// Auxiliar: Handle precalculated gamut check
 203.323 +static
 203.324 +void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
 203.325 +                                     const cmsUInt16Number wIn[],
 203.326 +                                     cmsUInt16Number wOut[])
 203.327 +{
 203.328 +    cmsUInt16Number wOutOfGamut;
 203.329 +
 203.330 +    p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data);
 203.331 +    if (wOutOfGamut >= 1) {
 203.332 +
 203.333 +        cmsUInt16Number i;
 203.334 +
 203.335 +        for (i=0; i < p ->Lut->OutputChannels; i++)
 203.336 +            wOut[i] = Alarm[i];
 203.337 +    }
 203.338 +    else
 203.339 +        p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 203.340 +}
 203.341 +
 203.342 +// Gamut check, No caché, 16 bits.
 203.343 +static
 203.344 +void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
 203.345 +                                  const void* in,
 203.346 +                                  void* out, cmsUInt32Number Size)
 203.347 +{
 203.348 +    cmsUInt8Number* accum;
 203.349 +    cmsUInt8Number* output;
 203.350 +    cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 203.351 +    cmsUInt32Number i, n;
 203.352 +
 203.353 +    accum  = (cmsUInt8Number*)  in;
 203.354 +    output = (cmsUInt8Number*)  out;
 203.355 +    n = Size;                    // Buffer len
 203.356 +
 203.357 +    for (i=0; i < n; i++) {
 203.358 +
 203.359 +        accum = p -> FromInput(p, wIn, accum, Size);
 203.360 +        TransformOnePixelWithGamutCheck(p, wIn, wOut);
 203.361 +        output = p -> ToOutput(p, wOut, output, Size);
 203.362 +    }
 203.363 +}
 203.364 +
 203.365 +
 203.366 +// No gamut check, Caché, 16 bits,
 203.367 +static
 203.368 +void CachedXFORM(_cmsTRANSFORM* p,
 203.369 +                 const void* in,
 203.370 +                 void* out, cmsUInt32Number Size)
 203.371 +{
 203.372 +    cmsUInt8Number* accum;
 203.373 +    cmsUInt8Number* output;
 203.374 +    cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 203.375 +    cmsUInt32Number i, n;
 203.376 +    cmsUInt16Number CacheIn[cmsMAXCHANNELS], CacheOut[cmsMAXCHANNELS];
 203.377 +
 203.378 +    accum  = (cmsUInt8Number*)  in;
 203.379 +    output = (cmsUInt8Number*)  out;
 203.380 +    n = Size;                    // Buffer len
 203.381 +
 203.382 +    // Empty buffers for quick memcmp
 203.383 +    memset(wIn,  0, sizeof(wIn));
 203.384 +    memset(wOut, 0, sizeof(wOut));
 203.385 +
 203.386 +
 203.387 +    LCMS_READ_LOCK(&p ->rwlock);
 203.388 +    memmove(CacheIn,  p ->CacheIn, sizeof(CacheIn));
 203.389 +    memmove(CacheOut, p ->CacheOut, sizeof(CacheOut));
 203.390 +    LCMS_UNLOCK(&p ->rwlock);
 203.391 +
 203.392 +    for (i=0; i < n; i++) {
 203.393 +
 203.394 +        accum = p -> FromInput(p, wIn, accum, Size);
 203.395 +
 203.396 +        if (memcmp(wIn, CacheIn, sizeof(CacheIn)) == 0) {
 203.397 +
 203.398 +            memmove(wOut, CacheOut, sizeof(CacheOut));
 203.399 +        }
 203.400 +        else {
 203.401 +
 203.402 +            p ->Lut ->Eval16Fn(wIn, wOut, p -> Lut->Data);
 203.403 +
 203.404 +            memmove(CacheIn,  wIn,  sizeof(CacheIn));
 203.405 +            memmove(CacheOut, wOut, sizeof(CacheOut));
 203.406 +        }
 203.407 +
 203.408 +        output = p -> ToOutput(p, wOut, output, Size);
 203.409 +    }
 203.410 +
 203.411 +
 203.412 +    LCMS_WRITE_LOCK(&p ->rwlock);
 203.413 +    memmove(p->CacheIn,  CacheIn, sizeof(CacheIn));
 203.414 +    memmove(p->CacheOut, CacheOut, sizeof(CacheOut));
 203.415 +    LCMS_UNLOCK(&p ->rwlock);
 203.416 +}
 203.417 +
 203.418 +
 203.419 +// All those nice features together
 203.420 +static
 203.421 +void CachedXFORMGamutCheck(_cmsTRANSFORM* p,
 203.422 +                           const void* in,
 203.423 +                           void* out, cmsUInt32Number Size)
 203.424 +{
 203.425 +       cmsUInt8Number* accum;
 203.426 +       cmsUInt8Number* output;
 203.427 +       cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
 203.428 +       cmsUInt32Number i, n;
 203.429 +       cmsUInt16Number CacheIn[cmsMAXCHANNELS], CacheOut[cmsMAXCHANNELS];
 203.430 +
 203.431 +       accum  = (cmsUInt8Number*)  in;
 203.432 +       output = (cmsUInt8Number*)  out;
 203.433         n = Size;                    // Buffer len
 203.434  
 203.435 -       for (i=0; i < n; i++)
 203.436 -       {
 203.437 -       accum = p -> FromInput(p, wIn, accum);
 203.438 -       output = p -> ToOutput(p, wIn, output);
 203.439 -       }
 203.440 +       // Empty buffers for quick memcmp
 203.441 +       memset(wIn,  0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.442 +       memset(wOut, 0, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.443  
 203.444 -}
 203.445 -
 203.446 -
 203.447 -// This is the "normal" proofing transform
 203.448 -
 203.449 -static
 203.450 -void NormalXFORM(_LPcmsTRANSFORM p,
 203.451 -                     LPVOID in,
 203.452 -                     LPVOID out, unsigned int Size)
 203.453 -{
 203.454 -       register LPBYTE accum;
 203.455 -       register LPBYTE output;
 203.456 -       WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
 203.457 -       WORD wStageABC[3], wPCS[3], wStageLMN[MAXCHANNELS];
 203.458 -       WORD wGamut[1];
 203.459 -       register unsigned int i, n;
 203.460 -
 203.461 -
 203.462 -
 203.463 -       accum  = (LPBYTE) in;
 203.464 -       output = (LPBYTE) out;
 203.465 -       n = Size;                    // Buffer len
 203.466 -
 203.467 -       for (i=0; i < n; i++)
 203.468 -       {
 203.469 -
 203.470 -       accum = p -> FromInput(p, wIn, accum);
 203.471 -
 203.472 -       p -> FromDevice(p, wIn, wStageABC);
 203.473 -
 203.474 -       if (p -> Stage1) {
 203.475 -
 203.476 -              p -> Stage1(wStageABC, wPCS, &p->m1, &p->of1);
 203.477 -
 203.478 -              if (wPCS[0] == 0xFFFF &&
 203.479 -                  wPCS[1] == 0xFFFF &&
 203.480 -                  wPCS[2] == 0xFFFF) {
 203.481 -
 203.482 -                     // White cutoff
 203.483 -
 203.484 -                     output = p -> ToOutput((_LPcmsTRANSFORM) p,
 203.485 -                                   _cmsWhiteBySpace(cmsGetColorSpace(p -> OutputProfile)),
 203.486 -                                   output);
 203.487 -                     continue;
 203.488 -                     }
 203.489 -              }
 203.490 -       else
 203.491 -              COPY_3CHANS(wPCS, wStageABC);
 203.492 -
 203.493 -
 203.494 -       if (p->Gamut) {
 203.495 -
 203.496 -       // Gamut check, enabled across CLUT
 203.497 -
 203.498 -       cmsEvalLUT(p -> Gamut, wPCS, wGamut);
 203.499 -
 203.500 -       if (wGamut[0] >= 1) {
 203.501 -
 203.502 -              wOut[0] = AlarmR;          // Gamut alarm
 203.503 -              wOut[1] = AlarmG;
 203.504 -              wOut[2] = AlarmB;
 203.505 -              wOut[3] = 0;
 203.506 -
 203.507 -              output = p -> ToOutput((_LPcmsTRANSFORM)p, wOut, output);
 203.508 -              continue;
 203.509 -              }
 203.510 -       }
 203.511 -
 203.512 -       if (p -> Preview)
 203.513 -       {
 203.514 -              WORD wPreview[3];    // PCS
 203.515 -
 203.516 -              cmsEvalLUT(p -> Preview, wPCS, wPreview);
 203.517 -              COPY_3CHANS(wPCS, wPreview);
 203.518 -       }
 203.519 -
 203.520 -       if (p -> Stage2) {
 203.521 -
 203.522 -              p -> Stage2(wPCS, wStageLMN, &p->m2, &p->of2);
 203.523 -
 203.524 -              if (wPCS[0] == 0xFFFF &&
 203.525 -                  wPCS[1] == 0xFFFF &&
 203.526 -                  wPCS[2] == 0xFFFF) {
 203.527 -
 203.528 -                     // White cutoff
 203.529 -
 203.530 -                     output = p -> ToOutput((_LPcmsTRANSFORM)p,
 203.531 -                                   _cmsWhiteBySpace(cmsGetColorSpace(p -> OutputProfile)),
 203.532 -                                   output);
 203.533 -
 203.534 -                     continue;
 203.535 -                     }
 203.536 -
 203.537 -              }
 203.538 -       else
 203.539 -              COPY_3CHANS(wStageLMN, wPCS);
 203.540 -
 203.541 -       // Here wOut may come as MAXCHANNELS channels
 203.542 -
 203.543 -       p -> ToDevice(p, wStageLMN, wOut);
 203.544 -
 203.545 -       output = p -> ToOutput((_LPcmsTRANSFORM)p, wOut, output);
 203.546 -       }
 203.547 -}
 203.548 -
 203.549 -// Using precalculated LUT
 203.550 -
 203.551 -static
 203.552 -void PrecalculatedXFORM(_LPcmsTRANSFORM p,
 203.553 -                     LPVOID in,
 203.554 -                     LPVOID out, unsigned int Size)
 203.555 -{
 203.556 -       register LPBYTE accum;
 203.557 -       register LPBYTE output;
 203.558 -       WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
 203.559 -       unsigned int i, n;
 203.560 -
 203.561 -
 203.562 -       accum  = (LPBYTE) in;
 203.563 -       output = (LPBYTE) out;
 203.564 -       n = Size;                    // Buffer len
 203.565 +       LCMS_READ_LOCK(&p ->rwlock);
 203.566 +           memmove(CacheIn,  p ->CacheIn, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.567 +           memmove(CacheOut, p ->CacheOut, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.568 +       LCMS_UNLOCK(&p ->rwlock);
 203.569  
 203.570  
 203.571         for (i=0; i < n; i++) {
 203.572  
 203.573 -         accum = p -> FromInput(p, wIn, accum);
 203.574 +            accum = p -> FromInput(p, wIn, accum, Size);
 203.575  
 203.576 -         // Try to speedup things on plain devicelinks
 203.577 +            if (memcmp(wIn, CacheIn, sizeof(cmsUInt16Number) * cmsMAXCHANNELS) == 0) {
 203.578 +                    memmove(wOut, CacheOut, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.579 +            }
 203.580 +            else {
 203.581 +                    TransformOnePixelWithGamutCheck(p, wIn, wOut);
 203.582 +                    memmove(CacheIn, wIn, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.583 +                    memmove(CacheOut, wOut, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.584 +            }
 203.585  
 203.586 -         if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) {
 203.587 -
 203.588 -           p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut,
 203.589 -                                    p ->DeviceLink -> T,
 203.590 -                                    &p ->DeviceLink -> CLut16params);
 203.591 -         }
 203.592 -         else
 203.593 -            cmsEvalLUT(p -> DeviceLink, wIn, wOut);
 203.594 -
 203.595 -
 203.596 -          output = p -> ToOutput(p, wOut, output);
 203.597 -       }
 203.598 -}
 203.599 -
 203.600 -// Auxiliar: Handle precalculated gamut check
 203.601 -
 203.602 -static
 203.603 -void TransformOnePixelWithGamutCheck(_LPcmsTRANSFORM p, WORD wIn[], WORD wOut[])
 203.604 -{
 203.605 -    WORD wOutOfGamut;
 203.606 -
 203.607 -       cmsEvalLUT(p ->GamutCheck,  wIn, &wOutOfGamut);
 203.608 -
 203.609 -       if (wOutOfGamut >= 1) {
 203.610 -
 203.611 -              ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
 203.612 -
 203.613 -              wOut[0] = AlarmR;
 203.614 -              wOut[1] = AlarmG;
 203.615 -              wOut[2] = AlarmB;
 203.616 -
 203.617 -       }
 203.618 -       else
 203.619 -            cmsEvalLUT(p -> DeviceLink, wIn, wOut);
 203.620 -
 203.621 -}
 203.622 -
 203.623 -
 203.624 -static
 203.625 -void PrecalculatedXFORMGamutCheck(_LPcmsTRANSFORM p,
 203.626 -                                  LPVOID in,
 203.627 -                                  LPVOID out, unsigned int Size)
 203.628 -{
 203.629 -       register LPBYTE accum;
 203.630 -       register LPBYTE output;
 203.631 -       WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
 203.632 -       register unsigned int i, n;
 203.633 -
 203.634 -
 203.635 -       accum  = (LPBYTE) in;
 203.636 -       output = (LPBYTE) out;
 203.637 -       n = Size;                    // Buffer len
 203.638 -
 203.639 -       for (i=0; i < n; i++) {
 203.640 -
 203.641 -       accum = p -> FromInput(p, wIn, accum);
 203.642 -
 203.643 -       TransformOnePixelWithGamutCheck(p, wIn, wOut);
 203.644 -
 203.645 -       output = p -> ToOutput(p, wOut, output);
 203.646 -       }
 203.647 -}
 203.648 -
 203.649 -
 203.650 -
 203.651 -// Using precalculated LUT + Cache
 203.652 -
 203.653 -static
 203.654 -void CachedXFORM(_LPcmsTRANSFORM p,
 203.655 -                     LPVOID in,
 203.656 -                     LPVOID out, unsigned int Size)
 203.657 -{
 203.658 -       register LPBYTE accum;
 203.659 -       register LPBYTE output;
 203.660 -       WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
 203.661 -       register unsigned int i, n;
 203.662 -       WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
 203.663 -
 203.664 -
 203.665 -       accum  = (LPBYTE) in;
 203.666 -       output = (LPBYTE) out;
 203.667 -       n = Size;                    // Buffer len
 203.668 -
 203.669 -       // Empty buffers for quick memcmp
 203.670 -
 203.671 -       ZeroMemory(wIn,  sizeof(WORD) * MAXCHANNELS);
 203.672 -       ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
 203.673 -
 203.674 -
 203.675 -       LCMS_READ_LOCK(&p ->rwlock);
 203.676 -           CopyMemory(CacheIn,  p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
 203.677 -           CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
 203.678 -       LCMS_UNLOCK(&p ->rwlock);
 203.679 -
 203.680 -       for (i=0; i < n; i++) {
 203.681 -
 203.682 -       accum = p -> FromInput(p, wIn, accum);
 203.683 -
 203.684 -
 203.685 -       if (memcmp(wIn, CacheIn, sizeof(WORD) * MAXCHANNELS) == 0) {
 203.686 -
 203.687 -            CopyMemory(wOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
 203.688 -       }
 203.689 -       else {
 203.690 -
 203.691 -            // Try to speedup things on plain devicelinks
 203.692 -
 203.693 -             if (p ->DeviceLink ->wFlags == LUT_HAS3DGRID) {
 203.694 -
 203.695 -             p ->DeviceLink ->CLut16params.Interp3D(wIn, wOut,
 203.696 -                                    p ->DeviceLink -> T,
 203.697 -                                    &p ->DeviceLink -> CLut16params);
 203.698 -             }
 203.699 -             else
 203.700 -                  cmsEvalLUT(p -> DeviceLink, wIn, wOut);
 203.701 -
 203.702 -
 203.703 -            CopyMemory(CacheIn,  wIn,  sizeof(WORD) * MAXCHANNELS);
 203.704 -            CopyMemory(CacheOut, wOut, sizeof(WORD) * MAXCHANNELS);
 203.705 -       }
 203.706 -
 203.707 -       output = p -> ToOutput(p, wOut, output);
 203.708 -       }
 203.709 -
 203.710 -
 203.711 -       LCMS_WRITE_LOCK(&p ->rwlock);
 203.712 -           CopyMemory(p->CacheIn,  CacheIn, sizeof(WORD) * MAXCHANNELS);
 203.713 -           CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
 203.714 -       LCMS_UNLOCK(&p ->rwlock);
 203.715 -
 203.716 -}
 203.717 -
 203.718 -
 203.719 -
 203.720 -// Using precalculated LUT + Cache
 203.721 -
 203.722 -static
 203.723 -void CachedXFORMGamutCheck(_LPcmsTRANSFORM p,
 203.724 -                           LPVOID in,
 203.725 -                           LPVOID out, unsigned int Size)
 203.726 -{
 203.727 -       register LPBYTE accum;
 203.728 -       register LPBYTE output;
 203.729 -       WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
 203.730 -       register unsigned int i, n;
 203.731 -       WORD CacheIn[MAXCHANNELS], CacheOut[MAXCHANNELS];
 203.732 -
 203.733 -
 203.734 -       accum  = (LPBYTE) in;
 203.735 -       output = (LPBYTE) out;
 203.736 -       n = Size;                    // Buffer len
 203.737 -
 203.738 -       // Empty buffers for quick memcmp
 203.739 -
 203.740 -       ZeroMemory(wIn,  sizeof(WORD) * MAXCHANNELS);
 203.741 -       ZeroMemory(wOut, sizeof(WORD) * MAXCHANNELS);
 203.742 -
 203.743 -       LCMS_READ_LOCK(&p ->rwlock);
 203.744 -           CopyMemory(CacheIn,  p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
 203.745 -           CopyMemory(CacheOut, p ->CacheOut, sizeof(WORD) * MAXCHANNELS);
 203.746 -       LCMS_UNLOCK(&p ->rwlock);
 203.747 -
 203.748 -
 203.749 -       for (i=0; i < n; i++) {
 203.750 -
 203.751 -       accum = p -> FromInput(p, wIn, accum);
 203.752 -
 203.753 -       if (memcmp(wIn, CacheIn, sizeof(WORD) * MAXCHANNELS) == 0) {
 203.754 -
 203.755 -            CopyMemory(wOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
 203.756 -       }
 203.757 -       else {
 203.758 -
 203.759 -            TransformOnePixelWithGamutCheck(p, wIn, wOut);
 203.760 -
 203.761 -            CopyMemory(CacheIn, wIn, sizeof(WORD) * MAXCHANNELS);
 203.762 -            CopyMemory(CacheOut, wOut, sizeof(WORD) * MAXCHANNELS);
 203.763 -       }
 203.764 -
 203.765 -       output = p -> ToOutput(p, wOut, output);
 203.766 +            output = p -> ToOutput(p, wOut, output, Size);
 203.767         }
 203.768  
 203.769          LCMS_WRITE_LOCK(&p ->rwlock);
 203.770 -           CopyMemory(p->CacheIn,  CacheIn, sizeof(WORD) * MAXCHANNELS);
 203.771 -           CopyMemory(p->CacheOut, CacheOut, sizeof(WORD) * MAXCHANNELS);
 203.772 +           memmove(p->CacheIn,  CacheIn, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.773 +           memmove(p->CacheOut, CacheOut, sizeof(cmsUInt16Number) * cmsMAXCHANNELS);
 203.774          LCMS_UNLOCK(&p ->rwlock);
 203.775  }
 203.776  
 203.777  
 203.778 -// Using smelted Matrix/Shaper
 203.779  
 203.780 +
 203.781 +// Allocate transform struct and set it to defaults
 203.782  static
 203.783 -void MatrixShaperXFORM(_LPcmsTRANSFORM p,
 203.784 -                     LPVOID in,
 203.785 -                     LPVOID out, unsigned int Size)
 203.786 +_cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsUInt32Number InputFormat, cmsUInt32Number OutputFormat, cmsUInt32Number dwFlags)
 203.787  {
 203.788 -       register LPBYTE accum;
 203.789 -       register LPBYTE output;
 203.790 -       WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
 203.791 -       register unsigned int i, n;
 203.792 +    // Allocate needed memory
 203.793 +    _cmsTRANSFORM* p = (_cmsTRANSFORM*) _cmsMallocZero(ContextID, sizeof(_cmsTRANSFORM));
 203.794 +    if (!p) return NULL;
 203.795  
 203.796 +    // Check whatever this is a true floating point transform
 203.797 +    if (_cmsFormatterIsFloat(InputFormat) && _cmsFormatterIsFloat(OutputFormat)) {
 203.798  
 203.799 -       accum  = (LPBYTE) in;
 203.800 -       output = (LPBYTE) out;
 203.801 -       n = Size;                    // Buffer len
 203.802 +        // Get formatter function always return a valid union, but the contents of this union may be NULL.
 203.803 +        p ->FromInputFloat = _cmsGetFormatter(InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 203.804 +        p ->ToOutputFloat  = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_FLOAT).FmtFloat;
 203.805  
 203.806 -       for (i=0; i < n; i++)
 203.807 -       {
 203.808 -       accum = p -> FromInput(p, wIn, accum);
 203.809 -       cmsEvalMatShaper(p -> SmeltMatShaper, wIn, wOut);
 203.810 -       output = p -> ToOutput(p, wOut, output);
 203.811 -       }
 203.812 -}
 203.813 +        if (p ->FromInputFloat == NULL || p ->ToOutputFloat == NULL) {
 203.814  
 203.815 -
 203.816 -// Using Named color input table
 203.817 -
 203.818 -static
 203.819 -void NC2deviceXform(_LPcmsTRANSFORM p,
 203.820 -                     LPVOID in,
 203.821 -                     LPVOID out, unsigned int Size)
 203.822 -{
 203.823 -
 203.824 -       register LPBYTE accum;
 203.825 -       register LPBYTE output;
 203.826 -       WORD wIn[MAXCHANNELS], wOut[MAXCHANNELS];
 203.827 -       register unsigned int i;
 203.828 -
 203.829 -
 203.830 -       accum  = (LPBYTE) in;
 203.831 -       output = (LPBYTE) out;
 203.832 -
 203.833 -       for (i=0; i < Size; i++) {
 203.834 -
 203.835 -       accum = p -> FromInput(p, wIn, accum);
 203.836 -       CopyMemory(wOut, p ->NamedColorList->List[wIn[0]].DeviceColorant, sizeof(WORD) * MAXCHANNELS);
 203.837 -       output = p -> ToOutput(p, wOut, output);
 203.838 -       }
 203.839 -
 203.840 -}
 203.841 -
 203.842 -
 203.843 -
 203.844 -// --------------------------------------------------------------------------
 203.845 -// Build a LUT based on shape-matrix method.
 203.846 -
 203.847 -
 203.848 -// Some non-conformant gray profiles are using kTCR as L*,
 203.849 -// this function converts the curve to XYZ PCS.
 203.850 -
 203.851 -static
 203.852 -void FromLstarToXYZ(LPGAMMATABLE g, LPGAMMATABLE gxyz[3])
 203.853 -{
 203.854 -    int i;
 203.855 -    int nPoints = 4096;
 203.856 -    cmsCIELab Lab;
 203.857 -    cmsCIEXYZ XYZ;
 203.858 -    L16PARAMS L16;
 203.859 -
 203.860 -    // Setup interpolation across origin
 203.861 -    cmsCalcL16Params(g ->nEntries, &L16);
 203.862 -
 203.863 -    // Allocate curves
 203.864 -    gxyz[0] = cmsAllocGamma(nPoints);
 203.865 -    gxyz[1] = cmsAllocGamma(nPoints);
 203.866 -    gxyz[2] = cmsAllocGamma(nPoints);
 203.867 -
 203.868 -    // Transport from Lab to XYZ
 203.869 -
 203.870 -    for (i=0; i < nPoints; i++) {
 203.871 -
 203.872 -        WORD val = _cmsQuantizeVal(i, nPoints);
 203.873 -        WORD w   = cmsLinearInterpLUT16(val, g->GammaTable, &L16);
 203.874 -
 203.875 -        Lab.L = ((double) 100.0 * w ) / 65535.0;
 203.876 -        Lab.a = Lab.b = 0;
 203.877 -
 203.878 -        cmsLab2XYZ(NULL, &XYZ, &Lab);
 203.879 -
 203.880 -        // Should be same curve
 203.881 -        gxyz[0] ->GammaTable[i] = (WORD) floor((65535.0 * XYZ.X) / D50X + 0.5);
 203.882 -        gxyz[1] ->GammaTable[i] = (WORD) floor((65535.0 * XYZ.Y) / D50Y + 0.5);
 203.883 -        gxyz[2] ->GammaTable[i] = (WORD) floor((65535.0 * XYZ.Z) / D50Z + 0.5);
 203.884 -    }
 203.885 -}
 203.886 -
 203.887 -// Monochrome version
 203.888 -
 203.889 -static
 203.890 -LPMATSHAPER cmsBuildGrayInputMatrixShaper(cmsHPROFILE hProfile)
 203.891 -{
 203.892 -       cmsCIEXYZ Illuminant;
 203.893 -       LPGAMMATABLE GrayTRC, Shapes[3];
 203.894 -       LPMATSHAPER MatShaper;
 203.895 -       MAT3 Scale;
 203.896 -
 203.897 -       GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag);        // Y
 203.898 -       if (GrayTRC == NULL) return NULL;
 203.899 -
 203.900 -       cmsTakeIluminant(&Illuminant, hProfile);
 203.901 -
 203.902 -       if (cmsGetPCS(hProfile) == icSigLabData) {
 203.903 -
 203.904 -                // Fixup for Lab monochrome
 203.905 -                FromLstarToXYZ(GrayTRC, Shapes);
 203.906 -       }
 203.907 -       else  {
 203.908 -                Shapes[0] = cmsDupGamma(GrayTRC);
 203.909 -                Shapes[1] = cmsDupGamma(GrayTRC);
 203.910 -                Shapes[2] = cmsDupGamma(GrayTRC);
 203.911 -       }
 203.912 -
 203.913 -       if (!Shapes[0] || !Shapes[1] || !Shapes[2])
 203.914 -              return NULL;
 203.915 -
 203.916 -       cmsFreeGamma(GrayTRC);
 203.917 -
 203.918 -       // R=G=B as precondition
 203.919 -
 203.920 -       VEC3init(&Scale.v[0], Illuminant.X/3,  Illuminant.X/3,  Illuminant.X/3);
 203.921 -       VEC3init(&Scale.v[1], Illuminant.Y/3,  Illuminant.Y/3,  Illuminant.Y/3);
 203.922 -       VEC3init(&Scale.v[2], Illuminant.Z/3,  Illuminant.Z/3,  Illuminant.Z/3);
 203.923 -
 203.924 -
 203.925 -       MatShaper = cmsAllocMatShaper(&Scale, Shapes, MATSHAPER_INPUT);
 203.926 -       cmsFreeGammaTriple(Shapes);
 203.927 -       return MatShaper;
 203.928 -
 203.929 -}
 203.930 -
 203.931 -
 203.932 -// Monochrome as output
 203.933 -
 203.934 -static
 203.935 -LPMATSHAPER cmsBuildGrayOutputMatrixShaper(cmsHPROFILE hProfile)
 203.936 -{
 203.937 -       cmsCIEXYZ Illuminant;
 203.938 -       LPGAMMATABLE GrayTRC, Shapes[3];
 203.939 -       LPMATSHAPER MatShaper;
 203.940 -       MAT3 Scale;
 203.941 -
 203.942 -       cmsTakeIluminant(&Illuminant, hProfile);
 203.943 -
 203.944 -       // That is a special case for non-compliant profiles.
 203.945 -
 203.946 -       if (cmsGetPCS(hProfile) == icSigLabData) {
 203.947 -
 203.948 -                LPGAMMATABLE Shapes1[3];
 203.949 -
 203.950 -                GrayTRC = cmsReadICCGamma(hProfile, icSigGrayTRCTag);
 203.951 -                FromLstarToXYZ(GrayTRC, Shapes1);
 203.952 -
 203.953 -                // Reversing must be done after curve translation
 203.954 -
 203.955 -                Shapes[0] = cmsReverseGamma(Shapes1[0]->nEntries, Shapes1[0]);
 203.956 -                Shapes[1] = cmsReverseGamma(Shapes1[1]->nEntries, Shapes1[1]);
 203.957 -                Shapes[2] = cmsReverseGamma(Shapes1[2]->nEntries, Shapes1[2]);
 203.958 -
 203.959 -                cmsFreeGammaTriple(Shapes1);
 203.960 -
 203.961 -       }
 203.962 -       else  {
 203.963 -
 203.964 -                // Normal case
 203.965 -
 203.966 -                GrayTRC = cmsReadICCGammaReversed(hProfile, icSigGrayTRCTag);   // Y
 203.967 -
 203.968 -                Shapes[0] = cmsDupGamma(GrayTRC);
 203.969 -                Shapes[1] = cmsDupGamma(GrayTRC);
 203.970 -                Shapes[2] = cmsDupGamma(GrayTRC);
 203.971 -       }
 203.972 -
 203.973 -       if (!Shapes[0] || !Shapes[1] || !Shapes[2])
 203.974 -              return NULL;
 203.975 -
 203.976 -       cmsFreeGamma(GrayTRC);
 203.977 -
 203.978 -       VEC3init(&Scale.v[0], 0,  1.0/Illuminant.Y,  0);
 203.979 -       VEC3init(&Scale.v[1], 0,  1.0/Illuminant.Y,  0);
 203.980 -       VEC3init(&Scale.v[2], 0,  1.0/Illuminant.Y,  0);
 203.981 -
 203.982 -
 203.983 -       MatShaper = cmsAllocMatShaper(&Scale, Shapes, MATSHAPER_OUTPUT);
 203.984 -       cmsFreeGammaTriple(Shapes);
 203.985 -       return MatShaper;
 203.986 -
 203.987 -}
 203.988 -
 203.989 -
 203.990 -
 203.991 -// Input matrix, only in XYZ
 203.992 -
 203.993 -LPMATSHAPER cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile)
 203.994 -{
 203.995 -       MAT3 DoubleMat;
 203.996 -       LPGAMMATABLE Shapes[3];
 203.997 -       LPMATSHAPER InMatSh;
 203.998 -
 203.999 -       // Check if this is a grayscale profile. If so, build
203.1000 -       // appropiate conversion tables. The tables are the PCS
203.1001 -       // iluminant, scaled across GrayTRC
203.1002 -
203.1003 -       if (cmsGetColorSpace(InputProfile) == icSigGrayData)
203.1004 -       {
203.1005 -              return cmsBuildGrayInputMatrixShaper(InputProfile);
203.1006 -       }
203.1007 -
203.1008 -       if (!cmsReadICCMatrixRGB2XYZ(&DoubleMat, InputProfile))
203.1009 -                     return NULL;
203.1010 -
203.1011 -       Shapes[0] = cmsReadICCGamma(InputProfile, icSigRedTRCTag);
203.1012 -       Shapes[1] = cmsReadICCGamma(InputProfile, icSigGreenTRCTag);
203.1013 -       Shapes[2] = cmsReadICCGamma(InputProfile, icSigBlueTRCTag);
203.1014 -
203.1015 -       if (!Shapes[0] || !Shapes[1] || !Shapes[2])
203.1016 -                     return NULL;
203.1017 -
203.1018 -       InMatSh = cmsAllocMatShaper(&DoubleMat, Shapes, MATSHAPER_INPUT);
203.1019 -
203.1020 -       cmsFreeGammaTriple(Shapes);
203.1021 -
203.1022 -       return InMatSh;
203.1023 -}
203.1024 -
203.1025 -
203.1026 -// Output style matrix-shaper
203.1027 -
203.1028 -
203.1029 -LPMATSHAPER cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile)
203.1030 -{
203.1031 -       MAT3 DoubleMat, DoubleInv;
203.1032 -       LPGAMMATABLE InverseShapes[3];
203.1033 -       LPMATSHAPER OutMatSh;
203.1034 -
203.1035 -
203.1036 -
203.1037 -       if (cmsGetColorSpace(OutputProfile) == icSigGrayData)
203.1038 -       {
203.1039 -              return cmsBuildGrayOutputMatrixShaper(OutputProfile);
203.1040 -       }
203.1041 -
203.1042 -
203.1043 -       if (!cmsReadICCMatrixRGB2XYZ(&DoubleMat, OutputProfile))
203.1044 -                     return NULL;
203.1045 -
203.1046 -       if (MAT3inverse(&DoubleMat, &DoubleInv) < 0)
203.1047 -              return NULL;
203.1048 -
203.1049 -
203.1050 -       InverseShapes[0] = cmsReadICCGammaReversed(OutputProfile, icSigRedTRCTag);
203.1051 -       InverseShapes[1] = cmsReadICCGammaReversed(OutputProfile, icSigGreenTRCTag);
203.1052 -       InverseShapes[2] = cmsReadICCGammaReversed(OutputProfile, icSigBlueTRCTag);
203.1053 -
203.1054 -       if (InverseShapes[0] == NULL ||
203.1055 -           InverseShapes[1] == NULL ||
203.1056 -           InverseShapes[2] == NULL) return NULL;
203.1057 -
203.1058 -       OutMatSh = cmsAllocMatShaper(&DoubleInv, InverseShapes, MATSHAPER_OUTPUT);
203.1059 -
203.1060 -       cmsFreeGammaTriple(InverseShapes);
203.1061 -
203.1062 -       return OutMatSh;
203.1063 -}
203.1064 -
203.1065 -
203.1066 -
203.1067 -// This function builds a transform matrix chaining parameters
203.1068 -
203.1069 -static
203.1070 -LCMSBOOL cmsBuildSmeltMatShaper(_LPcmsTRANSFORM p)
203.1071 -{
203.1072 -       MAT3 From, To, ToInv, Transfer;
203.1073 -       LPGAMMATABLE In[3], InverseOut[3];
203.1074 -
203.1075 -
203.1076 -       if (!cmsReadICCMatrixRGB2XYZ(&From, p -> InputProfile))
203.1077 -                     return FALSE;
203.1078 -
203.1079 -
203.1080 -       if (!cmsReadICCMatrixRGB2XYZ(&To, p -> OutputProfile))
203.1081 -                     return FALSE;
203.1082 -
203.1083 -       // invert dest
203.1084 -
203.1085 -       if (MAT3inverse(&To, &ToInv) < 0)
203.1086 -                        return FALSE;
203.1087 -
203.1088 -       // Multiply
203.1089 -        MAT3per(&Transfer, &ToInv, &From);
203.1090 -
203.1091 -
203.1092 -        // Read gamma curves
203.1093 -
203.1094 -        In[0] = cmsReadICCGamma(p -> InputProfile, icSigRedTRCTag);
203.1095 -        In[1] = cmsReadICCGamma(p -> InputProfile, icSigGreenTRCTag);
203.1096 -        In[2] = cmsReadICCGamma(p -> InputProfile, icSigBlueTRCTag);
203.1097 -
203.1098 -        if (!In[0] || !In[1] || !In[2])
203.1099 -                     return FALSE;
203.1100 -
203.1101 -
203.1102 -        InverseOut[0] = cmsReadICCGammaReversed(p -> OutputProfile, icSigRedTRCTag);
203.1103 -        InverseOut[1] = cmsReadICCGammaReversed(p -> OutputProfile, icSigGreenTRCTag);
203.1104 -        InverseOut[2] = cmsReadICCGammaReversed(p -> OutputProfile, icSigBlueTRCTag);
203.1105 -
203.1106 -        if (!InverseOut[0] || !InverseOut[1] || !InverseOut[2]) {
203.1107 -                     cmsFreeGammaTriple(In);
203.1108 -                     return FALSE;
203.1109 +            cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
203.1110 +            _cmsFree(ContextID, p);
203.1111 +            return NULL;
203.1112          }
203.1113  
203.1114 -        p -> SmeltMatShaper = cmsAllocMatShaper2(&Transfer, In, InverseOut, MATSHAPER_ALLSMELTED);
203.1115 +        // Float transforms don't use caché, always are non-NULL
203.1116 +        p ->xform = FloatXFORM;
203.1117 +    }
203.1118 +    else {
203.1119  
203.1120 -        cmsFreeGammaTriple(In);
203.1121 -        cmsFreeGammaTriple(InverseOut);
203.1122 +        p ->FromInput = _cmsGetFormatter(InputFormat,  cmsFormatterInput, CMS_PACK_FLAGS_16BITS).Fmt16;
203.1123 +        p ->ToOutput  = _cmsGetFormatter(OutputFormat, cmsFormatterOutput, CMS_PACK_FLAGS_16BITS).Fmt16;
203.1124  
203.1125 -        return (p -> SmeltMatShaper != NULL);
203.1126 -}
203.1127 +        if (p ->FromInput == NULL || p ->ToOutput == NULL) {
203.1128  
203.1129 +            cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported raster format");
203.1130 +            _cmsFree(ContextID, p);
203.1131 +            return NULL;
203.1132 +        }
203.1133  
203.1134 +        if (dwFlags & cmsFLAGS_NULLTRANSFORM) {
203.1135  
203.1136 +            p ->xform = NullXFORM;
203.1137 +        }
203.1138 +        else {
203.1139 +            if (dwFlags & cmsFLAGS_NOCACHE) {
203.1140  
203.1141 -// Conversion between PCS ------------------------------------------
203.1142 +                if (dwFlags & cmsFLAGS_GAMUTCHECK)
203.1143 +                    p ->xform = PrecalculatedXFORMGamutCheck;  // Gamut check, no caché
203.1144 +                else
203.1145 +                    p ->xform = PrecalculatedXFORM;  // No caché, no gamut check
203.1146 +            }
203.1147 +            else {
203.1148  
203.1149 -// Identifies intent archieved by LUT
203.1150 -
203.1151 -static
203.1152 -int GetPhase(cmsHPROFILE hProfile)
203.1153 -{
203.1154 -       switch (cmsGetPCS(hProfile)) {
203.1155 -
203.1156 -       case icSigXYZData: return XYZRel;
203.1157 -
203.1158 -       case icSigLabData: return LabRel;
203.1159 -
203.1160 -       default:  cmsSignalError(LCMS_ERRC_ABORTED, "Invalid PCS");
203.1161 -       }
203.1162 -
203.1163 -       return XYZRel;
203.1164 -}
203.1165 -
203.1166 -
203.1167 -
203.1168 -
203.1169 -static
203.1170 -void TakeConversionRoutines(_LPcmsTRANSFORM p, int DoBPC)
203.1171 -{
203.1172 -       cmsCIEXYZ BlackPointIn, WhitePointIn, IlluminantIn;
203.1173 -       cmsCIEXYZ BlackPointOut, WhitePointOut, IlluminantOut;
203.1174 -       cmsCIEXYZ BlackPointProof, WhitePointProof, IlluminantProof;
203.1175 -       MAT3 ChromaticAdaptationMatrixIn, ChromaticAdaptationMatrixOut;
203.1176 -       MAT3 ChromaticAdaptationMatrixProof;
203.1177 -
203.1178 -
203.1179 -       cmsTakeIluminant(&IlluminantIn,        p -> InputProfile);
203.1180 -       cmsTakeMediaWhitePoint(&WhitePointIn,  p -> InputProfile);
203.1181 -       cmsTakeMediaBlackPoint(&BlackPointIn,  p -> InputProfile);
203.1182 -       cmsReadChromaticAdaptationMatrix(&ChromaticAdaptationMatrixIn, p -> InputProfile);
203.1183 -
203.1184 -       cmsTakeIluminant(&IlluminantOut,        p -> OutputProfile);
203.1185 -       cmsTakeMediaWhitePoint(&WhitePointOut,  p -> OutputProfile);
203.1186 -       cmsTakeMediaBlackPoint(&BlackPointOut,  p -> OutputProfile);
203.1187 -       cmsReadChromaticAdaptationMatrix(&ChromaticAdaptationMatrixOut, p -> OutputProfile);
203.1188 -
203.1189 -
203.1190 -       if (p -> Preview == NULL && p ->Gamut == NULL)     // Non-proofing
203.1191 -       {
203.1192 -            if (p ->Intent == INTENT_PERCEPTUAL ||
203.1193 -                p ->Intent == INTENT_SATURATION) {
203.1194 -
203.1195 -
203.1196 -                    // For v4 profiles, Perceptual PCS has a reference black point
203.1197 -                    // which v2 profiles should scale to.
203.1198 -
203.1199 -                    if ((cmsGetProfileICCversion(p ->InputProfile) >= 0x4000000) ||
203.1200 -                        (cmsGetProfileICCversion(p ->OutputProfile) >= 0x4000000)) {
203.1201 -
203.1202 -                           DoBPC = TRUE;
203.1203 -                    }
203.1204 -            }
203.1205 -
203.1206 -            // Black point compensation does not apply to absolute intent
203.1207 -
203.1208 -            if (p ->Intent == INTENT_ABSOLUTE_COLORIMETRIC)
203.1209 -                            DoBPC = FALSE;
203.1210 -
203.1211 -            // Black point compensation does not apply to devicelink profiles
203.1212 -
203.1213 -            if (cmsGetDeviceClass(p ->InputProfile) == icSigLinkClass)
203.1214 -                            DoBPC = FALSE;
203.1215 -
203.1216 -            if (cmsGetDeviceClass(p ->OutputProfile) == icSigLinkClass)
203.1217 -                            DoBPC = FALSE;
203.1218 -
203.1219 -            if (DoBPC) {
203.1220 -
203.1221 -                // Detect Black points
203.1222 -
203.1223 -                cmsDetectBlackPoint(&BlackPointIn,    p->InputProfile,   p->Intent, 0);
203.1224 -                cmsDetectBlackPoint(&BlackPointOut,   p->OutputProfile,  p->Intent, 0);
203.1225 -
203.1226 -                // If equal black points, then do nothing. This often applies to BP=0
203.1227 -
203.1228 -                if (BlackPointIn.X == BlackPointOut.X &&
203.1229 -                    BlackPointIn.Y == BlackPointOut.Y &&
203.1230 -                    BlackPointIn.Z == BlackPointOut.Z)
203.1231 -                                DoBPC = FALSE;
203.1232 -
203.1233 +                if (dwFlags & cmsFLAGS_GAMUTCHECK)
203.1234 +                    p ->xform = CachedXFORMGamutCheck;    // Gamut check, caché
203.1235 +                else
203.1236 +                    p ->xform = CachedXFORM;  // No gamut check, caché
203.1237  
203.1238              }
203.1239 -
203.1240 -            cmsChooseCnvrt(p -> Intent == INTENT_ABSOLUTE_COLORIMETRIC,
203.1241 -
203.1242 -                 p -> Phase1,
203.1243 -                             &BlackPointIn,
203.1244 -                             &WhitePointIn,
203.1245 -                             &IlluminantIn,
203.1246 -                             &ChromaticAdaptationMatrixIn,
203.1247 -
203.1248 -                 p -> Phase3,
203.1249 -                             &BlackPointOut,
203.1250 -                             &WhitePointOut,
203.1251 -                             &IlluminantOut,
203.1252 -                             &ChromaticAdaptationMatrixOut,
203.1253 -
203.1254 -                 DoBPC,
203.1255 -                 p ->AdaptationState,
203.1256 -                 &p->Stage1,
203.1257 -                 &p->m1, &p->of1);
203.1258 -
203.1259 -       }
203.1260 -       else // Proofing
203.1261 -       {
203.1262 -
203.1263 -
203.1264 -       cmsTakeIluminant(&IlluminantProof,        p -> PreviewProfile);
203.1265 -       cmsTakeMediaWhitePoint(&WhitePointProof,  p -> PreviewProfile);
203.1266 -       cmsTakeMediaBlackPoint(&BlackPointProof,  p -> PreviewProfile);
203.1267 -       cmsReadChromaticAdaptationMatrix(&ChromaticAdaptationMatrixProof, p -> PreviewProfile);
203.1268 -
203.1269 -       if (DoBPC) {
203.1270 -
203.1271 -            cmsDetectBlackPoint(&BlackPointProof, p->PreviewProfile, p->Intent, 0);
203.1272 -            cmsDetectBlackPoint(&BlackPointIn,    p->InputProfile,   p->Intent, 0);
203.1273 -            cmsDetectBlackPoint(&BlackPointOut,   p->OutputProfile,  p->Intent, 0);
203.1274 -
203.1275 -            // Reality check
203.1276 -
203.1277 -            if (BlackPointIn.X == BlackPointProof.X &&
203.1278 -                BlackPointIn.Y == BlackPointProof.Y &&
203.1279 -                BlackPointIn.Z == BlackPointProof.Z)
203.1280 -                                DoBPC = FALSE;
203.1281 -
203.1282 -
203.1283 -       }
203.1284 -
203.1285 -
203.1286 -
203.1287 -       cmsChooseCnvrt(p -> Intent == INTENT_ABSOLUTE_COLORIMETRIC,
203.1288 -
203.1289 -                 p -> Phase1,
203.1290 -                             &BlackPointIn,
203.1291 -                             &WhitePointIn,
203.1292 -                             &IlluminantIn,
203.1293 -                             &ChromaticAdaptationMatrixIn,
203.1294 -
203.1295 -                 p -> Phase2,
203.1296 -                             &BlackPointProof,
203.1297 -                             &WhitePointProof,
203.1298 -                             &IlluminantProof,
203.1299 -                             &ChromaticAdaptationMatrixProof,
203.1300 -                 DoBPC,
203.1301 -                 p ->AdaptationState,
203.1302 -                 &p->Stage1,
203.1303 -                 &p->m1, &p->of1);
203.1304 -
203.1305 -       cmsChooseCnvrt(p -> ProofIntent == INTENT_ABSOLUTE_COLORIMETRIC,
203.1306 -
203.1307 -                 p -> Phase2,
203.1308 -                             &BlackPointProof,
203.1309 -                             &WhitePointProof,
203.1310 -                             &IlluminantProof,
203.1311 -                             &ChromaticAdaptationMatrixProof,
203.1312 -
203.1313 -                 p -> Phase3,
203.1314 -                             &BlackPointOut,
203.1315 -                             &WhitePointOut,
203.1316 -                             &IlluminantOut,
203.1317 -                             &ChromaticAdaptationMatrixOut,
203.1318 -                 0,
203.1319 -                 0.0,
203.1320 -                 &p->Stage2,
203.1321 -                 &p->m2, &p->of2);
203.1322 -       }
203.1323 -
203.1324 -}
203.1325 -
203.1326 -
203.1327 -// Check colorspace
203.1328 -
203.1329 -static
203.1330 -LCMSBOOL IsProperColorSpace(cmsHPROFILE hProfile, DWORD dwFormat, LCMSBOOL lUsePCS)
203.1331 -{
203.1332 -       int Space = T_COLORSPACE(dwFormat);
203.1333 -
203.1334 -       if (Space == PT_ANY) return TRUE;
203.1335 -
203.1336 -       if (lUsePCS)
203.1337 -           return (Space == _cmsLCMScolorSpace(cmsGetPCS(hProfile)));
203.1338 -       else
203.1339 -           return (Space == _cmsLCMScolorSpace(cmsGetColorSpace(hProfile)));
203.1340 -}
203.1341 -
203.1342 -
203.1343 -// Auxiliary: allocate transform struct and set to defaults
203.1344 -
203.1345 -static
203.1346 -_LPcmsTRANSFORM AllocEmptyTransform(void)
203.1347 -{
203.1348 -    // Allocate needed memory
203.1349 -
203.1350 -    _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) _cmsMalloc(sizeof(_cmsTRANSFORM));
203.1351 -    if (!p) {
203.1352 -
203.1353 -          cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateTransform: _cmsMalloc() failed");
203.1354 -          return NULL;
203.1355 +        }
203.1356      }
203.1357  
203.1358 -    ZeroMemory(p, sizeof(_cmsTRANSFORM));
203.1359  
203.1360 -    // Initialize default methods
203.1361 -
203.1362 -    p -> xform          = NULL;
203.1363 -    p -> Intent         = INTENT_PERCEPTUAL;
203.1364 -    p -> ProofIntent    = INTENT_ABSOLUTE_COLORIMETRIC;
203.1365 -    p -> DoGamutCheck   = FALSE;
203.1366 -    p -> InputProfile   = NULL;
203.1367 -    p -> OutputProfile  = NULL;
203.1368 -    p -> PreviewProfile = NULL;
203.1369 -    p -> Preview        = NULL;
203.1370 -    p -> Gamut          = NULL;
203.1371 -    p -> DeviceLink     = NULL;
203.1372 -    p -> InMatShaper    = NULL;
203.1373 -    p -> OutMatShaper   = NULL;
203.1374 -    p -> SmeltMatShaper = NULL;
203.1375 -    p -> NamedColorList = NULL;
203.1376 -    p -> EntryColorSpace = (icColorSpaceSignature) 0;
203.1377 -    p -> ExitColorSpace  = (icColorSpaceSignature) 0;
203.1378 -    p -> AdaptationState = GlobalAdaptationState;
203.1379 -
203.1380 +    // Create a mutex for shared memory
203.1381      LCMS_CREATE_LOCK(&p->rwlock);
203.1382  
203.1383 +    p ->InputFormat     = InputFormat;
203.1384 +    p ->OutputFormat    = OutputFormat;
203.1385 +    p ->dwOriginalFlags = dwFlags;
203.1386 +    p ->ContextID       = ContextID;
203.1387      return p;
203.1388  }
203.1389  
203.1390 -
203.1391 -// Identify whatever a transform is to be cached
203.1392 -
203.1393  static
203.1394 -void SetPrecalculatedTransform(_LPcmsTRANSFORM p)
203.1395 +cmsBool GetXFormColorSpaces(int nProfiles, cmsHPROFILE hProfiles[], cmsColorSpaceSignature* Input, cmsColorSpaceSignature* Output)
203.1396  {
203.1397 -    if ((p->dwOriginalFlags & cmsFLAGS_GAMUTCHECK) && p ->GamutCheck != NULL) {
203.1398 -
203.1399 -        p -> xform = PrecalculatedXFORMGamutCheck;
203.1400 -
203.1401 -        if (!(p->dwOriginalFlags & cmsFLAGS_NOTCACHE)) {
203.1402 -
203.1403 -            ZeroMemory(p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
203.1404 -            TransformOnePixelWithGamutCheck(p, p->CacheIn, p ->CacheOut);
203.1405 -            p ->xform = CachedXFORMGamutCheck;
203.1406 -        }
203.1407 -
203.1408 -    }
203.1409 -    else {
203.1410 -
203.1411 -        p -> xform = PrecalculatedXFORM;
203.1412 -
203.1413 -        if (!(p->dwOriginalFlags & cmsFLAGS_NOTCACHE)) {
203.1414 -
203.1415 -            ZeroMemory(p ->CacheIn, sizeof(WORD) * MAXCHANNELS);
203.1416 -            cmsEvalLUT(p ->DeviceLink, p->CacheIn, p ->CacheOut);
203.1417 -            p ->xform = CachedXFORM;
203.1418 -        }
203.1419 -    }
203.1420 -}
203.1421 -
203.1422 -
203.1423 -// Transform is identified as device-link
203.1424 -static
203.1425 -cmsHPROFILE CreateDeviceLinkTransform(_LPcmsTRANSFORM p)
203.1426 -{
203.1427 -
203.1428 -    if (!IsProperColorSpace(p->InputProfile, p->InputFormat, FALSE)) {
203.1429 -        cmsSignalError(LCMS_ERRC_ABORTED, "Device link is operating on wrong colorspace on input");
203.1430 -        return NULL;
203.1431 -    }
203.1432 -
203.1433 -    if (!IsProperColorSpace(p->InputProfile, p->OutputFormat, TRUE)) {
203.1434 -        cmsSignalError(LCMS_ERRC_ABORTED, "Device link is operating on wrong colorspace on output");
203.1435 -        return NULL;
203.1436 -    }
203.1437 -
203.1438 -    // Device link does only have AToB0Tag (ICC-Spec 1998/09)
203.1439 -
203.1440 -    p->DeviceLink = cmsReadICCLut(p->InputProfile, icSigAToB0Tag);
203.1441 -
203.1442 -    if (!p->DeviceLink) {
203.1443 -
203.1444 -         cmsSignalError(LCMS_ERRC_ABORTED, "Noncompliant device-link profile");
203.1445 -         cmsDeleteTransform((cmsHTRANSFORM) p);
203.1446 -         return NULL;
203.1447 -         }
203.1448 -
203.1449 -    if (p ->PreviewProfile != NULL) {
203.1450 -            cmsSignalError(LCMS_ERRC_WARNING, "Proofing not supported on device link transforms");
203.1451 -    }
203.1452 -
203.1453 -    if (p ->OutputProfile != NULL) {
203.1454 -            cmsSignalError(LCMS_ERRC_WARNING, "Output profile should be NULL, since this is a device-link transform");
203.1455 -    }
203.1456 -
203.1457 -    p -> Phase1 = -1;
203.1458 -    p -> Phase2 = -1;
203.1459 -    p -> Phase3 = -1;
203.1460 -
203.1461 -    SetPrecalculatedTransform(p);
203.1462 -
203.1463 -    p -> EntryColorSpace = cmsGetColorSpace(p -> InputProfile);
203.1464 -    p -> ExitColorSpace  = cmsGetPCS(p -> InputProfile);
203.1465 -
203.1466 -    if (p ->EntryColorSpace == icSigRgbData ||
203.1467 -        p ->EntryColorSpace == icSigCmyData) {
203.1468 -
203.1469 -                    p->DeviceLink -> CLut16params.Interp3D = cmsTetrahedralInterp16;
203.1470 -    }
203.1471 -
203.1472 -    // Precalculated device-link profile is ready
203.1473 -    return (cmsHTRANSFORM) p;
203.1474 -}
203.1475 -
203.1476 -
203.1477 -// Transform that includes proofing
203.1478 -static
203.1479 -void CreateProof(_LPcmsTRANSFORM p, icTagSignature *ToTagPtr)
203.1480 -
203.1481 -{
203.1482 -    icTagSignature ProofTag;
203.1483 -
203.1484 -    if (p -> dwOriginalFlags & cmsFLAGS_SOFTPROOFING) {
203.1485 -
203.1486 -      // Apr-15, 2002 - Too much profiles does have bogus content
203.1487 -      // on preview tag, so I do compute it by my own.
203.1488 -
203.1489 -      p -> Preview = _cmsComputeSoftProofLUT(p ->PreviewProfile, p ->Intent);
203.1490 -      p -> Phase2  = LabRel;
203.1491 -
203.1492 -      // That's a proofing transfor, so use second intent for output.
203.1493 -
203.1494 -      *ToTagPtr  = PCS2Device[p->ProofIntent];
203.1495 -
203.1496 -      if (p -> Preview == NULL) {
203.1497 -
203.1498 -        ProofTag = Preview[p -> Intent];
203.1499 -
203.1500 -        if (!cmsIsTag(p ->PreviewProfile,  ProofTag)) {
203.1501 -
203.1502 -            ProofTag = Preview[0];
203.1503 -            if (!cmsIsTag(p ->PreviewProfile,  ProofTag))
203.1504 -                            ProofTag = (icTagSignature)0;
203.1505 -        }
203.1506 -
203.1507 -        if (ProofTag) {
203.1508 -
203.1509 -             p -> Preview = cmsReadICCLut(p ->PreviewProfile, ProofTag);
203.1510 -             p -> Phase2 = GetPhase(p ->PreviewProfile);
203.1511 -
203.1512 -        }
203.1513 -        else
203.1514 -             {
203.1515 -             p -> Preview = NULL;
203.1516 -             p ->PreviewProfile = NULL;
203.1517 -             cmsSignalError(LCMS_ERRC_WARNING, "Sorry, the proof profile has not previewing capabilities");
203.1518 -             }
203.1519 -      }
203.1520 -
203.1521 -    }
203.1522 -
203.1523 -
203.1524 -    // Aug-31, 2001 - Too much profiles does have bogus content
203.1525 -    // on gamut tag, so I do compute it by my own.
203.1526 -
203.1527 -    if ((p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK) && (p -> dwOriginalFlags & cmsFLAGS_NOTPRECALC)) {
203.1528 -
203.1529 -
203.1530 -             p -> Gamut = _cmsComputeGamutLUT(p->PreviewProfile, p ->Intent);
203.1531 -             p -> Phase2  = LabRel;
203.1532 -
203.1533 -             if (p -> Gamut == NULL) {
203.1534 -
203.1535 -                // Profile goes only in one direction... try to see
203.1536 -                // if profile has the tag, and use it, no matter it
203.1537 -                // could be bogus. This is the last chance!
203.1538 -
203.1539 -                if (cmsIsTag(p ->PreviewProfile, icSigGamutTag)) {
203.1540 -
203.1541 -                    p -> Gamut = cmsReadICCLut(p ->PreviewProfile, icSigGamutTag);
203.1542 -
203.1543 -                    }
203.1544 -                    else   {
203.1545 -
203.1546 -                     // Nope, cannot be done.
203.1547 -
203.1548 -                     cmsSignalError(LCMS_ERRC_WARNING, "Sorry, the proof profile has not gamut checking capabilities");
203.1549 -                     p -> Gamut = NULL;
203.1550 -                    }
203.1551 -             }
203.1552 -
203.1553 -      }
203.1554 -
203.1555 -}
203.1556 -
203.1557 -// Choose the adequate transform routine
203.1558 -
203.1559 -static
203.1560 -_LPcmsTRANSFORM PickTransformRoutine(_LPcmsTRANSFORM p,
203.1561 -                                    icTagSignature *FromTagPtr,
203.1562 -                                    icTagSignature *ToTagPtr)
203.1563 -{
203.1564 -
203.1565 -
203.1566 -
203.1567 -
203.1568 -        // Is a named color profile?
203.1569 -        if (cmsGetDeviceClass(p->InputProfile) == icSigNamedColorClass) {
203.1570 -
203.1571 -                  // Yes, and used as input
203.1572 -                  p ->FromDevice = NC2toPCS;
203.1573 -        }
203.1574 -        else {
203.1575 -                // Can we optimize matrix-shaper only transform?
203.1576 -
203.1577 -                   if ((*FromTagPtr == 0) &&
203.1578 -                       (*ToTagPtr == 0) &&
203.1579 -                       (!p->PreviewProfile) &&
203.1580 -                       (p -> Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
203.1581 -                       (p -> EntryColorSpace == icSigRgbData) &&
203.1582 -                       (p -> ExitColorSpace == icSigRgbData)  &&
203.1583 -                       !(p -> dwOriginalFlags & cmsFLAGS_BLACKPOINTCOMPENSATION)) {
203.1584 -
203.1585 -                          // Yes... try to smelt matrix-shapers
203.1586 -                          p -> xform = MatrixShaperXFORM;
203.1587 -                          p -> dwOriginalFlags |= cmsFLAGS_NOTPRECALC;
203.1588 -
203.1589 -                          if (!cmsBuildSmeltMatShaper(p))
203.1590 -                          {
203.1591 -                                 cmsSignalError(LCMS_ERRC_ABORTED, "unable to smelt shaper-matrix, required tags missing");
203.1592 -                                 return NULL;
203.1593 -                          }
203.1594 -
203.1595 -                          p -> Phase1 = p -> Phase3 = XYZRel;
203.1596 -                          return p;
203.1597 -
203.1598 -                }
203.1599 -
203.1600 -                // No, is a transform involving LUT
203.1601 -
203.1602 -                if (*FromTagPtr != 0) {
203.1603 -
203.1604 -                     p -> FromDevice = LUTtoPCS;
203.1605 -                     p -> Device2PCS = cmsReadICCLut(p -> InputProfile, *FromTagPtr);
203.1606 -                     if (!p -> Device2PCS) {
203.1607 -
203.1608 -                            cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for input");
203.1609 -                            return NULL;
203.1610 -                            }
203.1611 -
203.1612 -              }
203.1613 -              else
203.1614 -              {
203.1615 -                     p -> FromDevice = ShaperMatrixToPCS;
203.1616 -                     p -> InMatShaper = cmsBuildInputMatrixShaper(p -> InputProfile);
203.1617 -
203.1618 -                     if (!p ->InMatShaper) {
203.1619 -                            cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for input");
203.1620 -                            return NULL;
203.1621 -                            }
203.1622 -
203.1623 -                     p -> Phase1 = XYZRel;
203.1624 -
203.1625 -              }
203.1626 -              }
203.1627 -
203.1628 -              if (*ToTagPtr != 0) {
203.1629 -
203.1630 -                     p -> ToDevice = PCStoLUT;
203.1631 -                     p -> PCS2Device = cmsReadICCLut(p -> OutputProfile, *ToTagPtr);
203.1632 -                     if (!p -> PCS2Device) {
203.1633 -                            cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for output");
203.1634 -                            return NULL;
203.1635 -                            }
203.1636 -
203.1637 -                     }
203.1638 -              else
203.1639 -              {
203.1640 -                     p -> ToDevice = PCStoShaperMatrix;
203.1641 -                     p -> OutMatShaper = cmsBuildOutputMatrixShaper(p->OutputProfile);
203.1642 -
203.1643 -                     if (!p -> OutMatShaper) {
203.1644 -                            cmsSignalError(LCMS_ERRC_ABORTED, "profile is unsuitable for output");
203.1645 -                            return NULL;
203.1646 -                            }
203.1647 -                     p -> Phase3 = XYZRel;
203.1648 -
203.1649 -              }
203.1650 -
203.1651 -
203.1652 -       return p;
203.1653 -}
203.1654 -
203.1655 -
203.1656 -
203.1657 -
203.1658 -// Create a transform.
203.1659 -
203.1660 -cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
203.1661 -                                               DWORD InputFormat,
203.1662 -                                               cmsHPROFILE OutputProfile,
203.1663 -                                               DWORD OutputFormat,
203.1664 -                                               cmsHPROFILE ProofingProfile,
203.1665 -                                               int nIntent,
203.1666 -                                               int ProofingIntent,
203.1667 -                                               DWORD dwFlags)
203.1668 -
203.1669 -{
203.1670 -       _LPcmsTRANSFORM p;
203.1671 -       icTagSignature FromTag;
203.1672 -       icTagSignature ToTag;
203.1673 -
203.1674 -       if (nIntent < 0 || nIntent > 3 ||
203.1675 -           ProofingIntent < 0 || ProofingIntent > 3) {
203.1676 -
203.1677 -            cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateTransform: intent mismatch");
203.1678 -            return NULL;
203.1679 -       }
203.1680 -
203.1681 -       p = AllocEmptyTransform();
203.1682 -       if (p == NULL) return NULL;
203.1683 -
203.1684 -       p -> xform           = NormalXFORM;
203.1685 -       p -> Intent          = nIntent;
203.1686 -       p -> ProofIntent     = ProofingIntent;
203.1687 -       p -> DoGamutCheck    = FALSE;
203.1688 -       p -> InputProfile    = InputProfile;
203.1689 -       p -> OutputProfile   = OutputProfile;
203.1690 -       p -> PreviewProfile  = ProofingProfile;
203.1691 -       p -> InputFormat     = InputFormat;
203.1692 -       p -> OutputFormat    = OutputFormat;
203.1693 -       p -> dwOriginalFlags = dwFlags;
203.1694 -
203.1695 -       p -> lInputV4Lab     = p ->lOutputV4Lab = FALSE;
203.1696 -
203.1697 -
203.1698 -       p -> FromInput = _cmsIdentifyInputFormat(p, InputFormat);
203.1699 -       p -> ToOutput  = _cmsIdentifyOutputFormat(p, OutputFormat);
203.1700 -
203.1701 -       // Null transform can be done without profiles
203.1702 -       if ((p->dwOriginalFlags & cmsFLAGS_NULLTRANSFORM) ||
203.1703 -                        ((InputProfile == NULL) &&
203.1704 -                         (OutputProfile == NULL))) {
203.1705 -
203.1706 -            p -> xform = NullXFORM;
203.1707 -            return (cmsHTRANSFORM) p;
203.1708 -       }
203.1709 -
203.1710 -       // From here we need at least one input profile
203.1711 -       if (InputProfile == NULL) {
203.1712 -
203.1713 -          cmsSignalError(LCMS_ERRC_ABORTED, "Input profile cannot be NULL!");
203.1714 -          cmsDeleteTransform((cmsHTRANSFORM) p);
203.1715 -          return NULL;
203.1716 -       }
203.1717 -
203.1718 -
203.1719 -       //  Device link are means to store precalculated transform grids.
203.1720 -       if (cmsGetDeviceClass(InputProfile) == icSigLinkClass) {
203.1721 -
203.1722 -            return CreateDeviceLinkTransform(p);
203.1723 -       }
203.1724 -
203.1725 -       if (!IsProperColorSpace(InputProfile, InputFormat, FALSE)) {
203.1726 -
203.1727 -              cmsSignalError(LCMS_ERRC_ABORTED, "Input profile is operating on wrong colorspace");
203.1728 -              cmsDeleteTransform((cmsHTRANSFORM) p);
203.1729 -              return NULL;
203.1730 -       }
203.1731 -
203.1732 -       p ->EntryColorSpace = cmsGetColorSpace(InputProfile);
203.1733 -
203.1734 -       // Oct-21-2002: Added named color transforms
203.1735 -       if (cmsGetDeviceClass(InputProfile) == icSigNamedColorClass) {
203.1736 -
203.1737 -        if (p ->NamedColorList == NULL)
203.1738 -                p ->NamedColorList = cmsAllocNamedColorList(0);
203.1739 -
203.1740 -        cmsReadICCnamedColorList(p, InputProfile, icSigNamedColor2Tag);
203.1741 -
203.1742 -        // Special case. If output profile == NULL, then the transform gives
203.1743 -        // device values from named colors.
203.1744 -
203.1745 -        if (OutputProfile == NULL) {
203.1746 -
203.1747 -            p ->ExitColorSpace = p -> EntryColorSpace;
203.1748 -            p ->xform = NC2deviceXform;
203.1749 -            return (cmsHTRANSFORM) p;
203.1750 -        }
203.1751 -
203.1752 -        // Named color doesn't precalc anything
203.1753 -        p -> dwOriginalFlags |= cmsFLAGS_NOTPRECALC;
203.1754 -       }
203.1755 -
203.1756 -
203.1757 -       // From here we need also output profile.
203.1758 -      if (OutputProfile == NULL) {
203.1759 -          cmsSignalError(LCMS_ERRC_ABORTED, "Output profile cannot be NULL!");
203.1760 -          cmsDeleteTransform((cmsHTRANSFORM) p);
203.1761 -          return NULL;
203.1762 -       }
203.1763 -
203.1764 -
203.1765 -       if (!IsProperColorSpace(OutputProfile, OutputFormat, FALSE)) {
203.1766 -              cmsSignalError(LCMS_ERRC_ABORTED, "Output profile is operating on wrong colorspace");
203.1767 -              cmsDeleteTransform((cmsHTRANSFORM) p);
203.1768 -              return NULL;
203.1769 -       }
203.1770 -
203.1771 -       p -> ExitColorSpace = cmsGetColorSpace(OutputProfile);
203.1772 -
203.1773 -       // Named color only on input
203.1774 -       if (cmsGetDeviceClass(OutputProfile) == icSigNamedColorClass) {
203.1775 -
203.1776 -           cmsSignalError(LCMS_ERRC_ABORTED, "Named color profiles are not supported as output");
203.1777 -           cmsDeleteTransform((cmsHTRANSFORM) p);
203.1778 -           return NULL;
203.1779 -       }
203.1780 -
203.1781 -       p -> Phase1 = GetPhase(InputProfile);
203.1782 -       p -> Phase2 = -1;
203.1783 -       p -> Phase3 = GetPhase(OutputProfile);
203.1784 -
203.1785 -       // Try to locate a LUT
203.1786 -
203.1787 -       FromTag  = Device2PCS[nIntent];
203.1788 -       ToTag    = PCS2Device[nIntent];
203.1789 -
203.1790 -       if (!cmsIsTag(InputProfile, FromTag)) {
203.1791 -
203.1792 -              FromTag = Device2PCS[0];
203.1793 -
203.1794 -              if (!cmsIsTag(InputProfile,  FromTag)) {
203.1795 -                            FromTag = (icTagSignature)0;
203.1796 -              }
203.1797 -       }
203.1798 -
203.1799 -       // If proofing is needed, add required tags/parameters
203.1800 -       if (ProofingProfile)
203.1801 -           CreateProof(p, &ToTag);
203.1802 -
203.1803 -
203.1804 -       if (!cmsIsTag(OutputProfile,  ToTag)) {
203.1805 -
203.1806 -           ToTag = PCS2Device[0];
203.1807 -
203.1808 -           // 12-Dec-2003, Abstract profiles can be placed as output and still using AToB0
203.1809 -           if (cmsGetDeviceClass(OutputProfile) == icSigAbstractClass) {
203.1810 -
203.1811 -                    if (!cmsIsTag(OutputProfile,  ToTag)) {
203.1812 -                                ToTag = (icTagSignature) icSigAToB0Tag;
203.1813 -                    }
203.1814 -           }
203.1815 -
203.1816 -           if (!cmsIsTag(OutputProfile,  ToTag))
203.1817 -                            ToTag = (icTagSignature)0;
203.1818 -       }
203.1819 -
203.1820 -
203.1821 -       if (p-> dwOriginalFlags & cmsFLAGS_MATRIXINPUT)
203.1822 -              FromTag = (icTagSignature)0;
203.1823 -
203.1824 -       if (p -> dwOriginalFlags & cmsFLAGS_MATRIXOUTPUT)
203.1825 -              ToTag = (icTagSignature)0;
203.1826 -
203.1827 -
203.1828 -
203.1829 -       if (PickTransformRoutine(p, &FromTag, &ToTag) == NULL) {
203.1830 -
203.1831 -          cmsDeleteTransform((cmsHTRANSFORM) p);
203.1832 -          return NULL;
203.1833 -
203.1834 -       }
203.1835 -
203.1836 -       TakeConversionRoutines(p, dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION);
203.1837 -
203.1838 -       if (!(p -> dwOriginalFlags & cmsFLAGS_NOTPRECALC)) {
203.1839 -
203.1840 -               LPLUT DeviceLink;
203.1841 -               LPLUT GamutCheck = NULL;
203.1842 -
203.1843 -
203.1844 -               if (p ->EntryColorSpace == icSigCmykData &&
203.1845 -                   p ->ExitColorSpace == icSigCmykData &&
203.1846 -                   (dwFlags & cmsFLAGS_PRESERVEBLACK)) {
203.1847 -
203.1848 -                    DeviceLink = _cmsPrecalculateBlackPreservingDeviceLink((cmsHTRANSFORM) p, dwFlags);
203.1849 -
203.1850 -                    // Cannot be done at all?
203.1851 -                    if (DeviceLink == NULL)
203.1852 -                            DeviceLink = _cmsPrecalculateDeviceLink((cmsHTRANSFORM) p, dwFlags);
203.1853 -
203.1854 -               }
203.1855 -               else {
203.1856 -
203.1857 -                    DeviceLink = _cmsPrecalculateDeviceLink((cmsHTRANSFORM) p, dwFlags);
203.1858 -               }
203.1859 -
203.1860 -               // Allow to specify cmsFLAGS_GAMUTCHECK, even if no proofing profile is given
203.1861 -               if ((p ->PreviewProfile != NULL) && (p -> dwOriginalFlags & cmsFLAGS_GAMUTCHECK)) {
203.1862 -
203.1863 -                   GamutCheck = _cmsPrecalculateGamutCheck((cmsHTRANSFORM) p);
203.1864 -               }
203.1865 -
203.1866 -               // If input colorspace is Rgb, Cmy, then use tetrahedral interpolation
203.1867 -               // for speed reasons (it only works well on spaces on Luma is diagonal, and
203.1868 -               // not if luma is in separate channel)
203.1869 -               if (p ->EntryColorSpace == icSigRgbData ||
203.1870 -                   p ->EntryColorSpace == icSigCmyData) {
203.1871 -
203.1872 -
203.1873 -                    cmsCalcCLUT16ParamsEx(DeviceLink->CLut16params.nSamples,
203.1874 -                                          DeviceLink->CLut16params.nInputs,
203.1875 -                                          DeviceLink->CLut16params.nOutputs,
203.1876 -                                          TRUE, &DeviceLink->CLut16params);
203.1877 -
203.1878 -               }
203.1879 -
203.1880 -               // If this is a 8-bit transform, optimize LUT further.
203.1881 -
203.1882 -                if ((T_BYTES(InputFormat) == 1) && (T_CHANNELS(InputFormat) == 3)) {
203.1883 -
203.1884 -                    DeviceLink = _cmsBlessLUT8(DeviceLink);
203.1885 -                    if (DeviceLink == NULL) return NULL;
203.1886 -
203.1887 -                }
203.1888 -
203.1889 -
203.1890 -                p ->GamutCheck = GamutCheck;
203.1891 -
203.1892 -                if (DeviceLink) {
203.1893 -
203.1894 -                    p ->DeviceLink = DeviceLink;
203.1895 -
203.1896 -                    if ((nIntent != INTENT_ABSOLUTE_COLORIMETRIC) &&
203.1897 -                        !(p -> dwOriginalFlags & cmsFLAGS_NOWHITEONWHITEFIXUP))
203.1898 -
203.1899 -                            _cmsFixWhiteMisalignment(p);
203.1900 -
203.1901 -                }
203.1902 -                else
203.1903 -                {
203.1904 -
203.1905 -                     cmsSignalError(LCMS_ERRC_ABORTED,
203.1906 -                                "Cannot precalculate %d->%d channels transform!",
203.1907 -                                T_CHANNELS(InputFormat), T_CHANNELS(OutputFormat));
203.1908 -
203.1909 -                     cmsDeleteTransform(p);
203.1910 -                     return NULL;
203.1911 -                }
203.1912 -
203.1913 -
203.1914 -              SetPrecalculatedTransform(p);
203.1915 -
203.1916 -
203.1917 -       }
203.1918 -
203.1919 -       // Re-Identify formats
203.1920 -       p -> FromInput = _cmsIdentifyInputFormat(p, InputFormat);
203.1921 -       p -> ToOutput  = _cmsIdentifyOutputFormat(p, OutputFormat);
203.1922 -
203.1923 -
203.1924 -       return p;
203.1925 -}
203.1926 -
203.1927 -
203.1928 -// Wrapper por simpler non-proofing transforms.
203.1929 -
203.1930 -cmsHTRANSFORM LCMSEXPORT cmsCreateTransform(cmsHPROFILE Input,
203.1931 -                                       DWORD InputFormat,
203.1932 -                                       cmsHPROFILE Output,
203.1933 -                                       DWORD OutputFormat,
203.1934 -                                       int Intent,
203.1935 -                                       DWORD dwFlags)
203.1936 -
203.1937 -{
203.1938 -       return cmsCreateProofingTransform(Input, InputFormat,
203.1939 -                                         Output, OutputFormat,
203.1940 -                                         NULL,
203.1941 -                                         Intent, INTENT_ABSOLUTE_COLORIMETRIC,
203.1942 -                                         dwFlags);
203.1943 -}
203.1944 -
203.1945 -
203.1946 -// Profiles are *NOT* closed
203.1947 -
203.1948 -void LCMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform)
203.1949 -{
203.1950 -       _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) (LPSTR) hTransform;
203.1951 -
203.1952 -       if (p -> Device2PCS)
203.1953 -              cmsFreeLUT(p -> Device2PCS);
203.1954 -       if (p -> PCS2Device)
203.1955 -              cmsFreeLUT(p -> PCS2Device);
203.1956 -       if (p -> Gamut)
203.1957 -              cmsFreeLUT(p -> Gamut);
203.1958 -       if (p -> Preview)
203.1959 -              cmsFreeLUT(p -> Preview);
203.1960 -       if (p -> DeviceLink)
203.1961 -              cmsFreeLUT(p -> DeviceLink);
203.1962 -       if (p -> InMatShaper)
203.1963 -              cmsFreeMatShaper(p -> InMatShaper);
203.1964 -       if (p -> OutMatShaper)
203.1965 -              cmsFreeMatShaper(p -> OutMatShaper);
203.1966 -       if (p -> SmeltMatShaper)
203.1967 -              cmsFreeMatShaper(p -> SmeltMatShaper);
203.1968 -       if (p ->NamedColorList)
203.1969 -              cmsFreeNamedColorList(p ->NamedColorList);
203.1970 -       if (p -> GamutCheck)
203.1971 -            cmsFreeLUT(p -> GamutCheck);
203.1972 -
203.1973 -       LCMS_FREE_LOCK(&p->rwlock);
203.1974 -
203.1975 -       _cmsFree((void *) p);
203.1976 -}
203.1977 -
203.1978 -
203.1979 -// Apply transform code
203.1980 -void LCMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
203.1981 -                    LPVOID InputBuffer,
203.1982 -                    LPVOID OutputBuffer, unsigned int Size)
203.1983 -
203.1984 -{
203.1985 -
203.1986 -            _LPcmsTRANSFORM p = (_LPcmsTRANSFORM) (LPSTR) Transform;
203.1987 -
203.1988 -            p -> StrideIn = p -> StrideOut = Size;
203.1989 -
203.1990 -            p -> xform(p, InputBuffer, OutputBuffer, Size);
203.1991 -
203.1992 -}
203.1993 -
203.1994 -
203.1995 -void LCMSEXPORT cmsSetAlarmCodes(int r, int g, int b)
203.1996 -{
203.1997 -       AlarmR = RGB_8_TO_16(r);
203.1998 -       AlarmG = RGB_8_TO_16(g);
203.1999 -       AlarmB = RGB_8_TO_16(b);
203.2000 -}
203.2001 -
203.2002 -void LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b)
203.2003 -{
203.2004 -       *r = RGB_16_TO_8(AlarmR);
203.2005 -       *g = RGB_16_TO_8(AlarmG);
203.2006 -       *b = RGB_16_TO_8(AlarmB);
203.2007 -}
203.2008 -
203.2009 -// Returns TRUE if the profile is implemented as matrix-shaper
203.2010 -
203.2011 -LCMSBOOL LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile)
203.2012 -{
203.2013 -    switch (cmsGetColorSpace(hProfile)) {
203.2014 -
203.2015 -    case icSigGrayData:
203.2016 -
203.2017 -        return cmsIsTag(hProfile, icSigGrayTRCTag);
203.2018 -
203.2019 -    case icSigRgbData:
203.2020 -
203.2021 -        return (cmsIsTag(hProfile, icSigRedColorantTag) &&
203.2022 -                cmsIsTag(hProfile, icSigGreenColorantTag) &&
203.2023 -                cmsIsTag(hProfile, icSigBlueColorantTag) &&
203.2024 -                cmsIsTag(hProfile, icSigRedTRCTag) &&
203.2025 -                cmsIsTag(hProfile, icSigGreenTRCTag) &&
203.2026 -                cmsIsTag(hProfile, icSigBlueTRCTag));
203.2027 -
203.2028 -    default:
203.2029 -
203.2030 -        return FALSE;
203.2031 -    }
203.2032 -}
203.2033 -
203.2034 -
203.2035 -LCMSBOOL LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile,
203.2036 -                                                int Intent, int UsedDirection)
203.2037 -{
203.2038 -
203.2039 -     icTagSignature* TagTable;
203.2040 -
203.2041 -     // Device link profiles only implements the intent in header
203.2042 -
203.2043 -     if (cmsGetDeviceClass(hProfile) != icSigLinkClass) {
203.2044 -
203.2045 -       switch (UsedDirection) {
203.2046 -
203.2047 -       case LCMS_USED_AS_INPUT: TagTable = Device2PCS; break;
203.2048 -       case LCMS_USED_AS_OUTPUT:TagTable = PCS2Device; break;
203.2049 -       case LCMS_USED_AS_PROOF: TagTable = Preview; break;
203.2050 -
203.2051 -       default:
203.2052 -        cmsSignalError(LCMS_ERRC_ABORTED, "Unexpected direction (%d)", UsedDirection);
203.2053 -        return FALSE;
203.2054 -       }
203.2055 -
203.2056 -       if (cmsIsTag(hProfile, TagTable[Intent])) return TRUE;
203.2057 -       return _cmsIsMatrixShaper(hProfile);
203.2058 -     }
203.2059 -
203.2060 -     return (cmsTakeRenderingIntent(hProfile) == Intent);
203.2061 -}
203.2062 -
203.2063 -// Multiple profile transform.
203.2064 -static
203.2065 -int MultiprofileSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)
203.2066 -{
203.2067 -    cmsHTRANSFORM* Transforms = (cmsHTRANSFORM*) Cargo;
203.2068 +    cmsColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
203.2069 +    cmsColorSpaceSignature PostColorSpace;
203.2070      int i;
203.2071  
203.2072 -    cmsDoTransform(Transforms[0], In, Out, 1);
203.2073 +    if (hProfiles[0] == NULL) return FALSE;
203.2074  
203.2075 -    for (i=1; Transforms[i]; i++)
203.2076 -        cmsDoTransform(Transforms[i], Out, Out, 1);
203.2077 -
203.2078 -
203.2079 -
203.2080 -    return TRUE;
203.2081 -}
203.2082 -
203.2083 -
203.2084 -static
203.2085 -int IsAllowedInSingleXform(icProfileClassSignature aClass)
203.2086 -{
203.2087 -    return (aClass == icSigInputClass) ||
203.2088 -           (aClass == icSigDisplayClass) ||
203.2089 -           (aClass == icSigOutputClass) ||
203.2090 -           (aClass == icSigColorSpaceClass);
203.2091 -}
203.2092 -
203.2093 -
203.2094 -// A multiprofile transform does chain several profiles into a single
203.2095 -// devicelink. It couls also be used to merge named color profiles into
203.2096 -// a single database.
203.2097 -
203.2098 -
203.2099 -cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
203.2100 -                                                                int nProfiles,
203.2101 -                                                                DWORD dwInput,
203.2102 -                                                                DWORD dwOutput,
203.2103 -                                                                int Intent,
203.2104 -                                                                DWORD dwFlags)
203.2105 -{
203.2106 -    cmsHTRANSFORM Transforms[257];
203.2107 -    DWORD dwPrecalcFlags = (dwFlags|cmsFLAGS_NOTPRECALC|cmsFLAGS_NOTCACHE);
203.2108 -    DWORD FormatInput, FormatOutput;
203.2109 -    cmsHPROFILE hLab, hXYZ, hProfile;
203.2110 -    icColorSpaceSignature ColorSpace, CurrentColorSpace;
203.2111 -    icColorSpaceSignature ColorSpaceIn, ColorSpaceOut;
203.2112 -    LPLUT Grid;
203.2113 -    int nGridPoints, ChannelsInput, ChannelsOutput = 3, i;
203.2114 -    _LPcmsTRANSFORM p;
203.2115 -    int nNamedColor;
203.2116 -
203.2117 -    if (nProfiles > 255) {
203.2118 -        cmsSignalError(LCMS_ERRC_ABORTED, "What are you trying to do with more that 255 profiles?!?, of course aborted");
203.2119 -        return NULL;
203.2120 -    }
203.2121 -
203.2122 -    // There is a simple case with just two profiles, try to catch it in order of getting
203.2123 -    // black preservation to work on this function, at least with two profiles.
203.2124 -
203.2125 -
203.2126 -    if (nProfiles == 2) {
203.2127 -
203.2128 -        icProfileClassSignature Class1 = cmsGetDeviceClass(hProfiles[0]);
203.2129 -        icProfileClassSignature Class2 = cmsGetDeviceClass(hProfiles[1]);
203.2130 -
203.2131 -        // Only input, output and display are allowed
203.2132 -
203.2133 -        if (IsAllowedInSingleXform(Class1) &&
203.2134 -            IsAllowedInSingleXform(Class2))
203.2135 -                   return cmsCreateTransform(hProfiles[0], dwInput, hProfiles[1], dwOutput, Intent, dwFlags);
203.2136 -    }
203.2137 -
203.2138 -
203.2139 -    // Creates a phantom transform for latter filling
203.2140 -    p = (_LPcmsTRANSFORM) cmsCreateTransform(NULL, dwInput,
203.2141 -                                             NULL, dwOutput, Intent, cmsFLAGS_NULLTRANSFORM);
203.2142 -
203.2143 -    // If user wants null one, give it
203.2144 -    if (dwFlags & cmsFLAGS_NULLTRANSFORM) return (cmsHPROFILE) p;
203.2145 -
203.2146 -    // Is a bunch of named color profiles?
203.2147 -    nNamedColor = 0;
203.2148 -    for (i=0; i < nProfiles; i++) {
203.2149 -        if (cmsGetDeviceClass(hProfiles[i]) == icSigNamedColorClass)
203.2150 -                nNamedColor++;
203.2151 -    }
203.2152 -
203.2153 -
203.2154 -    if (nNamedColor == nProfiles) {
203.2155 -
203.2156 -            // Yes, only named color. Create a named color-device
203.2157 -            // and append to named color table
203.2158 -
203.2159 -            cmsDeleteTransform((cmsHTRANSFORM) p);
203.2160 -
203.2161 -            p = (_LPcmsTRANSFORM) cmsCreateTransform(hProfiles[0], dwInput, NULL, dwOutput, Intent, dwFlags);
203.2162 -            for (i=1; i < nProfiles; i++) {
203.2163 -                    cmsReadICCnamedColorList(p, hProfiles[i], icSigNamedColor2Tag);
203.2164 -            }
203.2165 -
203.2166 -            return p;   // Ok, done so far
203.2167 -    }
203.2168 -    else
203.2169 -    if (nNamedColor > 0) {
203.2170 -
203.2171 -        cmsDeleteTransform((cmsHTRANSFORM) p);
203.2172 -        cmsSignalError(LCMS_ERRC_ABORTED, "Could not mix named color profiles with other types in multiprofile transform");
203.2173 -        return NULL;
203.2174 -    }
203.2175 -
203.2176 -
203.2177 -    // We will need a 3DCLUT for device link
203.2178 -    Grid =  cmsAllocLUT();
203.2179 -    if (!Grid) return NULL;
203.2180 -
203.2181 -    // This one is our PCS (Always Lab)
203.2182 -    hLab  = cmsCreateLabProfile(NULL);
203.2183 -    hXYZ  = cmsCreateXYZProfile();
203.2184 -
203.2185 -    if (!hLab || !hXYZ) goto ErrorCleanup;
203.2186 -
203.2187 -    // Take some info....
203.2188 -
203.2189 -    p ->EntryColorSpace = CurrentColorSpace = cmsGetColorSpace(hProfiles[0]);
203.2190 -
203.2191 +    *Input = PostColorSpace = cmsGetColorSpace(hProfiles[0]);
203.2192  
203.2193      for (i=0; i < nProfiles; i++) {
203.2194  
203.2195 -        int lIsDeviceLink, lIsInput;
203.2196 +        cmsHPROFILE hProfile = hProfiles[i];
203.2197  
203.2198 -        // Check colorspace
203.2199 +        int lIsInput = (PostColorSpace != cmsSigXYZData) &&
203.2200 +                       (PostColorSpace != cmsSigLabData);
203.2201  
203.2202 -        hProfile      = hProfiles[i];
203.2203 -        lIsDeviceLink = (cmsGetDeviceClass(hProfile) == icSigLinkClass);
203.2204 -        lIsInput      = (CurrentColorSpace != icSigXYZData) &&
203.2205 -                        (CurrentColorSpace != icSigLabData);
203.2206 +        if (hProfile == NULL) return FALSE;
203.2207  
203.2208          if (lIsInput) {
203.2209  
203.2210              ColorSpaceIn    = cmsGetColorSpace(hProfile);
203.2211              ColorSpaceOut   = cmsGetPCS(hProfile);
203.2212 -
203.2213          }
203.2214          else {
203.2215  
203.2216 @@ -1912,136 +486,302 @@
203.2217              ColorSpaceOut   = cmsGetColorSpace(hProfile);
203.2218          }
203.2219  
203.2220 -        ChannelsInput  = _cmsChannelsOf(ColorSpaceIn);
203.2221 -        ChannelsOutput = _cmsChannelsOf(ColorSpaceOut);
203.2222 +        PostColorSpace = ColorSpaceOut;
203.2223 +    }
203.2224  
203.2225 -        FormatInput    = BYTES_SH(2)|CHANNELS_SH(ChannelsInput);
203.2226 -        FormatOutput   = BYTES_SH(2)|CHANNELS_SH(ChannelsOutput);
203.2227 +    *Output = PostColorSpace;
203.2228  
203.2229 -        ColorSpace = ColorSpaceIn;
203.2230 +    return TRUE;
203.2231 +}
203.2232  
203.2233 +// Check colorspace
203.2234 +static
203.2235 +cmsBool  IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwFormat)
203.2236 +{
203.2237 +    int Space1 = T_COLORSPACE(dwFormat);
203.2238 +    int Space2 = _cmsLCMScolorSpace(Check);
203.2239  
203.2240 -        if (ColorSpace == CurrentColorSpace) {
203.2241 +    if (Space1 == PT_ANY) return TRUE;
203.2242 +    if (Space1 == Space2) return TRUE;
203.2243  
203.2244 -            if (lIsDeviceLink) {
203.2245 +    if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
203.2246 +    if (Space1 == PT_Lab   && Space2 == PT_LabV2) return TRUE;
203.2247  
203.2248 -                Transforms[i]  = cmsCreateTransform(hProfile, FormatInput,
203.2249 -                                                    NULL,     FormatOutput,
203.2250 -                                                    Intent,   dwPrecalcFlags);
203.2251 -            }
203.2252 +    return FALSE;
203.2253 +}
203.2254  
203.2255 -            else {
203.2256 +// ----------------------------------------------------------------------------------------------------------------
203.2257  
203.2258 -                if (lIsInput) {
203.2259 +// New to lcms 2.0 -- have all parameters available.
203.2260 +cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
203.2261 +                                                   cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
203.2262 +                                                   cmsBool  BPC[],
203.2263 +                                                   cmsUInt32Number Intents[],
203.2264 +                                                   cmsFloat64Number AdaptationStates[],
203.2265 +                                                   cmsHPROFILE hGamutProfile,
203.2266 +                                                   cmsUInt32Number nGamutPCSposition,
203.2267 +                                                   cmsUInt32Number InputFormat,
203.2268 +                                                   cmsUInt32Number OutputFormat,
203.2269 +                                                   cmsUInt32Number dwFlags)
203.2270 +{
203.2271 +    _cmsTRANSFORM* xform;
203.2272 +    cmsBool  FloatTransform;
203.2273 +    cmsColorSpaceSignature EntryColorSpace;
203.2274 +    cmsColorSpaceSignature ExitColorSpace;
203.2275 +    cmsPipeline* Lut;
203.2276 +    cmsUInt32Number LastIntent = Intents[nProfiles-1];
203.2277  
203.2278 -                        Transforms[i]  = cmsCreateTransform(hProfile, FormatInput,
203.2279 -                                                  (ColorSpaceOut == icSigLabData ? hLab : hXYZ), FormatOutput,
203.2280 -                                                  Intent, dwPrecalcFlags);
203.2281 -                }
203.2282 -                else {
203.2283 -                        Transforms[i]  = cmsCreateTransform((ColorSpaceIn == icSigLabData ? hLab : hXYZ), FormatInput,
203.2284 -                                                  hProfile, FormatOutput,
203.2285 -                                                  Intent, dwPrecalcFlags);
203.2286 +    // If gamut check is requested, make sure we have a gamut profile
203.2287 +    if (dwFlags & cmsFLAGS_GAMUTCHECK) {
203.2288 +        if (hGamutProfile == NULL) dwFlags &= ~cmsFLAGS_GAMUTCHECK;
203.2289 +    }
203.2290  
203.2291 -                }
203.2292 -            }
203.2293 +    // On floating point transforms, inhibit optimizations
203.2294 +    FloatTransform = (_cmsFormatterIsFloat(InputFormat) && _cmsFormatterIsFloat(OutputFormat));
203.2295  
203.2296 +    if (_cmsFormatterIsFloat(InputFormat) || _cmsFormatterIsFloat(OutputFormat))
203.2297 +        dwFlags |= cmsFLAGS_NOCACHE;
203.2298  
203.2299 +    // Mark entry/exit spaces
203.2300 +    if (!GetXFormColorSpaces(nProfiles, hProfiles, &EntryColorSpace, &ExitColorSpace)) {
203.2301 +        cmsSignalError(ContextID, cmsERROR_NULL, "NULL input profiles on transform");
203.2302 +        return NULL;
203.2303 +    }
203.2304 +
203.2305 +    // Check if proper colorspaces
203.2306 +    if (!IsProperColorSpace(EntryColorSpace, InputFormat)) {
203.2307 +        cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong input color space on transform");
203.2308 +        return NULL;
203.2309 +    }
203.2310 +
203.2311 +    if (!IsProperColorSpace(ExitColorSpace, OutputFormat)) {
203.2312 +        cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "Wrong output color space on transform");
203.2313 +        return NULL;
203.2314 +    }
203.2315 +
203.2316 +    // Create a pipeline with all transformations
203.2317 +    Lut = _cmsLinkProfiles(ContextID, nProfiles, Intents, hProfiles, BPC, AdaptationStates, dwFlags);
203.2318 +    if (Lut == NULL) {
203.2319 +        cmsSignalError(ContextID, cmsERROR_NOT_SUITABLE, "Couldn't link the profiles");
203.2320 +        return NULL;
203.2321 +    }
203.2322 +
203.2323 +    // Optimize the LUT if possible
203.2324 +    _cmsOptimizePipeline(&Lut, LastIntent, &InputFormat, &OutputFormat, &dwFlags);
203.2325 +
203.2326 +
203.2327 +    // All seems ok
203.2328 +    xform = AllocEmptyTransform(ContextID, InputFormat, OutputFormat, dwFlags);
203.2329 +    if (xform == NULL) {
203.2330 +        cmsPipelineFree(Lut);
203.2331 +        return NULL;
203.2332 +    }
203.2333 +
203.2334 +    // Keep values
203.2335 +    xform ->EntryColorSpace = EntryColorSpace;
203.2336 +    xform ->ExitColorSpace  = ExitColorSpace;
203.2337 +    xform ->Lut             = Lut;
203.2338 +
203.2339 +
203.2340 +    // Create a gamut check LUT if requested
203.2341 +    if (hGamutProfile != NULL && (dwFlags & cmsFLAGS_GAMUTCHECK))
203.2342 +        xform ->GamutCheck  = _cmsCreateGamutCheckPipeline(ContextID, hProfiles,
203.2343 +                                                        BPC, Intents,
203.2344 +                                                        AdaptationStates,
203.2345 +                                                        nGamutPCSposition,
203.2346 +                                                        hGamutProfile);
203.2347 +
203.2348 +
203.2349 +    // Try to read input and output colorant table
203.2350 +    if (cmsIsTag(hProfiles[0], cmsSigColorantTableTag)) {
203.2351 +
203.2352 +        // Input table can only come in this way.
203.2353 +        xform ->InputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[0], cmsSigColorantTableTag));
203.2354 +    }
203.2355 +
203.2356 +    // Output is a little bit more complex.
203.2357 +    if (cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigLinkClass) {
203.2358 +
203.2359 +        // This tag may exist only on devicelink profiles.
203.2360 +        if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag)) {
203.2361 +
203.2362 +            // It may be NULL if error
203.2363 +            xform ->OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableOutTag));
203.2364          }
203.2365 -        else  // Can come from pcs?
203.2366 -        if (CurrentColorSpace == icSigXYZData) {
203.2367  
203.2368 -            Transforms[i] = cmsCreateTransform(hXYZ, FormatInput,
203.2369 -                                              hProfile, FormatOutput,
203.2370 -                                              Intent, dwPrecalcFlags);
203.2371 +    } else {
203.2372  
203.2373 +        if (cmsIsTag(hProfiles[nProfiles-1], cmsSigColorantTableTag)) {
203.2374 +
203.2375 +            xform -> OutputColorant = cmsDupNamedColorList((cmsNAMEDCOLORLIST*) cmsReadTag(hProfiles[nProfiles-1], cmsSigColorantTableTag));
203.2376          }
203.2377 -        else
203.2378 -        if (CurrentColorSpace == icSigLabData) {
203.2379 +    }
203.2380  
203.2381 -            Transforms[i] = cmsCreateTransform(hLab, FormatInput,
203.2382 -                                              hProfile, FormatOutput,
203.2383 -                                              Intent, dwPrecalcFlags);
203.2384 +    // Store the sequence of profiles
203.2385 +    if (dwFlags & cmsFLAGS_KEEP_SEQUENCE) {
203.2386 +        xform ->Sequence = _cmsCompileProfileSequence(ContextID, nProfiles, hProfiles);
203.2387 +    }
203.2388 +    else
203.2389 +        xform ->Sequence = NULL;
203.2390  
203.2391 +    // If this is a cached transform, init first value, which is zero (16 bits only)
203.2392 +    if (!(dwFlags & cmsFLAGS_NOCACHE)) {
203.2393 +
203.2394 +        memset(&xform ->CacheIn, 0, sizeof(xform ->CacheIn));
203.2395 +
203.2396 +        if (xform ->GamutCheck != NULL) {
203.2397 +            TransformOnePixelWithGamutCheck(xform, xform ->CacheIn, xform->CacheOut);
203.2398          }
203.2399          else {
203.2400 -                cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateMultiprofileTransform: ColorSpace mismatch");
203.2401 -                goto ErrorCleanup;
203.2402 +
203.2403 +            xform ->Lut ->Eval16Fn(xform ->CacheIn, xform->CacheOut, xform -> Lut->Data);
203.2404          }
203.2405  
203.2406 -        if (Transforms[i] == NULL) {
203.2407 -            cmsSignalError(LCMS_ERRC_ABORTED, "cmsCreateMultiprofileTransform: unable to create transform");
203.2408 -            goto ErrorCleanup;
203.2409 -        }
203.2410 -        CurrentColorSpace = ColorSpaceOut;
203.2411 -
203.2412      }
203.2413  
203.2414 -    p ->ExitColorSpace = CurrentColorSpace;
203.2415 -    Transforms[i] = NULL;   // End marker
203.2416 +    return (cmsHTRANSFORM) xform;
203.2417 +}
203.2418  
203.2419 -    p ->InputProfile  = hProfiles[0];
203.2420 -    p ->OutputProfile = hProfiles[nProfiles - 1];
203.2421 +// Multiprofile transforms: Gamut check is not available here, as it is unclear from which profile the gamut comes.
203.2422  
203.2423 -    nGridPoints = _cmsReasonableGridpointsByColorspace(p ->EntryColorSpace, dwFlags);
203.2424 +cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID,
203.2425 +                                                       cmsHPROFILE hProfiles[],
203.2426 +                                                       cmsUInt32Number nProfiles,
203.2427 +                                                       cmsUInt32Number InputFormat,
203.2428 +                                                       cmsUInt32Number OutputFormat,
203.2429 +                                                       cmsUInt32Number Intent,
203.2430 +                                                       cmsUInt32Number dwFlags)
203.2431 +{
203.2432 +    cmsUInt32Number i;
203.2433 +    cmsBool BPC[256];
203.2434 +    cmsUInt32Number Intents[256];
203.2435 +    cmsFloat64Number AdaptationStates[256];
203.2436  
203.2437 -    ChannelsInput  = _cmsChannelsOf(cmsGetColorSpace(p ->InputProfile));
203.2438 -
203.2439 -    Grid = cmsAlloc3DGrid(Grid, nGridPoints, ChannelsInput, ChannelsOutput);
203.2440 -
203.2441 -    if (!(dwFlags & cmsFLAGS_NOPRELINEARIZATION))
203.2442 -           _cmsComputePrelinearizationTablesFromXFORM(Transforms, nProfiles, Grid);
203.2443 -
203.2444 -    // Compute device link on 16-bit basis
203.2445 -    if (!cmsSample3DGrid(Grid, MultiprofileSampler, (LPVOID) Transforms, Grid -> wFlags)) {
203.2446 -
203.2447 -                cmsFreeLUT(Grid);
203.2448 -                goto ErrorCleanup;
203.2449 +    if (nProfiles <= 0 || nProfiles > 255) {
203.2450 +         cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
203.2451 +        return NULL;
203.2452      }
203.2453  
203.2454 -    // All ok, store the newly created LUT
203.2455 -    p -> DeviceLink   = Grid;
203.2456 -
203.2457 -    SetPrecalculatedTransform(p);
203.2458 -
203.2459 -    for (i=nProfiles-1; i >= 0; --i)
203.2460 -        cmsDeleteTransform(Transforms[i]);
203.2461 -
203.2462 -
203.2463 -    if (hLab) cmsCloseProfile(hLab);
203.2464 -    if (hXYZ) cmsCloseProfile(hXYZ);
203.2465 -
203.2466 -
203.2467 -    if (p ->EntryColorSpace == icSigRgbData ||
203.2468 -        p ->EntryColorSpace == icSigCmyData) {
203.2469 -
203.2470 -                    p->DeviceLink -> CLut16params.Interp3D = cmsTetrahedralInterp16;
203.2471 +    for (i=0; i < nProfiles; i++) {
203.2472 +        BPC[i] = dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION ? TRUE : FALSE;
203.2473 +        Intents[i] = Intent;
203.2474 +        AdaptationStates[i] = GlobalAdaptationState;
203.2475      }
203.2476  
203.2477  
203.2478 -    if ((Intent != INTENT_ABSOLUTE_COLORIMETRIC) &&
203.2479 -        !(dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP))
203.2480 -                            _cmsFixWhiteMisalignment(p);
203.2481 -
203.2482 -    return (cmsHTRANSFORM) p;
203.2483 -
203.2484 -
203.2485 -ErrorCleanup:
203.2486 -
203.2487 -    if (hLab) cmsCloseProfile(hLab);
203.2488 -    if (hXYZ) cmsCloseProfile(hXYZ);
203.2489 -    return NULL;
203.2490 +    return cmsCreateExtendedTransform(ContextID, nProfiles, hProfiles, BPC, Intents, AdaptationStates, NULL, 0, InputFormat, OutputFormat, dwFlags);
203.2491  }
203.2492  
203.2493  
203.2494  
203.2495 -double LCMSEXPORT cmsSetAdaptationState(double d)
203.2496 +cmsHTRANSFORM CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
203.2497 +                                                  cmsUInt32Number nProfiles,
203.2498 +                                                  cmsUInt32Number InputFormat,
203.2499 +                                                  cmsUInt32Number OutputFormat,
203.2500 +                                                  cmsUInt32Number Intent,
203.2501 +                                                  cmsUInt32Number dwFlags)
203.2502  {
203.2503 -    double OldVal = GlobalAdaptationState;
203.2504  
203.2505 -    if (d >= 0)
203.2506 -            GlobalAdaptationState = d;
203.2507 +    if (nProfiles <= 0 || nProfiles > 255) {
203.2508 +         cmsSignalError(NULL, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
203.2509 +         return NULL;
203.2510 +    }
203.2511  
203.2512 -    return OldVal;
203.2513 +    return cmsCreateMultiprofileTransformTHR(cmsGetProfileContextID(hProfiles[0]),
203.2514 +                                                  hProfiles,
203.2515 +                                                  nProfiles,
203.2516 +                                                  InputFormat,
203.2517 +                                                  OutputFormat,
203.2518 +                                                  Intent,
203.2519 +                                                  dwFlags);
203.2520 +}
203.2521 +
203.2522 +cmsHTRANSFORM CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID,
203.2523 +                                              cmsHPROFILE Input,
203.2524 +                                              cmsUInt32Number InputFormat,
203.2525 +                                              cmsHPROFILE Output,
203.2526 +                                              cmsUInt32Number OutputFormat,
203.2527 +                                              cmsUInt32Number Intent,
203.2528 +                                              cmsUInt32Number dwFlags)
203.2529 +{
203.2530 +
203.2531 +    cmsHPROFILE hArray[2];
203.2532 +
203.2533 +    hArray[0] = Input;
203.2534 +    hArray[1] = Output;
203.2535 +
203.2536 +    return cmsCreateMultiprofileTransformTHR(ContextID, hArray, Output == NULL ? 1 : 2, InputFormat, OutputFormat, Intent, dwFlags);
203.2537 +}
203.2538 +
203.2539 +CMSAPI cmsHTRANSFORM CMSEXPORT cmsCreateTransform(cmsHPROFILE Input,
203.2540 +                                                  cmsUInt32Number InputFormat,
203.2541 +                                                  cmsHPROFILE Output,
203.2542 +                                                  cmsUInt32Number OutputFormat,
203.2543 +                                                  cmsUInt32Number Intent,
203.2544 +                                                  cmsUInt32Number dwFlags)
203.2545 +{
203.2546 +    return cmsCreateTransformTHR(cmsGetProfileContextID(Input), Input, InputFormat, Output, OutputFormat, Intent, dwFlags);
203.2547 +}
203.2548 +
203.2549 +
203.2550 +cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID,
203.2551 +                                                   cmsHPROFILE InputProfile,
203.2552 +                                                   cmsUInt32Number InputFormat,
203.2553 +                                                   cmsHPROFILE OutputProfile,
203.2554 +                                                   cmsUInt32Number OutputFormat,
203.2555 +                                                   cmsHPROFILE ProofingProfile,
203.2556 +                                                   cmsUInt32Number nIntent,
203.2557 +                                                   cmsUInt32Number ProofingIntent,
203.2558 +                                                   cmsUInt32Number dwFlags)
203.2559 +{
203.2560 +    cmsHPROFILE hArray[4];
203.2561 +    cmsUInt32Number Intents[4];
203.2562 +    cmsBool  BPC[4];
203.2563 +    cmsFloat64Number Adaptation[4];
203.2564 +    cmsBool  DoBPC = (dwFlags & cmsFLAGS_BLACKPOINTCOMPENSATION) ? TRUE : FALSE;
203.2565 +
203.2566 +
203.2567 +    hArray[0]  = InputProfile; hArray[1] = ProofingProfile; hArray[2]  = ProofingProfile;               hArray[3] = OutputProfile;
203.2568 +    Intents[0] = nIntent;      Intents[1] = nIntent;        Intents[2] = INTENT_RELATIVE_COLORIMETRIC;  Intents[3] = ProofingIntent;
203.2569 +    BPC[0]     = DoBPC;        BPC[1] = DoBPC;              BPC[2] = 0;                                 BPC[3] = 0;
203.2570 +
203.2571 +    Adaptation[0] = Adaptation[1] = Adaptation[2] = Adaptation[3] = GlobalAdaptationState;
203.2572 +
203.2573 +    if (!(dwFlags & (cmsFLAGS_SOFTPROOFING|cmsFLAGS_GAMUTCHECK)))
203.2574 +        return cmsCreateTransformTHR(ContextID, InputProfile, InputFormat, OutputProfile, OutputFormat, nIntent, dwFlags);
203.2575 +
203.2576 +    return cmsCreateExtendedTransform(ContextID, 4, hArray, BPC, Intents, Adaptation,
203.2577 +                                        ProofingProfile, 1, InputFormat, OutputFormat, dwFlags);
203.2578  
203.2579  }
203.2580 +
203.2581 +
203.2582 +cmsHTRANSFORM CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE InputProfile,
203.2583 +                                                   cmsUInt32Number InputFormat,
203.2584 +                                                   cmsHPROFILE OutputProfile,
203.2585 +                                                   cmsUInt32Number OutputFormat,
203.2586 +                                                   cmsHPROFILE ProofingProfile,
203.2587 +                                                   cmsUInt32Number nIntent,
203.2588 +                                                   cmsUInt32Number ProofingIntent,
203.2589 +                                                   cmsUInt32Number dwFlags)
203.2590 +{
203.2591 +    return cmsCreateProofingTransformTHR(cmsGetProfileContextID(InputProfile),
203.2592 +                                                   InputProfile,
203.2593 +                                                   InputFormat,
203.2594 +                                                   OutputProfile,
203.2595 +                                                   OutputFormat,
203.2596 +                                                   ProofingProfile,
203.2597 +                                                   nIntent,
203.2598 +                                                   ProofingIntent,
203.2599 +                                                   dwFlags);
203.2600 +}
203.2601 +
203.2602 +
203.2603 +// Grab the ContextID from an open transform. Returns NULL if a NULL transform is passed
203.2604 +cmsContext CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform)
203.2605 +{
203.2606 +    _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
203.2607 +
203.2608 +    if (xform == NULL) return NULL;
203.2609 +    return xform -> ContextID;
203.2610 +}
   204.1 --- a/src/share/native/sun/java2d/cmm/lcms/icc34.h	Thu Sep 23 17:33:40 2010 -0700
   204.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   204.3 @@ -1,1023 +0,0 @@
   204.4 -/*
   204.5 - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
   204.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   204.7 - *
   204.8 - * This code is free software; you can redistribute it and/or modify it
   204.9 - * under the terms of the GNU General Public License version 2 only, as
  204.10 - * published by the Free Software Foundation.  Oracle designates this
  204.11 - * particular file as subject to the "Classpath" exception as provided
  204.12 - * by Oracle in the LICENSE file that accompanied this code.
  204.13 - *
  204.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  204.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  204.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  204.17 - * version 2 for more details (a copy is included in the LICENSE file that
  204.18 - * accompanied this code).
  204.19 - *
  204.20 - * You should have received a copy of the GNU General Public License version
  204.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  204.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  204.23 - *
  204.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  204.25 - * or visit www.oracle.com if you need additional information or have any
  204.26 - * questions.
  204.27 - */
  204.28 -
  204.29 -/* Header file guard bands */
  204.30 -#ifndef ICC_H
  204.31 -#define ICC_H
  204.32 -
  204.33 -/*
  204.34 - * This version of the header file corresponds to the profile
  204.35 - * specification version 3.4.
  204.36 - *
  204.37 - * All header file entries are pre-fixed with "ic" to help
  204.38 - * avoid name space collisions. Signatures are pre-fixed with
  204.39 - * icSig.
  204.40 - *
  204.41 - * The structures defined in this header file were created to
  204.42 - * represent a description of an ICC profile on disk. Rather
  204.43 - * than use pointers a technique is used where a single byte array
  204.44 - * was placed at the end of each structure. This allows us in "C"
  204.45 - * to extend the structure by allocating more data than is needed
  204.46 - * to account for variable length structures.
  204.47 - *
  204.48 - * This also ensures that data following is allocated
  204.49 - * contiguously and makes it easier to write and read data from
  204.50 - * the file.
  204.51 - *
  204.52 - * For example to allocate space for a 256 count length UCR
  204.53 - * and BG array, and fill the allocated data.  Note strlen + 1
  204.54 - * to remember NULL terminator.
  204.55 - *
  204.56 -        icUcrBgCurve    *ucrCurve, *bgCurve;
  204.57 -        int             ucr_nbytes, bg_nbytes, string_bytes;
  204.58 -        icUcrBg         *ucrBgWrite;
  204.59 -        char            ucr_string[100], *ucr_char;
  204.60 -
  204.61 -        strcpy(ucr_string, "Example ucrBG curves");
  204.62 -        ucr_nbytes = sizeof(icUInt32Number) +
  204.63 -                 (UCR_CURVE_SIZE * sizeof(icUInt16Number));
  204.64 -        bg_nbytes = sizeof(icUInt32Number) +
  204.65 -                 (BG_CURVE_SIZE * sizeof(icUInt16Number));
  204.66 -        string_bytes = strlen(ucr_string) + 1;
  204.67 -
  204.68 -        ucrBgWrite = (icUcrBg *)malloc(
  204.69 -                                (ucr_nbytes + bg_nbytes + string_bytes));
  204.70 -
  204.71 -        ucrCurve = (icUcrBgCurve *)ucrBgWrite->data;
  204.72 -        ucrCurve->count = UCR_CURVE_SIZE;
  204.73 -        for (i=0; i<ucrCurve->count; i++)
  204.74 -                ucrCurve->curve[i] = (icUInt16Number)i;
  204.75 -
  204.76 -        bgCurve = (icUcrBgCurve *)((char *)ucrCurve + ucr_nbytes);
  204.77 -        bgCurve->count = BG_CURVE_SIZE;
  204.78 -        for (i=0; i<bgCurve->count; i++)
  204.79 -                bgCurve->curve[i] = 255 - (icUInt16Number)i;
  204.80 -
  204.81 -        ucr_char = (char *)((char *)bgCurve + bg_nbytes);
  204.82 -        memcpy(ucr_char, ucr_string, string_bytes);
  204.83 - *
  204.84 - */
  204.85 -
  204.86 -/*
  204.87 - * Many of the structures contain variable length arrays. This
  204.88 - * is represented by the use of the convention.
  204.89 - *
  204.90 - *      type    data[icAny];
  204.91 - */
  204.92 -
  204.93 -/*------------------------------------------------------------------------*/
  204.94 -/*
  204.95 - * Defines used in the specification
  204.96 - */
  204.97 -#define icMagicNumber                   0x61637370L     /* 'acsp' */
  204.98 -#define icVersionNumber                 0x02100000L     /* 2.1.0, BCD */
  204.99 -
 204.100 -/* Screening Encodings */
 204.101 -#define icPrtrDefaultScreensFalse       0x00000000L     /* Bit pos 0 */
 204.102 -#define icPrtrDefaultScreensTrue        0x00000001L     /* Bit pos 0 */
 204.103 -#define icLinesPerInch                  0x00000002L     /* Bit pos 1 */
 204.104 -#define icLinesPerCm                    0x00000000L     /* Bit pos 1 */
 204.105 -
 204.106 -/*
 204.107 - * Device attributes, currently defined values correspond
 204.108 - * to the low 4 bytes of the 8 byte attribute quantity, see
 204.109 - * the header for their location.
 204.110 - */
 204.111 -#define icReflective                    0x00000000L     /* Bit pos 0 */
 204.112 -#define icTransparency                  0x00000001L     /* Bit pos 0 */
 204.113 -#define icGlossy                        0x00000000L     /* Bit pos 1 */
 204.114 -#define icMatte                         0x00000002L     /* Bit pos 1 */
 204.115 -
 204.116 -/*
 204.117 - * Profile header flags, the low 16 bits are reserved for consortium
 204.118 - * use.
 204.119 - */
 204.120 -#define icEmbeddedProfileFalse          0x00000000L     /* Bit pos 0 */
 204.121 -#define icEmbeddedProfileTrue           0x00000001L     /* Bit pos 0 */
 204.122 -#define icUseAnywhere                   0x00000000L     /* Bit pos 1 */
 204.123 -#define icUseWithEmbeddedDataOnly       0x00000002L     /* Bit pos 1 */
 204.124 -
 204.125 -/* Ascii or Binary data */
 204.126 -#define icAsciiData                     0x00000000L
 204.127 -#define icBinaryData                    0x00000001L
 204.128 -
 204.129 -/*
 204.130 - * Define used to indicate that this is a variable length array
 204.131 - */
 204.132 -#define icAny                           1
 204.133 -
 204.134 -
 204.135 -/*------------------------------------------------------------------------*/
 204.136 -/*
 204.137 - * Use this area to translate platform definitions of long
 204.138 - * etc into icXXX form. The rest of the header uses the icXXX
 204.139 - * typedefs. Signatures are 4 byte quantities.
 204.140 - *
 204.141 - */
 204.142 -
 204.143 -
 204.144 -#ifdef PACKAGE_NAME
 204.145 -/*
 204.146 -  June 9, 2003, Adapted for use with configure by Bob Friesenhahn
 204.147 -  Added the stupid check for autoconf by Marti Maria.
 204.148 -  PACKAGE_NAME is defined if autoconf is being used
 204.149 -*/
 204.150 -
 204.151 -typedef @UINT8_T@       icUInt8Number;
 204.152 -typedef @UINT16_T@      icUInt16Number;
 204.153 -typedef @UINT32_T@      icUInt32Number;
 204.154 -typedef @UINT32_T@      icUInt64Number[2];
 204.155 -
 204.156 -typedef @INT8_T@        icInt8Number;
 204.157 -typedef @INT16_T@       icInt16Number;
 204.158 -typedef @INT32_T@       icInt32Number;
 204.159 -typedef @INT32_T@       icInt64Number[2];
 204.160 -
 204.161 -#else
 204.162 -
 204.163 -/*
 204.164 - *Apr-17-2002: Modified by Marti Maria in order to provide wider portability.
 204.165 - */
 204.166 -
 204.167 -#if defined (__digital__) && defined (__unix__)
 204.168 -
 204.169 -/* Tru64 */
 204.170 -
 204.171 -#include <inttypes.h>
 204.172 -
 204.173 -typedef uint8_t   icUInt8Number;
 204.174 -typedef uint16_t  icUInt16Number;
 204.175 -typedef uint32_t  icUInt32Number;
 204.176 -typedef uint32_t  icUInt64Number[2];
 204.177 -
 204.178 -typedef int8_t     icInt8Number;
 204.179 -typedef int16_t    icInt16Number;
 204.180 -typedef int32_t    icInt32Number;
 204.181 -typedef int32_t    icInt64Number[2];
 204.182 -
 204.183 -#else
 204.184 -#ifdef __sgi
 204.185 -#include "sgidefs.h"
 204.186 -
 204.187 -
 204.188 -/*
 204.189 - * Number definitions
 204.190 - */
 204.191 -
 204.192 -/* Unsigned integer numbers */
 204.193 -typedef unsigned char   icUInt8Number;
 204.194 -typedef unsigned short  icUInt16Number;
 204.195 -typedef __uint32_t      icUInt32Number;
 204.196 -typedef __uint32_t      icUInt64Number[2];
 204.197 -
 204.198 -/* Signed numbers */
 204.199 -typedef char            icInt8Number;
 204.200 -typedef short           icInt16Number;
 204.201 -typedef __int32_t       icInt32Number;
 204.202 -typedef __int32_t       icInt64Number[2];
 204.203 -
 204.204 -
 204.205 -#else
 204.206 -#if defined(__GNUC__) || defined(__unix__) || defined(__unix)
 204.207 -
 204.208 -#include <sys/types.h>
 204.209 -
 204.210 -#if defined(__sun) || defined(__hpux) || defined (__MINGW) || defined(__MINGW32__)
 204.211 -
 204.212 -#if defined (__MINGW) || defined(__MINGW32__)
 204.213 -#include <stdint.h>
 204.214 -#endif
 204.215 -
 204.216 -
 204.217 -typedef uint8_t   icUInt8Number;
 204.218 -typedef uint16_t  icUInt16Number;
 204.219 -typedef uint32_t  icUInt32Number;
 204.220 -typedef uint32_t  icUInt64Number[2];
 204.221 -
 204.222 -#else
 204.223 -
 204.224 -/* Unsigned integer numbers */
 204.225 -typedef u_int8_t   icUInt8Number;
 204.226 -typedef u_int16_t  icUInt16Number;
 204.227 -typedef u_int32_t  icUInt32Number;
 204.228 -typedef u_int32_t  icUInt64Number[2];
 204.229 -
 204.230 -#endif
 204.231 -
 204.232 -
 204.233 -/* Signed numbers */
 204.234 -typedef int8_t     icInt8Number;
 204.235 -typedef int16_t    icInt16Number;
 204.236 -typedef int32_t    icInt32Number;
 204.237 -typedef int32_t    icInt64Number[2];
 204.238 -
 204.239 -
 204.240 -#else /* default definitions */
 204.241 -
 204.242 -/*
 204.243 - * Number definitions
 204.244 - */
 204.245 -
 204.246 -/* Unsigned integer numbers */
 204.247 -typedef unsigned char   icUInt8Number;
 204.248 -typedef unsigned short  icUInt16Number;
 204.249 -typedef unsigned long   icUInt32Number;
 204.250 -typedef unsigned long   icUInt64Number[2];
 204.251 -
 204.252 -/* Signed numbers */
 204.253 -typedef char            icInt8Number;
 204.254 -typedef short           icInt16Number;
 204.255 -typedef long            icInt32Number;
 204.256 -typedef long            icInt64Number[2];
 204.257 -
 204.258 -
 204.259 -#endif  /* default defs */
 204.260 -#endif
 204.261 -#endif
 204.262 -#endif
 204.263 -
 204.264 -/* Base types */
 204.265 -
 204.266 -typedef icInt32Number    icSignature;
 204.267 -typedef icInt32Number    icS15Fixed16Number;
 204.268 -typedef icUInt32Number   icU16Fixed16Number;
 204.269 -
 204.270 -
 204.271 -/*------------------------------------------------------------------------*/
 204.272 -/* public tags and sizes */
 204.273 -typedef enum {
 204.274 -    icSigAToB0Tag                       = 0x41324230L,  /* 'A2B0' */
 204.275 -    icSigAToB1Tag                       = 0x41324231L,  /* 'A2B1' */
 204.276 -    icSigAToB2Tag                       = 0x41324232L,  /* 'A2B2' */
 204.277 -    icSigBlueColorantTag                = 0x6258595AL,  /* 'bXYZ' */
 204.278 -    icSigBlueTRCTag                     = 0x62545243L,  /* 'bTRC' */
 204.279 -    icSigBToA0Tag                       = 0x42324130L,  /* 'B2A0' */
 204.280 -    icSigBToA1Tag                       = 0x42324131L,  /* 'B2A1' */
 204.281 -    icSigBToA2Tag                       = 0x42324132L,  /* 'B2A2' */
 204.282 -    icSigCalibrationDateTimeTag         = 0x63616C74L,  /* 'calt' */
 204.283 -    icSigCharTargetTag                  = 0x74617267L,  /* 'targ' */
 204.284 -    icSigCopyrightTag                   = 0x63707274L,  /* 'cprt' */
 204.285 -    icSigCrdInfoTag                     = 0x63726469L,  /* 'crdi' */
 204.286 -    icSigDeviceMfgDescTag               = 0x646D6E64L,  /* 'dmnd' */
 204.287 -    icSigDeviceModelDescTag             = 0x646D6464L,  /* 'dmdd' */
 204.288 -    icSigGamutTag                       = 0x67616D74L,  /* 'gamt ' */
 204.289 -    icSigGrayTRCTag                     = 0x6b545243L,  /* 'kTRC' */
 204.290 -    icSigGreenColorantTag               = 0x6758595AL,  /* 'gXYZ' */
 204.291 -    icSigGreenTRCTag                    = 0x67545243L,  /* 'gTRC' */
 204.292 -    icSigLuminanceTag                   = 0x6C756d69L,  /* 'lumi' */
 204.293 -    icSigMeasurementTag                 = 0x6D656173L,  /* 'meas' */
 204.294 -    icSigMediaBlackPointTag             = 0x626B7074L,  /* 'bkpt' */
 204.295 -    icSigMediaWhitePointTag             = 0x77747074L,  /* 'wtpt' */
 204.296 -    icSigNamedColorTag                  = 0x6E636f6CL,  /* 'ncol'
 204.297 -                                                         * OBSOLETE, use ncl2 */
 204.298 -    icSigNamedColor2Tag                 = 0x6E636C32L,  /* 'ncl2' */
 204.299 -    icSigPreview0Tag                    = 0x70726530L,  /* 'pre0' */
 204.300 -    icSigPreview1Tag                    = 0x70726531L,  /* 'pre1' */
 204.301 -    icSigPreview2Tag                    = 0x70726532L,  /* 'pre2' */
 204.302 -    icSigProfileDescriptionTag          = 0x64657363L,  /* 'desc' */
 204.303 -    icSigProfileSequenceDescTag         = 0x70736571L,  /* 'pseq' */
 204.304 -    icSigPs2CRD0Tag                     = 0x70736430L,  /* 'psd0' */
 204.305 -    icSigPs2CRD1Tag                     = 0x70736431L,  /* 'psd1' */
 204.306 -    icSigPs2CRD2Tag                     = 0x70736432L,  /* 'psd2' */
 204.307 -    icSigPs2CRD3Tag                     = 0x70736433L,  /* 'psd3' */
 204.308 -    icSigPs2CSATag                      = 0x70733273L,  /* 'ps2s' */
 204.309 -    icSigPs2RenderingIntentTag          = 0x70733269L,  /* 'ps2i' */
 204.310 -    icSigRedColorantTag                 = 0x7258595AL,  /* 'rXYZ' */
 204.311 -    icSigRedTRCTag                      = 0x72545243L,  /* 'rTRC' */
 204.312 -    icSigScreeningDescTag               = 0x73637264L,  /* 'scrd' */
 204.313 -    icSigScreeningTag                   = 0x7363726EL,  /* 'scrn' */
 204.314 -    icSigTechnologyTag                  = 0x74656368L,  /* 'tech' */
 204.315 -    icSigUcrBgTag                       = 0x62666420L,  /* 'bfd ' */
 204.316 -    icSigViewingCondDescTag             = 0x76756564L,  /* 'vued' */
 204.317 -    icSigViewingConditionsTag           = 0x76696577L,  /* 'view' */
 204.318 -    icMaxEnumTag                        = 0xFFFFFFFFL
 204.319 -} icTagSignature;
 204.320 -
 204.321 -/* technology signature descriptions */
 204.322 -typedef enum {
 204.323 -    icSigDigitalCamera                  = 0x6463616DL,  /* 'dcam' */
 204.324 -    icSigFilmScanner                    = 0x6673636EL,  /* 'fscn' */
 204.325 -    icSigReflectiveScanner              = 0x7273636EL,  /* 'rscn' */
 204.326 -    icSigInkJetPrinter                  = 0x696A6574L,  /* 'ijet' */
 204.327 -    icSigThermalWaxPrinter              = 0x74776178L,  /* 'twax' */
 204.328 -    icSigElectrophotographicPrinter     = 0x6570686FL,  /* 'epho' */
 204.329 -    icSigElectrostaticPrinter           = 0x65737461L,  /* 'esta' */
 204.330 -    icSigDyeSublimationPrinter          = 0x64737562L,  /* 'dsub' */
 204.331 -    icSigPhotographicPaperPrinter       = 0x7270686FL,  /* 'rpho' */
 204.332 -    icSigFilmWriter                     = 0x6670726EL,  /* 'fprn' */
 204.333 -    icSigVideoMonitor                   = 0x7669646DL,  /* 'vidm' */
 204.334 -    icSigVideoCamera                    = 0x76696463L,  /* 'vidc' */
 204.335 -    icSigProjectionTelevision           = 0x706A7476L,  /* 'pjtv' */
 204.336 -    icSigCRTDisplay                     = 0x43525420L,  /* 'CRT ' */
 204.337 -    icSigPMDisplay                      = 0x504D4420L,  /* 'PMD ' */
 204.338 -    icSigAMDisplay                      = 0x414D4420L,  /* 'AMD ' */
 204.339 -    icSigPhotoCD                        = 0x4B504344L,  /* 'KPCD' */
 204.340 -    icSigPhotoImageSetter               = 0x696D6773L,  /* 'imgs' */
 204.341 -    icSigGravure                        = 0x67726176L,  /* 'grav' */
 204.342 -    icSigOffsetLithography              = 0x6F666673L,  /* 'offs' */
 204.343 -    icSigSilkscreen                     = 0x73696C6BL,  /* 'silk' */
 204.344 -    icSigFlexography                    = 0x666C6578L,  /* 'flex' */
 204.345 -    icMaxEnumTechnology                 = 0xFFFFFFFFL
 204.346 -} icTechnologySignature;
 204.347 -
 204.348 -/* type signatures */
 204.349 -typedef enum {
 204.350 -    icSigCurveType                      = 0x63757276L,  /* 'curv' */
 204.351 -    icSigDataType                       = 0x64617461L,  /* 'data' */
 204.352 -    icSigDateTimeType                   = 0x6474696DL,  /* 'dtim' */
 204.353 -    icSigLut16Type                      = 0x6d667432L,  /* 'mft2' */
 204.354 -    icSigLut8Type                       = 0x6d667431L,  /* 'mft1' */
 204.355 -    icSigMeasurementType                = 0x6D656173L,  /* 'meas' */
 204.356 -    icSigNamedColorType                 = 0x6E636f6CL,  /* 'ncol'
 204.357 -                                                         * OBSOLETE, use ncl2 */
 204.358 -    icSigProfileSequenceDescType        = 0x70736571L,  /* 'pseq' */
 204.359 -    icSigS15Fixed16ArrayType            = 0x73663332L,  /* 'sf32' */
 204.360 -    icSigScreeningType                  = 0x7363726EL,  /* 'scrn' */
 204.361 -    icSigSignatureType                  = 0x73696720L,  /* 'sig ' */
 204.362 -    icSigTextType                       = 0x74657874L,  /* 'text' */
 204.363 -    icSigTextDescriptionType            = 0x64657363L,  /* 'desc' */
 204.364 -    icSigU16Fixed16ArrayType            = 0x75663332L,  /* 'uf32' */
 204.365 -    icSigUcrBgType                      = 0x62666420L,  /* 'bfd ' */
 204.366 -    icSigUInt16ArrayType                = 0x75693136L,  /* 'ui16' */
 204.367 -    icSigUInt32ArrayType                = 0x75693332L,  /* 'ui32' */
 204.368 -    icSigUInt64ArrayType                = 0x75693634L,  /* 'ui64' */
 204.369 -    icSigUInt8ArrayType                 = 0x75693038L,  /* 'ui08' */
 204.370 -    icSigViewingConditionsType          = 0x76696577L,  /* 'view' */
 204.371 -    icSigXYZType                        = 0x58595A20L,  /* 'XYZ ' */
 204.372 -    icSigXYZArrayType                   = 0x58595A20L,  /* 'XYZ ' */
 204.373 -    icSigNamedColor2Type                = 0x6E636C32L,  /* 'ncl2' */
 204.374 -    icSigCrdInfoType                    = 0x63726469L,  /* 'crdi' */
 204.375 -    icMaxEnumType                       = 0xFFFFFFFFL
 204.376 -} icTagTypeSignature;
 204.377 -
 204.378 -/*
 204.379 - * Color Space Signatures
 204.380 - * Note that only icSigXYZData and icSigLabData are valid
 204.381 - * Profile Connection Spaces (PCSs)
 204.382 - */
 204.383 -typedef enum {
 204.384 -    icSigXYZData                        = 0x58595A20L,  /* 'XYZ ' */
 204.385 -    icSigLabData                        = 0x4C616220L,  /* 'Lab ' */
 204.386 -    icSigLuvData                        = 0x4C757620L,  /* 'Luv ' */
 204.387 -    icSigYCbCrData                      = 0x59436272L,  /* 'YCbr' */
 204.388 -    icSigYxyData                        = 0x59787920L,  /* 'Yxy ' */
 204.389 -    icSigRgbData                        = 0x52474220L,  /* 'RGB ' */
 204.390 -    icSigGrayData                       = 0x47524159L,  /* 'GRAY' */
 204.391 -    icSigHsvData                        = 0x48535620L,  /* 'HSV ' */
 204.392 -    icSigHlsData                        = 0x484C5320L,  /* 'HLS ' */
 204.393 -    icSigCmykData                       = 0x434D594BL,  /* 'CMYK' */
 204.394 -    icSigCmyData                        = 0x434D5920L,  /* 'CMY ' */
 204.395 -    icSig2colorData                     = 0x32434C52L,  /* '2CLR' */
 204.396 -    icSig3colorData                     = 0x33434C52L,  /* '3CLR' */
 204.397 -    icSig4colorData                     = 0x34434C52L,  /* '4CLR' */
 204.398 -    icSig5colorData                     = 0x35434C52L,  /* '5CLR' */
 204.399 -    icSig6colorData                     = 0x36434C52L,  /* '6CLR' */
 204.400 -    icSig7colorData                     = 0x37434C52L,  /* '7CLR' */
 204.401 -    icSig8colorData                     = 0x38434C52L,  /* '8CLR' */
 204.402 -    icSig9colorData                     = 0x39434C52L,  /* '9CLR' */
 204.403 -    icSig10colorData                    = 0x41434C52L,  /* 'ACLR' */
 204.404 -    icSig11colorData                    = 0x42434C52L,  /* 'BCLR' */
 204.405 -    icSig12colorData                    = 0x43434C52L,  /* 'CCLR' */
 204.406 -    icSig13colorData                    = 0x44434C52L,  /* 'DCLR' */
 204.407 -    icSig14colorData                    = 0x45434C52L,  /* 'ECLR' */
 204.408 -    icSig15colorData                    = 0x46434C52L,  /* 'FCLR' */
 204.409 -    icMaxEnumData                       = 0xFFFFFFFFL
 204.410 -} icColorSpaceSignature;
 204.411 -
 204.412 -/* profileClass enumerations */
 204.413 -typedef enum {
 204.414 -    icSigInputClass                     = 0x73636E72L,  /* 'scnr' */
 204.415 -    icSigDisplayClass                   = 0x6D6E7472L,  /* 'mntr' */
 204.416 -    icSigOutputClass                    = 0x70727472L,  /* 'prtr' */
 204.417 -    icSigLinkClass                      = 0x6C696E6BL,  /* 'link' */
 204.418 -    icSigAbstractClass                  = 0x61627374L,  /* 'abst' */
 204.419 -    icSigColorSpaceClass                = 0x73706163L,  /* 'spac' */
 204.420 -    icSigNamedColorClass                = 0x6e6d636cL,  /* 'nmcl' */
 204.421 -    icMaxEnumClass                      = 0xFFFFFFFFL
 204.422 -} icProfileClassSignature;
 204.423 -
 204.424 -/* Platform Signatures */
 204.425 -typedef enum {
 204.426 -    icSigMacintosh                      = 0x4150504CL,  /* 'APPL' */
 204.427 -    icSigMicrosoft                      = 0x4D534654L,  /* 'MSFT' */
 204.428 -    icSigSolaris                        = 0x53554E57L,  /* 'SUNW' */
 204.429 -    icSigSGI                            = 0x53474920L,  /* 'SGI ' */
 204.430 -    icSigTaligent                       = 0x54474E54L,  /* 'TGNT' */
 204.431 -    icMaxEnumPlatform                   = 0xFFFFFFFFL
 204.432 -} icPlatformSignature;
 204.433 -
 204.434 -/*------------------------------------------------------------------------*/
 204.435 -/*
 204.436 - * Other enums
 204.437 - */
 204.438 -
 204.439 -/* Measurement Flare, used in the measurmentType tag */
 204.440 -typedef enum {
 204.441 -    icFlare0                            = 0x00000000L,  /* 0% flare */
 204.442 -    icFlare100                          = 0x00000001L,  /* 100% flare */
 204.443 -    icMaxFlare                          = 0xFFFFFFFFL
 204.444 -} icMeasurementFlare;
 204.445 -
 204.446 -/* Measurement Geometry, used in the measurmentType tag */
 204.447 -typedef enum {
 204.448 -    icGeometryUnknown                   = 0x00000000L,  /* Unknown */
 204.449 -    icGeometry045or450                  = 0x00000001L,  /* 0/45, 45/0 */
 204.450 -    icGeometry0dord0                    = 0x00000002L,  /* 0/d or d/0 */
 204.451 -    icMaxGeometry                       = 0xFFFFFFFFL
 204.452 -} icMeasurementGeometry;
 204.453 -
 204.454 -/* Rendering Intents, used in the profile header */
 204.455 -typedef enum {
 204.456 -    icPerceptual                        = 0,
 204.457 -    icRelativeColorimetric              = 1,
 204.458 -    icSaturation                        = 2,
 204.459 -    icAbsoluteColorimetric              = 3,
 204.460 -    icMaxEnumIntent                     = 0xFFFFFFFFL
 204.461 -} icRenderingIntent;
 204.462 -
 204.463 -/* Different Spot Shapes currently defined, used for screeningType */
 204.464 -typedef enum {
 204.465 -    icSpotShapeUnknown                  = 0,
 204.466 -    icSpotShapePrinterDefault           = 1,
 204.467 -    icSpotShapeRound                    = 2,
 204.468 -    icSpotShapeDiamond                  = 3,
 204.469 -    icSpotShapeEllipse                  = 4,
 204.470 -    icSpotShapeLine                     = 5,
 204.471 -    icSpotShapeSquare                   = 6,
 204.472 -    icSpotShapeCross                    = 7,
 204.473 -    icMaxEnumSpot                       = 0xFFFFFFFFL
 204.474 -} icSpotShape;
 204.475 -
 204.476 -/* Standard Observer, used in the measurmentType tag */
 204.477 -typedef enum {
 204.478 -    icStdObsUnknown                     = 0x00000000L,  /* Unknown */
 204.479 -    icStdObs1931TwoDegrees              = 0x00000001L,  /* 2 deg */
 204.480 -    icStdObs1964TenDegrees              = 0x00000002L,  /* 10 deg */
 204.481 -    icMaxStdObs                         = 0xFFFFFFFFL
 204.482 -} icStandardObserver;
 204.483 -
 204.484 -/* Pre-defined illuminants, used in measurement and viewing conditions type */
 204.485 -typedef enum {
 204.486 -    icIlluminantUnknown                 = 0x00000000L,
 204.487 -    icIlluminantD50                     = 0x00000001L,
 204.488 -    icIlluminantD65                     = 0x00000002L,
 204.489 -    icIlluminantD93                     = 0x00000003L,
 204.490 -    icIlluminantF2                      = 0x00000004L,
 204.491 -    icIlluminantD55                     = 0x00000005L,
 204.492 -    icIlluminantA                       = 0x00000006L,
 204.493 -    icIlluminantEquiPowerE              = 0x00000007L,
 204.494 -    icIlluminantF8                      = 0x00000008L,
 204.495 -    icMaxEnumIluminant                  = 0xFFFFFFFFL
 204.496 -} icIlluminant;
 204.497 -
 204.498 -
 204.499 -/*------------------------------------------------------------------------*/
 204.500 -/*
 204.501 - * Arrays of numbers
 204.502 - */
 204.503 -
 204.504 -/* Int8 Array */
 204.505 -typedef struct {
 204.506 -    icInt8Number        data[icAny];    /* Variable array of values */
 204.507 -} icInt8Array;
 204.508 -
 204.509 -/* UInt8 Array */
 204.510 -typedef struct {
 204.511 -    icUInt8Number       data[icAny];    /* Variable array of values */
 204.512 -} icUInt8Array;
 204.513 -
 204.514 -/* uInt16 Array */
 204.515 -typedef struct {
 204.516 -    icUInt16Number      data[icAny];    /* Variable array of values */
 204.517 -} icUInt16Array;
 204.518 -
 204.519 -/* Int16 Array */
 204.520 -typedef struct {
 204.521 -    icInt16Number       data[icAny];    /* Variable array of values */
 204.522 -} icInt16Array;
 204.523 -
 204.524 -/* uInt32 Array */
 204.525 -typedef struct {
 204.526 -    icUInt32Number      data[icAny];    /* Variable array of values */
 204.527 -} icUInt32Array;
 204.528 -
 204.529 -/* Int32 Array */
 204.530 -typedef struct {
 204.531 -    icInt32Number       data[icAny];    /* Variable array of values */
 204.532 -} icInt32Array;
 204.533 -
 204.534 -/* UInt64 Array */
 204.535 -typedef struct {
 204.536 -    icUInt64Number      data[icAny];    /* Variable array of values */
 204.537 -} icUInt64Array;
 204.538 -
 204.539 -/* Int64 Array */
 204.540 -typedef struct {
 204.541 -    icInt64Number       data[icAny];    /* Variable array of values */
 204.542 -} icInt64Array;
 204.543 -
 204.544 -/* u16Fixed16 Array */
 204.545 -typedef struct {
 204.546 -    icU16Fixed16Number  data[icAny];    /* Variable array of values */
 204.547 -} icU16Fixed16Array;
 204.548 -
 204.549 -/* s15Fixed16 Array */
 204.550 -typedef struct {
 204.551 -    icS15Fixed16Number  data[icAny];    /* Variable array of values */
 204.552 -} icS15Fixed16Array;
 204.553 -
 204.554 -/* The base date time number */
 204.555 -typedef struct {
 204.556 -    icUInt16Number      year;
 204.557 -    icUInt16Number      month;
 204.558 -    icUInt16Number      day;
 204.559 -    icUInt16Number      hours;
 204.560 -    icUInt16Number      minutes;
 204.561 -    icUInt16Number      seconds;
 204.562 -} icDateTimeNumber;
 204.563 -
 204.564 -/* XYZ Number  */
 204.565 -typedef struct {
 204.566 -    icS15Fixed16Number  X;
 204.567 -    icS15Fixed16Number  Y;
 204.568 -    icS15Fixed16Number  Z;
 204.569 -} icXYZNumber;
 204.570 -
 204.571 -/* XYZ Array */
 204.572 -typedef struct {
 204.573 -    icXYZNumber         data[icAny];    /* Variable array of XYZ numbers */
 204.574 -} icXYZArray;
 204.575 -
 204.576 -/* Curve */
 204.577 -typedef struct {
 204.578 -    icUInt32Number      count;          /* Number of entries */
 204.579 -    icUInt16Number      data[icAny];    /* The actual table data, real
 204.580 -                                         * number is determined by count
 204.581 -                                         * Interpretation depends on how
 204.582 -                                         * data is used with a given tag
 204.583 -                                         */
 204.584 -} icCurve;
 204.585 -
 204.586 -/* Data */
 204.587 -typedef struct {
 204.588 -    icUInt32Number      dataFlag;       /* 0 = ascii, 1 = binary */
 204.589 -    icInt8Number        data[icAny];    /* Data, size from tag */
 204.590 -} icData;
 204.591 -
 204.592 -/* lut16 */
 204.593 -typedef struct {
 204.594 -    icUInt8Number       inputChan;      /* Number of input channels */
 204.595 -    icUInt8Number       outputChan;     /* Number of output channels */
 204.596 -    icUInt8Number       clutPoints;     /* Number of grid points */
 204.597 -    icInt8Number        pad;            /* Padding for byte alignment */
 204.598 -    icS15Fixed16Number  e00;            /* e00 in the 3 * 3 */
 204.599 -    icS15Fixed16Number  e01;            /* e01 in the 3 * 3 */
 204.600 -    icS15Fixed16Number  e02;            /* e02 in the 3 * 3 */
 204.601 -    icS15Fixed16Number  e10;            /* e10 in the 3 * 3 */
 204.602 -    icS15Fixed16Number  e11;            /* e11 in the 3 * 3 */
 204.603 -    icS15Fixed16Number  e12;            /* e12 in the 3 * 3 */
 204.604 -    icS15Fixed16Number  e20;            /* e20 in the 3 * 3 */
 204.605 -    icS15Fixed16Number  e21;            /* e21 in the 3 * 3 */
 204.606 -    icS15Fixed16Number  e22;            /* e22 in the 3 * 3 */
 204.607 -    icUInt16Number      inputEnt;       /* Num of in-table entries */
 204.608 -    icUInt16Number      outputEnt;      /* Num of out-table entries */
 204.609 -    icUInt16Number      data[icAny];    /* Data follows see spec */
 204.610 -/*
 204.611 - *  Data that follows is of this form
 204.612 - *
 204.613 - *  icUInt16Number      inputTable[inputChan][icAny];   * The in-table
 204.614 - *  icUInt16Number      clutTable[icAny];               * The clut
 204.615 - *  icUInt16Number      outputTable[outputChan][icAny]; * The out-table
 204.616 - */
 204.617 -} icLut16;
 204.618 -
 204.619 -/* lut8, input & output tables are always 256 bytes in length */
 204.620 -typedef struct {
 204.621 -    icUInt8Number       inputChan;      /* Num of input channels */
 204.622 -    icUInt8Number       outputChan;     /* Num of output channels */
 204.623 -    icUInt8Number       clutPoints;     /* Num of grid points */
 204.624 -    icInt8Number        pad;
 204.625 -    icS15Fixed16Number  e00;            /* e00 in the 3 * 3 */
 204.626 -    icS15Fixed16Number  e01;            /* e01 in the 3 * 3 */
 204.627 -    icS15Fixed16Number  e02;            /* e02 in the 3 * 3 */
 204.628 -    icS15Fixed16Number  e10;            /* e10 in the 3 * 3 */
 204.629 -    icS15Fixed16Number  e11;            /* e11 in the 3 * 3 */
 204.630 -    icS15Fixed16Number  e12;            /* e12 in the 3 * 3 */
 204.631 -    icS15Fixed16Number  e20;            /* e20 in the 3 * 3 */
 204.632 -    icS15Fixed16Number  e21;            /* e21 in the 3 * 3 */
 204.633 -    icS15Fixed16Number  e22;            /* e22 in the 3 * 3 */
 204.634 -    icUInt8Number       data[icAny];    /* Data follows see spec */
 204.635 -/*
 204.636 - *  Data that follows is of this form
 204.637 - *
 204.638 - *  icUInt8Number       inputTable[inputChan][256];     * The in-table
 204.639 - *  icUInt8Number       clutTable[icAny];               * The clut
 204.640 - *  icUInt8Number       outputTable[outputChan][256];   * The out-table
 204.641 - */
 204.642 -} icLut8;
 204.643 -
 204.644 -/* Measurement Data */
 204.645 -typedef struct {
 204.646 -    icStandardObserver          stdObserver;    /* Standard observer */
 204.647 -    icXYZNumber                 backing;        /* XYZ for backing */
 204.648 -    icMeasurementGeometry       geometry;       /* Meas. geometry */
 204.649 -    icMeasurementFlare          flare;          /* Measurement flare */
 204.650 -    icIlluminant                illuminant;     /* Illuminant */
 204.651 -} icMeasurement;
 204.652 -
 204.653 -/* Named color */
 204.654 -
 204.655 -/*
 204.656 - * icNamedColor2 takes the place of icNamedColor
 204.657 - */
 204.658 -typedef struct {
 204.659 -    icUInt32Number      vendorFlag;     /* Bottom 16 bits for IC use */
 204.660 -    icUInt32Number      count;          /* Count of named colors */
 204.661 -    icUInt32Number      nDeviceCoords;  /* Num of device coordinates */
 204.662 -    icInt8Number        prefix[32];     /* Prefix for each color name */
 204.663 -    icInt8Number        suffix[32];     /* Suffix for each color name */
 204.664 -    icInt8Number        data[icAny];    /* Named color data follows */
 204.665 -/*
 204.666 - *  Data that follows is of this form
 204.667 - *
 204.668 - * icInt8Number         root1[32];              * Root name for 1st color
 204.669 - * icUInt16Number       pcsCoords1[icAny];      * PCS coords of 1st color
 204.670 - * icUInt16Number       deviceCoords1[icAny];   * Dev coords of 1st color
 204.671 - * icInt8Number         root2[32];              * Root name for 2nd color
 204.672 - * icUInt16Number       pcsCoords2[icAny];      * PCS coords of 2nd color
 204.673 - * icUInt16Number       deviceCoords2[icAny];   * Dev coords of 2nd color
 204.674 - *                      :
 204.675 - *                      :
 204.676 - * Repeat for name and PCS and device color coordinates up to (count-1)
 204.677 - *
 204.678 - * NOTES:
 204.679 - * PCS and device space can be determined from the header.
 204.680 - *
 204.681 - * PCS coordinates are icUInt16 numbers and are described in Annex A of
 204.682 - * the ICC spec. Only 16 bit L*a*b* and XYZ are allowed. The number of
 204.683 - * coordinates is consistent with the headers PCS.
 204.684 - *
 204.685 - * Device coordinates are icUInt16 numbers where 0x0000 represents
 204.686 - * the minimum value and 0xFFFF represents the maximum value.
 204.687 - * If the nDeviceCoords value is 0 this field is not given.
 204.688 - */
 204.689 -} icNamedColor2;
 204.690 -
 204.691 -/* Profile sequence structure */
 204.692 -typedef struct {
 204.693 -    icSignature                 deviceMfg;      /* Dev Manufacturer */
 204.694 -    icSignature                 deviceModel;    /* Dev Model */
 204.695 -    icUInt64Number              attributes;     /* Dev attributes */
 204.696 -    icTechnologySignature       technology;     /* Technology sig */
 204.697 -    icInt8Number                data[icAny];    /* Desc text follows */
 204.698 -/*
 204.699 - *  Data that follows is of this form, this is an icInt8Number
 204.700 - *  to avoid problems with a compiler generating  bad code as
 204.701 - *  these arrays are variable in length.
 204.702 - *
 204.703 - * icTextDescription            deviceMfgDesc;  * Manufacturer text
 204.704 - * icTextDescription            modelDesc;      * Model text
 204.705 - */
 204.706 -} icDescStruct;
 204.707 -
 204.708 -/* Profile sequence description */
 204.709 -typedef struct {
 204.710 -    icUInt32Number      count;          /* Number of descriptions */
 204.711 -    icUInt8Number       data[icAny];    /* Array of desc structs */
 204.712 -} icProfileSequenceDesc;
 204.713 -
 204.714 -/* textDescription */
 204.715 -typedef struct {
 204.716 -    icUInt32Number      count;          /* Description length */
 204.717 -    icInt8Number        data[icAny];    /* Descriptions follow */
 204.718 -/*
 204.719 - *  Data that follows is of this form
 204.720 - *
 204.721 - * icInt8Number         desc[count]     * NULL terminated ascii string
 204.722 - * icUInt32Number       ucLangCode;     * UniCode language code
 204.723 - * icUInt32Number       ucCount;        * UniCode description length
 204.724 - * icInt16Number        ucDesc[ucCount];* The UniCode description
 204.725 - * icUInt16Number       scCode;         * ScriptCode code
 204.726 - * icUInt8Number        scCount;        * ScriptCode count
 204.727 - * icInt8Number         scDesc[67];     * ScriptCode Description
 204.728 - */
 204.729 -} icTextDescription;
 204.730 -
 204.731 -/* Screening Data */
 204.732 -typedef struct {
 204.733 -    icS15Fixed16Number  frequency;      /* Frequency */
 204.734 -    icS15Fixed16Number  angle;          /* Screen angle */
 204.735 -    icSpotShape         spotShape;      /* Spot Shape encodings below */
 204.736 -} icScreeningData;
 204.737 -
 204.738 -typedef struct {
 204.739 -    icUInt32Number      screeningFlag;  /* Screening flag */
 204.740 -    icUInt32Number      channels;       /* Number of channels */
 204.741 -    icScreeningData     data[icAny];    /* Array of screening data */
 204.742 -} icScreening;
 204.743 -
 204.744 -/* Text Data */
 204.745 -typedef struct {
 204.746 -    icInt8Number        data[icAny];    /* Variable array of chars */
 204.747 -} icText;
 204.748 -
 204.749 -/* Structure describing either a UCR or BG curve */
 204.750 -typedef struct {
 204.751 -    icUInt32Number      count;          /* Curve length */
 204.752 -    icUInt16Number      curve[icAny];   /* The array of curve values */
 204.753 -} icUcrBgCurve;
 204.754 -
 204.755 -/* Under color removal, black generation */
 204.756 -typedef struct {
 204.757 -    icInt8Number        data[icAny];            /* The Ucr BG data */
 204.758 -/*
 204.759 - *  Data that follows is of this form, this is a icInt8Number
 204.760 - *  to avoid problems with a compiler generating  bad code as
 204.761 - *  these arrays are variable in length.
 204.762 - *
 204.763 - * icUcrBgCurve         ucr;            * Ucr curve
 204.764 - * icUcrBgCurve         bg;             * Bg curve
 204.765 - * icInt8Number         string;         * UcrBg description
 204.766 - */
 204.767 -} icUcrBg;
 204.768 -
 204.769 -/* viewingConditionsType */
 204.770 -typedef struct {
 204.771 -    icXYZNumber         illuminant;     /* In candelas per sq. meter */
 204.772 -    icXYZNumber         surround;       /* In candelas per sq. meter */
 204.773 -    icIlluminant        stdIluminant;   /* See icIlluminant defines */
 204.774 -} icViewingCondition;
 204.775 -
 204.776 -/* CrdInfo type */
 204.777 -typedef struct {
 204.778 -    icUInt32Number      count;          /* Char count includes NULL */
 204.779 -    icInt8Number        desc[icAny];    /* Null terminated string */
 204.780 -} icCrdInfo;
 204.781 -
 204.782 -/*------------------------------------------------------------------------*/
 204.783 -/*
 204.784 - * Tag Type definitions
 204.785 - */
 204.786 -
 204.787 -/*
 204.788 - * Many of the structures contain variable length arrays. This
 204.789 - * is represented by the use of the convention.
 204.790 - *
 204.791 - *      type    data[icAny];
 204.792 - */
 204.793 -
 204.794 -/* The base part of each tag */
 204.795 -typedef struct {
 204.796 -    icTagTypeSignature  sig;            /* Signature */
 204.797 -    icInt8Number        reserved[4];    /* Reserved, set to 0 */
 204.798 -} icTagBase;
 204.799 -
 204.800 -/* curveType */
 204.801 -typedef struct {
 204.802 -    icTagBase           base;           /* Signature, "curv" */
 204.803 -    icCurve             curve;          /* The curve data */
 204.804 -} icCurveType;
 204.805 -
 204.806 -/* dataType */
 204.807 -typedef struct {
 204.808 -    icTagBase           base;           /* Signature, "data" */
 204.809 -    icData              data;           /* The data structure */
 204.810 -} icDataType;
 204.811 -
 204.812 -/* dateTimeType */
 204.813 -typedef struct {
 204.814 -    icTagBase           base;           /* Signature, "dtim" */
 204.815 -    icDateTimeNumber    date;           /* The date */
 204.816 -} icDateTimeType;
 204.817 -
 204.818 -/* lut16Type */
 204.819 -typedef struct {
 204.820 -    icTagBase           base;           /* Signature, "mft2" */
 204.821 -    icLut16             lut;            /* Lut16 data */
 204.822 -} icLut16Type;
 204.823 -
 204.824 -/* lut8Type, input & output tables are always 256 bytes in length */
 204.825 -typedef struct {
 204.826 -    icTagBase           base;           /* Signature, "mft1" */
 204.827 -    icLut8              lut;            /* Lut8 data */
 204.828 -} icLut8Type;
 204.829 -
 204.830 -/* Measurement Type */
 204.831 -typedef struct {
 204.832 -    icTagBase           base;           /* Signature, "meas" */
 204.833 -    icMeasurement       measurement;    /* Measurement data */
 204.834 -} icMeasurementType;
 204.835 -
 204.836 -/* Named color type */
 204.837 -/* icNamedColor2Type, replaces icNamedColorType */
 204.838 -typedef struct {
 204.839 -    icTagBase           base;           /* Signature, "ncl2" */
 204.840 -    icNamedColor2       ncolor;         /* Named color data */
 204.841 -} icNamedColor2Type;
 204.842 -
 204.843 -/* Profile sequence description type */
 204.844 -typedef struct {
 204.845 -    icTagBase                   base;   /* Signature, "pseq" */
 204.846 -    icProfileSequenceDesc       desc;   /* The seq description */
 204.847 -} icProfileSequenceDescType;
 204.848 -
 204.849 -/* textDescriptionType */
 204.850 -typedef struct {
 204.851 -    icTagBase                   base;   /* Signature, "desc" */
 204.852 -    icTextDescription           desc;   /* The description */
 204.853 -} icTextDescriptionType;
 204.854 -
 204.855 -/* s15Fixed16Type */
 204.856 -typedef struct {
 204.857 -    icTagBase           base;           /* Signature, "sf32" */
 204.858 -    icS15Fixed16Array   data;           /* Array of values */
 204.859 -} icS15Fixed16ArrayType;
 204.860 -
 204.861 -typedef struct {
 204.862 -    icTagBase           base;           /* Signature, "scrn" */
 204.863 -    icScreening         screen;         /* Screening structure */
 204.864 -} icScreeningType;
 204.865 -
 204.866 -/* sigType */
 204.867 -typedef struct {
 204.868 -    icTagBase           base;           /* Signature, "sig" */
 204.869 -    icSignature         signature;      /* The signature data */
 204.870 -} icSignatureType;
 204.871 -
 204.872 -/* textType */
 204.873 -typedef struct {
 204.874 -    icTagBase           base;           /* Signature, "text" */
 204.875 -    icText              data;           /* Variable array of chars */
 204.876 -} icTextType;
 204.877 -
 204.878 -/* u16Fixed16Type */
 204.879 -typedef struct {
 204.880 -    icTagBase           base;           /* Signature, "uf32" */
 204.881 -    icU16Fixed16Array   data;           /* Variable array of values */
 204.882 -} icU16Fixed16ArrayType;
 204.883 -
 204.884 -/* Under color removal, black generation type */
 204.885 -typedef struct {
 204.886 -    icTagBase           base;           /* Signature, "bfd " */
 204.887 -    icUcrBg             data;           /* ucrBg structure */
 204.888 -} icUcrBgType;
 204.889 -
 204.890 -/* uInt16Type */
 204.891 -typedef struct {
 204.892 -    icTagBase           base;           /* Signature, "ui16" */
 204.893 -    icUInt16Array       data;           /* Variable array of values */
 204.894 -} icUInt16ArrayType;
 204.895 -
 204.896 -/* uInt32Type */
 204.897 -typedef struct {
 204.898 -    icTagBase           base;           /* Signature, "ui32" */
 204.899 -    icUInt32Array       data;           /* Variable array of values */
 204.900 -} icUInt32ArrayType;
 204.901 -
 204.902 -/* uInt64Type */
 204.903 -typedef struct {
 204.904 -    icTagBase           base;           /* Signature, "ui64" */
 204.905 -    icUInt64Array       data;           /* Variable array of values */
 204.906 -} icUInt64ArrayType;
 204.907 -
 204.908 -/* uInt8Type */
 204.909 -typedef struct {
 204.910 -    icTagBase           base;           /* Signature, "ui08" */
 204.911 -    icUInt8Array        data;           /* Variable array of values */
 204.912 -} icUInt8ArrayType;
 204.913 -
 204.914 -/* viewingConditionsType */
 204.915 -typedef struct {
 204.916 -    icTagBase           base;           /* Signature, "view" */
 204.917 -    icViewingCondition  view;           /* Viewing conditions */
 204.918 -} icViewingConditionType;
 204.919 -
 204.920 -/* XYZ Type */
 204.921 -typedef struct {
 204.922 -    icTagBase           base;           /* Signature, "XYZ" */
 204.923 -    icXYZArray          data;           /* Variable array of XYZ nums */
 204.924 -} icXYZType;
 204.925 -
 204.926 -/* CRDInfoType where [0] is the CRD product name count and string and
 204.927 - * [1] -[5] are the rendering intents 0-4 counts and strings
 204.928 - */
 204.929 -typedef struct {
 204.930 -    icTagBase           base;           /* Signature, "crdi" */
 204.931 -    icCrdInfo           info;           /* 5 sets of counts & strings */
 204.932 -}icCrdInfoType;
 204.933 -     /*   icCrdInfo       productName;     PS product count/string */
 204.934 -     /*   icCrdInfo       CRDName0;        CRD name for intent 0 */
 204.935 -     /*   icCrdInfo       CRDName1;        CRD name for intent 1 */
 204.936 -     /*   icCrdInfo       CRDName2;        CRD name for intent 2 */
 204.937 -     /*   icCrdInfo       CRDName3;        CRD name for intent 3 */
 204.938 -
 204.939 -/*------------------------------------------------------------------------*/
 204.940 -
 204.941 -/*
 204.942 - * Lists of tags, tags, profile header and profile structure
 204.943 - */
 204.944 -
 204.945 -/* A tag */
 204.946 -typedef struct {
 204.947 -    icTagSignature      sig;            /* The tag signature */
 204.948 -    icUInt32Number      offset;         /* Start of tag relative to
 204.949 -                                         * start of header, Spec
 204.950 -                                         * Clause 5 */
 204.951 -    icUInt32Number      size;           /* Size in bytes */
 204.952 -} icTag;
 204.953 -
 204.954 -/* A Structure that may be used independently for a list of tags */
 204.955 -typedef struct {
 204.956 -    icUInt32Number      count;          /* Num tags in the profile */
 204.957 -    icTag               tags[icAny];    /* Variable array of tags */
 204.958 -} icTagList;
 204.959 -
 204.960 -/* The Profile header */
 204.961 -typedef struct {
 204.962 -    icUInt32Number              size;           /* Prof size in bytes */
 204.963 -    icSignature                 cmmId;          /* CMM for profile */
 204.964 -    icUInt32Number              version;        /* Format version */
 204.965 -    icProfileClassSignature     deviceClass;    /* Type of profile */
 204.966 -    icColorSpaceSignature       colorSpace;     /* Clr space of data */
 204.967 -    icColorSpaceSignature       pcs;            /* PCS, XYZ or Lab */
 204.968 -    icDateTimeNumber            date;           /* Creation Date */
 204.969 -    icSignature                 magic;          /* icMagicNumber */
 204.970 -    icPlatformSignature         platform;       /* Primary Platform */
 204.971 -    icUInt32Number              flags;          /* Various bits */
 204.972 -    icSignature                 manufacturer;   /* Dev manufacturer */
 204.973 -    icUInt32Number              model;          /* Dev model number */
 204.974 -    icUInt64Number              attributes;     /* Device attributes */
 204.975 -    icUInt32Number              renderingIntent;/* Rendering intent */
 204.976 -    icXYZNumber                 illuminant;     /* Profile illuminant */
 204.977 -    icSignature                 creator;        /* Profile creator */
 204.978 -    icInt8Number                reserved[44];   /* Reserved */
 204.979 -} icHeader;
 204.980 -
 204.981 -/*
 204.982 - * A profile,
 204.983 - * we can't use icTagList here because its not at the end of the structure
 204.984 - */
 204.985 -typedef struct {
 204.986 -    icHeader            header;         /* The header */
 204.987 -    icUInt32Number      count;          /* Num tags in the profile */
 204.988 -    icInt8Number        data[icAny];    /* The tagTable and tagData */
 204.989 -/*
 204.990 - * Data that follows is of the form
 204.991 - *
 204.992 - * icTag        tagTable[icAny];        * The tag table
 204.993 - * icInt8Number tagData[icAny];         * The tag data
 204.994 - */
 204.995 -} icProfile;
 204.996 -
 204.997 -/*------------------------------------------------------------------------*/
 204.998 -/* Obsolete entries */
 204.999 -
204.1000 -/* icNamedColor was replaced with icNamedColor2 */
204.1001 -typedef struct {
204.1002 -    icUInt32Number      vendorFlag;     /* Bottom 16 bits for IC use */
204.1003 -    icUInt32Number      count;          /* Count of named colors */
204.1004 -    icInt8Number        data[icAny];    /* Named color data follows */
204.1005 -/*
204.1006 - *  Data that follows is of this form
204.1007 - *
204.1008 - * icInt8Number         prefix[icAny];  * Prefix
204.1009 - * icInt8Number         suffix[icAny];  * Suffix
204.1010 - * icInt8Number         root1[icAny];   * Root name
204.1011 - * icInt8Number         coords1[icAny]; * Color coordinates
204.1012 - * icInt8Number         root2[icAny];   * Root name
204.1013 - * icInt8Number         coords2[icAny]; * Color coordinates
204.1014 - *                      :
204.1015 - *                      :
204.1016 - * Repeat for root name and color coordinates up to (count-1)
204.1017 - */
204.1018 -} icNamedColor;
204.1019 -
204.1020 -/* icNamedColorType was replaced by icNamedColor2Type */
204.1021 -typedef struct {
204.1022 -    icTagBase           base;           /* Signature, "ncol" */
204.1023 -    icNamedColor        ncolor;         /* Named color data */
204.1024 -} icNamedColorType;
204.1025 -
204.1026 -#endif /* ICC_H */
   205.1 --- a/src/share/native/sun/java2d/cmm/lcms/lcms.h	Thu Sep 23 17:33:40 2010 -0700
   205.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   205.3 @@ -1,2099 +0,0 @@
   205.4 -/*
   205.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   205.6 - *
   205.7 - * This code is free software; you can redistribute it and/or modify it
   205.8 - * under the terms of the GNU General Public License version 2 only, as
   205.9 - * published by the Free Software Foundation.  Oracle designates this
  205.10 - * particular file as subject to the "Classpath" exception as provided
  205.11 - * by Oracle in the LICENSE file that accompanied this code.
  205.12 - *
  205.13 - * This code is distributed in the hope that it will be useful, but WITHOUT
  205.14 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  205.15 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  205.16 - * version 2 for more details (a copy is included in the LICENSE file that
  205.17 - * accompanied this code).
  205.18 - *
  205.19 - * You should have received a copy of the GNU General Public License version
  205.20 - * 2 along with this work; if not, write to the Free Software Foundation,
  205.21 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  205.22 - *
  205.23 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  205.24 - * or visit www.oracle.com if you need additional information or have any
  205.25 - * questions.
  205.26 - */
  205.27 -
  205.28 -// This file is available under and governed by the GNU General Public
  205.29 -// License version 2 only, as published by the Free Software Foundation.
  205.30 -// However, the following notice accompanied the original version of this
  205.31 -// file:
  205.32 -//
  205.33 -//
  205.34 -//  Little cms
  205.35 -//  Copyright (C) 1998-2007 Marti Maria
  205.36 -//
  205.37 -// Permission is hereby granted, free of charge, to any person obtaining
  205.38 -// a copy of this software and associated documentation files (the "Software"),
  205.39 -// to deal in the Software without restriction, including without limitation
  205.40 -// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  205.41 -// and/or sell copies of the Software, and to permit persons to whom the Software
  205.42 -// is furnished to do so, subject to the following conditions:
  205.43 -//
  205.44 -// The above copyright notice and this permission notice shall be included in
  205.45 -// all copies or substantial portions of the Software.
  205.46 -//
  205.47 -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  205.48 -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  205.49 -// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  205.50 -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  205.51 -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  205.52 -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  205.53 -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  205.54 -
  205.55 -// Version 1.18
  205.56 -
  205.57 -#ifndef __cms_H
  205.58 -
  205.59 -// ********** Configuration toggles ****************************************
  205.60 -
  205.61 -//   Optimization mode.
  205.62 -//
  205.63 -// Note that USE_ASSEMBLER Is fastest by far, but it is limited to Pentium.
  205.64 -// USE_FLOAT are the generic floating-point routines. USE_C should work on
  205.65 -// virtually any machine.
  205.66 -
  205.67 -//#define USE_FLOAT        1
  205.68 -// #define USE_C            1
  205.69 -#define USE_ASSEMBLER    1
  205.70 -
  205.71 -// Define this if you are using this package as a DLL (windows only)
  205.72 -
  205.73 -// #define LCMS_DLL     1
  205.74 -// #define LCMS_DLL_BUILD   1
  205.75 -
  205.76 -// Uncomment if you are trying the engine in a non-windows environment
  205.77 -// like linux, SGI, VAX, FreeBSD, BeOS, etc.
  205.78 -#define NON_WINDOWS  1
  205.79 -
  205.80 -// Uncomment this one if you are using big endian machines (only meaningful
  205.81 -// when NON_WINDOWS is used)
  205.82 -// #define USE_BIG_ENDIAN   1
  205.83 -
  205.84 -// Uncomment this one if your compiler/machine does support the
  205.85 -// "long long" type This will speedup fixed point math. (USE_C only)
  205.86 -#define USE_INT64        1
  205.87 -
  205.88 -// Some machines does not have a reliable 'swab' function. Usually
  205.89 -// leave commented unless the testbed diagnoses the contrary.
  205.90 -// #define USE_CUSTOM_SWAB   1
  205.91 -
  205.92 -// Uncomment this if your compiler supports inline
  205.93 -#define USE_INLINE  1
  205.94 -
  205.95 -// Uncomment this if your compiler doesn't work with fast floor function
  205.96 -// #define USE_DEFAULT_FLOOR_CONVERSION  1
  205.97 -
  205.98 -// Uncomment this line on multithreading environments
  205.99 -// #define USE_PTHREADS    1
 205.100 -
 205.101 -// Uncomment this line if you want lcms to use the black point tag in profile,
 205.102 -// if commented, lcms will compute the black point by its own.
 205.103 -// It is safer to leve it commented out
 205.104 -// #define HONOR_BLACK_POINT_TAG    1
 205.105 -
 205.106 -// ********** End of configuration toggles ******************************
 205.107 -
 205.108 -#define LCMS_VERSION        118
 205.109 -
 205.110 -// Microsoft VisualC++
 205.111 -
 205.112 -// Deal with Microsoft's attempt at deprecating C standard runtime functions
 205.113 -#ifdef _MSC_VER
 205.114 -#    undef NON_WINDOWS
 205.115 -#    if (_MSC_VER >= 1400)
 205.116 -#      ifndef _CRT_SECURE_NO_DEPRECATE
 205.117 -#        define _CRT_SECURE_NO_DEPRECATE 1
 205.118 -#      endif
 205.119 -#    endif
 205.120 -#endif
 205.121 -
 205.122 -// Borland C
 205.123 -
 205.124 -#ifdef __BORLANDC__
 205.125 -#    undef NON_WINDOWS
 205.126 -#endif
 205.127 -
 205.128 -#include <stdio.h>
 205.129 -#include <stdlib.h>
 205.130 -#include <math.h>
 205.131 -#include <assert.h>
 205.132 -#include <stdarg.h>
 205.133 -#include <time.h>
 205.134 -
 205.135 -// Metroworks CodeWarrior
 205.136 -#ifdef __MWERKS__
 205.137 -#   define unlink remove
 205.138 -#   if WIN32
 205.139 -#       define USE_CUSTOM_SWAB 1
 205.140 -#       undef  NON_WINDOWS
 205.141 -#   else
 205.142 -#       define NON_WINDOWS   1
 205.143 -#   endif
 205.144 -#endif
 205.145 -
 205.146 -
 205.147 -// Here comes the Non-Windows settings
 205.148 -
 205.149 -#ifdef NON_WINDOWS
 205.150 -
 205.151 -// Non windows environments. Also avoid indentation on includes.
 205.152 -
 205.153 -#ifdef USE_PTHREADS
 205.154 -#   include <pthread.h>
 205.155 -typedef    pthread_rwlock_t      LCMS_RWLOCK_T;
 205.156 -#   define LCMS_CREATE_LOCK(x)       pthread_rwlock_init((x), NULL)
 205.157 -#   define LCMS_FREE_LOCK(x)         pthread_rwlock_destroy((x))
 205.158 -#   define LCMS_READ_LOCK(x)             pthread_rwlock_rdlock((x))
 205.159 -#   define LCMS_WRITE_LOCK(x)        pthread_rwlock_wrlock((x))
 205.160 -#   define LCMS_UNLOCK(x)            pthread_rwlock_unlock((x))
 205.161 -#endif
 205.162 -
 205.163 -#undef LCMS_DLL
 205.164 -
 205.165 -#ifdef  USE_ASSEMBLER
 205.166 -#  undef  USE_ASSEMBLER
 205.167 -#  define USE_C               1
 205.168 -#endif
 205.169 -
 205.170 -#ifdef _HOST_BIG_ENDIAN
 205.171 -#   define USE_BIG_ENDIAN      1
 205.172 -#endif
 205.173 -
 205.174 -#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc) || defined(__ppc__) || defined(__s390__) || defined(__s390x__)
 205.175 -#   define USE_BIG_ENDIAN      1
 205.176 -#endif
 205.177 -
 205.178 -#if TARGET_CPU_PPC
 205.179 -#   define USE_BIG_ENDIAN   1
 205.180 -#endif
 205.181 -
 205.182 -#if macintosh
 205.183 -# ifndef __LITTLE_ENDIAN__
 205.184 -#   define USE_BIG_ENDIAN      1
 205.185 -# endif
 205.186 -#endif
 205.187 -
 205.188 -#ifdef __BIG_ENDIAN__
 205.189 -#   define USE_BIG_ENDIAN      1
 205.190 -#endif
 205.191 -
 205.192 -#ifdef WORDS_BIGENDIAN
 205.193 -#   define USE_BIG_ENDIAN      1
 205.194 -#endif
 205.195 -
 205.196 -#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
 205.197 -#  include <sys/types.h>
 205.198 -#  define USE_INT64           1
 205.199 -#  define LCMSSLONGLONG       int64_t
 205.200 -#  define LCMSULONGLONG       u_int64_t
 205.201 -#endif
 205.202 -
 205.203 -#ifdef USE_INT64
 205.204 -#   ifndef LCMSULONGLONG
 205.205 -#       define LCMSULONGLONG unsigned long long
 205.206 -#       define LCMSSLONGLONG long long
 205.207 -#   endif
 205.208 -#endif
 205.209 -
 205.210 -#if !defined(__INTEGRITY)
 205.211 -#   include <memory.h>
 205.212 -#endif
 205.213 -
 205.214 -#include <string.h>
 205.215 -
 205.216 -#if defined(__GNUC__) || defined(__FreeBSD__)
 205.217 -#   include <unistd.h>
 205.218 -#endif
 205.219 -
 205.220 -#ifndef LCMS_WIN_TYPES_ALREADY_DEFINED
 205.221 -
 205.222 -typedef unsigned char BYTE, *LPBYTE;
 205.223 -typedef unsigned short WORD, *LPWORD;
 205.224 -typedef unsigned long DWORD, *LPDWORD;
 205.225 -typedef char *LPSTR;
 205.226 -typedef void *LPVOID;
 205.227 -
 205.228 -#define ZeroMemory(p,l)     memset((p),0,(l))
 205.229 -#define CopyMemory(d,s,l)   memcpy((d),(s),(l))
 205.230 -#define FAR
 205.231 -
 205.232 -#ifndef stricmp
 205.233 -#   define stricmp strcasecmp
 205.234 -#endif
 205.235 -
 205.236 -
 205.237 -#ifndef FALSE
 205.238 -#       define FALSE 0
 205.239 -#endif
 205.240 -#ifndef TRUE
 205.241 -#       define TRUE  1
 205.242 -#endif
 205.243 -
 205.244 -#define LOWORD(l)    ((WORD)(l))
 205.245 -#define HIWORD(l)    ((WORD)((DWORD)(l) >> 16))
 205.246 -
 205.247 -#ifndef MAX_PATH
 205.248 -#       define MAX_PATH     (256)
 205.249 -#endif
 205.250 -
 205.251 -#define cdecl
 205.252 -#endif
 205.253 -
 205.254 -// The specification for "inline" is section 6.7.4 of the C99 standard (ISO/IEC 9899:1999).
 205.255 -
 205.256 -#define LCMS_INLINE static inline
 205.257 -
 205.258 -#else
 205.259 -
 205.260 -// Win32 stuff
 205.261 -
 205.262 -#ifndef WIN32_LEAN_AND_MEAN
 205.263 -#  define WIN32_LEAN_AND_MEAN
 205.264 -#endif
 205.265 -
 205.266 -#include <windows.h>
 205.267 -
 205.268 -#ifdef _WIN64
 205.269 -# ifdef USE_ASSEMBLER
 205.270 -#    undef  USE_ASSEMBLER
 205.271 -#    define USE_C           1
 205.272 -# endif
 205.273 -#endif
 205.274 -
 205.275 -#ifdef  USE_INT64
 205.276 -#  ifndef LCMSULONGLONG
 205.277 -#    define LCMSULONGLONG unsigned __int64
 205.278 -#    define LCMSSLONGLONG __int64
 205.279 -#  endif
 205.280 -#endif
 205.281 -
 205.282 -// This works for both VC & BorlandC
 205.283 -#define LCMS_INLINE __inline
 205.284 -
 205.285 -#ifdef USE_PTHREADS
 205.286 -typedef CRITICAL_SECTION LCMS_RWLOCK_T;
 205.287 -#   define LCMS_CREATE_LOCK(x)       InitializeCriticalSection((x))
 205.288 -#   define LCMS_FREE_LOCK(x)         DeleteCriticalSection((x))
 205.289 -#   define LCMS_READ_LOCK(x)             EnterCriticalSection((x))
 205.290 -#   define LCMS_WRITE_LOCK(x)        EnterCriticalSection((x))
 205.291 -#   define LCMS_UNLOCK(x)            LeaveCriticalSection((x))
 205.292 -#endif
 205.293 -
 205.294 -#endif
 205.295 -
 205.296 -#ifndef USE_PTHREADS
 205.297 -typedef int LCMS_RWLOCK_T;
 205.298 -#   define LCMS_CREATE_LOCK(x)
 205.299 -#   define LCMS_FREE_LOCK(x)
 205.300 -#   define LCMS_READ_LOCK(x)
 205.301 -#   define LCMS_WRITE_LOCK(x)
 205.302 -#   define LCMS_UNLOCK(x)
 205.303 -#endif
 205.304 -
 205.305 -// Base types
 205.306 -
 205.307 -typedef int   LCMSBOOL;
 205.308 -typedef void* LCMSHANDLE;
 205.309 -
 205.310 -#include "icc34.h"          // ICC header file
 205.311 -
 205.312 -
 205.313 -// Some tag & type additions
 205.314 -
 205.315 -#define lcmsSignature                  ((icSignature)           0x6c636d73L)
 205.316 -
 205.317 -#define icSigLuvKData                  ((icColorSpaceSignature) 0x4C75764BL)  // 'LuvK'
 205.318 -
 205.319 -#define icSigHexachromeData            ((icColorSpaceSignature) 0x4d434836L)  // MCH6
 205.320 -#define icSigHeptachromeData           ((icColorSpaceSignature) 0x4d434837L)  // MCH7
 205.321 -#define icSigOctachromeData            ((icColorSpaceSignature) 0x4d434838L)  // MCH8
 205.322 -
 205.323 -#define icSigMCH5Data                  ((icColorSpaceSignature) 0x4d434835L)  // MCH5
 205.324 -#define icSigMCH6Data                  ((icColorSpaceSignature) 0x4d434836L)  // MCH6
 205.325 -#define icSigMCH7Data                  ((icColorSpaceSignature) 0x4d434837L)  // MCH7
 205.326 -#define icSigMCH8Data                  ((icColorSpaceSignature) 0x4d434838L)  // MCH8
 205.327 -#define icSigMCH9Data                  ((icColorSpaceSignature) 0x4d434839L)  // MCH9
 205.328 -#define icSigMCHAData                  ((icColorSpaceSignature) 0x4d434841L)  // MCHA
 205.329 -#define icSigMCHBData                  ((icColorSpaceSignature) 0x4d434842L)  // MCHB
 205.330 -#define icSigMCHCData                  ((icColorSpaceSignature) 0x4d434843L)  // MCHC
 205.331 -#define icSigMCHDData                  ((icColorSpaceSignature) 0x4d434844L)  // MCHD
 205.332 -#define icSigMCHEData                  ((icColorSpaceSignature) 0x4d434845L)  // MCHE
 205.333 -#define icSigMCHFData                  ((icColorSpaceSignature) 0x4d434846L)  // MCHF
 205.334 -
 205.335 -#define icSigChromaticityTag            ((icTagSignature) 0x6368726dL) // As per Addendum 2 to Spec. ICC.1:1998-09
 205.336 -#define icSigChromaticAdaptationTag     ((icTagSignature) 0x63686164L) // 'chad'
 205.337 -#define icSigColorantTableTag           ((icTagSignature) 0x636c7274L) // 'clrt'
 205.338 -#define icSigColorantTableOutTag        ((icTagSignature) 0x636c6f74L) // 'clot'
 205.339 -
 205.340 -#define icSigParametricCurveType        ((icTagTypeSignature) 0x70617261L)  // parametric (ICC 4.0)
 205.341 -#define icSigMultiLocalizedUnicodeType  ((icTagTypeSignature) 0x6D6C7563L)
 205.342 -#define icSigS15Fixed16ArrayType        ((icTagTypeSignature) 0x73663332L)
 205.343 -#define icSigChromaticityType           ((icTagTypeSignature) 0x6368726dL)
 205.344 -#define icSiglutAtoBType                ((icTagTypeSignature) 0x6d414220L)  // mAB
 205.345 -#define icSiglutBtoAType                ((icTagTypeSignature) 0x6d424120L)  // mBA
 205.346 -#define icSigColorantTableType          ((icTagTypeSignature) 0x636c7274L)  // clrt
 205.347 -
 205.348 -
 205.349 -typedef struct {
 205.350 -    icUInt8Number       gridPoints[16]; // Number of grid points in each dimension.
 205.351 -    icUInt8Number       prec;           // Precision of data elements in bytes.
 205.352 -    icUInt8Number       pad1;
 205.353 -    icUInt8Number       pad2;
 205.354 -    icUInt8Number       pad3;
 205.355 -    /*icUInt8Number     data[icAny];     Data follows see spec for size */
 205.356 -} icCLutStruct;
 205.357 -
 205.358 -// icLutAtoB
 205.359 -typedef struct {
 205.360 -    icUInt8Number       inputChan;      // Number of input channels
 205.361 -    icUInt8Number       outputChan;     // Number of output channels
 205.362 -    icUInt8Number       pad1;
 205.363 -    icUInt8Number       pad2;
 205.364 -    icUInt32Number      offsetB;        // Offset to first "B" curve
 205.365 -    icUInt32Number      offsetMat;      // Offset to matrix
 205.366 -    icUInt32Number      offsetM;        // Offset to first "M" curve
 205.367 -    icUInt32Number      offsetC;        // Offset to CLUT
 205.368 -    icUInt32Number      offsetA;        // Offset to first "A" curve
 205.369 -    /*icUInt8Number     data[icAny];     Data follows see spec for size */
 205.370 -} icLutAtoB;
 205.371 -
 205.372 -// icLutBtoA
 205.373 -typedef struct {
 205.374 -    icUInt8Number       inputChan;      // Number of input channels
 205.375 -    icUInt8Number       outputChan;     // Number of output channels
 205.376 -    icUInt8Number       pad1;
 205.377 -    icUInt8Number       pad2;
 205.378 -    icUInt32Number      offsetB;        // Offset to first "B" curve
 205.379 -    icUInt32Number      offsetMat;      // Offset to matrix
 205.380 -    icUInt32Number      offsetM;        // Offset to first "M" curve
 205.381 -    icUInt32Number      offsetC;        // Offset to CLUT
 205.382 -    icUInt32Number      offsetA;        // Offset to first "A" curve
 205.383 -    /*icUInt8Number     data[icAny];     Data follows see spec for size */
 205.384 -} icLutBtoA;
 205.385 -
 205.386 -
 205.387 -
 205.388 -
 205.389 -
 205.390 -#ifdef __cplusplus
 205.391 -extern "C" {
 205.392 -#endif
 205.393 -
 205.394 -// Calling convention
 205.395 -
 205.396 -#ifdef NON_WINDOWS
 205.397 -#  define LCMSEXPORT
 205.398 -#  define LCMSAPI
 205.399 -#else
 205.400 -# ifdef LCMS_DLL
 205.401 -#   ifdef __BORLANDC__
 205.402 -#      define LCMSEXPORT __stdcall _export
 205.403 -#      define LCMSAPI
 205.404 -#   else
 205.405 -       // VC++
 205.406 -#       define LCMSEXPORT  _stdcall
 205.407 -#       ifdef LCMS_DLL_BUILD
 205.408 -#           define LCMSAPI     __declspec(dllexport)
 205.409 -#       else
 205.410 -#           define LCMSAPI     __declspec(dllimport)
 205.411 -#       endif
 205.412 -#   endif
 205.413 -# else
 205.414 -#       define LCMSEXPORT cdecl
 205.415 -#       define LCMSAPI
 205.416 -# endif
 205.417 -#endif
 205.418 -
 205.419 -#ifdef  USE_ASSEMBLER
 205.420 -#ifdef __BORLANDC__
 205.421 -
 205.422 -#      define ASM     asm
 205.423 -#      define RET(v)  return(v)
 205.424 -#else
 205.425 -      // VC++
 205.426 -#      define ASM     __asm
 205.427 -#      define RET(v)  return
 205.428 -#endif
 205.429 -#endif
 205.430 -
 205.431 -#ifdef _MSC_VER
 205.432 -#ifndef  stricmp
 205.433 -#      define stricmp _stricmp
 205.434 -#endif
 205.435 -#ifndef unlink
 205.436 -#      define unlink  _unlink
 205.437 -#endif
 205.438 -#ifndef swab
 205.439 -#      define swab    _swab
 205.440 -#endif
 205.441 -#ifndef itoa
 205.442 -#       define itoa   _itoa
 205.443 -#endif
 205.444 -#ifndef fileno
 205.445 -#       define fileno   _fileno
 205.446 -#endif
 205.447 -#ifndef strupr
 205.448 -#       define strupr   _strupr
 205.449 -#endif
 205.450 -#ifndef hypot
 205.451 -#       define hypot    _hypot
 205.452 -#endif
 205.453 -#ifndef snprintf
 205.454 -#       define snprintf  _snprintf
 205.455 -#endif
 205.456 -#ifndef vsnprintf
 205.457 -#       define vsnprintf  _vsnprintf
 205.458 -#endif
 205.459 -
 205.460 -
 205.461 -#endif
 205.462 -
 205.463 -
 205.464 -#ifndef M_PI
 205.465 -#       define M_PI    3.14159265358979323846
 205.466 -#endif
 205.467 -
 205.468 -#ifndef LOGE
 205.469 -#       define LOGE   0.4342944819
 205.470 -#endif
 205.471 -
 205.472 -// ********** Little cms API ***************************************************
 205.473 -
 205.474 -typedef LCMSHANDLE cmsHPROFILE;        // Opaque typedefs to hide internals
 205.475 -typedef LCMSHANDLE cmsHTRANSFORM;
 205.476 -
 205.477 -#define MAXCHANNELS  16                // Maximum number of channels
 205.478 -
 205.479 -// Format of pixel is defined by one DWORD, using bit fields as follows
 205.480 -//
 205.481 -//            D TTTTT U Y F P X S EEE CCCC BBB
 205.482 -//
 205.483 -//            D: Use dither (8 bits only)
 205.484 -//            T: Pixeltype
 205.485 -//            F: Flavor  0=MinIsBlack(Chocolate) 1=MinIsWhite(Vanilla)
 205.486 -//            P: Planar? 0=Chunky, 1=Planar
 205.487 -//            X: swap 16 bps endianess?
 205.488 -//            S: Do swap? ie, BGR, KYMC
 205.489 -//            E: Extra samples
 205.490 -//            C: Channels (Samples per pixel)
 205.491 -//            B: Bytes per sample
 205.492 -//            Y: Swap first - changes ABGR to BGRA and KCMY to CMYK
 205.493 -
 205.494 -
 205.495 -#define DITHER_SH(s)           ((s) << 22)
 205.496 -#define COLORSPACE_SH(s)       ((s) << 16)
 205.497 -#define SWAPFIRST_SH(s)        ((s) << 14)
 205.498 -#define FLAVOR_SH(s)           ((s) << 13)
 205.499 -#define PLANAR_SH(p)           ((p) << 12)
 205.500 -#define ENDIAN16_SH(e)         ((e) << 11)
 205.501 -#define DOSWAP_SH(e)           ((e) << 10)
 205.502 -#define EXTRA_SH(e)            ((e) << 7)
 205.503 -#define CHANNELS_SH(c)         ((c) << 3)
 205.504 -#define BYTES_SH(b)            (b)
 205.505 -
 205.506 -// Pixel types
 205.507 -
 205.508 -#define PT_ANY       0    // Don't check colorspace
 205.509 -                          // 1 & 2 are reserved
 205.510 -#define PT_GRAY      3
 205.511 -#define PT_RGB       4
 205.512 -#define PT_CMY       5
 205.513 -#define PT_CMYK      6
 205.514 -#define PT_YCbCr     7
 205.515 -#define PT_YUV       8      // Lu'v'
 205.516 -#define PT_XYZ       9
 205.517 -#define PT_Lab       10
 205.518 -#define PT_YUVK      11     // Lu'v'K
 205.519 -#define PT_HSV       12
 205.520 -#define PT_HLS       13
 205.521 -#define PT_Yxy       14
 205.522 -#define PT_HiFi      15
 205.523 -#define PT_HiFi7     16
 205.524 -#define PT_HiFi8     17
 205.525 -#define PT_HiFi9     18
 205.526 -#define PT_HiFi10    19
 205.527 -#define PT_HiFi11    20
 205.528 -#define PT_HiFi12    21
 205.529 -#define PT_HiFi13    22
 205.530 -#define PT_HiFi14    23
 205.531 -#define PT_HiFi15    24
 205.532 -
 205.533 -#define NOCOLORSPACECHECK(x)    ((x) & 0xFFFF)
 205.534 -
 205.535 -// Some (not all!) representations
 205.536 -
 205.537 -#ifndef TYPE_RGB_8      // TYPE_RGB_8 is a very common identifier, so don't include ours
 205.538 -                        // if user has it already defined.
 205.539 -
 205.540 -#define TYPE_GRAY_8            (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(1))
 205.541 -#define TYPE_GRAY_8_REV        (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1))
 205.542 -#define TYPE_GRAY_16           (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2))
 205.543 -#define TYPE_GRAY_16_REV       (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1))
 205.544 -#define TYPE_GRAY_16_SE        (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.545 -#define TYPE_GRAYA_8           (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1))
 205.546 -#define TYPE_GRAYA_16          (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2))
 205.547 -#define TYPE_GRAYA_16_SE       (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.548 -#define TYPE_GRAYA_8_PLANAR    (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1)|PLANAR_SH(1))
 205.549 -#define TYPE_GRAYA_16_PLANAR   (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|PLANAR_SH(1))
 205.550 -
 205.551 -#define TYPE_RGB_8             (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1))
 205.552 -#define TYPE_RGB_8_PLANAR      (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 205.553 -#define TYPE_BGR_8             (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1))
 205.554 -#define TYPE_BGR_8_PLANAR      (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|PLANAR_SH(1))
 205.555 -#define TYPE_RGB_16            (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2))
 205.556 -#define TYPE_RGB_16_PLANAR     (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 205.557 -#define TYPE_RGB_16_SE         (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.558 -#define TYPE_BGR_16            (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1))
 205.559 -#define TYPE_BGR_16_PLANAR     (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PLANAR_SH(1))
 205.560 -#define TYPE_BGR_16_SE         (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.561 -
 205.562 -#define TYPE_RGBA_8            (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1))
 205.563 -#define TYPE_RGBA_8_PLANAR     (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 205.564 -#define TYPE_RGBA_16           (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
 205.565 -#define TYPE_RGBA_16_PLANAR    (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 205.566 -#define TYPE_RGBA_16_SE        (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.567 -
 205.568 -#define TYPE_ARGB_8            (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1))
 205.569 -#define TYPE_ARGB_16           (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|SWAPFIRST_SH(1))
 205.570 -
 205.571 -#define TYPE_ABGR_8            (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1))
 205.572 -#define TYPE_ABGR_16           (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1))
 205.573 -#define TYPE_ABGR_16_PLANAR    (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PLANAR_SH(1))
 205.574 -#define TYPE_ABGR_16_SE        (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.575 -
 205.576 -#define TYPE_BGRA_8            (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
 205.577 -#define TYPE_BGRA_16           (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
 205.578 -#define TYPE_BGRA_16_SE        (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)|SWAPFIRST_SH(1))
 205.579 -
 205.580 -#define TYPE_CMY_8             (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1))
 205.581 -#define TYPE_CMY_8_PLANAR      (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 205.582 -#define TYPE_CMY_16            (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2))
 205.583 -#define TYPE_CMY_16_PLANAR     (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 205.584 -#define TYPE_CMY_16_SE         (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.585 -
 205.586 -#define TYPE_CMYK_8            (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1))
 205.587 -#define TYPE_CMYKA_8           (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(1))
 205.588 -#define TYPE_CMYK_8_REV        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1))
 205.589 -#define TYPE_YUVK_8            TYPE_CMYK_8_REV
 205.590 -#define TYPE_CMYK_8_PLANAR     (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|PLANAR_SH(1))
 205.591 -#define TYPE_CMYK_16           (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2))
 205.592 -#define TYPE_CMYK_16_REV       (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1))
 205.593 -#define TYPE_YUVK_16           TYPE_CMYK_16_REV
 205.594 -#define TYPE_CMYK_16_PLANAR    (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|PLANAR_SH(1))
 205.595 -#define TYPE_CMYK_16_SE        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.596 -
 205.597 -#define TYPE_KYMC_8            (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1))
 205.598 -#define TYPE_KYMC_16           (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1))
 205.599 -#define TYPE_KYMC_16_SE        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.600 -
 205.601 -#define TYPE_KCMY_8            (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1))
 205.602 -#define TYPE_KCMY_8_REV        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1)|SWAPFIRST_SH(1))
 205.603 -#define TYPE_KCMY_16           (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1))
 205.604 -#define TYPE_KCMY_16_REV       (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1)|SWAPFIRST_SH(1))
 205.605 -#define TYPE_KCMY_16_SE        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1)|SWAPFIRST_SH(1))
 205.606 -
 205.607 -
 205.608 -// HiFi separations, Thanks to Steven Greaves for providing the code,
 205.609 -// the colorspace is not checked
 205.610 -#define TYPE_CMYK5_8           (CHANNELS_SH(5)|BYTES_SH(1))
 205.611 -#define TYPE_CMYK5_16          (CHANNELS_SH(5)|BYTES_SH(2))
 205.612 -#define TYPE_CMYK5_16_SE       (CHANNELS_SH(5)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.613 -#define TYPE_KYMC5_8           (CHANNELS_SH(5)|BYTES_SH(1)|DOSWAP_SH(1))
 205.614 -#define TYPE_KYMC5_16          (CHANNELS_SH(5)|BYTES_SH(2)|DOSWAP_SH(1))
 205.615 -#define TYPE_KYMC5_16_SE       (CHANNELS_SH(5)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.616 -
 205.617 -#define TYPE_CMYKcm_8          (CHANNELS_SH(6)|BYTES_SH(1))
 205.618 -#define TYPE_CMYKcm_8_PLANAR   (CHANNELS_SH(6)|BYTES_SH(1)|PLANAR_SH(1))
 205.619 -#define TYPE_CMYKcm_16         (CHANNELS_SH(6)|BYTES_SH(2))
 205.620 -#define TYPE_CMYKcm_16_PLANAR  (CHANNELS_SH(6)|BYTES_SH(2)|PLANAR_SH(1))
 205.621 -#define TYPE_CMYKcm_16_SE      (CHANNELS_SH(6)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.622 -
 205.623 -// Separations with more than 6 channels aren't very standarized,
 205.624 -// Except most start with CMYK and add other colors, so I just used
 205.625 -// then total number of channels after CMYK i.e CMYK8_8
 205.626 -
 205.627 -#define TYPE_CMYK7_8           (CHANNELS_SH(7)|BYTES_SH(1))
 205.628 -#define TYPE_CMYK7_16          (CHANNELS_SH(7)|BYTES_SH(2))
 205.629 -#define TYPE_CMYK7_16_SE       (CHANNELS_SH(7)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.630 -#define TYPE_KYMC7_8           (CHANNELS_SH(7)|BYTES_SH(1)|DOSWAP_SH(1))
 205.631 -#define TYPE_KYMC7_16          (CHANNELS_SH(7)|BYTES_SH(2)|DOSWAP_SH(1))
 205.632 -#define TYPE_KYMC7_16_SE       (CHANNELS_SH(7)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.633 -#define TYPE_CMYK8_8           (CHANNELS_SH(8)|BYTES_SH(1))
 205.634 -#define TYPE_CMYK8_16          (CHANNELS_SH(8)|BYTES_SH(2))
 205.635 -#define TYPE_CMYK8_16_SE       (CHANNELS_SH(8)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.636 -#define TYPE_KYMC8_8           (CHANNELS_SH(8)|BYTES_SH(1)|DOSWAP_SH(1))
 205.637 -#define TYPE_KYMC8_16          (CHANNELS_SH(8)|BYTES_SH(2)|DOSWAP_SH(1))
 205.638 -#define TYPE_KYMC8_16_SE       (CHANNELS_SH(8)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.639 -#define TYPE_CMYK9_8           (CHANNELS_SH(9)|BYTES_SH(1))
 205.640 -#define TYPE_CMYK9_16          (CHANNELS_SH(9)|BYTES_SH(2))
 205.641 -#define TYPE_CMYK9_16_SE       (CHANNELS_SH(9)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.642 -#define TYPE_KYMC9_8           (CHANNELS_SH(9)|BYTES_SH(1)|DOSWAP_SH(1))
 205.643 -#define TYPE_KYMC9_16          (CHANNELS_SH(9)|BYTES_SH(2)|DOSWAP_SH(1))
 205.644 -#define TYPE_KYMC9_16_SE       (CHANNELS_SH(9)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.645 -#define TYPE_CMYK10_8          (CHANNELS_SH(10)|BYTES_SH(1))
 205.646 -#define TYPE_CMYK10_16         (CHANNELS_SH(10)|BYTES_SH(2))
 205.647 -#define TYPE_CMYK10_16_SE      (CHANNELS_SH(10)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.648 -#define TYPE_KYMC10_8          (CHANNELS_SH(10)|BYTES_SH(1)|DOSWAP_SH(1))
 205.649 -#define TYPE_KYMC10_16         (CHANNELS_SH(10)|BYTES_SH(2)|DOSWAP_SH(1))
 205.650 -#define TYPE_KYMC10_16_SE      (CHANNELS_SH(10)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.651 -#define TYPE_CMYK11_8          (CHANNELS_SH(11)|BYTES_SH(1))
 205.652 -#define TYPE_CMYK11_16         (CHANNELS_SH(11)|BYTES_SH(2))
 205.653 -#define TYPE_CMYK11_16_SE      (CHANNELS_SH(11)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.654 -#define TYPE_KYMC11_8          (CHANNELS_SH(11)|BYTES_SH(1)|DOSWAP_SH(1))
 205.655 -#define TYPE_KYMC11_16         (CHANNELS_SH(11)|BYTES_SH(2)|DOSWAP_SH(1))
 205.656 -#define TYPE_KYMC11_16_SE      (CHANNELS_SH(11)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.657 -#define TYPE_CMYK12_8          (CHANNELS_SH(12)|BYTES_SH(1))
 205.658 -#define TYPE_CMYK12_16         (CHANNELS_SH(12)|BYTES_SH(2))
 205.659 -#define TYPE_CMYK12_16_SE      (CHANNELS_SH(12)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.660 -#define TYPE_KYMC12_8          (CHANNELS_SH(12)|BYTES_SH(1)|DOSWAP_SH(1))
 205.661 -#define TYPE_KYMC12_16         (CHANNELS_SH(12)|BYTES_SH(2)|DOSWAP_SH(1))
 205.662 -#define TYPE_KYMC12_16_SE      (CHANNELS_SH(12)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 205.663 -
 205.664 -// Colorimetric
 205.665 -
 205.666 -#define TYPE_XYZ_16            (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(2))
 205.667 -#define TYPE_Lab_8             (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1))
 205.668 -#define TYPE_ALab_8            (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1))
 205.669 -#define TYPE_Lab_16            (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(2))
 205.670 -#define TYPE_Yxy_16            (COLORSPACE_SH(PT_Yxy)|CHANNELS_SH(3)|BYTES_SH(2))
 205.671 -
 205.672 -// YCbCr
 205.673 -
 205.674 -#define TYPE_YCbCr_8           (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(1))
 205.675 -#define TYPE_YCbCr_8_PLANAR    (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 205.676 -#define TYPE_YCbCr_16          (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2))
 205.677 -#define TYPE_YCbCr_16_PLANAR   (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 205.678 -#define TYPE_YCbCr_16_SE       (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.679 -
 205.680 -// YUV
 205.681 -
 205.682 -#define TYPE_YUV_8           (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(1))
 205.683 -#define TYPE_YUV_8_PLANAR    (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 205.684 -#define TYPE_YUV_16          (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2))
 205.685 -#define TYPE_YUV_16_PLANAR   (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 205.686 -#define TYPE_YUV_16_SE       (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.687 -
 205.688 -// HLS
 205.689 -
 205.690 -#define TYPE_HLS_8           (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(1))
 205.691 -#define TYPE_HLS_8_PLANAR    (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 205.692 -#define TYPE_HLS_16          (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2))
 205.693 -#define TYPE_HLS_16_PLANAR   (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 205.694 -#define TYPE_HLS_16_SE       (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.695 -
 205.696 -
 205.697 -// HSV
 205.698 -
 205.699 -#define TYPE_HSV_8           (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(1))
 205.700 -#define TYPE_HSV_8_PLANAR    (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 205.701 -#define TYPE_HSV_16          (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2))
 205.702 -#define TYPE_HSV_16_PLANAR   (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 205.703 -#define TYPE_HSV_16_SE       (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 205.704 -
 205.705 -// Named color index. Only 16 bits allowed (don't check colorspace)
 205.706 -
 205.707 -#define TYPE_NAMED_COLOR_INDEX   (CHANNELS_SH(1)|BYTES_SH(2))
 205.708 -
 205.709 -// Double values. Painful slow, but sometimes helpful. NOTE THAT 'BYTES' FIELD IS SET TO ZERO!
 205.710 -
 205.711 -#define TYPE_XYZ_DBL        (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(0))
 205.712 -#define TYPE_Lab_DBL        (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(0))
 205.713 -#define TYPE_GRAY_DBL       (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(0))
 205.714 -#define TYPE_RGB_DBL        (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0))
 205.715 -#define TYPE_CMYK_DBL       (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(0))
 205.716 -
 205.717 -#endif
 205.718 -
 205.719 -
 205.720 -// Gamma table parameters
 205.721 -
 205.722 -typedef struct {
 205.723 -
 205.724 -    unsigned int Crc32;  // Has my table been touched?
 205.725 -
 205.726 -    // Keep initial parameters for further serialization
 205.727 -
 205.728 -    int          Type;
 205.729 -    double       Params[10];
 205.730 -
 205.731 -    }  LCMSGAMMAPARAMS, FAR* LPLCMSGAMMAPARAMS;
 205.732 -
 205.733 -// Gamma tables.
 205.734 -
 205.735 -typedef struct {
 205.736 -
 205.737 -    LCMSGAMMAPARAMS Seed;       // Parameters used for table creation
 205.738 -
 205.739 -    // Table-based representation follows
 205.740 -
 205.741 -    int  nEntries;
 205.742 -    WORD GammaTable[1];
 205.743 -
 205.744 -    } GAMMATABLE;
 205.745 -
 205.746 -typedef GAMMATABLE FAR* LPGAMMATABLE;
 205.747 -
 205.748 -// Sampled curves (1D)
 205.749 -typedef struct {
 205.750 -
 205.751 -    int     nItems;
 205.752 -    double* Values;
 205.753 -
 205.754 -    } SAMPLEDCURVE;
 205.755 -
 205.756 -typedef SAMPLEDCURVE FAR* LPSAMPLEDCURVE;
 205.757 -
 205.758 -// Vectors
 205.759 -typedef struct {                // Float Vector
 205.760 -
 205.761 -    double n[3];
 205.762 -
 205.763 -    } VEC3;
 205.764 -
 205.765 -typedef VEC3 FAR* LPVEC3;
 205.766 -
 205.767 -
 205.768 -typedef struct {                // Matrix
 205.769 -
 205.770 -    VEC3 v[3];
 205.771 -
 205.772 -    } MAT3;
 205.773 -
 205.774 -typedef MAT3 FAR* LPMAT3;
 205.775 -
 205.776 -// Colorspace values
 205.777 -typedef struct {
 205.778 -
 205.779 -        double X;
 205.780 -        double Y;
 205.781 -        double Z;
 205.782 -
 205.783 -    } cmsCIEXYZ;
 205.784 -
 205.785 -typedef cmsCIEXYZ FAR* LPcmsCIEXYZ;
 205.786 -
 205.787 -typedef struct {
 205.788 -
 205.789 -        double x;
 205.790 -        double y;
 205.791 -        double Y;
 205.792 -
 205.793 -    } cmsCIExyY;
 205.794 -
 205.795 -typedef cmsCIExyY FAR* LPcmsCIExyY;
 205.796 -
 205.797 -typedef struct {
 205.798 -
 205.799 -        double L;
 205.800 -        double a;
 205.801 -        double b;
 205.802 -
 205.803 -    } cmsCIELab;
 205.804 -
 205.805 -typedef cmsCIELab FAR* LPcmsCIELab;
 205.806 -
 205.807 -typedef struct {
 205.808 -
 205.809 -        double L;
 205.810 -        double C;
 205.811 -        double h;
 205.812 -
 205.813 -    } cmsCIELCh;
 205.814 -
 205.815 -typedef cmsCIELCh FAR* LPcmsCIELCh;
 205.816 -
 205.817 -typedef struct {
 205.818 -
 205.819 -        double J;
 205.820 -        double C;
 205.821 -        double h;
 205.822 -
 205.823 -    } cmsJCh;
 205.824 -
 205.825 -typedef cmsJCh FAR* LPcmsJCh;
 205.826 -
 205.827 -// Primaries
 205.828 -typedef struct {
 205.829 -
 205.830 -        cmsCIEXYZ  Red;
 205.831 -        cmsCIEXYZ  Green;
 205.832 -        cmsCIEXYZ  Blue;
 205.833 -
 205.834 -    } cmsCIEXYZTRIPLE;
 205.835 -
 205.836 -typedef cmsCIEXYZTRIPLE FAR* LPcmsCIEXYZTRIPLE;
 205.837 -
 205.838 -
 205.839 -typedef struct {
 205.840 -
 205.841 -        cmsCIExyY  Red;
 205.842 -        cmsCIExyY  Green;
 205.843 -        cmsCIExyY  Blue;
 205.844 -
 205.845 -    } cmsCIExyYTRIPLE;
 205.846 -
 205.847 -typedef cmsCIExyYTRIPLE FAR* LPcmsCIExyYTRIPLE;
 205.848 -
 205.849 -
 205.850 -
 205.851 -// Following ICC spec
 205.852 -
 205.853 -#define D50X  (0.9642)
 205.854 -#define D50Y  (1.0)
 205.855 -#define D50Z  (0.8249)
 205.856 -
 205.857 -#define PERCEPTUAL_BLACK_X  (0.00336)
 205.858 -#define PERCEPTUAL_BLACK_Y  (0.0034731)
 205.859 -#define PERCEPTUAL_BLACK_Z  (0.00287)
 205.860 -
 205.861 -// Does return pointers to constant structs
 205.862 -
 205.863 -LCMSAPI LPcmsCIEXYZ LCMSEXPORT cmsD50_XYZ(void);
 205.864 -LCMSAPI LPcmsCIExyY LCMSEXPORT cmsD50_xyY(void);
 205.865 -
 205.866 -
 205.867 -// Input/Output
 205.868 -
 205.869 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess);
 205.870 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize);
 205.871 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile);
 205.872 -
 205.873 -// Predefined run-time profiles
 205.874 -
 205.875 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateRGBProfile(LPcmsCIExyY WhitePoint,
 205.876 -                                        LPcmsCIExyYTRIPLE Primaries,
 205.877 -                                        LPGAMMATABLE TransferFunction[3]);
 205.878 -
 205.879 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateGrayProfile(LPcmsCIExyY WhitePoint,
 205.880 -                                              LPGAMMATABLE TransferFunction);
 205.881 -
 205.882 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateLinearizationDeviceLink(icColorSpaceSignature ColorSpace,
 205.883 -                                                        LPGAMMATABLE TransferFunctions[]);
 205.884 -
 205.885 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateInkLimitingDeviceLink(icColorSpaceSignature ColorSpace,
 205.886 -                                                      double Limit);
 205.887 -
 205.888 -
 205.889 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateLabProfile(LPcmsCIExyY WhitePoint);
 205.890 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateLab4Profile(LPcmsCIExyY WhitePoint);
 205.891 -
 205.892 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateXYZProfile(void);
 205.893 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreate_sRGBProfile(void);
 205.894 -
 205.895 -
 205.896 -
 205.897 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints,
 205.898 -                                                     double Bright,
 205.899 -                                                     double Contrast,
 205.900 -                                                     double Hue,
 205.901 -                                                     double Saturation,
 205.902 -                                                     int TempSrc,
 205.903 -                                                     int TempDest);
 205.904 -
 205.905 -LCMSAPI cmsHPROFILE   LCMSEXPORT cmsCreateNULLProfile(void);
 205.906 -
 205.907 -
 205.908 -// Colorimetric space conversions
 205.909 -
 205.910 -LCMSAPI void          LCMSEXPORT cmsXYZ2xyY(LPcmsCIExyY Dest, const cmsCIEXYZ* Source);
 205.911 -LCMSAPI void          LCMSEXPORT cmsxyY2XYZ(LPcmsCIEXYZ Dest, const cmsCIExyY* Source);
 205.912 -LCMSAPI void          LCMSEXPORT cmsXYZ2Lab(LPcmsCIEXYZ WhitePoint, LPcmsCIELab Lab, const cmsCIEXYZ* xyz);
 205.913 -LCMSAPI void          LCMSEXPORT cmsLab2XYZ(LPcmsCIEXYZ WhitePoint, LPcmsCIEXYZ xyz, const cmsCIELab* Lab);
 205.914 -LCMSAPI void          LCMSEXPORT cmsLab2LCh(LPcmsCIELCh LCh, const cmsCIELab* Lab);
 205.915 -LCMSAPI void          LCMSEXPORT cmsLCh2Lab(LPcmsCIELab Lab, const cmsCIELCh* LCh);
 205.916 -
 205.917 -
 205.918 -// CIELab handling
 205.919 -
 205.920 -LCMSAPI double        LCMSEXPORT cmsDeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2);
 205.921 -LCMSAPI double        LCMSEXPORT cmsCIE94DeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2);
 205.922 -LCMSAPI double        LCMSEXPORT cmsBFDdeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2);
 205.923 -LCMSAPI double        LCMSEXPORT cmsCMCdeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2);
 205.924 -LCMSAPI double        LCMSEXPORT cmsCIE2000DeltaE(LPcmsCIELab Lab1, LPcmsCIELab Lab2, double Kl, double Kc, double Kh);
 205.925 -
 205.926 -LCMSAPI void          LCMSEXPORT cmsClampLab(LPcmsCIELab Lab, double amax, double amin, double bmax, double bmin);
 205.927 -
 205.928 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsWhitePointFromTemp(int TempK, LPcmsCIExyY WhitePoint);
 205.929 -
 205.930 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsAdaptToIlluminant(LPcmsCIEXYZ Result,
 205.931 -                                                        LPcmsCIEXYZ SourceWhitePt,
 205.932 -                                                        LPcmsCIEXYZ Illuminant,
 205.933 -                                                        LPcmsCIEXYZ Value);
 205.934 -
 205.935 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsBuildRGB2XYZtransferMatrix(LPMAT3 r,
 205.936 -                                                        LPcmsCIExyY WhitePoint,
 205.937 -                                                        LPcmsCIExyYTRIPLE Primaries);
 205.938 -
 205.939 -// Viewing conditions
 205.940 -
 205.941 -#define AVG_SURROUND_4     0
 205.942 -#define AVG_SURROUND       1
 205.943 -#define DIM_SURROUND       2
 205.944 -#define DARK_SURROUND      3
 205.945 -#define CUTSHEET_SURROUND  4
 205.946 -
 205.947 -#define D_CALCULATE             (-1)
 205.948 -#define D_CALCULATE_DISCOUNT    (-2)
 205.949 -
 205.950 -typedef struct {
 205.951 -
 205.952 -              cmsCIEXYZ whitePoint;
 205.953 -              double    Yb;
 205.954 -              double    La;
 205.955 -              int       surround;
 205.956 -              double    D_value;
 205.957 -
 205.958 -    } cmsViewingConditions;
 205.959 -
 205.960 -typedef cmsViewingConditions FAR* LPcmsViewingConditions;
 205.961 -
 205.962 -// CIECAM97s
 205.963 -
 205.964 -LCMSAPI LCMSHANDLE    LCMSEXPORT cmsCIECAM97sInit(LPcmsViewingConditions pVC2);
 205.965 -LCMSAPI void          LCMSEXPORT cmsCIECAM97sDone(LCMSHANDLE hModel);
 205.966 -LCMSAPI void          LCMSEXPORT cmsCIECAM97sForward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh pOut);
 205.967 -LCMSAPI void          LCMSEXPORT cmsCIECAM97sReverse(LCMSHANDLE hModel, LPcmsJCh pIn,    LPcmsCIEXYZ pOut);
 205.968 -
 205.969 -
 205.970 -// CIECAM02
 205.971 -
 205.972 -LCMSAPI LCMSHANDLE    LCMSEXPORT cmsCIECAM02Init(LPcmsViewingConditions pVC);
 205.973 -LCMSAPI void          LCMSEXPORT cmsCIECAM02Done(LCMSHANDLE hModel);
 205.974 -LCMSAPI void          LCMSEXPORT cmsCIECAM02Forward(LCMSHANDLE hModel, LPcmsCIEXYZ pIn, LPcmsJCh pOut);
 205.975 -LCMSAPI void          LCMSEXPORT cmsCIECAM02Reverse(LCMSHANDLE hModel, LPcmsJCh pIn,    LPcmsCIEXYZ pOut);
 205.976 -
 205.977 -
 205.978 -// Gamma
 205.979 -
 205.980 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsBuildGamma(int nEntries, double Gamma);
 205.981 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsBuildParametricGamma(int nEntries, int Type, double Params[]);
 205.982 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsAllocGamma(int nEntries);
 205.983 -LCMSAPI void          LCMSEXPORT cmsFreeGamma(LPGAMMATABLE Gamma);
 205.984 -LCMSAPI void          LCMSEXPORT cmsFreeGammaTriple(LPGAMMATABLE Gamma[3]);
 205.985 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsDupGamma(LPGAMMATABLE Src);
 205.986 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsReverseGamma(int nResultSamples, LPGAMMATABLE InGamma);
 205.987 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsJoinGamma(LPGAMMATABLE InGamma,  LPGAMMATABLE OutGamma);
 205.988 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsJoinGammaEx(LPGAMMATABLE InGamma,  LPGAMMATABLE OutGamma, int nPoints);
 205.989 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsSmoothGamma(LPGAMMATABLE Tab, double lambda);
 205.990 -LCMSAPI double        LCMSEXPORT cmsEstimateGamma(LPGAMMATABLE t);
 205.991 -LCMSAPI double        LCMSEXPORT cmsEstimateGammaEx(LPWORD Table, int nEntries, double Thereshold);
 205.992 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsReadICCGamma(cmsHPROFILE hProfile, icTagSignature sig);
 205.993 -LCMSAPI LPGAMMATABLE  LCMSEXPORT cmsReadICCGammaReversed(cmsHPROFILE hProfile, icTagSignature sig);
 205.994 -
 205.995 -// Access to Profile data.
 205.996 -
 205.997 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
 205.998 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
 205.999 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile);
205.1000 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeColorants(LPcmsCIEXYZTRIPLE Dest, cmsHPROFILE hProfile);
205.1001 -LCMSAPI DWORD         LCMSEXPORT cmsTakeHeaderFlags(cmsHPROFILE hProfile);
205.1002 -LCMSAPI DWORD         LCMSEXPORT cmsTakeHeaderAttributes(cmsHPROFILE hProfile);
205.1003 -
205.1004 -LCMSAPI void          LCMSEXPORT cmsSetLanguage(const char LanguageCode[4], const char CountryCode[4]);
205.1005 -LCMSAPI const char*   LCMSEXPORT cmsTakeProductName(cmsHPROFILE hProfile);
205.1006 -LCMSAPI const char*   LCMSEXPORT cmsTakeProductDesc(cmsHPROFILE hProfile);
205.1007 -LCMSAPI const char*   LCMSEXPORT cmsTakeProductInfo(cmsHPROFILE hProfile);
205.1008 -LCMSAPI const char*   LCMSEXPORT cmsTakeManufacturer(cmsHPROFILE hProfile);
205.1009 -LCMSAPI const char*   LCMSEXPORT cmsTakeModel(cmsHPROFILE hProfile);
205.1010 -LCMSAPI const char*   LCMSEXPORT cmsTakeCopyright(cmsHPROFILE hProfile);
205.1011 -LCMSAPI const BYTE*   LCMSEXPORT cmsTakeProfileID(cmsHPROFILE hProfile);
205.1012 -
205.1013 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
205.1014 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeCalibrationDateTime(struct tm *Dest, cmsHPROFILE hProfile);
205.1015 -
205.1016 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig);
205.1017 -LCMSAPI int           LCMSEXPORT cmsTakeRenderingIntent(cmsHPROFILE hProfile);
205.1018 -
205.1019 -LCMSAPI LCMSBOOL      LCMSEXPORT cmsTakeCharTargetData(cmsHPROFILE hProfile, char** Data, size_t* len);
205.1020 -
205.1021 -LCMSAPI int           LCMSEXPORT cmsReadICCTextEx(cmsHPROFILE hProfile, icTagSignature sig, char *Text, size_t size);
205.1022 -LCMSAPI int           LCMSEXPORT cmsReadICCText(cmsHPROFILE hProfile, icTagSignature sig, char *Text);
205.1023 -
205.1024 -
205.1025 -#define LCMS_DESC_MAX     512
205.1026 -
205.1027 -typedef struct {
205.1028 -
205.1029 -            icSignature                 deviceMfg;
205.1030 -            icSignature                 deviceModel;
205.1031 -            icUInt32Number              attributes[2];
205.1032 -            icTechnologySignature       technology;
205.1033 -
205.1034 -            char Manufacturer[LCMS_DESC_MAX];
205.1035 -            char Model[LCMS_DESC_MAX];
205.1036 -
205.1037 -    } cmsPSEQDESC, FAR *LPcmsPSEQDESC;
205.1038 -
205.1039 -typedef struct {
205.1040 -
205.1041 -            int n;
205.1042 -            cmsPSEQDESC seq[1];
205.1043 -
205.1044 -    } cmsSEQ, FAR *LPcmsSEQ;
205.1045 -
205.1046 -
205.1047 -LCMSAPI LPcmsSEQ      LCMSEXPORT cmsReadProfileSequenceDescription(cmsHPROFILE hProfile);
205.1048 -LCMSAPI void          LCMSEXPORT cmsFreeProfileSequenceDescription(LPcmsSEQ pseq);
205.1049 -
205.1050 -
205.1051 -// Translate form/to our notation to ICC
205.1052 -LCMSAPI icColorSpaceSignature LCMSEXPORT _cmsICCcolorSpace(int OurNotation);
205.1053 -LCMSAPI int                   LCMSEXPORT _cmsLCMScolorSpace(icColorSpaceSignature ProfileSpace);
205.1054 -LCMSAPI int                   LCMSEXPORT _cmsChannelsOf(icColorSpaceSignature ColorSpace);
205.1055 -LCMSAPI LCMSBOOL              LCMSEXPORT _cmsIsMatrixShaper(cmsHPROFILE hProfile);
205.1056 -
205.1057 -// How profiles may be used
205.1058 -#define LCMS_USED_AS_INPUT      0
205.1059 -#define LCMS_USED_AS_OUTPUT     1
205.1060 -#define LCMS_USED_AS_PROOF      2
205.1061 -
205.1062 -LCMSAPI LCMSBOOL                LCMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, int Intent, int UsedDirection);
205.1063 -
205.1064 -LCMSAPI icColorSpaceSignature   LCMSEXPORT cmsGetPCS(cmsHPROFILE hProfile);
205.1065 -LCMSAPI icColorSpaceSignature   LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile);
205.1066 -LCMSAPI icProfileClassSignature LCMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile);
205.1067 -LCMSAPI DWORD                   LCMSEXPORT cmsGetProfileICCversion(cmsHPROFILE hProfile);
205.1068 -LCMSAPI void                    LCMSEXPORT cmsSetProfileICCversion(cmsHPROFILE hProfile, DWORD Version);
205.1069 -LCMSAPI icInt32Number           LCMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile);
205.1070 -LCMSAPI icTagSignature          LCMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, icInt32Number n);
205.1071 -
205.1072 -
205.1073 -LCMSAPI void          LCMSEXPORT cmsSetDeviceClass(cmsHPROFILE hProfile, icProfileClassSignature sig);
205.1074 -LCMSAPI void          LCMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, icColorSpaceSignature sig);
205.1075 -LCMSAPI void          LCMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, icColorSpaceSignature pcs);
205.1076 -LCMSAPI void          LCMSEXPORT cmsSetRenderingIntent(cmsHPROFILE hProfile, int RenderingIntent);
205.1077 -LCMSAPI void          LCMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, DWORD Flags);
205.1078 -LCMSAPI void          LCMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, DWORD Flags);
205.1079 -LCMSAPI void          LCMSEXPORT cmsSetProfileID(cmsHPROFILE hProfile, LPBYTE ProfileID);
205.1080 -
205.1081 -// Intents
205.1082 -
205.1083 -#define INTENT_PERCEPTUAL                 0
205.1084 -#define INTENT_RELATIVE_COLORIMETRIC      1
205.1085 -#define INTENT_SATURATION                 2
205.1086 -#define INTENT_ABSOLUTE_COLORIMETRIC      3
205.1087 -
205.1088 -// Flags
205.1089 -
205.1090 -#define cmsFLAGS_MATRIXINPUT              0x0001
205.1091 -#define cmsFLAGS_MATRIXOUTPUT             0x0002
205.1092 -#define cmsFLAGS_MATRIXONLY               (cmsFLAGS_MATRIXINPUT|cmsFLAGS_MATRIXOUTPUT)
205.1093 -
205.1094 -#define cmsFLAGS_NOWHITEONWHITEFIXUP      0x0004    // Don't hot fix scum dot
205.1095 -#define cmsFLAGS_NOPRELINEARIZATION       0x0010    // Don't create prelinearization tables
205.1096 -                                                    // on precalculated transforms (internal use)
205.1097 -
205.1098 -#define cmsFLAGS_GUESSDEVICECLASS         0x0020    // Guess device class (for transform2devicelink)
205.1099 -
205.1100 -#define cmsFLAGS_NOTCACHE                 0x0040    // Inhibit 1-pixel cache
205.1101 -
205.1102 -#define cmsFLAGS_NOTPRECALC               0x0100
205.1103 -#define cmsFLAGS_NULLTRANSFORM            0x0200    // Don't transform anyway
205.1104 -#define cmsFLAGS_HIGHRESPRECALC           0x0400    // Use more memory to give better accurancy
205.1105 -#define cmsFLAGS_LOWRESPRECALC            0x0800    // Use less memory to minimize resouces
205.1106 -
205.1107 -
205.1108 -#define cmsFLAGS_WHITEBLACKCOMPENSATION   0x2000
205.1109 -#define cmsFLAGS_BLACKPOINTCOMPENSATION   cmsFLAGS_WHITEBLACKCOMPENSATION
205.1110 -
205.1111 -// Proofing flags
205.1112 -
205.1113 -#define cmsFLAGS_GAMUTCHECK               0x1000    // Out of Gamut alarm
205.1114 -#define cmsFLAGS_SOFTPROOFING             0x4000    // Do softproofing
205.1115 -
205.1116 -// Black preservation
205.1117 -
205.1118 -#define cmsFLAGS_PRESERVEBLACK            0x8000
205.1119 -
205.1120 -// CRD special
205.1121 -
205.1122 -#define cmsFLAGS_NODEFAULTRESOURCEDEF     0x01000000
205.1123 -
205.1124 -// Gridpoints
205.1125 -
205.1126 -#define cmsFLAGS_GRIDPOINTS(n)           (((n) & 0xFF) << 16)
205.1127 -
205.1128 -
205.1129 -// Transforms
205.1130 -
205.1131 -LCMSAPI cmsHTRANSFORM LCMSEXPORT cmsCreateTransform(cmsHPROFILE Input,
205.1132 -                                               DWORD InputFormat,
205.1133 -                                               cmsHPROFILE Output,
205.1134 -                                               DWORD OutputFormat,
205.1135 -                                               int Intent,
205.1136 -                                               DWORD dwFlags);
205.1137 -
205.1138 -LCMSAPI cmsHTRANSFORM LCMSEXPORT cmsCreateProofingTransform(cmsHPROFILE Input,
205.1139 -                                               DWORD InputFormat,
205.1140 -                                               cmsHPROFILE Output,
205.1141 -                                               DWORD OutputFormat,
205.1142 -                                               cmsHPROFILE Proofing,
205.1143 -                                               int Intent,
205.1144 -                                               int ProofingIntent,
205.1145 -                                               DWORD dwFlags);
205.1146 -
205.1147 -LCMSAPI cmsHTRANSFORM LCMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
205.1148 -                                                                int nProfiles,
205.1149 -                                                                DWORD InputFormat,
205.1150 -                                                                DWORD OutputFormat,
205.1151 -                                                                int Intent,
205.1152 -                                                                DWORD dwFlags);
205.1153 -
205.1154 -LCMSAPI void         LCMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform);
205.1155 -
205.1156 -LCMSAPI void         LCMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
205.1157 -                                                 LPVOID InputBuffer,
205.1158 -                                                 LPVOID OutputBuffer,
205.1159 -                                                 unsigned int Size);
205.1160 -
205.1161 -LCMSAPI void         LCMSEXPORT cmsChangeBuffersFormat(cmsHTRANSFORM hTransform, DWORD InputFormat, DWORD dwOutputFormat);
205.1162 -
205.1163 -LCMSAPI void         LCMSEXPORT cmsSetAlarmCodes(int r, int g, int b);
205.1164 -LCMSAPI void         LCMSEXPORT cmsGetAlarmCodes(int *r, int *g, int *b);
205.1165 -
205.1166 -
205.1167 -// Adaptation state for absolute colorimetric intent
205.1168 -
205.1169 -LCMSAPI double       LCMSEXPORT cmsSetAdaptationState(double d);
205.1170 -
205.1171 -
205.1172 -// Primary preservation strategy
205.1173 -
205.1174 -#define LCMS_PRESERVE_PURE_K    0
205.1175 -#define LCMS_PRESERVE_K_PLANE   1
205.1176 -
205.1177 -LCMSAPI int LCMSEXPORT cmsSetCMYKPreservationStrategy(int n);
205.1178 -
205.1179 -// Named color support
205.1180 -typedef struct {
205.1181 -                char Name[MAX_PATH];
205.1182 -                WORD PCS[3];
205.1183 -                WORD DeviceColorant[MAXCHANNELS];
205.1184 -
205.1185 -
205.1186 -        } cmsNAMEDCOLOR, FAR* LPcmsNAMEDCOLOR;
205.1187 -
205.1188 -typedef struct {
205.1189 -                int nColors;
205.1190 -                int Allocated;
205.1191 -                int ColorantCount;
205.1192 -                char Prefix[33];
205.1193 -                char Suffix[33];
205.1194 -
205.1195 -                cmsNAMEDCOLOR List[1];
205.1196 -
205.1197 -        } cmsNAMEDCOLORLIST, FAR* LPcmsNAMEDCOLORLIST;
205.1198 -
205.1199 -// Named color support
205.1200 -
205.1201 -LCMSAPI int      LCMSEXPORT cmsNamedColorCount(cmsHTRANSFORM xform);
205.1202 -LCMSAPI LCMSBOOL LCMSEXPORT cmsNamedColorInfo(cmsHTRANSFORM xform, int nColor, char* Name, char* Prefix, char* Suffix);
205.1203 -LCMSAPI int      LCMSEXPORT cmsNamedColorIndex(cmsHTRANSFORM xform, const char* Name);
205.1204 -
205.1205 -// Colorant tables
205.1206 -
205.1207 -LCMSAPI LPcmsNAMEDCOLORLIST LCMSEXPORT cmsReadColorantTable(cmsHPROFILE hProfile, icTagSignature sig);
205.1208 -
205.1209 -// Profile creation
205.1210 -
205.1211 -LCMSAPI LCMSBOOL LCMSEXPORT cmsAddTag(cmsHPROFILE hProfile, icTagSignature sig, const void* data);
205.1212 -
205.1213 -// Converts a transform to a devicelink profile
205.1214 -LCMSAPI cmsHPROFILE LCMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, DWORD dwFlags);
205.1215 -
205.1216 -// Set the 'save as 8-bit' flag
205.1217 -LCMSAPI void LCMSEXPORT _cmsSetLUTdepth(cmsHPROFILE hProfile, int depth);
205.1218 -
205.1219 -
205.1220 -// Save profile
205.1221 -LCMSAPI LCMSBOOL LCMSEXPORT _cmsSaveProfile(cmsHPROFILE hProfile, const char* FileName);
205.1222 -LCMSAPI LCMSBOOL LCMSEXPORT _cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr,
205.1223 -                                                                size_t* BytesNeeded);
205.1224 -
205.1225 -
205.1226 -
205.1227 -// PostScript ColorRenderingDictionary and ColorSpaceArray
205.1228 -
205.1229 -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCSA(cmsHPROFILE hProfile, int Intent, LPVOID Buffer, DWORD dwBufferLen);
205.1230 -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCRD(cmsHPROFILE hProfile, int Intent, LPVOID Buffer, DWORD dwBufferLen);
205.1231 -LCMSAPI DWORD LCMSEXPORT cmsGetPostScriptCRDEx(cmsHPROFILE hProfile, int Intent, DWORD dwFlags, LPVOID Buffer, DWORD dwBufferLen);
205.1232 -
205.1233 -
205.1234 -// Error handling
205.1235 -
205.1236 -#define LCMS_ERROR_ABORT    0
205.1237 -#define LCMS_ERROR_SHOW     1
205.1238 -#define LCMS_ERROR_IGNORE   2
205.1239 -
205.1240 -LCMSAPI int LCMSEXPORT cmsErrorAction(int nAction);
205.1241 -
205.1242 -#define LCMS_ERRC_WARNING        0x1000
205.1243 -#define LCMS_ERRC_RECOVERABLE    0x2000
205.1244 -#define LCMS_ERRC_ABORTED        0x3000
205.1245 -
205.1246 -typedef int (* cmsErrorHandlerFunction)(int ErrorCode, const char *ErrorText);
205.1247 -
205.1248 -LCMSAPI void LCMSEXPORT cmsSetErrorHandler(cmsErrorHandlerFunction Fn);
205.1249 -
205.1250 -
205.1251 -// LUT manipulation
205.1252 -
205.1253 -
205.1254 -typedef struct _lcms_LUT_struc LUT, FAR* LPLUT; // opaque pointer
205.1255 -
205.1256 -LCMSAPI LPLUT  LCMSEXPORT cmsAllocLUT(void);
205.1257 -LCMSAPI LPLUT  LCMSEXPORT cmsAllocLinearTable(LPLUT NewLUT, LPGAMMATABLE Tables[], int nTable);
205.1258 -LCMSAPI LPLUT  LCMSEXPORT cmsAlloc3DGrid(LPLUT Lut, int clutPoints, int inputChan, int outputChan);
205.1259 -LCMSAPI LPLUT  LCMSEXPORT cmsSetMatrixLUT(LPLUT Lut, LPMAT3 M);
205.1260 -LCMSAPI LPLUT  LCMSEXPORT cmsSetMatrixLUT4(LPLUT Lut, LPMAT3 M, LPVEC3 off, DWORD dwFlags);
205.1261 -LCMSAPI void   LCMSEXPORT cmsFreeLUT(LPLUT Lut);
205.1262 -LCMSAPI void   LCMSEXPORT cmsEvalLUT(LPLUT Lut, WORD In[], WORD Out[]);
205.1263 -LCMSAPI double LCMSEXPORT cmsEvalLUTreverse(LPLUT Lut, WORD Target[], WORD Result[], LPWORD Hint);
205.1264 -LCMSAPI LPLUT  LCMSEXPORT cmsReadICCLut(cmsHPROFILE hProfile, icTagSignature sig);
205.1265 -LCMSAPI LPLUT  LCMSEXPORT cmsDupLUT(LPLUT Orig);
205.1266 -
205.1267 -
205.1268 -// LUT Sampling
205.1269 -
205.1270 -typedef int (* _cmsSAMPLER)(register WORD In[],
205.1271 -                            register WORD Out[],
205.1272 -                            register LPVOID Cargo);
205.1273 -
205.1274 -#define SAMPLER_HASTL1      LUT_HASTL1
205.1275 -#define SAMPLER_HASTL2      LUT_HASTL2
205.1276 -#define SAMPLER_INSPECT     0x01000000
205.1277 -
205.1278 -LCMSAPI int LCMSEXPORT cmsSample3DGrid(LPLUT Lut, _cmsSAMPLER Sampler, LPVOID Cargo, DWORD dwFlags);
205.1279 -
205.1280 -// Formatters
205.1281 -
205.1282 -typedef unsigned char* (* cmsFORMATTER)(register void* CMMcargo,
205.1283 -                                        register WORD ToUnroll[],
205.1284 -                                        register LPBYTE Buffer);
205.1285 -
205.1286 -LCMSAPI void LCMSEXPORT cmsSetUserFormatters(cmsHTRANSFORM hTransform, DWORD dwInput,  cmsFORMATTER Input,
205.1287 -                                                               DWORD dwOutput, cmsFORMATTER Output);
205.1288 -
205.1289 -LCMSAPI void LCMSEXPORT cmsGetUserFormatters(cmsHTRANSFORM hTransform,
205.1290 -                                                               LPDWORD InputFormat, cmsFORMATTER* Input,
205.1291 -                                                               LPDWORD OutputFormat, cmsFORMATTER* Output);
205.1292 -
205.1293 -
205.1294 -// IT8.7 / CGATS.17-200x handling
205.1295 -
205.1296 -LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8Alloc(void);
205.1297 -LCMSAPI void            LCMSEXPORT cmsIT8Free(LCMSHANDLE IT8);
205.1298 -
205.1299 -// Tables
205.1300 -
205.1301 -LCMSAPI int             LCMSEXPORT cmsIT8TableCount(LCMSHANDLE IT8);
205.1302 -LCMSAPI int             LCMSEXPORT cmsIT8SetTable(LCMSHANDLE IT8, int nTable);
205.1303 -
205.1304 -// Persistence
205.1305 -LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8LoadFromFile(const char* cFileName);
205.1306 -LCMSAPI LCMSHANDLE      LCMSEXPORT cmsIT8LoadFromMem(void *Ptr, size_t len);
205.1307 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SaveToFile(LCMSHANDLE IT8, const char* cFileName);
205.1308 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SaveToMem(LCMSHANDLE hIT8, void *MemPtr, size_t* BytesNeeded);
205.1309 -
205.1310 -// Properties
205.1311 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetSheetType(LCMSHANDLE hIT8);
205.1312 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetSheetType(LCMSHANDLE hIT8, const char* Type);
205.1313 -
205.1314 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetComment(LCMSHANDLE hIT8, const char* cComment);
205.1315 -
205.1316 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyStr(LCMSHANDLE hIT8, const char* cProp, const char *Str);
205.1317 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyDbl(LCMSHANDLE hIT8, const char* cProp, double Val);
205.1318 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyHex(LCMSHANDLE hIT8, const char* cProp, int Val);
205.1319 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char* cSubProp, const char *Val);
205.1320 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetPropertyUncooked(LCMSHANDLE hIT8, const char* Key, const char* Buffer);
205.1321 -
205.1322 -
205.1323 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetProperty(LCMSHANDLE hIT8, const char* cProp);
205.1324 -LCMSAPI double          LCMSEXPORT cmsIT8GetPropertyDbl(LCMSHANDLE hIT8, const char* cProp);
205.1325 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char *cSubProp);
205.1326 -LCMSAPI int             LCMSEXPORT cmsIT8EnumProperties(LCMSHANDLE hIT8, const char ***PropertyNames);
205.1327 -LCMSAPI int             LCMSEXPORT cmsIT8EnumPropertyMulti(LCMSHANDLE hIT8, const char* cProp, const char*** SubpropertyNames);
205.1328 -
205.1329 -// Datasets
205.1330 -
205.1331 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetDataRowCol(LCMSHANDLE IT8, int row, int col);
205.1332 -LCMSAPI double          LCMSEXPORT cmsIT8GetDataRowColDbl(LCMSHANDLE IT8, int row, int col);
205.1333 -
205.1334 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataRowCol(LCMSHANDLE hIT8, int row, int col,
205.1335 -                                                const char* Val);
205.1336 -
205.1337 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataRowColDbl(LCMSHANDLE hIT8, int row, int col,
205.1338 -                                                double Val);
205.1339 -
205.1340 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetData(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
205.1341 -
205.1342 -
205.1343 -LCMSAPI double          LCMSEXPORT cmsIT8GetDataDbl(LCMSHANDLE IT8, const char* cPatch, const char* cSample);
205.1344 -
205.1345 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetData(LCMSHANDLE IT8, const char* cPatch,
205.1346 -                                                const char* cSample,
205.1347 -                                                const char *Val);
205.1348 -
205.1349 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataDbl(LCMSHANDLE hIT8, const char* cPatch,
205.1350 -                                                const char* cSample,
205.1351 -                                                double Val);
205.1352 -
205.1353 -LCMSAPI int             LCMSEXPORT cmsIT8GetDataFormat(LCMSHANDLE hIT8, const char* cSample);
205.1354 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetDataFormat(LCMSHANDLE IT8, int n, const char *Sample);
205.1355 -LCMSAPI int             LCMSEXPORT cmsIT8EnumDataFormat(LCMSHANDLE IT8, char ***SampleNames);
205.1356 -
205.1357 -
205.1358 -LCMSAPI const char*     LCMSEXPORT cmsIT8GetPatchName(LCMSHANDLE hIT8, int nPatch, char* buffer);
205.1359 -LCMSAPI int             LCMSEXPORT cmsIT8GetPatchByName(LCMSHANDLE hIT8, const char *cSample);
205.1360 -
205.1361 -// The LABEL extension
205.1362 -
205.1363 -LCMSAPI int             LCMSEXPORT cmsIT8SetTableByLabel(LCMSHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType);
205.1364 -
205.1365 -LCMSAPI LCMSBOOL        LCMSEXPORT cmsIT8SetIndexColumn(LCMSHANDLE hIT8, const char* cSample);
205.1366 -
205.1367 -// Formatter for double
205.1368 -LCMSAPI void            LCMSEXPORT cmsIT8DefineDblFormat(LCMSHANDLE IT8, const char* Formatter);
205.1369 -
205.1370 -
205.1371 -// ***************************************************************************
205.1372 -// End of Little cms API From here functions are private
205.1373 -// You can use them only if using static libraries, and at your own risk of
205.1374 -// be stripped or changed at futures releases.
205.1375 -
205.1376 -#ifndef LCMS_APIONLY
205.1377 -
205.1378 -
205.1379 -// Compatibility with anterior versions-- not needed anymore
205.1380 -//  -- Morge
205.1381 -
205.1382 -LCMSAPI void          LCMSEXPORT cmsLabEncoded2Float(LPcmsCIELab Lab, const WORD wLab[3]);
205.1383 -LCMSAPI void          LCMSEXPORT cmsLabEncoded2Float4(LPcmsCIELab Lab, const WORD wLab[3]);
205.1384 -LCMSAPI void          LCMSEXPORT cmsFloat2LabEncoded(WORD wLab[3], const cmsCIELab* Lab);
205.1385 -LCMSAPI void          LCMSEXPORT cmsFloat2LabEncoded4(WORD wLab[3], const cmsCIELab* Lab);
205.1386 -LCMSAPI void          LCMSEXPORT cmsXYZEncoded2Float(LPcmsCIEXYZ fxyz, const WORD XYZ[3]);
205.1387 -LCMSAPI void          LCMSEXPORT cmsFloat2XYZEncoded(WORD XYZ[3], const cmsCIEXYZ* fXYZ);
205.1388 -
205.1389 -
205.1390 -// Profiling Extensions --- Would be removed from API in future revisions
205.1391 -
205.1392 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile,  icTagSignature sig, const char* Text);
205.1393 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile,   icTagSignature sig, const cmsCIEXYZ* XYZ);
205.1394 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile,   icTagSignature sig, const void* lut);
205.1395 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction);
205.1396 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm);
205.1397 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ PSeq);
205.1398 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
205.1399 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime);
205.1400 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc);
205.1401 -LCMSAPI LCMSBOOL      LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat);
205.1402 -
205.1403 -// --------------------------------------------------------------------------------------------------- Inline functions
205.1404 -
205.1405 -// Fast floor conversion logic. Thanks to Sree Kotay and Stuart Nixon
205.1406 -// note than this only works in the range ..-32767...+32767 because
205.1407 -// mantissa is interpreted as 15.16 fixed point.
205.1408 -// The union is to avoid pointer aliasing overoptimization.
205.1409 -
205.1410 -LCMS_INLINE int _cmsQuickFloor(double val)
205.1411 -{
205.1412 -#ifdef USE_DEFAULT_FLOOR_CONVERSION
205.1413 -    return (int) floor(val);
205.1414 -#else
205.1415 -    const double _lcms_double2fixmagic = 68719476736.0 * 1.5;  // 2^36 * 1.5, (52-16=36) uses limited precision to floor
205.1416 -    union {
205.1417 -        double val;
205.1418 -        int halves[2];
205.1419 -    } temp;
205.1420 -
205.1421 -    temp.val = val + _lcms_double2fixmagic;
205.1422 -
205.1423 -
205.1424 -#ifdef USE_BIG_ENDIAN
205.1425 -    return temp.halves[1] >> 16;
205.1426 -#else
205.1427 -    return temp.halves[0] >> 16;
205.1428 -#endif
205.1429 -#endif
205.1430 -}
205.1431 -
205.1432 -
205.1433 -
205.1434 -// Clamp with saturation
205.1435 -
205.1436 -LCMS_INLINE WORD _cmsClampWord(int in)
205.1437 -{
205.1438 -       if (in < 0) return 0;
205.1439 -       if (in > 0xFFFF) return 0xFFFFU;   // Including marker
205.1440 -       return (WORD) in;
205.1441 -}
205.1442 -
205.1443 -#ifndef LCMS_USER_ALLOC
205.1444 -
205.1445 -// Low-level alloc hook
205.1446 -
205.1447 -LCMS_INLINE void* _cmsMalloc(size_t size)
205.1448 -{
205.1449 -    if (size > ((size_t) 1024*1024*500)) return NULL;  // Never allow over 500Mb
205.1450 -    if (size < 0) return NULL;              // Prevent signed size_t exploits
205.1451 -
205.1452 -    return (void*) malloc(size);
205.1453 -}
205.1454 -
205.1455 -LCMS_INLINE void* _cmsCalloc(size_t nmemb, size_t size)
205.1456 -{
205.1457 -    size_t alloc = nmemb * size;
205.1458 -
205.1459 -        if (size == 0) {
205.1460 -                return _cmsMalloc(0);
205.1461 -        }
205.1462 -        if (alloc / size != nmemb) {
205.1463 -        return NULL;
205.1464 -    }
205.1465 -    return _cmsMalloc(alloc);
205.1466 -}
205.1467 -
205.1468 -LCMS_INLINE void _cmsFree(void *Ptr)
205.1469 -{
205.1470 -    if (Ptr) free(Ptr);
205.1471 -}
205.1472 -
205.1473 -#endif
205.1474 -
205.1475 -// ------------------------------------------------------------------------------------------- end of inline functions
205.1476 -
205.1477 -// Signal error from inside lcms code
205.1478 -
205.1479 -void cdecl cmsSignalError(int ErrorCode, const char *ErrorText, ...);
205.1480 -
205.1481 -// Alignment handling (needed in ReadLUT16 and ReadLUT8)
205.1482 -
205.1483 -typedef struct {
205.1484 -        icS15Fixed16Number a;
205.1485 -        icUInt16Number     b;
205.1486 -
205.1487 -       } _cmsTestAlign16;
205.1488 -
205.1489 -#define SIZEOF_UINT16_ALIGNED (sizeof(_cmsTestAlign16) - sizeof(icS15Fixed16Number))
205.1490 -
205.1491 -typedef struct {
205.1492 -        icS15Fixed16Number a;
205.1493 -        icUInt8Number      b;
205.1494 -
205.1495 -       } _cmsTestAlign8;
205.1496 -
205.1497 -#define SIZEOF_UINT8_ALIGNED (sizeof(_cmsTestAlign8) - sizeof(icS15Fixed16Number))
205.1498 -
205.1499 -
205.1500 -// Fixed point
205.1501 -
205.1502 -
205.1503 -typedef icInt32Number Fixed32;       // Fixed 15.16 whith sign
205.1504 -
205.1505 -#define INT_TO_FIXED(x)         ((x)<<16)
205.1506 -#define DOUBLE_TO_FIXED(x)      ((Fixed32) ((x)*65536.0+0.5))
205.1507 -#define FIXED_TO_INT(x)         ((x)>>16)
205.1508 -#define FIXED_REST_TO_INT(x)    ((x)& 0xFFFFU)
205.1509 -#define FIXED_TO_DOUBLE(x)      (((double)x)/65536.0)
205.1510 -#define ROUND_FIXED_TO_INT(x)   (((x)+0x8000)>>16)
205.1511 -
205.1512 -
205.1513 -Fixed32 cdecl FixedMul(Fixed32 a, Fixed32 b);
205.1514 -Fixed32 cdecl FixedSquare(Fixed32 a);
205.1515 -
205.1516 -
205.1517 -#ifdef USE_INLINE
205.1518 -
205.1519 -LCMS_INLINE Fixed32 ToFixedDomain(int a)        { return a + ((a + 0x7fff) / 0xffff); }
205.1520 -LCMS_INLINE int     FromFixedDomain(Fixed32 a)  { return a - ((a + 0x7fff) >> 16); }
205.1521 -
205.1522 -#else
205.1523 -
205.1524 -Fixed32 cdecl ToFixedDomain(int a);              // (a * 65536.0 / 65535.0)
205.1525 -int     cdecl FromFixedDomain(Fixed32 a);        // (a * 65535.0 + .5)
205.1526 -
205.1527 -#endif
205.1528 -
205.1529 -Fixed32 cdecl FixedLERP(Fixed32 a, Fixed32 l, Fixed32 h);
205.1530 -WORD    cdecl FixedScale(WORD a, Fixed32 s);
205.1531 -
205.1532 -// Vector & Matrix operations. I'm using the notation frequently found in
205.1533 -// literature. Mostly 'Graphic Gems' samples. Not to be same routines.
205.1534 -
205.1535 -// Vector members
205.1536 -
205.1537 -#define VX      0
205.1538 -#define VY      1
205.1539 -#define VZ      2
205.1540 -
205.1541 -typedef struct {                // Fixed 15.16 bits vector
205.1542 -        Fixed32 n[3];
205.1543 -        } WVEC3, FAR* LPWVEC3;
205.1544 -
205.1545 -typedef struct {                // Matrix (Fixed 15.16)
205.1546 -        WVEC3 v[3];
205.1547 -        } WMAT3, FAR* LPWMAT3;
205.1548 -
205.1549 -
205.1550 -
205.1551 -void      cdecl VEC3init(LPVEC3 r, double x, double y, double z);   // double version
205.1552 -void      cdecl VEC3initF(LPWVEC3 r, double x, double y, double z); // Fix32 version
205.1553 -void      cdecl VEC3toFix(LPWVEC3 r, LPVEC3 v);
205.1554 -void      cdecl VEC3fromFix(LPVEC3 r, LPWVEC3 v);
205.1555 -void      cdecl VEC3scaleFix(LPWORD r, LPWVEC3 Scale);
205.1556 -void      cdecl VEC3swap(LPVEC3 a, LPVEC3 b);
205.1557 -void      cdecl VEC3divK(LPVEC3 r, LPVEC3 v, double d);
205.1558 -void      cdecl VEC3perK(LPVEC3 r, LPVEC3 v, double d);
205.1559 -void      cdecl VEC3minus(LPVEC3 r, LPVEC3 a, LPVEC3 b);
205.1560 -void      cdecl VEC3perComp(LPVEC3 r, LPVEC3 a, LPVEC3 b);
205.1561 -LCMSBOOL  cdecl VEC3equal(LPWVEC3 a, LPWVEC3 b, double Tolerance);
205.1562 -LCMSBOOL  cdecl VEC3equalF(LPVEC3 a, LPVEC3 b, double Tolerance);
205.1563 -void      cdecl VEC3scaleAndCut(LPWVEC3 r, LPVEC3 v, double d);
205.1564 -void      cdecl VEC3cross(LPVEC3 r, LPVEC3 u, LPVEC3 v);
205.1565 -void      cdecl VEC3saturate(LPVEC3 v);
205.1566 -double    cdecl VEC3distance(LPVEC3 a, LPVEC3 b);
205.1567 -double    cdecl VEC3length(LPVEC3 a);
205.1568 -
205.1569 -void      cdecl MAT3identity(LPMAT3 a);
205.1570 -void      cdecl MAT3per(LPMAT3 r, LPMAT3 a, LPMAT3 b);
205.1571 -void      cdecl MAT3perK(LPMAT3 r, LPMAT3 v, double d);
205.1572 -int       cdecl MAT3inverse(LPMAT3 a, LPMAT3 b);
205.1573 -LCMSBOOL  cdecl MAT3solve(LPVEC3 x, LPMAT3 a, LPVEC3 b);
205.1574 -double    cdecl MAT3det(LPMAT3 m);
205.1575 -void      cdecl MAT3eval(LPVEC3 r, LPMAT3 a, LPVEC3 v);
205.1576 -void      cdecl MAT3toFix(LPWMAT3 r, LPMAT3 v);
205.1577 -void      cdecl MAT3fromFix(LPMAT3 r, LPWMAT3 v);
205.1578 -void      cdecl MAT3evalW(LPWVEC3 r, LPWMAT3 a, LPWVEC3 v);
205.1579 -LCMSBOOL  cdecl MAT3isIdentity(LPWMAT3 a, double Tolerance);
205.1580 -void      cdecl MAT3scaleAndCut(LPWMAT3 r, LPMAT3 v, double d);
205.1581 -
205.1582 -// Is a table linear?
205.1583 -
205.1584 -int  cdecl cmsIsLinear(WORD Table[], int nEntries);
205.1585 -
205.1586 -// I hold this structures describing domain
205.1587 -// details mainly for optimization purposes.
205.1588 -
205.1589 -struct _lcms_l16params_struc;
205.1590 -
205.1591 -typedef void (* _cms3DLERP)(WORD Input[],
205.1592 -                            WORD Output[],
205.1593 -                            WORD LutTable[],
205.1594 -                            struct _lcms_l16params_struc* p);
205.1595 -
205.1596 -
205.1597 -
205.1598 -typedef struct _lcms_l8opt_struc {      // Used on 8 bit interpolations
205.1599 -
205.1600 -              unsigned int X0[256], Y0[256], Z0[256];
205.1601 -              WORD rx[256], ry[256], rz[256];
205.1602 -
205.1603 -        } L8PARAMS, FAR* LPL8PARAMS;
205.1604 -
205.1605 -typedef struct _lcms_l16params_struc {    // Used on 16 bits interpolations
205.1606 -
205.1607 -               int nSamples;       // Valid on all kinds of tables
205.1608 -               int nInputs;        // != 1 only in 3D interpolation
205.1609 -               int nOutputs;       // != 1 only in 3D interpolation
205.1610 -
205.1611 -               WORD Domain;
205.1612 -
205.1613 -               int opta1, opta2;
205.1614 -               int opta3, opta4;     // Optimization for 3D LUT
205.1615 -               int opta5, opta6;
205.1616 -               int opta7, opta8;
205.1617 -
205.1618 -               _cms3DLERP Interp3D; // The interpolation routine
205.1619 -
205.1620 -                LPL8PARAMS p8;      // Points to some tables for 8-bit speedup
205.1621 -
205.1622 -               } L16PARAMS, *LPL16PARAMS;
205.1623 -
205.1624 -
205.1625 -void    cdecl cmsCalcL16Params(int nSamples, LPL16PARAMS p);
205.1626 -void    cdecl cmsCalcCLUT16Params(int nSamples, int InputChan, int OutputChan, LPL16PARAMS p);
205.1627 -void    cdecl cmsCalcCLUT16ParamsEx(int nSamples, int InputChan, int OutputChan,
205.1628 -                                            LCMSBOOL lUseTetrahedral, LPL16PARAMS p);
205.1629 -
205.1630 -WORD    cdecl cmsLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p);
205.1631 -Fixed32 cdecl cmsLinearInterpFixed(WORD Value1, WORD LutTable[], LPL16PARAMS p);
205.1632 -WORD    cdecl cmsReverseLinearInterpLUT16(WORD Value, WORD LutTable[], LPL16PARAMS p);
205.1633 -
205.1634 -void cdecl cmsTrilinearInterp16(WORD Input[],
205.1635 -                                WORD Output[],
205.1636 -                                WORD LutTable[],
205.1637 -                                LPL16PARAMS p);
205.1638 -
205.1639 -void cdecl cmsTetrahedralInterp16(WORD Input[],
205.1640 -                                  WORD Output[],
205.1641 -                                  WORD LutTable[], LPL16PARAMS p);
205.1642 -
205.1643 -void cdecl cmsTetrahedralInterp8(WORD Input[],
205.1644 -                                 WORD Output[],
205.1645 -                                 WORD LutTable[],  LPL16PARAMS p);
205.1646 -
205.1647 -// LUT handling
205.1648 -
205.1649 -#define LUT_HASMATRIX       0x0001        // Do-op Flags
205.1650 -#define LUT_HASTL1          0x0002
205.1651 -#define LUT_HASTL2          0x0008
205.1652 -#define LUT_HAS3DGRID       0x0010
205.1653 -
205.1654 -// New in rev 4.0 of ICC spec
205.1655 -
205.1656 -#define LUT_HASMATRIX3     0x0020   // Matrix + offset for LutAToB
205.1657 -#define LUT_HASMATRIX4     0x0040   // Matrix + offset for LutBToA
205.1658 -
205.1659 -#define LUT_HASTL3         0x0100   // '3' curves for LutAToB
205.1660 -#define LUT_HASTL4         0x0200   // '4' curves for LutBToA
205.1661 -
205.1662 -// V4 emulation
205.1663 -
205.1664 -#define LUT_V4_OUTPUT_EMULATE_V2    0x10000     // Is a V4 output LUT, emulating V2
205.1665 -#define LUT_V4_INPUT_EMULATE_V2     0x20000     // Is a V4 input LUT, emulating V2
205.1666 -#define LUT_V2_OUTPUT_EMULATE_V4    0x40000     // Is a V2 output LUT, emulating V4
205.1667 -#define LUT_V2_INPUT_EMULATE_V4     0x80000     // Is a V2 input LUT, emulating V4
205.1668 -
205.1669 -
205.1670 -struct _lcms_LUT_struc {
205.1671 -
205.1672 -               DWORD wFlags;
205.1673 -               WMAT3 Matrix;                    // 15fixed16 matrix
205.1674 -
205.1675 -               unsigned int InputChan;
205.1676 -               unsigned int OutputChan;
205.1677 -               unsigned int InputEntries;
205.1678 -               unsigned int OutputEntries;
205.1679 -               unsigned int cLutPoints;
205.1680 -
205.1681 -
205.1682 -               LPWORD L1[MAXCHANNELS];          // First linearization
205.1683 -               LPWORD L2[MAXCHANNELS];          // Last linearization
205.1684 -
205.1685 -               LPWORD T;                        // 3D CLUT
205.1686 -               unsigned int Tsize;              // CLUT size in bytes
205.1687 -
205.1688 -              // Parameters & Optimizations
205.1689 -
205.1690 -               L16PARAMS In16params;
205.1691 -               L16PARAMS Out16params;
205.1692 -               L16PARAMS CLut16params;
205.1693 -
205.1694 -               int Intent;                       // Accomplished intent
205.1695 -
205.1696 -               // New for Rev 4.0 of spec (reserved)
205.1697 -
205.1698 -               WMAT3 Mat3;
205.1699 -               WVEC3 Ofs3;
205.1700 -               LPWORD L3[MAXCHANNELS];
205.1701 -               L16PARAMS L3params;
205.1702 -               unsigned int L3Entries;
205.1703 -
205.1704 -               WMAT3 Mat4;
205.1705 -               WVEC3 Ofs4;
205.1706 -               LPWORD L4[MAXCHANNELS];
205.1707 -               L16PARAMS L4params;
205.1708 -               unsigned int L4Entries;
205.1709 -
205.1710 -               // Gray axes fixup. Only on v2 8-bit Lab LUT
205.1711 -
205.1712 -               LCMSBOOL FixGrayAxes;
205.1713 -
205.1714 -
205.1715 -               // Parameters used for curve creation
205.1716 -
205.1717 -               LCMSGAMMAPARAMS LCurvesSeed[4][MAXCHANNELS];
205.1718 -
205.1719 -
205.1720 -               }; // LUT, FAR* LPLUT;
205.1721 -
205.1722 -
205.1723 -LCMSBOOL         cdecl _cmsSmoothEndpoints(LPWORD Table, int nEntries);
205.1724 -
205.1725 -
205.1726 -// CRC of gamma tables
205.1727 -
205.1728 -unsigned int _cmsCrc32OfGammaTable(LPGAMMATABLE Table);
205.1729 -
205.1730 -// Sampled curves
205.1731 -
205.1732 -LPSAMPLEDCURVE cdecl cmsAllocSampledCurve(int nItems);
205.1733 -void           cdecl cmsFreeSampledCurve(LPSAMPLEDCURVE p);
205.1734 -LPSAMPLEDCURVE cdecl cmsDupSampledCurve(LPSAMPLEDCURVE p);
205.1735 -
205.1736 -LPSAMPLEDCURVE cdecl cmsConvertGammaToSampledCurve(LPGAMMATABLE Gamma, int nPoints);
205.1737 -LPGAMMATABLE   cdecl cmsConvertSampledCurveToGamma(LPSAMPLEDCURVE Sampled, double Max);
205.1738 -
205.1739 -void           cdecl cmsEndpointsOfSampledCurve(LPSAMPLEDCURVE p, double* Min, double* Max);
205.1740 -void           cdecl cmsClampSampledCurve(LPSAMPLEDCURVE p, double Min, double Max);
205.1741 -LCMSBOOL       cdecl cmsSmoothSampledCurve(LPSAMPLEDCURVE Tab, double SmoothingLambda);
205.1742 -void           cdecl cmsRescaleSampledCurve(LPSAMPLEDCURVE p, double Min, double Max, int nPoints);
205.1743 -
205.1744 -LPSAMPLEDCURVE cdecl cmsJoinSampledCurves(LPSAMPLEDCURVE X, LPSAMPLEDCURVE Y, int nResultingPoints);
205.1745 -
205.1746 -// Shaper/Matrix handling
205.1747 -
205.1748 -#define MATSHAPER_HASMATRIX        0x0001        // Do-ops flags
205.1749 -#define MATSHAPER_HASSHAPER        0x0002
205.1750 -#define MATSHAPER_INPUT            0x0004        // Behaviour
205.1751 -#define MATSHAPER_OUTPUT           0x0008
205.1752 -#define MATSHAPER_HASINPSHAPER     0x0010
205.1753 -#define MATSHAPER_ALLSMELTED       (MATSHAPER_INPUT|MATSHAPER_OUTPUT)
205.1754 -
205.1755 -
205.1756 -typedef struct {
205.1757 -               DWORD dwFlags;
205.1758 -
205.1759 -               WMAT3 Matrix;
205.1760 -
205.1761 -               L16PARAMS p16;       // Primary curve
205.1762 -               LPWORD L[3];
205.1763 -
205.1764 -               L16PARAMS p2_16;     // Secondary curve (used as input in smelted ones)
205.1765 -               LPWORD L2[3];
205.1766 -
205.1767 -               } MATSHAPER, FAR* LPMATSHAPER;
205.1768 -
205.1769 -LPMATSHAPER cdecl cmsAllocMatShaper(LPMAT3 matrix, LPGAMMATABLE Shaper[], DWORD Behaviour);
205.1770 -LPMATSHAPER cdecl cmsAllocMatShaper2(LPMAT3 matrix, LPGAMMATABLE In[], LPGAMMATABLE Out[], DWORD Behaviour);
205.1771 -
205.1772 -void        cdecl cmsFreeMatShaper(LPMATSHAPER MatShaper);
205.1773 -void        cdecl cmsEvalMatShaper(LPMATSHAPER MatShaper, WORD In[], WORD Out[]);
205.1774 -
205.1775 -LCMSBOOL    cdecl cmsReadICCMatrixRGB2XYZ(LPMAT3 r, cmsHPROFILE hProfile);
205.1776 -
205.1777 -LPMATSHAPER cdecl cmsBuildInputMatrixShaper(cmsHPROFILE InputProfile);
205.1778 -LPMATSHAPER cdecl cmsBuildOutputMatrixShaper(cmsHPROFILE OutputProfile);
205.1779 -
205.1780 -
205.1781 -
205.1782 -// White Point & Primary chromas handling
205.1783 -LCMSBOOL cdecl cmsAdaptationMatrix(LPMAT3 r, LPMAT3 ConeMatrix, LPcmsCIEXYZ FromIll, LPcmsCIEXYZ ToIll);
205.1784 -LCMSBOOL cdecl cmsAdaptMatrixToD50(LPMAT3 r, LPcmsCIExyY SourceWhitePt);
205.1785 -LCMSBOOL cdecl cmsAdaptMatrixFromD50(LPMAT3 r, LPcmsCIExyY DestWhitePt);
205.1786 -
205.1787 -LCMSBOOL cdecl cmsReadChromaticAdaptationMatrix(LPMAT3 r, cmsHPROFILE hProfile);
205.1788 -
205.1789 -// Inter-PCS conversion routines. They assume D50 as white point.
205.1790 -void cdecl cmsXYZ2LabEncoded(WORD XYZ[3], WORD Lab[3]);
205.1791 -void cdecl cmsLab2XYZEncoded(WORD Lab[3], WORD XYZ[3]);
205.1792 -
205.1793 -// Retrieve text representation of WP
205.1794 -void cdecl _cmsIdentifyWhitePoint(char *Buffer, LPcmsCIEXYZ WhitePt);
205.1795 -
205.1796 -// Quantize to WORD in a (MaxSamples - 1) domain
205.1797 -WORD cdecl _cmsQuantizeVal(double i, int MaxSamples);
205.1798 -
205.1799 -LPcmsNAMEDCOLORLIST  cdecl cmsAllocNamedColorList(int n);
205.1800 -int                  cdecl cmsReadICCnamedColorList(cmsHTRANSFORM xform, cmsHPROFILE hProfile, icTagSignature sig);
205.1801 -void                 cdecl cmsFreeNamedColorList(LPcmsNAMEDCOLORLIST List);
205.1802 -LCMSBOOL             cdecl cmsAppendNamedColor(cmsHTRANSFORM xform, const char* Name, WORD PCS[3], WORD Colorant[MAXCHANNELS]);
205.1803 -
205.1804 -
205.1805 -// I/O
205.1806 -
205.1807 -#define MAX_TABLE_TAG       100
205.1808 -
205.1809 -// This is the internal struct holding profile details.
205.1810 -
205.1811 -typedef struct _lcms_iccprofile_struct {
205.1812 -
205.1813 -              void* stream;   // Associated stream. If NULL,
205.1814 -                              // tags are supposed to be in
205.1815 -                              // memory rather than in a file.
205.1816 -
205.1817 -               // Only most important items found in ICC profile
205.1818 -
205.1819 -               icProfileClassSignature DeviceClass;
205.1820 -               icColorSpaceSignature   ColorSpace;
205.1821 -               icColorSpaceSignature   PCS;
205.1822 -               icRenderingIntent       RenderingIntent;
205.1823 -               icUInt32Number          flags;
205.1824 -               icUInt32Number          attributes;
205.1825 -               cmsCIEXYZ               Illuminant;
205.1826 -
205.1827 -               // Additions for V4 profiles
205.1828 -
205.1829 -               icUInt32Number          Version;
205.1830 -               MAT3                    ChromaticAdaptation;
205.1831 -               cmsCIEXYZ               MediaWhitePoint;
205.1832 -               cmsCIEXYZ               MediaBlackPoint;
205.1833 -               BYTE                    ProfileID[16];
205.1834 -
205.1835 -
205.1836 -               // Dictionary
205.1837 -
205.1838 -               icInt32Number           TagCount;
205.1839 -               icTagSignature          TagNames[MAX_TABLE_TAG];
205.1840 -               size_t                  TagSizes[MAX_TABLE_TAG];
205.1841 -               size_t                  TagOffsets[MAX_TABLE_TAG];
205.1842 -               LPVOID                  TagPtrs[MAX_TABLE_TAG];
205.1843 -
205.1844 -               char                    PhysicalFile[MAX_PATH];
205.1845 -
205.1846 -               LCMSBOOL                IsWrite;
205.1847 -               LCMSBOOL                SaveAs8Bits;
205.1848 -
205.1849 -               struct tm               Created;
205.1850 -
205.1851 -               // I/O handlers
205.1852 -
205.1853 -               size_t   (* Read)(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc);
205.1854 -
205.1855 -               LCMSBOOL (* Seek)(struct _lcms_iccprofile_struct* Icc, size_t offset);
205.1856 -               LCMSBOOL (* Close)(struct _lcms_iccprofile_struct* Icc);
205.1857 -               size_t   (* Tell)(struct _lcms_iccprofile_struct* Icc);
205.1858 -               LCMSBOOL  (* Grow)(struct _lcms_iccprofile_struct* Icc, size_t amount);
205.1859 -
205.1860 -               // Writting
205.1861 -
205.1862 -               LCMSBOOL (* Write)(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr);
205.1863 -
205.1864 -               size_t UsedSpace;
205.1865 -
205.1866 -
205.1867 -              } LCMSICCPROFILE, FAR* LPLCMSICCPROFILE;
205.1868 -
205.1869 -
205.1870 -// Create an empty template for virtual profiles
205.1871 -cmsHPROFILE cdecl _cmsCreateProfilePlaceholder(void);
205.1872 -
205.1873 -// Search into tag dictionary
205.1874 -icInt32Number cdecl _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError);
205.1875 -
205.1876 -// Search for a particular tag, replace if found or add new one else
205.1877 -LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const void* Init);
205.1878 -
205.1879 -
205.1880 -LPLCMSICCPROFILE cdecl _cmsCreateProfileFromFilePlaceholder(const char* FileName);
205.1881 -LPLCMSICCPROFILE cdecl _cmsCreateProfileFromMemPlaceholder(LPVOID MemPtr, DWORD dwSize);
205.1882 -
205.1883 -void _cmsSetSaveToDisk(LPLCMSICCPROFILE Icc, const char* FileName);
205.1884 -void _cmsSetSaveToMemory(LPLCMSICCPROFILE Icc, LPVOID MemPtr, size_t dwSize);
205.1885 -
205.1886 -
205.1887 -
205.1888 -// These macros unpack format specifiers into integers
205.1889 -
205.1890 -#define T_DITHER(s)           (((s)>>22)&1)
205.1891 -#define T_COLORSPACE(s)       (((s)>>16)&31)
205.1892 -#define T_SWAPFIRST(s)        (((s)>>14)&1)
205.1893 -#define T_FLAVOR(s)           (((s)>>13)&1)
205.1894 -#define T_PLANAR(p)           (((p)>>12)&1)
205.1895 -#define T_ENDIAN16(e)         (((e)>>11)&1)
205.1896 -#define T_DOSWAP(e)           (((e)>>10)&1)
205.1897 -#define T_EXTRA(e)            (((e)>>7)&7)
205.1898 -#define T_CHANNELS(c)         (((c)>>3)&15)
205.1899 -#define T_BYTES(b)            ((b)&7)
205.1900 -
205.1901 -
205.1902 -
205.1903 -// Internal XFORM struct
205.1904 -struct _cmstransform_struct;
205.1905 -
205.1906 -// Full xform
205.1907 -typedef void (* _cmsCOLORCALLBACKFN)(struct _cmstransform_struct *Transform,
205.1908 -                               LPVOID InputBuffer,
205.1909 -                               LPVOID OutputBuffer, unsigned int Size);
205.1910 -
205.1911 -// intermediate pass, from WORD[] to WORD[]
205.1912 -
205.1913 -typedef void   (* _cmsADJFN)(WORD In[], WORD Out[], LPWMAT3 m, LPWVEC3 b);
205.1914 -
205.1915 -typedef void   (* _cmsTRANSFN)(struct _cmstransform_struct *Transform,
205.1916 -                               WORD In[], WORD Out[]);
205.1917 -
205.1918 -typedef void   (* _cmsCNVRT)(WORD In[], WORD Out[]);
205.1919 -
205.1920 -typedef LPBYTE (* _cmsFIXFN)(register struct _cmstransform_struct *info,
205.1921 -                             register WORD ToUnroll[],
205.1922 -                             register LPBYTE Buffer);
205.1923 -
205.1924 -
205.1925 -
205.1926 -// Transformation
205.1927 -typedef struct _cmstransform_struct {
205.1928 -
205.1929 -                    // Keep formats for further reference
205.1930 -                    DWORD InputFormat, OutputFormat;
205.1931 -
205.1932 -                    DWORD StrideIn, StrideOut;      // Planar support
205.1933 -
205.1934 -                    int Intent, ProofIntent;
205.1935 -                    int DoGamutCheck;
205.1936 -
205.1937 -
205.1938 -                    cmsHPROFILE InputProfile;
205.1939 -                    cmsHPROFILE OutputProfile;
205.1940 -                    cmsHPROFILE PreviewProfile;
205.1941 -
205.1942 -                    icColorSpaceSignature EntryColorSpace;
205.1943 -                    icColorSpaceSignature ExitColorSpace;
205.1944 -
205.1945 -                    DWORD dwOriginalFlags;      // Flags as specified by user
205.1946 -
205.1947 -                    WMAT3 m1, m2;       // Matrix holding inter PCS operation
205.1948 -                    WVEC3 of1, of2;     // Offset terms
205.1949 -
205.1950 -                    _cmsCOLORCALLBACKFN xform;
205.1951 -
205.1952 -                    // Steps in xFORM
205.1953 -
205.1954 -                    _cmsFIXFN   FromInput;
205.1955 -                    _cmsTRANSFN FromDevice;
205.1956 -                    _cmsADJFN   Stage1;
205.1957 -                    _cmsADJFN   Stage2;
205.1958 -                    _cmsTRANSFN ToDevice;
205.1959 -                    _cmsFIXFN   ToOutput;
205.1960 -
205.1961 -                    // LUTs
205.1962 -
205.1963 -                    LPLUT Device2PCS;
205.1964 -                    LPLUT PCS2Device;
205.1965 -                    LPLUT Gamut;         // Gamut check
205.1966 -                    LPLUT Preview;       // Preview (Proof)
205.1967 -
205.1968 -                    LPLUT DeviceLink;    // Precalculated grid - device link profile
205.1969 -                    LPLUT GamutCheck;    // Precalculated device -> gamut check
205.1970 -
205.1971 -                    // Matrix/Shapers
205.1972 -
205.1973 -                    LPMATSHAPER InMatShaper;
205.1974 -                    LPMATSHAPER OutMatShaper;
205.1975 -                    LPMATSHAPER SmeltMatShaper;
205.1976 -
205.1977 -                    // Phase of Lab/XYZ, Abs/Rel
205.1978 -
205.1979 -                    int Phase1, Phase2, Phase3;
205.1980 -
205.1981 -                    // Named color table
205.1982 -
205.1983 -                    LPcmsNAMEDCOLORLIST NamedColorList;
205.1984 -
205.1985 -                    // Flag for transform involving v4 profiles
205.1986 -
205.1987 -                    LCMSBOOL lInputV4Lab, lOutputV4Lab;
205.1988 -
205.1989 -
205.1990 -                    // 1-pixel cache
205.1991 -
205.1992 -                    WORD CacheIn[MAXCHANNELS];
205.1993 -                    WORD CacheOut[MAXCHANNELS];
205.1994 -
205.1995 -                    double AdaptationState; // Figure for v4 incomplete state of adaptation
205.1996 -
205.1997 -                    LCMS_RWLOCK_T rwlock;
205.1998 -
205.1999 -                   } _cmsTRANSFORM,FAR *_LPcmsTRANSFORM;
205.2000 -
205.2001 -
205.2002 -
205.2003 -// Packing & Unpacking
205.2004 -
205.2005 -_cmsFIXFN cdecl _cmsIdentifyInputFormat(_LPcmsTRANSFORM xform,  DWORD dwInput);
205.2006 -_cmsFIXFN cdecl _cmsIdentifyOutputFormat(_LPcmsTRANSFORM xform, DWORD dwOutput);
205.2007 -
205.2008 -
205.2009 -// Conversion
205.2010 -
205.2011 -#define XYZRel       0
205.2012 -#define LabRel       1
205.2013 -
205.2014 -
205.2015 -int cdecl cmsChooseCnvrt(int Absolute,
205.2016 -                 int Phase1, LPcmsCIEXYZ BlackPointIn,
205.2017 -                             LPcmsCIEXYZ WhitePointIn,
205.2018 -                             LPcmsCIEXYZ IlluminantIn,
205.2019 -                             LPMAT3 ChromaticAdaptationMatrixIn,
205.2020 -
205.2021 -                 int Phase2, LPcmsCIEXYZ BlackPointOut,
205.2022 -                             LPcmsCIEXYZ WhitePointOut,
205.2023 -                             LPcmsCIEXYZ IlluminantOut,
205.2024 -                             LPMAT3 ChromaticAdaptationMatrixOut,
205.2025 -                 int DoBPC,
205.2026 -                 double AdaptationState,
205.2027 -                 _cmsADJFN *fn1,
205.2028 -                 LPWMAT3 wm, LPWVEC3 wof);
205.2029 -
205.2030 -
205.2031 -
205.2032 -// Clamping & Gamut handling
205.2033 -
205.2034 -LCMSBOOL cdecl   _cmsEndPointsBySpace(icColorSpaceSignature Space,
205.2035 -                            WORD **White, WORD **Black, int *nOutputs);
205.2036 -
205.2037 -WORD * cdecl _cmsWhiteBySpace(icColorSpaceSignature Space);
205.2038 -
205.2039 -
205.2040 -
205.2041 -WORD cdecl Clamp_L(Fixed32 in);
205.2042 -WORD cdecl Clamp_ab(Fixed32 in);
205.2043 -
205.2044 -// Detection of black point
205.2045 -
205.2046 -#define LCMS_BPFLAGS_D50_ADAPTED    0x0001
205.2047 -
205.2048 -int cdecl cmsDetectBlackPoint(LPcmsCIEXYZ BlackPoint, cmsHPROFILE hProfile, int Intent, DWORD dwFlags);
205.2049 -
205.2050 -// choose reasonable resolution
205.2051 -int cdecl _cmsReasonableGridpointsByColorspace(icColorSpaceSignature Colorspace, DWORD dwFlags);
205.2052 -
205.2053 -// Precalculate device link
205.2054 -LPLUT cdecl _cmsPrecalculateDeviceLink(cmsHTRANSFORM h, DWORD dwFlags);
205.2055 -
205.2056 -// Precalculate black preserving device link
205.2057 -LPLUT _cmsPrecalculateBlackPreservingDeviceLink(cmsHTRANSFORM hCMYK2CMYK, DWORD dwFlags);
205.2058 -
205.2059 -// Precalculate gamut check
205.2060 -LPLUT cdecl _cmsPrecalculateGamutCheck(cmsHTRANSFORM h);
205.2061 -
205.2062 -// Hot fixes bad profiles
205.2063 -LCMSBOOL cdecl _cmsFixWhiteMisalignment(_LPcmsTRANSFORM p);
205.2064 -
205.2065 -// Marks LUT as 8 bit on input
205.2066 -LPLUT cdecl _cmsBlessLUT8(LPLUT Lut);
205.2067 -
205.2068 -// Compute gamut boundary
205.2069 -LPLUT cdecl _cmsComputeGamutLUT(cmsHPROFILE hProfile, int Intent);
205.2070 -
205.2071 -// Compute softproof
205.2072 -LPLUT cdecl _cmsComputeSoftProofLUT(cmsHPROFILE hProfile, int nIntent);
205.2073 -
205.2074 -// Find a suitable prelinearization tables, matching the given transform
205.2075 -void cdecl _cmsComputePrelinearizationTablesFromXFORM(cmsHTRANSFORM h[], int nTransforms, LPLUT Grid);
205.2076 -
205.2077 -
205.2078 -// Build a tone curve for K->K' if possible (only works on CMYK)
205.2079 -LPGAMMATABLE _cmsBuildKToneCurve(cmsHTRANSFORM hCMYK2CMYK, int nPoints);
205.2080 -
205.2081 -// Validates a LUT
205.2082 -LCMSBOOL cdecl _cmsValidateLUT(LPLUT NewLUT);
205.2083 -
205.2084 -
205.2085 -// These are two VITAL macros, from converting between 8 and 16 bit
205.2086 -// representation.
205.2087 -
205.2088 -#define RGB_8_TO_16(rgb) (WORD) ((((WORD) (rgb)) << 8)|(rgb))
205.2089 -#define RGB_16_TO_8(rgb) (BYTE) ((((rgb) * 65281 + 8388608) >> 24) & 0xFF)
205.2090 -
205.2091 -
205.2092 -#endif  // LCMS_APIONLY
205.2093 -
205.2094 -
205.2095 -#define __cms_H
205.2096 -
205.2097 -#ifdef __cplusplus
205.2098 -}
205.2099 -#endif
205.2100 -
205.2101 -#endif
205.2102 -
   206.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   206.2 +++ b/src/share/native/sun/java2d/cmm/lcms/lcms2.h	Fri Sep 24 16:41:32 2010 -0700
   206.3 @@ -0,0 +1,1751 @@
   206.4 +/*
   206.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   206.6 + *
   206.7 + * This code is free software; you can redistribute it and/or modify it
   206.8 + * under the terms of the GNU General Public License version 2 only, as
   206.9 + * published by the Free Software Foundation.  Oracle designates this
  206.10 + * particular file as subject to the "Classpath" exception as provided
  206.11 + * by Oracle in the LICENSE file that accompanied this code.
  206.12 + *
  206.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  206.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  206.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  206.16 + * version 2 for more details (a copy is included in the LICENSE file that
  206.17 + * accompanied this code).
  206.18 + *
  206.19 + * You should have received a copy of the GNU General Public License version
  206.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  206.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  206.22 + *
  206.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  206.24 + * or visit www.oracle.com if you need additional information or have any
  206.25 + * questions.
  206.26 + */
  206.27 +
  206.28 +// This file is available under and governed by the GNU General Public
  206.29 +// License version 2 only, as published by the Free Software Foundation.
  206.30 +// However, the following notice accompanied the original version of this
  206.31 +// file:
  206.32 +//
  206.33 +//---------------------------------------------------------------------------------
  206.34 +//
  206.35 +//  Little Color Management System
  206.36 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  206.37 +//
  206.38 +// Permission is hereby granted, free of charge, to any person obtaining
  206.39 +// a copy of this software and associated documentation files (the "Software"),
  206.40 +// to deal in the Software without restriction, including without limitation
  206.41 +// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  206.42 +// and/or sell copies of the Software, and to permit persons to whom the Software
  206.43 +// is furnished to do so, subject to the following conditions:
  206.44 +//
  206.45 +// The above copyright notice and this permission notice shall be included in
  206.46 +// all copies or substantial portions of the Software.
  206.47 +//
  206.48 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  206.49 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  206.50 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  206.51 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  206.52 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  206.53 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  206.54 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  206.55 +//
  206.56 +//---------------------------------------------------------------------------------
  206.57 +//
  206.58 +// Version 2.0
  206.59 +//
  206.60 +
  206.61 +#ifndef _lcms2_H
  206.62 +
  206.63 +// ********** Configuration toggles ****************************************
  206.64 +
  206.65 +// Uncomment this one if you are using big endian machines
  206.66 +// #define CMS_USE_BIG_ENDIAN   1
  206.67 +
  206.68 +// Uncomment this one if your compiler/machine does NOT support the
  206.69 +// "long long" type.
  206.70 +// #define CMS_DONT_USE_INT64        1
  206.71 +
  206.72 +// Uncomment this if your compiler doesn't work with fast floor function
  206.73 +// #define CMS_DONT_USE_FAST_FLOOR 1
  206.74 +
  206.75 +// Uncomment this line if your system does not support multithreading
  206.76 +#define CMS_DONT_USE_PTHREADS    1
  206.77 +
  206.78 +// Uncomment this line if you want lcms to use the black point tag in profile,
  206.79 +// if commented, lcms will compute the black point by its own.
  206.80 +// It is safer to leave it commented out
  206.81 +// #define CMS_USE_PROFILE_BLACK_POINT_TAG    1
  206.82 +
  206.83 +// Uncomment this line if you are compiling as C++ and want a C++ API
  206.84 +// #define CMS_USE_CPP_API
  206.85 +
  206.86 +// Uncomment this line if you need strict CGATS syntax. Makes CGATS files to
  206.87 +// require "KEYWORD" on undefined identifiers, keep it comented out unless needed
  206.88 +// #define CMS_STRICT_CGATS  1
  206.89 +
  206.90 +// ********** End of configuration toggles ******************************
  206.91 +
  206.92 +// Needed for streams
  206.93 +#include <stdio.h>
  206.94 +
  206.95 +// Needed for portability (C99 per 7.1.2)
  206.96 +#include <limits.h>
  206.97 +#include <time.h>
  206.98 +#include <stddef.h>
  206.99 +
 206.100 +#ifndef CMS_USE_CPP_API
 206.101 +#   ifdef __cplusplus
 206.102 +extern "C" {
 206.103 +#   endif
 206.104 +#endif
 206.105 +
 206.106 +// Version/release
 206.107 +#define LCMS_VERSION        2000
 206.108 +
 206.109 +// I will give the chance of redefining basic types for compilers that are not fully C99 compliant
 206.110 +#ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
 206.111 +
 206.112 +// Base types
 206.113 +typedef unsigned char        cmsUInt8Number;   // That is guaranteed by the C99 spec
 206.114 +typedef signed char          cmsInt8Number;    // That is guaranteed by the C99 spec
 206.115 +
 206.116 +// IEEE float storage numbers
 206.117 +typedef float                cmsFloat32Number;
 206.118 +typedef double               cmsFloat64Number;
 206.119 +
 206.120 +// 16-bit base types
 206.121 +#if (USHRT_MAX == 65535U)
 206.122 + typedef unsigned short      cmsUInt16Number;
 206.123 +#elif (UINT_MAX == 65535U)
 206.124 + typedef unsigned int        cmsUInt16Number;
 206.125 +#else
 206.126 +#  error "Unable to find 16 bits unsigned type, unsupported compiler"
 206.127 +#endif
 206.128 +
 206.129 +#if (SHRT_MAX == 32767)
 206.130 +  typedef  short             cmsInt16Number;
 206.131 +#elif (INT_MAX == 32767)
 206.132 +  typedef  int               cmsInt16Number;
 206.133 +#else
 206.134 +#  error "Unable to find 16 bits signed type, unsupported compiler"
 206.135 +#endif
 206.136 +
 206.137 +// 32-bit base type
 206.138 +#if (UINT_MAX == 4294967295U)
 206.139 + typedef unsigned int        cmsUInt32Number;
 206.140 +#elif (ULONG_MAX == 4294967295U)
 206.141 + typedef unsigned long       cmsUInt32Number;
 206.142 +#else
 206.143 +#  error "Unable to find 32 bit unsigned type, unsupported compiler"
 206.144 +#endif
 206.145 +
 206.146 +#if (INT_MAX == +2147483647)
 206.147 + typedef  int                cmsInt32Number;
 206.148 +#elif (LONG_MAX == +2147483647)
 206.149 + typedef  long               cmsInt32Number;
 206.150 +#else
 206.151 +#  error "Unable to find 32 bit signed type, unsupported compiler"
 206.152 +#endif
 206.153 +
 206.154 +// 64-bit base types
 206.155 +#ifndef CMS_DONT_USE_INT64
 206.156 +#  if (ULONG_MAX  == 18446744073709551615U)
 206.157 +    typedef unsigned long   cmsUInt64Number;
 206.158 +#  elif (ULLONG_MAX == 18446744073709551615U)
 206.159 +      typedef unsigned long long   cmsUInt64Number;
 206.160 +#  else
 206.161 +#     define CMS_DONT_USE_INT64 1
 206.162 +#  endif
 206.163 +#  if (LONG_MAX == +9223372036854775807)
 206.164 +      typedef  long          cmsInt64Number;
 206.165 +#  elif (LLONG_MAX == +9223372036854775807)
 206.166 +      typedef  long long     cmsInt64Number;
 206.167 +#  else
 206.168 +#     define CMS_DONT_USE_INT64 1
 206.169 +#  endif
 206.170 +#endif
 206.171 +#endif
 206.172 +
 206.173 +// In the case 64 bit numbers are not supported by the compiler
 206.174 +#ifdef CMS_DONT_USE_INT64
 206.175 +    typedef cmsUInt32Number      cmsUInt64Number[2];
 206.176 +    typedef cmsInt32Number       cmsInt64Number[2];
 206.177 +#endif
 206.178 +
 206.179 +// Derivative types
 206.180 +typedef cmsUInt32Number      cmsSignature;
 206.181 +typedef cmsUInt16Number      cmsU8Fixed8Number;
 206.182 +typedef cmsInt32Number       cmsS15Fixed16Number;
 206.183 +typedef cmsUInt32Number      cmsU16Fixed16Number;
 206.184 +
 206.185 +// Boolean type, which will be using the native integer
 206.186 +typedef int                  cmsBool;
 206.187 +
 206.188 +// Try to detect windows
 206.189 +#if defined (_WIN32) || defined(_WIN64) || defined(WIN32) || defined(_WIN32_)
 206.190 +#  define CMS_IS_WINDOWS_ 1
 206.191 +#endif
 206.192 +
 206.193 +#ifdef _MSC_VER
 206.194 +#  define CMS_IS_WINDOWS_ 1
 206.195 +#endif
 206.196 +
 206.197 +#ifdef __BORLANDC__
 206.198 +#  define CMS_IS_WINDOWS_ 1
 206.199 +#endif
 206.200 +
 206.201 +// Try to detect big endian platforms. This list can be endless, so only some checks are performed over here.
 206.202 +// you can pass this toggle to the compiler by using -DCMS_USE_BIG_ENDIAN or something similar
 206.203 +
 206.204 +#if defined(_HOST_BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(WORDS_BIGENDIAN)
 206.205 +#   define CMS_USE_BIG_ENDIAN      1
 206.206 +#endif
 206.207 +
 206.208 +#if defined(__sgi__) || defined(__sgi) || defined(__powerpc__) || defined(sparc)
 206.209 +#   define CMS_USE_BIG_ENDIAN      1
 206.210 +#endif
 206.211 +
 206.212 +#if defined(__ppc__) || defined(__s390__) || defined(__s390x__)
 206.213 +#   define CMS_USE_BIG_ENDIAN   1
 206.214 +#endif
 206.215 +
 206.216 +#ifdef TARGET_CPU_PPC
 206.217 +#   define CMS_USE_BIG_ENDIAN   1
 206.218 +#endif
 206.219 +
 206.220 +#ifdef macintosh
 206.221 +# ifndef __LITTLE_ENDIAN__
 206.222 +#   define CMS_USE_BIG_ENDIAN      1
 206.223 +# endif
 206.224 +#endif
 206.225 +
 206.226 +// Calling convention -- this is hardly platform and compiler dependent
 206.227 +#ifdef CMS_IS_WINDOWS_
 206.228 +#  if defined(CMS_DLL) || defined(CMS_DLL_BUILD)
 206.229 +#     ifdef __BORLANDC__
 206.230 +#        define CMSEXPORT       __stdcall _export
 206.231 +#        define CMSAPI
 206.232 +#     else
 206.233 +#        define CMSEXPORT      _stdcall
 206.234 +#        ifdef CMS_DLL_BUILD
 206.235 +#            define CMSAPI    __declspec(dllexport)
 206.236 +#        else
 206.237 +#           define CMSAPI     __declspec(dllimport)
 206.238 +#       endif
 206.239 +#     endif
 206.240 +#  else
 206.241 +#       define CMSEXPORT
 206.242 +#       define CMSAPI
 206.243 +#  endif
 206.244 +#else
 206.245 +# define CMSEXPORT
 206.246 +# define CMSAPI
 206.247 +#endif
 206.248 +
 206.249 +// Some common definitions
 206.250 +#define cmsMAX_PATH     256
 206.251 +
 206.252 +#ifndef FALSE
 206.253 +#       define FALSE 0
 206.254 +#endif
 206.255 +#ifndef TRUE
 206.256 +#       define TRUE  1
 206.257 +#endif
 206.258 +
 206.259 +// D50 XYZ normalized to Y=1.0
 206.260 +#define cmsD50X             0.9642
 206.261 +#define cmsD50Y             1.0
 206.262 +#define cmsD50Z             0.8249
 206.263 +
 206.264 +// V4 perceptual black
 206.265 +#define cmsPERCEPTUAL_BLACK_X  0.00336
 206.266 +#define cmsPERCEPTUAL_BLACK_Y  0.0034731
 206.267 +#define cmsPERCEPTUAL_BLACK_Z  0.00287
 206.268 +
 206.269 +// Definitions in ICC spec
 206.270 +#define cmsMagicNumber      0x61637370     // 'acsp'
 206.271 +#define lcmsSignature       0x6c636d73     // 'lcms'
 206.272 +
 206.273 +
 206.274 +// Base ICC type definitions
 206.275 +typedef enum {
 206.276 +    cmsSigChromaticityType                  = 0x6368726D,  // 'chrm'
 206.277 +    cmsSigColorantOrderType                 = 0x636C726F,  // 'clro'
 206.278 +    cmsSigColorantTableType                 = 0x636C7274,  // 'clrt'
 206.279 +    cmsSigCrdInfoType                       = 0x63726469,  // 'crdi'
 206.280 +    cmsSigCurveType                         = 0x63757276,  // 'curv'
 206.281 +    cmsSigDataType                          = 0x64617461,  // 'data'
 206.282 +    cmsSigDateTimeType                      = 0x6474696D,  // 'dtim'
 206.283 +    cmsSigDeviceSettingsType                = 0x64657673,  // 'devs'
 206.284 +    cmsSigLut16Type                         = 0x6d667432,  // 'mft2'
 206.285 +    cmsSigLut8Type                          = 0x6d667431,  // 'mft1'
 206.286 +    cmsSigLutAtoBType                       = 0x6d414220,  // 'mAB '
 206.287 +    cmsSigLutBtoAType                       = 0x6d424120,  // 'mBA '
 206.288 +    cmsSigMeasurementType                   = 0x6D656173,  // 'meas'
 206.289 +    cmsSigMultiLocalizedUnicodeType         = 0x6D6C7563,  // 'mluc'
 206.290 +    cmsSigMultiProcessElementType           = 0x6D706574,  // 'mpet'
 206.291 +    cmsSigNamedColorType                    = 0x6E636f6C,  // 'ncol' -- DEPRECATED!
 206.292 +    cmsSigNamedColor2Type                   = 0x6E636C32,  // 'ncl2'
 206.293 +    cmsSigParametricCurveType               = 0x70617261,  // 'para'
 206.294 +    cmsSigProfileSequenceDescType           = 0x70736571,  // 'pseq'
 206.295 +    cmsSigProfileSequenceIdType             = 0x70736964,  // 'psid'
 206.296 +    cmsSigResponseCurveSet16Type            = 0x72637332,  // 'rcs2'
 206.297 +    cmsSigS15Fixed16ArrayType               = 0x73663332,  // 'sf32'
 206.298 +    cmsSigScreeningType                     = 0x7363726E,  // 'scrn'
 206.299 +    cmsSigSignatureType                     = 0x73696720,  // 'sig '
 206.300 +    cmsSigTextType                          = 0x74657874,  // 'text'
 206.301 +    cmsSigTextDescriptionType               = 0x64657363,  // 'desc'
 206.302 +    cmsSigU16Fixed16ArrayType               = 0x75663332,  // 'uf32'
 206.303 +    cmsSigUcrBgType                         = 0x62666420,  // 'bfd '
 206.304 +    cmsSigUInt16ArrayType                   = 0x75693136,  // 'ui16'
 206.305 +    cmsSigUInt32ArrayType                   = 0x75693332,  // 'ui32'
 206.306 +    cmsSigUInt64ArrayType                   = 0x75693634,  // 'ui64'
 206.307 +    cmsSigUInt8ArrayType                    = 0x75693038,  // 'ui08'
 206.308 +    cmsSigViewingConditionsType             = 0x76696577,  // 'view'
 206.309 +    cmsSigXYZType                           = 0x58595A20,  // 'XYZ '
 206.310 +    cmsSigVcgtType                          = 0x76636774   // 'vcgt'
 206.311 +
 206.312 +} cmsTagTypeSignature;
 206.313 +
 206.314 +// Base ICC tag definitions
 206.315 +typedef enum {
 206.316 +    cmsSigAToB0Tag                          = 0x41324230,  // 'A2B0'
 206.317 +    cmsSigAToB1Tag                          = 0x41324231,  // 'A2B1'
 206.318 +    cmsSigAToB2Tag                          = 0x41324232,  // 'A2B2'
 206.319 +    cmsSigBlueColorantTag                   = 0x6258595A,  // 'bXYZ'
 206.320 +    cmsSigBlueMatrixColumnTag               = 0x6258595A,  // 'bXYZ'
 206.321 +    cmsSigBlueTRCTag                        = 0x62545243,  // 'bTRC'
 206.322 +    cmsSigBToA0Tag                          = 0x42324130,  // 'B2A0'
 206.323 +    cmsSigBToA1Tag                          = 0x42324131,  // 'B2A1'
 206.324 +    cmsSigBToA2Tag                          = 0x42324132,  // 'B2A2'
 206.325 +    cmsSigCalibrationDateTimeTag            = 0x63616C74,  // 'calt'
 206.326 +    cmsSigCharTargetTag                     = 0x74617267,  // 'targ'
 206.327 +    cmsSigChromaticAdaptationTag            = 0x63686164,  // 'chad'
 206.328 +    cmsSigChromaticityTag                   = 0x6368726D,  // 'chrm'
 206.329 +    cmsSigColorantOrderTag                  = 0x636C726F,  // 'clro'
 206.330 +    cmsSigColorantTableTag                  = 0x636C7274,  // 'clrt'
 206.331 +    cmsSigColorantTableOutTag               = 0x636C6F74,  // 'clot'
 206.332 +    cmsSigColorimetricIntentImageStateTag   = 0x63696973,  // 'ciis'
 206.333 +    cmsSigCopyrightTag                      = 0x63707274,  // 'cprt'
 206.334 +    cmsSigCrdInfoTag                        = 0x63726469,  // 'crdi'
 206.335 +    cmsSigDataTag                           = 0x64617461,  // 'data'
 206.336 +    cmsSigDateTimeTag                       = 0x6474696D,  // 'dtim'
 206.337 +    cmsSigDeviceMfgDescTag                  = 0x646D6E64,  // 'dmnd'
 206.338 +    cmsSigDeviceModelDescTag                = 0x646D6464,  // 'dmdd'
 206.339 +    cmsSigDeviceSettingsTag                 = 0x64657673,  // 'devs'
 206.340 +    cmsSigDToB0Tag                          = 0x44324230,  // 'D2B0'
 206.341 +    cmsSigDToB1Tag                          = 0x44324231,  // 'D2B1'
 206.342 +    cmsSigDToB2Tag                          = 0x44324232,  // 'D2B2'
 206.343 +    cmsSigDToB3Tag                          = 0x44324233,  // 'D2B3'
 206.344 +    cmsSigBToD0Tag                          = 0x42324430,  // 'B2D0'
 206.345 +    cmsSigBToD1Tag                          = 0x42324431,  // 'B2D1'
 206.346 +    cmsSigBToD2Tag                          = 0x42324432,  // 'B2D2'
 206.347 +    cmsSigBToD3Tag                          = 0x42324433,  // 'B2D3'
 206.348 +    cmsSigGamutTag                          = 0x67616D74,  // 'gamt'
 206.349 +    cmsSigGrayTRCTag                        = 0x6b545243,  // 'kTRC'
 206.350 +    cmsSigGreenColorantTag                  = 0x6758595A,  // 'gXYZ'
 206.351 +    cmsSigGreenMatrixColumnTag              = 0x6758595A,  // 'gXYZ'
 206.352 +    cmsSigGreenTRCTag                       = 0x67545243,  // 'gTRC'
 206.353 +    cmsSigLuminanceTag                      = 0x6C756d69,  // 'lumi'
 206.354 +    cmsSigMeasurementTag                    = 0x6D656173,  // 'meas'
 206.355 +    cmsSigMediaBlackPointTag                = 0x626B7074,  // 'bkpt'
 206.356 +    cmsSigMediaWhitePointTag                = 0x77747074,  // 'wtpt'
 206.357 +    cmsSigNamedColorTag                     = 0x6E636f6C,  // 'ncol' // Deprecated by the ICC
 206.358 +    cmsSigNamedColor2Tag                    = 0x6E636C32,  // 'ncl2'
 206.359 +    cmsSigOutputResponseTag                 = 0x72657370,  // 'resp'
 206.360 +    cmsSigPerceptualRenderingIntentGamutTag = 0x72696730,  // 'rig0'
 206.361 +    cmsSigPreview0Tag                       = 0x70726530,  // 'pre0'
 206.362 +    cmsSigPreview1Tag                       = 0x70726531,  // 'pre1'
 206.363 +    cmsSigPreview2Tag                       = 0x70726532,  // 'pre2'
 206.364 +    cmsSigProfileDescriptionTag             = 0x64657363,  // 'desc'
 206.365 +    cmsSigProfileSequenceDescTag            = 0x70736571,  // 'pseq'
 206.366 +    cmsSigProfileSequenceIdTag              = 0x70736964,  // 'psid'
 206.367 +    cmsSigPs2CRD0Tag                        = 0x70736430,  // 'psd0'
 206.368 +    cmsSigPs2CRD1Tag                        = 0x70736431,  // 'psd1'
 206.369 +    cmsSigPs2CRD2Tag                        = 0x70736432,  // 'psd2'
 206.370 +    cmsSigPs2CRD3Tag                        = 0x70736433,  // 'psd3'
 206.371 +    cmsSigPs2CSATag                         = 0x70733273,  // 'ps2s'
 206.372 +    cmsSigPs2RenderingIntentTag             = 0x70733269,  // 'ps2i'
 206.373 +    cmsSigRedColorantTag                    = 0x7258595A,  // 'rXYZ'
 206.374 +    cmsSigRedMatrixColumnTag                = 0x7258595A,  // 'rXYZ'
 206.375 +    cmsSigRedTRCTag                         = 0x72545243,  // 'rTRC'
 206.376 +    cmsSigSaturationRenderingIntentGamutTag = 0x72696732,  // 'rig2'
 206.377 +    cmsSigScreeningDescTag                  = 0x73637264,  // 'scrd'
 206.378 +    cmsSigScreeningTag                      = 0x7363726E,  // 'scrn'
 206.379 +    cmsSigTechnologyTag                     = 0x74656368,  // 'tech'
 206.380 +    cmsSigUcrBgTag                          = 0x62666420,  // 'bfd '
 206.381 +    cmsSigViewingCondDescTag                = 0x76756564,  // 'vued'
 206.382 +    cmsSigViewingConditionsTag              = 0x76696577,  // 'view'
 206.383 +    cmsSigVcgtTag                           = 0x76636774   // 'vcgt'
 206.384 +
 206.385 +} cmsTagSignature;
 206.386 +
 206.387 +
 206.388 +// ICC Technology tag
 206.389 +typedef enum {
 206.390 +    cmsSigDigitalCamera                     = 0x6463616D,  // 'dcam'
 206.391 +    cmsSigFilmScanner                       = 0x6673636E,  // 'fscn'
 206.392 +    cmsSigReflectiveScanner                 = 0x7273636E,  // 'rscn'
 206.393 +    cmsSigInkJetPrinter                     = 0x696A6574,  // 'ijet'
 206.394 +    cmsSigThermalWaxPrinter                 = 0x74776178,  // 'twax'
 206.395 +    cmsSigElectrophotographicPrinter        = 0x6570686F,  // 'epho'
 206.396 +    cmsSigElectrostaticPrinter              = 0x65737461,  // 'esta'
 206.397 +    cmsSigDyeSublimationPrinter             = 0x64737562,  // 'dsub'
 206.398 +    cmsSigPhotographicPaperPrinter          = 0x7270686F,  // 'rpho'
 206.399 +    cmsSigFilmWriter                        = 0x6670726E,  // 'fprn'
 206.400 +    cmsSigVideoMonitor                      = 0x7669646D,  // 'vidm'
 206.401 +    cmsSigVideoCamera                       = 0x76696463,  // 'vidc'
 206.402 +    cmsSigProjectionTelevision              = 0x706A7476,  // 'pjtv'
 206.403 +    cmsSigCRTDisplay                        = 0x43525420,  // 'CRT '
 206.404 +    cmsSigPMDisplay                         = 0x504D4420,  // 'PMD '
 206.405 +    cmsSigAMDisplay                         = 0x414D4420,  // 'AMD '
 206.406 +    cmsSigPhotoCD                           = 0x4B504344,  // 'KPCD'
 206.407 +    cmsSigPhotoImageSetter                  = 0x696D6773,  // 'imgs'
 206.408 +    cmsSigGravure                           = 0x67726176,  // 'grav'
 206.409 +    cmsSigOffsetLithography                 = 0x6F666673,  // 'offs'
 206.410 +    cmsSigSilkscreen                        = 0x73696C6B,  // 'silk'
 206.411 +    cmsSigFlexography                       = 0x666C6578,  // 'flex'
 206.412 +    cmsSigMotionPictureFilmScanner          = 0x6D706673,  // 'mpfs'
 206.413 +    cmsSigMotionPictureFilmRecorder         = 0x6D706672,  // 'mpfr'
 206.414 +    cmsSigDigitalMotionPictureCamera        = 0x646D7063,  // 'dmpc'
 206.415 +    cmsSigDigitalCinemaProjector            = 0x64636A70,  // 'dcpj'
 206.416 +
 206.417 +} cmsTechnologySignature;
 206.418 +
 206.419 +
 206.420 +// ICC Color spaces
 206.421 +typedef enum {
 206.422 +    cmsSigXYZData                           = 0x58595A20,  // 'XYZ '
 206.423 +    cmsSigLabData                           = 0x4C616220,  // 'Lab '
 206.424 +    cmsSigLuvData                           = 0x4C757620,  // 'Luv '
 206.425 +    cmsSigYCbCrData                         = 0x59436272,  // 'YCbr'
 206.426 +    cmsSigYxyData                           = 0x59787920,  // 'Yxy '
 206.427 +    cmsSigRgbData                           = 0x52474220,  // 'RGB '
 206.428 +    cmsSigGrayData                          = 0x47524159,  // 'GRAY'
 206.429 +    cmsSigHsvData                           = 0x48535620,  // 'HSV '
 206.430 +    cmsSigHlsData                           = 0x484C5320,  // 'HLS '
 206.431 +    cmsSigCmykData                          = 0x434D594B,  // 'CMYK'
 206.432 +    cmsSigCmyData                           = 0x434D5920,  // 'CMY '
 206.433 +    cmsSigMCH1Data                          = 0x4D434831,  // 'MCH1'
 206.434 +    cmsSigMCH2Data                          = 0x4D434832,  // 'MCH2'
 206.435 +    cmsSigMCH3Data                          = 0x4D434833,  // 'MCH3'
 206.436 +    cmsSigMCH4Data                          = 0x4D434834,  // 'MCH4'
 206.437 +    cmsSigMCH5Data                          = 0x4D434835,  // 'MCH5'
 206.438 +    cmsSigMCH6Data                          = 0x4D434836,  // 'MCH6'
 206.439 +    cmsSigMCH7Data                          = 0x4D434837,  // 'MCH7'
 206.440 +    cmsSigMCH8Data                          = 0x4D434838,  // 'MCH8'
 206.441 +    cmsSigMCH9Data                          = 0x4D434839,  // 'MCH9'
 206.442 +    cmsSigMCHAData                          = 0x4D43483A,  // 'MCHA'
 206.443 +    cmsSigMCHBData                          = 0x4D43483B,  // 'MCHB'
 206.444 +    cmsSigMCHCData                          = 0x4D43483C,  // 'MCHC'
 206.445 +    cmsSigMCHDData                          = 0x4D43483D,  // 'MCHD'
 206.446 +    cmsSigMCHEData                          = 0x4D43483E,  // 'MCHE'
 206.447 +    cmsSigMCHFData                          = 0x4D43483F,  // 'MCHF'
 206.448 +    cmsSigNamedData                         = 0x6e6d636c,  // 'nmcl'
 206.449 +    cmsSig1colorData                        = 0x31434C52,  // '1CLR'
 206.450 +    cmsSig2colorData                        = 0x32434C52,  // '2CLR'
 206.451 +    cmsSig3colorData                        = 0x33434C52,  // '3CLR'
 206.452 +    cmsSig4colorData                        = 0x34434C52,  // '4CLR'
 206.453 +    cmsSig5colorData                        = 0x35434C52,  // '5CLR'
 206.454 +    cmsSig6colorData                        = 0x36434C52,  // '6CLR'
 206.455 +    cmsSig7colorData                        = 0x37434C52,  // '7CLR'
 206.456 +    cmsSig8colorData                        = 0x38434C52,  // '8CLR'
 206.457 +    cmsSig9colorData                        = 0x39434C52,  // '9CLR'
 206.458 +    cmsSig10colorData                       = 0x41434C52,  // 'ACLR'
 206.459 +    cmsSig11colorData                       = 0x42434C52,  // 'BCLR'
 206.460 +    cmsSig12colorData                       = 0x43434C52,  // 'CCLR'
 206.461 +    cmsSig13colorData                       = 0x44434C52,  // 'DCLR'
 206.462 +    cmsSig14colorData                       = 0x45434C52,  // 'ECLR'
 206.463 +    cmsSig15colorData                       = 0x46434C52,  // 'FCLR'
 206.464 +    cmsSigLuvKData                          = 0x4C75764B   // 'LuvK'
 206.465 +
 206.466 +} cmsColorSpaceSignature;
 206.467 +
 206.468 +// ICC Profile Class
 206.469 +typedef enum {
 206.470 +    cmsSigInputClass                        = 0x73636E72,  // 'scnr'
 206.471 +    cmsSigDisplayClass                      = 0x6D6E7472,  // 'mntr'
 206.472 +    cmsSigOutputClass                       = 0x70727472,  // 'prtr'
 206.473 +    cmsSigLinkClass                         = 0x6C696E6B,  // 'link'
 206.474 +    cmsSigAbstractClass                     = 0x61627374,  // 'abst'
 206.475 +    cmsSigColorSpaceClass                   = 0x73706163,  // 'spac'
 206.476 +    cmsSigNamedColorClass                   = 0x6e6d636c,  // 'nmcl'
 206.477 +
 206.478 +} cmsProfileClassSignature;
 206.479 +
 206.480 +// ICC Platforms
 206.481 +typedef enum {
 206.482 +    cmsSigMacintosh                         = 0x4150504C,  // 'APPL'
 206.483 +    cmsSigMicrosoft                         = 0x4D534654,  // 'MSFT'
 206.484 +    cmsSigSolaris                           = 0x53554E57,  // 'SUNW'
 206.485 +    cmsSigSGI                               = 0x53474920,  // 'SGI '
 206.486 +    cmsSigTaligent                          = 0x54474E54,  // 'TGNT'
 206.487 +    cmsSigUnices                            = 0x2A6E6978   // '*nix'   // From argyll -- Not official
 206.488 +
 206.489 +} cmsPlatformSignature;
 206.490 +
 206.491 +// Reference gamut
 206.492 +#define  cmsSigPerceptualReferenceMediumGamut         0x70726d67  //'prmg'
 206.493 +
 206.494 +// For cmsSigColorimetricIntentImageStateTag
 206.495 +#define  cmsSigSceneColorimetryEstimates              0x73636F65  //'scoe'
 206.496 +#define  cmsSigSceneAppearanceEstimates               0x73617065  //'sape'
 206.497 +#define  cmsSigFocalPlaneColorimetryEstimates         0x66706365  //'fpce'
 206.498 +#define  cmsSigReflectionHardcopyOriginalColorimetry  0x72686F63  //'rhoc'
 206.499 +#define  cmsSigReflectionPrintOutputColorimetry       0x72706F63  //'rpoc'
 206.500 +
 206.501 +// Multi process elements types
 206.502 +typedef enum {
 206.503 +    cmsSigCurveSetElemType              = 0x63767374,  //'cvst'
 206.504 +    cmsSigMatrixElemType                = 0x6D617466,  //'matf'
 206.505 +    cmsSigCLutElemType                  = 0x636C7574,  //'clut'
 206.506 +
 206.507 +    cmsSigBAcsElemType                  = 0x62414353,  // 'bACS'
 206.508 +    cmsSigEAcsElemType                  = 0x65414353,  // 'eACS'
 206.509 +
 206.510 +    // Custom from here, not in the ICC Spec
 206.511 +    cmsSigXYZ2LabElemType               = 0x6C327820,  // 'l2x '
 206.512 +    cmsSigLab2XYZElemType               = 0x78326C20,  // 'x2l '
 206.513 +    cmsSigNamedColorElemType            = 0x6E636C20,  // 'ncl '
 206.514 +    cmsSigLabV2toV4                     = 0x32203420,  // '2 4 '
 206.515 +    cmsSigLabV4toV2                     = 0x34203220,  // '4 2 '
 206.516 +
 206.517 +    // Identities
 206.518 +    cmsSigIdentityElemType              = 0x69646E20   // 'idn '
 206.519 +
 206.520 +} cmsStageSignature;
 206.521 +
 206.522 +// Types of CurveElements
 206.523 +typedef enum {
 206.524 +
 206.525 +    cmsSigFormulaCurveSeg               = 0x70617266, // 'parf'
 206.526 +    cmsSigSampledCurveSeg               = 0x73616D66, // 'samf'
 206.527 +    cmsSigSegmentedCurve                = 0x63757266  // 'curf'
 206.528 +
 206.529 +} cmsCurveSegSignature;
 206.530 +
 206.531 +// Used in ResponseCurveType
 206.532 +#define  cmsSigStatusA                    0x53746141 //'StaA'
 206.533 +#define  cmsSigStatusE                    0x53746145 //'StaE'
 206.534 +#define  cmsSigStatusI                    0x53746149 //'StaI'
 206.535 +#define  cmsSigStatusT                    0x53746154 //'StaT'
 206.536 +#define  cmsSigStatusM                    0x5374614D //'StaM'
 206.537 +#define  cmsSigDN                         0x444E2020 //'DN  '
 206.538 +#define  cmsSigDNP                        0x444E2050 //'DN P'
 206.539 +#define  cmsSigDNN                        0x444E4E20 //'DNN '
 206.540 +#define  cmsSigDNNP                       0x444E4E50 //'DNNP'
 206.541 +
 206.542 +// Device attributes, currently defined values correspond to the low 4 bytes
 206.543 +// of the 8 byte attribute quantity
 206.544 +#define cmsReflective     0
 206.545 +#define cmsTransparency   1
 206.546 +#define cmsGlossy         0
 206.547 +#define cmsMatte          2
 206.548 +
 206.549 +// Common structures in ICC tags
 206.550 +typedef struct {
 206.551 +    cmsUInt32Number len;
 206.552 +    cmsUInt32Number flag;
 206.553 +    cmsUInt8Number  data[1];
 206.554 +
 206.555 +} cmsICCData;
 206.556 +
 206.557 +// ICC date time
 206.558 +typedef struct {
 206.559 +    cmsUInt16Number      year;
 206.560 +    cmsUInt16Number      month;
 206.561 +    cmsUInt16Number      day;
 206.562 +    cmsUInt16Number      hours;
 206.563 +    cmsUInt16Number      minutes;
 206.564 +    cmsUInt16Number      seconds;
 206.565 +
 206.566 +} cmsDateTimeNumber;
 206.567 +
 206.568 +// ICC XYZ
 206.569 +typedef struct {
 206.570 +    cmsS15Fixed16Number  X;
 206.571 +    cmsS15Fixed16Number  Y;
 206.572 +    cmsS15Fixed16Number  Z;
 206.573 +
 206.574 +} cmsEncodedXYZNumber;
 206.575 +
 206.576 +
 206.577 +// Profile ID as computed by MD5 algorithm
 206.578 +typedef union {
 206.579 +    cmsUInt8Number       ID8[16];
 206.580 +    cmsUInt16Number      ID16[8];
 206.581 +    cmsUInt32Number      ID32[4];
 206.582 +
 206.583 +} cmsProfileID;
 206.584 +
 206.585 +
 206.586 +// ----------------------------------------------------------------------------------------------
 206.587 +// ICC profile internal base types. Strictly, shouldn't be declared in this header, but maybe
 206.588 +// somebody want to use this info for accessing profile header directly, so here it is.
 206.589 +
 206.590 +// Profile header -- it is 32-bit aligned, so no issues are expected on alignment
 206.591 +typedef struct {
 206.592 +    cmsUInt32Number              size;           // Profile size in bytes
 206.593 +    cmsSignature                 cmmId;          // CMM for this profile
 206.594 +    cmsUInt32Number              version;        // Format version number
 206.595 +    cmsProfileClassSignature     deviceClass;    // Type of profile
 206.596 +    cmsColorSpaceSignature       colorSpace;     // Color space of data
 206.597 +    cmsColorSpaceSignature       pcs;            // PCS, XYZ or Lab only
 206.598 +    cmsDateTimeNumber            date;           // Date profile was created
 206.599 +    cmsSignature                 magic;          // Magic Number to identify an ICC profile
 206.600 +    cmsPlatformSignature         platform;       // Primary Platform
 206.601 +    cmsUInt32Number              flags;          // Various bit settings
 206.602 +    cmsSignature                 manufacturer;   // Device manufacturer
 206.603 +    cmsUInt32Number              model;          // Device model number
 206.604 +    cmsUInt64Number              attributes;     // Device attributes
 206.605 +    cmsUInt32Number              renderingIntent;// Rendering intent
 206.606 +    cmsEncodedXYZNumber          illuminant;     // Profile illuminant
 206.607 +    cmsSignature                 creator;        // Profile creator
 206.608 +    cmsProfileID                 profileID;      // Profile ID using MD5
 206.609 +    cmsInt8Number                reserved[28];   // Reserved for future use
 206.610 +
 206.611 +} cmsICCHeader;
 206.612 +
 206.613 +// ICC base tag
 206.614 +typedef struct {
 206.615 +    cmsTagTypeSignature  sig;
 206.616 +    cmsInt8Number        reserved[4];
 206.617 +
 206.618 +} cmsTagBase;
 206.619 +
 206.620 +// A tag entry in directory
 206.621 +typedef struct {
 206.622 +    cmsTagSignature      sig;            // The tag signature
 206.623 +    cmsUInt32Number      offset;         // Start of tag
 206.624 +    cmsUInt32Number      size;           // Size in bytes
 206.625 +
 206.626 +} cmsTagEntry;
 206.627 +
 206.628 +// ----------------------------------------------------------------------------------------------
 206.629 +
 206.630 +// Little CMS specific typedefs
 206.631 +
 206.632 +typedef void* cmsContext;              // Context identifier for multithreaded environments
 206.633 +typedef void* cmsHANDLE ;              // Generic handle
 206.634 +typedef void* cmsHPROFILE;             // Opaque typedefs to hide internals
 206.635 +typedef void* cmsHTRANSFORM;
 206.636 +
 206.637 +#define cmsMAXCHANNELS  16                // Maximum number of channels in ICC profiles
 206.638 +
 206.639 +// Format of pixel is defined by one cmsUInt32Number, using bit fields as follows
 206.640 +//
 206.641 +//            A O TTTTT U Y F P X S EEE CCCC BBB
 206.642 +//
 206.643 +//            A: Floating point -- With this flag we can differentiate 16 bits as float and as int
 206.644 +//            O: Optimized -- previous optimization already returns the final 8-bit value
 206.645 +//            T: Pixeltype
 206.646 +//            F: Flavor  0=MinIsBlack(Chocolate) 1=MinIsWhite(Vanilla)
 206.647 +//            P: Planar? 0=Chunky, 1=Planar
 206.648 +//            X: swap 16 bps endianess?
 206.649 +//            S: Do swap? ie, BGR, KYMC
 206.650 +//            E: Extra samples
 206.651 +//            C: Channels (Samples per pixel)
 206.652 +//            B: bytes per sample
 206.653 +//            Y: Swap first - changes ABGR to BGRA and KCMY to CMYK
 206.654 +
 206.655 +#define FLOAT_SH(a)            ((a) << 22)
 206.656 +#define OPTIMIZED_SH(s)        ((s) << 21)
 206.657 +#define COLORSPACE_SH(s)       ((s) << 16)
 206.658 +#define SWAPFIRST_SH(s)        ((s) << 14)
 206.659 +#define FLAVOR_SH(s)           ((s) << 13)
 206.660 +#define PLANAR_SH(p)           ((p) << 12)
 206.661 +#define ENDIAN16_SH(e)         ((e) << 11)
 206.662 +#define DOSWAP_SH(e)           ((e) << 10)
 206.663 +#define EXTRA_SH(e)            ((e) << 7)
 206.664 +#define CHANNELS_SH(c)         ((c) << 3)
 206.665 +#define BYTES_SH(b)            (b)
 206.666 +
 206.667 +// These macros unpack format specifiers into integers
 206.668 +#define T_FLOAT(a)            (((a)>>22)&1)
 206.669 +#define T_OPTIMIZED(o)        (((o)>>21)&1)
 206.670 +#define T_COLORSPACE(s)       (((s)>>16)&31)
 206.671 +#define T_SWAPFIRST(s)        (((s)>>14)&1)
 206.672 +#define T_FLAVOR(s)           (((s)>>13)&1)
 206.673 +#define T_PLANAR(p)           (((p)>>12)&1)
 206.674 +#define T_ENDIAN16(e)         (((e)>>11)&1)
 206.675 +#define T_DOSWAP(e)           (((e)>>10)&1)
 206.676 +#define T_EXTRA(e)            (((e)>>7)&7)
 206.677 +#define T_CHANNELS(c)         (((c)>>3)&15)
 206.678 +#define T_BYTES(b)            ((b)&7)
 206.679 +
 206.680 +
 206.681 +// Pixel types
 206.682 +#define PT_ANY       0    // Don't check colorspace
 206.683 +                          // 1 & 2 are reserved
 206.684 +#define PT_GRAY      3
 206.685 +#define PT_RGB       4
 206.686 +#define PT_CMY       5
 206.687 +#define PT_CMYK      6
 206.688 +#define PT_YCbCr     7
 206.689 +#define PT_YUV       8      // Lu'v'
 206.690 +#define PT_XYZ       9
 206.691 +#define PT_Lab       10
 206.692 +#define PT_YUVK      11     // Lu'v'K
 206.693 +#define PT_HSV       12
 206.694 +#define PT_HLS       13
 206.695 +#define PT_Yxy       14
 206.696 +
 206.697 +#define PT_MCH1      15
 206.698 +#define PT_MCH2      16
 206.699 +#define PT_MCH3      17
 206.700 +#define PT_MCH4      18
 206.701 +#define PT_MCH5      19
 206.702 +#define PT_MCH6      20
 206.703 +#define PT_MCH7      21
 206.704 +#define PT_MCH8      22
 206.705 +#define PT_MCH9      23
 206.706 +#define PT_MCH10     24
 206.707 +#define PT_MCH11     25
 206.708 +#define PT_MCH12     26
 206.709 +#define PT_MCH13     27
 206.710 +#define PT_MCH14     28
 206.711 +#define PT_MCH15     29
 206.712 +
 206.713 +#define PT_LabV2     30     // Identical to PT_Lab, but using the V2 old encoding
 206.714 +
 206.715 +// Some (not all!) representations
 206.716 +
 206.717 +#ifndef TYPE_RGB_8      // TYPE_RGB_8 is a very common identifier, so don't include ours
 206.718 +                        // if user has it already defined.
 206.719 +
 206.720 +#define TYPE_GRAY_8            (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(1))
 206.721 +#define TYPE_GRAY_8_REV        (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(1)|FLAVOR_SH(1))
 206.722 +#define TYPE_GRAY_16           (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2))
 206.723 +#define TYPE_GRAY_16_REV       (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)|FLAVOR_SH(1))
 206.724 +#define TYPE_GRAY_16_SE        (COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.725 +#define TYPE_GRAYA_8           (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1))
 206.726 +#define TYPE_GRAYA_16          (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2))
 206.727 +#define TYPE_GRAYA_16_SE       (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.728 +#define TYPE_GRAYA_8_PLANAR    (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(1)|PLANAR_SH(1))
 206.729 +#define TYPE_GRAYA_16_PLANAR   (COLORSPACE_SH(PT_GRAY)|EXTRA_SH(1)|CHANNELS_SH(1)|BYTES_SH(2)|PLANAR_SH(1))
 206.730 +
 206.731 +#define TYPE_RGB_8             (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1))
 206.732 +#define TYPE_RGB_8_PLANAR      (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 206.733 +#define TYPE_BGR_8             (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1))
 206.734 +#define TYPE_BGR_8_PLANAR      (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|PLANAR_SH(1))
 206.735 +#define TYPE_RGB_16            (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2))
 206.736 +#define TYPE_RGB_16_PLANAR     (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 206.737 +#define TYPE_RGB_16_SE         (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.738 +#define TYPE_BGR_16            (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1))
 206.739 +#define TYPE_BGR_16_PLANAR     (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PLANAR_SH(1))
 206.740 +#define TYPE_BGR_16_SE         (COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.741 +
 206.742 +#define TYPE_RGBA_8            (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1))
 206.743 +#define TYPE_RGBA_8_PLANAR     (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 206.744 +#define TYPE_RGBA_16           (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
 206.745 +#define TYPE_RGBA_16_PLANAR    (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 206.746 +#define TYPE_RGBA_16_SE        (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.747 +
 206.748 +#define TYPE_ARGB_8            (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|SWAPFIRST_SH(1))
 206.749 +#define TYPE_ARGB_16           (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|SWAPFIRST_SH(1))
 206.750 +
 206.751 +#define TYPE_ABGR_8            (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1))
 206.752 +#define TYPE_ABGR_16           (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1))
 206.753 +#define TYPE_ABGR_16_PLANAR    (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|PLANAR_SH(1))
 206.754 +#define TYPE_ABGR_16_SE        (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.755 +
 206.756 +#define TYPE_BGRA_8            (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
 206.757 +#define TYPE_BGRA_16           (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
 206.758 +#define TYPE_BGRA_16_SE        (COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1)|SWAPFIRST_SH(1))
 206.759 +
 206.760 +#define TYPE_CMY_8             (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1))
 206.761 +#define TYPE_CMY_8_PLANAR      (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 206.762 +#define TYPE_CMY_16            (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2))
 206.763 +#define TYPE_CMY_16_PLANAR     (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 206.764 +#define TYPE_CMY_16_SE         (COLORSPACE_SH(PT_CMY)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.765 +
 206.766 +#define TYPE_CMYK_8            (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1))
 206.767 +#define TYPE_CMYKA_8           (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(1))
 206.768 +#define TYPE_CMYK_8_REV        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1))
 206.769 +#define TYPE_YUVK_8            TYPE_CMYK_8_REV
 206.770 +#define TYPE_CMYK_8_PLANAR     (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|PLANAR_SH(1))
 206.771 +#define TYPE_CMYK_16           (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2))
 206.772 +#define TYPE_CMYK_16_REV       (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1))
 206.773 +#define TYPE_YUVK_16           TYPE_CMYK_16_REV
 206.774 +#define TYPE_CMYK_16_PLANAR    (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|PLANAR_SH(1))
 206.775 +#define TYPE_CMYK_16_SE        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.776 +
 206.777 +#define TYPE_KYMC_8            (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1))
 206.778 +#define TYPE_KYMC_16           (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1))
 206.779 +#define TYPE_KYMC_16_SE        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.780 +
 206.781 +#define TYPE_KCMY_8            (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|SWAPFIRST_SH(1))
 206.782 +#define TYPE_KCMY_8_REV        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|FLAVOR_SH(1)|SWAPFIRST_SH(1))
 206.783 +#define TYPE_KCMY_16           (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|SWAPFIRST_SH(1))
 206.784 +#define TYPE_KCMY_16_REV       (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|FLAVOR_SH(1)|SWAPFIRST_SH(1))
 206.785 +#define TYPE_KCMY_16_SE        (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2)|ENDIAN16_SH(1)|SWAPFIRST_SH(1))
 206.786 +
 206.787 +#define TYPE_CMYK5_8           (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(1))
 206.788 +#define TYPE_CMYK5_16          (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(2))
 206.789 +#define TYPE_CMYK5_16_SE       (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.790 +#define TYPE_KYMC5_8           (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(1)|DOSWAP_SH(1))
 206.791 +#define TYPE_KYMC5_16          (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(2)|DOSWAP_SH(1))
 206.792 +#define TYPE_KYMC5_16_SE       (COLORSPACE_SH(PT_MCH5)|CHANNELS_SH(5)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.793 +#define TYPE_CMYK6_8           (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(1))
 206.794 +#define TYPE_CMYK6_8_PLANAR    (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(1)|PLANAR_SH(1))
 206.795 +#define TYPE_CMYK6_16          (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(2))
 206.796 +#define TYPE_CMYK6_16_PLANAR   (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(2)|PLANAR_SH(1))
 206.797 +#define TYPE_CMYK6_16_SE       (COLORSPACE_SH(PT_MCH6)|CHANNELS_SH(6)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.798 +#define TYPE_CMYK7_8           (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(1))
 206.799 +#define TYPE_CMYK7_16          (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(2))
 206.800 +#define TYPE_CMYK7_16_SE       (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.801 +#define TYPE_KYMC7_8           (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(1)|DOSWAP_SH(1))
 206.802 +#define TYPE_KYMC7_16          (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(2)|DOSWAP_SH(1))
 206.803 +#define TYPE_KYMC7_16_SE       (COLORSPACE_SH(PT_MCH7)|CHANNELS_SH(7)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.804 +#define TYPE_CMYK8_8           (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(1))
 206.805 +#define TYPE_CMYK8_16          (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(2))
 206.806 +#define TYPE_CMYK8_16_SE       (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.807 +#define TYPE_KYMC8_8           (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(1)|DOSWAP_SH(1))
 206.808 +#define TYPE_KYMC8_16          (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(2)|DOSWAP_SH(1))
 206.809 +#define TYPE_KYMC8_16_SE       (COLORSPACE_SH(PT_MCH8)|CHANNELS_SH(8)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.810 +#define TYPE_CMYK9_8           (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(1))
 206.811 +#define TYPE_CMYK9_16          (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(2))
 206.812 +#define TYPE_CMYK9_16_SE       (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.813 +#define TYPE_KYMC9_8           (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(1)|DOSWAP_SH(1))
 206.814 +#define TYPE_KYMC9_16          (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(2)|DOSWAP_SH(1))
 206.815 +#define TYPE_KYMC9_16_SE       (COLORSPACE_SH(PT_MCH9)|CHANNELS_SH(9)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.816 +#define TYPE_CMYK10_8          (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(1))
 206.817 +#define TYPE_CMYK10_16         (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(2))
 206.818 +#define TYPE_CMYK10_16_SE      (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.819 +#define TYPE_KYMC10_8          (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(1)|DOSWAP_SH(1))
 206.820 +#define TYPE_KYMC10_16         (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(2)|DOSWAP_SH(1))
 206.821 +#define TYPE_KYMC10_16_SE      (COLORSPACE_SH(PT_MCH10)|CHANNELS_SH(10)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.822 +#define TYPE_CMYK11_8          (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(1))
 206.823 +#define TYPE_CMYK11_16         (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(2))
 206.824 +#define TYPE_CMYK11_16_SE      (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.825 +#define TYPE_KYMC11_8          (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(1)|DOSWAP_SH(1))
 206.826 +#define TYPE_KYMC11_16         (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(2)|DOSWAP_SH(1))
 206.827 +#define TYPE_KYMC11_16_SE      (COLORSPACE_SH(PT_MCH11)|CHANNELS_SH(11)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.828 +#define TYPE_CMYK12_8          (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(1))
 206.829 +#define TYPE_CMYK12_16         (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(2))
 206.830 +#define TYPE_CMYK12_16_SE      (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.831 +#define TYPE_KYMC12_8          (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(1)|DOSWAP_SH(1))
 206.832 +#define TYPE_KYMC12_16         (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(2)|DOSWAP_SH(1))
 206.833 +#define TYPE_KYMC12_16_SE      (COLORSPACE_SH(PT_MCH12)|CHANNELS_SH(12)|BYTES_SH(2)|DOSWAP_SH(1)|ENDIAN16_SH(1))
 206.834 +
 206.835 +// Colorimetric
 206.836 +#define TYPE_XYZ_16            (COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(2))
 206.837 +#define TYPE_Lab_8             (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1))
 206.838 +#define TYPE_LabV2_8           (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1))
 206.839 +
 206.840 +#define TYPE_ALab_8            (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1))
 206.841 +#define TYPE_ALabV2_8          (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(1)|EXTRA_SH(1)|DOSWAP_SH(1))
 206.842 +#define TYPE_Lab_16            (COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(2))
 206.843 +#define TYPE_LabV2_16          (COLORSPACE_SH(PT_LabV2)|CHANNELS_SH(3)|BYTES_SH(2))
 206.844 +#define TYPE_Yxy_16            (COLORSPACE_SH(PT_Yxy)|CHANNELS_SH(3)|BYTES_SH(2))
 206.845 +
 206.846 +// YCbCr
 206.847 +#define TYPE_YCbCr_8           (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(1))
 206.848 +#define TYPE_YCbCr_8_PLANAR    (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 206.849 +#define TYPE_YCbCr_16          (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2))
 206.850 +#define TYPE_YCbCr_16_PLANAR   (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 206.851 +#define TYPE_YCbCr_16_SE       (COLORSPACE_SH(PT_YCbCr)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.852 +
 206.853 +// YUV
 206.854 +#define TYPE_YUV_8             (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(1))
 206.855 +#define TYPE_YUV_8_PLANAR      (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 206.856 +#define TYPE_YUV_16            (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2))
 206.857 +#define TYPE_YUV_16_PLANAR     (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 206.858 +#define TYPE_YUV_16_SE         (COLORSPACE_SH(PT_YUV)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.859 +
 206.860 +// HLS
 206.861 +#define TYPE_HLS_8             (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(1))
 206.862 +#define TYPE_HLS_8_PLANAR      (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 206.863 +#define TYPE_HLS_16            (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2))
 206.864 +#define TYPE_HLS_16_PLANAR     (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 206.865 +#define TYPE_HLS_16_SE         (COLORSPACE_SH(PT_HLS)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.866 +
 206.867 +// HSV
 206.868 +#define TYPE_HSV_8             (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(1))
 206.869 +#define TYPE_HSV_8_PLANAR      (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(1)|PLANAR_SH(1))
 206.870 +#define TYPE_HSV_16            (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2))
 206.871 +#define TYPE_HSV_16_PLANAR     (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)|PLANAR_SH(1))
 206.872 +#define TYPE_HSV_16_SE         (COLORSPACE_SH(PT_HSV)|CHANNELS_SH(3)|BYTES_SH(2)|ENDIAN16_SH(1))
 206.873 +
 206.874 +// Named color index. Only 16 bits allowed (don't check colorspace)
 206.875 +#define TYPE_NAMED_COLOR_INDEX (CHANNELS_SH(1)|BYTES_SH(2))
 206.876 +
 206.877 +// Float formatters.
 206.878 +#define TYPE_XYZ_FLT          (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(4))
 206.879 +#define TYPE_Lab_FLT          (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(4))
 206.880 +#define TYPE_GRAY_FLT         (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(4))
 206.881 +#define TYPE_RGB_FLT          (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4))
 206.882 +#define TYPE_CMYK_FLT         (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(4))
 206.883 +
 206.884 +// Floating point formatters.
 206.885 +// NOTE THAT 'BYTES' FIELD IS SET TO ZERO ON DLB because 8 bytes overflows the bitfield
 206.886 +#define TYPE_XYZ_DBL          (FLOAT_SH(1)|COLORSPACE_SH(PT_XYZ)|CHANNELS_SH(3)|BYTES_SH(0))
 206.887 +#define TYPE_Lab_DBL          (FLOAT_SH(1)|COLORSPACE_SH(PT_Lab)|CHANNELS_SH(3)|BYTES_SH(0))
 206.888 +#define TYPE_GRAY_DBL         (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(0))
 206.889 +#define TYPE_RGB_DBL          (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(0))
 206.890 +#define TYPE_CMYK_DBL         (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(0))
 206.891 +
 206.892 +#endif
 206.893 +
 206.894 +// Colorspaces
 206.895 +typedef struct {
 206.896 +        cmsFloat64Number X;
 206.897 +        cmsFloat64Number Y;
 206.898 +        cmsFloat64Number Z;
 206.899 +
 206.900 +    } cmsCIEXYZ;
 206.901 +
 206.902 +typedef struct {
 206.903 +        cmsFloat64Number x;
 206.904 +        cmsFloat64Number y;
 206.905 +        cmsFloat64Number Y;
 206.906 +
 206.907 +    } cmsCIExyY;
 206.908 +
 206.909 +typedef struct {
 206.910 +        cmsFloat64Number L;
 206.911 +        cmsFloat64Number a;
 206.912 +        cmsFloat64Number b;
 206.913 +
 206.914 +    } cmsCIELab;
 206.915 +
 206.916 +typedef struct {
 206.917 +        cmsFloat64Number L;
 206.918 +        cmsFloat64Number C;
 206.919 +        cmsFloat64Number h;
 206.920 +
 206.921 +    } cmsCIELCh;
 206.922 +
 206.923 +typedef struct {
 206.924 +        cmsFloat64Number J;
 206.925 +        cmsFloat64Number C;
 206.926 +        cmsFloat64Number h;
 206.927 +
 206.928 +    } cmsJCh;
 206.929 +
 206.930 +typedef struct {
 206.931 +        cmsCIEXYZ  Red;
 206.932 +        cmsCIEXYZ  Green;
 206.933 +        cmsCIEXYZ  Blue;
 206.934 +
 206.935 +    } cmsCIEXYZTRIPLE;
 206.936 +
 206.937 +typedef struct {
 206.938 +        cmsCIExyY  Red;
 206.939 +        cmsCIExyY  Green;
 206.940 +        cmsCIExyY  Blue;
 206.941 +
 206.942 +    } cmsCIExyYTRIPLE;
 206.943 +
 206.944 +// Illuminant types for structs below
 206.945 +#define cmsILLUMINANT_TYPE_UNKNOWN 0x0000000
 206.946 +#define cmsILLUMINANT_TYPE_D50     0x0000001
 206.947 +#define cmsILLUMINANT_TYPE_D65     0x0000002
 206.948 +#define cmsILLUMINANT_TYPE_D93     0x0000003
 206.949 +#define cmsILLUMINANT_TYPE_F2      0x0000004
 206.950 +#define cmsILLUMINANT_TYPE_D55     0x0000005
 206.951 +#define cmsILLUMINANT_TYPE_A       0x0000006
 206.952 +#define cmsILLUMINANT_TYPE_E       0x0000007
 206.953 +#define cmsILLUMINANT_TYPE_F8      0x0000008
 206.954 +
 206.955 +typedef struct {
 206.956 +        cmsUInt32Number  Observer;    // 0 = unknown, 1=CIE 1931, 2=CIE 1964
 206.957 +        cmsCIEXYZ        Backing;     // Value of backing
 206.958 +        cmsUInt32Number  Geometry;    // 0=unknown, 1=45/0, 0/45 2=0d, d/0
 206.959 +        cmsFloat64Number Flare;       // 0..1.0
 206.960 +        cmsUInt32Number  IlluminantType;
 206.961 +
 206.962 +    } cmsICCMeasurementConditions;
 206.963 +
 206.964 +typedef struct {
 206.965 +        cmsCIEXYZ       IlluminantXYZ;   // Not the same struct as CAM02,
 206.966 +        cmsCIEXYZ       SurroundXYZ;     // This is for storing the tag
 206.967 +        cmsUInt32Number IlluminantType;  // viewing condition
 206.968 +
 206.969 +    } cmsICCViewingConditions;
 206.970 +
 206.971 +// Support of non-standard functions --------------------------------------------------------------------------------------
 206.972 +
 206.973 +CMSAPI int               CMSEXPORT cmsstrcasecmp(const char* s1, const char* s2);
 206.974 +CMSAPI long int          CMSEXPORT cmsfilelength(FILE* f);
 206.975 +
 206.976 +// Plug-In registering  ---------------------------------------------------------------------------------------------------
 206.977 +
 206.978 +CMSAPI cmsBool           CMSEXPORT cmsPlugin(void* Plugin);
 206.979 +CMSAPI void              CMSEXPORT cmsUnregisterPlugins(void);
 206.980 +
 206.981 +// Error logging ----------------------------------------------------------------------------------------------------------
 206.982 +
 206.983 +// There is no error handling at all. When a function fails, it returns proper value.
 206.984 +// For example, all create functions does return NULL on failure. Other may return FALSE.
 206.985 +// It may be interesting, for the developer, to know why the function is failing.
 206.986 +// for that reason, lcms2 does offer a logging function. This function will get
 206.987 +// an ENGLISH string with some clues on what is going wrong. You can show this
 206.988 +// info to the end user if you wish, or just create some sort of log on disk.
 206.989 +// The logging function should NOT terminate the program, as this obviously can leave
 206.990 +// unfreed resources. It is the programmer's responsibility to check each function
 206.991 +// return code to make sure it didn't fail.
 206.992 +
 206.993 +#define cmsERROR_UNDEFINED                    0
 206.994 +#define cmsERROR_FILE                         1
 206.995 +#define cmsERROR_RANGE                        2
 206.996 +#define cmsERROR_INTERNAL                     3
 206.997 +#define cmsERROR_NULL                         4
 206.998 +#define cmsERROR_READ                         5
 206.999 +#define cmsERROR_SEEK                         6
206.1000 +#define cmsERROR_WRITE                        7
206.1001 +#define cmsERROR_UNKNOWN_EXTENSION            8
206.1002 +#define cmsERROR_COLORSPACE_CHECK             9
206.1003 +#define cmsERROR_ALREADY_DEFINED              10
206.1004 +#define cmsERROR_BAD_SIGNATURE                11
206.1005 +#define cmsERROR_CORRUPTION_DETECTED          12
206.1006 +#define cmsERROR_NOT_SUITABLE                 13
206.1007 +
206.1008 +// Error logger is called with the ContextID when a message is raised. This gives the
206.1009 +// chance to know which thread is responsible of the warning and any environment associated
206.1010 +// with it. Non-multithreading applications may safely ignore this parameter.
206.1011 +// Note that under certain special circumstances, ContextID may be NULL.
206.1012 +typedef void  (* cmsLogErrorHandlerFunction)(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text);
206.1013 +
206.1014 +// Allows user to set any specific logger
206.1015 +CMSAPI void              CMSEXPORT cmsSetLogErrorHandler(cmsLogErrorHandlerFunction Fn);
206.1016 +
206.1017 +// Conversions --------------------------------------------------------------------------------------------------------------
206.1018 +
206.1019 +// Returns pointers to constant structs
206.1020 +CMSAPI const cmsCIEXYZ*  CMSEXPORT cmsD50_XYZ(void);
206.1021 +CMSAPI const cmsCIExyY*  CMSEXPORT cmsD50_xyY(void);
206.1022 +
206.1023 +// Colorimetric space conversions
206.1024 +CMSAPI void              CMSEXPORT cmsXYZ2xyY(cmsCIExyY* Dest, const cmsCIEXYZ* Source);
206.1025 +CMSAPI void              CMSEXPORT cmsxyY2XYZ(cmsCIEXYZ* Dest, const cmsCIExyY* Source);
206.1026 +CMSAPI void              CMSEXPORT cmsXYZ2Lab(const cmsCIEXYZ* WhitePoint, cmsCIELab* Lab, const cmsCIEXYZ* xyz);
206.1027 +CMSAPI void              CMSEXPORT cmsLab2XYZ(const cmsCIEXYZ* WhitePoint, cmsCIEXYZ* xyz, const cmsCIELab* Lab);
206.1028 +CMSAPI void              CMSEXPORT cmsLab2LCh(cmsCIELCh*LCh, const cmsCIELab* Lab);
206.1029 +CMSAPI void              CMSEXPORT cmsLCh2Lab(cmsCIELab* Lab, const cmsCIELCh* LCh);
206.1030 +
206.1031 +// Encoding /Decoding on PCS
206.1032 +CMSAPI void              CMSEXPORT cmsLabEncoded2Float(cmsCIELab* Lab, const cmsUInt16Number wLab[3]);
206.1033 +CMSAPI void              CMSEXPORT cmsLabEncoded2FloatV2(cmsCIELab* Lab, const cmsUInt16Number wLab[3]);
206.1034 +CMSAPI void              CMSEXPORT cmsFloat2LabEncoded(cmsUInt16Number wLab[3], const cmsCIELab* Lab);
206.1035 +CMSAPI void              CMSEXPORT cmsFloat2LabEncodedV2(cmsUInt16Number wLab[3], const cmsCIELab* Lab);
206.1036 +CMSAPI void              CMSEXPORT cmsXYZEncoded2Float(cmsCIEXYZ* fxyz, const cmsUInt16Number XYZ[3]);
206.1037 +CMSAPI void              CMSEXPORT cmsFloat2XYZEncoded(cmsUInt16Number XYZ[3], const cmsCIEXYZ* fXYZ);
206.1038 +
206.1039 +// DeltaE metrics
206.1040 +CMSAPI cmsFloat64Number  CMSEXPORT cmsDeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2);
206.1041 +CMSAPI cmsFloat64Number  CMSEXPORT cmsCIE94DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2);
206.1042 +CMSAPI cmsFloat64Number  CMSEXPORT cmsBFDdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2);
206.1043 +CMSAPI cmsFloat64Number  CMSEXPORT cmsCMCdeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2, cmsFloat64Number l, cmsFloat64Number c);
206.1044 +CMSAPI cmsFloat64Number  CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIELab* Lab2, cmsFloat64Number Kl, cmsFloat64Number Kc, cmsFloat64Number Kh);
206.1045 +
206.1046 +// Temperature <-> Chromaticity (Black body)
206.1047 +CMSAPI cmsBool           CMSEXPORT cmsWhitePointFromTemp(cmsCIExyY* WhitePoint, cmsFloat64Number  TempK);
206.1048 +CMSAPI cmsBool           CMSEXPORT cmsTempFromWhitePoint(cmsFloat64Number* TempK, const cmsCIExyY* WhitePoint);
206.1049 +
206.1050 +// Chromatic adaptation
206.1051 +CMSAPI cmsBool           CMSEXPORT cmsAdaptToIlluminant(cmsCIEXYZ* Result, const cmsCIEXYZ* SourceWhitePt,
206.1052 +                                                                           const cmsCIEXYZ* Illuminant,
206.1053 +                                                                           const cmsCIEXYZ* Value);
206.1054 +
206.1055 +// CIECAM02 ---------------------------------------------------------------------------------------------------
206.1056 +
206.1057 +// Viewing conditions. Please note those are CAM model viewing conditions, and not the ICC tag viewing
206.1058 +// conditions, which I'm naming cmsICCViewingConditions to make differences evident. Unfortunately, the tag
206.1059 +// cannot deal with surround La, Yb and D value so is basically useless to store CAM02 viewing conditions.
206.1060 +
206.1061 +
206.1062 +#define AVG_SURROUND       1
206.1063 +#define DIM_SURROUND       2
206.1064 +#define DARK_SURROUND      3
206.1065 +#define CUTSHEET_SURROUND  4
206.1066 +
206.1067 +#define D_CALCULATE        (-1)
206.1068 +
206.1069 +typedef struct {
206.1070 +    cmsCIEXYZ        whitePoint;
206.1071 +    cmsFloat64Number Yb;
206.1072 +    cmsFloat64Number La;
206.1073 +    int              surround;
206.1074 +    cmsFloat64Number D_value;
206.1075 +
206.1076 +    } cmsViewingConditions;
206.1077 +
206.1078 +CMSAPI cmsHANDLE         CMSEXPORT cmsCIECAM02Init(cmsContext ContextID, const cmsViewingConditions* pVC);
206.1079 +CMSAPI void              CMSEXPORT cmsCIECAM02Done(cmsHANDLE hModel);
206.1080 +CMSAPI void              CMSEXPORT cmsCIECAM02Forward(cmsHANDLE hModel, const cmsCIEXYZ* pIn, cmsJCh* pOut);
206.1081 +CMSAPI void              CMSEXPORT cmsCIECAM02Reverse(cmsHANDLE hModel, const cmsJCh* pIn,    cmsCIEXYZ* pOut);
206.1082 +
206.1083 +
206.1084 +// Tone curves -----------------------------------------------------------------------------------------
206.1085 +
206.1086 +// This describes a curve segment. For a table of supported types, see the manual. User can increase the number of
206.1087 +// available types by using a proper plug-in. Parametric segments allow 10 parameters at most
206.1088 +
206.1089 +typedef struct {
206.1090 +    cmsFloat32Number   x0, x1;           // Domain; for x0 < x <= x1
206.1091 +    cmsInt32Number     Type;             // Parametric type, Type == 0 means sampled segment. Negative values are reserved
206.1092 +    cmsFloat64Number   Params[10];       // Parameters if Type != 0
206.1093 +    cmsUInt32Number    nGridPoints;      // Number of grid points if Type == 0
206.1094 +    cmsFloat32Number*  SampledPoints;    // Points to an array of floats if Type == 0
206.1095 +
206.1096 +} cmsCurveSegment;
206.1097 +
206.1098 +// The internal representation is none of your business.
206.1099 +typedef struct _cms_curve_struct cmsToneCurve;
206.1100 +
206.1101 +CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildSegmentedToneCurve(cmsContext ContextID, cmsInt32Number nSegments, const cmsCurveSegment Segments[]);
206.1102 +CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[]);
206.1103 +CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildGamma(cmsContext ContextID, cmsFloat64Number Gamma);
206.1104 +CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildTabulatedToneCurve16(cmsContext ContextID, cmsInt32Number nEntries, const cmsUInt16Number values[]);
206.1105 +CMSAPI cmsToneCurve*     CMSEXPORT cmsBuildTabulatedToneCurveFloat(cmsContext ContextID, cmsUInt32Number nEntries, const cmsFloat32Number values[]);
206.1106 +CMSAPI void              CMSEXPORT cmsFreeToneCurve(cmsToneCurve* Curve);
206.1107 +CMSAPI void              CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3]);
206.1108 +CMSAPI cmsToneCurve*     CMSEXPORT cmsDupToneCurve(const cmsToneCurve* Src);
206.1109 +CMSAPI cmsToneCurve*     CMSEXPORT cmsReverseToneCurve(const cmsToneCurve* InGamma);
206.1110 +CMSAPI cmsToneCurve*     CMSEXPORT cmsReverseToneCurveEx(cmsInt32Number nResultSamples, const cmsToneCurve* InGamma);
206.1111 +CMSAPI cmsToneCurve*     CMSEXPORT cmsJoinToneCurve(cmsContext ContextID, const cmsToneCurve* X,  const cmsToneCurve* Y, cmsUInt32Number nPoints);
206.1112 +CMSAPI cmsBool           CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda);
206.1113 +CMSAPI cmsFloat32Number  CMSEXPORT cmsEvalToneCurveFloat(const cmsToneCurve* Curve, cmsFloat32Number v);
206.1114 +CMSAPI cmsUInt16Number   CMSEXPORT cmsEvalToneCurve16(const cmsToneCurve* Curve, cmsUInt16Number v);
206.1115 +CMSAPI cmsBool           CMSEXPORT cmsIsToneCurveMultisegment(const cmsToneCurve* InGamma);
206.1116 +CMSAPI cmsBool           CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve);
206.1117 +CMSAPI cmsBool           CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t);
206.1118 +CMSAPI cmsBool           CMSEXPORT cmsIsToneCurveDescending(const cmsToneCurve* t);
206.1119 +CMSAPI cmsInt32Number    CMSEXPORT cmsGetToneCurveParametricType(const cmsToneCurve* t);
206.1120 +CMSAPI cmsFloat64Number  CMSEXPORT cmsEstimateGamma(const cmsToneCurve* t, cmsFloat64Number Precision);
206.1121 +
206.1122 +
206.1123 +// Implements pipelines of multi-processing elements -------------------------------------------------------------
206.1124 +
206.1125 +// Nothing to see here, move along
206.1126 +typedef struct _cmsPipeline_struct cmsPipeline;
206.1127 +typedef struct _cmsStage_struct cmsStage;
206.1128 +
206.1129 +// Those are hi-level pipelines
206.1130 +CMSAPI cmsPipeline*      CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels);
206.1131 +CMSAPI void              CMSEXPORT cmsPipelineFree(cmsPipeline* lut);
206.1132 +CMSAPI cmsPipeline*      CMSEXPORT cmsPipelineDup(const cmsPipeline* Orig);
206.1133 +
206.1134 +CMSAPI cmsUInt32Number   CMSEXPORT cmsPipelineInputChannels(const cmsPipeline* lut);
206.1135 +CMSAPI cmsUInt32Number   CMSEXPORT cmsPipelineOutputChannels(const cmsPipeline* lut);
206.1136 +
206.1137 +CMSAPI cmsUInt32Number   CMSEXPORT cmsPipelineStageCount(const cmsPipeline* lut);
206.1138 +CMSAPI cmsStage*         CMSEXPORT cmsPipelineGetPtrToFirstStage(const cmsPipeline* lut);
206.1139 +CMSAPI cmsStage*         CMSEXPORT cmsPipelineGetPtrToLastStage(const cmsPipeline* lut);
206.1140 +
206.1141 +CMSAPI void              CMSEXPORT cmsPipelineEval16(const cmsUInt16Number In[], cmsUInt16Number Out[], const cmsPipeline* lut);
206.1142 +CMSAPI void              CMSEXPORT cmsPipelineEvalFloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsPipeline* lut);
206.1143 +CMSAPI cmsBool           CMSEXPORT cmsPipelineEvalReverseFloat(cmsFloat32Number Target[], cmsFloat32Number Result[], cmsFloat32Number Hint[], const cmsPipeline* lut);
206.1144 +CMSAPI cmsBool           CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2);
206.1145 +CMSAPI cmsBool           CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lut, cmsBool On);
206.1146 +
206.1147 +// Where to place/locate the stages in the pipeline chain
206.1148 +typedef enum { cmsAT_BEGIN, cmsAT_END } cmsStageLoc;
206.1149 +
206.1150 +CMSAPI void              CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe);
206.1151 +CMSAPI void              CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe);
206.1152 +
206.1153 +// This function is quite useful to analyze the structure of a Pipeline and retrieve the Stage elements
206.1154 +// that conform the Pipeline. It should be called with the Pipeline, the number of expected elements and
206.1155 +// then a list of expected types followed with a list of double pointers to Stage elements. If
206.1156 +// the function founds a match with current pipeline, it fills the pointers and returns TRUE
206.1157 +// if not, returns FALSE without touching anything.
206.1158 +CMSAPI cmsBool           CMSEXPORT cmsPipelineCheckAndRetreiveStages(const cmsPipeline* Lut, cmsUInt32Number n, ...);
206.1159 +
206.1160 +// Matrix has double precision and CLUT has only float precision. That is because an ICC profile can encode
206.1161 +// matrices with far more precision that CLUTS
206.1162 +CMSAPI cmsStage*         CMSEXPORT cmsStageAllocIdentity(cmsContext ContextID, cmsUInt32Number nChannels);
206.1163 +CMSAPI cmsStage*         CMSEXPORT cmsStageAllocToneCurves(cmsContext ContextID, cmsUInt32Number nChannels, cmsToneCurve* const Curves[]);
206.1164 +CMSAPI cmsStage*         CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number Rows, cmsUInt32Number Cols, const cmsFloat64Number* Matrix, const cmsFloat64Number* Offset);
206.1165 +
206.1166 +CMSAPI cmsStage*         CMSEXPORT cmsStageAllocCLut16bit(cmsContext ContextID, cmsUInt32Number nGridPoints, cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsUInt16Number* Table);
206.1167 +CMSAPI cmsStage*         CMSEXPORT cmsStageAllocCLutFloat(cmsContext ContextID, cmsUInt32Number nGridPoints, cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsFloat32Number* Table);
206.1168 +
206.1169 +CMSAPI cmsStage*         CMSEXPORT cmsStageAllocCLut16bitGranular(cmsContext ContextID, const cmsUInt32Number clutPoints[], cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsUInt16Number* Table);
206.1170 +CMSAPI cmsStage*         CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const cmsUInt32Number clutPoints[], cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsFloat32Number* Table);
206.1171 +
206.1172 +CMSAPI cmsStage*         CMSEXPORT cmsStageDup(cmsStage* mpe);
206.1173 +CMSAPI void              CMSEXPORT cmsStageFree(cmsStage* mpe);
206.1174 +CMSAPI cmsStage*         CMSEXPORT cmsStageNext(const cmsStage* mpe);
206.1175 +
206.1176 +CMSAPI cmsUInt32Number   CMSEXPORT cmsStageInputChannels(const cmsStage* mpe);
206.1177 +CMSAPI cmsUInt32Number   CMSEXPORT cmsStageOutputChannels(const cmsStage* mpe);
206.1178 +CMSAPI cmsStageSignature CMSEXPORT cmsStageType(const cmsStage* mpe);
206.1179 +CMSAPI void*             CMSEXPORT cmsStageData(const cmsStage* mpe);
206.1180 +
206.1181 +// Sampling
206.1182 +typedef cmsInt32Number (* cmsSAMPLER16)   (register const cmsUInt16Number In[],
206.1183 +                                            register cmsUInt16Number Out[],
206.1184 +                                            register void * Cargo);
206.1185 +
206.1186 +typedef cmsInt32Number (* cmsSAMPLERFLOAT)(register const cmsFloat32Number In[],
206.1187 +                                            register cmsFloat32Number Out[],
206.1188 +                                            register void * Cargo);
206.1189 +
206.1190 +// Use this flag to prevent changes being written to destination
206.1191 +#define SAMPLER_INSPECT     0x01000000
206.1192 +
206.1193 +// For CLUT only
206.1194 +CMSAPI cmsBool           CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe,    cmsSAMPLER16 Sampler,    void* Cargo, cmsUInt32Number dwFlags);
206.1195 +CMSAPI cmsBool           CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void* Cargo, cmsUInt32Number dwFlags);
206.1196 +
206.1197 +
206.1198 +// Slicers
206.1199 +CMSAPI cmsBool           CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
206.1200 +                                                   cmsSAMPLER16 Sampler, void * Cargo);
206.1201 +
206.1202 +CMSAPI cmsBool           CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
206.1203 +                                                   cmsSAMPLERFLOAT Sampler, void * Cargo);
206.1204 +
206.1205 +// Multilocalized Unicode management ---------------------------------------------------------------------------------------
206.1206 +
206.1207 +typedef struct _cms_MLU_struct cmsMLU;
206.1208 +
206.1209 +#define  cmsNoLanguage "\0\0"
206.1210 +#define  cmsNoCountry  "\0\0"
206.1211 +
206.1212 +CMSAPI cmsMLU*           CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems);
206.1213 +CMSAPI void              CMSEXPORT cmsMLUfree(cmsMLU* mlu);
206.1214 +CMSAPI cmsMLU*           CMSEXPORT cmsMLUdup(const cmsMLU* mlu);
206.1215 +
206.1216 +CMSAPI cmsBool           CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu,
206.1217 +                                                  const char LanguageCode[3], const char CountryCode[3],
206.1218 +                                                  const char* ASCIIString);
206.1219 +CMSAPI cmsBool           CMSEXPORT cmsMLUsetWide(cmsMLU* mlu,
206.1220 +                                                  const char LanguageCode[3], const char CountryCode[3],
206.1221 +                                                  const wchar_t* WideString);
206.1222 +
206.1223 +CMSAPI cmsUInt32Number   CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
206.1224 +                                                  const char LanguageCode[3], const char CountryCode[3],
206.1225 +                                                  char* Buffer,    cmsUInt32Number BufferSize);
206.1226 +
206.1227 +CMSAPI cmsUInt32Number   CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
206.1228 +                                                 const char LanguageCode[3], const char CountryCode[3],
206.1229 +                                                 wchar_t* Buffer, cmsUInt32Number BufferSize);
206.1230 +
206.1231 +CMSAPI cmsBool           CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
206.1232 +                                                         const char LanguageCode[3], const char CountryCode[3],
206.1233 +                                                         char ObtainedLanguage[3], char ObtainedCountry[3]);
206.1234 +
206.1235 +// Undercolorremoval & black generation -------------------------------------------------------------------------------------
206.1236 +
206.1237 +typedef struct {
206.1238 +        cmsToneCurve* Ucr;
206.1239 +        cmsToneCurve* Bg;
206.1240 +        cmsMLU*       Desc;
206.1241 +
206.1242 +} cmsUcrBg;
206.1243 +
206.1244 +// Screening ----------------------------------------------------------------------------------------------------------------
206.1245 +
206.1246 +#define cmsPRINTER_DEFAULT_SCREENS     0x0001
206.1247 +#define cmsFREQUENCE_UNITS_LINES_CM    0x0000
206.1248 +#define cmsFREQUENCE_UNITS_LINES_INCH  0x0002
206.1249 +
206.1250 +#define cmsSPOT_UNKNOWN         0
206.1251 +#define cmsSPOT_PRINTER_DEFAULT 1
206.1252 +#define cmsSPOT_ROUND           2
206.1253 +#define cmsSPOT_DIAMOND         3
206.1254 +#define cmsSPOT_ELLIPSE         4
206.1255 +#define cmsSPOT_LINE            5
206.1256 +#define cmsSPOT_SQUARE          6
206.1257 +#define cmsSPOT_CROSS           7
206.1258 +
206.1259 +typedef struct {
206.1260 +    cmsFloat64Number  Frequency;
206.1261 +    cmsFloat64Number  ScreenAngle;
206.1262 +    cmsUInt32Number   SpotShape;
206.1263 +
206.1264 +} cmsScreeningChannel;
206.1265 +
206.1266 +typedef struct {
206.1267 +    cmsUInt32Number Flag;
206.1268 +    cmsUInt32Number nChannels;
206.1269 +    cmsScreeningChannel Channels[cmsMAXCHANNELS];
206.1270 +
206.1271 +} cmsScreening;
206.1272 +
206.1273 +
206.1274 +// Named color -----------------------------------------------------------------------------------------------------------------
206.1275 +
206.1276 +typedef struct _cms_NAMEDCOLORLIST_struct cmsNAMEDCOLORLIST;
206.1277 +
206.1278 +CMSAPI cmsNAMEDCOLORLIST* CMSEXPORT cmsAllocNamedColorList(cmsContext ContextID,
206.1279 +                                                           cmsUInt32Number n,
206.1280 +                                                           cmsUInt32Number ColorantCount,
206.1281 +                                                           const char* Prefix, const char* Suffix);
206.1282 +
206.1283 +CMSAPI void               CMSEXPORT cmsFreeNamedColorList(cmsNAMEDCOLORLIST* v);
206.1284 +CMSAPI cmsNAMEDCOLORLIST* CMSEXPORT cmsDupNamedColorList(const cmsNAMEDCOLORLIST* v);
206.1285 +CMSAPI cmsBool            CMSEXPORT cmsAppendNamedColor(cmsNAMEDCOLORLIST* v, const char* Name,
206.1286 +                                                            cmsUInt16Number PCS[3],
206.1287 +                                                            cmsUInt16Number Colorant[cmsMAXCHANNELS]);
206.1288 +
206.1289 +CMSAPI cmsUInt32Number    CMSEXPORT cmsNamedColorCount(const cmsNAMEDCOLORLIST* v);
206.1290 +CMSAPI cmsInt32Number     CMSEXPORT cmsNamedColorIndex(const cmsNAMEDCOLORLIST* v, const char* Name);
206.1291 +
206.1292 +CMSAPI cmsBool            CMSEXPORT cmsNamedColorInfo(const cmsNAMEDCOLORLIST* NamedColorList, cmsUInt32Number nColor,
206.1293 +                                                      char* Name,
206.1294 +                                                      char* Prefix,
206.1295 +                                                      char* Suffix,
206.1296 +                                                      cmsUInt16Number* PCS,
206.1297 +                                                      cmsUInt16Number* Colorant);
206.1298 +
206.1299 +// Retrieve named color list from transform
206.1300 +CMSAPI cmsNAMEDCOLORLIST* CMSEXPORT cmsGetNamedColorList(cmsHTRANSFORM xform);
206.1301 +
206.1302 +// Profile sequence -----------------------------------------------------------------------------------------------------
206.1303 +
206.1304 +// Profile sequence descriptor. Some fields come from profile sequence descriptor tag, others
206.1305 +// come from Profile Sequence Identifier Tag
206.1306 +typedef struct {
206.1307 +    cmsSignature           deviceMfg;
206.1308 +    cmsSignature           deviceModel;
206.1309 +    cmsUInt64Number        attributes;
206.1310 +    cmsTechnologySignature technology;
206.1311 +    cmsProfileID           ProfileID;
206.1312 +    cmsMLU*                Manufacturer;
206.1313 +    cmsMLU*                Model;
206.1314 +    cmsMLU*                Description;
206.1315 +
206.1316 +} cmsPSEQDESC;
206.1317 +
206.1318 +typedef struct {
206.1319 +
206.1320 +    cmsUInt32Number n;
206.1321 +    cmsContext     ContextID;
206.1322 +    cmsPSEQDESC*    seq;
206.1323 +
206.1324 +} cmsSEQ;
206.1325 +
206.1326 +CMSAPI cmsSEQ*           CMSEXPORT cmsAllocProfileSequenceDescription(cmsContext ContextID, cmsUInt32Number n);
206.1327 +CMSAPI cmsSEQ*           CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq);
206.1328 +CMSAPI void              CMSEXPORT cmsFreeProfileSequenceDescription(cmsSEQ* pseq);
206.1329 +
206.1330 +// Access to Profile data ----------------------------------------------------------------------------------------------
206.1331 +CMSAPI cmsHPROFILE       CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID);
206.1332 +
206.1333 +CMSAPI cmsContext        CMSEXPORT cmsGetProfileContextID(cmsHPROFILE hProfile);
206.1334 +CMSAPI cmsInt32Number    CMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile);
206.1335 +CMSAPI cmsTagSignature   CMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, cmsUInt32Number n);
206.1336 +CMSAPI cmsBool           CMSEXPORT cmsIsTag(cmsHPROFILE hProfile, cmsTagSignature sig);
206.1337 +
206.1338 +// Read and write pre-formatted data
206.1339 +CMSAPI void*             CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig);
206.1340 +CMSAPI cmsBool           CMSEXPORT cmsWriteTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data);
206.1341 +CMSAPI cmsBool           CMSEXPORT cmsLinkTag(cmsHPROFILE hProfile, cmsTagSignature sig, cmsTagSignature dest);
206.1342 +
206.1343 +// Read and write raw data
206.1344 +CMSAPI cmsInt32Number    CMSEXPORT cmsReadRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, void* Buffer, cmsUInt32Number BufferSize);
206.1345 +CMSAPI cmsBool           CMSEXPORT cmsWriteRawTag(cmsHPROFILE hProfile, cmsTagSignature sig, const void* data, cmsUInt32Number Size);
206.1346 +
206.1347 +// Access header data
206.1348 +CMSAPI cmsUInt32Number   CMSEXPORT cmsGetHeaderFlags(cmsHPROFILE hProfile);
206.1349 +CMSAPI void              CMSEXPORT cmsGetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number* Flags);
206.1350 +CMSAPI void              CMSEXPORT cmsGetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID);
206.1351 +CMSAPI cmsBool           CMSEXPORT cmsGetHeaderCreationDateTime(cmsHPROFILE hProfile, struct tm *Dest);
206.1352 +CMSAPI cmsUInt32Number   CMSEXPORT cmsGetHeaderRenderingIntent(cmsHPROFILE hProfile);
206.1353 +
206.1354 +CMSAPI void              CMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, cmsUInt32Number Flags);
206.1355 +CMSAPI cmsUInt32Number   CMSEXPORT cmsGetHeaderManufacturer(cmsHPROFILE hProfile);
206.1356 +CMSAPI void              CMSEXPORT cmsSetHeaderManufacturer(cmsHPROFILE hProfile, cmsUInt32Number manufacturer);
206.1357 +CMSAPI cmsUInt32Number   CMSEXPORT cmsGetHeaderModel(cmsHPROFILE hProfile);
206.1358 +CMSAPI void              CMSEXPORT cmsSetHeaderModel(cmsHPROFILE hProfile, cmsUInt32Number model);
206.1359 +CMSAPI void              CMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, cmsUInt64Number Flags);
206.1360 +CMSAPI void              CMSEXPORT cmsSetHeaderProfileID(cmsHPROFILE hProfile, cmsUInt8Number* ProfileID);
206.1361 +CMSAPI void              CMSEXPORT cmsSetHeaderRenderingIntent(cmsHPROFILE hProfile, cmsUInt32Number RenderingIntent);
206.1362 +
206.1363 +CMSAPI cmsColorSpaceSignature
206.1364 +                         CMSEXPORT cmsGetPCS(cmsHPROFILE hProfile);
206.1365 +CMSAPI void              CMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, cmsColorSpaceSignature pcs);
206.1366 +CMSAPI cmsColorSpaceSignature
206.1367 +                         CMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile);
206.1368 +CMSAPI void              CMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, cmsColorSpaceSignature sig);
206.1369 +CMSAPI cmsProfileClassSignature
206.1370 +                         CMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile);
206.1371 +CMSAPI void              CMSEXPORT cmsSetDeviceClass(cmsHPROFILE hProfile, cmsProfileClassSignature sig);
206.1372 +CMSAPI void              CMSEXPORT cmsSetProfileVersion(cmsHPROFILE hProfile, cmsFloat64Number Version);
206.1373 +CMSAPI cmsFloat64Number  CMSEXPORT cmsGetProfileVersion(cmsHPROFILE hProfile);
206.1374 +
206.1375 +CMSAPI cmsUInt32Number   CMSEXPORT cmsGetEncodedICCversion(cmsHPROFILE hProfile);
206.1376 +CMSAPI void              CMSEXPORT cmsSetEncodedICCversion(cmsHPROFILE hProfile, cmsUInt32Number Version);
206.1377 +
206.1378 +// How profiles may be used
206.1379 +#define LCMS_USED_AS_INPUT      0
206.1380 +#define LCMS_USED_AS_OUTPUT     1
206.1381 +#define LCMS_USED_AS_PROOF      2
206.1382 +
206.1383 +CMSAPI cmsBool           CMSEXPORT cmsIsIntentSupported(cmsHPROFILE hProfile, cmsUInt32Number Intent, int UsedDirection);
206.1384 +CMSAPI cmsBool           CMSEXPORT cmsIsMatrixShaper(cmsHPROFILE hProfile);
206.1385 +CMSAPI cmsBool           CMSEXPORT cmsIsCLUT(cmsHPROFILE hProfile, cmsUInt32Number Intent, int UsedDirection);
206.1386 +
206.1387 +// Translate form/to our notation to ICC
206.1388 +CMSAPI cmsColorSpaceSignature   CMSEXPORT _cmsICCcolorSpace(int OurNotation);
206.1389 +CMSAPI int                      CMSEXPORT _cmsLCMScolorSpace(cmsColorSpaceSignature ProfileSpace);
206.1390 +
206.1391 +CMSAPI cmsUInt32Number   CMSEXPORT cmsChannelsOf(cmsColorSpaceSignature ColorSpace);
206.1392 +
206.1393 +// Build a suitable formatter for the colorspace of this profile
206.1394 +CMSAPI cmsUInt32Number   CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
206.1395 +CMSAPI cmsUInt32Number   CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsUInt32Number nBytes, cmsBool lIsFloat);
206.1396 +
206.1397 +
206.1398 +// Localized info
206.1399 +typedef enum {
206.1400 +             cmsInfoDescription  = 0,
206.1401 +             cmsInfoManufacturer = 1,
206.1402 +             cmsInfoModel        = 2,
206.1403 +             cmsInfoCopyright    = 3
206.1404 +} cmsInfoType;
206.1405 +
206.1406 +CMSAPI cmsUInt32Number   CMSEXPORT cmsGetProfileInfo(cmsHPROFILE hProfile, cmsInfoType Info,
206.1407 +                                                            const char LanguageCode[3], const char CountryCode[3],
206.1408 +                                                            wchar_t* Buffer, cmsUInt32Number BufferSize);
206.1409 +
206.1410 +CMSAPI cmsUInt32Number   CMSEXPORT cmsGetProfileInfoASCII(cmsHPROFILE hProfile, cmsInfoType Info,
206.1411 +                                                            const char LanguageCode[3], const char CountryCode[3],
206.1412 +                                                            char* Buffer, cmsUInt32Number BufferSize);
206.1413 +
206.1414 +// IO handlers ----------------------------------------------------------------------------------------------------------
206.1415 +
206.1416 +typedef struct _cms_io_handler cmsIOHANDLER;
206.1417 +
206.1418 +CMSAPI cmsIOHANDLER*     CMSEXPORT cmsOpenIOhandlerFromFile(cmsContext ContextID, const char* FileName, const char* AccessMode);
206.1419 +CMSAPI cmsIOHANDLER*     CMSEXPORT cmsOpenIOhandlerFromStream(cmsContext ContextID, FILE* Stream);
206.1420 +CMSAPI cmsIOHANDLER*     CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buffer, cmsUInt32Number size, const char* AccessMode);
206.1421 +CMSAPI cmsIOHANDLER*     CMSEXPORT cmsOpenIOhandlerFromNULL(cmsContext ContextID);
206.1422 +CMSAPI cmsBool           CMSEXPORT cmsCloseIOhandler(cmsIOHANDLER* io);
206.1423 +
206.1424 +// MD5 message digest --------------------------------------------------------------------------------------------------
206.1425 +
206.1426 +CMSAPI cmsBool           CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile);
206.1427 +
206.1428 +// Profile high level funtions ------------------------------------------------------------------------------------------
206.1429 +
206.1430 +CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromFile(const char *ICCProfile, const char *sAccess);
206.1431 +CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromFileTHR(cmsContext ContextID, const char *ICCProfile, const char *sAccess);
206.1432 +CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromStream(FILE* ICCProfile, const char* sAccess);
206.1433 +CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromStreamTHR(cmsContext ContextID, FILE* ICCProfile, const char* sAccess);
206.1434 +CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromMem(const void * MemPtr, cmsUInt32Number dwSize);
206.1435 +CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromMemTHR(cmsContext ContextID, const void * MemPtr, cmsUInt32Number dwSize);
206.1436 +CMSAPI cmsHPROFILE      CMSEXPORT cmsOpenProfileFromIOhandlerTHR(cmsContext ContextID, cmsIOHANDLER* io);
206.1437 +CMSAPI cmsBool          CMSEXPORT cmsCloseProfile(cmsHPROFILE hProfile);
206.1438 +
206.1439 +CMSAPI cmsBool          CMSEXPORT cmsSaveProfileToFile(cmsHPROFILE hProfile, const char* FileName);
206.1440 +CMSAPI cmsBool          CMSEXPORT cmsSaveProfileToStream(cmsHPROFILE hProfile, FILE* Stream);
206.1441 +CMSAPI cmsBool          CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUInt32Number* BytesNeeded);
206.1442 +CMSAPI cmsUInt32Number  CMSEXPORT cmsSaveProfileToIOhandler(cmsHPROFILE hProfile, cmsIOHANDLER* io);
206.1443 +
206.1444 +// Predefined virtual profiles ------------------------------------------------------------------------------------------
206.1445 +
206.1446 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateRGBProfileTHR(cmsContext ContextID,
206.1447 +                                                   const cmsCIExyY* WhitePoint,
206.1448 +                                                   const cmsCIExyYTRIPLE* Primaries,
206.1449 +                                                   cmsToneCurve* const TransferFunction[3]);
206.1450 +
206.1451 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateRGBProfile(const cmsCIExyY* WhitePoint,
206.1452 +                                                   const cmsCIExyYTRIPLE* Primaries,
206.1453 +                                                   cmsToneCurve* const TransferFunction[3]);
206.1454 +
206.1455 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateGrayProfileTHR(cmsContext ContextID,
206.1456 +                                                    const cmsCIExyY* WhitePoint,
206.1457 +                                                    const cmsToneCurve* TransferFunction);
206.1458 +
206.1459 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateGrayProfile(const cmsCIExyY* WhitePoint,
206.1460 +                                                    const cmsToneCurve* TransferFunction);
206.1461 +
206.1462 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateLinearizationDeviceLinkTHR(cmsContext ContextID,
206.1463 +                                                                cmsColorSpaceSignature ColorSpace,
206.1464 +                                                                cmsToneCurve* const TransferFunctions[]);
206.1465 +
206.1466 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateLinearizationDeviceLink(cmsColorSpaceSignature ColorSpace,
206.1467 +                                                                cmsToneCurve* const TransferFunctions[]);
206.1468 +
206.1469 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
206.1470 +                                                              cmsColorSpaceSignature ColorSpace, cmsFloat64Number Limit);
206.1471 +
206.1472 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateInkLimitingDeviceLink(cmsColorSpaceSignature ColorSpace, cmsFloat64Number Limit);
206.1473 +
206.1474 +
206.1475 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateLab2ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint);
206.1476 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateLab2Profile(const cmsCIExyY* WhitePoint);
206.1477 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateLab4ProfileTHR(cmsContext ContextID, const cmsCIExyY* WhitePoint);
206.1478 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateLab4Profile(const cmsCIExyY* WhitePoint);
206.1479 +
206.1480 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateXYZProfileTHR(cmsContext ContextID);
206.1481 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateXYZProfile(void);
206.1482 +
206.1483 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID);
206.1484 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreate_sRGBProfile(void);
206.1485 +
206.1486 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateBCHSWabstractProfileTHR(cmsContext ContextID,
206.1487 +                                                             int nLUTPoints,
206.1488 +                                                             cmsFloat64Number Bright,
206.1489 +                                                             cmsFloat64Number Contrast,
206.1490 +                                                             cmsFloat64Number Hue,
206.1491 +                                                             cmsFloat64Number Saturation,
206.1492 +                                                             int TempSrc,
206.1493 +                                                             int TempDest);
206.1494 +
206.1495 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateBCHSWabstractProfile(int nLUTPoints,
206.1496 +                                                             cmsFloat64Number Bright,
206.1497 +                                                             cmsFloat64Number Contrast,
206.1498 +                                                             cmsFloat64Number Hue,
206.1499 +                                                             cmsFloat64Number Saturation,
206.1500 +                                                             int TempSrc,
206.1501 +                                                             int TempDest);
206.1502 +
206.1503 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateNULLProfileTHR(cmsContext ContextID);
206.1504 +CMSAPI cmsHPROFILE      CMSEXPORT cmsCreateNULLProfile(void);
206.1505 +
206.1506 +// Converts a transform to a devicelink profile
206.1507 +CMSAPI cmsHPROFILE      CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags);
206.1508 +
206.1509 +// Intents ----------------------------------------------------------------------------------------------
206.1510 +
206.1511 +// ICC Intents
206.1512 +#define INTENT_PERCEPTUAL                              0
206.1513 +#define INTENT_RELATIVE_COLORIMETRIC                   1
206.1514 +#define INTENT_SATURATION                              2
206.1515 +#define INTENT_ABSOLUTE_COLORIMETRIC                   3
206.1516 +
206.1517 +// Non-ICC intents
206.1518 +#define INTENT_PRESERVE_K_ONLY_PERCEPTUAL             10
206.1519 +#define INTENT_PRESERVE_K_ONLY_RELATIVE_COLORIMETRIC  11
206.1520 +#define INTENT_PRESERVE_K_ONLY_SATURATION             12
206.1521 +#define INTENT_PRESERVE_K_PLANE_PERCEPTUAL            13
206.1522 +#define INTENT_PRESERVE_K_PLANE_RELATIVE_COLORIMETRIC 14
206.1523 +#define INTENT_PRESERVE_K_PLANE_SATURATION            15
206.1524 +
206.1525 +// Call with NULL as parameters to get the intent count
206.1526 +CMSAPI cmsUInt32Number  CMSEXPORT cmsGetSupportedIntents(cmsUInt32Number nMax, cmsUInt32Number* Codes, char** Descriptions);
206.1527 +
206.1528 +// Flags
206.1529 +
206.1530 +#define cmsFLAGS_NOCACHE                  0x0040    // Inhibit 1-pixel cache
206.1531 +#define cmsFLAGS_NOOPTIMIZE               0x0100    // Inhibit optimizations
206.1532 +#define cmsFLAGS_NULLTRANSFORM            0x0200    // Don't transform anyway
206.1533 +
206.1534 +
206.1535 +// Proofing flags
206.1536 +#define cmsFLAGS_GAMUTCHECK               0x1000    // Out of Gamut alarm
206.1537 +#define cmsFLAGS_SOFTPROOFING             0x4000    // Do softproofing
206.1538 +
206.1539 +// Misc
206.1540 +#define cmsFLAGS_BLACKPOINTCOMPENSATION   0x2000
206.1541 +#define cmsFLAGS_NOWHITEONWHITEFIXUP      0x0004    // Don't fix scum dot
206.1542 +#define cmsFLAGS_HIGHRESPRECALC           0x0400    // Use more memory to give better accurancy
206.1543 +#define cmsFLAGS_LOWRESPRECALC            0x0800    // Use less memory to minimize resouces
206.1544 +
206.1545 +// For devicelink creation
206.1546 +#define cmsFLAGS_8BITS_DEVICELINK         0x0008   // Create 8 bits devicelinks
206.1547 +#define cmsFLAGS_GUESSDEVICECLASS         0x0020   // Guess device class (for transform2devicelink)
206.1548 +#define cmsFLAGS_KEEP_SEQUENCE            0x0080   // Keep profile sequence for devicelink creation
206.1549 +
206.1550 +// Specific to a particular optimizations
206.1551 +#define cmsFLAGS_FORCE_CLUT               0x0002    // Force CLUT optimization
206.1552 +#define cmsFLAGS_CLUT_POST_LINEARIZATION  0x0001    // create postlinearization tables if possible
206.1553 +#define cmsFLAGS_CLUT_PRE_LINEARIZATION   0x0010    // create prelinearization tables if possible
206.1554 +
206.1555 +// Fine-tune control over number of gridpoints
206.1556 +#define cmsFLAGS_GRIDPOINTS(n)           (((n) & 0xFF) << 16)
206.1557 +
206.1558 +// CRD special
206.1559 +#define cmsFLAGS_NODEFAULTRESOURCEDEF     0x01000000
206.1560 +
206.1561 +// Transforms ---------------------------------------------------------------------------------------------------
206.1562 +
206.1563 +CMSAPI cmsHTRANSFORM    CMSEXPORT cmsCreateTransformTHR(cmsContext ContextID,
206.1564 +                                                  cmsHPROFILE Input,
206.1565 +                                                  cmsUInt32Number InputFormat,
206.1566 +                                                  cmsHPROFILE Output,
206.1567 +                                                  cmsUInt32Number OutputFormat,
206.1568 +                                                  cmsUInt32Number Intent,
206.1569 +                                                  cmsUInt32Number dwFlags);
206.1570 +
206.1571 +CMSAPI cmsHTRANSFORM    CMSEXPORT cmsCreateTransform(cmsHPROFILE Input,
206.1572 +                                                  cmsUInt32Number InputFormat,
206.1573 +                                                  cmsHPROFILE Output,
206.1574 +                                                  cmsUInt32Number OutputFormat,
206.1575 +                                                  cmsUInt32Number Intent,
206.1576 +                                                  cmsUInt32Number dwFlags);
206.1577 +
206.1578 +CMSAPI cmsHTRANSFORM    CMSEXPORT cmsCreateProofingTransformTHR(cmsContext ContextID,
206.1579 +                                                  cmsHPROFILE Input,
206.1580 +                                                  cmsUInt32Number InputFormat,
206.1581 +                                                  cmsHPROFILE Output,
206.1582 +                                                  cmsUInt32Number OutputFormat,
206.1583 +                                                  cmsHPROFILE Proofing,
206.1584 +                                                  cmsUInt32Number Intent,
206.1585 +                                                  cmsUInt32Number ProofingIntent,
206.1586 +                                                  cmsUInt32Number dwFlags);
206.1587 +
206.1588 +CMSAPI cmsHTRANSFORM    CMSEXPORT cmsCreateProofingTransform(cmsHPROFILE Input,
206.1589 +                                                  cmsUInt32Number InputFormat,
206.1590 +                                                  cmsHPROFILE Output,
206.1591 +                                                  cmsUInt32Number OutputFormat,
206.1592 +                                                  cmsHPROFILE Proofing,
206.1593 +                                                  cmsUInt32Number Intent,
206.1594 +                                                  cmsUInt32Number ProofingIntent,
206.1595 +                                                  cmsUInt32Number dwFlags);
206.1596 +
206.1597 +CMSAPI cmsHTRANSFORM    CMSEXPORT cmsCreateMultiprofileTransformTHR(cmsContext ContextID,
206.1598 +                                                  cmsHPROFILE hProfiles[],
206.1599 +                                                  cmsUInt32Number nProfiles,
206.1600 +                                                  cmsUInt32Number InputFormat,
206.1601 +                                                  cmsUInt32Number OutputFormat,
206.1602 +                                                  cmsUInt32Number Intent,
206.1603 +                                                  cmsUInt32Number dwFlags);
206.1604 +
206.1605 +
206.1606 +CMSAPI cmsHTRANSFORM    CMSEXPORT cmsCreateMultiprofileTransform(cmsHPROFILE hProfiles[],
206.1607 +                                                  cmsUInt32Number nProfiles,
206.1608 +                                                  cmsUInt32Number InputFormat,
206.1609 +                                                  cmsUInt32Number OutputFormat,
206.1610 +                                                  cmsUInt32Number Intent,
206.1611 +                                                  cmsUInt32Number dwFlags);
206.1612 +
206.1613 +
206.1614 +CMSAPI cmsHTRANSFORM    CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
206.1615 +                                                   cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[],
206.1616 +                                                   cmsBool  BPC[],
206.1617 +                                                   cmsUInt32Number Intents[],
206.1618 +                                                   cmsFloat64Number AdaptationStates[],
206.1619 +                                                   cmsHPROFILE hGamutProfile,
206.1620 +                                                   cmsUInt32Number nGamutPCSposition,
206.1621 +                                                   cmsUInt32Number InputFormat,
206.1622 +                                                   cmsUInt32Number OutputFormat,
206.1623 +                                                   cmsUInt32Number dwFlags);
206.1624 +
206.1625 +CMSAPI void             CMSEXPORT cmsDeleteTransform(cmsHTRANSFORM hTransform);
206.1626 +
206.1627 +CMSAPI void             CMSEXPORT cmsDoTransform(cmsHTRANSFORM Transform,
206.1628 +                                                 const void * InputBuffer,
206.1629 +                                                 void * OutputBuffer,
206.1630 +                                                 cmsUInt32Number Size);
206.1631 +
206.1632 +CMSAPI void             CMSEXPORT cmsSetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
206.1633 +CMSAPI void             CMSEXPORT cmsGetAlarmCodes(cmsUInt16Number NewAlarm[cmsMAXCHANNELS]);
206.1634 +
206.1635 +// Adaptation state for absolute colorimetric intent
206.1636 +CMSAPI cmsFloat64Number CMSEXPORT cmsSetAdaptationState(cmsFloat64Number d);
206.1637 +
206.1638 +CMSAPI cmsContext       CMSEXPORT cmsGetTransformContextID(cmsHTRANSFORM hTransform);
206.1639 +
206.1640 +
206.1641 +// PostScript ColorRenderingDictionary and ColorSpaceArray ----------------------------------------------------
206.1642 +
206.1643 +typedef enum { cmsPS_RESOURCE_CSA, cmsPS_RESOURCE_CRD } cmsPSResourceType;
206.1644 +
206.1645 +// lcms2 unified method to access postscript color resources
206.1646 +CMSAPI cmsUInt32Number  CMSEXPORT cmsGetPostScriptColorResource(cmsContext ContextID,
206.1647 +                                                                cmsPSResourceType Type,
206.1648 +                                                                cmsHPROFILE hProfile,
206.1649 +                                                                cmsUInt32Number Intent,
206.1650 +                                                                cmsUInt32Number dwFlags,
206.1651 +                                                                cmsIOHANDLER* io);
206.1652 +
206.1653 +CMSAPI cmsUInt32Number  CMSEXPORT cmsGetPostScriptCSA(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags, void* Buffer, cmsUInt32Number dwBufferLen);
206.1654 +CMSAPI cmsUInt32Number  CMSEXPORT cmsGetPostScriptCRD(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags, void* Buffer, cmsUInt32Number dwBufferLen);
206.1655 +
206.1656 +
206.1657 +// IT8.7 / CGATS.17-200x handling -----------------------------------------------------------------------------
206.1658 +
206.1659 +CMSAPI cmsHANDLE        CMSEXPORT cmsIT8Alloc(cmsContext ContextID);
206.1660 +CMSAPI void             CMSEXPORT cmsIT8Free(cmsHANDLE hIT8);
206.1661 +
206.1662 +// Tables
206.1663 +CMSAPI cmsUInt32Number  CMSEXPORT cmsIT8TableCount(cmsHANDLE hIT8);
206.1664 +CMSAPI cmsInt32Number   CMSEXPORT cmsIT8SetTable(cmsHANDLE hIT8, cmsUInt32Number nTable);
206.1665 +
206.1666 +// Persistence
206.1667 +CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromFile(cmsContext ContextID, const char* cFileName);
206.1668 +CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromMem(cmsContext ContextID, void *Ptr, cmsUInt32Number len);
206.1669 +// CMSAPI cmsHANDLE        CMSEXPORT cmsIT8LoadFromIOhandler(cmsContext ContextID, cmsIOHANDLER* io);
206.1670 +
206.1671 +CMSAPI cmsBool          CMSEXPORT cmsIT8SaveToFile(cmsHANDLE hIT8, const char* cFileName);
206.1672 +CMSAPI cmsBool          CMSEXPORT cmsIT8SaveToMem(cmsHANDLE hIT8, void *MemPtr, cmsUInt32Number* BytesNeeded);
206.1673 +
206.1674 +// Properties
206.1675 +CMSAPI const char*      CMSEXPORT cmsIT8GetSheetType(cmsHANDLE hIT8);
206.1676 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetSheetType(cmsHANDLE hIT8, const char* Type);
206.1677 +
206.1678 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetComment(cmsHANDLE hIT8, const char* cComment);
206.1679 +
206.1680 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetPropertyStr(cmsHANDLE hIT8, const char* cProp, const char *Str);
206.1681 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetPropertyDbl(cmsHANDLE hIT8, const char* cProp, cmsFloat64Number Val);
206.1682 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetPropertyHex(cmsHANDLE hIT8, const char* cProp, cmsUInt32Number Val);
206.1683 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetPropertyUncooked(cmsHANDLE hIT8, const char* Key, const char* Buffer);
206.1684 +
206.1685 +
206.1686 +CMSAPI const char*      CMSEXPORT cmsIT8GetProperty(cmsHANDLE hIT8, const char* cProp);
206.1687 +CMSAPI cmsFloat64Number CMSEXPORT cmsIT8GetPropertyDbl(cmsHANDLE hIT8, const char* cProp);
206.1688 +CMSAPI cmsUInt32Number  CMSEXPORT cmsIT8EnumProperties(cmsHANDLE hIT8, char ***PropertyNames);
206.1689 +
206.1690 +// Datasets
206.1691 +CMSAPI const char*      CMSEXPORT cmsIT8GetDataRowCol(cmsHANDLE hIT8, int row, int col);
206.1692 +CMSAPI cmsFloat64Number CMSEXPORT cmsIT8GetDataRowColDbl(cmsHANDLE hIT8, int row, int col);
206.1693 +
206.1694 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetDataRowCol(cmsHANDLE hIT8, int row, int col,
206.1695 +                                                const char* Val);
206.1696 +
206.1697 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetDataRowColDbl(cmsHANDLE hIT8, int row, int col,
206.1698 +                                                cmsFloat64Number Val);
206.1699 +
206.1700 +CMSAPI const char*      CMSEXPORT cmsIT8GetData(cmsHANDLE hIT8, const char* cPatch, const char* cSample);
206.1701 +
206.1702 +
206.1703 +CMSAPI cmsFloat64Number CMSEXPORT cmsIT8GetDataDbl(cmsHANDLE hIT8, const char* cPatch, const char* cSample);
206.1704 +
206.1705 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetData(cmsHANDLE hIT8, const char* cPatch,
206.1706 +                                                const char* cSample,
206.1707 +                                                const char *Val);
206.1708 +
206.1709 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetDataDbl(cmsHANDLE hIT8, const char* cPatch,
206.1710 +                                                const char* cSample,
206.1711 +                                                cmsFloat64Number Val);
206.1712 +
206.1713 +CMSAPI int              CMSEXPORT cmsIT8FindDataFormat(cmsHANDLE hIT8, const char* cSample);
206.1714 +CMSAPI cmsBool          CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE hIT8, int n, const char *Sample);
206.1715 +CMSAPI int              CMSEXPORT cmsIT8EnumDataFormat(cmsHANDLE hIT8, char ***SampleNames);
206.1716 +
206.1717 +CMSAPI const char*      CMSEXPORT cmsIT8GetPatchName(cmsHANDLE hIT8, int nPatch, char* buffer);
206.1718 +
206.1719 +// The LABEL extension
206.1720 +CMSAPI int              CMSEXPORT cmsIT8SetTableByLabel(cmsHANDLE hIT8, const char* cSet, const char* cField, const char* ExpectedType);
206.1721 +
206.1722 +// Formatter for double
206.1723 +CMSAPI void             CMSEXPORT cmsIT8DefineDblFormat(cmsHANDLE hIT8, const char* Formatter);
206.1724 +
206.1725 +// Gamut boundary description routines ------------------------------------------------------------------------------
206.1726 +
206.1727 +CMSAPI cmsHANDLE        CMSEXPORT cmsGBDAlloc(cmsContext ContextID);
206.1728 +CMSAPI void             CMSEXPORT cmsGBDFree(cmsHANDLE hGBD);
206.1729 +CMSAPI cmsBool          CMSEXPORT cmsGDBAddPoint(cmsHANDLE hGBD, const cmsCIELab* Lab);
206.1730 +CMSAPI cmsBool          CMSEXPORT cmsGDBCompute(cmsHANDLE  hGDB, cmsUInt32Number dwFlags);
206.1731 +CMSAPI cmsBool          CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab);
206.1732 +
206.1733 +// Feature detection  ----------------------------------------------------------------------------------------------
206.1734 +
206.1735 +// Estimate the black point
206.1736 +CMSAPI cmsBool          CMSEXPORT cmsDetectBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags);
206.1737 +
206.1738 +// Estimate total area coverage
206.1739 +CMSAPI cmsFloat64Number CMSEXPORT cmsDetectTAC(cmsHPROFILE hProfile);
206.1740 +
206.1741 +
206.1742 +// Poor man's gamut mapping
206.1743 +CMSAPI cmsBool          CMSEXPORT cmsDesaturateLab(cmsCIELab* Lab,
206.1744 +                                                   double amax, double amin,
206.1745 +                                                   double bmax, double bmin);
206.1746 +
206.1747 +#ifndef CMS_USE_CPP_API
206.1748 +#   ifdef __cplusplus
206.1749 +    }
206.1750 +#   endif
206.1751 +#endif
206.1752 +
206.1753 +#define _lcms2_H
206.1754 +#endif
   207.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   207.2 +++ b/src/share/native/sun/java2d/cmm/lcms/lcms2_internal.h	Fri Sep 24 16:41:32 2010 -0700
   207.3 @@ -0,0 +1,678 @@
   207.4 +/*
   207.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   207.6 + *
   207.7 + * This code is free software; you can redistribute it and/or modify it
   207.8 + * under the terms of the GNU General Public License version 2 only, as
   207.9 + * published by the Free Software Foundation.  Oracle designates this
  207.10 + * particular file as subject to the "Classpath" exception as provided
  207.11 + * by Oracle in the LICENSE file that accompanied this code.
  207.12 + *
  207.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  207.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  207.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  207.16 + * version 2 for more details (a copy is included in the LICENSE file that
  207.17 + * accompanied this code).
  207.18 + *
  207.19 + * You should have received a copy of the GNU General Public License version
  207.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  207.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  207.22 + *
  207.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  207.24 + * or visit www.oracle.com if you need additional information or have any
  207.25 + * questions.
  207.26 + */
  207.27 +
  207.28 +// This file is available under and governed by the GNU General Public
  207.29 +// License version 2 only, as published by the Free Software Foundation.
  207.30 +// However, the following notice accompanied the original version of this
  207.31 +// file:
  207.32 +//
  207.33 +//---------------------------------------------------------------------------------
  207.34 +//
  207.35 +//  Little Color Management System
  207.36 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  207.37 +//
  207.38 +// Permission is hereby granted, free of charge, to any person obtaining
  207.39 +// a copy of this software and associated documentation files (the "Software"),
  207.40 +// to deal in the Software without restriction, including without limitation
  207.41 +// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  207.42 +// and/or sell copies of the Software, and to permit persons to whom the Software
  207.43 +// is furnished to do so, subject to the following conditions:
  207.44 +//
  207.45 +// The above copyright notice and this permission notice shall be included in
  207.46 +// all copies or substantial portions of the Software.
  207.47 +//
  207.48 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  207.49 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  207.50 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  207.51 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  207.52 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  207.53 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  207.54 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  207.55 +//
  207.56 +//---------------------------------------------------------------------------------
  207.57 +//
  207.58 +
  207.59 +#ifndef _lcms_internal_H
  207.60 +
  207.61 +// Include plug-in foundation
  207.62 +#ifndef _lcms_plugin_H
  207.63 +#   include "lcms2_plugin.h"
  207.64 +#endif
  207.65 +
  207.66 +// ctype is part of C99 as per 7.1.2
  207.67 +#include <ctype.h>
  207.68 +
  207.69 +// assert macro is part of C99 as per 7.2
  207.70 +#include <assert.h>
  207.71 +
  207.72 +// Some needed constants
  207.73 +#ifndef M_PI
  207.74 +#       define M_PI        3.14159265358979323846
  207.75 +#endif
  207.76 +
  207.77 +#ifndef M_LOG10E
  207.78 +#       define M_LOG10E    0.434294481903251827651
  207.79 +#endif
  207.80 +
  207.81 +// BorlandC 5.5 is broken on that
  207.82 +#ifdef __BORLANDC__
  207.83 +#define sinf(x) (float)sin((float)x)
  207.84 +#define sqrtf(x) (float)sqrt((float)x)
  207.85 +#endif
  207.86 +
  207.87 +
  207.88 +// Alignment of ICC file format uses 4 bytes (cmsUInt32Number)
  207.89 +#define _cmsSIZEOFLONGMINUS1    (sizeof(cmsUInt32Number)-1)
  207.90 +#define _cmsALIGNLONG(x) (((x)+_cmsSIZEOFLONGMINUS1) & ~(_cmsSIZEOFLONGMINUS1))
  207.91 +
  207.92 +// Maximum encodeable values in floating point
  207.93 +#define MAX_ENCODEABLE_XYZ  (1.0 + 32767.0/32768.0)
  207.94 +#define MIN_ENCODEABLE_ab2  (-128.0)
  207.95 +#define MAX_ENCODEABLE_ab2  ((65535.0/256.0) - 128.0)
  207.96 +#define MIN_ENCODEABLE_ab4  (-128.0)
  207.97 +#define MAX_ENCODEABLE_ab4  (127.0)
  207.98 +
  207.99 +// Maximum of channels for internal pipeline evaluation
 207.100 +#define MAX_STAGE_CHANNELS      128
 207.101 +
 207.102 +// Unused parameter warning supression
 207.103 +#define cmsUNUSED_PARAMETER(x) ((void)x)
 207.104 +
 207.105 +// The specification for "inline" is section 6.7.4 of the C99 standard (ISO/IEC 9899:1999).
 207.106 +// unfortunately VisualC++ does not conform that
 207.107 +#if defined(_MSC_VER) || defined(__BORLANDC__)
 207.108 +#   define cmsINLINE __inline
 207.109 +#else
 207.110 +#   define cmsINLINE static inline
 207.111 +#endif
 207.112 +
 207.113 +// Other replacement functions
 207.114 +#ifdef _MSC_VER
 207.115 +# ifndef snprintf
 207.116 +#       define snprintf  _snprintf
 207.117 +# endif
 207.118 +# ifndef vsnprintf
 207.119 +#       define vsnprintf  _vsnprintf
 207.120 +# endif
 207.121 +#endif
 207.122 +
 207.123 +// Pthreads. In windows we use the native WIN32 API instead
 207.124 +#ifdef CMS_DONT_USE_PTHREADS
 207.125 +typedef int LCMS_RWLOCK_T;
 207.126 +#   define LCMS_CREATE_LOCK(x)
 207.127 +#   define LCMS_FREE_LOCK(x)
 207.128 +#   define LCMS_READ_LOCK(x)
 207.129 +#   define LCMS_WRITE_LOCK(x)
 207.130 +#   define LCMS_UNLOCK(x)
 207.131 +#else
 207.132 +#ifdef CMS_IS_WINDOWS_
 207.133 +#   ifndef WIN32_LEAN_AND_MEAN
 207.134 +#       define WIN32_LEAN_AND_MEAN
 207.135 +#   endif
 207.136 +#   include <windows.h>
 207.137 +    typedef CRITICAL_SECTION LCMS_RWLOCK_T;
 207.138 +#   define LCMS_CREATE_LOCK(x)       InitializeCriticalSection((x))
 207.139 +#   define LCMS_FREE_LOCK(x)         DeleteCriticalSection((x))
 207.140 +#   define LCMS_READ_LOCK(x)         EnterCriticalSection((x))
 207.141 +#   define LCMS_WRITE_LOCK(x)        EnterCriticalSection((x))
 207.142 +#   define LCMS_UNLOCK(x)            LeaveCriticalSection((x))
 207.143 +#else
 207.144 +#   include <pthread.h>
 207.145 +    typedef    pthread_rwlock_t      LCMS_RWLOCK_T;
 207.146 +#   define LCMS_CREATE_LOCK(x)       pthread_rwlock_init((x), NULL)
 207.147 +#   define LCMS_FREE_LOCK(x)         pthread_rwlock_destroy((x))
 207.148 +#   define LCMS_READ_LOCK(x)         pthread_rwlock_rdlock((x))
 207.149 +#   define LCMS_WRITE_LOCK(x)        pthread_rwlock_wrlock((x))
 207.150 +#   define LCMS_UNLOCK(x)            pthread_rwlock_unlock((x))
 207.151 +#endif
 207.152 +#endif
 207.153 +
 207.154 +// A fast way to convert from/to 16 <-> 8 bits
 207.155 +#define FROM_8_TO_16(rgb) (cmsUInt16Number) ((((cmsUInt16Number) (rgb)) << 8)|(rgb))
 207.156 +#define FROM_16_TO_8(rgb) (cmsUInt8Number) ((((rgb) * 65281 + 8388608) >> 24) & 0xFF)
 207.157 +
 207.158 +// Code analysis is broken on asserts
 207.159 +#ifdef _MSC_VER
 207.160 +#    if (_MSC_VER >= 1500)
 207.161 +#            define _cmsAssert(a)  { assert((a)); __analysis_assume((a)); }
 207.162 +#     else
 207.163 +#            define _cmsAssert(a)   assert((a))
 207.164 +#     endif
 207.165 +#else
 207.166 +#      define _cmsAssert(a)   assert((a))
 207.167 +#endif
 207.168 +
 207.169 +//---------------------------------------------------------------------------------
 207.170 +
 207.171 +// Determinant lower than that are assumed zero (used on matrix invert)
 207.172 +#define MATRIX_DET_TOLERANCE    0.0001
 207.173 +
 207.174 +//---------------------------------------------------------------------------------
 207.175 +
 207.176 +// Fixed point
 207.177 +#define FIXED_TO_INT(x)         ((x)>>16)
 207.178 +#define FIXED_REST_TO_INT(x)    ((x)&0xFFFFU)
 207.179 +#define ROUND_FIXED_TO_INT(x)   (((x)+0x8000)>>16)
 207.180 +
 207.181 +cmsINLINE cmsS15Fixed16Number _cmsToFixedDomain(int a)                   { return a + ((a + 0x7fff) / 0xffff); }
 207.182 +cmsINLINE int                 _cmsFromFixedDomain(cmsS15Fixed16Number a) { return a - ((a + 0x7fff) >> 16); }
 207.183 +
 207.184 +// -----------------------------------------------------------------------------------------------------------
 207.185 +
 207.186 +// Fast floor conversion logic. Thanks to Sree Kotay and Stuart Nixon
 207.187 +// note than this only works in the range ..-32767...+32767 because
 207.188 +// mantissa is interpreted as 15.16 fixed point.
 207.189 +// The union is to avoid pointer aliasing overoptimization.
 207.190 +cmsINLINE int _cmsQuickFloor(cmsFloat64Number val)
 207.191 +{
 207.192 +#ifdef CMS_DONT_USE_FAST_FLOOR
 207.193 +    return (int) floor(val);
 207.194 +#else
 207.195 +    const cmsFloat64Number _lcms_double2fixmagic = 68719476736.0 * 1.5;  // 2^36 * 1.5, (52-16=36) uses limited precision to floor
 207.196 +    union {
 207.197 +        cmsFloat64Number val;
 207.198 +        int halves[2];
 207.199 +    } temp;
 207.200 +
 207.201 +    temp.val = val + _lcms_double2fixmagic;
 207.202 +
 207.203 +#ifdef CMS_USE_BIG_ENDIAN
 207.204 +    return temp.halves[1] >> 16;
 207.205 +#else
 207.206 +    return temp.halves[0] >> 16;
 207.207 +#endif
 207.208 +#endif
 207.209 +}
 207.210 +
 207.211 +// Fast floor restricted to 0..65535.0
 207.212 +cmsINLINE cmsUInt16Number _cmsQuickFloorWord(cmsFloat64Number d)
 207.213 +{
 207.214 +    return (cmsUInt16Number) _cmsQuickFloor(d - 32767.0) + 32767U;
 207.215 +}
 207.216 +
 207.217 +// Floor to word, taking care of saturation
 207.218 +cmsINLINE cmsUInt16Number _cmsQuickSaturateWord(cmsFloat64Number d)
 207.219 +{
 207.220 +    d += 0.5;
 207.221 +    if (d <= 0) return 0;
 207.222 +    if (d >= 65535.0) return 0xffff;
 207.223 +
 207.224 +    return _cmsQuickFloorWord(d);
 207.225 +}
 207.226 +
 207.227 +// Plug-In registering ---------------------------------------------------------------
 207.228 +
 207.229 +// Specialized function for plug-in memory management. No pairing free() since whole pool is freed at once.
 207.230 +void* _cmsPluginMalloc(cmsUInt32Number size);
 207.231 +
 207.232 +// Memory management
 207.233 +cmsBool   _cmsRegisterMemHandlerPlugin(cmsPluginBase* Plugin);
 207.234 +
 207.235 +// Interpolation
 207.236 +cmsBool  _cmsRegisterInterpPlugin(cmsPluginBase* Plugin);
 207.237 +
 207.238 +// Parametric curves
 207.239 +cmsBool  _cmsRegisterParametricCurvesPlugin(cmsPluginBase* Plugin);
 207.240 +
 207.241 +// Formatters management
 207.242 +cmsBool  _cmsRegisterFormattersPlugin(cmsPluginBase* Plugin);
 207.243 +
 207.244 +// Tag type management
 207.245 +cmsBool  _cmsRegisterTagTypePlugin(cmsPluginBase* Plugin);
 207.246 +
 207.247 +// Tag management
 207.248 +cmsBool  _cmsRegisterTagPlugin(cmsPluginBase* Plugin);
 207.249 +
 207.250 +// Intent management
 207.251 +cmsBool  _cmsRegisterRenderingIntentPlugin(cmsPluginBase* Plugin);
 207.252 +
 207.253 +// Multi Process elements
 207.254 +cmsBool  _cmsRegisterMultiProcessElementPlugin(cmsPluginBase* Plugin);
 207.255 +
 207.256 +// Optimization
 207.257 +cmsBool  _cmsRegisterOptimizationPlugin(cmsPluginBase* Plugin);
 207.258 +
 207.259 +
 207.260 +// ---------------------------------------------------------------------------------------------------------
 207.261 +
 207.262 +// Suballocators. Those are blocks of memory that is freed at the end on whole block.
 207.263 +typedef struct _cmsSubAllocator_chunk_st {
 207.264 +
 207.265 +    cmsUInt8Number* Block;
 207.266 +    cmsUInt32Number BlockSize;
 207.267 +    cmsUInt32Number Used;
 207.268 +
 207.269 +    struct _cmsSubAllocator_chunk_st* next;
 207.270 +
 207.271 +} _cmsSubAllocator_chunk;
 207.272 +
 207.273 +
 207.274 +typedef struct {
 207.275 +
 207.276 +    cmsContext ContextID;
 207.277 +    _cmsSubAllocator_chunk* h;
 207.278 +
 207.279 +} _cmsSubAllocator;
 207.280 +
 207.281 +
 207.282 +_cmsSubAllocator* _cmsCreateSubAlloc(cmsContext ContextID, cmsUInt32Number Initial);
 207.283 +void              _cmsSubAllocDestroy(_cmsSubAllocator* s);
 207.284 +void*             _cmsSubAlloc(_cmsSubAllocator* s, cmsUInt32Number size);
 207.285 +
 207.286 +// ----------------------------------------------------------------------------------
 207.287 +
 207.288 +// MLU internal representation
 207.289 +typedef struct {
 207.290 +
 207.291 +    cmsUInt16Number Language;
 207.292 +    cmsUInt16Number Country;
 207.293 +
 207.294 +    cmsUInt32Number StrW;       // Offset to current unicode string
 207.295 +    cmsUInt32Number Len;        // Lenght in bytes
 207.296 +
 207.297 +} _cmsMLUentry;
 207.298 +
 207.299 +struct _cms_MLU_struct {
 207.300 +
 207.301 +    cmsContext ContextID;
 207.302 +
 207.303 +    // The directory
 207.304 +    int AllocatedEntries;
 207.305 +    int UsedEntries;
 207.306 +    _cmsMLUentry* Entries;     // Array of pointers to strings allocated in MemPool
 207.307 +
 207.308 +    // The Pool
 207.309 +    cmsUInt32Number PoolSize;  // The maximum allocated size
 207.310 +    cmsUInt32Number PoolUsed;  // The used size
 207.311 +    void*  MemPool;            // Pointer to begin of memory pool
 207.312 +};
 207.313 +
 207.314 +// Named color list internal representation
 207.315 +typedef struct {
 207.316 +
 207.317 +    char Name[cmsMAX_PATH];
 207.318 +    cmsUInt16Number PCS[3];
 207.319 +    cmsUInt16Number DeviceColorant[cmsMAXCHANNELS];
 207.320 +
 207.321 +} _cmsNAMEDCOLOR;
 207.322 +
 207.323 +struct _cms_NAMEDCOLORLIST_struct {
 207.324 +
 207.325 +    cmsUInt32Number nColors;
 207.326 +    cmsUInt32Number Allocated;
 207.327 +    cmsUInt32Number ColorantCount;
 207.328 +
 207.329 +    char Prefix[33];      // Prefix and suffix are defined to be 32 characters at most
 207.330 +    char Suffix[33];
 207.331 +
 207.332 +    _cmsNAMEDCOLOR* List;
 207.333 +
 207.334 +    cmsContext ContextID;
 207.335 +};
 207.336 +
 207.337 +
 207.338 +// ----------------------------------------------------------------------------------
 207.339 +
 207.340 +// This is the internal struct holding profile details.
 207.341 +
 207.342 +// Maximum supported tags in a profile
 207.343 +#define MAX_TABLE_TAG       100
 207.344 +
 207.345 +typedef struct _cms_iccprofile_struct {
 207.346 +
 207.347 +    // I/O handler
 207.348 +    cmsIOHANDLER*            IOhandler;
 207.349 +
 207.350 +    // The thread ID
 207.351 +    cmsContext               ContextID;
 207.352 +
 207.353 +    // Creation time
 207.354 +    struct tm                Created;
 207.355 +
 207.356 +    // Only most important items found in ICC profiles
 207.357 +    cmsUInt32Number          Version;
 207.358 +    cmsProfileClassSignature DeviceClass;
 207.359 +    cmsColorSpaceSignature   ColorSpace;
 207.360 +    cmsColorSpaceSignature   PCS;
 207.361 +    cmsUInt32Number          RenderingIntent;
 207.362 +    cmsUInt32Number          flags;
 207.363 +    cmsUInt32Number          manufacturer, model;
 207.364 +    cmsUInt64Number          attributes;
 207.365 +
 207.366 +    cmsProfileID             ProfileID;
 207.367 +
 207.368 +    // Dictionary
 207.369 +    cmsUInt32Number          TagCount;
 207.370 +    cmsTagSignature          TagNames[MAX_TABLE_TAG];
 207.371 +    cmsTagSignature          TagLinked[MAX_TABLE_TAG];           // The tag to wich is linked (0=none)
 207.372 +    cmsUInt32Number          TagSizes[MAX_TABLE_TAG];            // Size on disk
 207.373 +    cmsUInt32Number          TagOffsets[MAX_TABLE_TAG];
 207.374 +    cmsBool                  TagSaveAsRaw[MAX_TABLE_TAG];        // True to write uncooked
 207.375 +    void *                   TagPtrs[MAX_TABLE_TAG];
 207.376 +    cmsTagTypeHandler*       TagTypeHandlers[MAX_TABLE_TAG];     // Same structure may be serialized on different types
 207.377 +                                                                 // depending on profile version, so we keep track of the                                                             // type handler for each tag in the list.
 207.378 +    // Special
 207.379 +    cmsBool                  IsWrite;
 207.380 +
 207.381 +} _cmsICCPROFILE;
 207.382 +
 207.383 +// IO helpers for profiles
 207.384 +cmsBool              _cmsReadHeader(_cmsICCPROFILE* Icc);
 207.385 +cmsBool              _cmsWriteHeader(_cmsICCPROFILE* Icc, cmsUInt32Number UsedSpace);
 207.386 +int                  _cmsSearchTag(_cmsICCPROFILE* Icc, cmsTagSignature sig, cmsBool lFollowLinks);
 207.387 +
 207.388 +// Tag types
 207.389 +cmsTagTypeHandler*   _cmsGetTagTypeHandler(cmsTagTypeSignature sig);
 207.390 +cmsTagTypeSignature  _cmsGetTagTrueType(cmsHPROFILE hProfile, cmsTagSignature sig);
 207.391 +cmsTagDescriptor*    _cmsGetTagDescriptor(cmsTagSignature sig);
 207.392 +
 207.393 +// Error logging ---------------------------------------------------------------------------------------------------------
 207.394 +
 207.395 +void                 _cmsTagSignature2String(char String[5], cmsTagSignature sig);
 207.396 +
 207.397 +// Interpolation ---------------------------------------------------------------------------------------------------------
 207.398 +
 207.399 +cmsInterpParams*     _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
 207.400 +cmsInterpParams*     _cmsComputeInterpParamsEx(cmsContext ContextID, const cmsUInt32Number nSamples[], int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags);
 207.401 +void                 _cmsFreeInterpParams(cmsInterpParams* p);
 207.402 +
 207.403 +// Curves ----------------------------------------------------------------------------------------------------------------
 207.404 +
 207.405 +// This struct holds information about a segment, plus a pointer to the function that implements the evaluation.
 207.406 +// In the case of table-based, Eval pointer is set to NULL
 207.407 +
 207.408 +// The gamma function main structure
 207.409 +struct _cms_curve_struct {
 207.410 +
 207.411 +    cmsInterpParams*  InterpParams;  // Private optimizations for interpolation
 207.412 +
 207.413 +    cmsUInt32Number   nSegments;     // Number of segments in the curve. Zero for a 16-bit based tables
 207.414 +    cmsCurveSegment*  Segments;      // The segments
 207.415 +    cmsInterpParams** SegInterp;     // Array of private optimizations for interpolation in table-based segments
 207.416 +
 207.417 +    cmsParametricCurveEvaluator* Evals;  // Evaluators (one per segment)
 207.418 +
 207.419 +    // 16 bit Table-based representation follows
 207.420 +    cmsUInt32Number    nEntries;      // Number of table elements
 207.421 +    cmsUInt16Number*   Table16;       // The table itself.
 207.422 +};
 207.423 +
 207.424 +
 207.425 +//  Pipelines & Stages ---------------------------------------------------------------------------------------------
 207.426 +
 207.427 +// A single stage
 207.428 +struct _cmsStage_struct {
 207.429 +
 207.430 +    cmsContext          ContextID;
 207.431 +
 207.432 +    cmsStageSignature   Type;           // Identifies the stage
 207.433 +    cmsStageSignature   Implements;     // Identifies the *function* of the stage (for optimizations)
 207.434 +
 207.435 +    cmsUInt32Number     InputChannels;  // Input channels -- for optimization purposes
 207.436 +    cmsUInt32Number     OutputChannels; // Output channels -- for optimization purposes
 207.437 +
 207.438 +    _cmsStageEvalFn     EvalPtr;        // Points to fn that evaluates the stage (always in floating point)
 207.439 +    _cmsStageDupElemFn  DupElemPtr;     // Points to a fn that duplicates the *data* of the stage
 207.440 +    _cmsStageFreeElemFn FreePtr;        // Points to a fn that sets the *data* of the stage free
 207.441 +
 207.442 +    // A generic pointer to whatever memory needed by the stage
 207.443 +    void*               Data;
 207.444 +
 207.445 +    // Maintains linked list (used internally)
 207.446 +    struct _cmsStage_struct* Next;
 207.447 +};
 207.448 +
 207.449 +// Data kept in "Element" member of cmsStage
 207.450 +
 207.451 +// Curves
 207.452 +typedef struct {
 207.453 +    cmsUInt32Number nCurves;
 207.454 +    cmsToneCurve**  TheCurves;
 207.455 +
 207.456 +} _cmsStageToneCurvesData;
 207.457 +
 207.458 +// Matrix
 207.459 +typedef struct {
 207.460 +    cmsFloat64Number*  Double;          // floating point for the matrix
 207.461 +    cmsFloat64Number*  Offset;          // The offset
 207.462 +
 207.463 +} _cmsStageMatrixData;
 207.464 +
 207.465 +// CLUT
 207.466 +typedef struct {
 207.467 +
 207.468 +    union {                       // Can have only one of both representations at same time
 207.469 +        cmsUInt16Number*  T;      // Points to the table 16 bits table
 207.470 +        cmsFloat32Number* TFloat; // Points to the cmsFloat32Number table
 207.471 +
 207.472 +    } Tab;
 207.473 +
 207.474 +    cmsInterpParams* Params;
 207.475 +    cmsUInt32Number  nEntries;
 207.476 +    cmsBool          HasFloatValues;
 207.477 +
 207.478 +} _cmsStageCLutData;
 207.479 +
 207.480 +
 207.481 +// Special Stages (cannot be saved)
 207.482 +cmsStage*        _cmsStageAllocLab2XYZ(cmsContext ContextID);
 207.483 +cmsStage*        _cmsStageAllocXYZ2Lab(cmsContext ContextID);
 207.484 +cmsStage*        _cmsStageAllocLabPrelin(cmsContext ContextID);
 207.485 +cmsStage*        _cmsStageAllocLabV2ToV4(cmsContext ContextID);
 207.486 +cmsStage*        _cmsStageAllocLabV2ToV4curves(cmsContext ContextID);
 207.487 +cmsStage*        _cmsStageAllocLabV4ToV2(cmsContext ContextID);
 207.488 +cmsStage*        _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList);
 207.489 +cmsStage*        _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels);
 207.490 +cmsStage*        _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan);
 207.491 +
 207.492 +// For curve set only
 207.493 +cmsToneCurve**     _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
 207.494 +
 207.495 +
 207.496 +// Pipeline Evaluator (in floating point)
 207.497 +typedef void (* _cmsPipelineEvalFloatFn)(const cmsFloat32Number In[],
 207.498 +                                         cmsFloat32Number Out[],
 207.499 +                                         const void* Data);
 207.500 +
 207.501 +struct _cmsPipeline_struct {
 207.502 +
 207.503 +    cmsStage* Elements;                                // Points to elements chain
 207.504 +    cmsUInt32Number InputChannels, OutputChannels;
 207.505 +
 207.506 +    // Data & evaluators
 207.507 +    void *Data;
 207.508 +
 207.509 +   _cmsOPTeval16Fn         Eval16Fn;
 207.510 +   _cmsPipelineEvalFloatFn EvalFloatFn;
 207.511 +   _cmsOPTfreeDataFn       FreeDataFn;
 207.512 +   _cmsOPTdupDataFn        DupDataFn;
 207.513 +
 207.514 +    cmsContext ContextID;            // Environment
 207.515 +
 207.516 +    cmsBool  SaveAs8Bits;            // Implemntation-specific: save as 8 bits if possible
 207.517 +};
 207.518 +
 207.519 +// LUT reading & creation -------------------------------------------------------------------------------------------
 207.520 +
 207.521 +// Read tags using low-level function, provide necessary glue code to adapt versions, etc. All those return a brand new copy
 207.522 +// of the LUTS, since ownership of original is up to the profile. The user should free allocated resources.
 207.523 +
 207.524 +cmsPipeline*      _cmsReadInputLUT(cmsHPROFILE hProfile, int Intent);
 207.525 +cmsPipeline*      _cmsReadOutputLUT(cmsHPROFILE hProfile, int Intent);
 207.526 +cmsPipeline*      _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent);
 207.527 +
 207.528 +// Special values
 207.529 +cmsBool           _cmsReadMediaWhitePoint(cmsCIEXYZ* Dest, cmsHPROFILE hProfile);
 207.530 +cmsBool           _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile);
 207.531 +
 207.532 +// Profile linker --------------------------------------------------------------------------------------------------
 207.533 +
 207.534 +cmsPipeline* _cmsLinkProfiles(cmsContext         ContextID,
 207.535 +                              cmsUInt32Number    nProfiles,
 207.536 +                              cmsUInt32Number    TheIntents[],
 207.537 +                              cmsHPROFILE        hProfiles[],
 207.538 +                              cmsBool            BPC[],
 207.539 +                              cmsFloat64Number   AdaptationStates[],
 207.540 +                              cmsUInt32Number    dwFlags);
 207.541 +
 207.542 +// Sequence --------------------------------------------------------------------------------------------------------
 207.543 +
 207.544 +cmsSEQ* _cmsReadProfileSequence(cmsHPROFILE hProfile);
 207.545 +cmsBool _cmsWriteProfileSequence(cmsHPROFILE hProfile, const cmsSEQ* seq);
 207.546 +cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfiles, cmsHPROFILE hProfiles[]);
 207.547 +
 207.548 +
 207.549 +// LUT optimization ------------------------------------------------------------------------------------------------
 207.550 +
 207.551 +cmsUInt16Number  _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples);
 207.552 +int              _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags);
 207.553 +
 207.554 +cmsBool          _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
 207.555 +                                      cmsUInt16Number **White,
 207.556 +                                      cmsUInt16Number **Black,
 207.557 +                                      cmsUInt32Number *nOutputs);
 207.558 +
 207.559 +cmsBool          _cmsOptimizePipeline(cmsPipeline**    Lut,
 207.560 +                                      int              Intent,
 207.561 +                                      cmsUInt32Number* InputFormat,
 207.562 +                                      cmsUInt32Number* OutputFormat,
 207.563 +                                      cmsUInt32Number* dwFlags );
 207.564 +
 207.565 +
 207.566 +// Hi level LUT building ----------------------------------------------------------------------------------------------
 207.567 +
 207.568 +cmsPipeline*     _cmsCreateGamutCheckPipeline(cmsContext ContextID,
 207.569 +                                              cmsHPROFILE hProfiles[],
 207.570 +                                              cmsBool  BPC[],
 207.571 +                                              cmsUInt32Number Intents[],
 207.572 +                                              cmsFloat64Number AdaptationStates[],
 207.573 +                                              cmsUInt32Number nGamutPCSposition,
 207.574 +                                              cmsHPROFILE hGamut);
 207.575 +
 207.576 +
 207.577 +// Formatters ------------------------------------------------------------------------------------------------------------
 207.578 +
 207.579 +cmsBool         _cmsFormatterIsFloat(cmsUInt32Number Type);
 207.580 +cmsBool         _cmsFormatterIs8bit(cmsUInt32Number Type);
 207.581 +
 207.582 +cmsFormatter    _cmsGetFormatter(cmsUInt32Number Type,          // Specific type, i.e. TYPE_RGB_8
 207.583 +                                 cmsFormatterDirection Dir,
 207.584 +                                 cmsUInt32Number dwFlags);
 207.585 +
 207.586 +
 207.587 +// Transform logic ------------------------------------------------------------------------------------------------------
 207.588 +
 207.589 +struct _cmstransform_struct;
 207.590 +
 207.591 +// Full xform
 207.592 +typedef void (* _cmsTransformFn)(struct _cmstransform_struct *Transform,
 207.593 +                                 const void* InputBuffer,
 207.594 +                                 void* OutputBuffer, cmsUInt32Number Size);
 207.595 +
 207.596 +typedef struct {
 207.597 +
 207.598 +    cmsUInt32Number InputFormat, OutputFormat; // Keep formats for further reference
 207.599 +    cmsUInt32Number StrideIn, StrideOut;       // Planar support
 207.600 +
 207.601 +} cmsFormatterInfo;
 207.602 +
 207.603 +// Transformation
 207.604 +typedef struct _cmstransform_struct {
 207.605 +
 207.606 +    cmsUInt32Number InputFormat, OutputFormat; // Keep formats for further reference
 207.607 +
 207.608 +    // Points to transform code
 207.609 +    _cmsTransformFn xform;
 207.610 +
 207.611 +    // Formatters, cannot be embedded into LUT because cache
 207.612 +    cmsFormatter16 FromInput;
 207.613 +    cmsFormatter16 ToOutput;
 207.614 +
 207.615 +    cmsFormatterFloat FromInputFloat;
 207.616 +    cmsFormatterFloat ToOutputFloat;
 207.617 +
 207.618 +    // 1-pixel cache (16 bits only)
 207.619 +    cmsUInt16Number CacheIn[cmsMAXCHANNELS];
 207.620 +    cmsUInt16Number CacheOut[cmsMAXCHANNELS];
 207.621 +
 207.622 +    // Semaphor for cache
 207.623 +    LCMS_RWLOCK_T rwlock;
 207.624 +
 207.625 +    // A MPE LUT holding the full (optimized) transform
 207.626 +    cmsPipeline* Lut;
 207.627 +
 207.628 +    // A MPE LUT holding the gamut check. It goes from the input space to bilevel
 207.629 +    cmsPipeline* GamutCheck;
 207.630 +
 207.631 +    // Colorant tables
 207.632 +    cmsNAMEDCOLORLIST* InputColorant;       // Input Colorant table
 207.633 +    cmsNAMEDCOLORLIST* OutputColorant;      // Colorant table (for n chans > CMYK)
 207.634 +
 207.635 +    // Informational only
 207.636 +    cmsColorSpaceSignature EntryColorSpace;
 207.637 +    cmsColorSpaceSignature ExitColorSpace;
 207.638 +
 207.639 +    // Profiles used to create the transform
 207.640 +    cmsSEQ* Sequence;
 207.641 +
 207.642 +    cmsUInt32Number  dwOriginalFlags;
 207.643 +    cmsFloat64Number AdaptationState;
 207.644 +
 207.645 +    // The intent of this transform. That is usually the last intent in the profilechain, but may differ
 207.646 +    cmsUInt32Number RenderingIntent;
 207.647 +
 207.648 +    // An id that uniquely identifies the running context. May be null.
 207.649 +    cmsContext ContextID;
 207.650 +
 207.651 +} _cmsTRANSFORM;
 207.652 +
 207.653 +// --------------------------------------------------------------------------------------------------
 207.654 +
 207.655 +cmsHTRANSFORM _cmsChain2Lab(cmsContext             ContextID,
 207.656 +                            cmsUInt32Number        nProfiles,
 207.657 +                            cmsUInt32Number        InputFormat,
 207.658 +                            cmsUInt32Number        OutputFormat,
 207.659 +                            const cmsUInt32Number  Intents[],
 207.660 +                            const cmsHPROFILE      hProfiles[],
 207.661 +                            const cmsBool          BPC[],
 207.662 +                            const cmsFloat64Number AdaptationStates[],
 207.663 +                            cmsUInt32Number        dwFlags);
 207.664 +
 207.665 +
 207.666 +cmsToneCurve* _cmsBuildKToneCurve(cmsContext       ContextID,
 207.667 +                            cmsUInt32Number        nPoints,
 207.668 +                            cmsUInt32Number        nProfiles,
 207.669 +                            const cmsUInt32Number  Intents[],
 207.670 +                            const cmsHPROFILE      hProfiles[],
 207.671 +                            const cmsBool          BPC[],
 207.672 +                            const cmsFloat64Number AdaptationStates[],
 207.673 +                            cmsUInt32Number        dwFlags);
 207.674 +
 207.675 +cmsBool   _cmsAdaptationMatrix(cmsMAT3* r, const cmsMAT3* ConeMatrix, const cmsCIEXYZ* FromIll, const cmsCIEXYZ* ToIll);
 207.676 +
 207.677 +cmsBool   _cmsBuildRGB2XYZtransferMatrix(cmsMAT3* r, const cmsCIExyY* WhitePoint, const cmsCIExyYTRIPLE* Primaries);
 207.678 +
 207.679 +
 207.680 +#define _lcms_internal_H
 207.681 +#endif
   208.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   208.2 +++ b/src/share/native/sun/java2d/cmm/lcms/lcms2_plugin.h	Fri Sep 24 16:41:32 2010 -0700
   208.3 @@ -0,0 +1,562 @@
   208.4 +/*
   208.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   208.6 + *
   208.7 + * This code is free software; you can redistribute it and/or modify it
   208.8 + * under the terms of the GNU General Public License version 2 only, as
   208.9 + * published by the Free Software Foundation.  Oracle designates this
  208.10 + * particular file as subject to the "Classpath" exception as provided
  208.11 + * by Oracle in the LICENSE file that accompanied this code.
  208.12 + *
  208.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  208.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  208.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  208.16 + * version 2 for more details (a copy is included in the LICENSE file that
  208.17 + * accompanied this code).
  208.18 + *
  208.19 + * You should have received a copy of the GNU General Public License version
  208.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  208.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  208.22 + *
  208.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  208.24 + * or visit www.oracle.com if you need additional information or have any
  208.25 + * questions.
  208.26 + */
  208.27 +
  208.28 +// This file is available under and governed by the GNU General Public
  208.29 +// License version 2 only, as published by the Free Software Foundation.
  208.30 +// However, the following notice accompanied the original version of this
  208.31 +// file:
  208.32 +//
  208.33 +//---------------------------------------------------------------------------------
  208.34 +//
  208.35 +//  Little Color Management System
  208.36 +//  Copyright (c) 1998-2010 Marti Maria Saguer
  208.37 +//
  208.38 +// Permission is hereby granted, free of charge, to any person obtaining
  208.39 +// a copy of this software and associated documentation files (the "Software"),
  208.40 +// to deal in the Software without restriction, including without limitation
  208.41 +// the rights to use, copy, modify, merge, publish, distribute, sublicense,
  208.42 +// and/or sell copies of the Software, and to permit persons to whom the Software
  208.43 +// is furnished to do so, subject to the following conditions:
  208.44 +//
  208.45 +// The above copyright notice and this permission notice shall be included in
  208.46 +// all copies or substantial portions of the Software.
  208.47 +//
  208.48 +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  208.49 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  208.50 +// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  208.51 +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  208.52 +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  208.53 +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  208.54 +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  208.55 +//
  208.56 +//---------------------------------------------------------------------------------
  208.57 +//
  208.58 +// This is the plug-in header file. Normal LittleCMS clients should not use it.
  208.59 +// It is provided for plug-in writters that may want to access the support
  208.60 +// functions to do low level operations. All plug-in related structures
  208.61 +// are defined here. Including this file forces to include the standard API too.
  208.62 +
  208.63 +#ifndef _lcms_plugin_H
  208.64 +
  208.65 +// Deal with Microsoft's attempt at deprecating C standard runtime functions
  208.66 +#ifdef _MSC_VER
  208.67 +#    if (_MSC_VER >= 1400)
  208.68 +#      ifndef _CRT_SECURE_NO_DEPRECATE
  208.69 +#        define _CRT_SECURE_NO_DEPRECATE
  208.70 +#      endif
  208.71 +#      ifndef _CRT_SECURE_NO_WARNINGS
  208.72 +#        define _CRT_SECURE_NO_WARNINGS
  208.73 +#      endif
  208.74 +#    endif
  208.75 +#endif
  208.76 +
  208.77 +#ifndef _lcms2_H
  208.78 +#include "lcms2.h"
  208.79 +#endif
  208.80 +
  208.81 +// We need some standard C functions.
  208.82 +#include <stdlib.h>
  208.83 +#include <math.h>
  208.84 +#include <stdarg.h>
  208.85 +#include <memory.h>
  208.86 +#include <string.h>
  208.87 +
  208.88 +
  208.89 +#ifndef CMS_USE_CPP_API
  208.90 +#   ifdef __cplusplus
  208.91 +extern "C" {
  208.92 +#   endif
  208.93 +#endif
  208.94 +
  208.95 +// Vector & Matrix operations -----------------------------------------------------------------------
  208.96 +
  208.97 +// Axis of the matrix/array. No specific meaning at all.
  208.98 +#define VX      0
  208.99 +#define VY      1
 208.100 +#define VZ      2
 208.101 +
 208.102 +// Vectors
 208.103 +typedef struct {
 208.104 +    cmsFloat64Number n[3];
 208.105 +
 208.106 +    } cmsVEC3;
 208.107 +
 208.108 +// 3x3 Matrix
 208.109 +typedef struct {
 208.110 +    cmsVEC3 v[3];
 208.111 +
 208.112 +    } cmsMAT3;
 208.113 +
 208.114 +CMSAPI void               CMSEXPORT _cmsVEC3init(cmsVEC3* r, cmsFloat64Number x, cmsFloat64Number y, cmsFloat64Number z);
 208.115 +CMSAPI void               CMSEXPORT _cmsVEC3minus(cmsVEC3* r, const cmsVEC3* a, const cmsVEC3* b);
 208.116 +CMSAPI void               CMSEXPORT _cmsVEC3cross(cmsVEC3* r, const cmsVEC3* u, const cmsVEC3* v);
 208.117 +CMSAPI cmsFloat64Number   CMSEXPORT _cmsVEC3dot(const cmsVEC3* u, const cmsVEC3* v);
 208.118 +CMSAPI cmsFloat64Number   CMSEXPORT _cmsVEC3length(const cmsVEC3* a);
 208.119 +CMSAPI cmsFloat64Number   CMSEXPORT _cmsVEC3distance(const cmsVEC3* a, const cmsVEC3* b);
 208.120 +
 208.121 +CMSAPI void               CMSEXPORT _cmsMAT3identity(cmsMAT3* a);
 208.122 +CMSAPI cmsBool            CMSEXPORT _cmsMAT3isIdentity(const cmsMAT3* a);
 208.123 +CMSAPI void               CMSEXPORT _cmsMAT3per(cmsMAT3* r, const cmsMAT3* a, const cmsMAT3* b);
 208.124 +CMSAPI cmsBool            CMSEXPORT _cmsMAT3inverse(const cmsMAT3* a, cmsMAT3* b);
 208.125 +CMSAPI cmsBool            CMSEXPORT _cmsMAT3solve(cmsVEC3* x, cmsMAT3* a, cmsVEC3* b);
 208.126 +CMSAPI void               CMSEXPORT _cmsMAT3eval(cmsVEC3* r, const cmsMAT3* a, const cmsVEC3* v);
 208.127 +
 208.128 +
 208.129 +// Error logging  -------------------------------------------------------------------------------------
 208.130 +
 208.131 +CMSAPI void               CMSEXPORT  cmsSignalError(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *ErrorText, ...);
 208.132 +
 208.133 +// Memory management ----------------------------------------------------------------------------------
 208.134 +
 208.135 +CMSAPI void*              CMSEXPORT _cmsMalloc(cmsContext ContextID, cmsUInt32Number size);
 208.136 +CMSAPI void*              CMSEXPORT _cmsMallocZero(cmsContext ContextID, cmsUInt32Number size);
 208.137 +CMSAPI void*              CMSEXPORT _cmsCalloc(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size);
 208.138 +CMSAPI void*              CMSEXPORT _cmsRealloc(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize);
 208.139 +CMSAPI void               CMSEXPORT _cmsFree(cmsContext ContextID, void* Ptr);
 208.140 +CMSAPI void*              CMSEXPORT _cmsDupMem(cmsContext ContextID, const void* Org, cmsUInt32Number size);
 208.141 +
 208.142 +// I/O handler ----------------------------------------------------------------------------------
 208.143 +
 208.144 +struct _cms_io_handler {
 208.145 +
 208.146 +    void* stream;   // Associated stream, which is implemented differently depending on media.
 208.147 +
 208.148 +    cmsContext        ContextID;
 208.149 +    cmsUInt32Number   UsedSpace;
 208.150 +    char              PhysicalFile[cmsMAX_PATH];
 208.151 +
 208.152 +    cmsUInt32Number   (* Read)(struct _cms_io_handler* iohandler, void *Buffer,
 208.153 +                                                                  cmsUInt32Number size,
 208.154 +                                                                  cmsUInt32Number count);
 208.155 +    cmsBool           (* Seek)(struct _cms_io_handler* iohandler, cmsUInt32Number offset);
 208.156 +    cmsBool           (* Close)(struct _cms_io_handler* iohandler);
 208.157 +    cmsUInt32Number   (* Tell)(struct _cms_io_handler* iohandler);
 208.158 +    cmsBool           (* Write)(struct _cms_io_handler* iohandler, cmsUInt32Number size,
 208.159 +                                                                   const void* Buffer);
 208.160 +};
 208.161 +
 208.162 +// Endianess adjust functions
 208.163 +CMSAPI cmsUInt16Number   CMSEXPORT  _cmsAdjustEndianess16(cmsUInt16Number Word);
 208.164 +CMSAPI cmsUInt32Number   CMSEXPORT  _cmsAdjustEndianess32(cmsUInt32Number Value);
 208.165 +CMSAPI void              CMSEXPORT  _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number QWord);
 208.166 +
 208.167 +// Helper IO functions
 208.168 +CMSAPI cmsBool           CMSEXPORT  _cmsReadUInt8Number(cmsIOHANDLER* io,  cmsUInt8Number* n);
 208.169 +CMSAPI cmsBool           CMSEXPORT  _cmsReadUInt16Number(cmsIOHANDLER* io, cmsUInt16Number* n);
 208.170 +CMSAPI cmsBool           CMSEXPORT  _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n);
 208.171 +CMSAPI cmsBool           CMSEXPORT  _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n);
 208.172 +CMSAPI cmsBool           CMSEXPORT  _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n);
 208.173 +CMSAPI cmsBool           CMSEXPORT  _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n);
 208.174 +CMSAPI cmsBool           CMSEXPORT  _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ);
 208.175 +CMSAPI cmsBool           CMSEXPORT  _cmsReadUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, cmsUInt16Number* Array);
 208.176 +
 208.177 +CMSAPI cmsBool           CMSEXPORT  _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n);
 208.178 +CMSAPI cmsBool           CMSEXPORT  _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n);
 208.179 +CMSAPI cmsBool           CMSEXPORT  _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n);
 208.180 +CMSAPI cmsBool           CMSEXPORT  _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n);
 208.181 +CMSAPI cmsBool           CMSEXPORT  _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number n);
 208.182 +CMSAPI cmsBool           CMSEXPORT  _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n);
 208.183 +CMSAPI cmsBool           CMSEXPORT  _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ);
 208.184 +CMSAPI cmsBool           CMSEXPORT  _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array);
 208.185 +
 208.186 +// ICC base tag
 208.187 +typedef struct {
 208.188 +    cmsTagTypeSignature  sig;
 208.189 +    cmsInt8Number        reserved[4];
 208.190 +
 208.191 +} _cmsTagBase;
 208.192 +
 208.193 +// Type base helper functions
 208.194 +CMSAPI cmsTagTypeSignature  CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io);
 208.195 +CMSAPI cmsBool              CMSEXPORT _cmsWriteTypeBase(cmsIOHANDLER* io, cmsTagTypeSignature sig);
 208.196 +
 208.197 +// Alignment functions
 208.198 +CMSAPI cmsBool             CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io);
 208.199 +CMSAPI cmsBool             CMSEXPORT _cmsWriteAlignment(cmsIOHANDLER* io);
 208.200 +
 208.201 +// To deal with text streams. 2K at most
 208.202 +CMSAPI cmsBool             CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...);
 208.203 +
 208.204 +// Fixed point helper functions
 208.205 +CMSAPI cmsFloat64Number    CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8);
 208.206 +CMSAPI cmsUInt16Number     CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val);
 208.207 +
 208.208 +CMSAPI cmsFloat64Number    CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32);
 208.209 +CMSAPI cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v);
 208.210 +
 208.211 +// Date/time helper functions
 208.212 +CMSAPI void                CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source);
 208.213 +CMSAPI void                CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest);
 208.214 +
 208.215 +
 208.216 +//----------------------------------------------------------------------------------------------------------
 208.217 +
 208.218 +// Plug-in foundation
 208.219 +#define cmsPluginMagicNumber                 0x61637070     // 'acpp'
 208.220 +
 208.221 +#define cmsPluginMemHandlerSig               0x6D656D48     // 'memH'
 208.222 +#define cmsPluginInterpolationSig            0x696E7048     // 'inpH'
 208.223 +#define cmsPluginParametricCurveSig          0x70617248     // 'parH'
 208.224 +#define cmsPluginFormattersSig               0x66726D48     // 'frmH
 208.225 +#define cmsPluginTagTypeSig                  0x74797048     // 'typH'
 208.226 +#define cmsPluginTagSig                      0x74616748     // 'tagH'
 208.227 +#define cmsPluginRenderingIntentSig          0x696E7448     // 'intH'
 208.228 +#define cmsPluginMultiProcessElementSig      0x6D706548     // 'mpeH'
 208.229 +#define cmsPluginOptimizationSig             0x6F707448     // 'optH'
 208.230 +
 208.231 +typedef struct _cmsPluginBaseStruct {
 208.232 +
 208.233 +        cmsUInt32Number                Magic;               // 'acpp' signature
 208.234 +        cmsUInt32Number                ExpectedVersion;     // Expected version of LittleCMS
 208.235 +        cmsUInt32Number                Type;                // Type of plug-in
 208.236 +        struct _cmsPluginBaseStruct*   Next;                // For multiple plugin definition. NULL for end of list.
 208.237 +
 208.238 +} cmsPluginBase;
 208.239 +
 208.240 +// Maximum number of types in a plugin array
 208.241 +#define MAX_TYPES_IN_LCMS_PLUGIN    20
 208.242 +
 208.243 +//----------------------------------------------------------------------------------------------------------
 208.244 +
 208.245 +// Memory handler. Each new plug-in type replaces current behaviour
 208.246 +typedef struct {
 208.247 +
 208.248 +        cmsPluginBase base;
 208.249 +
 208.250 +        // Required
 208.251 +        void * (* MallocPtr)(cmsContext ContextID, cmsUInt32Number size);
 208.252 +        void   (* FreePtr)(cmsContext ContextID, void *Ptr);
 208.253 +        void * (* ReallocPtr)(cmsContext ContextID, void* Ptr, cmsUInt32Number NewSize);
 208.254 +
 208.255 +        // Optional
 208.256 +        void * (* MallocZeroPtr)(cmsContext ContextID, cmsUInt32Number size);
 208.257 +        void * (* CallocPtr)(cmsContext ContextID, cmsUInt32Number num, cmsUInt32Number size);
 208.258 +        void * (* DupPtr)(cmsContext ContextID, const void* Org, cmsUInt32Number size);
 208.259 +
 208.260 +} cmsPluginMemHandler;
 208.261 +
 208.262 +
 208.263 +// ------------------------------------------------------------------------------------------------------------------
 208.264 +
 208.265 +// Interpolation. 16 bits and floating point versions.
 208.266 +struct _cms_interp_struc;
 208.267 +
 208.268 +// Interpolation callbacks
 208.269 +
 208.270 +// 16 bits forward interpolation. This function performs precision-limited linear interpolation
 208.271 +// and is supposed to be quite fast. Implementation may be tetrahedral or trilinear, and plug-ins may
 208.272 +// choose to implement any other interpolation algorithm.
 208.273 +typedef void (* _cmsInterpFn16)(register const cmsUInt16Number Input[],
 208.274 +                                register cmsUInt16Number Output[],
 208.275 +                                register const struct _cms_interp_struc* p);
 208.276 +
 208.277 +// Floating point forward interpolation. Full precision interpolation using floats. This is not a
 208.278 +// time critical function. Implementation may be tetrahedral or trilinear, and plug-ins may
 208.279 +// choose to implement any other interpolation algorithm.
 208.280 +typedef void (* _cmsInterpFnFloat)(cmsFloat32Number const Input[],
 208.281 +                                   cmsFloat32Number Output[],
 208.282 +                                   const struct _cms_interp_struc* p);
 208.283 +
 208.284 +
 208.285 +
 208.286 +// This type holds a pointer to an interpolator that can be either 16 bits or float
 208.287 +typedef union {
 208.288 +    _cmsInterpFn16       Lerp16;            // Forward interpolation in 16 bits
 208.289 +    _cmsInterpFnFloat    LerpFloat;         // Forward interpolation in floating point
 208.290 +} cmsInterpFunction;
 208.291 +
 208.292 +// Flags for interpolator selection
 208.293 +#define CMS_LERP_FLAGS_16BITS             0x0000        // The default
 208.294 +#define CMS_LERP_FLAGS_FLOAT              0x0001        // Requires different implementation
 208.295 +#define CMS_LERP_FLAGS_TRILINEAR          0x0100        // Hint only
 208.296 +
 208.297 +
 208.298 +#define MAX_INPUT_DIMENSIONS 8
 208.299 +
 208.300 +typedef struct _cms_interp_struc {  // Used on all interpolations. Supplied by lcms2 when calling the interpolation function
 208.301 +
 208.302 +    cmsContext ContextID;     // The calling thread
 208.303 +
 208.304 +    cmsUInt32Number dwFlags;  // Keep original flags
 208.305 +    cmsUInt32Number nInputs;  // != 1 only in 3D interpolation
 208.306 +    cmsUInt32Number nOutputs; // != 1 only in 3D interpolation
 208.307 +
 208.308 +    cmsUInt32Number nSamples[MAX_INPUT_DIMENSIONS];  // Valid on all kinds of tables
 208.309 +    cmsUInt32Number Domain[MAX_INPUT_DIMENSIONS];    // Domain = nSamples - 1
 208.310 +
 208.311 +    cmsUInt32Number opta[MAX_INPUT_DIMENSIONS];     // Optimization for 3D CLUT. This is the number of nodes premultiplied for each
 208.312 +                                                    // dimension. For example, in 7 nodes, 7, 7^2 , 7^3, 7^4, etc. On non-regular
 208.313 +                                                    // Samplings may vary according of the number of nodes for each dimension.
 208.314 +
 208.315 +    const void *Table;                // Points to the actual interpolation table
 208.316 +    cmsInterpFunction Interpolation;  // Points to the function to do the interpolation
 208.317 +
 208.318 + } cmsInterpParams;
 208.319 +
 208.320 +// Interpolators factory
 208.321 +typedef cmsInterpFunction (* cmsInterpFnFactory)(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
 208.322 +
 208.323 +// The plug-in
 208.324 +typedef struct {
 208.325 +    cmsPluginBase base;
 208.326 +
 208.327 +    // Points to a user-supplied function which implements the factory
 208.328 +    cmsInterpFnFactory InterpolatorsFactory;
 208.329 +
 208.330 +} cmsPluginInterpolation;
 208.331 +
 208.332 +//----------------------------------------------------------------------------------------------------------
 208.333 +
 208.334 +// Parametric curves. A negative type means same function but analytically inverted. Max. number of params is 10
 208.335 +
 208.336 +// Evaluator callback for user-suplied parametric curves. May implement more than one type
 208.337 +typedef  cmsFloat64Number (* cmsParametricCurveEvaluator)(cmsInt32Number Type, const cmsFloat64Number Params[10], cmsFloat64Number R);
 208.338 +
 208.339 +// Plug-in may implement an arbitrary number of parametric curves
 208.340 +typedef struct {
 208.341 +    cmsPluginBase base;
 208.342 +
 208.343 +    cmsUInt32Number nFunctions;                                     // Number of supported functions
 208.344 +    cmsUInt32Number FunctionTypes[MAX_TYPES_IN_LCMS_PLUGIN];        // The identification types
 208.345 +    cmsUInt32Number ParameterCount[MAX_TYPES_IN_LCMS_PLUGIN];       // Number of parameters for each function
 208.346 +
 208.347 +    cmsParametricCurveEvaluator    Evaluator;                       // The evaluator
 208.348 +
 208.349 +} cmsPluginParametricCurves;
 208.350 +//----------------------------------------------------------------------------------------------------------
 208.351 +
 208.352 +// Formatters. This plug-in adds new handlers, replacing them if they already exist. Formatters dealing with
 208.353 +// cmsFloat32Number (bps = 4) or double (bps = 0) types are requested via FormatterFloat callback. Others come across
 208.354 +// Formatter16 callback
 208.355 +
 208.356 +struct _cmstransform_struct;
 208.357 +
 208.358 +typedef cmsUInt8Number* (* cmsFormatter16)(register struct _cmstransform_struct* CMMcargo,
 208.359 +                                           register cmsUInt16Number Values[],
 208.360 +                                           register cmsUInt8Number*  Buffer,
 208.361 +                                           register cmsUInt32Number  Stride);
 208.362 +
 208.363 +typedef cmsUInt8Number* (* cmsFormatterFloat)(struct _cmstransform_struct* CMMcargo,
 208.364 +                                              cmsFloat32Number Values[],
 208.365 +                                              cmsUInt8Number*  Buffer,
 208.366 +                                              cmsUInt32Number  Stride);
 208.367 +
 208.368 +// This type holds a pointer to a formatter that can be either 16 bits or cmsFloat32Number
 208.369 +typedef union {
 208.370 +    cmsFormatter16    Fmt16;
 208.371 +    cmsFormatterFloat FmtFloat;
 208.372 +
 208.373 +} cmsFormatter;
 208.374 +
 208.375 +#define CMS_PACK_FLAGS_16BITS       0x0000
 208.376 +#define CMS_PACK_FLAGS_FLOAT        0x0001
 208.377 +
 208.378 +typedef enum { cmsFormatterInput=0, cmsFormatterOutput=1 } cmsFormatterDirection;
 208.379 +
 208.380 +typedef cmsFormatter (* cmsFormatterFactory)(cmsUInt32Number Type,           // Specific type, i.e. TYPE_RGB_8
 208.381 +                                             cmsFormatterDirection Dir,
 208.382 +                                             cmsUInt32Number dwFlags);      // precision
 208.383 +
 208.384 +// Plug-in may implement an arbitrary number of formatters
 208.385 +typedef struct {
 208.386 +    cmsPluginBase          base;
 208.387 +    cmsFormatterFactory    FormattersFactory;
 208.388 +
 208.389 +} cmsPluginFormatters;
 208.390 +
 208.391 +//----------------------------------------------------------------------------------------------------------
 208.392 +
 208.393 +// Tag type handler. Each type is free to return anything it wants, and it is up to the caller to
 208.394 +// know in advance what is the type contained in the tag.
 208.395 +typedef struct _cms_typehandler_struct {
 208.396 +
 208.397 +        cmsTagTypeSignature Signature;     // The signature of the type
 208.398 +
 208.399 +        // Allocates and reads items
 208.400 +        void *   (* ReadPtr)(struct _cms_typehandler_struct* self,
 208.401 +                             cmsIOHANDLER*      io,
 208.402 +                             cmsUInt32Number*   nItems,
 208.403 +                             cmsUInt32Number    SizeOfTag);
 208.404 +
 208.405 +        // Writes n Items
 208.406 +        cmsBool  (* WritePtr)(struct _cms_typehandler_struct* self,
 208.407 +                              cmsIOHANDLER*     io,
 208.408 +                              void*             Ptr,
 208.409 +                              cmsUInt32Number   nItems);
 208.410 +
 208.411 +        // Duplicate an item or array of items
 208.412 +        void*   (* DupPtr)(struct _cms_typehandler_struct* self,
 208.413 +                           const void *Ptr,
 208.414 +                           cmsUInt32Number n);
 208.415 +
 208.416 +        // Free all resources
 208.417 +        void    (* FreePtr)(struct _cms_typehandler_struct* self,
 208.418 +                            void *Ptr);
 208.419 +
 208.420 +        // The calling thread
 208.421 +        cmsContext     ContextID;
 208.422 +
 208.423 +} cmsTagTypeHandler;
 208.424 +
 208.425 +// Each plug-in implements a single type
 208.426 +typedef struct {
 208.427 +        cmsPluginBase      base;
 208.428 +        cmsTagTypeHandler  Handler;
 208.429 +
 208.430 +} cmsPluginTagType;
 208.431 +
 208.432 +//----------------------------------------------------------------------------------------------------------
 208.433 +
 208.434 +// This is the tag plugin, which identifies tags. For writing, a pointer to function is provided.
 208.435 +// This function should return the desired type for this tag, given the version of profile
 208.436 +// and the data being serialized.
 208.437 +typedef struct {
 208.438 +
 208.439 +    cmsUInt32Number     ElemCount;          // If this tag needs an array, how many elements should keep
 208.440 +
 208.441 +    // For reading.
 208.442 +    cmsUInt32Number     nSupportedTypes;    // In how many types this tag can come (MAX_TYPES_IN_LCMS_PLUGIN maximum)
 208.443 +    cmsTagTypeSignature SupportedTypes[MAX_TYPES_IN_LCMS_PLUGIN];
 208.444 +
 208.445 +    // For writting
 208.446 +    cmsTagTypeSignature (* DecideType)(cmsFloat64Number ICCVersion, const void *Data);
 208.447 +
 208.448 +} cmsTagDescriptor;
 208.449 +
 208.450 +// Plug-in implements a single tag
 208.451 +typedef struct {
 208.452 +    cmsPluginBase    base;
 208.453 +
 208.454 +    cmsTagSignature  Signature;
 208.455 +    cmsTagDescriptor Descriptor;
 208.456 +
 208.457 +} cmsPluginTag;
 208.458 +
 208.459 +//----------------------------------------------------------------------------------------------------------
 208.460 +
 208.461 +// Custom intents. This function should join all profiles specified in the array in
 208.462 +// a single LUT. Any custom intent in the chain redirects to custom function. If more than
 208.463 +// one custom intent is found, the one located first is invoked. Usually users should use only one
 208.464 +// custom intent, so mixing custom intents in same multiprofile transform is not supported.
 208.465 +
 208.466 +typedef cmsPipeline* (* cmsIntentFn)( cmsContext       ContextID,
 208.467 +                                      cmsUInt32Number  nProfiles,
 208.468 +                                      cmsUInt32Number  Intents[],
 208.469 +                                      cmsHPROFILE      hProfiles[],
 208.470 +                                      cmsBool          BPC[],
 208.471 +                                      cmsFloat64Number AdaptationStates[],
 208.472 +                                      cmsUInt32Number  dwFlags);
 208.473 +
 208.474 +
 208.475 +// Each plug-in defines a single intent number.
 208.476 +typedef struct {
 208.477 +    cmsPluginBase     base;
 208.478 +    cmsUInt32Number   Intent;
 208.479 +    cmsIntentFn       Link;
 208.480 +    char              Description[256];
 208.481 +
 208.482 +} cmsPluginRenderingIntent;
 208.483 +
 208.484 +
 208.485 +// The default ICC intents (perceptual, saturation, rel.col and abs.col)
 208.486 +CMSAPI cmsPipeline*  CMSEXPORT _cmsDefaultICCintents(cmsContext       ContextID,
 208.487 +                                                     cmsUInt32Number  nProfiles,
 208.488 +                                                     cmsUInt32Number  Intents[],
 208.489 +                                                     cmsHPROFILE      hProfiles[],
 208.490 +                                                     cmsBool          BPC[],
 208.491 +                                                     cmsFloat64Number AdaptationStates[],
 208.492 +                                                     cmsUInt32Number  dwFlags);
 208.493 +
 208.494 +
 208.495 +//----------------------------------------------------------------------------------------------------------
 208.496 +
 208.497 +// Pipelines, Multi Process Elements.
 208.498 +
 208.499 +typedef void (* _cmsStageEvalFn)     (const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage* mpe);
 208.500 +typedef void*(* _cmsStageDupElemFn)  (cmsStage* mpe);
 208.501 +typedef void (* _cmsStageFreeElemFn) (cmsStage* mpe);
 208.502 +
 208.503 +
 208.504 +// This function allocates a generic MPE
 208.505 +CMSAPI cmsStage* CMSEXPORT _cmsStageAllocPlaceholder(cmsContext ContextID,
 208.506 +                                cmsStageSignature     Type,
 208.507 +                                cmsUInt32Number       InputChannels,
 208.508 +                                cmsUInt32Number       OutputChannels,
 208.509 +                                _cmsStageEvalFn       EvalPtr,            // Points to fn that evaluates the element (always in floating point)
 208.510 +                                _cmsStageDupElemFn    DupElemPtr,         // Points to a fn that duplicates the stage
 208.511 +                                _cmsStageFreeElemFn   FreePtr,            // Points to a fn that sets the element free
 208.512 +                                void*                 Data);              // A generic pointer to whatever memory needed by the element
 208.513 +typedef struct {
 208.514 +      cmsPluginBase     base;
 208.515 +      cmsTagTypeHandler Handler;
 208.516 +
 208.517 +}  cmsPluginMultiProcessElement;
 208.518 +
 208.519 +//----------------------------------------------------------------------------------------------------------
 208.520 +// Optimization. Using this plug-in, additional optimization strategies may be implemented.
 208.521 +// The function should return TRUE if any optimization is done on the LUT, this terminates
 208.522 +// the optimization  search. Or FALSE if it is unable to optimize and want to give a chance
 208.523 +// to the rest of optimizers.
 208.524 +
 208.525 +typedef void     (* _cmsOPTeval16Fn)(register const cmsUInt16Number In[],
 208.526 +                                     register cmsUInt16Number Out[],
 208.527 +                                     register const void* Data);
 208.528 +
 208.529 +typedef void     (* _cmsOPTfreeDataFn)(cmsContext ContextID, void* Data);
 208.530 +typedef void*    (* _cmsOPTdupDataFn)(cmsContext ContextID, const void* Data);
 208.531 +
 208.532 +
 208.533 +typedef cmsBool  (* _cmsOPToptimizeFn)(cmsPipeline** Lut,
 208.534 +                                       cmsUInt32Number  Intent,
 208.535 +                                       cmsUInt32Number* InputFormat,
 208.536 +                                       cmsUInt32Number* OutputFormat,
 208.537 +                                       cmsUInt32Number* dwFlags);
 208.538 +
 208.539 +// This function may be used to set the optional evaluator and a block of private data. If private data is being used, an optional
 208.540 +// duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality.
 208.541 +
 208.542 +CMSAPI void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut,
 208.543 +                                               _cmsOPTeval16Fn Eval16,
 208.544 +                                               void* PrivateData,
 208.545 +                                               _cmsOPTfreeDataFn FreePrivateDataFn,
 208.546 +                                               _cmsOPTdupDataFn DupPrivateDataFn);
 208.547 +
 208.548 +typedef struct {
 208.549 +      cmsPluginBase     base;
 208.550 +
 208.551 +      // Optimize entry point
 208.552 +      _cmsOPToptimizeFn  OptimizePtr;
 208.553 +
 208.554 +}  cmsPluginOptimization;
 208.555 +
 208.556 +//----------------------------------------------------------------------------------------------------------
 208.557 +
 208.558 +#ifndef CMS_USE_CPP_API
 208.559 +#   ifdef __cplusplus
 208.560 +    }
 208.561 +#   endif
 208.562 +#endif
 208.563 +
 208.564 +#define _lcms_plugin_H
 208.565 +#endif
   209.1 --- a/src/solaris/bin/java_md.c	Thu Sep 23 17:33:40 2010 -0700
   209.2 +++ b/src/solaris/bin/java_md.c	Fri Sep 24 16:41:32 2010 -0700
   209.3 @@ -535,7 +535,7 @@
   209.4  GetApplicationHome(char *buf, jint bufsize)
   209.5  {
   209.6      if (execname != NULL) {
   209.7 -        JLI_StrNCpy(buf, execname, bufsize-1);
   209.8 +        JLI_Snprintf(buf, bufsize, "%s", execname);
   209.9          buf[bufsize-1] = '\0';
  209.10      } else {
  209.11          return JNI_FALSE;
   210.1 --- a/src/solaris/classes/java/lang/UNIXProcess.java.linux	Thu Sep 23 17:33:40 2010 -0700
   210.2 +++ b/src/solaris/classes/java/lang/UNIXProcess.java.linux	Fri Sep 24 16:41:32 2010 -0700
   210.3 @@ -39,6 +39,7 @@
   210.4  import java.util.concurrent.Executor;
   210.5  import java.util.concurrent.ThreadFactory;
   210.6  import java.security.AccessController;
   210.7 +import static java.security.AccessController.doPrivileged;
   210.8  import java.security.PrivilegedAction;
   210.9  import java.security.PrivilegedActionException;
  210.10  import java.security.PrivilegedExceptionAction;
  210.11 @@ -94,14 +95,13 @@
  210.12          private final static ThreadGroup group = getRootThreadGroup();
  210.13  
  210.14          private static ThreadGroup getRootThreadGroup() {
  210.15 -            return AccessController.doPrivileged
  210.16 -            (new PrivilegedAction<ThreadGroup> () {
  210.17 -            public ThreadGroup run() {
  210.18 -                ThreadGroup root = Thread.currentThread().getThreadGroup();
  210.19 -                while (root.getParent() != null)
  210.20 -                    root = root.getParent();
  210.21 -                return root;
  210.22 -            }});
  210.23 +            return doPrivileged(new PrivilegedAction<ThreadGroup> () {
  210.24 +                public ThreadGroup run() {
  210.25 +                    ThreadGroup root = Thread.currentThread().getThreadGroup();
  210.26 +                    while (root.getParent() != null)
  210.27 +                        root = root.getParent();
  210.28 +                    return root;
  210.29 +                }});
  210.30          }
  210.31  
  210.32          public Thread newThread(Runnable grimReaper) {
  210.33 @@ -117,8 +117,12 @@
  210.34      /**
  210.35       * The thread pool of "process reaper" daemon threads.
  210.36       */
  210.37 -    private static final Executor processReaperExecutor
  210.38 -        = Executors.newCachedThreadPool(new ProcessReaperThreadFactory());
  210.39 +    private static final Executor processReaperExecutor =
  210.40 +        doPrivileged(new PrivilegedAction<Executor>() {
  210.41 +            public Executor run() {
  210.42 +                return Executors.newCachedThreadPool
  210.43 +                    (new ProcessReaperThreadFactory());
  210.44 +            }});
  210.45  
  210.46      UNIXProcess(final byte[] prog,
  210.47                  final byte[] argBlock, final int argc,
  210.48 @@ -136,8 +140,7 @@
  210.49                            redirectErrorStream);
  210.50  
  210.51          try {
  210.52 -            AccessController.doPrivileged
  210.53 -            (new PrivilegedExceptionAction<Void>() {
  210.54 +            doPrivileged(new PrivilegedExceptionAction<Void>() {
  210.55                  public Void run() throws IOException {
  210.56                      initStreams(fds);
  210.57                      return null;
   211.1 --- a/src/solaris/classes/sun/net/NetHooks.java	Thu Sep 23 17:33:40 2010 -0700
   211.2 +++ b/src/solaris/classes/sun/net/NetHooks.java	Fri Sep 24 16:41:32 2010 -0700
   211.3 @@ -73,28 +73,7 @@
   211.4       * be changed to use the ServiceLoader facility to allow the deployment of
   211.5       * other providers.
   211.6       */
   211.7 -    private static Provider loadProvider(final String cn) {
   211.8 -        return AccessController
   211.9 -            .doPrivileged(new PrivilegedAction<Provider>() {
  211.10 -                @Override public Provider run() {
  211.11 -                    Class<Provider> c;
  211.12 -                    try {
  211.13 -                        c = (Class<Provider>)Class.forName(cn, true, null);
  211.14 -                    } catch (ClassNotFoundException x) {
  211.15 -                        return null;
  211.16 -                    }
  211.17 -                    try {
  211.18 -                        return c.newInstance();
  211.19 -                    } catch (IllegalAccessException x) {
  211.20 -                        throw new AssertionError(x);
  211.21 -                    } catch (InstantiationException x) {
  211.22 -                        throw new AssertionError(x);
  211.23 -                    }
  211.24 -            }});
  211.25 -    }
  211.26 -    private static final Provider provider = AccessController
  211.27 -        .doPrivileged(new GetPropertyAction("os.name")).equals("SunOS") ?
  211.28 -            loadProvider("sun.net.spi.SdpProvider") : null;
  211.29 +    private static final Provider provider = new sun.net.sdp.SdpProvider();
  211.30  
  211.31      /**
  211.32       * Invoke prior to binding a TCP socket.
  211.33 @@ -104,8 +83,7 @@
  211.34                                       int port)
  211.35          throws IOException
  211.36      {
  211.37 -        if (provider != null)
  211.38 -            provider.implBeforeTcpBind(fdObj, address, port);
  211.39 +        provider.implBeforeTcpBind(fdObj, address, port);
  211.40      }
  211.41  
  211.42      /**
  211.43 @@ -116,7 +94,6 @@
  211.44                                          int port)
  211.45          throws IOException
  211.46      {
  211.47 -        if (provider != null)
  211.48 -            provider.implBeforeTcpConnect(fdObj, address, port);
  211.49 +        provider.implBeforeTcpConnect(fdObj, address, port);
  211.50      }
  211.51  }
   212.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   212.2 +++ b/src/solaris/classes/sun/net/sdp/SdpProvider.java	Fri Sep 24 16:41:32 2010 -0700
   212.3 @@ -0,0 +1,335 @@
   212.4 +/*
   212.5 + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   212.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   212.7 + *
   212.8 + * This code is free software; you can redistribute it and/or modify it
   212.9 + * under the terms of the GNU General Public License version 2 only, as
  212.10 + * published by the Free Software Foundation.  Oracle designates this
  212.11 + * particular file as subject to the "Classpath" exception as provided
  212.12 + * by Oracle in the LICENSE file that accompanied this code.
  212.13 + *
  212.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  212.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  212.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  212.17 + * version 2 for more details (a copy is included in the LICENSE file that
  212.18 + * accompanied this code).
  212.19 + *
  212.20 + * You should have received a copy of the GNU General Public License version
  212.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  212.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  212.23 + *
  212.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  212.25 + * or visit www.oracle.com if you need additional information or have any
  212.26 + * questions.
  212.27 + */
  212.28 +
  212.29 +package sun.net.sdp;
  212.30 +
  212.31 +import sun.net.NetHooks;
  212.32 +import java.net.InetAddress;
  212.33 +import java.net.Inet4Address;
  212.34 +import java.net.UnknownHostException;
  212.35 +import java.util.*;
  212.36 +import java.io.File;
  212.37 +import java.io.FileDescriptor;
  212.38 +import java.io.IOException;
  212.39 +import java.io.PrintStream;
  212.40 +import java.security.AccessController;
  212.41 +
  212.42 +import sun.net.sdp.SdpSupport;
  212.43 +import sun.security.action.GetPropertyAction;
  212.44 +
  212.45 +/**
  212.46 + * A NetHooks provider that converts sockets from the TCP to SDP protocol prior
  212.47 + * to binding or connecting.
  212.48 + */
  212.49 +
  212.50 +public class SdpProvider extends NetHooks.Provider {
  212.51 +    // maximum port
  212.52 +    private static final int MAX_PORT = 65535;
  212.53 +
  212.54 +    // indicates if SDP is enabled and the rules for when the protocol is used
  212.55 +    private final boolean enabled;
  212.56 +    private final List<Rule> rules;
  212.57 +
  212.58 +    // logging for debug purposes
  212.59 +    private PrintStream log;
  212.60 +
  212.61 +    public SdpProvider() {
  212.62 +        // if this property is not defined then there is nothing to do.
  212.63 +        String file = AccessController.doPrivileged(
  212.64 +            new GetPropertyAction("com.sun.sdp.conf"));
  212.65 +        if (file == null) {
  212.66 +            this.enabled = false;
  212.67 +            this.rules = null;
  212.68 +            return;
  212.69 +        }
  212.70 +
  212.71 +        // load configuration file
  212.72 +        List<Rule> list = null;
  212.73 +        if (file != null) {
  212.74 +            try {
  212.75 +                list = loadRulesFromFile(file);
  212.76 +            } catch (IOException e) {
  212.77 +                fail("Error reading %s: %s", file, e.getMessage());
  212.78 +            }
  212.79 +        }
  212.80 +
  212.81 +        // check if debugging is enabled
  212.82 +        PrintStream out = null;
  212.83 +        String logfile = AccessController.doPrivileged(
  212.84 +            new GetPropertyAction("com.sun.sdp.debug"));
  212.85 +        if (logfile != null) {
  212.86 +            out = System.out;
  212.87 +            if (logfile.length() > 0) {
  212.88 +                try {
  212.89 +                    out = new PrintStream(logfile);
  212.90 +                } catch (IOException ignore) { }
  212.91 +            }
  212.92 +        }
  212.93 +
  212.94 +        this.enabled = !list.isEmpty();
  212.95 +        this.rules = list;
  212.96 +        this.log = out;
  212.97 +    }
  212.98 +
  212.99 +    // supported actions
 212.100 +    private static enum Action {
 212.101 +        BIND,
 212.102 +        CONNECT;
 212.103 +    }
 212.104 +
 212.105 +    // a rule for matching a bind or connect request
 212.106 +    private static interface Rule {
 212.107 +        boolean match(Action action, InetAddress address, int port);
 212.108 +    }
 212.109 +
 212.110 +    // rule to match port[-end]
 212.111 +    private static class PortRangeRule implements Rule {
 212.112 +        private final Action action;
 212.113 +        private final int portStart;
 212.114 +        private final int portEnd;
 212.115 +        PortRangeRule(Action action, int portStart, int portEnd) {
 212.116 +            this.action = action;
 212.117 +            this.portStart = portStart;
 212.118 +            this.portEnd = portEnd;
 212.119 +        }
 212.120 +        Action action() {
 212.121 +            return action;
 212.122 +        }
 212.123 +        @Override
 212.124 +        public boolean match(Action action, InetAddress address, int port) {
 212.125 +            return (action == this.action &&
 212.126 +                    port >= this.portStart &&
 212.127 +                    port <= this.portEnd);
 212.128 +        }
 212.129 +    }
 212.130 +
 212.131 +    // rule to match address[/prefix] port[-end]
 212.132 +    private static class AddressPortRangeRule extends PortRangeRule {
 212.133 +        private final byte[] addressAsBytes;
 212.134 +        private final int prefixByteCount;
 212.135 +        private final byte mask;
 212.136 +        AddressPortRangeRule(Action action, InetAddress address,
 212.137 +                             int prefix, int port, int end)
 212.138 +        {
 212.139 +            super(action, port, end);
 212.140 +            this.addressAsBytes = address.getAddress();
 212.141 +            this.prefixByteCount = prefix >> 3;
 212.142 +            this.mask = (byte)(0xff << (8 - (prefix % 8)));
 212.143 +        }
 212.144 +        @Override
 212.145 +        public boolean match(Action action, InetAddress address, int port) {
 212.146 +            if (action != action())
 212.147 +                return false;
 212.148 +            byte[] candidate = address.getAddress();
 212.149 +            // same address type?
 212.150 +            if (candidate.length != addressAsBytes.length)
 212.151 +                return false;
 212.152 +            // check bytes
 212.153 +            for (int i=0; i<prefixByteCount; i++) {
 212.154 +                if (candidate[i] != addressAsBytes[i])
 212.155 +                    return false;
 212.156 +            }
 212.157 +            // check remaining bits
 212.158 +            if ((prefixByteCount < addressAsBytes.length) &&
 212.159 +                ((candidate[prefixByteCount] & mask) !=
 212.160 +                 (addressAsBytes[prefixByteCount] & mask)))
 212.161 +                    return false;
 212.162 +            return super.match(action, address, port);
 212.163 +        }
 212.164 +    }
 212.165 +
 212.166 +    // parses port:[-end]
 212.167 +    private static int[] parsePortRange(String s) {
 212.168 +        int pos = s.indexOf('-');
 212.169 +        try {
 212.170 +            int[] result = new int[2];
 212.171 +            if (pos < 0) {
 212.172 +                boolean all = s.equals("*");
 212.173 +                result[0] = all ? 0 : Integer.parseInt(s);
 212.174 +                result[1] = all ? MAX_PORT : result[0];
 212.175 +            } else {
 212.176 +                String low = s.substring(0, pos);
 212.177 +                if (low.length() == 0) low = "*";
 212.178 +                String high = s.substring(pos+1);
 212.179 +                if (high.length() == 0) high = "*";
 212.180 +                result[0] = low.equals("*") ? 0 : Integer.parseInt(low);
 212.181 +                result[1] = high.equals("*") ? MAX_PORT : Integer.parseInt(high);
 212.182 +            }
 212.183 +            return result;
 212.184 +        } catch (NumberFormatException e) {
 212.185 +            return new int[0];
 212.186 +        }
 212.187 +    }
 212.188 +
 212.189 +    private static void fail(String msg, Object... args) {
 212.190 +        Formatter f = new Formatter();
 212.191 +        f.format(msg, args);
 212.192 +        throw new RuntimeException(f.out().toString());
 212.193 +    }
 212.194 +
 212.195 +    // loads rules from the given file
 212.196 +    // Each non-blank/non-comment line must have the format:
 212.197 +    // ("bind" | "connect") 1*LWSP-char (hostname | ipaddress["/" prefix])
 212.198 +    //     1*LWSP-char ("*" | port) [ "-" ("*" | port) ]
 212.199 +    private static List<Rule> loadRulesFromFile(String file)
 212.200 +        throws IOException
 212.201 +    {
 212.202 +        Scanner scanner = new Scanner(new File(file));
 212.203 +        try {
 212.204 +            List<Rule> result = new ArrayList<Rule>();
 212.205 +            while (scanner.hasNextLine()) {
 212.206 +                String line = scanner.nextLine().trim();
 212.207 +
 212.208 +                // skip blank lines and comments
 212.209 +                if (line.length() == 0 || line.charAt(0) == '#')
 212.210 +                    continue;
 212.211 +
 212.212 +                // must have 3 fields
 212.213 +                String[] s = line.split("\\s+");
 212.214 +                if (s.length != 3) {
 212.215 +                    fail("Malformed line '%s'", line);
 212.216 +                    continue;
 212.217 +                }
 212.218 +
 212.219 +                // first field is the action ("bind" or "connect")
 212.220 +                Action action = null;
 212.221 +                for (Action a: Action.values()) {
 212.222 +                    if (s[0].equalsIgnoreCase(a.name())) {
 212.223 +                        action = a;
 212.224 +                        break;
 212.225 +                    }
 212.226 +                }
 212.227 +                if (action == null) {
 212.228 +                    fail("Action '%s' not recognized", s[0]);
 212.229 +                    continue;
 212.230 +                }
 212.231 +
 212.232 +                // * port[-end]
 212.233 +                int[] ports = parsePortRange(s[2]);
 212.234 +                if (ports.length == 0) {
 212.235 +                    fail("Malformed port range '%s'", s[2]);
 212.236 +                    continue;
 212.237 +                }
 212.238 +
 212.239 +                // match all addresses
 212.240 +                if (s[1].equals("*")) {
 212.241 +                    result.add(new PortRangeRule(action, ports[0], ports[1]));
 212.242 +                    continue;
 212.243 +                }
 212.244 +
 212.245 +                // hostname | ipaddress[/prefix]
 212.246 +                int pos = s[1].indexOf('/');
 212.247 +                try {
 212.248 +                    if (pos < 0) {
 212.249 +                        // hostname or ipaddress (no prefix)
 212.250 +                        InetAddress[] addresses = InetAddress.getAllByName(s[1]);
 212.251 +                        for (InetAddress address: addresses) {
 212.252 +                            int prefix =
 212.253 +                                (address instanceof Inet4Address) ? 32 : 128;
 212.254 +                            result.add(new AddressPortRangeRule(action, address,
 212.255 +                                prefix, ports[0], ports[1]));
 212.256 +                        }
 212.257 +                    } else {
 212.258 +                        // ipaddress/prefix
 212.259 +                        InetAddress address = InetAddress
 212.260 +                            .getByName(s[1].substring(0, pos));
 212.261 +                        int prefix = -1;
 212.262 +                        try {
 212.263 +                            prefix = Integer.parseInt(s[1].substring(pos+1));
 212.264 +                            if (address instanceof Inet4Address) {
 212.265 +                                // must be 1-31
 212.266 +                                if (prefix < 0 || prefix > 32) prefix = -1;
 212.267 +                            } else {
 212.268 +                                // must be 1-128
 212.269 +                                if (prefix < 0 || prefix > 128) prefix = -1;
 212.270 +                            }
 212.271 +                        } catch (NumberFormatException e) {
 212.272 +                        }
 212.273 +
 212.274 +                        if (prefix > 0) {
 212.275 +                            result.add(new AddressPortRangeRule(action,
 212.276 +                                        address, prefix, ports[0], ports[1]));
 212.277 +                        } else {
 212.278 +                            fail("Malformed prefix '%s'", s[1]);
 212.279 +                            continue;
 212.280 +                        }
 212.281 +                    }
 212.282 +                } catch (UnknownHostException uhe) {
 212.283 +                    fail("Unknown host or malformed IP address '%s'", s[1]);
 212.284 +                    continue;
 212.285 +                }
 212.286 +            }
 212.287 +            return result;
 212.288 +        } finally {
 212.289 +            scanner.close();
 212.290 +        }
 212.291 +    }
 212.292 +
 212.293 +    // converts unbound TCP socket to a SDP socket if it matches the rules
 212.294 +    private void convertTcpToSdpIfMatch(FileDescriptor fdObj,
 212.295 +                                               Action action,
 212.296 +                                               InetAddress address,
 212.297 +                                               int port)
 212.298 +        throws IOException
 212.299 +    {
 212.300 +        boolean matched = false;
 212.301 +        for (Rule rule: rules) {
 212.302 +            if (rule.match(action, address, port)) {
 212.303 +                SdpSupport.convertSocket(fdObj);
 212.304 +                matched = true;
 212.305 +                break;
 212.306 +            }
 212.307 +        }
 212.308 +        if (log != null) {
 212.309 +            String addr = (address instanceof Inet4Address) ?
 212.310 +                address.getHostAddress() : "[" + address.getHostAddress() + "]";
 212.311 +            if (matched) {
 212.312 +                log.format("%s to %s:%d (socket converted to SDP protocol)\n", action, addr, port);
 212.313 +            } else {
 212.314 +                log.format("%s to %s:%d (no match)\n", action, addr, port);
 212.315 +            }
 212.316 +        }
 212.317 +    }
 212.318 +
 212.319 +    @Override
 212.320 +    public void implBeforeTcpBind(FileDescriptor fdObj,
 212.321 +                              InetAddress address,
 212.322 +                              int port)
 212.323 +        throws IOException
 212.324 +    {
 212.325 +        if (enabled)
 212.326 +            convertTcpToSdpIfMatch(fdObj, Action.BIND, address, port);
 212.327 +    }
 212.328 +
 212.329 +    @Override
 212.330 +    public void implBeforeTcpConnect(FileDescriptor fdObj,
 212.331 +                                InetAddress address,
 212.332 +                                int port)
 212.333 +        throws IOException
 212.334 +    {
 212.335 +        if (enabled)
 212.336 +            convertTcpToSdpIfMatch(fdObj, Action.CONNECT, address, port);
 212.337 +    }
 212.338 +}
   213.1 --- a/src/solaris/classes/sun/net/spi/SdpProvider.java	Thu Sep 23 17:33:40 2010 -0700
   213.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   213.3 @@ -1,339 +0,0 @@
   213.4 -/*
   213.5 - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   213.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   213.7 - *
   213.8 - * This code is free software; you can redistribute it and/or modify it
   213.9 - * under the terms of the GNU General Public License version 2 only, as
  213.10 - * published by the Free Software Foundation.  Oracle designates this
  213.11 - * particular file as subject to the "Classpath" exception as provided
  213.12 - * by Oracle in the LICENSE file that accompanied this code.
  213.13 - *
  213.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  213.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  213.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  213.17 - * version 2 for more details (a copy is included in the LICENSE file that
  213.18 - * accompanied this code).
  213.19 - *
  213.20 - * You should have received a copy of the GNU General Public License version
  213.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  213.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  213.23 - *
  213.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  213.25 - * or visit www.oracle.com if you need additional information or have any
  213.26 - * questions.
  213.27 - */
  213.28 -
  213.29 -package sun.net.spi;
  213.30 -
  213.31 -import sun.net.NetHooks;
  213.32 -import java.net.InetAddress;
  213.33 -import java.net.Inet4Address;
  213.34 -import java.net.UnknownHostException;
  213.35 -import java.util.*;
  213.36 -import java.io.File;
  213.37 -import java.io.FileDescriptor;
  213.38 -import java.io.IOException;
  213.39 -import java.io.PrintStream;
  213.40 -
  213.41 -import sun.misc.SharedSecrets;
  213.42 -import sun.misc.JavaIOFileDescriptorAccess;
  213.43 -
  213.44 -/**
  213.45 - * A NetHooks provider that converts sockets from the TCP to SDP protocol prior
  213.46 - * to binding or connecting.
  213.47 - */
  213.48 -
  213.49 -public class SdpProvider extends NetHooks.Provider {
  213.50 -    private static final JavaIOFileDescriptorAccess fdAccess =
  213.51 -        SharedSecrets.getJavaIOFileDescriptorAccess();
  213.52 -
  213.53 -    // maximum port
  213.54 -    private static final int MAX_PORT = 65535;
  213.55 -
  213.56 -    // indicates if SDP is enabled and the rules for when the protocol is used
  213.57 -    private final boolean enabled;
  213.58 -    private final List<Rule> rules;
  213.59 -
  213.60 -    // logging for debug purposes
  213.61 -    private PrintStream log;
  213.62 -
  213.63 -    public SdpProvider() {
  213.64 -        // if this property is not defined then there is nothing to do.
  213.65 -        String file = System.getProperty("com.sun.sdp.conf");
  213.66 -        if (file == null) {
  213.67 -            this.enabled = false;
  213.68 -            this.rules = null;
  213.69 -            return;
  213.70 -        }
  213.71 -
  213.72 -        // load configuration file
  213.73 -        List<Rule> list = null;
  213.74 -        if (file != null) {
  213.75 -            try {
  213.76 -                list = loadRulesFromFile(file);
  213.77 -            } catch (IOException e) {
  213.78 -                fail("Error reading %s: %s", file, e.getMessage());
  213.79 -            }
  213.80 -        }
  213.81 -
  213.82 -        // check if debugging is enabled
  213.83 -        PrintStream out = null;
  213.84 -        String logfile = System.getProperty("com.sun.sdp.debug");
  213.85 -        if (logfile != null) {
  213.86 -            out = System.out;
  213.87 -            if (logfile.length() > 0) {
  213.88 -                try {
  213.89 -                    out = new PrintStream(logfile);
  213.90 -                } catch (IOException ignore) { }
  213.91 -            }
  213.92 -        }
  213.93 -
  213.94 -        this.enabled = !list.isEmpty();
  213.95 -        this.rules = list;
  213.96 -        this.log = out;
  213.97 -    }
  213.98 -
  213.99 -    // supported actions
 213.100 -    private static enum Action {
 213.101 -        BIND,
 213.102 -        CONNECT;
 213.103 -    }
 213.104 -
 213.105 -    // a rule for matching a bind or connect request
 213.106 -    private static interface Rule {
 213.107 -        boolean match(Action action, InetAddress address, int port);
 213.108 -    }
 213.109 -
 213.110 -    // rule to match port[-end]
 213.111 -    private static class PortRangeRule implements Rule {
 213.112 -        private final Action action;
 213.113 -        private final int portStart;
 213.114 -        private final int portEnd;
 213.115 -        PortRangeRule(Action action, int portStart, int portEnd) {
 213.116 -            this.action = action;
 213.117 -            this.portStart = portStart;
 213.118 -            this.portEnd = portEnd;
 213.119 -        }
 213.120 -        Action action() {
 213.121 -            return action;
 213.122 -        }
 213.123 -        @Override
 213.124 -        public boolean match(Action action, InetAddress address, int port) {
 213.125 -            return (action == this.action &&
 213.126 -                    port >= this.portStart &&
 213.127 -                    port <= this.portEnd);
 213.128 -        }
 213.129 -    }
 213.130 -
 213.131 -    // rule to match address[/prefix] port[-end]
 213.132 -    private static class AddressPortRangeRule extends PortRangeRule {
 213.133 -        private final byte[] addressAsBytes;
 213.134 -        private final int prefixByteCount;
 213.135 -        private final byte mask;
 213.136 -        AddressPortRangeRule(Action action, InetAddress address,
 213.137 -                             int prefix, int port, int end)
 213.138 -        {
 213.139 -            super(action, port, end);
 213.140 -            this.addressAsBytes = address.getAddress();
 213.141 -            this.prefixByteCount = prefix >> 3;
 213.142 -            this.mask = (byte)(0xff << (8 - (prefix % 8)));
 213.143 -        }
 213.144 -        @Override
 213.145 -        public boolean match(Action action, InetAddress address, int port) {
 213.146 -            if (action != action())
 213.147 -                return false;
 213.148 -            byte[] candidate = address.getAddress();
 213.149 -            // same address type?
 213.150 -            if (candidate.length != addressAsBytes.length)
 213.151 -                return false;
 213.152 -            // check bytes
 213.153 -            for (int i=0; i<prefixByteCount; i++) {
 213.154 -                if (candidate[i] != addressAsBytes[i])
 213.155 -                    return false;
 213.156 -            }
 213.157 -            // check remaining bits
 213.158 -            if ((prefixByteCount < addressAsBytes.length) &&
 213.159 -                ((candidate[prefixByteCount] & mask) !=
 213.160 -                 (addressAsBytes[prefixByteCount] & mask)))
 213.161 -                    return false;
 213.162 -            return super.match(action, address, port);
 213.163 -        }
 213.164 -    }
 213.165 -
 213.166 -    // parses port:[-end]
 213.167 -    private static int[] parsePortRange(String s) {
 213.168 -        int pos = s.indexOf('-');
 213.169 -        try {
 213.170 -            int[] result = new int[2];
 213.171 -            if (pos < 0) {
 213.172 -                boolean all = s.equals("*");
 213.173 -                result[0] = all ? 0 : Integer.parseInt(s);
 213.174 -                result[1] = all ? MAX_PORT : result[0];
 213.175 -            } else {
 213.176 -                String low = s.substring(0, pos);
 213.177 -                if (low.length() == 0) low = "*";
 213.178 -                String high = s.substring(pos+1);
 213.179 -                if (high.length() == 0) high = "*";
 213.180 -                result[0] = low.equals("*") ? 0 : Integer.parseInt(low);
 213.181 -                result[1] = high.equals("*") ? MAX_PORT : Integer.parseInt(high);
 213.182 -            }
 213.183 -            return result;
 213.184 -        } catch (NumberFormatException e) {
 213.185 -            return new int[0];
 213.186 -        }
 213.187 -    }
 213.188 -
 213.189 -    private static void fail(String msg, Object... args) {
 213.190 -        Formatter f = new Formatter();
 213.191 -        f.format(msg, args);
 213.192 -        throw new RuntimeException(f.out().toString());
 213.193 -    }
 213.194 -
 213.195 -    // loads rules from the given file
 213.196 -    // Each non-blank/non-comment line must have the format:
 213.197 -    // ("bind" | "connect") 1*LWSP-char (hostname | ipaddress["/" prefix])
 213.198 -    //     1*LWSP-char ("*" | port) [ "-" ("*" | port) ]
 213.199 -    private static List<Rule> loadRulesFromFile(String file)
 213.200 -        throws IOException
 213.201 -    {
 213.202 -        Scanner scanner = new Scanner(new File(file));
 213.203 -        try {
 213.204 -            List<Rule> result = new ArrayList<Rule>();
 213.205 -            while (scanner.hasNextLine()) {
 213.206 -                String line = scanner.nextLine().trim();
 213.207 -
 213.208 -                // skip blank lines and comments
 213.209 -                if (line.length() == 0 || line.charAt(0) == '#')
 213.210 -                    continue;
 213.211 -
 213.212 -                // must have 3 fields
 213.213 -                String[] s = line.split("\\s+");
 213.214 -                if (s.length != 3) {
 213.215 -                    fail("Malformed line '%s'", line);
 213.216 -                    continue;
 213.217 -                }
 213.218 -
 213.219 -                // first field is the action ("bind" or "connect")
 213.220 -                Action action = null;
 213.221 -                for (Action a: Action.values()) {
 213.222 -                    if (s[0].equalsIgnoreCase(a.name())) {
 213.223 -                        action = a;
 213.224 -                        break;
 213.225 -                    }
 213.226 -                }
 213.227 -                if (action == null) {
 213.228 -                    fail("Action '%s' not recognized", s[0]);
 213.229 -                    continue;
 213.230 -                }
 213.231 -
 213.232 -                // * port[-end]
 213.233 -                int[] ports = parsePortRange(s[2]);
 213.234 -                if (ports.length == 0) {
 213.235 -                    fail("Malformed port range '%s'", s[2]);
 213.236 -                    continue;
 213.237 -                }
 213.238 -
 213.239 -                // match all addresses
 213.240 -                if (s[1].equals("*")) {
 213.241 -                    result.add(new PortRangeRule(action, ports[0], ports[1]));
 213.242 -                    continue;
 213.243 -                }
 213.244 -
 213.245 -                // hostname | ipaddress[/prefix]
 213.246 -                int pos = s[1].indexOf('/');
 213.247 -                try {
 213.248 -                    if (pos < 0) {
 213.249 -                        // hostname or ipaddress (no prefix)
 213.250 -                        InetAddress[] addresses = InetAddress.getAllByName(s[1]);
 213.251 -                        for (InetAddress address: addresses) {
 213.252 -                            int prefix =
 213.253 -                                (address instanceof Inet4Address) ? 32 : 128;
 213.254 -                            result.add(new AddressPortRangeRule(action, address,
 213.255 -                                prefix, ports[0], ports[1]));
 213.256 -                        }
 213.257 -                    } else {
 213.258 -                        // ipaddress/prefix
 213.259 -                        InetAddress address = InetAddress
 213.260 -                            .getByName(s[1].substring(0, pos));
 213.261 -                        int prefix = -1;
 213.262 -                        try {
 213.263 -                            prefix = Integer.parseInt(s[1].substring(pos+1));
 213.264 -                            if (address instanceof Inet4Address) {
 213.265 -                                // must be 1-31
 213.266 -                                if (prefix < 0 || prefix > 32) prefix = -1;
 213.267 -                            } else {
 213.268 -                                // must be 1-128
 213.269 -                                if (prefix < 0 || prefix > 128) prefix = -1;
 213.270 -                            }
 213.271 -                        } catch (NumberFormatException e) {
 213.272 -                        }
 213.273 -
 213.274 -                        if (prefix > 0) {
 213.275 -                            result.add(new AddressPortRangeRule(action,
 213.276 -                                        address, prefix, ports[0], ports[1]));
 213.277 -                        } else {
 213.278 -                            fail("Malformed prefix '%s'", s[1]);
 213.279 -                            continue;
 213.280 -                        }
 213.281 -                    }
 213.282 -                } catch (UnknownHostException uhe) {
 213.283 -                    fail("Unknown host or malformed IP address '%s'", s[1]);
 213.284 -                    continue;
 213.285 -                }
 213.286 -            }
 213.287 -            return result;
 213.288 -        } finally {
 213.289 -            scanner.close();
 213.290 -        }
 213.291 -    }
 213.292 -
 213.293 -    // converts unbound TCP socket to a SDP socket if it matches the rules
 213.294 -    private void convertTcpToSdpIfMatch(FileDescriptor fdObj,
 213.295 -                                               Action action,
 213.296 -                                               InetAddress address,
 213.297 -                                               int port)
 213.298 -        throws IOException
 213.299 -    {
 213.300 -        boolean matched = false;
 213.301 -        for (Rule rule: rules) {
 213.302 -            if (rule.match(action, address, port)) {
 213.303 -                int fd = fdAccess.get(fdObj);
 213.304 -                convert(fd);
 213.305 -                matched = true;
 213.306 -                break;
 213.307 -            }
 213.308 -        }
 213.309 -        if (log != null) {
 213.310 -            String addr = (address instanceof Inet4Address) ?
 213.311 -                address.getHostAddress() : "[" + address.getHostAddress() + "]";
 213.312 -            if (matched) {
 213.313 -                log.format("%s to %s:%d (socket converted to SDP protocol)\n", action, addr, port);
 213.314 -            } else {
 213.315 -                log.format("%s to %s:%d (no match)\n", action, addr, port);
 213.316 -            }
 213.317 -        }
 213.318 -    }
 213.319 -
 213.320 -    @Override
 213.321 -    public void implBeforeTcpBind(FileDescriptor fdObj,
 213.322 -                              InetAddress address,
 213.323 -                              int port)
 213.324 -        throws IOException
 213.325 -    {
 213.326 -        if (enabled)
 213.327 -            convertTcpToSdpIfMatch(fdObj, Action.BIND, address, port);
 213.328 -    }
 213.329 -
 213.330 -    @Override
 213.331 -    public void implBeforeTcpConnect(FileDescriptor fdObj,
 213.332 -                                InetAddress address,
 213.333 -                                int port)
 213.334 -        throws IOException
 213.335 -    {
 213.336 -        if (enabled)
 213.337 -            convertTcpToSdpIfMatch(fdObj, Action.CONNECT, address, port);
 213.338 -    }
 213.339 -
 213.340 -    // -- native methods --
 213.341 -    private static native void convert(int fd) throws IOException;
 213.342 -}
   214.1 --- a/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java	Thu Sep 23 17:33:40 2010 -0700
   214.2 +++ b/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java	Fri Sep 24 16:41:32 2010 -0700
   214.3 @@ -1,5 +1,5 @@
   214.4  /*
   214.5 - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
   214.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   214.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   214.8   *
   214.9   * This code is free software; you can redistribute it and/or modify it
  214.10 @@ -25,20 +25,14 @@
  214.11  
  214.12  package sun.net.www.protocol.http.ntlm;
  214.13  
  214.14 +import com.sun.security.ntlm.Client;
  214.15 +import com.sun.security.ntlm.NTLMException;
  214.16  import java.io.IOException;
  214.17 -import java.io.UnsupportedEncodingException;
  214.18  import java.net.InetAddress;
  214.19  import java.net.PasswordAuthentication;
  214.20  import java.net.UnknownHostException;
  214.21  import java.net.URL;
  214.22  import java.security.GeneralSecurityException;
  214.23 -import java.security.MessageDigest;
  214.24 -import java.security.NoSuchAlgorithmException;
  214.25 -import javax.crypto.Cipher;
  214.26 -import javax.crypto.NoSuchPaddingException;
  214.27 -import javax.crypto.SecretKey;
  214.28 -import javax.crypto.SecretKeyFactory;
  214.29 -import javax.crypto.spec.DESKeySpec;
  214.30  
  214.31  import sun.net.www.HeaderParser;
  214.32  import sun.net.www.protocol.http.AuthenticationInfo;
  214.33 @@ -72,14 +66,8 @@
  214.34   */
  214.35  
  214.36  public class NTLMAuthentication extends AuthenticationInfo {
  214.37 -    private static final long serialVersionUID = -2403849171106437142L;
  214.38 +    private static final long serialVersionUID = 170L;
  214.39  
  214.40 -    private byte[] type1;
  214.41 -    private byte[] type3;
  214.42 -
  214.43 -    private SecretKeyFactory fac;
  214.44 -    private Cipher cipher;
  214.45 -    private MessageDigest md4;
  214.46      private String hostname;
  214.47      private static String defaultDomain; /* Domain to use if not specified by user */
  214.48  
  214.49 @@ -94,53 +82,28 @@
  214.50      }
  214.51  
  214.52      private void init0() {
  214.53 -        type1 = new byte[256];
  214.54 -        type3 = new byte[256];
  214.55 -        System.arraycopy (new byte[] {'N','T','L','M','S','S','P',0,1}, 0, type1, 0, 9);
  214.56 -        type1[12] = (byte) 3;
  214.57 -        type1[13] = (byte) 0xb2;
  214.58 -        type1[28] = (byte) 0x20;
  214.59 -        System.arraycopy (new byte[] {'N','T','L','M','S','S','P',0,3}, 0, type3, 0, 9);
  214.60 -        type3[12] = (byte) 0x18;
  214.61 -        type3[14] = (byte) 0x18;
  214.62 -        type3[20] = (byte) 0x18;
  214.63 -        type3[22] = (byte) 0x18;
  214.64 -        type3[32] = (byte) 0x40;
  214.65 -        type3[60] = (byte) 1;
  214.66 -        type3[61] = (byte) 0x82;
  214.67  
  214.68 -        try {
  214.69 -            hostname = java.security.AccessController.doPrivileged(
  214.70 -                new java.security.PrivilegedAction<String>() {
  214.71 -                public String run() {
  214.72 -                    String localhost;
  214.73 -                    try {
  214.74 -                        localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
  214.75 -                    } catch (UnknownHostException e) {
  214.76 -                         localhost = "localhost";
  214.77 -                    }
  214.78 -                    return localhost;
  214.79 +        hostname = java.security.AccessController.doPrivileged(
  214.80 +            new java.security.PrivilegedAction<String>() {
  214.81 +            public String run() {
  214.82 +                String localhost;
  214.83 +                try {
  214.84 +                    localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
  214.85 +                } catch (UnknownHostException e) {
  214.86 +                     localhost = "localhost";
  214.87                  }
  214.88 -            });
  214.89 -            int x = hostname.indexOf ('.');
  214.90 -            if (x != -1) {
  214.91 -                hostname = hostname.substring (0, x);
  214.92 +                return localhost;
  214.93              }
  214.94 -            fac = SecretKeyFactory.getInstance ("DES");
  214.95 -            cipher = Cipher.getInstance ("DES/ECB/NoPadding");
  214.96 -            md4 = sun.security.provider.MD4.getInstance();
  214.97 -        } catch (NoSuchPaddingException e) {
  214.98 -            assert false;
  214.99 -        } catch (NoSuchAlgorithmException e) {
 214.100 -            assert false;
 214.101 +        });
 214.102 +        int x = hostname.indexOf ('.');
 214.103 +        if (x != -1) {
 214.104 +            hostname = hostname.substring (0, x);
 214.105          }
 214.106      };
 214.107  
 214.108      PasswordAuthentication pw;
 214.109 -    String username;
 214.110 -    String ntdomain;
 214.111 -    String password;
 214.112  
 214.113 +    Client client;
 214.114      /**
 214.115       * Create a NTLMAuthentication:
 214.116       * Username may be specified as domain<BACKSLASH>username in the application Authenticator.
 214.117 @@ -156,6 +119,9 @@
 214.118      }
 214.119  
 214.120      private void init (PasswordAuthentication pw) {
 214.121 +        String username;
 214.122 +        String ntdomain;
 214.123 +        char[] password;
 214.124          this.pw = pw;
 214.125          String s = pw.getUserName();
 214.126          int i = s.indexOf ('\\');
 214.127 @@ -166,8 +132,19 @@
 214.128              ntdomain = s.substring (0, i).toUpperCase();
 214.129              username = s.substring (i+1);
 214.130          }
 214.131 -        password = new String (pw.getPassword());
 214.132 +        password = pw.getPassword();
 214.133          init0();
 214.134 +        try {
 214.135 +            client = new Client(System.getProperty("ntlm.version"), hostname,
 214.136 +                    username, ntdomain, password);
 214.137 +        } catch (NTLMException ne) {
 214.138 +            try {
 214.139 +                client = new Client(null, hostname, username, ntdomain, password);
 214.140 +            } catch (NTLMException ne2) {
 214.141 +                // Will never happen
 214.142 +                throw new AssertionError("Really?");
 214.143 +            }
 214.144 +        }
 214.145      }
 214.146  
 214.147     /**
 214.148 @@ -240,181 +217,26 @@
 214.149          }
 214.150      }
 214.151  
 214.152 -    private void copybytes (byte[] dest, int destpos, String src, String enc) {
 214.153 -        try {
 214.154 -            byte[] x = src.getBytes(enc);
 214.155 -            System.arraycopy (x, 0, dest, destpos, x.length);
 214.156 -        } catch (UnsupportedEncodingException e) {
 214.157 -            assert false;
 214.158 -        }
 214.159 -    }
 214.160 -
 214.161      private String buildType1Msg () {
 214.162 -        int dlen = ntdomain.length();
 214.163 -        type1[16]= (byte) (dlen % 256);
 214.164 -        type1[17]= (byte) (dlen / 256);
 214.165 -        type1[18] = type1[16];
 214.166 -        type1[19] = type1[17];
 214.167 -
 214.168 -        int hlen = hostname.length();
 214.169 -        type1[24]= (byte) (hlen % 256);
 214.170 -        type1[25]= (byte) (hlen / 256);
 214.171 -        type1[26] = type1[24];
 214.172 -        type1[27] = type1[25];
 214.173 -
 214.174 -        copybytes (type1, 32, hostname, "ISO8859_1");
 214.175 -        copybytes (type1, hlen+32, ntdomain, "ISO8859_1");
 214.176 -        type1[20] = (byte) ((hlen+32) % 256);
 214.177 -        type1[21] = (byte) ((hlen+32) / 256);
 214.178 -
 214.179 -        byte[] msg = new byte [32 + hlen + dlen];
 214.180 -        System.arraycopy (type1, 0, msg, 0, 32 + hlen + dlen);
 214.181 +        byte[] msg = client.type1();
 214.182          String result = "NTLM " + (new B64Encoder()).encode (msg);
 214.183          return result;
 214.184      }
 214.185  
 214.186 -
 214.187 -    /* Convert a 7 byte array to an 8 byte array (for a des key with parity)
 214.188 -     * input starts at offset off
 214.189 -     */
 214.190 -    private byte[] makeDesKey (byte[] input, int off) {
 214.191 -        int[] in = new int [input.length];
 214.192 -        for (int i=0; i<in.length; i++ ) {
 214.193 -            in[i] = input[i]<0 ? input[i]+256: input[i];
 214.194 -        }
 214.195 -        byte[] out = new byte[8];
 214.196 -        out[0] = (byte)in[off+0];
 214.197 -        out[1] = (byte)(((in[off+0] << 7) & 0xFF) | (in[off+1] >> 1));
 214.198 -        out[2] = (byte)(((in[off+1] << 6) & 0xFF) | (in[off+2] >> 2));
 214.199 -        out[3] = (byte)(((in[off+2] << 5) & 0xFF) | (in[off+3] >> 3));
 214.200 -        out[4] = (byte)(((in[off+3] << 4) & 0xFF) | (in[off+4] >> 4));
 214.201 -        out[5] = (byte)(((in[off+4] << 3) & 0xFF) | (in[off+5] >> 5));
 214.202 -        out[6] = (byte)(((in[off+5] << 2) & 0xFF) | (in[off+6] >> 6));
 214.203 -        out[7] = (byte)((in[off+6] << 1) & 0xFF);
 214.204 -        return out;
 214.205 -    }
 214.206 -
 214.207 -    private byte[] calcLMHash () throws GeneralSecurityException {
 214.208 -        byte[] magic = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
 214.209 -        byte[] pwb = password.toUpperCase ().getBytes();
 214.210 -        byte[] pwb1 = new byte [14];
 214.211 -        int len = password.length();
 214.212 -        if (len > 14)
 214.213 -            len = 14;
 214.214 -        System.arraycopy (pwb, 0, pwb1, 0, len); /* Zero padded */
 214.215 -
 214.216 -        DESKeySpec dks1 = new DESKeySpec (makeDesKey (pwb1, 0));
 214.217 -        DESKeySpec dks2 = new DESKeySpec (makeDesKey (pwb1, 7));
 214.218 -
 214.219 -        SecretKey key1 = fac.generateSecret (dks1);
 214.220 -        SecretKey key2 = fac.generateSecret (dks2);
 214.221 -        cipher.init (Cipher.ENCRYPT_MODE, key1);
 214.222 -        byte[] out1 = cipher.doFinal (magic, 0, 8);
 214.223 -        cipher.init (Cipher.ENCRYPT_MODE, key2);
 214.224 -        byte[] out2 = cipher.doFinal (magic, 0, 8);
 214.225 -
 214.226 -        byte[] result = new byte [21];
 214.227 -        System.arraycopy (out1, 0, result, 0, 8);
 214.228 -        System.arraycopy (out2, 0, result, 8, 8);
 214.229 -        return result;
 214.230 -    }
 214.231 -
 214.232 -    private byte[] calcNTHash () throws GeneralSecurityException {
 214.233 -        byte[] pw = null;
 214.234 -        try {
 214.235 -            pw = password.getBytes ("UnicodeLittleUnmarked");
 214.236 -        } catch (UnsupportedEncodingException e) {
 214.237 -            assert false;
 214.238 -        }
 214.239 -        byte[] out = md4.digest (pw);
 214.240 -        byte[] result = new byte [21];
 214.241 -        System.arraycopy (out, 0, result, 0, 16);
 214.242 -        return result;
 214.243 -    }
 214.244 -
 214.245 -    /* key is a 21 byte array. Split it into 3 7 byte chunks,
 214.246 -     * Convert each to 8 byte DES keys, encrypt the text arg with
 214.247 -     * each key and return the three results in a sequential []
 214.248 -     */
 214.249 -    private byte[] calcResponse (byte[] key, byte[] text)
 214.250 -    throws GeneralSecurityException {
 214.251 -        assert key.length == 21;
 214.252 -        DESKeySpec dks1 = new DESKeySpec (makeDesKey (key, 0));
 214.253 -        DESKeySpec dks2 = new DESKeySpec (makeDesKey (key, 7));
 214.254 -        DESKeySpec dks3 = new DESKeySpec (makeDesKey (key, 14));
 214.255 -        SecretKey key1 = fac.generateSecret (dks1);
 214.256 -        SecretKey key2 = fac.generateSecret (dks2);
 214.257 -        SecretKey key3 = fac.generateSecret (dks3);
 214.258 -        cipher.init (Cipher.ENCRYPT_MODE, key1);
 214.259 -        byte[] out1 = cipher.doFinal (text, 0, 8);
 214.260 -        cipher.init (Cipher.ENCRYPT_MODE, key2);
 214.261 -        byte[] out2 = cipher.doFinal (text, 0, 8);
 214.262 -        cipher.init (Cipher.ENCRYPT_MODE, key3);
 214.263 -        byte[] out3 = cipher.doFinal (text, 0, 8);
 214.264 -        byte[] result = new byte [24];
 214.265 -        System.arraycopy (out1, 0, result, 0, 8);
 214.266 -        System.arraycopy (out2, 0, result, 8, 8);
 214.267 -        System.arraycopy (out3, 0, result, 16, 8);
 214.268 -        return result;
 214.269 -    }
 214.270 -
 214.271      private String buildType3Msg (String challenge) throws GeneralSecurityException,
 214.272                                                             IOException  {
 214.273          /* First decode the type2 message to get the server nonce */
 214.274          /* nonce is located at type2[24] for 8 bytes */
 214.275  
 214.276          byte[] type2 = (new sun.misc.BASE64Decoder()).decodeBuffer (challenge);
 214.277 -        byte[] nonce = new byte [8];
 214.278 -        System.arraycopy (type2, 24, nonce, 0, 8);
 214.279 -
 214.280 -        int ulen = username.length()*2;
 214.281 -        type3[36] = type3[38] = (byte) (ulen % 256);
 214.282 -        type3[37] = type3[39] = (byte) (ulen / 256);
 214.283 -        int dlen = ntdomain.length()*2;
 214.284 -        type3[28] = type3[30] = (byte) (dlen % 256);
 214.285 -        type3[29] = type3[31] = (byte) (dlen / 256);
 214.286 -        int hlen = hostname.length()*2;
 214.287 -        type3[44] = type3[46] = (byte) (hlen % 256);
 214.288 -        type3[45] = type3[47] = (byte) (hlen / 256);
 214.289 -
 214.290 -        int l = 64;
 214.291 -        copybytes (type3, l, ntdomain, "UnicodeLittleUnmarked");
 214.292 -        type3[32] = (byte) (l % 256);
 214.293 -        type3[33] = (byte) (l / 256);
 214.294 -        l += dlen;
 214.295 -        copybytes (type3, l, username, "UnicodeLittleUnmarked");
 214.296 -        type3[40] = (byte) (l % 256);
 214.297 -        type3[41] = (byte) (l / 256);
 214.298 -        l += ulen;
 214.299 -        copybytes (type3, l, hostname, "UnicodeLittleUnmarked");
 214.300 -        type3[48] = (byte) (l % 256);
 214.301 -        type3[49] = (byte) (l / 256);
 214.302 -        l += hlen;
 214.303 -
 214.304 -        byte[] lmhash = calcLMHash();
 214.305 -        byte[] lmresponse = calcResponse (lmhash, nonce);
 214.306 -        byte[] nthash = calcNTHash();
 214.307 -        byte[] ntresponse = calcResponse (nthash, nonce);
 214.308 -        System.arraycopy (lmresponse, 0, type3, l, 24);
 214.309 -        type3[16] = (byte) (l % 256);
 214.310 -        type3[17] = (byte) (l / 256);
 214.311 -        l += 24;
 214.312 -        System.arraycopy (ntresponse, 0, type3, l, 24);
 214.313 -        type3[24] = (byte) (l % 256);
 214.314 -        type3[25] = (byte) (l / 256);
 214.315 -        l += 24;
 214.316 -        type3[56] = (byte) (l % 256);
 214.317 -        type3[57] = (byte) (l / 256);
 214.318 -
 214.319 -        byte[] msg = new byte [l];
 214.320 -        System.arraycopy (type3, 0, msg, 0, l);
 214.321 +        byte[] nonce = new byte[8];
 214.322 +        new java.util.Random().nextBytes(nonce);
 214.323 +        byte[] msg = client.type3(type2, nonce);
 214.324          String result = "NTLM " + (new B64Encoder()).encode (msg);
 214.325          return result;
 214.326      }
 214.327 -
 214.328  }
 214.329  
 214.330 -
 214.331  class B64Encoder extends sun.misc.BASE64Encoder {
 214.332      /* to force it to to the entire encoding in one line */
 214.333      protected int bytesPerLine () {
   215.1 --- a/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Thu Sep 23 17:33:40 2010 -0700
   215.2 +++ b/src/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Fri Sep 24 16:41:32 2010 -0700
   215.3 @@ -65,10 +65,9 @@
   215.4       */
   215.5      DevPollSelectorImpl(SelectorProvider sp) {
   215.6          super(sp);
   215.7 -        int[] fdes = new int[2];
   215.8 -        IOUtil.initPipe(fdes, false);
   215.9 -        fd0 = fdes[0];
  215.10 -        fd1 = fdes[1];
  215.11 +        long pipeFds = IOUtil.makePipe(false);
  215.12 +        fd0 = (int) (pipeFds >>> 32);
  215.13 +        fd1 = (int) pipeFds;
  215.14          pollWrapper = new DevPollArrayWrapper();
  215.15          pollWrapper.initInterrupt(fd0, fd1);
  215.16          fdToKey = new HashMap<Integer,SelectionKeyImpl>();
  215.17 @@ -147,7 +146,7 @@
  215.18          selectedKeys = null;
  215.19  
  215.20          // Deregister channels
  215.21 -        Iterator i = keys.iterator();
  215.22 +        Iterator<SelectionKey> i = keys.iterator();
  215.23          while (i.hasNext()) {
  215.24              SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
  215.25              deregister(ski);
   216.1 --- a/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java	Thu Sep 23 17:33:40 2010 -0700
   216.2 +++ b/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java	Fri Sep 24 16:41:32 2010 -0700
   216.3 @@ -62,10 +62,9 @@
   216.4       */
   216.5      EPollSelectorImpl(SelectorProvider sp) {
   216.6          super(sp);
   216.7 -        int[] fdes = new int[2];
   216.8 -        IOUtil.initPipe(fdes, false);
   216.9 -        fd0 = fdes[0];
  216.10 -        fd1 = fdes[1];
  216.11 +        long pipeFds = IOUtil.makePipe(false);
  216.12 +        fd0 = (int) (pipeFds >>> 32);
  216.13 +        fd1 = (int) pipeFds;
  216.14          pollWrapper = new EPollArrayWrapper();
  216.15          pollWrapper.initInterrupt(fd0, fd1);
  216.16          fdToKey = new HashMap<Integer,SelectionKeyImpl>();
  216.17 @@ -144,7 +143,7 @@
  216.18          selectedKeys = null;
  216.19  
  216.20          // Deregister channels
  216.21 -        Iterator i = keys.iterator();
  216.22 +        Iterator<SelectionKey> i = keys.iterator();
  216.23          while (i.hasNext()) {
  216.24              SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
  216.25              deregister(ski);
   217.1 --- a/src/solaris/classes/sun/nio/ch/InheritedChannel.java	Thu Sep 23 17:33:40 2010 -0700
   217.2 +++ b/src/solaris/classes/sun/nio/ch/InheritedChannel.java	Fri Sep 24 16:41:32 2010 -0700
   217.3 @@ -96,7 +96,7 @@
   217.4                                           FileDescriptor fd)
   217.5              throws IOException
   217.6          {
   217.7 -            super(sp, fd);
   217.8 +            super(sp, fd, true);
   217.9          }
  217.10  
  217.11          protected void implCloseSelectableChannel() throws IOException {
   218.1 --- a/src/solaris/classes/sun/nio/ch/PipeImpl.java	Thu Sep 23 17:33:40 2010 -0700
   218.2 +++ b/src/solaris/classes/sun/nio/ch/PipeImpl.java	Fri Sep 24 16:41:32 2010 -0700
   218.3 @@ -39,13 +39,14 @@
   218.4      private final SinkChannel sink;
   218.5  
   218.6      PipeImpl(SelectorProvider sp) {
   218.7 -        int[] fdes = new int[2];
   218.8 -        IOUtil.initPipe(fdes, true);
   218.9 +        long pipeFds = IOUtil.makePipe(true);
  218.10 +        int readFd = (int) (pipeFds >>> 32);
  218.11 +        int writeFd = (int) pipeFds;
  218.12          FileDescriptor sourcefd = new FileDescriptor();
  218.13 -        IOUtil.setfdVal(sourcefd, fdes[0]);
  218.14 +        IOUtil.setfdVal(sourcefd, readFd);
  218.15          source = new SourceChannelImpl(sp, sourcefd);
  218.16          FileDescriptor sinkfd = new FileDescriptor();
  218.17 -        IOUtil.setfdVal(sinkfd, fdes[1]);
  218.18 +        IOUtil.setfdVal(sinkfd, writeFd);
  218.19          sink = new SinkChannelImpl(sp, sinkfd);
  218.20      }
  218.21  
   219.1 --- a/src/solaris/classes/sun/nio/ch/PollSelectorImpl.java	Thu Sep 23 17:33:40 2010 -0700
   219.2 +++ b/src/solaris/classes/sun/nio/ch/PollSelectorImpl.java	Fri Sep 24 16:41:32 2010 -0700
   219.3 @@ -54,10 +54,9 @@
   219.4       */
   219.5      PollSelectorImpl(SelectorProvider sp) {
   219.6          super(sp, 1, 1);
   219.7 -        int[] fdes = new int[2];
   219.8 -        IOUtil.initPipe(fdes, false);
   219.9 -        fd0 = fdes[0];
  219.10 -        fd1 = fdes[1];
  219.11 +        long pipeFds = IOUtil.makePipe(false);
  219.12 +        fd0 = (int) (pipeFds >>> 32);
  219.13 +        fd1 = (int) pipeFds;
  219.14          pollWrapper = new PollArrayWrapper(INIT_CAP);
  219.15          pollWrapper.initInterrupt(fd0, fd1);
  219.16          channelArray = new SelectionKeyImpl[INIT_CAP];
   220.1 --- a/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java	Thu Sep 23 17:33:40 2010 -0700
   220.2 +++ b/src/solaris/classes/sun/nio/fs/UnixDirectoryStream.java	Fri Sep 24 16:41:32 2010 -0700
   220.3 @@ -27,7 +27,6 @@
   220.4  
   220.5  import java.nio.file.*;
   220.6  import java.util.Iterator;
   220.7 -import java.util.ConcurrentModificationException;
   220.8  import java.util.NoSuchElementException;
   220.9  import java.util.concurrent.locks.*;
  220.10  import java.io.IOException;
  220.11 @@ -139,9 +138,6 @@
  220.12          // next entry to return
  220.13          private Path nextEntry;
  220.14  
  220.15 -        // previous entry returned by next method (needed by remove method)
  220.16 -        private Path prevEntry;
  220.17 -
  220.18          UnixDirectoryIterator(DirectoryStream<Path> stream) {
  220.19              atEof = false;
  220.20              this.stream = stream;
  220.21 @@ -168,24 +164,19 @@
  220.22                  // prevent close while reading
  220.23                  readLock().lock();
  220.24                  try {
  220.25 -                    if (isClosed)
  220.26 -                        throwAsConcurrentModificationException(new
  220.27 -                            ClosedDirectoryStreamException());
  220.28 -                    try {
  220.29 +                    if (isOpen()) {
  220.30                          nameAsBytes = readdir(dp);
  220.31 -                    } catch (UnixException x) {
  220.32 -                        try {
  220.33 -                            x.rethrowAsIOException(dir);
  220.34 -                        } catch (IOException ioe) {
  220.35 -                            throwAsConcurrentModificationException(ioe);
  220.36 -                        }
  220.37                      }
  220.38 +                } catch (UnixException x) {
  220.39 +                    IOException ioe = x.asIOException(dir);
  220.40 +                    throw new DirectoryIteratorException(ioe);
  220.41                  } finally {
  220.42                      readLock().unlock();
  220.43                  }
  220.44  
  220.45                  // EOF
  220.46                  if (nameAsBytes == null) {
  220.47 +                    atEof = true;
  220.48                      return null;
  220.49                  }
  220.50  
  220.51 @@ -198,7 +189,7 @@
  220.52                          if (filter == null || filter.accept(entry))
  220.53                              return entry;
  220.54                      } catch (IOException ioe) {
  220.55 -                        throwAsConcurrentModificationException(ioe);
  220.56 +                        throw new DirectoryIteratorException(ioe);
  220.57                      }
  220.58                  }
  220.59              }
  220.60 @@ -206,66 +197,28 @@
  220.61  
  220.62          @Override
  220.63          public synchronized boolean hasNext() {
  220.64 -            if (nextEntry == null && !atEof) {
  220.65 +            if (nextEntry == null && !atEof)
  220.66                  nextEntry = readNextEntry();
  220.67 -
  220.68 -                // at EOF?
  220.69 -                if (nextEntry == null)
  220.70 -                    atEof = true;
  220.71 -            }
  220.72              return nextEntry != null;
  220.73          }
  220.74  
  220.75          @Override
  220.76          public synchronized Path next() {
  220.77 -            if (nextEntry == null) {
  220.78 -                if (!atEof) {
  220.79 -                    nextEntry = readNextEntry();
  220.80 -                }
  220.81 -                if (nextEntry == null) {
  220.82 -                    atEof = true;
  220.83 -                    throw new NoSuchElementException();
  220.84 -                }
  220.85 +            Path result;
  220.86 +            if (nextEntry == null && !atEof) {
  220.87 +                result = readNextEntry();
  220.88 +            } else {
  220.89 +                result = nextEntry;
  220.90 +                nextEntry = null;
  220.91              }
  220.92 -            prevEntry = nextEntry;
  220.93 -            nextEntry = null;
  220.94 -            return prevEntry;
  220.95 +            if (result == null)
  220.96 +                throw new NoSuchElementException();
  220.97 +            return result;
  220.98          }
  220.99  
 220.100          @Override
 220.101          public void remove() {
 220.102 -            if (isClosed) {
 220.103 -                throwAsConcurrentModificationException(new
 220.104 -                    ClosedDirectoryStreamException());
 220.105 -            }
 220.106 -            Path entry;
 220.107 -            synchronized (this) {
 220.108 -                if (prevEntry == null)
 220.109 -                    throw new IllegalStateException("No previous entry to remove");
 220.110 -                entry = prevEntry;
 220.111 -                prevEntry = null;
 220.112 -            }
 220.113 -
 220.114 -            // use (race-free) unlinkat if available
 220.115 -            try {
 220.116 -                if (stream instanceof UnixSecureDirectoryStream) {
 220.117 -                    ((UnixSecureDirectoryStream)stream)
 220.118 -                        .implDelete(entry.getName(), false, 0);
 220.119 -                } else {
 220.120 -                    entry.delete();
 220.121 -                }
 220.122 -            } catch (IOException ioe) {
 220.123 -                throwAsConcurrentModificationException(ioe);
 220.124 -            } catch (SecurityException se) {
 220.125 -                throwAsConcurrentModificationException(se);
 220.126 -            }
 220.127 +            throw new UnsupportedOperationException();
 220.128          }
 220.129      }
 220.130 -
 220.131 -    private static void throwAsConcurrentModificationException(Throwable t) {
 220.132 -        ConcurrentModificationException cme = new ConcurrentModificationException();
 220.133 -        cme.initCause(t);
 220.134 -        throw cme;
 220.135 -    }
 220.136 -
 220.137  }
   221.1 --- a/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java	Thu Sep 23 17:33:40 2010 -0700
   221.2 +++ b/src/solaris/classes/sun/nio/fs/UnixSecureDirectoryStream.java	Fri Sep 24 16:41:32 2010 -0700
   221.3 @@ -166,7 +166,7 @@
   221.4       * Deletes file/directory in this directory. Works in a race-free manner
   221.5       * when invoked with flags.
   221.6       */
   221.7 -    void implDelete(Path obj, boolean haveFlags, int flags)
   221.8 +    private void implDelete(Path obj, boolean haveFlags, int flags)
   221.9          throws IOException
  221.10      {
  221.11          UnixPath file = getName(obj);
   222.1 --- a/src/solaris/native/java/lang/java_props_md.c	Thu Sep 23 17:33:40 2010 -0700
   222.2 +++ b/src/solaris/native/java/lang/java_props_md.c	Fri Sep 24 16:41:32 2010 -0700
   222.3 @@ -115,6 +115,174 @@
   222.4  #define P_tmpdir "/var/tmp"
   222.5  #endif
   222.6  
   222.7 +static int ParseLocale(int cat, char ** std_language, char ** std_country, char ** std_variant, char ** std_encoding) {
   222.8 +    char temp[64];
   222.9 +    char *language = NULL, *country = NULL, *variant = NULL,
  222.10 +         *encoding = NULL;
  222.11 +    char *p, encoding_variant[64];
  222.12 +    char *lc;
  222.13 +
  222.14 +    /* Query the locale set for the category */
  222.15 +    lc = setlocale(cat, NULL);
  222.16 +
  222.17 +#ifndef __linux__
  222.18 +    if (lc == NULL) {
  222.19 +        return 0;
  222.20 +    }
  222.21 +
  222.22 +    if (cat == LC_CTYPE) {
  222.23 +        /*
  222.24 +         * Workaround for Solaris bug 4201684: Xlib doesn't like @euro
  222.25 +         * locales. Since we don't depend on the libc @euro behavior,
  222.26 +         * we just remove the qualifier.
  222.27 +         * On Linux, the bug doesn't occur; on the other hand, @euro
  222.28 +         * is needed there because it's a shortcut that also determines
  222.29 +         * the encoding - without it, we wouldn't get ISO-8859-15.
  222.30 +         * Therefore, this code section is Solaris-specific.
  222.31 +         */
  222.32 +        lc = strdup(lc);    /* keep a copy, setlocale trashes original. */
  222.33 +        strcpy(temp, lc);
  222.34 +        p = strstr(temp, "@euro");
  222.35 +        if (p != NULL) {
  222.36 +            *p = '\0';
  222.37 +            setlocale(LC_ALL, temp);
  222.38 +        }
  222.39 +    }
  222.40 +#else
  222.41 +    if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
  222.42 +        lc = "en_US";
  222.43 +    }
  222.44 +#endif
  222.45 +
  222.46 +    /*
  222.47 +     * locale string format in Solaris is
  222.48 +     * <language name>_<country name>.<encoding name>@<variant name>
  222.49 +     * <country name>, <encoding name>, and <variant name> are optional.
  222.50 +     */
  222.51 +
  222.52 +    strcpy(temp, lc);
  222.53 +
  222.54 +    /* Parse the language, country, encoding, and variant from the
  222.55 +     * locale.  Any of the elements may be missing, but they must occur
  222.56 +     * in the order language_country.encoding@variant, and must be
  222.57 +     * preceded by their delimiter (except for language).
  222.58 +     *
  222.59 +     * If the locale name (without .encoding@variant, if any) matches
  222.60 +     * any of the names in the locale_aliases list, map it to the
  222.61 +     * corresponding full locale name.  Most of the entries in the
  222.62 +     * locale_aliases list are locales that include a language name but
  222.63 +     * no country name, and this facility is used to map each language
  222.64 +     * to a default country if that's possible.  It's also used to map
  222.65 +     * the Solaris locale aliases to their proper Java locale IDs.
  222.66 +     */
  222.67 +    if ((p = strchr(temp, '.')) != NULL) {
  222.68 +        strcpy(encoding_variant, p); /* Copy the leading '.' */
  222.69 +        *p = '\0';
  222.70 +    } else if ((p = strchr(temp, '@')) != NULL) {
  222.71 +         strcpy(encoding_variant, p); /* Copy the leading '@' */
  222.72 +         *p = '\0';
  222.73 +    } else {
  222.74 +        *encoding_variant = '\0';
  222.75 +    }
  222.76 +
  222.77 +    if (mapLookup(locale_aliases, temp, &p)) {
  222.78 +        strcpy(temp, p);
  222.79 +    }
  222.80 +
  222.81 +    language = temp;
  222.82 +    if ((country = strchr(temp, '_')) != NULL) {
  222.83 +        *country++ = '\0';
  222.84 +    }
  222.85 +
  222.86 +    p = encoding_variant;
  222.87 +    if ((encoding = strchr(p, '.')) != NULL) {
  222.88 +        p[encoding++ - p] = '\0';
  222.89 +        p = encoding;
  222.90 +    }
  222.91 +    if ((variant = strchr(p, '@')) != NULL) {
  222.92 +        p[variant++ - p] = '\0';
  222.93 +    }
  222.94 +
  222.95 +    /* Normalize the language name */
  222.96 +    if (std_language != NULL) {
  222.97 +        *std_language = "en";
  222.98 +        if (language != NULL) {
  222.99 +            mapLookup(language_names, language, std_language);
 222.100 +        }
 222.101 +    }
 222.102 +
 222.103 +    /* Normalize the country name */
 222.104 +    if (std_country != NULL && country != NULL) {
 222.105 +        *std_country = country;
 222.106 +        mapLookup(country_names, country, std_country);
 222.107 +    }
 222.108 +
 222.109 +    /* Normalize the variant name.  Note that we only use
 222.110 +     * variants listed in the mapping array; others are ignored. */
 222.111 +    if (std_variant != NULL && variant != NULL) {
 222.112 +        mapLookup(variant_names, variant, std_variant);
 222.113 +    }
 222.114 +
 222.115 +    /* Normalize the encoding name.  Note that we IGNORE the string
 222.116 +     * 'encoding' extracted from the locale name above.  Instead, we use the
 222.117 +     * more reliable method of calling nl_langinfo(CODESET).  This function
 222.118 +     * returns an empty string if no encoding is set for the given locale
 222.119 +     * (e.g., the C or POSIX locales); we use the default ISO 8859-1
 222.120 +     * converter for such locales.
 222.121 +     */
 222.122 +    if (std_encoding != NULL) {
 222.123 +        /* OK, not so reliable - nl_langinfo() gives wrong answers on
 222.124 +         * Euro locales, in particular. */
 222.125 +        if (strcmp(p, "ISO8859-15") == 0)
 222.126 +            p = "ISO8859-15";
 222.127 +        else
 222.128 +            p = nl_langinfo(CODESET);
 222.129 +
 222.130 +        /* Convert the bare "646" used on Solaris to a proper IANA name */
 222.131 +        if (strcmp(p, "646") == 0)
 222.132 +            p = "ISO646-US";
 222.133 +
 222.134 +        /* return same result nl_langinfo would return for en_UK,
 222.135 +         * in order to use optimizations. */
 222.136 +        *std_encoding = (*p != '\0') ? p : "ISO8859-1";
 222.137 +
 222.138 +#ifdef __linux__
 222.139 +        /*
 222.140 +         * Remap the encoding string to a different value for japanese
 222.141 +         * locales on linux so that customized converters are used instead
 222.142 +         * of the default converter for "EUC-JP". The customized converters
 222.143 +         * omit support for the JIS0212 encoding which is not supported by
 222.144 +         * the variant of "EUC-JP" encoding used on linux
 222.145 +         */
 222.146 +        if (strcmp(p, "EUC-JP") == 0) {
 222.147 +            *std_encoding = "EUC-JP-LINUX";
 222.148 +        }
 222.149 +#else
 222.150 +        if (strcmp(p,"eucJP") == 0) {
 222.151 +            /* For Solaris use customized vendor defined character
 222.152 +             * customized EUC-JP converter
 222.153 +             */
 222.154 +            *std_encoding = "eucJP-open";
 222.155 +        } else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
 222.156 +            /*
 222.157 +             * Remap the encoding string to Big5_Solaris which augments
 222.158 +             * the default converter for Solaris Big5 locales to include
 222.159 +             * seven additional ideographic characters beyond those included
 222.160 +             * in the Java "Big5" converter.
 222.161 +             */
 222.162 +            *std_encoding = "Big5_Solaris";
 222.163 +        } else if (strcmp(p, "Big5-HKSCS") == 0) {
 222.164 +            /*
 222.165 +             * Solaris uses HKSCS2001
 222.166 +             */
 222.167 +            *std_encoding = "Big5-HKSCS-2001";
 222.168 +        }
 222.169 +#endif
 222.170 +    }
 222.171 +
 222.172 +    return 1;
 222.173 +}
 222.174 +
 222.175  /* This function gets called very early, before VM_CALLS are setup.
 222.176   * Do not use any of the VM_CALLS entries!!!
 222.177   */
 222.178 @@ -185,182 +353,25 @@
 222.179      /* Determine the language, country, variant, and encoding from the host,
 222.180       * and store these in the user.language, user.country, user.variant and
 222.181       * file.encoding system properties. */
 222.182 -    {
 222.183 -        char *lc;
 222.184 -        lc = setlocale(LC_CTYPE, "");
 222.185 -#ifndef __linux__
 222.186 -        if (lc == NULL) {
 222.187 -            /*
 222.188 -             * 'lc == null' means system doesn't support user's environment
 222.189 -             * variable's locale.
 222.190 -             */
 222.191 -          setlocale(LC_ALL, "C");
 222.192 -          sprops.language = "en";
 222.193 -          sprops.encoding = "ISO8859-1";
 222.194 -          sprops.sun_jnu_encoding = sprops.encoding;
 222.195 -        } else {
 222.196 -#else
 222.197 -        if (lc == NULL || !strcmp(lc, "C") || !strcmp(lc, "POSIX")) {
 222.198 -            lc = "en_US";
 222.199 -        }
 222.200 -        {
 222.201 -#endif
 222.202 -
 222.203 -            /*
 222.204 -             * locale string format in Solaris is
 222.205 -             * <language name>_<country name>.<encoding name>@<variant name>
 222.206 -             * <country name>, <encoding name>, and <variant name> are optional.
 222.207 -             */
 222.208 -            char temp[64];
 222.209 -            char *language = NULL, *country = NULL, *variant = NULL,
 222.210 -                 *encoding = NULL;
 222.211 -            char *std_language = NULL, *std_country = NULL, *std_variant = NULL,
 222.212 -                 *std_encoding = NULL;
 222.213 -            char *p, encoding_variant[64];
 222.214 -            int i, found;
 222.215 -
 222.216 -#ifndef __linux__
 222.217 -            /*
 222.218 -             * Workaround for Solaris bug 4201684: Xlib doesn't like @euro
 222.219 -             * locales. Since we don't depend on the libc @euro behavior,
 222.220 -             * we just remove the qualifier.
 222.221 -             * On Linux, the bug doesn't occur; on the other hand, @euro
 222.222 -             * is needed there because it's a shortcut that also determines
 222.223 -             * the encoding - without it, we wouldn't get ISO-8859-15.
 222.224 -             * Therefore, this code section is Solaris-specific.
 222.225 -             */
 222.226 -            lc = strdup(lc);    /* keep a copy, setlocale trashes original. */
 222.227 -            strcpy(temp, lc);
 222.228 -            p = strstr(temp, "@euro");
 222.229 -            if (p != NULL)
 222.230 -                *p = '\0';
 222.231 -            setlocale(LC_ALL, temp);
 222.232 -#endif
 222.233 -
 222.234 -            strcpy(temp, lc);
 222.235 -
 222.236 -            /* Parse the language, country, encoding, and variant from the
 222.237 -             * locale.  Any of the elements may be missing, but they must occur
 222.238 -             * in the order language_country.encoding@variant, and must be
 222.239 -             * preceded by their delimiter (except for language).
 222.240 -             *
 222.241 -             * If the locale name (without .encoding@variant, if any) matches
 222.242 -             * any of the names in the locale_aliases list, map it to the
 222.243 -             * corresponding full locale name.  Most of the entries in the
 222.244 -             * locale_aliases list are locales that include a language name but
 222.245 -             * no country name, and this facility is used to map each language
 222.246 -             * to a default country if that's possible.  It's also used to map
 222.247 -             * the Solaris locale aliases to their proper Java locale IDs.
 222.248 -             */
 222.249 -            if ((p = strchr(temp, '.')) != NULL) {
 222.250 -                strcpy(encoding_variant, p); /* Copy the leading '.' */
 222.251 -                *p = '\0';
 222.252 -            } else if ((p = strchr(temp, '@')) != NULL) {
 222.253 -                 strcpy(encoding_variant, p); /* Copy the leading '@' */
 222.254 -                 *p = '\0';
 222.255 -            } else {
 222.256 -                *encoding_variant = '\0';
 222.257 -            }
 222.258 -
 222.259 -            if (mapLookup(locale_aliases, temp, &p)) {
 222.260 -                strcpy(temp, p);
 222.261 -            }
 222.262 -
 222.263 -            language = temp;
 222.264 -            if ((country = strchr(temp, '_')) != NULL) {
 222.265 -                *country++ = '\0';
 222.266 -            }
 222.267 -
 222.268 -            p = encoding_variant;
 222.269 -            if ((encoding = strchr(p, '.')) != NULL) {
 222.270 -                p[encoding++ - p] = '\0';
 222.271 -                p = encoding;
 222.272 -            }
 222.273 -            if ((variant = strchr(p, '@')) != NULL) {
 222.274 -                p[variant++ - p] = '\0';
 222.275 -            }
 222.276 -
 222.277 -            /* Normalize the language name */
 222.278 -            std_language = "en";
 222.279 -            if (language != NULL) {
 222.280 -                mapLookup(language_names, language, &std_language);
 222.281 -            }
 222.282 -            sprops.language = std_language;
 222.283 -
 222.284 -            /* Normalize the country name */
 222.285 -            if (country != NULL) {
 222.286 -                std_country = country;
 222.287 -                mapLookup(country_names, country, &std_country);
 222.288 -                sprops.country = strdup(std_country);
 222.289 -            }
 222.290 -
 222.291 -            /* Normalize the variant name.  Note that we only use
 222.292 -             * variants listed in the mapping array; others are ignored. */
 222.293 -            if (variant != NULL) {
 222.294 -                mapLookup(variant_names, variant, &std_variant);
 222.295 -                sprops.variant = std_variant;
 222.296 -            }
 222.297 -
 222.298 -            /* Normalize the encoding name.  Note that we IGNORE the string
 222.299 -             * 'encoding' extracted from the locale name above.  Instead, we use the
 222.300 -             * more reliable method of calling nl_langinfo(CODESET).  This function
 222.301 -             * returns an empty string if no encoding is set for the given locale
 222.302 -             * (e.g., the C or POSIX locales); we use the default ISO 8859-1
 222.303 -             * converter for such locales.
 222.304 -             */
 222.305 -
 222.306 -            /* OK, not so reliable - nl_langinfo() gives wrong answers on
 222.307 -             * Euro locales, in particular. */
 222.308 -            if (strcmp(p, "ISO8859-15") == 0)
 222.309 -                p = "ISO8859-15";
 222.310 -            else
 222.311 -                p = nl_langinfo(CODESET);
 222.312 -
 222.313 -            /* Convert the bare "646" used on Solaris to a proper IANA name */
 222.314 -            if (strcmp(p, "646") == 0)
 222.315 -                p = "ISO646-US";
 222.316 -
 222.317 -            /* return same result nl_langinfo would return for en_UK,
 222.318 -             * in order to use optimizations. */
 222.319 -            std_encoding = (*p != '\0') ? p : "ISO8859-1";
 222.320 -
 222.321 -
 222.322 -#ifdef __linux__
 222.323 -            /*
 222.324 -             * Remap the encoding string to a different value for japanese
 222.325 -             * locales on linux so that customized converters are used instead
 222.326 -             * of the default converter for "EUC-JP". The customized converters
 222.327 -             * omit support for the JIS0212 encoding which is not supported by
 222.328 -             * the variant of "EUC-JP" encoding used on linux
 222.329 -             */
 222.330 -            if (strcmp(p, "EUC-JP") == 0) {
 222.331 -                std_encoding = "EUC-JP-LINUX";
 222.332 -            }
 222.333 -#else
 222.334 -            if (strcmp(p,"eucJP") == 0) {
 222.335 -                /* For Solaris use customized vendor defined character
 222.336 -                 * customized EUC-JP converter
 222.337 -                 */
 222.338 -                std_encoding = "eucJP-open";
 222.339 -            } else if (strcmp(p, "Big5") == 0 || strcmp(p, "BIG5") == 0) {
 222.340 -                /*
 222.341 -                 * Remap the encoding string to Big5_Solaris which augments
 222.342 -                 * the default converter for Solaris Big5 locales to include
 222.343 -                 * seven additional ideographic characters beyond those included
 222.344 -                 * in the Java "Big5" converter.
 222.345 -                 */
 222.346 -                std_encoding = "Big5_Solaris";
 222.347 -            } else if (strcmp(p, "Big5-HKSCS") == 0) {
 222.348 -                /*
 222.349 -                 * Solaris uses HKSCS2001
 222.350 -                 */
 222.351 -                std_encoding = "Big5-HKSCS-2001";
 222.352 -            }
 222.353 -#endif
 222.354 -            sprops.encoding = std_encoding;
 222.355 -            sprops.sun_jnu_encoding = sprops.encoding;
 222.356 -        }
 222.357 +    setlocale(LC_ALL, "");
 222.358 +    if (ParseLocale(LC_CTYPE,
 222.359 +                    &(sprops.format_language),
 222.360 +                    &(sprops.format_country),
 222.361 +                    &(sprops.format_variant),
 222.362 +                    &(sprops.encoding))) {
 222.363 +        ParseLocale(LC_MESSAGES,
 222.364 +                    &(sprops.language),
 222.365 +                    &(sprops.country),
 222.366 +                    &(sprops.variant),
 222.367 +                    NULL);
 222.368 +    } else {
 222.369 +        sprops.language = "en";
 222.370 +        sprops.encoding = "ISO8859-1";
 222.371      }
 222.372 +    sprops.display_language = sprops.language;
 222.373 +    sprops.display_country = sprops.country;
 222.374 +    sprops.display_variant = sprops.variant;
 222.375 +    sprops.sun_jnu_encoding = sprops.encoding;
 222.376  
 222.377  #ifdef __linux__
 222.378  #if __BYTE_ORDER == __LITTLE_ENDIAN
   223.1 --- a/src/solaris/native/sun/awt/gtk2_interface.c	Thu Sep 23 17:33:40 2010 -0700
   223.2 +++ b/src/solaris/native/sun/awt/gtk2_interface.c	Fri Sep 24 16:41:32 2010 -0700
   223.3 @@ -1,5 +1,5 @@
   223.4  /*
   223.5 - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
   223.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   223.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   223.8   *
   223.9   * This code is free software; you can redistribute it and/or modify it
  223.10 @@ -371,6 +371,16 @@
  223.11      return convertionBuffer;
  223.12  }
  223.13  
  223.14 +static void throw_exception(JNIEnv *env, const char* name, const char* message)
  223.15 +{
  223.16 +    jclass class = (*env)->FindClass(env, name);
  223.17 +
  223.18 +    if (class != NULL)
  223.19 +        (*env)->ThrowNew(env, class, message);
  223.20 +
  223.21 +    (*env)->DeleteLocalRef(env, class);
  223.22 +}
  223.23 +
  223.24  /* This is a workaround for the bug:
  223.25   * http://sourceware.org/bugzilla/show_bug.cgi?id=1814
  223.26   * (dlsym/dlopen clears dlerror state)
  223.27 @@ -859,14 +869,26 @@
  223.28   * comparing results. This can be optimized by using subclassed pixmap and
  223.29   * doing the second drawing only if necessary.
  223.30  */
  223.31 -void gtk2_init_painting(gint width, gint height)
  223.32 +void gtk2_init_painting(JNIEnv *env, gint width, gint height)
  223.33  {
  223.34      GdkGC *gc;
  223.35 +    GdkPixbuf *white, *black;
  223.36  
  223.37      init_containers();
  223.38  
  223.39      if (gtk2_pixbuf_width < width || gtk2_pixbuf_height < height)
  223.40      {
  223.41 +        white = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
  223.42 +        black = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8, width, height);
  223.43 +
  223.44 +        if (white == NULL || black == NULL)
  223.45 +        {
  223.46 +            snprintf(convertionBuffer, CONV_BUFFER_SIZE, "Couldn't create pixbuf of size %dx%d", width, height);
  223.47 +            throw_exception(env, "java/lang/RuntimeException", convertionBuffer);
  223.48 +            fp_gdk_threads_leave();
  223.49 +            return;
  223.50 +        }
  223.51 +
  223.52          if (gtk2_white_pixmap != NULL) {
  223.53              /* free old stuff */
  223.54              (*fp_g_object_unref)(gtk2_white_pixmap);
  223.55 @@ -875,14 +897,12 @@
  223.56              (*fp_g_object_unref)(gtk2_black_pixbuf);
  223.57          }
  223.58  
  223.59 -        gtk2_white_pixmap = (*fp_gdk_pixmap_new)
  223.60 -                                (gtk2_window->window, width, height, -1);
  223.61 -        gtk2_black_pixmap = (*fp_gdk_pixmap_new)
  223.62 -                                (gtk2_window->window, width, height, -1);
  223.63 -        gtk2_white_pixbuf = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8,
  223.64 -                                                 width, height);
  223.65 -        gtk2_black_pixbuf = (*fp_gdk_pixbuf_new)(GDK_COLORSPACE_RGB, TRUE, 8,
  223.66 -                                                 width, height);
  223.67 +        gtk2_white_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1);
  223.68 +        gtk2_black_pixmap = (*fp_gdk_pixmap_new)(gtk2_window->window, width, height, -1);
  223.69 +
  223.70 +        gtk2_white_pixbuf = white;
  223.71 +        gtk2_black_pixbuf = black;
  223.72 +
  223.73          gtk2_pixbuf_width = width;
  223.74          gtk2_pixbuf_height = height;
  223.75      }
   224.1 --- a/src/solaris/native/sun/awt/gtk2_interface.h	Thu Sep 23 17:33:40 2010 -0700
   224.2 +++ b/src/solaris/native/sun/awt/gtk2_interface.h	Fri Sep 24 16:41:32 2010 -0700
   224.3 @@ -1,5 +1,5 @@
   224.4  /*
   224.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
   224.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   224.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   224.8   *
   224.9   * This code is free software; you can redistribute it and/or modify it
  224.10 @@ -717,7 +717,7 @@
  224.11  void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
  224.12          gint x, gint y, gint width, gint height);
  224.13  
  224.14 -void gtk2_init_painting(gint w, gint h);
  224.15 +void gtk2_init_painting(JNIEnv *env, gint w, gint h);
  224.16  gint gtk2_copy_image(gint *dest, gint width, gint height);
  224.17  
  224.18  gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type);
   225.1 --- a/src/solaris/native/sun/awt/swing_GTKEngine.c	Thu Sep 23 17:33:40 2010 -0700
   225.2 +++ b/src/solaris/native/sun/awt/swing_GTKEngine.c	Fri Sep 24 16:41:32 2010 -0700
   225.3 @@ -1,5 +1,5 @@
   225.4  /*
   225.5 - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
   225.6 + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
   225.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   225.8   *
   225.9   * This code is free software; you can redistribute it and/or modify it
  225.10 @@ -293,7 +293,7 @@
  225.11          JNIEnv *env, jobject this, jint w, jint h)
  225.12  {
  225.13      fp_gdk_threads_enter();
  225.14 -    gtk2_init_painting(w, h);
  225.15 +    gtk2_init_painting(env, w, h);
  225.16      fp_gdk_threads_leave();
  225.17  }
  225.18  
   226.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   226.2 +++ b/src/solaris/native/sun/net/sdp/SdpSupport.c	Fri Sep 24 16:41:32 2010 -0700
   226.3 @@ -0,0 +1,123 @@
   226.4 +/*
   226.5 + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   226.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   226.7 + *
   226.8 + * This code is free software; you can redistribute it and/or modify it
   226.9 + * under the terms of the GNU General Public License version 2 only, as
  226.10 + * published by the Free Software Foundation.  Oracle designates this
  226.11 + * particular file as subject to the "Classpath" exception as provided
  226.12 + * by Oracle in the LICENSE file that accompanied this code.
  226.13 + *
  226.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  226.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  226.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  226.17 + * version 2 for more details (a copy is included in the LICENSE file that
  226.18 + * accompanied this code).
  226.19 + *
  226.20 + * You should have received a copy of the GNU General Public License version
  226.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  226.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  226.23 + *
  226.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  226.25 + * or visit www.oracle.com if you need additional information or have any
  226.26 + * questions.
  226.27 + */
  226.28 +
  226.29 +#include <sys/types.h>
  226.30 +#include <sys/socket.h>
  226.31 +#include <errno.h>
  226.32 +
  226.33 +#if defined(__solaris__)
  226.34 +  #if !defined(PROTO_SDP)
  226.35 +    #define PROTO_SDP       257
  226.36 +  #endif
  226.37 +#elif defined(__linux__)
  226.38 +  #if !defined(AF_INET_SDP)
  226.39 +    #define AF_INET_SDP     27
  226.40 +  #endif
  226.41 +#endif
  226.42 +
  226.43 +#include "jni.h"
  226.44 +#include "jni_util.h"
  226.45 +#include "net_util.h"
  226.46 +
  226.47 +#define RESTARTABLE(_cmd, _result) do { \
  226.48 +  do { \
  226.49 +    _result = _cmd; \
  226.50 +  } while((_result == -1) && (errno == EINTR)); \
  226.51 +} while(0)
  226.52 +
  226.53 +
  226.54 +/**
  226.55 + * Creates a SDP socket.
  226.56 + */
  226.57 +static int create(JNIEnv* env)
  226.58 +{
  226.59 +    int s;
  226.60 +
  226.61 +#if defined(__solaris__)
  226.62 +  #ifdef AF_INET6
  226.63 +    int domain = ipv6_available() ? AF_INET6 : AF_INET;
  226.64 +  #else
  226.65 +    int domain = AF_INET;
  226.66 +  #endif
  226.67 +    s = socket(domain, SOCK_STREAM, PROTO_SDP);
  226.68 +#elif defined(__linux__)
  226.69 +    /**
  226.70 +     * IPv6 not supported by SDP on Linux
  226.71 +     */
  226.72 +    if (ipv6_available()) {
  226.73 +        JNU_ThrowIOException(env, "IPv6 not supported");
  226.74 +        return;
  226.75 +    }
  226.76 +    s = socket(AF_INET_SDP, SOCK_STREAM, 0);
  226.77 +#else
  226.78 +    /* not supported on other platforms at this time */
  226.79 +    s = -1;
  226.80 +    errno = EPROTONOSUPPORT;
  226.81 +#endif
  226.82 +
  226.83 +    if (s < 0)
  226.84 +        JNU_ThrowIOExceptionWithLastError(env, "socket");
  226.85 +    return s;
  226.86 +}
  226.87 +
  226.88 +/**
  226.89 + * Creates a SDP socket, returning file descriptor referencing the socket.
  226.90 + */
  226.91 +JNIEXPORT jint JNICALL
  226.92 +Java_sun_net_sdp_SdpSupport_create0(JNIEnv *env, jclass cls)
  226.93 +{
  226.94 +    return create(env);
  226.95 +}
  226.96 +
  226.97 +/**
  226.98 + * Converts an existing file descriptor, that references an unbound TCP socket,
  226.99 + * to SDP.
 226.100 + */
 226.101 +JNIEXPORT void JNICALL
 226.102 +Java_sun_net_sdp_SdpSupport_convert0(JNIEnv *env, jclass cls, int fd)
 226.103 +{
 226.104 +    int s = create(env);
 226.105 +    if (s >= 0) {
 226.106 +        socklen_t len;
 226.107 +        int arg, res;
 226.108 +        struct linger linger;
 226.109 +
 226.110 +        /* copy socket options that are relevant to SDP */
 226.111 +        len = sizeof(arg);
 226.112 +        if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, &len) == 0)
 226.113 +            setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, len);
 226.114 +        len = sizeof(arg);
 226.115 +        if (getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, &len) == 0)
 226.116 +            setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, len);
 226.117 +        len = sizeof(linger);
 226.118 +        if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (void*)&linger, &len) == 0)
 226.119 +            setsockopt(s, SOL_SOCKET, SO_LINGER, (char*)&linger, len);
 226.120 +
 226.121 +        RESTARTABLE(dup2(s, fd), res);
 226.122 +        if (res < 0)
 226.123 +            JNU_ThrowIOExceptionWithLastError(env, "dup2");
 226.124 +        RESTARTABLE(close(s), res);
 226.125 +    }
 226.126 +}
   227.1 --- a/src/solaris/native/sun/net/spi/SdpProvider.c	Thu Sep 23 17:33:40 2010 -0700
   227.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   227.3 @@ -1,78 +0,0 @@
   227.4 -/*
   227.5 - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   227.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   227.7 - *
   227.8 - * This code is free software; you can redistribute it and/or modify it
   227.9 - * under the terms of the GNU General Public License version 2 only, as
  227.10 - * published by the Free Software Foundation.  Oracle designates this
  227.11 - * particular file as subject to the "Classpath" exception as provided
  227.12 - * by Oracle in the LICENSE file that accompanied this code.
  227.13 - *
  227.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  227.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  227.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  227.17 - * version 2 for more details (a copy is included in the LICENSE file that
  227.18 - * accompanied this code).
  227.19 - *
  227.20 - * You should have received a copy of the GNU General Public License version
  227.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  227.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  227.23 - *
  227.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  227.25 - * or visit www.oracle.com if you need additional information or have any
  227.26 - * questions.
  227.27 - */
  227.28 -
  227.29 -#include <sys/types.h>
  227.30 -#include <sys/socket.h>
  227.31 -
  227.32 -#if defined(__solaris__) && !defined(PROTO_SDP)
  227.33 -#define PROTO_SDP       257
  227.34 -#endif
  227.35 -
  227.36 -#include "jni.h"
  227.37 -#include "jni_util.h"
  227.38 -#include "net_util.h"
  227.39 -
  227.40 -#define RESTARTABLE(_cmd, _result) do { \
  227.41 -  do { \
  227.42 -    _result = _cmd; \
  227.43 -  } while((_result == -1) && (errno == EINTR)); \
  227.44 -} while(0)
  227.45 -
  227.46 -JNIEXPORT void JNICALL
  227.47 -Java_sun_net_spi_SdpProvider_convert(JNIEnv *env, jclass cls, jint fd)
  227.48 -{
  227.49 -#ifdef PROTO_SDP
  227.50 -#ifdef AF_INET6
  227.51 -    int domain = ipv6_available() ? AF_INET6 : AF_INET;
  227.52 -#else
  227.53 -    int domain = AF_INET;
  227.54 -#endif
  227.55 -    int s = socket(domain, SOCK_STREAM, PROTO_SDP);
  227.56 -    if (s < 0) {
  227.57 -        JNU_ThrowIOExceptionWithLastError(env, "socket");
  227.58 -    } else {
  227.59 -        int arg, len, res;
  227.60 -        struct linger linger;
  227.61 -
  227.62 -        /* copy socket options that are relevant to SDP */
  227.63 -        len = sizeof(arg);
  227.64 -        if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, &len) == 0)
  227.65 -            setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, len);
  227.66 -        len = sizeof(arg);
  227.67 -        if (getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, &len) == 0)
  227.68 -            setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, len);
  227.69 -        len = sizeof(linger);
  227.70 -        if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (void*)&linger, &len) == 0)
  227.71 -            setsockopt(s, SOL_SOCKET, SO_LINGER, (char*)&linger, len);
  227.72 -
  227.73 -        RESTARTABLE(dup2(s, fd), res);
  227.74 -        if (res < 0)
  227.75 -            JNU_ThrowIOExceptionWithLastError(env, "dup2");
  227.76 -        RESTARTABLE(close(s), res);
  227.77 -    }
  227.78 -#else
  227.79 -    JNU_ThrowInternalError(env, "should not reach here");
  227.80 -#endif
  227.81 -}
   228.1 --- a/src/solaris/native/sun/nio/ch/IOUtil.c	Thu Sep 23 17:33:40 2010 -0700
   228.2 +++ b/src/solaris/native/sun/nio/ch/IOUtil.c	Fri Sep 24 16:41:32 2010 -0700
   228.3 @@ -67,12 +67,9 @@
   228.4  configureBlocking(int fd, jboolean blocking)
   228.5  {
   228.6      int flags = fcntl(fd, F_GETFL);
   228.7 +    int newflags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
   228.8  
   228.9 -    if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK))
  228.10 -        return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
  228.11 -    else if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK))
  228.12 -        return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
  228.13 -    return 0;
  228.14 +    return (flags == newflags) ? 0 : fcntl(fd, F_SETFL, newflags);
  228.15  }
  228.16  
  228.17  JNIEXPORT void JNICALL
  228.18 @@ -83,27 +80,25 @@
  228.19          JNU_ThrowIOExceptionWithLastError(env, "Configure blocking failed");
  228.20  }
  228.21  
  228.22 -JNIEXPORT void JNICALL
  228.23 -Java_sun_nio_ch_IOUtil_initPipe(JNIEnv *env, jobject this,
  228.24 -                                    jintArray intArray, jboolean block)
  228.25 +JNIEXPORT jlong JNICALL
  228.26 +Java_sun_nio_ch_IOUtil_makePipe(JNIEnv *env, jobject this, jboolean blocking)
  228.27  {
  228.28      int fd[2];
  228.29 -    jint *ptr = 0;
  228.30  
  228.31      if (pipe(fd) < 0) {
  228.32          JNU_ThrowIOExceptionWithLastError(env, "Pipe failed");
  228.33 -        return;
  228.34 +        return 0;
  228.35      }
  228.36 -    if (block == JNI_FALSE) {
  228.37 +    if (blocking == JNI_FALSE) {
  228.38          if ((configureBlocking(fd[0], JNI_FALSE) < 0)
  228.39              || (configureBlocking(fd[1], JNI_FALSE) < 0)) {
  228.40              JNU_ThrowIOExceptionWithLastError(env, "Configure blocking failed");
  228.41 +            close(fd[0]);
  228.42 +            close(fd[1]);
  228.43 +            return 0;
  228.44          }
  228.45      }
  228.46 -    ptr = (*env)->GetPrimitiveArrayCritical(env, intArray, 0);
  228.47 -    ptr[0] = fd[0];
  228.48 -    ptr[1] = fd[1];
  228.49 -    (*env)->ReleasePrimitiveArrayCritical(env, intArray, ptr, 0);
  228.50 +    return ((jlong) fd[0] << 32) | (jlong) fd[1];
  228.51  }
  228.52  
  228.53  JNIEXPORT jboolean JNICALL
  228.54 @@ -131,21 +126,22 @@
  228.55  {
  228.56      if (n > 0) /* Number of bytes written */
  228.57          return n;
  228.58 -    if (n < 0) {
  228.59 -        if (errno == EAGAIN)
  228.60 -            return IOS_UNAVAILABLE;
  228.61 -        if (errno == EINTR)
  228.62 -            return IOS_INTERRUPTED;
  228.63 -    }
  228.64 -    if (n == 0) {
  228.65 +    else if (n == 0) {
  228.66          if (reading) {
  228.67              return IOS_EOF; /* EOF is -1 in javaland */
  228.68          } else {
  228.69              return 0;
  228.70          }
  228.71      }
  228.72 -    JNU_ThrowIOExceptionWithLastError(env, "Read/write failed");
  228.73 -    return IOS_THROWN;
  228.74 +    else if (errno == EAGAIN)
  228.75 +        return IOS_UNAVAILABLE;
  228.76 +    else if (errno == EINTR)
  228.77 +        return IOS_INTERRUPTED;
  228.78 +    else {
  228.79 +        const char *msg = reading ? "Read failed" : "Write failed";
  228.80 +        JNU_ThrowIOExceptionWithLastError(env, msg);
  228.81 +        return IOS_THROWN;
  228.82 +    }
  228.83  }
  228.84  
  228.85  /* Declared in nio_util.h for use elsewhere in NIO */
  228.86 @@ -155,21 +151,22 @@
  228.87  {
  228.88      if (n > 0) /* Number of bytes written */
  228.89          return n;
  228.90 -    if (n < 0) {
  228.91 -        if (errno == EAGAIN)
  228.92 -            return IOS_UNAVAILABLE;
  228.93 -        if (errno == EINTR)
  228.94 -            return IOS_INTERRUPTED;
  228.95 -    }
  228.96 -    if (n == 0) {
  228.97 +    else if (n == 0) {
  228.98          if (reading) {
  228.99              return IOS_EOF; /* EOF is -1 in javaland */
 228.100          } else {
 228.101              return 0;
 228.102          }
 228.103      }
 228.104 -    JNU_ThrowIOExceptionWithLastError(env, "Read/write failed");
 228.105 -    return IOS_THROWN;
 228.106 +    else if (errno == EAGAIN)
 228.107 +        return IOS_UNAVAILABLE;
 228.108 +    else if (errno == EINTR)
 228.109 +        return IOS_INTERRUPTED;
 228.110 +    else {
 228.111 +        const char *msg = reading ? "Read failed" : "Write failed";
 228.112 +        JNU_ThrowIOExceptionWithLastError(env, msg);
 228.113 +        return IOS_THROWN;
 228.114 +    }
 228.115  }
 228.116  
 228.117  jint
   229.1 --- a/src/windows/bin/java_md.c	Thu Sep 23 17:33:40 2010 -0700
   229.2 +++ b/src/windows/bin/java_md.c	Fri Sep 24 16:41:32 2010 -0700
   229.3 @@ -105,15 +105,15 @@
   229.4          exit(1);
   229.5      }
   229.6  
   229.7 -    /* Do this before we read jvm.cfg */
   229.8 -    EnsureJreInstallation(jrepath);
   229.9 -
  229.10      /* Find out where the JRE is that we will be using. */
  229.11      if (!GetJREPath(jrepath, so_jrepath)) {
  229.12          JLI_ReportErrorMessage(JRE_ERROR1);
  229.13          exit(2);
  229.14      }
  229.15  
  229.16 +    /* Do this before we read jvm.cfg and after jrepath is initialized */
  229.17 +    EnsureJreInstallation(jrepath);
  229.18 +
  229.19      /* Find the specified JVM type */
  229.20      if (ReadKnownVMs(jrepath, (char*)GetArch(), JNI_FALSE) < 1) {
  229.21          JLI_ReportErrorMessage(CFG_ERROR7);
  229.22 @@ -162,6 +162,10 @@
  229.23  #endif
  229.24  #ifdef CRT_DLL
  229.25          if (GetJREPath(crtpath, MAXPATHLEN)) {
  229.26 +            if (JLI_StrLen(crtpath) + JLI_StrLen("\\bin\\") + JLI_StrLen(CRT_DLL) >= MAXPATHLEN) {
  229.27 +                JLI_ReportErrorMessage(JRE_ERROR11);
  229.28 +                return JNI_FALSE;
  229.29 +            }
  229.30              (void)JLI_StrCat(crtpath, "\\bin\\" CRT_DLL);   /* Add crt dll */
  229.31              JLI_TraceLauncher("CRT path is %s\n", crtpath);
  229.32              if (_access(crtpath, 0) == 0) {
  229.33 @@ -213,6 +217,7 @@
  229.34      }
  229.35      /* Does our bundle directory exist ? */
  229.36      JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\lib\\bundles", jrepath);
  229.37 +    JLI_TraceLauncher("EnsureJreInstallation: %s\n", tmpbuf);
  229.38      if (stat(tmpbuf, &s) != 0) {
  229.39          return;
  229.40      }
  229.41 @@ -851,8 +856,7 @@
  229.42      /*
  229.43       * If this isn't the selected version, exec the selected version.
  229.44       */
  229.45 -    (void)JLI_StrCat(JLI_StrCat(JLI_StrCpy(path, jre), "\\bin\\"), progname);
  229.46 -    (void)JLI_StrCat(path, ".exe");
  229.47 +    JLI_Snprintf(path, sizeof(path), "%s\\bin\\%s.exe", jre, progname);
  229.48  
  229.49      /*
  229.50       * Although Windows has an execv() entrypoint, it doesn't actually
   230.1 --- a/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java	Thu Sep 23 17:33:40 2010 -0700
   230.2 +++ b/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java	Fri Sep 24 16:41:32 2010 -0700
   230.3 @@ -28,7 +28,6 @@
   230.4  import java.nio.file.*;
   230.5  import java.nio.file.attribute.BasicFileAttributes;
   230.6  import java.util.Iterator;
   230.7 -import java.util.ConcurrentModificationException;
   230.8  import java.util.NoSuchElementException;
   230.9  import java.io.IOException;
  230.10  
  230.11 @@ -121,17 +120,10 @@
  230.12          }
  230.13      }
  230.14  
  230.15 -    private static void throwAsConcurrentModificationException(Throwable t) {
  230.16 -        ConcurrentModificationException cme = new ConcurrentModificationException();
  230.17 -        cme.initCause(t);
  230.18 -        throw cme;
  230.19 -    }
  230.20 -
  230.21      private class WindowsDirectoryIterator implements Iterator<Path> {
  230.22          private boolean atEof;
  230.23          private String first;
  230.24          private Path nextEntry;
  230.25 -        private Path prevEntry;
  230.26  
  230.27          WindowsDirectoryIterator(String first) {
  230.28              atEof = false;
  230.29 @@ -156,7 +148,7 @@
  230.30                  if (filter.accept(entry))
  230.31                      return entry;
  230.32              } catch (IOException ioe) {
  230.33 -                throwAsConcurrentModificationException(ioe);
  230.34 +                throw new DirectoryIteratorException(ioe);
  230.35              }
  230.36              return null;
  230.37          }
  230.38 @@ -177,21 +169,19 @@
  230.39  
  230.40                  // synchronize on closeLock to prevent close while reading
  230.41                  synchronized (closeLock) {
  230.42 -                    if (!isOpen)
  230.43 -                        throwAsConcurrentModificationException(new
  230.44 -                            ClosedDirectoryStreamException());
  230.45                      try {
  230.46 -                        name = FindNextFile(handle, findDataBuffer.address());
  230.47 -                        if (name == null) {
  230.48 -                            // NO_MORE_FILES
  230.49 -                            return null;
  230.50 +                        if (isOpen) {
  230.51 +                            name = FindNextFile(handle, findDataBuffer.address());
  230.52                          }
  230.53                      } catch (WindowsException x) {
  230.54 -                        try {
  230.55 -                            x.rethrowAsIOException(dir);
  230.56 -                        } catch (IOException ioe) {
  230.57 -                            throwAsConcurrentModificationException(ioe);
  230.58 -                        }
  230.59 +                        IOException ioe = x.asIOException(dir);
  230.60 +                        throw new DirectoryIteratorException(ioe);
  230.61 +                    }
  230.62 +
  230.63 +                    // NO_MORE_FILES or stream closed
  230.64 +                    if (name == null) {
  230.65 +                        atEof = true;
  230.66 +                        return null;
  230.67                      }
  230.68  
  230.69                      // grab the attributes from the WIN32_FIND_DATA structure
  230.70 @@ -210,49 +200,28 @@
  230.71  
  230.72          @Override
  230.73          public synchronized boolean hasNext() {
  230.74 -            if (nextEntry == null && !atEof) {
  230.75 +            if (nextEntry == null && !atEof)
  230.76                  nextEntry = readNextEntry();
  230.77 -                atEof = (nextEntry == null);
  230.78 -            }
  230.79              return nextEntry != null;
  230.80          }
  230.81  
  230.82          @Override
  230.83          public synchronized Path next() {
  230.84 -            if (nextEntry == null) {
  230.85 -                if (!atEof) {
  230.86 -                    nextEntry = readNextEntry();
  230.87 -                }
  230.88 -                if (nextEntry == null) {
  230.89 -                    atEof = true;
  230.90 -                    throw new NoSuchElementException();
  230.91 -                }
  230.92 +            Path result = null;
  230.93 +            if (nextEntry == null && !atEof) {
  230.94 +                result = readNextEntry();
  230.95 +            } else {
  230.96 +                result = nextEntry;
  230.97 +                nextEntry = null;
  230.98              }
  230.99 -            prevEntry = nextEntry;
 230.100 -            nextEntry = null;
 230.101 -            return prevEntry;
 230.102 +            if (result == null)
 230.103 +                throw new NoSuchElementException();
 230.104 +            return result;
 230.105          }
 230.106  
 230.107          @Override
 230.108          public void remove() {
 230.109 -            if (!isOpen) {
 230.110 -                throwAsConcurrentModificationException(new
 230.111 -                    ClosedDirectoryStreamException());
 230.112 -            }
 230.113 -            Path entry;
 230.114 -            synchronized (this) {
 230.115 -                if (prevEntry == null)
 230.116 -                    throw new IllegalStateException("no last element");
 230.117 -                entry = prevEntry;
 230.118 -                prevEntry = null;
 230.119 -            }
 230.120 -            try {
 230.121 -                entry.delete();
 230.122 -            } catch (IOException ioe) {
 230.123 -                throwAsConcurrentModificationException(ioe);
 230.124 -            } catch (SecurityException se) {
 230.125 -                throwAsConcurrentModificationException(se);
 230.126 -            }
 230.127 +            throw new UnsupportedOperationException();
 230.128          }
 230.129      }
 230.130  }
   231.1 --- a/src/windows/native/java/lang/java_props_md.c	Thu Sep 23 17:33:40 2010 -0700
   231.2 +++ b/src/windows/native/java/lang/java_props_md.c	Fri Sep 24 16:41:32 2010 -0700
   231.3 @@ -43,413 +43,48 @@
   231.4  #endif
   231.5  
   231.6  typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
   231.7 +static void SetupI18nProps(LCID lcid, char** language, char** country,
   231.8 +               char** variant, char** encoding);
   231.9  
  231.10  #define SHELL_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
  231.11  
  231.12 -/* Encodings for Windows language groups. According to
  231.13 -   www.microsoft.com/globaldev/faqs/locales.asp,
  231.14 -   some locales do not have codepages, and are
  231.15 -   supported in Windows 2000/XP solely through Unicode.
  231.16 -   In this case, we use utf-8 encoding */
  231.17 +static char *
  231.18 +getEncodingInternal(LCID lcid)
  231.19 +{
  231.20 +    char * ret = malloc(16);
  231.21 +    int codepage;
  231.22  
  231.23 -static char *encoding_names[] = {
  231.24 -    "Cp1250",    /*  0:Latin 2  */
  231.25 -    "Cp1251",    /*  1:Cyrillic */
  231.26 -    "Cp1252",    /*  2:Latin 1  */
  231.27 -    "Cp1253",    /*  3:Greek    */
  231.28 -    "Cp1254",    /*  4:Latin 5  */
  231.29 -    "Cp1255",    /*  5:Hebrew   */
  231.30 -    "Cp1256",    /*  6:Arabic   */
  231.31 -    "Cp1257",    /*  7:Baltic   */
  231.32 -    "Cp1258",    /*  8:Viet Nam */
  231.33 -    "MS874",     /*  9:Thai     */
  231.34 -    "MS932",     /* 10:Japanese */
  231.35 -    "GBK",       /* 11:PRC GBK  */
  231.36 -    "MS949",     /* 12:Korean Extended Wansung */
  231.37 -    "MS950",     /* 13:Chinese (Taiwan, Hongkong, Macau) */
  231.38 -    "utf-8",     /* 14:Unicode  */
  231.39 -    "MS1361",    /* 15:Korean Johab */
  231.40 -};
  231.41 +    if (GetLocaleInfo(lcid,
  231.42 +                      LOCALE_IDEFAULTANSICODEPAGE,
  231.43 +                      ret+2, 14) == 0) {
  231.44 +        codepage = 1252;
  231.45 +    } else {
  231.46 +        codepage = atoi(ret+2);
  231.47 +    }
  231.48  
  231.49 -/*
  231.50 - * List mapping from LanguageID to Java locale IDs.
  231.51 - * The entries in this list should not be construed to suggest we actually have
  231.52 - * full locale-data and other support for all of these locales; these are
  231.53 - * merely all of the Windows locales for which we could construct an accurate
  231.54 - * locale ID.  The data is based on the web page "Windows XP/Server 2003 -
  231.55 - * List of Locale IDs, Input Locale, and Language Collection"
  231.56 - * (http://www.microsoft.com/globaldev/reference/winxp/xp-lcid.mspx)
  231.57 - *
  231.58 - * Some of the language IDs below are not yet used by Windows, but were
  231.59 - * defined by Microsoft for other products, such as Office XP. They may
  231.60 - * become Windows language IDs in the future.
  231.61 - *
  231.62 - */
  231.63 -typedef struct LANGIDtoLocale {
  231.64 -    WORD    langID;
  231.65 -    WORD    encoding;
  231.66 -    char*   javaID;
  231.67 -} LANGIDtoLocale;
  231.68 -
  231.69 -static LANGIDtoLocale langIDMap[] = {
  231.70 -    /* fallback locales to use when the country code doesn't match anything we have */
  231.71 -    0x01,    6, "ar",
  231.72 -    0x02,    1, "bg",
  231.73 -    0x03,    2, "ca",
  231.74 -    0x04,   11, "zh",
  231.75 -    0x05,    0, "cs",
  231.76 -    0x06,    2, "da",
  231.77 -    0x07,    2, "de",
  231.78 -    0x08,    3, "el",
  231.79 -    0x09,    2, "en",
  231.80 -    0x0a,    2, "es",
  231.81 -    0x0b,    2, "fi",
  231.82 -    0x0c,    2, "fr",
  231.83 -    0x0d,    5, "iw",
  231.84 -    0x0e,    0, "hu",
  231.85 -    0x0f,    2, "is",
  231.86 -    0x10,    2, "it",
  231.87 -    0x11,   10, "ja",
  231.88 -    0x12,   12, "ko",
  231.89 -    0x13,    2, "nl",
  231.90 -    0x14,    2, "no",
  231.91 -    0x15,    0, "pl",
  231.92 -    0x16,    2, "pt",
  231.93 -    0x17,    2, "rm",
  231.94 -    0x18,    0, "ro",
  231.95 -    0x19,    1, "ru",
  231.96 -    0x1a,    0, "sr",
  231.97 -    0x1b,    0, "sk",
  231.98 -    0x1c,    0, "sq",
  231.99 -    0x1d,    2, "sv",
 231.100 -    0x1e,    9, "th",
 231.101 -    0x1f,    4, "tr",
 231.102 -    0x20,    2, "ur",
 231.103 -    0x21,    2, "in",
 231.104 -    0x22,    1, "uk",
 231.105 -    0x23,    1, "be",
 231.106 -    0x24,    0, "sl",
 231.107 -    0x25,    7, "et",
 231.108 -    0x26,    7, "lv",
 231.109 -    0x27,    7, "lt",
 231.110 -    0x28,    1, "tg",
 231.111 -    0x29,    6, "fa",
 231.112 -    0x2a,    8, "vi",
 231.113 -    0x2b,   14, "hy",
 231.114 -    0x2c,    4, "az",
 231.115 -    0x2d,    2, "eu",
 231.116 -/*  0x2e,    2, "??",  no ISO-639 abbreviation for Sorbian */
 231.117 -    0x2f,    1, "mk",
 231.118 -    0x31,    2, "ts",
 231.119 -    0x32,    2, "tn",
 231.120 -    0x34,    2, "xh",
 231.121 -    0x35,    2, "zu",
 231.122 -    0x36,    2, "af",
 231.123 -    0x37,   14, "ka",
 231.124 -    0x38,    2, "fo",
 231.125 -    0x39,   14, "hi",
 231.126 -    0x3a,   14, "mt",
 231.127 -    0x3b,    2, "se",
 231.128 -    0x3c,    2, "gd",
 231.129 -    0x3d,    2, "yi",
 231.130 -    0x3e,    2, "ms",
 231.131 -    0x3f,    1, "kk",
 231.132 -    0x40,    1, "ky",
 231.133 -    0x41,    2, "sw",
 231.134 -    0x42,    0, "tk",
 231.135 -    0x43,    1, "uz",
 231.136 -    0x44,    1, "tt",
 231.137 -    0x45,   14, "bn",
 231.138 -    0x46,   14, "pa",
 231.139 -    0x47,   14, "gu",
 231.140 -    0x48,   14, "or",
 231.141 -    0x49,   14, "ta",
 231.142 -    0x4a,   14, "te",
 231.143 -    0x4b,   14, "kn",
 231.144 -    0x4c,   14, "ml",
 231.145 -    0x4d,   14, "as",
 231.146 -    0x4e,   14, "mr",
 231.147 -    0x4f,   14, "sa",
 231.148 -    0x50,    1, "mn",
 231.149 -    0x51,   14, "bo",
 231.150 -    0x52,    1, "cy",
 231.151 -    0x53,   14, "km",
 231.152 -    0x54,   14, "lo",
 231.153 -    0x56,    2, "gl",
 231.154 -    0x5b,   14, "si",
 231.155 -    0x5d,   14, "iu",
 231.156 -    0x5e,   14, "am",
 231.157 -/*  0x5f,    2, "??",  no ISO-639 abbreviation for Tamazight */
 231.158 -    0x68,    2, "ha",
 231.159 -    0x6a,    2, "yo",
 231.160 -    0x6b,    2, "qu",
 231.161 -    0x6d,    1, "ba",
 231.162 -    0x6f,    2, "kl",
 231.163 -    0x70,    2, "ig",
 231.164 -/*  0x78,   14, "??",  no ISO-639 abbreviation for Yi */
 231.165 -    0x7e,    2, "br",
 231.166 -    0x80,    6, "ug",
 231.167 -    0x81,   14, "mi",
 231.168 -    0x82,    2, "oc",
 231.169 -    0x83,    2, "co",
 231.170 -/*  0x84,    2, "??",  no ISO-639 abbreviation for Alsatian */
 231.171 -/*  0x85,    1, "??",  no ISO-639 abbreviation for Yakut */
 231.172 -/*  0x86,    2, "??",  no ISO-639 abbreviation for K'iche */
 231.173 -    0x87,    2, "rw",
 231.174 -    0x88,    2, "wo",
 231.175 -/*  0x8c,    6, "??",  no ISO-639 abbreviation for Dari */
 231.176 -    /* mappings for real Windows LCID values */
 231.177 -    0x0401,  6, "ar_SA",
 231.178 -    0x0402,  1, "bg_BG",
 231.179 -    0x0403,  2, "ca_ES",
 231.180 -    0x0404, 13, "zh_TW",
 231.181 -    0x0405,  0, "cs_CZ",
 231.182 -    0x0406,  2, "da_DK",
 231.183 -    0x0407,  2, "de_DE",
 231.184 -    0x0408,  3, "el_GR",
 231.185 -    0x0409,  2, "en_US",
 231.186 -    0x040a,  2, "es_ES",  /* (traditional sort) */
 231.187 -    0x040b,  2, "fi_FI",
 231.188 -    0x040c,  2, "fr_FR",
 231.189 -    0x040d,  5, "iw_IL",
 231.190 -    0x040e,  0, "hu_HU",
 231.191 -    0x040f,  2, "is_IS",
 231.192 -    0x0410,  2, "it_IT",
 231.193 -    0x0411, 10, "ja_JP",
 231.194 -    0x0412, 12, "ko_KR",
 231.195 -    0x0413,  2, "nl_NL",
 231.196 -    0x0414,  2, "no_NO",
 231.197 -    0x0415,  0, "pl_PL",
 231.198 -    0x0416,  2, "pt_BR",
 231.199 -    0x0417,  2, "rm_CH",
 231.200 -    0x0418,  0, "ro_RO",
 231.201 -    0x0419,  1, "ru_RU",
 231.202 -    0x041a,  0, "hr_HR",
 231.203 -    0x041b,  0, "sk_SK",
 231.204 -    0x041c,  0, "sq_AL",
 231.205 -    0x041d,  2, "sv_SE",
 231.206 -    0x041e,  9, "th_TH",
 231.207 -    0x041f,  4, "tr_TR",
 231.208 -    0x0420,  6, "ur_PK",
 231.209 -    0x0421,  2, "in_ID",
 231.210 -    0x0422,  1, "uk_UA",
 231.211 -    0x0423,  1, "be_BY",
 231.212 -    0x0424,  0, "sl_SI",
 231.213 -    0x0425,  7, "et_EE",
 231.214 -    0x0426,  7, "lv_LV",
 231.215 -    0x0427,  7, "lt_LT",
 231.216 -    0x0428,  1, "tg_TJ",
 231.217 -    0x0429,  6, "fa_IR",
 231.218 -    0x042a,  8, "vi_VN",
 231.219 -    0x042b, 14, "hy_AM",  /* Armenian  */
 231.220 -    0x042c,  4, "az_AZ",  /* Azeri_Latin */
 231.221 -    0x042d,  2, "eu_ES",
 231.222 -/*  0x042e,  2, "??",      no ISO-639 abbreviation for Upper Sorbian */
 231.223 -    0x042f,  1, "mk_MK",
 231.224 -/*  0x0430,  2, "??",      no ISO-639 abbreviation for Sutu */
 231.225 -    0x0431,  2, "ts",     /* (country?) */
 231.226 -    0x0432,  2, "tn_ZA",
 231.227 -/*  0x0433,  2, "??",      no ISO-639 abbreviation for Venda */
 231.228 -    0x0434,  2, "xh_ZA",
 231.229 -    0x0435,  2, "zu_ZA",
 231.230 -    0x0436,  2, "af_ZA",
 231.231 -    0x0437, 14, "ka_GE",  /* Georgian   */
 231.232 -    0x0438,  2, "fo_FO",
 231.233 -    0x0439, 14, "hi_IN",
 231.234 -    0x043a, 14, "mt_MT",
 231.235 -    0x043b,  2, "se_NO",  /* Sami, Northern - Norway */
 231.236 -    0x043c,  2, "gd_GB",
 231.237 -    0x043d,  2, "yi",     /* (country?) */
 231.238 -    0x043e,  2, "ms_MY",
 231.239 -    0x043f,  1, "kk_KZ",  /* Kazakh */
 231.240 -    0x0440,  1, "ky_KG",  /* Kyrgyz     */
 231.241 -    0x0441,  2, "sw_KE",
 231.242 -    0x0442,  0, "tk_TM",
 231.243 -    0x0443,  4, "uz_UZ",  /* Uzbek_Latin */
 231.244 -    0x0444,  1, "tt_RU",  /* Tatar */
 231.245 -    0x0445, 14, "bn_IN",  /* Bengali   */
 231.246 -    0x0446, 14, "pa_IN",  /* Punjabi   */
 231.247 -    0x0447, 14, "gu_IN",  /* Gujarati  */
 231.248 -    0x0448, 14, "or_IN",  /* Oriya     */
 231.249 -    0x0449, 14, "ta_IN",  /* Tamil     */
 231.250 -    0x044a, 14, "te_IN",  /* Telugu    */
 231.251 -    0x044b, 14, "kn_IN",  /* Kannada   */
 231.252 -    0x044c, 14, "ml_IN",  /* Malayalam */
 231.253 -    0x044d, 14, "as_IN",  /* Assamese  */
 231.254 -    0x044e, 14, "mr_IN",  /* Marathi   */
 231.255 -    0x044f, 14, "sa_IN",  /* Sanskrit  */
 231.256 -    0x0450,  1, "mn_MN",  /* Mongolian */
 231.257 -    0x0451, 14, "bo_CN",  /* Tibetan   */
 231.258 -    0x0452,  2, "cy_GB",  /* Welsh     */
 231.259 -    0x0453, 14, "km_KH",  /* Khmer     */
 231.260 -    0x0454, 14, "lo_LA",  /* Lao       */
 231.261 -    0x0456,  2, "gl_ES",  /* Galician  */
 231.262 -/*  0x0457, 14, "??_IN",  /* Konkani, no ISO-639 abbreviation*/
 231.263 -/*  0x045a, 14, "??_SY",  /* Syriac, no ISO-639 abbreviation*/
 231.264 -    0x045b, 14, "si_LK",  /* Sinhala   */
 231.265 -    0x045d, 14, "iu_CA",  /* Inuktitut */
 231.266 -    0x045e, 14, "am_ET",  /* Amharic   */
 231.267 -    0x0461, 14, "ne_NP",  /* Nepali */
 231.268 -    0x0462,  2, "fy_NL",  /* Frisian */
 231.269 -    0x0463,  6, "ps_AF",  /* Pushto */
 231.270 -/*  0x0464,  2, "??_PH",  /* Filipino, no ISO-639 abbreviation*/
 231.271 -    0x0465, 14, "dv_MV",  /* Divehi    */
 231.272 -    0x0468,  2, "ha_NG",  /* Hausa     */
 231.273 -    0x046a,  2, "yo_NG",  /* Yoruba    */
 231.274 -    0x046b,  2, "qu_BO",  /* Quechua - Bolivia */
 231.275 -/*  0x046c,  2, "??_ZA",  /* Northern Sotho, no ISO-639 abbreviation */
 231.276 -    0x046d,  1, "ba_RU",  /* Bashkir   */
 231.277 -    0x046e,  2, "lb_LU",  /* Luxembourgish */
 231.278 -    0x046f,  2, "kl_GL",  /* Greenlandic */
 231.279 -    0x0470,  2, "ig_NG",  /* Igbo      */
 231.280 -/*  0x0478, 14, "??_CN",  /* Yi (PRC), no ISO-639 abbreviation */
 231.281 -/*  0x047a,  2, "??_CL",  /* Mapudungun (Araucanian), no ISO-639 abbreviation */
 231.282 -/*  0x047c,  2, "??_CA",  /* Mohawk, no ISO-639 abbreviation */
 231.283 -    0x047e,  2, "br_FR",  /* Breton    */
 231.284 -    0x0480,  6, "ug_CN",  /* Uighur    */
 231.285 -    0x0481, 14, "mi_NZ",  /* Maori - New Zealand */
 231.286 -    0x0482,  2, "oc_FR",  /* Occitan   */
 231.287 -    0x0483,  2, "co_FR",  /* Corsican  */
 231.288 -/*  0x0484,  2, "??_FR",  /* Alsatian, no ISO-639 abbreviation */
 231.289 -/*  0x0485,  1, "??_RU",  /* Yakut, no ISO-639 abbreviation */
 231.290 -/*  0x0486,  2, "??_GT",  /* K'iche, no ISO-639 abbreviation */
 231.291 -    0x0487,  2, "rw_RW",  /* Kinyarwanda */
 231.292 -    0x0488,  2, "wo_SN",  /* Wolof */
 231.293 -/*  0x048c,  6, "??_AF",  /* Dari, no ISO-639 abbreviation */
 231.294 -    0x0801,  6, "ar_IQ",
 231.295 -    0x0804, 11, "zh_CN",
 231.296 -    0x0807,  2, "de_CH",
 231.297 -    0x0809,  2, "en_GB",
 231.298 -    0x080a,  2, "es_MX",
 231.299 -    0x080c,  2, "fr_BE",
 231.300 -    0x0810,  2, "it_CH",
 231.301 -    0x0812, 15, "ko_KR",  /* Korean(Johab)*/
 231.302 -    0x0813,  2, "nl_BE",
 231.303 -    0x0814,  2, "no_NO_NY",
 231.304 -    0x0816,  2, "pt_PT",
 231.305 -    0x0818,  0, "ro_MD",
 231.306 -    0x0819,  1, "ru_MD",
 231.307 -    0x081a,  0, "sr_CS",
 231.308 -    0x081d,  2, "sv_FI",
 231.309 -    0x082c,  1, "az_AZ",  /* Azeri_Cyrillic */
 231.310 -/*  0x082e,  2, "??",      no ISO-639 abbreviation for Lower Sorbian */
 231.311 -    0x083b,  2, "se_SE",  /* Sami, Northern - Sweden */
 231.312 -    0x083c,  2, "ga_IE",
 231.313 -    0x083e,  2, "ms_BN",
 231.314 -    0x0843,  1, "uz_UZ",  /* Uzbek_Cyrillic */
 231.315 -    0x0845, 14, "bn_BD",  /* Bengali   */
 231.316 -    0x0850, 14, "mn_CN",  /* Traditional Mongolian */
 231.317 -    0x085d,  2, "iu_CA",  /* Inuktitut */
 231.318 -/*  0x085f,  2, "??_DZ",      no ISO-639 abbreviation for Tamazight */
 231.319 -    0x086b,  2, "qu_EC",  /* Quechua - Ecuador */
 231.320 -    0x0c01,  6, "ar_EG",
 231.321 -    0x0c04, 13, "zh_HK",
 231.322 -    0x0c07,  2, "de_AT",
 231.323 -    0x0c09,  2, "en_AU",
 231.324 -    0x0c0a,  2, "es_ES",  /* (modern sort) */
 231.325 -    0x0c0c,  2, "fr_CA",
 231.326 -    0x0c1a,  1, "sr_CS",
 231.327 -    0x0c3b,  2, "se_FI",  /* Sami, Northern - Finland */
 231.328 -    0x0c6b,  2, "qu_PE",  /* Quechua - Peru */
 231.329 -    0x1001,  6, "ar_LY",
 231.330 -    0x1004, 11, "zh_SG",
 231.331 -    0x1007,  2, "de_LU",
 231.332 -    0x1009,  2, "en_CA",
 231.333 -    0x100a,  2, "es_GT",
 231.334 -    0x100c,  2, "fr_CH",
 231.335 -    0x101a,  0, "hr_BA",
 231.336 -/*  0x103b,  2, "??_NO",  /* Sami, Lule - Norway */
 231.337 -    0x1401,  6, "ar_DZ",
 231.338 -    0x1404, 13, "zh_MO",
 231.339 -    0x1407,  2, "de_LI",
 231.340 -    0x1409,  2, "en_NZ",
 231.341 -    0x140a,  2, "es_CR",
 231.342 -    0x140c,  2, "fr_LU",
 231.343 -    0x141a,  0, "bs_BA",
 231.344 -/*  0x143b,  2, "??_SE",  /* Sami, Lule - Sweden */
 231.345 -    0x1801,  6, "ar_MA",
 231.346 -    0x1809,  2, "en_IE",
 231.347 -    0x180a,  2, "es_PA",
 231.348 -    0x180c,  2, "fr_MC",
 231.349 -    0x181a,  0, "sr_BA",
 231.350 -/*  0x183b,  2, "??_NO",  /* Sami, Southern - Norway */
 231.351 -    0x1c01,  6, "ar_TN",
 231.352 -    0x1c09,  2, "en_ZA",
 231.353 -    0x1c0a,  2, "es_DO",
 231.354 -    0x1c1a,  1, "sr_BA",
 231.355 -/*  0x1c3b,  2, "??_SE",  /* Sami, Southern - Sweden */
 231.356 -    0x2001,  6, "ar_OM",
 231.357 -    0x2009,  2, "en_JM",
 231.358 -    0x200a,  2, "es_VE",
 231.359 -    0x201a,  0, "bs_BA",  /* Bosnian (Cyrillic) */
 231.360 -/*  0x203b,  2, "??_FI",  /* Sami, Skolt - Finland */
 231.361 -    0x2401,  6, "ar_YE",
 231.362 -    0x2409,  2, "en",     /* ("Caribbean", which could be any of many countries) */
 231.363 -    0x240a,  2, "es_CO",
 231.364 -/*  0x243b,  2, "??_FI",  /* Sami, Inari - Finland */
 231.365 -    0x2801,  6, "ar_SY",
 231.366 -    0x2809,  2, "en_BZ",
 231.367 -    0x280a,  2, "es_PE",
 231.368 -    0x2c01,  6, "ar_JO",
 231.369 -    0x2c09,  2, "en_TT",
 231.370 -    0x2c0a,  2, "es_AR",
 231.371 -    0x3001,  6, "ar_LB",
 231.372 -    0x3009,  2, "en_ZW",
 231.373 -    0x300a,  2, "es_EC",
 231.374 -    0x3401,  6, "ar_KW",
 231.375 -    0x3409,  2, "en_PH",
 231.376 -    0x340a,  2, "es_CL",
 231.377 -    0x3801,  6, "ar_AE",
 231.378 -    0x380a,  2, "es_UY",
 231.379 -    0x3c01,  6, "ar_BH",
 231.380 -    0x3c0a,  2, "es_PY",
 231.381 -    0x4001,  6, "ar_QA",
 231.382 -    0x4009,  2, "en_IN",
 231.383 -    0x400a,  2, "es_BO",
 231.384 -    0x4409,  2, "en_MY",
 231.385 -    0x440a,  2, "es_SV",
 231.386 -    0x4809,  2, "en_SG",
 231.387 -    0x480a,  2, "es_HN",
 231.388 -    0x4c0a,  2, "es_NI",
 231.389 -    0x500a,  2, "es_PR",
 231.390 -    0x540a,  2, "es_US"
 231.391 -};
 231.392 -
 231.393 -/*
 231.394 - * binary-search our list of LANGID values.  If we don't find the
 231.395 - * one we're looking for, mask out the country code and try again
 231.396 - * with just the primary language ID
 231.397 - */
 231.398 -static int
 231.399 -getLocaleEntryIndex(LANGID langID)
 231.400 -{
 231.401 -    int index = -1;
 231.402 -    int tries = 0;
 231.403 -    do {
 231.404 -        int lo, hi, mid;
 231.405 -        lo = 0;
 231.406 -        hi = sizeof(langIDMap) / sizeof(LANGIDtoLocale);
 231.407 -        while (index == -1 && lo < hi) {
 231.408 -            mid = (lo + hi) / 2;
 231.409 -            if (langIDMap[mid].langID == langID) {
 231.410 -                index = mid;
 231.411 -            } else if (langIDMap[mid].langID > langID) {
 231.412 -                hi = mid;
 231.413 -            } else {
 231.414 -                lo = mid + 1;
 231.415 -            }
 231.416 -        }
 231.417 -        langID = PRIMARYLANGID(langID);
 231.418 -        ++tries;
 231.419 -    } while (index == -1 && tries < 2);
 231.420 -
 231.421 -    return index;
 231.422 -}
 231.423 -
 231.424 -static char *
 231.425 -getEncodingInternal(int index)
 231.426 -{
 231.427 -    char * ret = encoding_names[langIDMap[index].encoding];
 231.428 +    switch (codepage) {
 231.429 +    case 0:
 231.430 +        strcpy(ret, "UTF-8");
 231.431 +        break;
 231.432 +    case 874:     /*  9:Thai     */
 231.433 +    case 932:     /* 10:Japanese */
 231.434 +    case 949:     /* 12:Korean Extended Wansung */
 231.435 +    case 950:     /* 13:Chinese (Taiwan, Hongkong, Macau) */
 231.436 +    case 1361:    /* 15:Korean Johab */
 231.437 +        ret[0] = 'M';
 231.438 +        ret[1] = 'S';
 231.439 +        break;
 231.440 +    case 936:
 231.441 +        strcpy(ret, "GBK");
 231.442 +        break;
 231.443 +    case 54936:
 231.444 +        strcpy(ret, "GB18030");
 231.445 +        break;
 231.446 +    default:
 231.447 +        ret[0] = 'C';
 231.448 +        ret[1] = 'p';
 231.449 +        break;
 231.450 +    }
 231.451  
 231.452      //Traditional Chinese Windows should use MS950_HKSCS_XP as the
 231.453      //default encoding, if HKSCS patch has been installed.
 231.454 @@ -460,7 +95,7 @@
 231.455          WCHAR  unicodeChar;
 231.456          MultiByteToWideChar(CP_ACP, 0, mbChar, 2, &unicodeChar, 1);
 231.457          if (unicodeChar == 0x92db) {
 231.458 -            ret = "MS950_HKSCS_XP";
 231.459 +            strcpy(ret, "MS950_HKSCS_XP");
 231.460          }
 231.461      } else {
 231.462          //SimpChinese Windows should use GB18030 as the default
 231.463 @@ -476,7 +111,7 @@
 231.464                  strcat(systemPath, "\\FONTS\\SimSun18030.ttc");
 231.465                  if ((f = fopen(systemPath, "r")) != NULL) {
 231.466                      fclose(f);
 231.467 -                    ret = "GB18030";
 231.468 +                    strcpy(ret, "GB18030");
 231.469                  }
 231.470              }
 231.471          }
 231.472 @@ -489,25 +124,35 @@
 231.473  DllExport const char *
 231.474  getEncodingFromLangID(LANGID langID)
 231.475  {
 231.476 -    int index = getLocaleEntryIndex(langID);
 231.477 -
 231.478 -    if (index != (-1)) {
 231.479 -        return getEncodingInternal(index);
 231.480 -    } else {
 231.481 -        return "Cp1252";
 231.482 -    }
 231.483 +    return getEncodingInternal(MAKELCID(langID, SORT_DEFAULT));
 231.484  }
 231.485  
 231.486  DllExport const char *
 231.487  getJavaIDFromLangID(LANGID langID)
 231.488  {
 231.489 -    int index = getLocaleEntryIndex(langID);
 231.490 +    char * lang;
 231.491 +    char * ctry;
 231.492 +    char * vrnt;
 231.493 +    char * enc;
 231.494 +    char * ret = malloc(16);
 231.495  
 231.496 -    if (index != (-1)) {
 231.497 -        return langIDMap[index].javaID;
 231.498 +    SetupI18nProps(MAKELCID(langID, SORT_DEFAULT), &lang, &ctry, &vrnt, &enc);
 231.499 +    if (ctry[0] != '\0') {
 231.500 +        if (vrnt[0] != '\0') {
 231.501 +            sprintf(ret, "%s_%s_%s", lang, ctry, vrnt);
 231.502 +        } else {
 231.503 +            sprintf(ret, "%s_%s", lang, ctry);
 231.504 +        }
 231.505      } else {
 231.506 -        return NULL;
 231.507 +        strcpy(ret, lang);
 231.508      }
 231.509 +
 231.510 +    free(lang);
 231.511 +    free(ctry);
 231.512 +    free(vrnt);
 231.513 +    free(enc);
 231.514 +
 231.515 +    return ret;
 231.516  }
 231.517  
 231.518  /*
 231.519 @@ -644,6 +289,58 @@
 231.520      return NULL;
 231.521  }
 231.522  
 231.523 +#define PROPSIZE 3      // two-letter + null terminator
 231.524 +static void
 231.525 +SetupI18nProps(LCID lcid, char** language, char** country,
 231.526 +               char** variant, char** encoding) {
 231.527 +    /* country */
 231.528 +    *country = malloc(PROPSIZE);
 231.529 +    if (GetLocaleInfo(lcid,
 231.530 +                      LOCALE_SISO3166CTRYNAME, *country, PROPSIZE) == 0) {
 231.531 +        (*country)[0] = '\0';
 231.532 +    }
 231.533 +
 231.534 +    /* language */
 231.535 +    *language = malloc(PROPSIZE);
 231.536 +    if (lcid == 0x46c) {
 231.537 +        /* Windows returns non-existent language code "ns" for Northern Sotho.
 231.538 +         * Defaults to en_US
 231.539 +         */
 231.540 +        strcpy(*language, "en");
 231.541 +        strcpy(*country, "US");
 231.542 +    } else if (GetLocaleInfo(lcid,
 231.543 +                      LOCALE_SISO639LANGNAME, *language, PROPSIZE) == 0) {
 231.544 +        if (lcid == 0x465) {
 231.545 +            /* for some reason, Windows returns "div" for this Divehi LCID, even though
 231.546 +             * there is a two letter language code "dv".  Tweak it here.
 231.547 +             */
 231.548 +            strcpy(*language, "dv");
 231.549 +            strcpy(*country, "MV");
 231.550 +        } else {
 231.551 +            /* defaults to en_US */
 231.552 +            strcpy(*language, "en");
 231.553 +            strcpy(*country, "US");
 231.554 +        }
 231.555 +    }
 231.556 +
 231.557 +    /* variant */
 231.558 +    *variant = malloc(PROPSIZE);
 231.559 +    (*variant)[0] = '\0';
 231.560 +
 231.561 +    /* handling for Norwegian */
 231.562 +    if (strcmp(*language, "nb") == 0) {
 231.563 +        strcpy(*language, "no");
 231.564 +        strcpy(*country , "NO");
 231.565 +    } else if (strcmp(*language, "nn") == 0) {
 231.566 +        strcpy(*language, "no");
 231.567 +        strcpy(*country , "NO");
 231.568 +        strcpy(*variant, "NY");
 231.569 +    }
 231.570 +
 231.571 +    /* encoding */
 231.572 +    *encoding = getEncodingInternal(lcid);
 231.573 +}
 231.574 +
 231.575  java_props_t *
 231.576  GetJavaProperties(JNIEnv* env)
 231.577  {
 231.578 @@ -876,62 +573,31 @@
 231.579           * query the system for the current system default locale
 231.580           * (which is a Windows LCID value),
 231.581           */
 231.582 -        LANGID langID = LANGIDFROMLCID(GetUserDefaultLCID());
 231.583 -        LANGID sysLangID = LANGIDFROMLCID(GetSystemDefaultLCID());
 231.584 +        LCID userDefaultLCID = GetUserDefaultLCID();
 231.585 +        LCID systemDefaultLCID = GetSystemDefaultLCID();
 231.586 +        LCID userDefaultUILang = GetUserDefaultUILanguage();
 231.587  
 231.588          {
 231.589 -            int index = getLocaleEntryIndex(langID);
 231.590 +            char * display_encoding;
 231.591  
 231.592 -            /*
 231.593 -             * if we didn't find the LCID that the system returned to us,
 231.594 -             * we don't have a Java locale ID that corresponds to it.
 231.595 -             * Fall back on en_US.
 231.596 -             */
 231.597 -            if (index == -1) {
 231.598 -                sprops.language = "en";
 231.599 -                sprops.country = "US";
 231.600 -                sprops.encoding = "Cp1252";
 231.601 -            } else {
 231.602 +            SetupI18nProps(userDefaultUILang,
 231.603 +                           &sprops.language,
 231.604 +                           &sprops.country,
 231.605 +                           &sprops.variant,
 231.606 +                           &display_encoding);
 231.607 +            SetupI18nProps(userDefaultLCID,
 231.608 +                           &sprops.format_language,
 231.609 +                           &sprops.format_country,
 231.610 +                           &sprops.format_variant,
 231.611 +                           &sprops.encoding);
 231.612 +            SetupI18nProps(userDefaultUILang,
 231.613 +                           &sprops.display_language,
 231.614 +                           &sprops.display_country,
 231.615 +                           &sprops.display_variant,
 231.616 +                           &display_encoding);
 231.617  
 231.618 -                /* otherwise, look up the corresponding Java locale ID from
 231.619 -                 * the list of Java locale IDs and set up the system properties
 231.620 -                 * accordingly.
 231.621 -                 */
 231.622 -
 231.623 -                char* lang;
 231.624 -                char* ctry;
 231.625 -                char* variant;
 231.626 -
 231.627 -                lang = strdup(langIDMap[index].javaID);
 231.628 -                ctry = lang;
 231.629 -
 231.630 -                while (*ctry != '_' && *ctry != 0)
 231.631 -                    ++ctry;
 231.632 -
 231.633 -                if (*ctry == '_') {
 231.634 -                    *ctry++ = 0;
 231.635 -                }
 231.636 -
 231.637 -                variant = ctry;
 231.638 -                while (*variant != '_' && *variant != 0)
 231.639 -                    ++variant;
 231.640 -
 231.641 -                if (*variant == '_') {
 231.642 -                    *variant++ = 0;
 231.643 -                }
 231.644 -
 231.645 -                sprops.language = lang;
 231.646 -                sprops.country = ctry;
 231.647 -                sprops.variant = variant;
 231.648 -                sprops.encoding = getEncodingInternal(index);
 231.649 -            }
 231.650 -            index = getLocaleEntryIndex(sysLangID);
 231.651 -            if (index == -1) {
 231.652 -                sprops.sun_jnu_encoding = "Cp1252";
 231.653 -            } else {
 231.654 -                sprops.sun_jnu_encoding = getEncodingInternal(index);
 231.655 -            }
 231.656 -            if (langID == 0x0c04 && ver.dwMajorVersion == 6) {
 231.657 +            sprops.sun_jnu_encoding = getEncodingInternal(systemDefaultLCID);
 231.658 +            if (LANGIDFROMLCID(userDefaultLCID) == 0x0c04 && ver.dwMajorVersion == 6) {
 231.659                  // MS claims "Vista has built-in support for HKSCS-2004.
 231.660                  // All of the HKSCS-2004 characters have Unicode 4.1.
 231.661                  // PUA code point assignments". But what it really means
   232.1 --- a/src/windows/native/sun/windows/awt_DataTransferer.cpp	Thu Sep 23 17:33:40 2010 -0700
   232.2 +++ b/src/windows/native/sun/windows/awt_DataTransferer.cpp	Fri Sep 24 16:41:32 2010 -0700
   232.3 @@ -201,6 +201,7 @@
   232.4          throw std::bad_alloc();
   232.5      }
   232.6      env->SetByteArrayRegion(retval, 0, length, (jbyte *)encoding);
   232.7 +    free((void *)encoding);
   232.8      return retval;
   232.9  }
  232.10  
   233.1 --- a/src/windows/native/sun/windows/awt_InputMethod.cpp	Thu Sep 23 17:33:40 2010 -0700
   233.2 +++ b/src/windows/native/sun/windows/awt_InputMethod.cpp	Fri Sep 24 16:41:32 2010 -0700
   233.3 @@ -296,7 +296,9 @@
   233.4          // so we can reset this flag.
   233.5          g_bUserHasChangedInputLang = FALSE;
   233.6  
   233.7 -        return CreateLocaleObject(env, javaLocaleName);
   233.8 +        jobject ret = CreateLocaleObject(env, javaLocaleName);
   233.9 +        free((void *)javaLocaleName);
  233.10 +        return ret;
  233.11      } else {
  233.12          return NULL;
  233.13      }
  233.14 @@ -323,6 +325,7 @@
  233.15      const char * requested = env->GetStringUTFChars(localeString, &isCopy);
  233.16      if ((current != NULL) && (strcmp(current, requested) == 0)) {
  233.17          env->ReleaseStringUTFChars(localeString, requested);
  233.18 +        free((void *)current);
  233.19          return JNI_TRUE;
  233.20      }
  233.21  
  233.22 @@ -352,6 +355,7 @@
  233.23  
  233.24      env->ReleaseStringUTFChars(localeString, requested);
  233.25      free(hKLList);
  233.26 +    free((void *)current);
  233.27      return retValue;
  233.28  
  233.29      CATCH_BAD_ALLOC_RET(JNI_FALSE);
  233.30 @@ -480,6 +484,7 @@
  233.31          env->SetObjectArrayElement(locales,
  233.32                                     current,
  233.33                                     CreateLocaleObject(env, javaLocaleNames[current]));
  233.34 +        free((void *)javaLocaleNames[current]);
  233.35      }
  233.36      DASSERT(!safe_ExceptionOccurred(env));
  233.37  
   234.1 --- a/src/windows/native/sun/windows/awt_MenuItem.cpp	Thu Sep 23 17:33:40 2010 -0700
   234.2 +++ b/src/windows/native/sun/windows/awt_MenuItem.cpp	Fri Sep 24 16:41:32 2010 -0700
   234.3 @@ -794,6 +794,11 @@
   234.4      jobject jitem = GetTarget(env);
   234.5      jstring label  =
   234.6          (jstring)(env)->GetObjectField(jitem, AwtMenuItem::labelID);
   234.7 +    if (label == NULL) {
   234.8 +        env->DeleteLocalRef(label);
   234.9 +        env->DeleteLocalRef(jitem);
  234.10 +        return FALSE; //separator must has '-' as label.
  234.11 +    }
  234.12      LPCWSTR labelW = JNU_GetStringPlatformChars(env, label, NULL);
  234.13      BOOL isSeparator = (labelW && (wcscmp(labelW, L"-") == 0));
  234.14      JNU_ReleaseStringPlatformChars(env, label, labelW);
   235.1 --- a/src/windows/native/sun/windows/awt_TextComponent.h	Thu Sep 23 17:33:40 2010 -0700
   235.2 +++ b/src/windows/native/sun/windows/awt_TextComponent.h	Fri Sep 24 16:41:32 2010 -0700
   235.3 @@ -113,8 +113,6 @@
   235.4      // Used to prevent untrusted code from synthesizing a WM_PASTE message
   235.5      // by posting a <CTRL>-V KeyEvent
   235.6      BOOL    m_synthetic;
   235.7 -    virtual void EditSetSel(CHARRANGE &cr) = 0;
   235.8 -    virtual void EditGetSel(CHARRANGE &cr) = 0;
   235.9      virtual LONG EditGetCharFromPos(POINT& pt) = 0;
  235.10  
  235.11  private:
   236.1 --- a/src/windows/native/sun/windows/awt_TextField.cpp	Thu Sep 23 17:33:40 2010 -0700
   236.2 +++ b/src/windows/native/sun/windows/awt_TextField.cpp	Fri Sep 24 16:41:32 2010 -0700
   236.3 @@ -41,7 +41,9 @@
   236.4   * AwtTextField methods
   236.5   */
   236.6  
   236.7 -AwtTextField::AwtTextField() {
   236.8 +AwtTextField::AwtTextField()
   236.9 +    : m_initialRescrollFlag( true )
  236.10 +{
  236.11  }
  236.12  
  236.13  /* Create a new AwtTextField object and window.   */
  236.14 @@ -116,10 +118,6 @@
  236.15      SendMessage(EM_SETSEL, cr.cpMin, cr.cpMax);
  236.16  }
  236.17  
  236.18 -void AwtTextField::EditGetSel(CHARRANGE &cr) {
  236.19 -    SendMessage(EM_SETSEL, reinterpret_cast<WPARAM>(&cr.cpMin), reinterpret_cast<LPARAM>(&cr.cpMax));
  236.20 -}
  236.21 -
  236.22  LONG AwtTextField::EditGetCharFromPos(POINT& pt) {
  236.23      return static_cast<LONG>(SendMessage(EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y)));
  236.24  }
  236.25 @@ -153,11 +151,9 @@
  236.26       * The workaround also allows us to implement synthetic focus mechanism.
  236.27       */
  236.28      if (IsFocusingMouseMessage(msg)) {
  236.29 -        CHARRANGE cr;
  236.30  
  236.31          LONG lCurPos = EditGetCharFromPos(msg->pt);
  236.32  
  236.33 -        EditGetSel(cr);
  236.34          /*
  236.35           * NOTE: Plain EDIT control always clears selection on mouse
  236.36           * button press. We are clearing the current selection only if
  236.37 @@ -174,6 +170,7 @@
  236.38              SetStartSelectionPos(lCurPos);
  236.39              SetEndSelectionPos(lCurPos);
  236.40          }
  236.41 +        CHARRANGE cr;
  236.42          cr.cpMin = GetStartSelectionPos();
  236.43          cr.cpMax = GetEndSelectionPos();
  236.44          EditSetSel(cr);
  236.45 @@ -310,6 +307,47 @@
  236.46      delete secs;
  236.47  }
  236.48  
  236.49 +void AwtTextField::Reshape(int x, int y, int w, int h)
  236.50 +{
  236.51 +    AwtTextComponent::Reshape( x, y, w, h );
  236.52 +
  236.53 +    // Another option would be to call this
  236.54 +    // after WM_SIZE notification is handled
  236.55 +    initialRescroll();
  236.56 +}
  236.57 +
  236.58 +
  236.59 +// Windows' Edit control features:
  236.60 +// (i) if text selection is set while control's width or height is 0,
  236.61 +//   text is scrolled oddly.
  236.62 +// (ii) if control's size is changed, text seems never be automatically
  236.63 +//   rescrolled.
  236.64 +//
  236.65 +// This method is designed for the following scenario: AWT spawns Edit
  236.66 +// control with 0x0 dimensions, then sets text selection, then resizes the
  236.67 +// control (couple of times). This might cause text appear undesirably scrolled.
  236.68 +// So we reset/set selection again to rescroll text. (see also CR 6480547)
  236.69 +void AwtTextField::initialRescroll()
  236.70 +{
  236.71 +    if( ! m_initialRescrollFlag ) {
  236.72 +        return;
  236.73 +    }
  236.74 +
  236.75 +    ::RECT r;
  236.76 +    BOOL ok = ::GetClientRect( GetHWnd(), &r );
  236.77 +    if( ! ok || r.right==0 || r.bottom==0 ) {
  236.78 +        return;
  236.79 +    }
  236.80 +
  236.81 +    m_initialRescrollFlag = false;
  236.82 +
  236.83 +    DWORD start, end;
  236.84 +    SendMessage( EM_GETSEL, (WPARAM)&start, (LPARAM)&end );
  236.85 +    SendMessage( EM_SETSEL, (WPARAM)0, (LPARAM)0 );
  236.86 +    SendMessage( EM_SETSEL, (WPARAM)start, (LPARAM)end );
  236.87 +}
  236.88 +
  236.89 +
  236.90  /************************************************************************
  236.91   * WTextFieldPeer native methods
  236.92   */
   237.1 --- a/src/windows/native/sun/windows/awt_TextField.h	Thu Sep 23 17:33:40 2010 -0700
   237.2 +++ b/src/windows/native/sun/windows/awt_TextField.h	Fri Sep 24 16:41:32 2010 -0700
   237.3 @@ -55,9 +55,14 @@
   237.4      static void _SetEchoChar(void *param);
   237.5  
   237.6    protected:
   237.7 +    LONG EditGetCharFromPos(POINT& pt);
   237.8 +    virtual void Reshape(int x, int y, int w, int h);
   237.9 +
  237.10 +private:
  237.11      void EditSetSel(CHARRANGE &cr);
  237.12 -    void EditGetSel(CHARRANGE &cr);
  237.13 -    LONG EditGetCharFromPos(POINT& pt);
  237.14 +    void initialRescroll();
  237.15 +
  237.16 +    bool m_initialRescrollFlag;
  237.17  };
  237.18  
  237.19  #endif /* AWT_TEXTFIELD_H */
   238.1 --- a/src/windows/native/sun/windows/awt_Window.h	Thu Sep 23 17:33:40 2010 -0700
   238.2 +++ b/src/windows/native/sun/windows/awt_Window.h	Fri Sep 24 16:41:32 2010 -0700
   238.3 @@ -1,5 +1,5 @@
   238.4  /*
   238.5 - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
   238.6 + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
   238.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   238.8   *
   238.9   * This code is free software; you can redistribute it and/or modify it
  238.10 @@ -193,12 +193,17 @@
  238.11  
  238.12      // Execute on Toolkit only.
  238.13      INLINE static LRESULT SynthesizeWmActivate(BOOL doActivate, HWND targetHWnd, HWND oppositeHWnd) {
  238.14 -        if (::IsWindowVisible(targetHWnd)) {
  238.15 -            return ::SendMessage(targetHWnd, WM_ACTIVATE,
  238.16 -                                 MAKEWPARAM(doActivate ? WA_ACTIVE : WA_INACTIVE, FALSE),
  238.17 -                                 (LPARAM) oppositeHWnd);
  238.18 +        if (doActivate &&
  238.19 +            (!::IsWindowVisible(targetHWnd) || ::IsIconic(::GetAncestor(targetHWnd, GA_ROOT))))
  238.20 +        {
  238.21 +            // The activation is rejected if either:
  238.22 +            // - The toplevel is not visible
  238.23 +            // - The toplevel (or its embedder) is minimised
  238.24 +            return 1;
  238.25          }
  238.26 -        return 1; // if not processed
  238.27 +        return ::SendMessage(targetHWnd, WM_ACTIVATE,
  238.28 +                             MAKEWPARAM(doActivate ? WA_ACTIVE : WA_INACTIVE, FALSE),
  238.29 +                             (LPARAM) oppositeHWnd);
  238.30      }
  238.31  
  238.32      void moveToDefaultLocation(); /* moves Window to X,Y specified by Window Manger */
   239.1 --- a/test/ProblemList.txt	Thu Sep 23 17:33:40 2010 -0700
   239.2 +++ b/test/ProblemList.txt	Fri Sep 24 16:41:32 2010 -0700
   239.3 @@ -201,9 +201,6 @@
   239.4  # Windows X64, RuntimeException: MyThread expected to have RUNNABLE but got WAITING
   239.5  java/lang/Thread/ThreadStateTest.java				generic-all
   239.6  
   239.7 -# Timeout on windows 64bit 
   239.8 -java/lang/ClassLoader/deadlock/TestCrossDelegate.sh		generic-all
   239.9 -
  239.10  ############################################################################
  239.11  
  239.12  # jdk_management
   240.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   240.2 +++ b/test/com/oracle/net/Sanity.java	Fri Sep 24 16:41:32 2010 -0700
   240.3 @@ -0,0 +1,142 @@
   240.4 +/*
   240.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   240.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   240.7 + *
   240.8 + * This code is free software; you can redistribute it and/or modify it
   240.9 + * under the terms of the GNU General Public License version 2 only, as
  240.10 + * published by the Free Software Foundation.
  240.11 + *
  240.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  240.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  240.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  240.15 + * version 2 for more details (a copy is included in the LICENSE file that
  240.16 + * accompanied this code).
  240.17 + *
  240.18 + * You should have received a copy of the GNU General Public License version
  240.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  240.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  240.21 + *
  240.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  240.23 + * or visit www.oracle.com if you need additional information or have any
  240.24 + * questions.
  240.25 + */
  240.26 +
  240.27 +import com.oracle.net.Sdp;
  240.28 +
  240.29 +import java.net.*;
  240.30 +import java.io.*;
  240.31 +import java.nio.channels.*;
  240.32 +import java.util.*;
  240.33 +
  240.34 +/**
  240.35 + * Exercise com.oracle.net.Sdp with each IP address plumbed to InfiniBand
  240.36 + * interfaces listed in a given file.
  240.37 + */
  240.38 +
  240.39 +public class Sanity {
  240.40 +    public static void main(String[] args) throws Exception {
  240.41 +        // The file is a list of interfaces to test.
  240.42 +        Scanner s = new Scanner(new File(args[0]));
  240.43 +        try {
  240.44 +            while (s.hasNextLine()) {
  240.45 +                String link = s.nextLine();
  240.46 +                NetworkInterface ni = NetworkInterface.getByName(link);
  240.47 +                if (ni != null) {
  240.48 +                    Enumeration<InetAddress> addrs = ni.getInetAddresses();
  240.49 +                    while (addrs.hasMoreElements()) {
  240.50 +                        InetAddress addr = addrs.nextElement();
  240.51 +                        System.out.format("Testing %s: %s\n", link, addr.getHostAddress());
  240.52 +                        test(addr);
  240.53 +                    }
  240.54 +                }
  240.55 +            }
  240.56 +        } finally {
  240.57 +            s.close();
  240.58 +        }
  240.59 +    }
  240.60 +
  240.61 +    static void test(InetAddress addr) throws Exception {
  240.62 +        // Test SocketChannel and ServerSocketChannel
  240.63 +        ServerSocketChannel ssc = Sdp.openServerSocketChannel();
  240.64 +        try {
  240.65 +            ssc.socket().bind(new InetSocketAddress(addr, 0));
  240.66 +            int port = ssc.socket().getLocalPort();
  240.67 +
  240.68 +            // SocketChannel.connect (implicit bind)
  240.69 +            SocketChannel client = Sdp.openSocketChannel();
  240.70 +            try {
  240.71 +                client.connect(new InetSocketAddress(addr, port));
  240.72 +                SocketChannel peer = ssc.accept();
  240.73 +                try {
  240.74 +                    testConnection(Channels.newOutputStream(client),
  240.75 +                                   Channels.newInputStream(peer));
  240.76 +                } finally {
  240.77 +                    peer.close();
  240.78 +                }
  240.79 +            } finally {
  240.80 +                client.close();
  240.81 +            }
  240.82 +
  240.83 +            // SocketChannel.connect (explicit bind)
  240.84 +            client = Sdp.openSocketChannel();
  240.85 +            try {
  240.86 +                client.socket().bind(new InetSocketAddress(addr, 0));
  240.87 +                client.connect(new InetSocketAddress(addr, port));
  240.88 +                ssc.accept().close();
  240.89 +            } finally {
  240.90 +                client.close();
  240.91 +            }
  240.92 +        } finally {
  240.93 +            ssc.close();
  240.94 +        }
  240.95 +
  240.96 +        // Test Socket and ServerSocket
  240.97 +        ServerSocket ss = Sdp.openServerSocket();
  240.98 +        try {
  240.99 +            ss.bind(new InetSocketAddress(addr, 0));
 240.100 +            int port = ss.getLocalPort();
 240.101 +
 240.102 +            // Socket.connect (implicit bind)
 240.103 +            Socket s = Sdp.openSocket();
 240.104 +            try {
 240.105 +                s.connect(new InetSocketAddress(addr, port));
 240.106 +                Socket peer = ss.accept();
 240.107 +                try {
 240.108 +                    testConnection(s.getOutputStream(), peer.getInputStream());
 240.109 +                } finally {
 240.110 +                    peer.close();
 240.111 +                }
 240.112 +            } finally {
 240.113 +                s.close();
 240.114 +            }
 240.115 +
 240.116 +            // Socket.connect (explicit bind)
 240.117 +            s = Sdp.openSocket();
 240.118 +            try {
 240.119 +                s.bind(new InetSocketAddress(addr, 0));
 240.120 +                s.connect(new InetSocketAddress(addr, port));
 240.121 +                ss.accept().close();
 240.122 +            } finally {
 240.123 +                s.close();
 240.124 +            }
 240.125 +        } finally {
 240.126 +            ss.close();
 240.127 +        }
 240.128 +    }
 240.129 +
 240.130 +    static void testConnection(OutputStream out, InputStream in)
 240.131 +        throws IOException
 240.132 +    {
 240.133 +        byte[] msg = "hello".getBytes();
 240.134 +        out.write(msg);
 240.135 +
 240.136 +        byte[] ba = new byte[100];
 240.137 +        int nread = 0;
 240.138 +        while (nread < msg.length) {
 240.139 +            int n = in.read(ba);
 240.140 +            if (n < 0)
 240.141 +                throw new IOException("EOF not expected!");
 240.142 +            nread += n;
 240.143 +        }
 240.144 +    }
 240.145 +}
   241.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   241.2 +++ b/test/com/oracle/net/sanity.sh	Fri Sep 24 16:41:32 2010 -0700
   241.3 @@ -0,0 +1,66 @@
   241.4 +#
   241.5 +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   241.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   241.7 +#
   241.8 +# This code is free software; you can redistribute it and/or modify it
   241.9 +# under the terms of the GNU General Public License version 2 only, as
  241.10 +# published by the Free Software Foundation.
  241.11 +#
  241.12 +# This code is distributed in the hope that it will be useful, but WITHOUT
  241.13 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  241.14 +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  241.15 +# version 2 for more details (a copy is included in the LICENSE file that
  241.16 +# accompanied this code).
  241.17 +#
  241.18 +# You should have received a copy of the GNU General Public License version
  241.19 +# 2 along with this work; if not, write to the Free Software Foundation,
  241.20 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  241.21 +#
  241.22 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  241.23 +# or visit www.oracle.com if you need additional information or have any
  241.24 +# questions.
  241.25 +#
  241.26 +
  241.27 +# @test
  241.28 +# @bug 6965072
  241.29 +# @summary Unit test for SDP support
  241.30 +# @build  Sanity
  241.31 +# @run shell sanity.sh
  241.32 +
  241.33 +IB_LINKS=ib.links
  241.34 +
  241.35 +OS=`uname -s`
  241.36 +case "$OS" in
  241.37 +    SunOS )
  241.38 +        /usr/sbin/dladm show-part -o LINK -p > ${IB_LINKS}
  241.39 +        if [ $? != 0 ]; then
  241.40 +            echo "Unable to get InfiniBand parition link information"
  241.41 +            exit 0
  241.42 +        fi
  241.43 +        ;;
  241.44 +    Linux )
  241.45 +        if [ ! -f /proc/net/sdp ]; then
  241.46 +            echo "InfiniBand SDP module not installed"
  241.47 +            exit 0
  241.48 +        fi
  241.49 +        egrep "^[ \t]+ib" /proc/net/dev|cut -d':' -f1|tr -d '\t ' > ${IB_LINKS}
  241.50 +        ;; 
  241.51 +    * )
  241.52 +        echo "This test only runs on Solaris or Linux"
  241.53 +        exit 0
  241.54 +        ;;
  241.55 +esac
  241.56 +
  241.57 +if [ -z "$TESTJAVA" ]; then
  241.58 +    JAVA=java
  241.59 +    TESTCLASSES=.
  241.60 +    TESTSRC=.
  241.61 +else
  241.62 +    JAVA="${TESTJAVA}/bin/java"
  241.63 +fi
  241.64 +
  241.65 +CLASSPATH=${TESTCLASSES}:${TESTSRC}
  241.66 +export CLASSPATH
  241.67 +
  241.68 +# Run sanity test (IPv4-only for now)
  241.69 +$JAVA -Djava.net.preferIPv4Stack=true Sanity ${IB_LINKS}
   242.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   242.2 +++ b/test/com/sun/security/sasl/ntlm/NTLMTest.java	Fri Sep 24 16:41:32 2010 -0700
   242.3 @@ -0,0 +1,416 @@
   242.4 +/*
   242.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   242.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   242.7 + *
   242.8 + * This code is free software; you can redistribute it and/or modify it
   242.9 + * under the terms of the GNU General Public License version 2 only, as
  242.10 + * published by the Free Software Foundation.
  242.11 + *
  242.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  242.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  242.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  242.15 + * version 2 for more details (a copy is included in the LICENSE file that
  242.16 + * accompanied this code).
  242.17 + *
  242.18 + * You should have received a copy of the GNU General Public License version
  242.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  242.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  242.21 + *
  242.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  242.23 + * or visit www.oracle.com if you need additional information or have any
  242.24 + * questions.
  242.25 + */
  242.26 +
  242.27 +/*
  242.28 + * @test
  242.29 + * @bug 6911951
  242.30 + * @summary NTLM should be a supported Java SASL mechanism
  242.31 + */
  242.32 +import java.io.IOException;
  242.33 +import javax.security.sasl.*;
  242.34 +import javax.security.auth.callback.*;
  242.35 +import java.util.*;
  242.36 +
  242.37 +import com.sun.security.ntlm.NTLMException;
  242.38 +
  242.39 +public class NTLMTest {
  242.40 +
  242.41 +    private static final String MECH = "NTLM";
  242.42 +    private static final String REALM = "REALM";
  242.43 +    private static final String PROTOCOL = "jmx";
  242.44 +    private static final byte[] EMPTY = new byte[0];
  242.45 +
  242.46 +    private static final String USER1 = "dummy";
  242.47 +    private static final char[] PASS1 = "bogus".toCharArray();
  242.48 +    private static final String USER2 = "foo";
  242.49 +    private static final char[] PASS2 = "bar".toCharArray();
  242.50 +
  242.51 +    private static final Map<String,char[]> maps =
  242.52 +            new HashMap<String,char[]>();
  242.53 +    static {
  242.54 +        maps.put(USER1, PASS1);
  242.55 +        maps.put(USER2, PASS2);
  242.56 +    }
  242.57 +
  242.58 +    static char[] getPass(String d, String u) {
  242.59 +        if (!d.equals(REALM)) return null;
  242.60 +        return maps.get(u);
  242.61 +    }
  242.62 +
  242.63 +    public static void main(String[] args) throws Exception {
  242.64 +
  242.65 +        checkAuthOnly();
  242.66 +        checkClientNameOverride();
  242.67 +        checkServerDomainOverride();
  242.68 +        checkClientDomainOverride();
  242.69 +        checkVersions();
  242.70 +        checkClientHostname();
  242.71 +    }
  242.72 +
  242.73 +    static void checkVersions() throws Exception {
  242.74 +        // Server accepts all version
  242.75 +        checkVersion(null, null);
  242.76 +        checkVersion("LM/NTLM", null);
  242.77 +        checkVersion("LM", null);
  242.78 +        checkVersion("NTLM", null);
  242.79 +        checkVersion("NTLM2", null);
  242.80 +        checkVersion("LMv2/NTLMv2", null);
  242.81 +        checkVersion("LMv2", null);
  242.82 +        checkVersion("NTLMv2", null);
  242.83 +
  242.84 +        // Client's default version is LMv2
  242.85 +        checkVersion(null, "LMv2");
  242.86 +
  242.87 +        // Also works if they specified identical versions
  242.88 +        checkVersion("LM/NTLM", "LM");
  242.89 +        checkVersion("LM", "LM");
  242.90 +        checkVersion("NTLM", "LM");
  242.91 +        checkVersion("NTLM2", "NTLM2");
  242.92 +        checkVersion("LMv2/NTLMv2", "LMv2");
  242.93 +        checkVersion("LMv2", "LMv2");
  242.94 +        checkVersion("NTLMv2", "LMv2");
  242.95 +
  242.96 +        // But should not work if different
  242.97 +        try {
  242.98 +            checkVersion("LM/NTLM", "LMv2");
  242.99 +            throw new Exception("Should not succeed");
 242.100 +        } catch (SaslException se) {
 242.101 +            NTLMException ne = (NTLMException)se.getCause();
 242.102 +            if (ne.errorCode() != NTLMException.AUTH_FAILED) {
 242.103 +                throw new Exception("Failed false");
 242.104 +            }
 242.105 +        }
 242.106 +        try {
 242.107 +            checkVersion("LMv2/NTLMv2", "LM");
 242.108 +            throw new Exception("Should not succeed");
 242.109 +        } catch (SaslException se) {
 242.110 +            NTLMException ne = (NTLMException)se.getCause();
 242.111 +            if (ne.errorCode() != NTLMException.AUTH_FAILED) {
 242.112 +                throw new Exception("Failed false");
 242.113 +            }
 242.114 +        }
 242.115 +
 242.116 +    }
 242.117 +
 242.118 +    /**
 242.119 +     * A test on version matching
 242.120 +     * @param vc ntlm version specified for client
 242.121 +     * @param vs ntlm version specified for server
 242.122 +     * @throws Exception
 242.123 +     */
 242.124 +    private static void checkVersion(String vc, String vs) throws Exception {
 242.125 +        Map<String,Object> pc = new HashMap<>();
 242.126 +        pc.put("com.sun.security.sasl.ntlm.version", vc);
 242.127 +        Map<String,Object> ps = new HashMap<>();
 242.128 +        ps.put("com.sun.security.sasl.ntlm.version", vs);
 242.129 +        SaslClient clnt = Sasl.createSaslClient(
 242.130 +                new String[]{MECH}, USER1, PROTOCOL, null, pc,
 242.131 +                new CallbackHandler() {
 242.132 +                    public void handle(Callback[] callbacks)
 242.133 +                            throws IOException, UnsupportedCallbackException {
 242.134 +                        for (Callback cb: callbacks) {
 242.135 +                            if (cb instanceof NameCallback) {
 242.136 +                                NameCallback ncb = (NameCallback)cb;
 242.137 +                                ncb.setName(ncb.getDefaultName());
 242.138 +                            } else if (cb instanceof PasswordCallback) {
 242.139 +                                ((PasswordCallback)cb).setPassword(PASS1);
 242.140 +                            }
 242.141 +                        }
 242.142 +                    }
 242.143 +                });
 242.144 +
 242.145 +        SaslServer srv = Sasl.createSaslServer(MECH, PROTOCOL, REALM, ps,
 242.146 +                new CallbackHandler() {
 242.147 +                    public void handle(Callback[] callbacks)
 242.148 +                            throws IOException, UnsupportedCallbackException {
 242.149 +                        String domain = null, name = null;
 242.150 +                        PasswordCallback pcb = null;
 242.151 +                        for (Callback cb: callbacks) {
 242.152 +                            if (cb instanceof NameCallback) {
 242.153 +                                name = ((NameCallback)cb).getDefaultName();
 242.154 +                            } else if (cb instanceof RealmCallback) {
 242.155 +                                domain = ((RealmCallback)cb).getDefaultText();
 242.156 +                            } else if (cb instanceof PasswordCallback) {
 242.157 +                                pcb = (PasswordCallback)cb;
 242.158 +                            }
 242.159 +                        }
 242.160 +                        if (pcb != null) {
 242.161 +                            pcb.setPassword(getPass(domain, name));
 242.162 +                        }
 242.163 +                    }
 242.164 +                });
 242.165 +
 242.166 +        handshake(clnt, srv);
 242.167 +    }
 242.168 +
 242.169 +    private static void checkClientHostname() throws Exception {
 242.170 +        Map<String,Object> pc = new HashMap<>();
 242.171 +        pc.put("com.sun.security.sasl.ntlm.hostname", "this.is.com");
 242.172 +        SaslClient clnt = Sasl.createSaslClient(
 242.173 +                new String[]{MECH}, USER1, PROTOCOL, null, pc,
 242.174 +                new CallbackHandler() {
 242.175 +                    public void handle(Callback[] callbacks)
 242.176 +                            throws IOException, UnsupportedCallbackException {
 242.177 +                        for (Callback cb: callbacks) {
 242.178 +                            if (cb instanceof NameCallback) {
 242.179 +                                NameCallback ncb = (NameCallback)cb;
 242.180 +                                ncb.setName(ncb.getDefaultName());
 242.181 +                            } else if (cb instanceof PasswordCallback) {
 242.182 +                                ((PasswordCallback)cb).setPassword(PASS1);
 242.183 +                            }
 242.184 +                        }
 242.185 +                    }
 242.186 +                });
 242.187 +
 242.188 +        SaslServer srv = Sasl.createSaslServer(MECH, PROTOCOL, REALM, null,
 242.189 +                new CallbackHandler() {
 242.190 +                    public void handle(Callback[] callbacks)
 242.191 +                            throws IOException, UnsupportedCallbackException {
 242.192 +                        String domain = null, name = null;
 242.193 +                        PasswordCallback pcb = null;
 242.194 +                        for (Callback cb: callbacks) {
 242.195 +                            if (cb instanceof NameCallback) {
 242.196 +                                name = ((NameCallback)cb).getDefaultName();
 242.197 +                            } else if (cb instanceof RealmCallback) {
 242.198 +                                domain = ((RealmCallback)cb).getDefaultText();
 242.199 +                            } else if (cb instanceof PasswordCallback) {
 242.200 +                                pcb = (PasswordCallback)cb;
 242.201 +                            }
 242.202 +                        }
 242.203 +                        if (pcb != null) {
 242.204 +                            pcb.setPassword(getPass(domain, name));
 242.205 +                        }
 242.206 +                    }
 242.207 +                });
 242.208 +
 242.209 +        handshake(clnt, srv);
 242.210 +        if (!"this.is.com".equals(
 242.211 +                srv.getNegotiatedProperty("com.sun.security.sasl.ntlm.hostname"))) {
 242.212 +            throw new Exception("Hostname not trasmitted to server");
 242.213 +        }
 242.214 +    }
 242.215 +
 242.216 +    /**
 242.217 +     * Client realm override, but finally overridden by server response
 242.218 +     */
 242.219 +    private static void checkClientDomainOverride() throws Exception {
 242.220 +        SaslClient clnt = Sasl.createSaslClient(
 242.221 +                new String[]{MECH}, USER1, PROTOCOL, "ANOTHERREALM", null,
 242.222 +                new CallbackHandler() {
 242.223 +                    public void handle(Callback[] callbacks)
 242.224 +                            throws IOException, UnsupportedCallbackException {
 242.225 +                        for (Callback cb: callbacks) {
 242.226 +                            if (cb instanceof NameCallback) {
 242.227 +                                NameCallback ncb = (NameCallback)cb;
 242.228 +                                ncb.setName(ncb.getDefaultName());
 242.229 +                            } else if(cb instanceof RealmCallback) {
 242.230 +                                RealmCallback dcb = (RealmCallback)cb;
 242.231 +                                dcb.setText("THIRDDOMAIN");
 242.232 +                            } else if (cb instanceof PasswordCallback) {
 242.233 +                                ((PasswordCallback)cb).setPassword(PASS1);
 242.234 +                            }
 242.235 +                        }
 242.236 +                    }
 242.237 +                });
 242.238 +
 242.239 +        SaslServer srv = Sasl.createSaslServer(MECH, PROTOCOL, REALM, null,
 242.240 +                new CallbackHandler() {
 242.241 +                    public void handle(Callback[] callbacks)
 242.242 +                            throws IOException, UnsupportedCallbackException {
 242.243 +                        String domain = null, name = null;
 242.244 +                        PasswordCallback pcb = null;
 242.245 +                        for (Callback cb: callbacks) {
 242.246 +                            if (cb instanceof NameCallback) {
 242.247 +                                name = ((NameCallback)cb).getDefaultName();
 242.248 +                            } else if (cb instanceof RealmCallback) {
 242.249 +                                domain = ((RealmCallback)cb).getDefaultText();
 242.250 +                            } else if (cb instanceof PasswordCallback) {
 242.251 +                                pcb = (PasswordCallback)cb;
 242.252 +                            }
 242.253 +                        }
 242.254 +                        if (pcb != null) {
 242.255 +                            pcb.setPassword(getPass(domain, name));
 242.256 +                        }
 242.257 +                    }
 242.258 +                });
 242.259 +
 242.260 +        handshake(clnt, srv);
 242.261 +    }
 242.262 +
 242.263 +    /**
 242.264 +     * Client side user name provided in callback.
 242.265 +     * @throws Exception
 242.266 +     */
 242.267 +    private static void checkClientNameOverride() throws Exception {
 242.268 +        SaslClient clnt = Sasl.createSaslClient(
 242.269 +                new String[]{MECH}, null, PROTOCOL, null, null,
 242.270 +                new CallbackHandler() {
 242.271 +                    public void handle(Callback[] callbacks)
 242.272 +                            throws IOException, UnsupportedCallbackException {
 242.273 +                        for (Callback cb: callbacks) {
 242.274 +                            if (cb instanceof NameCallback) {
 242.275 +                                NameCallback ncb = (NameCallback)cb;
 242.276 +                                ncb.setName(USER1);
 242.277 +                            } else if (cb instanceof PasswordCallback) {
 242.278 +                                ((PasswordCallback)cb).setPassword(PASS1);
 242.279 +                            }
 242.280 +                        }
 242.281 +                    }
 242.282 +                });
 242.283 +
 242.284 +        SaslServer srv = Sasl.createSaslServer(MECH, PROTOCOL, REALM, null,
 242.285 +                new CallbackHandler() {
 242.286 +                    public void handle(Callback[] callbacks)
 242.287 +                            throws IOException, UnsupportedCallbackException {
 242.288 +                        String domain = null, name = null;
 242.289 +                        PasswordCallback pcb = null;
 242.290 +                        for (Callback cb: callbacks) {
 242.291 +                            if (cb instanceof NameCallback) {
 242.292 +                                name = ((NameCallback)cb).getDefaultName();
 242.293 +                            } else if (cb instanceof RealmCallback) {
 242.294 +                                domain = ((RealmCallback)cb).getDefaultText();
 242.295 +                            } else if (cb instanceof PasswordCallback) {
 242.296 +                                pcb = (PasswordCallback)cb;
 242.297 +                            }
 242.298 +                        }
 242.299 +                        if (pcb != null) {
 242.300 +                            pcb.setPassword(getPass(domain, name));
 242.301 +                        }
 242.302 +                    }
 242.303 +                });
 242.304 +
 242.305 +        handshake(clnt, srv);
 242.306 +    }
 242.307 +
 242.308 +    /**
 242.309 +     * server side domain provided in props.
 242.310 +     * @throws Exception
 242.311 +     */
 242.312 +    private static void checkServerDomainOverride() throws Exception {
 242.313 +        SaslClient clnt = Sasl.createSaslClient(
 242.314 +                new String[]{MECH}, USER1, PROTOCOL, null, null,
 242.315 +                new CallbackHandler() {
 242.316 +                    public void handle(Callback[] callbacks)
 242.317 +                            throws IOException, UnsupportedCallbackException {
 242.318 +                        for (Callback cb: callbacks) {
 242.319 +                            if (cb instanceof NameCallback) {
 242.320 +                                NameCallback ncb = (NameCallback)cb;
 242.321 +                                ncb.setName(ncb.getDefaultName());
 242.322 +                            } else if (cb instanceof PasswordCallback) {
 242.323 +                                ((PasswordCallback)cb).setPassword(PASS1);
 242.324 +                            }
 242.325 +                        }
 242.326 +                    }
 242.327 +                });
 242.328 +
 242.329 +        Map<String,Object> ps = new HashMap<>();
 242.330 +        ps.put("com.sun.security.sasl.ntlm.domain", REALM);
 242.331 +        SaslServer srv = Sasl.createSaslServer(MECH, PROTOCOL, null, ps,
 242.332 +                new CallbackHandler() {
 242.333 +                    public void handle(Callback[] callbacks)
 242.334 +                            throws IOException, UnsupportedCallbackException {
 242.335 +                        String domain = null, name = null;
 242.336 +                        PasswordCallback pcb = null;
 242.337 +                        for (Callback cb: callbacks) {
 242.338 +                            if (cb instanceof NameCallback) {
 242.339 +                                name = ((NameCallback)cb).getDefaultName();
 242.340 +                            } else if (cb instanceof RealmCallback) {
 242.341 +                                domain = ((RealmCallback)cb).getDefaultText();
 242.342 +                            } else if (cb instanceof PasswordCallback) {
 242.343 +                                pcb = (PasswordCallback)cb;
 242.344 +                            }
 242.345 +                        }
 242.346 +                        if (pcb != null) {
 242.347 +                            pcb.setPassword(getPass(domain, name));
 242.348 +                        }
 242.349 +                    }
 242.350 +                });
 242.351 +
 242.352 +        handshake(clnt, srv);
 242.353 +    }
 242.354 +
 242.355 +    private static void checkAuthOnly() throws Exception {
 242.356 +        Map<String,Object> props = new HashMap<>();
 242.357 +        props.put(Sasl.QOP, "auth-conf");
 242.358 +        try {
 242.359 +            Sasl.createSaslClient(
 242.360 +                    new String[]{MECH}, USER2, PROTOCOL, REALM, props, null);
 242.361 +            throw new Exception("NTLM should not support auth-conf");
 242.362 +        } catch (SaslException se) {
 242.363 +            // Normal
 242.364 +        }
 242.365 +    }
 242.366 +
 242.367 +    private static void handshake(SaslClient clnt, SaslServer srv)
 242.368 +            throws Exception {
 242.369 +        if (clnt == null) {
 242.370 +            throw new IllegalStateException(
 242.371 +                    "Unable to find client impl for " + MECH);
 242.372 +        }
 242.373 +        if (srv == null) {
 242.374 +            throw new IllegalStateException(
 242.375 +                    "Unable to find server impl for " + MECH);
 242.376 +        }
 242.377 +
 242.378 +        byte[] response = (clnt.hasInitialResponse()
 242.379 +                ? clnt.evaluateChallenge(EMPTY) : EMPTY);
 242.380 +        System.out.println("Initial:");
 242.381 +        new sun.misc.HexDumpEncoder().encodeBuffer(response, System.out);
 242.382 +        byte[] challenge;
 242.383 +
 242.384 +        while (!clnt.isComplete() || !srv.isComplete()) {
 242.385 +            challenge = srv.evaluateResponse(response);
 242.386 +            response = null;
 242.387 +            if (challenge != null) {
 242.388 +                System.out.println("Challenge:");
 242.389 +                new sun.misc.HexDumpEncoder().encodeBuffer(challenge, System.out);
 242.390 +                response = clnt.evaluateChallenge(challenge);
 242.391 +            }
 242.392 +            if (response != null) {
 242.393 +                System.out.println("Response:");
 242.394 +                new sun.misc.HexDumpEncoder().encodeBuffer(response, System.out);
 242.395 +            }
 242.396 +        }
 242.397 +
 242.398 +        if (clnt.isComplete() && srv.isComplete()) {
 242.399 +            System.out.println("SUCCESS");
 242.400 +            if (!srv.getAuthorizationID().equals(USER1)) {
 242.401 +                throw new Exception("Not correct user");
 242.402 +            }
 242.403 +        } else {
 242.404 +            throw new IllegalStateException(
 242.405 +                    "FAILURE: mismatched state:"
 242.406 +                    + " client complete? " + clnt.isComplete()
 242.407 +                    + " server complete? " + srv.isComplete());
 242.408 +        }
 242.409 +
 242.410 +        if (!clnt.getNegotiatedProperty(Sasl.QOP).equals("auth") ||
 242.411 +                !srv.getNegotiatedProperty(Sasl.QOP).equals("auth") ||
 242.412 +                !clnt.getNegotiatedProperty(
 242.413 +                    "com.sun.security.sasl.ntlm.domain").equals(REALM)) {
 242.414 +            throw new Exception("Negotiated property error");
 242.415 +        }
 242.416 +        clnt.dispose();
 242.417 +        srv.dispose();
 242.418 +    }
 242.419 +}
   243.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   243.2 +++ b/test/java/awt/EventQueue/SecondaryLoopTest/SecondaryLoopTest.java	Fri Sep 24 16:41:32 2010 -0700
   243.3 @@ -0,0 +1,126 @@
   243.4 +/*
   243.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   243.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   243.7 + *
   243.8 + * This code is free software; you can redistribute it and/or modify it
   243.9 + * under the terms of the GNU General Public License version 2 only, as
  243.10 + * published by the Free Software Foundation.
  243.11 + *
  243.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  243.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  243.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  243.15 + * version 2 for more details (a copy is included in the LICENSE file that
  243.16 + * accompanied this code).
  243.17 + *
  243.18 + * You should have received a copy of the GNU General Public License version
  243.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  243.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  243.21 + *
  243.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  243.23 + * or visit www.oracle.com if you need additional information or have any
  243.24 + * questions.
  243.25 + */
  243.26 +
  243.27 +/*
  243.28 +  @test
  243.29 +  @bug 6949936
  243.30 +  @author Artem Ananiev: area=eventqueue
  243.31 +  @run main/timeout=30 SecondaryLoopTest
  243.32 +*/
  243.33 +
  243.34 +import java.awt.*;
  243.35 +
  243.36 +/**
  243.37 + * Unit test for java.awt.SecondaryLoop implementation
  243.38 + */
  243.39 +public class SecondaryLoopTest {
  243.40 +
  243.41 +    private static volatile boolean loopStarted;
  243.42 +    private static volatile boolean doubleEntered;
  243.43 +    private static volatile boolean loopActive;
  243.44 +    private static volatile boolean eventDispatched;
  243.45 +
  243.46 +    public static void main(String[] args) throws Exception {
  243.47 +        test(true, true);
  243.48 +        test(true, false);
  243.49 +        test(false, true);
  243.50 +        test(false, false);
  243.51 +    }
  243.52 +
  243.53 +    private static void test(final boolean enterEDT, final boolean exitEDT) throws Exception {
  243.54 +        System.out.println("Running test(" + enterEDT + ", " + exitEDT + ")");
  243.55 +        System.err.flush();
  243.56 +        loopStarted = true;
  243.57 +        Runnable enterRun = new Runnable() {
  243.58 +            @Override
  243.59 +            public void run() {
  243.60 +                Toolkit tk = Toolkit.getDefaultToolkit();
  243.61 +                EventQueue eq = tk.getSystemEventQueue();
  243.62 +                final SecondaryLoop loop = eq.createSecondaryLoop();
  243.63 +                doubleEntered = false;
  243.64 +                eventDispatched = false;
  243.65 +                Runnable eventRun = new Runnable() {
  243.66 +                    @Override
  243.67 +                    public void run() {
  243.68 +                        // Let the loop enter
  243.69 +                        sleep(1000);
  243.70 +                        if (loop.enter()) {
  243.71 +                            doubleEntered = true;
  243.72 +                        }
  243.73 +                        eventDispatched = true;
  243.74 +                    }
  243.75 +                };
  243.76 +                EventQueue.invokeLater(eventRun);
  243.77 +                Runnable exitRun = new Runnable() {
  243.78 +                    @Override
  243.79 +                    public void run() {
  243.80 +                        // Let the loop enter and eventRun finish
  243.81 +                        sleep(2000);
  243.82 +                        if (doubleEntered) {
  243.83 +                            // Hopefully, we get here if the loop is entered twice
  243.84 +                            loop.exit();
  243.85 +                        }
  243.86 +                        loop.exit();
  243.87 +                    }
  243.88 +                };
  243.89 +                if (exitEDT) {
  243.90 +                    EventQueue.invokeLater(exitRun);
  243.91 +                } else {
  243.92 +                    new Thread(exitRun).start();
  243.93 +                }
  243.94 +                if (!loop.enter()) {
  243.95 +                    loopStarted = false;
  243.96 +                }
  243.97 +                loopActive = eventDispatched;
  243.98 +            }
  243.99 +        };
 243.100 +        if (enterEDT) {
 243.101 +            EventQueue.invokeAndWait(enterRun);
 243.102 +        } else {
 243.103 +            enterRun.run();
 243.104 +        }
 243.105 +        // Print all the flags before we fail with exception
 243.106 +        System.out.println("    loopStarted = " + loopStarted);
 243.107 +        System.out.println("    doubleEntered = " + doubleEntered);
 243.108 +        System.out.println("    loopActive = " + loopActive);
 243.109 +        System.out.flush();
 243.110 +        if (!loopStarted) {
 243.111 +            throw new RuntimeException("Test FAILED: the secondary loop is not started");
 243.112 +        }
 243.113 +        if (doubleEntered) {
 243.114 +            throw new RuntimeException("Test FAILED: the secondary loop is started twice");
 243.115 +        }
 243.116 +        if (!loopActive) {
 243.117 +            throw new RuntimeException("Test FAILED: the secondary loop exited immediately");
 243.118 +        }
 243.119 +    }
 243.120 +
 243.121 +    private static void sleep(long t) {
 243.122 +        try {
 243.123 +            Thread.sleep(t);
 243.124 +        } catch (InterruptedException e) {
 243.125 +            e.printStackTrace(System.err);
 243.126 +        }
 243.127 +    }
 243.128 +
 243.129 +}
   244.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   244.2 +++ b/test/java/awt/Menu/NullMenuLabelTest/NullMenuLabelTest.java	Fri Sep 24 16:41:32 2010 -0700
   244.3 @@ -0,0 +1,26 @@
   244.4 +/*      @test 1.5 98/07/23
   244.5 +        @bug 4064202 4253466
   244.6 +        @summary Test for Win32 NPE when MenuItem with null label added.
   244.7 +        @author fred.ecks
   244.8 +        @run main/othervm NullMenuLabelTest
   244.9 +*/
  244.10 +
  244.11 +import java.awt.*;
  244.12 +
  244.13 +public class NullMenuLabelTest {
  244.14 +
  244.15 +    public static void main(String[] args) {
  244.16 +        Frame frame = new Frame("Test Frame");
  244.17 +        frame.pack();
  244.18 +        frame.setVisible(true);
  244.19 +        MenuBar menuBar = new MenuBar();
  244.20 +        frame.setMenuBar(menuBar);
  244.21 +        Menu menu = new Menu(null);
  244.22 +        menuBar.add(menu);
  244.23 +        menu.add(new MenuItem(null));
  244.24 +        // If we got this far, the test succeeded
  244.25 +        frame.setVisible(false);
  244.26 +        frame.dispose();
  244.27 +    }
  244.28 +
  244.29 +} // class NullMenuLabelTest
   245.1 --- a/test/java/awt/TextField/ScrollSelectionTest/ScrollSelectionTest.java	Thu Sep 23 17:33:40 2010 -0700
   245.2 +++ b/test/java/awt/TextField/ScrollSelectionTest/ScrollSelectionTest.java	Fri Sep 24 16:41:32 2010 -0700
   245.3 @@ -53,13 +53,14 @@
   245.4        frame.add(tf);
   245.5        tf.select(0, 20);
   245.6  
   245.7 -      String[] instructions =
   245.8 -       {
   245.9 +      String[] instructions = {
  245.10            "INSTRUCTIONS:",
  245.11            "This is a test for a win32 specific problem",
  245.12 -          "If you see all the letters from 'a' to 'z' and",
  245.13 -          "letters from 'a' to 't' are selected then test passes"
  245.14 -       };
  245.15 +         "If you see all the letters from 'a' to 'z' and",
  245.16 +          "letters from 'a' to 't' are selected then test passes.",
  245.17 +          "You may have to activate the frame to see the selection"
  245.18 +          + " highlighted (e.g. by clicking on frame's title)."
  245.19 +      };
  245.20        Sysout.createDialogWithInstructions( instructions );
  245.21  
  245.22      }// init()
   246.1 --- a/test/java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_3.java	Thu Sep 23 17:33:40 2010 -0700
   246.2 +++ b/test/java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_3.java	Fri Sep 24 16:41:32 2010 -0700
   246.3 @@ -114,6 +114,7 @@
   246.4          checkEvents(frameAdapter, 1, 1);
   246.5          checkEvents(buttonAdapter, 0, 0);
   246.6          w.setVisible(false);
   246.7 +        Util.waitForIdle(r);
   246.8      }
   246.9  
  246.10      public static void main(String []s)
   247.1 --- a/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh	Thu Sep 23 17:33:40 2010 -0700
   247.2 +++ b/test/java/lang/ClassLoader/deadlock/TestCrossDelegate.sh	Fri Sep 24 16:41:32 2010 -0700
   247.3 @@ -25,7 +25,7 @@
   247.4  # @summary (cl) ClassLoader.loadClass locks all instances in chain 
   247.5  #          when delegating
   247.6  # 
   247.7 -# @run shell/timeout=10 TestCrossDelegate.sh
   247.8 +# @run shell/timeout=300 TestCrossDelegate.sh
   247.9  
  247.10  # if running by hand on windows, change TESTSRC and TESTCLASSES to "."
  247.11  if [ "${TESTSRC}" = "" ] ; then
  247.12 @@ -41,10 +41,6 @@
  247.13      echo "FAILED!!!"
  247.14      exit 1
  247.15  fi
  247.16 -echo TESTSRC=${TESTSRC}
  247.17 -echo TESTCLASSES=${TESTCLASSES}
  247.18 -echo TESTJAVA=${TESTJAVA}
  247.19 -echo ""
  247.20  
  247.21  # set platform-specific variables
  247.22  OS=`uname -s`
  247.23 @@ -55,11 +51,20 @@
  247.24    Linux )
  247.25      FS="/"
  247.26      ;;
  247.27 -  Windows* | CYGWIN* )
  247.28 +  Windows*)
  247.29      FS="\\"
  247.30      ;;
  247.31 +  CYGWIN* )
  247.32 +    FS="\\"
  247.33 +    TESTCLASSES=`/usr/bin/cygpath -a -s -m ${TESTCLASSES}`
  247.34 +    ;;
  247.35  esac
  247.36  
  247.37 +echo TESTSRC=${TESTSRC}
  247.38 +echo TESTCLASSES=${TESTCLASSES}
  247.39 +echo TESTJAVA=${TESTJAVA}
  247.40 +echo ""
  247.41 +
  247.42  # compile test
  247.43  ${TESTJAVA}${FS}bin${FS}javac \
  247.44          -d ${TESTCLASSES} \
   248.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   248.2 +++ b/test/java/lang/ProcessBuilder/SecurityManagerClinit.java	Fri Sep 24 16:41:32 2010 -0700
   248.3 @@ -0,0 +1,79 @@
   248.4 +/*
   248.5 + * Copyright 2010 Google Inc.  All Rights Reserved.
   248.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   248.7 + *
   248.8 + * This code is free software; you can redistribute it and/or modify it
   248.9 + * under the terms of the GNU General Public License version 2 only, as
  248.10 + * published by the Free Software Foundation.
  248.11 + *
  248.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  248.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  248.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  248.15 + * version 2 for more details (a copy is included in the LICENSE file that
  248.16 + * accompanied this code).
  248.17 + *
  248.18 + * You should have received a copy of the GNU General Public License version
  248.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  248.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  248.21 + *
  248.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  248.23 + * or visit www.oracle.com if you need additional information or have any
  248.24 + * questions.
  248.25 + */
  248.26 +
  248.27 +/*
  248.28 + * @test
  248.29 + * @bug 6980747
  248.30 + * @summary Check that Process-related classes have the proper
  248.31 + *     doPrivileged blocks, and can be initialized with an adversarial
  248.32 + *     security manager.
  248.33 + * @run main/othervm SecurityManagerClinit
  248.34 + * @author Martin Buchholz
  248.35 + */
  248.36 +
  248.37 +import java.io.*;
  248.38 +import java.security.*;
  248.39 +
  248.40 +public class SecurityManagerClinit {
  248.41 +    private static class Policy extends java.security.Policy {
  248.42 +        private Permissions perms;
  248.43 +
  248.44 +        public Policy(Permission... permissions) {
  248.45 +            perms = new Permissions();
  248.46 +            for (Permission permission : permissions)
  248.47 +                perms.add(permission);
  248.48 +        }
  248.49 +
  248.50 +        public boolean implies(ProtectionDomain pd, Permission p) {
  248.51 +            return perms.implies(p);
  248.52 +        }
  248.53 +    }
  248.54 +
  248.55 +    public static void main(String[] args) throws Throwable {
  248.56 +        String javaExe =
  248.57 +            System.getProperty("java.home") +
  248.58 +            File.separator + "bin" + File.separator + "java";
  248.59 +
  248.60 +        // A funky contrived security setup, just for bug repro purposes.
  248.61 +        java.security.Security.setProperty("package.access", "java.util");
  248.62 +
  248.63 +        final Policy policy =
  248.64 +            new Policy
  248.65 +            (new FilePermission("<<ALL FILES>>", "execute"),
  248.66 +             new RuntimePermission("setSecurityManager"));
  248.67 +        Policy.setPolicy(policy);
  248.68 +
  248.69 +        System.setSecurityManager(new SecurityManager());
  248.70 +
  248.71 +        try {
  248.72 +            String[] cmd = { javaExe, "-version" };
  248.73 +            Process p = Runtime.getRuntime().exec(cmd);
  248.74 +            p.getOutputStream().close();
  248.75 +            p.getInputStream().close();
  248.76 +            p.getErrorStream().close();
  248.77 +            p.waitFor();
  248.78 +        } finally {
  248.79 +            System.setSecurityManager(null);
  248.80 +        }
  248.81 +    }
  248.82 +}
   249.1 --- a/test/java/nio/channels/FileChannel/Transfer.java	Thu Sep 23 17:33:40 2010 -0700
   249.2 +++ b/test/java/nio/channels/FileChannel/Transfer.java	Fri Sep 24 16:41:32 2010 -0700
   249.3 @@ -23,6 +23,7 @@
   249.4  
   249.5  /* @test
   249.6   * @bug 4434723 4482726 4559072 4638365 4795550 5081340 5103988 6253145
   249.7 + *   6984545
   249.8   * @summary Test FileChannel.transferFrom and transferTo
   249.9   * @library ..
  249.10   */
  249.11 @@ -55,6 +56,7 @@
  249.12          xferTest06(); // for bug 5081340
  249.13          xferTest07(); // for bug 5103988
  249.14          xferTest08(); // for bug 6253145
  249.15 +        xferTest09(); // for bug 6984545
  249.16      }
  249.17  
  249.18      private static void testFileChannel() throws Exception {
  249.19 @@ -505,6 +507,27 @@
  249.20          }
  249.21      }
  249.22  
  249.23 +    // Test that transferFrom with FileChannel source that is not readable
  249.24 +    // throws NonReadableChannelException
  249.25 +    static void xferTest09() throws Exception {
  249.26 +        File source = File.createTempFile("source", null);
  249.27 +        source.deleteOnExit();
  249.28 +
  249.29 +        File target = File.createTempFile("target", null);
  249.30 +        target.deleteOnExit();
  249.31 +
  249.32 +        FileChannel fc1 = new FileOutputStream(source).getChannel();
  249.33 +        FileChannel fc2 = new RandomAccessFile(target, "rw").getChannel();
  249.34 +        try {
  249.35 +            fc2.transferFrom(fc1, 0L, 0);
  249.36 +            throw new RuntimeException("NonReadableChannelException expected");
  249.37 +        } catch (NonReadableChannelException expected) {
  249.38 +        } finally {
  249.39 +            fc1.close();
  249.40 +            fc2.close();
  249.41 +        }
  249.42 +    }
  249.43 +
  249.44      /**
  249.45       * Creates file blah of specified size in bytes.
  249.46       */
   250.1 --- a/test/java/nio/channels/Selector/ConnectWrite.java	Thu Sep 23 17:33:40 2010 -0700
   250.2 +++ b/test/java/nio/channels/Selector/ConnectWrite.java	Fri Sep 24 16:41:32 2010 -0700
   250.3 @@ -38,7 +38,6 @@
   250.4  
   250.5      public static void main(String[] args) throws Exception {
   250.6          test1(13);
   250.7 -        test1(9);
   250.8      }
   250.9  
  250.10      public static void test1(int port) throws Exception {
   251.1 --- a/test/java/nio/file/DirectoryStream/Basic.java	Thu Sep 23 17:33:40 2010 -0700
   251.2 +++ b/test/java/nio/file/DirectoryStream/Basic.java	Fri Sep 24 16:41:32 2010 -0700
   251.3 @@ -104,20 +104,20 @@
   251.4              stream.close();
   251.5          }
   251.6  
   251.7 -        // check that IOExceptions throws by filters are propagated
   251.8 +        // check that an IOException thrown by a filter is propagated
   251.9          filter = new DirectoryStream.Filter<Path>() {
  251.10              public boolean accept(Path file) throws IOException {
  251.11 -                throw new IOException();
  251.12 +                throw new java.util.zip.ZipException();
  251.13              }
  251.14          };
  251.15          stream = dir.newDirectoryStream(filter);
  251.16          try {
  251.17              stream.iterator().hasNext();
  251.18 -            throw new RuntimeException("ConcurrentModificationException expected");
  251.19 -        } catch (ConcurrentModificationException x) {
  251.20 -            Throwable t = x.getCause();
  251.21 -            if (!(t instanceof IOException))
  251.22 -                throw new RuntimeException("Cause is not IOException as expected");
  251.23 +            throw new RuntimeException("DirectoryIteratorException expected");
  251.24 +        } catch (DirectoryIteratorException x) {
  251.25 +            IOException cause = x.getCause();
  251.26 +            if (!(cause instanceof java.util.zip.ZipException))
  251.27 +                throw new RuntimeException("Expected IOException not propagated");
  251.28          } finally {
  251.29              stream.close();
  251.30          }
  251.31 @@ -142,58 +142,49 @@
  251.32          } catch (NotDirectoryException x) {
  251.33          }
  251.34  
  251.35 -        // test iterator remove method
  251.36 -        stream = dir.newDirectoryStream();
  251.37 +        // test UnsupportedOperationException
  251.38 +        stream =  dir.newDirectoryStream();
  251.39          Iterator<Path> i = stream.iterator();
  251.40 -        while (i.hasNext()) {
  251.41 -            Path entry = i.next();
  251.42 -            if (!entry.getName().equals(foo))
  251.43 -                throw new RuntimeException("entry not expected");
  251.44 +        i.next();
  251.45 +        try {
  251.46              i.remove();
  251.47 +            throw new RuntimeException("UnsupportedOperationException expected");
  251.48 +        } catch (UnsupportedOperationException uoe) {
  251.49          }
  251.50 -        stream.close();
  251.51  
  251.52          // test IllegalStateException
  251.53 -        dir.resolve(foo).createFile();
  251.54          stream =  dir.newDirectoryStream();
  251.55 -        i = stream.iterator();
  251.56 -        i.next();
  251.57 +        stream.iterator();
  251.58          try {
  251.59 +            // attempt to obtain second iterator
  251.60              stream.iterator();
  251.61              throw new RuntimeException("IllegalStateException not thrown as expected");
  251.62          } catch (IllegalStateException x) {
  251.63          }
  251.64          stream.close();
  251.65 +
  251.66 +        stream =  dir.newDirectoryStream();
  251.67 +        stream.close();
  251.68          try {
  251.69 +            // attempt to obtain iterator after stream is closed
  251.70              stream.iterator();
  251.71              throw new RuntimeException("IllegalStateException not thrown as expected");
  251.72          } catch (IllegalStateException x) {
  251.73          }
  251.74 +
  251.75 +        // test that iterator reads to end of stream when closed
  251.76 +        stream =  dir.newDirectoryStream();
  251.77 +        i = stream.iterator();
  251.78 +        stream.close();
  251.79 +        while (i.hasNext())
  251.80 +            i.next();
  251.81 +
  251.82 +        stream =  dir.newDirectoryStream();
  251.83 +        i = stream.iterator();
  251.84 +        stream.close();
  251.85          try {
  251.86 -            i.hasNext();
  251.87 -            throw new RuntimeException("ConcurrentModificationException not thrown as expected");
  251.88 -        } catch (ConcurrentModificationException x) {
  251.89 -            Throwable t = x.getCause();
  251.90 -            if (!(t instanceof ClosedDirectoryStreamException))
  251.91 -                throw new RuntimeException("Cause is not ClosedDirectoryStreamException as expected");
  251.92 -        }
  251.93 -        try {
  251.94 -            i.next();
  251.95 -            throw new RuntimeException("ConcurrentModificationException not thrown as expected");
  251.96 -        } catch (ConcurrentModificationException x) {
  251.97 -            Throwable t = x.getCause();
  251.98 -            if (!(t instanceof ClosedDirectoryStreamException))
  251.99 -                throw new RuntimeException("Cause is not ClosedDirectoryStreamException as expected");
 251.100 -        }
 251.101 -        try {
 251.102 -            i.remove();
 251.103 -            throw new RuntimeException("ConcurrentModificationException not thrown as expected");
 251.104 -        } catch (ConcurrentModificationException x) {
 251.105 -            Throwable t = x.getCause();
 251.106 -            if (!(t instanceof ClosedDirectoryStreamException))
 251.107 -                throw new RuntimeException("Cause is not ClosedDirectoryStreamException as expected");
 251.108 -        }
 251.109 -
 251.110 +            for (;;) i.next();
 251.111 +        } catch (NoSuchElementException expected) { }
 251.112      }
 251.113  
 251.114      public static void main(String[] args) throws IOException {
   252.1 --- a/test/java/nio/file/DirectoryStream/SecureDS.java	Thu Sep 23 17:33:40 2010 -0700
   252.2 +++ b/test/java/nio/file/DirectoryStream/SecureDS.java	Fri Sep 24 16:41:32 2010 -0700
   252.3 @@ -166,22 +166,6 @@
   252.4          stream.deleteDirectory(dirEntry);
   252.5          stream.deleteFile(fileEntry);
   252.6  
   252.7 -        // Test: remove
   252.8 -        // (requires resetting environment to get new iterator)
   252.9 -        stream.close();
  252.10 -        dir2.moveTo(dir1);
  252.11 -        dir1.resolve(fileEntry).createFile();
  252.12 -        stream = (SecureDirectoryStream<Path>)dir1.newDirectoryStream();
  252.13 -        dir1.moveTo(dir2);
  252.14 -        Iterator<Path> iter = stream.iterator();
  252.15 -        int removed = 0;
  252.16 -        while (iter.hasNext()) {
  252.17 -            iter.next();
  252.18 -            iter.remove();
  252.19 -            removed++;
  252.20 -        }
  252.21 -        assertTrue(removed == 1);
  252.22 -
  252.23          // clean-up
  252.24          stream.close();
  252.25          dir2.delete();
   253.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   253.2 +++ b/test/java/nio/file/etc/Exceptions.java	Fri Sep 24 16:41:32 2010 -0700
   253.3 @@ -0,0 +1,131 @@
   253.4 +/*
   253.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   253.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   253.7 + *
   253.8 + * This code is free software; you can redistribute it and/or modify it
   253.9 + * under the terms of the GNU General Public License version 2 only, as
  253.10 + * published by the Free Software Foundation.
  253.11 + *
  253.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  253.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  253.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  253.15 + * version 2 for more details (a copy is included in the LICENSE file that
  253.16 + * accompanied this code).
  253.17 + *
  253.18 + * You should have received a copy of the GNU General Public License version
  253.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  253.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  253.21 + *
  253.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  253.23 + * or visit www.oracle.com if you need additional information or have any
  253.24 + * questions.
  253.25 + */
  253.26 +
  253.27 +/* @test
  253.28 + * @bug 4313887 6881498
  253.29 + * @summary Miscellenous tests on exceptions in java.nio.file
  253.30 + */
  253.31 +
  253.32 +import java.nio.file.*;
  253.33 +import java.io.*;
  253.34 +import java.util.Objects;
  253.35 +import java.lang.reflect.*;
  253.36 +
  253.37 +public class Exceptions {
  253.38 +
  253.39 +    public static void main(String[] args) throws Exception {
  253.40 +        testFileSystemException();
  253.41 +        testDirectoryIteratorException();
  253.42 +    }
  253.43 +
  253.44 +    static void testFileSystemException() throws Exception {
  253.45 +        String thisFile = "source";
  253.46 +        String otherFile = "target";
  253.47 +        String reason = "Access denied";
  253.48 +
  253.49 +        // getFile/getOtherFile
  253.50 +        testFileSystemException(thisFile, otherFile, reason);
  253.51 +        testFileSystemException(null, otherFile, reason);
  253.52 +        testFileSystemException(thisFile, null, reason);
  253.53 +        testFileSystemException(thisFile, otherFile, null);
  253.54 +
  253.55 +        // serialization
  253.56 +        FileSystemException exc;
  253.57 +        exc = new FileSystemException(thisFile, otherFile, reason);
  253.58 +        exc = (FileSystemException)deserialize(serialize(exc));
  253.59 +        if (!exc.getFile().equals(thisFile) || !exc.getOtherFile().equals(otherFile))
  253.60 +            throw new RuntimeException("Exception not reconstituted completely");
  253.61 +    }
  253.62 +
  253.63 +    static void testFileSystemException(String thisFile,
  253.64 +                                        String otherFile,
  253.65 +                                        String reason)
  253.66 +    {
  253.67 +        FileSystemException exc = new FileSystemException(thisFile, otherFile, reason);
  253.68 +        if (!Objects.equals(thisFile, exc.getFile()))
  253.69 +            throw new RuntimeException("getFile returned unexpected result");
  253.70 +        if (!Objects.equals(otherFile, exc.getOtherFile()))
  253.71 +            throw new RuntimeException("getOtherFile returned unexpected result");
  253.72 +        if (!Objects.equals(reason, exc.getReason()))
  253.73 +            throw new RuntimeException("getReason returned unexpected result");
  253.74 +    }
  253.75 +
  253.76 +    static void testDirectoryIteratorException() throws Exception {
  253.77 +        // NullPointerException
  253.78 +        try {
  253.79 +            new DirectoryIteratorException(null);
  253.80 +            throw new RuntimeException("NullPointerException expected");
  253.81 +        } catch (NullPointerException expected) { }
  253.82 +
  253.83 +        // serialization
  253.84 +        DirectoryIteratorException exc;
  253.85 +        exc = new DirectoryIteratorException(new IOException());
  253.86 +        exc = (DirectoryIteratorException)deserialize(serialize(exc));
  253.87 +        IOException ioe = exc.getCause();
  253.88 +        if (ioe == null)
  253.89 +            throw new RuntimeException("Cause should not be null");
  253.90 +
  253.91 +        // when deserializing then the cause should be an IOException
  253.92 +        hackCause(exc, null);
  253.93 +        try {
  253.94 +            deserialize(serialize(exc));
  253.95 +            throw new RuntimeException("InvalidObjectException expected");
  253.96 +        } catch (InvalidObjectException expected) { }
  253.97 +
  253.98 +        hackCause(exc, new RuntimeException());
  253.99 +        try {
 253.100 +            deserialize(serialize(exc));
 253.101 +            throw new RuntimeException("InvalidObjectException expected");
 253.102 +        } catch (InvalidObjectException expected) { }
 253.103 +    }
 253.104 +
 253.105 +
 253.106 +    // Use reflection to set a Throwable's cause.
 253.107 +    static void hackCause(Throwable t, Throwable cause)
 253.108 +        throws NoSuchFieldException, IllegalAccessException
 253.109 +    {
 253.110 +        Field f = Throwable.class.getDeclaredField("cause");
 253.111 +        f.setAccessible(true);
 253.112 +        f.set(t, cause);
 253.113 +    }
 253.114 +
 253.115 +    // Serialize the given object to a byte[]
 253.116 +    static byte[] serialize(Object o) throws IOException {
 253.117 +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 253.118 +        ObjectOutputStream oos = new ObjectOutputStream(baos);
 253.119 +        oos.writeObject(o);
 253.120 +        oos.close();
 253.121 +        return baos.toByteArray();
 253.122 +    }
 253.123 +
 253.124 +    // Read an object from its serialized form
 253.125 +    static Object deserialize(byte[] bytes)
 253.126 +        throws IOException, ClassNotFoundException
 253.127 +    {
 253.128 +        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
 253.129 +        ObjectInputStream ois = new ObjectInputStream(in);
 253.130 +        Object result = ois.readObject();
 253.131 +        ois.close();
 253.132 +        return result;
 253.133 +    }
 253.134 +}
   254.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   254.2 +++ b/test/java/text/Format/DateFormat/ISO8601ZoneTest.java	Fri Sep 24 16:41:32 2010 -0700
   254.3 @@ -0,0 +1,217 @@
   254.4 +/*
   254.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   254.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   254.7 + *
   254.8 + * This code is free software; you can redistribute it and/or modify it
   254.9 + * under the terms of the GNU General Public License version 2 only, as
  254.10 + * published by the Free Software Foundation.
  254.11 + *
  254.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  254.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  254.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  254.15 + * version 2 for more details (a copy is included in the LICENSE file that
  254.16 + * accompanied this code).
  254.17 + *
  254.18 + * You should have received a copy of the GNU General Public License version
  254.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  254.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  254.21 + *
  254.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  254.23 + * or visit www.oracle.com if you need additional information or have any
  254.24 + * questions.
  254.25 + */
  254.26 +
  254.27 +/*
  254.28 + * @test
  254.29 + * @bug 4919632
  254.30 + * @summary Unit test for ISO8601 time zone format support
  254.31 + */
  254.32 +
  254.33 +import java.text.*;
  254.34 +import java.util.*;
  254.35 +
  254.36 +public class ISO8601ZoneTest {
  254.37 +    static final Date TIMESTAMP = new Date(1283758039020L);
  254.38 +
  254.39 +    static final String[][] formatData = {
  254.40 +        // time zone name, expected output at TIMESTAMP
  254.41 +        { "America/Los_Angeles", "2010-09-06T00:27:19.020-07", },
  254.42 +        { "America/Los_Angeles", "2010-09-06T00:27:19.020-0700", },
  254.43 +        { "America/Los_Angeles", "2010-09-06T00:27:19.020-07:00", },
  254.44 +        { "Australia/Sydney", "2010-09-06T17:27:19.020+10", },
  254.45 +        { "Australia/Sydney", "2010-09-06T17:27:19.020+1000", },
  254.46 +        { "Australia/Sydney", "2010-09-06T17:27:19.020+10:00", },
  254.47 +        { "GMT-07:00", "2010-09-06T00:27:19.020-07", },
  254.48 +        { "GMT-07:00", "2010-09-06T00:27:19.020-0700", },
  254.49 +        { "GMT-07:00", "2010-09-06T00:27:19.020-07:00", },
  254.50 +        { "UTC", "2010-09-06T07:27:19.020Z", },
  254.51 +        { "UTC", "2010-09-06T07:27:19.020Z", },
  254.52 +        { "UTC", "2010-09-06T07:27:19.020Z", },
  254.53 +    };
  254.54 +
  254.55 +    static final String[] zones = {
  254.56 +        "America/Los_Angeles", "Australia/Sydney", "GMT-07:00",
  254.57 +        "UTC", "GMT+05:30", "GMT-01:23",
  254.58 +    };
  254.59 +
  254.60 +    static final String[] isoZoneFormats = {
  254.61 +        "yyyy-MM-dd'T'HH:mm:ss.SSSX",
  254.62 +        "yyyy-MM-dd'T'HH:mm:ss.SSSXX",
  254.63 +        "yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
  254.64 +    };
  254.65 +
  254.66 +    static final String[][] badData = {
  254.67 +        { "X", "1" },
  254.68 +        { "X", "+1" },
  254.69 +        { "X", "-2" },
  254.70 +        { "X", "-24" },
  254.71 +        { "X", "+24" },
  254.72 +
  254.73 +        { "XX", "9" },
  254.74 +        { "XX", "23" },
  254.75 +        { "XX", "234" },
  254.76 +        { "XX", "3456" },
  254.77 +        { "XX", "23456" },
  254.78 +        { "XX", "+1" },
  254.79 +        { "XX", "-12" },
  254.80 +        { "XX", "+123" },
  254.81 +        { "XX", "-12:34" },
  254.82 +        { "XX", "+12:34" },
  254.83 +        { "XX", "-2423" },
  254.84 +        { "XX", "+2423" },
  254.85 +        { "XX", "-1260" },
  254.86 +        { "XX", "+1260" },
  254.87 +
  254.88 +        { "XXX", "9" },
  254.89 +        { "XXX", "23" },
  254.90 +        { "XXX", "234" },
  254.91 +        { "XXX", "3456" },
  254.92 +        { "XXX", "23456" },
  254.93 +        { "XXX", "2:34" },
  254.94 +        { "XXX", "12:4" },
  254.95 +        { "XXX", "12:34" },
  254.96 +        { "XXX", "-1" },
  254.97 +        { "XXX", "+1" },
  254.98 +        { "XXX", "-12" },
  254.99 +        { "XXX", "+12" },
 254.100 +        { "XXX", "-123" },
 254.101 +        { "XXX", "+123" },
 254.102 +        { "XXX", "-1234" },
 254.103 +        { "XXX", "+1234" },
 254.104 +        { "XXX", "+24:23" },
 254.105 +        { "XXX", "+12:60" },
 254.106 +        { "XXX", "+1:23" },
 254.107 +        { "XXX", "+12:3" },
 254.108 +    };
 254.109 +
 254.110 +    static String[] badFormats = {
 254.111 +        "XXXX", "XXXXX", "XXXXXX",
 254.112 +    };
 254.113 +
 254.114 +    public static void main(String[] args) throws Exception {
 254.115 +        TimeZone tz = TimeZone.getDefault();
 254.116 +
 254.117 +        try {
 254.118 +            for (int i = 0; i < formatData.length; i++) {
 254.119 +                TimeZone.setDefault(TimeZone.getTimeZone(formatData[i][0]));
 254.120 +                formatTest(isoZoneFormats[i % isoZoneFormats.length],
 254.121 +                           formatData[i][1]);
 254.122 +            }
 254.123 +
 254.124 +            for (String zone : zones) {
 254.125 +                TimeZone.setDefault(TimeZone.getTimeZone(zone));
 254.126 +                for (String fmt : isoZoneFormats) {
 254.127 +                    roundtripTest(fmt);
 254.128 +                    SimpleDateFormat f = new SimpleDateFormat(fmt);
 254.129 +                }
 254.130 +
 254.131 +            }
 254.132 +
 254.133 +            for (String[] d : badData) {
 254.134 +                badDataParsing(d[0], d[1]);
 254.135 +            }
 254.136 +
 254.137 +            for (String fmt : badFormats) {
 254.138 +                badFormat(fmt);
 254.139 +            }
 254.140 +        } finally {
 254.141 +            TimeZone.setDefault(tz);
 254.142 +        }
 254.143 +
 254.144 +    }
 254.145 +
 254.146 +    static void formatTest(String fmt, String expected) throws Exception {
 254.147 +        SimpleDateFormat sdf = new SimpleDateFormat(fmt);
 254.148 +        String s = sdf.format(TIMESTAMP);
 254.149 +        if (!expected.equals(s)) {
 254.150 +            throw new RuntimeException("formatTest: got " + s
 254.151 +                                       + ", expected " + expected);
 254.152 +        }
 254.153 +
 254.154 +        Date d = sdf.parse(s);
 254.155 +        if (d.getTime() != TIMESTAMP.getTime()) {
 254.156 +            throw new RuntimeException("formatTest: parse(" + s
 254.157 +                                       + "), got " + d.getTime()
 254.158 +                                       + ", expected " + TIMESTAMP.getTime());
 254.159 +        }
 254.160 +
 254.161 +        ParsePosition pos = new ParsePosition(0);
 254.162 +        d = sdf.parse(s + "123", pos);
 254.163 +        if (d.getTime() != TIMESTAMP.getTime()) {
 254.164 +            throw new RuntimeException("formatTest: parse(" + s
 254.165 +                                       + "), got " + d.getTime()
 254.166 +                                       + ", expected " + TIMESTAMP.getTime());
 254.167 +        }
 254.168 +        if (pos.getIndex() != s.length()) {
 254.169 +            throw new RuntimeException("formatTest: wrong resulting parse position: "
 254.170 +                                       + pos.getIndex() + ", expected " + s.length());
 254.171 +        }
 254.172 +    }
 254.173 +
 254.174 +    static void roundtripTest(String fmt) throws Exception {
 254.175 +        SimpleDateFormat sdf = new SimpleDateFormat(fmt);
 254.176 +        Date date = new Date();
 254.177 +
 254.178 +        int fractionalHour = sdf.getTimeZone().getOffset(date.getTime());
 254.179 +        fractionalHour %= 3600000; // fraction of hour
 254.180 +
 254.181 +        String s = sdf.format(date);
 254.182 +        Date pd = sdf.parse(s);
 254.183 +        long diffsInMillis = pd.getTime() - date.getTime();
 254.184 +        if (diffsInMillis != 0) {
 254.185 +            if (diffsInMillis != fractionalHour) {
 254.186 +                throw new RuntimeException("fmt= " + fmt
 254.187 +                                           + ", diff="+diffsInMillis
 254.188 +                                           + ", fraction=" + fractionalHour);
 254.189 +            }
 254.190 +        }
 254.191 +    }
 254.192 +
 254.193 +
 254.194 +    static void badDataParsing(String fmt, String text) {
 254.195 +        try {
 254.196 +            SimpleDateFormat sdf = new SimpleDateFormat(fmt);
 254.197 +            sdf.parse(text);
 254.198 +            throw new RuntimeException("didn't throw an exception: fmt=" + fmt
 254.199 +                                       + ", text=" + text);
 254.200 +        } catch (ParseException e) {
 254.201 +            // OK
 254.202 +        }
 254.203 +    }
 254.204 +
 254.205 +    static void badFormat(String fmt) {
 254.206 +        try {
 254.207 +            SimpleDateFormat sdf = new SimpleDateFormat(fmt);
 254.208 +            throw new RuntimeException("Constructor didn't throw an exception: fmt=" + fmt);
 254.209 +        } catch (IllegalArgumentException e) {
 254.210 +            // OK
 254.211 +        }
 254.212 +        try {
 254.213 +            SimpleDateFormat sdf = new SimpleDateFormat();
 254.214 +            sdf.applyPattern(fmt);
 254.215 +            throw new RuntimeException("applyPattern didn't throw an exception: fmt=" + fmt);
 254.216 +        } catch (IllegalArgumentException e) {
 254.217 +            // OK
 254.218 +        }
 254.219 +    }
 254.220 +}
   255.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   255.2 +++ b/test/java/text/Format/DateFormat/WeekDateTest.java	Fri Sep 24 16:41:32 2010 -0700
   255.3 @@ -0,0 +1,166 @@
   255.4 +/*
   255.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   255.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   255.7 + *
   255.8 + * This code is free software; you can redistribute it and/or modify it
   255.9 + * under the terms of the GNU General Public License version 2 only, as
  255.10 + * published by the Free Software Foundation.
  255.11 + *
  255.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  255.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  255.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  255.15 + * version 2 for more details (a copy is included in the LICENSE file that
  255.16 + * accompanied this code).
  255.17 + *
  255.18 + * You should have received a copy of the GNU General Public License version
  255.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  255.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  255.21 + *
  255.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  255.23 + * or visit www.oracle.com if you need additional information or have any
  255.24 + * questions.
  255.25 + */
  255.26 +
  255.27 +/*
  255.28 + * @test
  255.29 + * @bug 4267450
  255.30 + * @summary Unit test for week date support
  255.31 + */
  255.32 +
  255.33 +import java.text.*;
  255.34 +import java.util.*;
  255.35 +import static java.util.GregorianCalendar.*;
  255.36 +
  255.37 +public class WeekDateTest {
  255.38 +    static SimpleDateFormat ymdFormat = new SimpleDateFormat("yyyy-MM-dd");
  255.39 +    static SimpleDateFormat ywdFormat = new SimpleDateFormat("YYYY-'W'ww-u");
  255.40 +    static {
  255.41 +        ymdFormat.setCalendar(newCalendar());
  255.42 +        ywdFormat.setCalendar(newCalendar());
  255.43 +    }
  255.44 +
  255.45 +    // Round-trip Data
  255.46 +    static final String[][] roundTripData = {
  255.47 +        { "2005-01-01", "2004-W53-6" },
  255.48 +        { "2005-01-02", "2004-W53-7" },
  255.49 +        { "2005-12-31", "2005-W52-6" },
  255.50 +        { "2007-01-01", "2007-W01-1" },
  255.51 +        { "2007-12-30", "2007-W52-7" },
  255.52 +        { "2007-12-31", "2008-W01-1" },
  255.53 +        { "2008-01-01", "2008-W01-2" },
  255.54 +        { "2008-12-29", "2009-W01-1" },
  255.55 +        { "2008-12-31", "2009-W01-3" },
  255.56 +        { "2009-01-01", "2009-W01-4" },
  255.57 +        { "2009-12-31", "2009-W53-4" },
  255.58 +        { "2010-01-03", "2009-W53-7" },
  255.59 +        { "2009-12-31", "2009-W53-4" },
  255.60 +        { "2010-01-01", "2009-W53-5" },
  255.61 +        { "2010-01-02", "2009-W53-6" },
  255.62 +        { "2010-01-03", "2009-W53-7" },
  255.63 +        { "2008-12-28", "2008-W52-7" },
  255.64 +        { "2008-12-29", "2009-W01-1" },
  255.65 +        { "2008-12-30", "2009-W01-2" },
  255.66 +        { "2008-12-31", "2009-W01-3" },
  255.67 +        { "2009-01-01", "2009-W01-4" },
  255.68 +        { "2009-01-01", "2009-W01-4" },
  255.69 +    };
  255.70 +
  255.71 +    // Data for leniency test
  255.72 +    static final String[][] leniencyData = {
  255.73 +        { "2008-12-28", "2009-W01-0" },
  255.74 +        { "2010-01-04", "2009-W53-8" },
  255.75 +        { "2008-12-29", "2008-W53-1" },
  255.76 +    };
  255.77 +
  255.78 +    static final String[] invalidData = {
  255.79 +        "2010-W00-1",
  255.80 +        "2010-W55-1",
  255.81 +        "2010-W03-0",
  255.82 +        "2010-W04-8",
  255.83 +        "2010-W04-19"
  255.84 +    };
  255.85 +
  255.86 +    public static void main(String[] args) throws Exception {
  255.87 +        formatTest(roundTripData);
  255.88 +        parseTest(roundTripData);
  255.89 +        parseTest(leniencyData);
  255.90 +        nonLenientTest(invalidData);
  255.91 +        noWeekDateSupport();
  255.92 +    }
  255.93 +
  255.94 +    private static void formatTest(String[][] data) throws Exception {
  255.95 +        for (String[] dates : data) {
  255.96 +            String regularDate = dates[0];
  255.97 +            String weekDate = dates[1];
  255.98 +            Date date = null;
  255.99 +            date = ymdFormat.parse(regularDate);
 255.100 +            String s = ywdFormat.format(date);
 255.101 +            if (!s.equals(weekDate)) {
 255.102 +                throw new RuntimeException("format: got="+s+", expecetd="+weekDate);
 255.103 +            }
 255.104 +        }
 255.105 +    }
 255.106 +
 255.107 +    private static void parseTest(String[][] data) throws Exception {
 255.108 +        for (String[] dates : data) {
 255.109 +            String regularDate = dates[0];
 255.110 +            String weekDate = dates[1];
 255.111 +            Date date1 = null, date2 = null;
 255.112 +            date1 = ymdFormat.parse(regularDate);
 255.113 +            date2 = ywdFormat.parse(weekDate);
 255.114 +            if (!date1.equals(date2)) {
 255.115 +                System.err.println(regularDate + ": date1 = " + date1);
 255.116 +                System.err.println(weekDate + ": date2 = " + date2);
 255.117 +                throw new RuntimeException("parse: date1 != date2");
 255.118 +            }
 255.119 +        }
 255.120 +    }
 255.121 +
 255.122 +
 255.123 +    // Non-lenient mode test
 255.124 +    private static void nonLenientTest(String[] data) {
 255.125 +        ywdFormat.setLenient(false);
 255.126 +        for (String date : data) {
 255.127 +            try {
 255.128 +                Date d = ywdFormat.parse(date);
 255.129 +                throw new RuntimeException("No ParseException thrown with " + date);
 255.130 +            } catch (ParseException e) {
 255.131 +                // OK
 255.132 +            }
 255.133 +        }
 255.134 +        ywdFormat.setLenient(true);
 255.135 +    }
 255.136 +
 255.137 +
 255.138 +    private static void noWeekDateSupport() throws Exception {
 255.139 +        // Tests with Japanese Imperial Calendar that doesn't support week dates.
 255.140 +        Calendar jcal = Calendar.getInstance(TimeZone.getTimeZone("GMT"),
 255.141 +                                             new Locale("ja", "JP", "JP"));
 255.142 +
 255.143 +        jcal.setFirstDayOfWeek(MONDAY);
 255.144 +        jcal.setMinimalDaysInFirstWeek(4);
 255.145 +        SimpleDateFormat sdf = new SimpleDateFormat("Y-'W'ww-u");
 255.146 +        sdf.setCalendar(jcal);
 255.147 +        Date d = sdf.parse("21-W01-3"); // 2008-12-31 == H20-12-31
 255.148 +        GregorianCalendar gcal = newCalendar();
 255.149 +        gcal.setTime(d);
 255.150 +        if (gcal.get(YEAR) != 2008
 255.151 +            || gcal.get(MONTH) != DECEMBER
 255.152 +            || gcal.get(DAY_OF_MONTH) != 31) {
 255.153 +            String s = String.format("noWeekDateSupport: got %04d-%02d-%02d, expected 2008-12-31%n",
 255.154 +                                     gcal.get(YEAR),
 255.155 +                                     gcal.get(MONTH)+1,
 255.156 +                                     gcal.get(DAY_OF_MONTH));
 255.157 +            throw new RuntimeException(s);
 255.158 +        }
 255.159 +    }
 255.160 +
 255.161 +    private static GregorianCalendar newCalendar() {
 255.162 +        // Use GMT to avoid any surprises related DST transitions.
 255.163 +        GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
 255.164 +        // Setup the ISO 8601 compatible parameters
 255.165 +        cal.setFirstDayOfWeek(MONDAY);
 255.166 +        cal.setMinimalDaysInFirstWeek(4);
 255.167 +        return cal;
 255.168 +    }
 255.169 +}
   256.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   256.2 +++ b/test/java/util/Calendar/WeekDateTest.java	Fri Sep 24 16:41:32 2010 -0700
   256.3 @@ -0,0 +1,188 @@
   256.4 +/*
   256.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   256.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   256.7 + *
   256.8 + * This code is free software; you can redistribute it and/or modify it
   256.9 + * under the terms of the GNU General Public License version 2 only, as
  256.10 + * published by the Free Software Foundation.
  256.11 + *
  256.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  256.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  256.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  256.15 + * version 2 for more details (a copy is included in the LICENSE file that
  256.16 + * accompanied this code).
  256.17 + *
  256.18 + * You should have received a copy of the GNU General Public License version
  256.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  256.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  256.21 + *
  256.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  256.23 + * or visit www.oracle.com if you need additional information or have any
  256.24 + * questions.
  256.25 + */
  256.26 +
  256.27 +/*
  256.28 + * @test
  256.29 + * @bug 4267450
  256.30 + * @summary Unit test for week date support
  256.31 + */
  256.32 +
  256.33 +import java.text.*;
  256.34 +import java.util.*;
  256.35 +import static java.util.GregorianCalendar.*;
  256.36 +
  256.37 +public class WeekDateTest {
  256.38 +
  256.39 +    // Week dates are in the ISO numbering for day-of-week.
  256.40 +    static int[][][] data = {
  256.41 +        // Calendar year-date, Week year-date
  256.42 +        {{ 2005, 01, 01}, { 2004, 53, 6}},
  256.43 +        {{ 2005, 01, 02}, { 2004, 53, 7}},
  256.44 +        {{ 2005, 12, 31}, { 2005, 52, 6}},
  256.45 +        {{ 2007, 01, 01}, { 2007, 01, 1}},
  256.46 +        {{ 2007, 12, 30}, { 2007, 52, 7}},
  256.47 +        {{ 2007, 12, 31}, { 2008, 01, 1}},
  256.48 +        {{ 2008, 01, 01}, { 2008, 01, 2}},
  256.49 +        {{ 2008, 12, 29}, { 2009, 01, 1}},
  256.50 +        {{ 2008, 12, 31}, { 2009, 01, 3}},
  256.51 +        {{ 2009, 01, 01}, { 2009, 01, 4}},
  256.52 +        {{ 2009, 12, 31}, { 2009, 53, 4}},
  256.53 +        {{ 2010, 01, 03}, { 2009, 53, 7}},
  256.54 +        {{ 2009, 12, 31}, { 2009, 53, 4}},
  256.55 +        {{ 2010, 01, 01}, { 2009, 53, 5}},
  256.56 +        {{ 2010, 01, 02}, { 2009, 53, 6}},
  256.57 +        {{ 2010, 01, 03}, { 2009, 53, 7}},
  256.58 +        {{ 2008, 12, 28}, { 2008, 52, 7}},
  256.59 +        {{ 2008, 12, 29}, { 2009, 01, 1}},
  256.60 +        {{ 2008, 12, 30}, { 2009, 01, 2}},
  256.61 +        {{ 2008, 12, 31}, { 2009, 01, 3}},
  256.62 +        {{ 2009, 01, 01}, { 2009, 01, 4}}
  256.63 +    };
  256.64 +
  256.65 +    // Data for leniency test
  256.66 +    static final int[][][] leniencyData = {
  256.67 +        {{ 2008, 12, 28}, { 2009,  0, 7}},
  256.68 +        {{ 2008, 12, 21}, { 2009, -1, 7}},
  256.69 +        {{ 2009,  1,  4}, { 2008, 53, 7}},
  256.70 +    };
  256.71 +
  256.72 +    static final int[][] invalidData = {
  256.73 +        { 2010, -1,  1},
  256.74 +        { 2010, 00,  1},
  256.75 +        { 2010, 55,  1},
  256.76 +        { 2010, 03,  0},
  256.77 +        { 2010, 04,  8},
  256.78 +        { 2010, 04, 19},
  256.79 +        { 2010, 05, -1},
  256.80 +    };
  256.81 +
  256.82 +    public static void main(String[] args) {
  256.83 +        GregorianCalendar cal = newCalendar();
  256.84 +        for (int[][] dates : data) {
  256.85 +            int[] expected = dates[0];
  256.86 +            int[] weekDate = dates[1];
  256.87 +            // Convert ISO 8601 day-of-week to Calendar.DAY_OF_WEEK.
  256.88 +            int dayOfWeek = getCalendarDayOfWeek(weekDate[2]);
  256.89 +
  256.90 +            cal.clear();
  256.91 +            cal.setWeekDate(weekDate[0], weekDate[1], dayOfWeek);
  256.92 +            if (cal.get(YEAR) != expected[0]
  256.93 +                || cal.get(MONTH)+1 != expected[1]
  256.94 +                || cal.get(DAY_OF_MONTH) != expected[2]) {
  256.95 +                String s = String.format("got=%4d-%02d-%02d, expected=%4d-%02d-%02d",
  256.96 +                               cal.get(YEAR), cal.get(MONTH)+1, cal.get(DAY_OF_MONTH),
  256.97 +                               expected[0], expected[1], expected[2]);
  256.98 +                throw new RuntimeException(s);
  256.99 +            }
 256.100 +            if (cal.getWeekYear() != weekDate[0]
 256.101 +                || cal.get(WEEK_OF_YEAR) != weekDate[1]
 256.102 +                || cal.get(DAY_OF_WEEK) != dayOfWeek) {
 256.103 +                String s = String.format(
 256.104 +                    "got=%4d-W%02d-%d, expected=%4d-W%02d-%d (not ISO day-of-week)",
 256.105 +                    cal.getWeekYear(), cal.get(WEEK_OF_YEAR), cal.get(DAY_OF_WEEK),
 256.106 +                    weekDate[0], weekDate[1], dayOfWeek);
 256.107 +                throw new RuntimeException(s);
 256.108 +            }
 256.109 +        }
 256.110 +
 256.111 +        // Test getWeeksInWeekYear().
 256.112 +        // If we avoid the first week of January and the last week of
 256.113 +        // December, getWeeksInWeekYear() and
 256.114 +        // getActualMaximum(WEEK_OF_YEAR) values should be the same.
 256.115 +        for (int year = 2000; year <= 2100; year++) {
 256.116 +            cal.clear();
 256.117 +            cal.set(year, JUNE, 1);
 256.118 +            int n = cal.getWeeksInWeekYear();
 256.119 +            if (n != cal.getActualMaximum(WEEK_OF_YEAR)) {
 256.120 +                String s = String.format("getWeeksInWeekYear() = %d, "
 256.121 +                                         + "getActualMaximum(WEEK_OF_YEAR) = %d%n",
 256.122 +                                         n, cal.getActualMaximum(WEEK_OF_YEAR));
 256.123 +                throw new RuntimeException(s);
 256.124 +            }
 256.125 +
 256.126 +            cal.setWeekDate(cal.getWeekYear(), 1, MONDAY);
 256.127 +            if (cal.getWeeksInWeekYear() != n) {
 256.128 +                String s = String.format("first day: got %d, expected %d%n",
 256.129 +                                         cal.getWeeksInWeekYear(), n);
 256.130 +                throw new RuntimeException(s);
 256.131 +            }
 256.132 +
 256.133 +            cal.setWeekDate(cal.getWeekYear(), n, SUNDAY);
 256.134 +            if (cal.getWeeksInWeekYear() != n) {
 256.135 +                String s = String.format("last day: got %d, expected %d%n",
 256.136 +                                         cal.getWeeksInWeekYear(), n);
 256.137 +                throw new RuntimeException(s);
 256.138 +            }
 256.139 +        }
 256.140 +
 256.141 +        // Test lenient mode with out of range values.
 256.142 +        for (int[][] dates : leniencyData) {
 256.143 +            int[] expected = dates[0];
 256.144 +            int[] weekDate = dates[1];
 256.145 +            // Convert ISO 8601 day-of-week to Calendar.DAY_OF_WEEK.
 256.146 +            int dayOfWeek = getCalendarDayOfWeek(weekDate[2]);
 256.147 +
 256.148 +            cal.clear();
 256.149 +            cal.setWeekDate(weekDate[0], weekDate[1], dayOfWeek);
 256.150 +            if (cal.get(YEAR) != expected[0]
 256.151 +                || cal.get(MONTH)+1 != expected[1]
 256.152 +                || cal.get(DAY_OF_MONTH) != expected[2]) {
 256.153 +                String s = String.format("got=%4d-%02d-%02d, expected=%4d-%02d-%02d",
 256.154 +                               cal.get(YEAR), cal.get(MONTH)+1, cal.get(DAY_OF_MONTH),
 256.155 +                               expected[0], expected[1], expected[2]);
 256.156 +                throw new RuntimeException(s);
 256.157 +            }
 256.158 +        }
 256.159 +
 256.160 +        // Test non-lenient mode
 256.161 +        cal.setLenient(false);
 256.162 +        for (int[] date : invalidData) {
 256.163 +            cal.clear();
 256.164 +            try {
 256.165 +                // Use the raw dayOfWeek value as invalid data
 256.166 +                cal.setWeekDate(date[0], date[1], date[2]);
 256.167 +                String s = String.format("didn't throw an IllegalArgumentException with"
 256.168 +                                         + " %d, %d, %d",date[0], date[1], date[2]);
 256.169 +                throw new RuntimeException(s);
 256.170 +            } catch (IllegalArgumentException e) {
 256.171 +                // OK
 256.172 +            }
 256.173 +        }
 256.174 +    }
 256.175 +
 256.176 +    private static GregorianCalendar newCalendar() {
 256.177 +        // Use GMT to avoid any surprises related DST transitions.
 256.178 +        GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
 256.179 +        if (!cal.isWeekDateSupported()) {
 256.180 +            throw new RuntimeException("Week dates not supported");
 256.181 +        }
 256.182 +        // Setup the ISO 8601 compatible parameters
 256.183 +        cal.setFirstDayOfWeek(MONDAY);
 256.184 +        cal.setMinimalDaysInFirstWeek(4);
 256.185 +        return cal;
 256.186 +    }
 256.187 +
 256.188 +    private static int getCalendarDayOfWeek(int isoDayOfWeek) {
 256.189 +        return (isoDayOfWeek == 7) ? SUNDAY : isoDayOfWeek + 1;
 256.190 +    }
 256.191 +}
   257.1 --- a/test/java/util/Formatter/Constructors.java	Thu Sep 23 17:33:40 2010 -0700
   257.2 +++ b/test/java/util/Formatter/Constructors.java	Fri Sep 24 16:41:32 2010 -0700
   257.3 @@ -58,7 +58,7 @@
   257.4      }
   257.5  
   257.6      static void locale(Formatter f) {
   257.7 -        locale(f, Locale.getDefault());
   257.8 +        locale(f, Locale.getDefault(Locale.Category.FORMAT));
   257.9      }
  257.10  
  257.11      static void locale(Formatter f, Locale l) {
   258.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   258.2 +++ b/test/java/util/Locale/LocaleCategory.java	Fri Sep 24 16:41:32 2010 -0700
   258.3 @@ -0,0 +1,66 @@
   258.4 +/*
   258.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   258.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   258.7 + *
   258.8 + * This code is free software; you can redistribute it and/or modify it
   258.9 + * under the terms of the GNU General Public License version 2 only, as
  258.10 + * published by the Free Software Foundation.
  258.11 + *
  258.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  258.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  258.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  258.15 + * version 2 for more details (a copy is included in the LICENSE file that
  258.16 + * accompanied this code).
  258.17 + *
  258.18 + * You should have received a copy of the GNU General Public License version
  258.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  258.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  258.21 + *
  258.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  258.23 + * or visit www.oracle.com if you need additional information or have any
  258.24 + * questions.
  258.25 + */
  258.26 +import java.util.Locale;
  258.27 +
  258.28 +public class LocaleCategory {
  258.29 +    private static Locale base = null;
  258.30 +    private static Locale disp = null;
  258.31 +    private static Locale fmt = null;
  258.32 +    private static String enc = null;
  258.33 +
  258.34 +    public static void main(String[] args) {
  258.35 +        base = new Locale(System.getProperty("user.language", ""),
  258.36 +                          System.getProperty("user.country", ""),
  258.37 +                          System.getProperty("user.variant", ""));
  258.38 +        disp = new Locale(System.getProperty("user.language.display", ""),
  258.39 +                          System.getProperty("user.country.display", ""),
  258.40 +                          System.getProperty("user.variant.display", ""));
  258.41 +        fmt  = new Locale(System.getProperty("user.language.format", ""),
  258.42 +                          System.getProperty("user.country.format", ""),
  258.43 +                          System.getProperty("user.variant.format", ""));
  258.44 +        checkDefault();
  258.45 +        testGetSetDefault();
  258.46 +    }
  258.47 +
  258.48 +    static void checkDefault() {
  258.49 +        if (!base.equals(Locale.getDefault()) ||
  258.50 +            !disp.equals(Locale.getDefault(Locale.Category.DISPLAY)) ||
  258.51 +            !fmt.equals(Locale.getDefault(Locale.Category.FORMAT))) {
  258.52 +            throw new RuntimeException("Some of the return values from getDefault() do not agree with the locale derived from \"user.xxxx\" system properties");
  258.53 +        }
  258.54 +    }
  258.55 +
  258.56 +    static void testGetSetDefault() {
  258.57 +        try {
  258.58 +            Locale.setDefault(null, null);
  258.59 +            throw new RuntimeException("setDefault(null, null) should throw a NullPointerException");
  258.60 +        } catch (NullPointerException npe) {}
  258.61 +
  258.62 +        Locale.setDefault(Locale.CHINA);
  258.63 +        if (!Locale.CHINA.equals(Locale.getDefault(Locale.Category.DISPLAY)) ||
  258.64 +            !Locale.CHINA.equals(Locale.getDefault(Locale.Category.FORMAT))) {
  258.65 +            throw new RuntimeException("setDefault() should set all default locales for all categories");
  258.66 +        }
  258.67 +    }
  258.68 +}
  258.69 +
   259.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   259.2 +++ b/test/java/util/Locale/LocaleCategory.sh	Fri Sep 24 16:41:32 2010 -0700
   259.3 @@ -0,0 +1,79 @@
   259.4 +#!/bin/sh
   259.5 +#
   259.6 +# @test
   259.7 +# @bug 4700857
   259.8 +# @summary tests for Locale.getDefault(Locale.Category) and 
   259.9 +#    Locale.setDefault(Locale.Category, Locale)
  259.10 +# @build LocaleCategory
  259.11 +# @run shell/timeout=600 LocaleCategory.sh
  259.12 +
  259.13 +if [ "${TESTSRC}" = "" ]
  259.14 +then
  259.15 +  echo "TESTSRC not set.  Test cannot execute.  Failed."
  259.16 +  exit 1
  259.17 +fi
  259.18 +echo "TESTSRC=${TESTSRC}"
  259.19 +if [ "${TESTJAVA}" = "" ]
  259.20 +then
  259.21 +  echo "TESTJAVA not set.  Test cannot execute.  Failed."
  259.22 +  exit 1
  259.23 +fi
  259.24 +echo "TESTJAVA=${TESTJAVA}"
  259.25 +if [ "${TESTCLASSES}" = "" ]
  259.26 +then
  259.27 +  echo "TESTCLASSES not set.  Test cannot execute.  Failed."
  259.28 +  exit 1
  259.29 +fi
  259.30 +echo "TESTCLASSES=${TESTCLASSES}"
  259.31 +echo "CLASSPATH=${CLASSPATH}"
  259.32 +
  259.33 +# set platform-dependent variables
  259.34 +OS=`uname -s`
  259.35 +case "$OS" in
  259.36 +  SunOS | Linux )
  259.37 +    PS=":"
  259.38 +    FS="/"
  259.39 +    ;;
  259.40 +  Windows* )
  259.41 +    PS=";"
  259.42 +    FS="\\"
  259.43 +    ;;
  259.44 +  * )
  259.45 +    echo "Unrecognized system!"
  259.46 +    exit 1;
  259.47 +    ;;
  259.48 +esac
  259.49 +
  259.50 +# test user.xxx.display user.xxx.format properties
  259.51 +
  259.52 +# run
  259.53 +RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} -Duser.language.display=ja -Duser.language.format=zh LocaleCategory"
  259.54 +
  259.55 +echo ${RUNCMD}
  259.56 +${RUNCMD}
  259.57 +result=$?
  259.58 +
  259.59 +if [ $result -eq 0 ]
  259.60 +then
  259.61 +  echo "Execution successful"
  259.62 +else
  259.63 +  echo "Execution of the test case failed."
  259.64 +fi
  259.65 +
  259.66 +# test user.xxx properties overriding user.xxx.display/format
  259.67 +
  259.68 +# run
  259.69 +RUNCMD="${TESTJAVA}${FS}bin${FS}java -classpath ${TESTCLASSES} -Duser.language=en -Duser.language.display=ja -Duser.language.format=zh LocaleCategory"
  259.70 +
  259.71 +echo ${RUNCMD}
  259.72 +${RUNCMD}
  259.73 +result=$?
  259.74 +
  259.75 +if [ $result -eq 0 ]
  259.76 +then
  259.77 +  echo "Execution successful"
  259.78 +else
  259.79 +  echo "Execution of the test case failed."
  259.80 +fi
  259.81 +
  259.82 +exit $result
   260.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   260.2 +++ b/test/java/util/Locale/LocaleEnhanceTest.java	Fri Sep 24 16:41:32 2010 -0700
   260.3 @@ -0,0 +1,1293 @@
   260.4 +/*
   260.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   260.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   260.7 + *
   260.8 + * This code is free software; you can redistribute it and/or modify it
   260.9 + * under the terms of the GNU General Public License version 2 only, as
  260.10 + * published by the Free Software Foundation.  Oracle designates this
  260.11 + * particular file as subject to the "Classpath" exception as provided
  260.12 + * by Oracle in the LICENSE file that accompanied this code.
  260.13 + *
  260.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  260.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  260.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  260.17 + * version 2 for more details (a copy is included in the LICENSE file that
  260.18 + * accompanied this code).
  260.19 + *
  260.20 + * You should have received a copy of the GNU General Public License version
  260.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  260.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  260.23 + *
  260.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  260.25 + * or visit www.oracle.com if you need additional information or have any
  260.26 + * questions.
  260.27 + */
  260.28 +
  260.29 +import java.io.BufferedReader;
  260.30 +import java.io.ByteArrayInputStream;
  260.31 +import java.io.ByteArrayOutputStream;
  260.32 +import java.io.File;
  260.33 +import java.io.FileInputStream;
  260.34 +import java.io.InputStreamReader;
  260.35 +import java.io.ObjectInputStream;
  260.36 +import java.io.ObjectOutputStream;
  260.37 +import java.net.URISyntaxException;
  260.38 +import java.net.URL;
  260.39 +import java.util.ArrayList;
  260.40 +import java.util.Arrays;
  260.41 +import java.util.IllformedLocaleException;
  260.42 +import java.util.List;
  260.43 +import java.util.Locale;
  260.44 +import java.util.Locale.Builder;
  260.45 +import java.util.Set;
  260.46 +
  260.47 +/**
  260.48 + * @test
  260.49 + * @bug 6875847
  260.50 + * @summary test API changes to Locale
  260.51 + */
  260.52 +public class LocaleEnhanceTest extends LocaleTestFmwk {
  260.53 +
  260.54 +    public static void main(String[] args) throws Exception {
  260.55 +        List<String> argList = new ArrayList<String>();
  260.56 +        argList.addAll(Arrays.asList(args));
  260.57 +        argList.add("-nothrow");
  260.58 +        new LocaleEnhanceTest().run(argList.toArray(new String[argList.size()]));
  260.59 +    }
  260.60 +
  260.61 +    public LocaleEnhanceTest() {
  260.62 +    }
  260.63 +
  260.64 +    ///
  260.65 +    /// Generic sanity tests
  260.66 +    ///
  260.67 +
  260.68 +    /** A canonical language code. */
  260.69 +    private static final String l = "en";
  260.70 +
  260.71 +    /** A canonical script code.. */
  260.72 +    private static final String s = "Latn";
  260.73 +
  260.74 +    /** A canonical region code. */
  260.75 +    private static final String c = "US";
  260.76 +
  260.77 +    /** A canonical variant code. */
  260.78 +    private static final String v = "NewYork";
  260.79 +
  260.80 +    /**
  260.81 +     * Ensure that Builder builds locales that have the expected
  260.82 +     * tag and java6 ID.  Note the odd cases for the ID.
  260.83 +     */
  260.84 +    public void testCreateLocaleCanonicalValid() {
  260.85 +        String[] valids = {
  260.86 +            "en-Latn-US-NewYork", "en_US_NewYork_#Latn",
  260.87 +            "en-Latn-US", "en_US_#Latn",
  260.88 +            "en-Latn-NewYork", "en__NewYork_#Latn", // double underscore
  260.89 +            "en-Latn", "en_#Latn",
  260.90 +            "en-US-NewYork", "en_US_NewYork",
  260.91 +            "en-US", "en_US",
  260.92 +            "en-NewYork", "en__NewYork", // double underscore
  260.93 +            "en", "en",
  260.94 +            "und-Latn-US-NewYork", "_US_NewYork_#Latn",
  260.95 +            "und-Latn-US", "_US_#Latn",
  260.96 +            "und-Latn-NewYork", "", // variant only not supported
  260.97 +            "und-Latn", "",
  260.98 +            "und-US-NewYork", "_US_NewYork",
  260.99 +            "und-US", "_US",
 260.100 +            "und-NewYork", "", // variant only not supported
 260.101 +            "und", ""
 260.102 +        };
 260.103 +
 260.104 +        Builder builder = new Builder();
 260.105 +
 260.106 +        for (int i = 0; i < valids.length; i += 2) {
 260.107 +            String tag = valids[i];
 260.108 +            String id = valids[i+1];
 260.109 +
 260.110 +            String idl = (i & 16) == 0 ? l : "";
 260.111 +            String ids = (i & 8) == 0 ? s : "";
 260.112 +            String idc = (i & 4) == 0 ? c : "";
 260.113 +            String idv = (i & 2) == 0 ? v : "";
 260.114 +
 260.115 +            String msg = String.valueOf(i/2) + ": '" + tag + "' ";
 260.116 +
 260.117 +            try {
 260.118 +                Locale l = builder
 260.119 +                    .setLanguage(idl)
 260.120 +                    .setScript(ids)
 260.121 +                    .setRegion(idc)
 260.122 +                    .setVariant(idv)
 260.123 +                    .build();
 260.124 +                assertEquals(msg + "language", idl, l.getLanguage());
 260.125 +                assertEquals(msg + "script", ids, l.getScript());
 260.126 +                assertEquals(msg + "country", idc, l.getCountry());
 260.127 +                assertEquals(msg + "variant", idv, l.getVariant());
 260.128 +                assertEquals(msg + "tag", tag, l.toLanguageTag());
 260.129 +                assertEquals(msg + "id", id, l.toString());
 260.130 +            }
 260.131 +            catch (IllegalArgumentException e) {
 260.132 +                errln(msg + e.getMessage());
 260.133 +            }
 260.134 +        }
 260.135 +    }
 260.136 +
 260.137 +    /**
 260.138 +     * Test that locale construction works with 'multiple variants'.
 260.139 +     * <p>
 260.140 +     * The string "Newer__Yorker" is treated as three subtags,
 260.141 +     * "Newer", "", and "Yorker", and concatenated into one
 260.142 +     * subtag by omitting empty subtags and joining the remainer
 260.143 +     * with underscores.  So the resulting variant tag is "Newer_Yorker".
 260.144 +     * Note that 'New' and 'York' are invalid BCP47 variant subtags
 260.145 +     * because they are too short.
 260.146 +     */
 260.147 +    public void testCreateLocaleMultipleVariants() {
 260.148 +
 260.149 +        String[] valids = {
 260.150 +            "en-Latn-US-Newer-Yorker",  "en_US_Newer_Yorker_#Latn",
 260.151 +            "en-Latn-Newer-Yorker",     "en__Newer_Yorker_#Latn",
 260.152 +            "en-US-Newer-Yorker",       "en_US_Newer_Yorker",
 260.153 +            "en-Newer-Yorker",          "en__Newer_Yorker",
 260.154 +            "und-Latn-US-Newer-Yorker", "_US_Newer_Yorker_#Latn",
 260.155 +            "und-Latn-Newer-Yorker",    "",
 260.156 +            "und-US-Newer-Yorker",      "_US_Newer_Yorker",
 260.157 +            "und-Newer-Yorker",         "",
 260.158 +        };
 260.159 +
 260.160 +        Builder builder = new Builder(); // lenient variant
 260.161 +
 260.162 +        final String idv = "Newer_Yorker";
 260.163 +        for (int i = 0; i < valids.length; i += 2) {
 260.164 +            String tag = valids[i];
 260.165 +            String id = valids[i+1];
 260.166 +
 260.167 +            String idl = (i & 8) == 0 ? l : "";
 260.168 +            String ids = (i & 4) == 0 ? s : "";
 260.169 +            String idc = (i & 2) == 0 ? c : "";
 260.170 +
 260.171 +            String msg = String.valueOf(i/2) + ": " + tag + " ";
 260.172 +            try {
 260.173 +                Locale l = builder
 260.174 +                    .setLanguage(idl)
 260.175 +                    .setScript(ids)
 260.176 +                    .setRegion(idc)
 260.177 +                    .setVariant(idv)
 260.178 +                    .build();
 260.179 +
 260.180 +                assertEquals(msg + " language", idl, l.getLanguage());
 260.181 +                assertEquals(msg + " script", ids, l.getScript());
 260.182 +                assertEquals(msg + " country", idc, l.getCountry());
 260.183 +                assertEquals(msg + " variant", idv, l.getVariant());
 260.184 +
 260.185 +                assertEquals(msg + "tag", tag, l.toLanguageTag());
 260.186 +                assertEquals(msg + "id", id, l.toString());
 260.187 +            }
 260.188 +            catch (IllegalArgumentException e) {
 260.189 +                errln(msg + e.getMessage());
 260.190 +            }
 260.191 +        }
 260.192 +    }
 260.193 +
 260.194 +    /**
 260.195 +     * Ensure that all these invalid formats are not recognized by
 260.196 +     * forLanguageTag.
 260.197 +     */
 260.198 +    public void testCreateLocaleCanonicalInvalidSeparator() {
 260.199 +        String[] invalids = {
 260.200 +            // trailing separator
 260.201 +            "en_Latn_US_NewYork_",
 260.202 +            "en_Latn_US_",
 260.203 +            "en_Latn_",
 260.204 +            "en_",
 260.205 +            "_",
 260.206 +
 260.207 +            // double separator
 260.208 +            "en_Latn_US__NewYork",
 260.209 +            "_Latn_US__NewYork",
 260.210 +            "en_US__NewYork",
 260.211 +            "_US__NewYork",
 260.212 +
 260.213 +            // are these OK?
 260.214 +            // "en_Latn__US_NewYork", // variant is 'US_NewYork'
 260.215 +            // "_Latn__US_NewYork", // variant is 'US_NewYork'
 260.216 +            // "en__Latn_US_NewYork", // variant is 'Latn_US_NewYork'
 260.217 +            // "en__US_NewYork", // variant is 'US_NewYork'
 260.218 +
 260.219 +            // double separator without language or script
 260.220 +            "__US",
 260.221 +            "__NewYork",
 260.222 +
 260.223 +            // triple separator anywhere except within variant
 260.224 +            "en___NewYork",
 260.225 +            "en_Latn___NewYork",
 260.226 +            "_Latn___NewYork",
 260.227 +            "___NewYork",
 260.228 +        };
 260.229 +
 260.230 +        for (int i = 0; i < invalids.length; ++i) {
 260.231 +            String id = invalids[i];
 260.232 +            Locale l = Locale.forLanguageTag(id);
 260.233 +            assertEquals(id, "und", l.toLanguageTag());
 260.234 +        }
 260.235 +    }
 260.236 +
 260.237 +    /**
 260.238 +     * Ensure that all current locale ids parse.  Use DateFormat as a proxy
 260.239 +     * for all current locale ids.
 260.240 +     */
 260.241 +    public void testCurrentLocales() {
 260.242 +        Locale[] locales = java.text.DateFormat.getAvailableLocales();
 260.243 +        Builder builder = new Builder();
 260.244 +
 260.245 +        for (Locale target : locales) {
 260.246 +            String tag = target.toLanguageTag();
 260.247 +
 260.248 +            // the tag recreates the original locale,
 260.249 +            // except no_NO_NY
 260.250 +            Locale tagResult = Locale.forLanguageTag(tag);
 260.251 +            if (!target.getVariant().equals("NY")) {
 260.252 +                assertEquals("tagResult", target, tagResult);
 260.253 +            }
 260.254 +
 260.255 +            // the builder also recreates the original locale,
 260.256 +            // except ja_JP_JP, th_TH_TH and no_NO_NY
 260.257 +            Locale builderResult = builder.setLocale(target).build();
 260.258 +            if (target.getVariant().length() != 2) {
 260.259 +                assertEquals("builderResult", target, builderResult);
 260.260 +            }
 260.261 +        }
 260.262 +    }
 260.263 +
 260.264 +    /**
 260.265 +     * Ensure that all icu locale ids parse.
 260.266 +     */
 260.267 +    public void testIcuLocales() throws Exception {
 260.268 +        BufferedReader br = new BufferedReader(
 260.269 +            new InputStreamReader(
 260.270 +                LocaleEnhanceTest.class.getResourceAsStream("icuLocales.txt"),
 260.271 +                "UTF-8"));
 260.272 +        String id = null;
 260.273 +        while (null != (id = br.readLine())) {
 260.274 +            Locale result = Locale.forLanguageTag(id);
 260.275 +            assertEquals("ulocale", id, result.toLanguageTag());
 260.276 +        }
 260.277 +    }
 260.278 +
 260.279 +    ///
 260.280 +    /// Compatibility tests
 260.281 +    ///
 260.282 +
 260.283 +    public void testConstructor() {
 260.284 +        // all the old weirdness still holds, no new weirdness
 260.285 +        String[][] tests = {
 260.286 +            // language to lower case, region to upper, variant unchanged
 260.287 +            // short
 260.288 +            { "X", "y", "z", "x", "Y" },
 260.289 +            // long
 260.290 +            { "xXxXxXxXxXxX", "yYyYyYyYyYyYyYyY", "zZzZzZzZzZzZzZzZ",
 260.291 +              "xxxxxxxxxxxx", "YYYYYYYYYYYYYYYY" },
 260.292 +            // mapped language ids
 260.293 +            { "he", "IW", "", "iw" },
 260.294 +            { "iw", "IW", "", "iw" },
 260.295 +            { "yi", "DE", "", "ji" },
 260.296 +            { "ji", "DE", "", "ji" },
 260.297 +            { "id", "ID", "", "in" },
 260.298 +            { "in", "ID", "", "in" },
 260.299 +            // special variants
 260.300 +            { "ja", "JP", "JP" },
 260.301 +            { "th", "TH", "TH" },
 260.302 +            { "no", "NO", "NY" },
 260.303 +            { "no", "NO", "NY" },
 260.304 +            // no canonicalization of 3-letter language codes
 260.305 +            { "eng", "US", "" }
 260.306 +        };
 260.307 +        for (int i = 0; i < tests.length; ++ i) {
 260.308 +            String[] test = tests[i];
 260.309 +            String id = String.valueOf(i);
 260.310 +            Locale locale = new Locale(test[0], test[1], test[2]);
 260.311 +            assertEquals(id + " lang", test.length > 3 ? test[3] : test[0], locale.getLanguage());
 260.312 +            assertEquals(id + " region", test.length > 4 ? test[4] : test[1], locale.getCountry());
 260.313 +            assertEquals(id + " variant", test.length > 5 ? test[5] : test[2], locale.getVariant());
 260.314 +        }
 260.315 +    }
 260.316 +
 260.317 +    ///
 260.318 +    /// Locale API tests.
 260.319 +    ///
 260.320 +
 260.321 +    public void testGetScript() {
 260.322 +        // forLanguageTag normalizes case
 260.323 +        Locale locale = Locale.forLanguageTag("und-latn");
 260.324 +        assertEquals("forLanguageTag", "Latn", locale.getScript());
 260.325 +
 260.326 +        // Builder normalizes case
 260.327 +        locale = new Builder().setScript("LATN").build();
 260.328 +        assertEquals("builder", "Latn", locale.getScript());
 260.329 +
 260.330 +        // empty string is returned, not null, if there is no script
 260.331 +        locale = Locale.forLanguageTag("und");
 260.332 +        assertEquals("script is empty string", "", locale.getScript());
 260.333 +    }
 260.334 +
 260.335 +    public void testGetExtension() {
 260.336 +        // forLanguageTag does NOT normalize to hyphen
 260.337 +        Locale locale = Locale.forLanguageTag("und-a-some_ex-tension");
 260.338 +        assertEquals("some_ex-tension", null, locale.getExtension('a'));
 260.339 +
 260.340 +        // regular extension
 260.341 +        locale = new Builder().setExtension('a', "some-ex-tension").build();
 260.342 +        assertEquals("builder", "some-ex-tension", locale.getExtension('a'));
 260.343 +
 260.344 +        // returns null if extension is not present
 260.345 +        assertEquals("empty b", null, locale.getExtension('b'));
 260.346 +
 260.347 +        // throws exception if extension tag is illegal
 260.348 +        new ExpectIAE() { public void call() { Locale.forLanguageTag("").getExtension('\uD800'); }};
 260.349 +
 260.350 +        // 'x' is not an extension, it's a private use tag, but it's accessed through this API
 260.351 +        locale = Locale.forLanguageTag("x-y-z-blork");
 260.352 +        assertEquals("x", "y-z-blork", locale.getExtension('x'));
 260.353 +    }
 260.354 +
 260.355 +    public void testGetExtensionKeys() {
 260.356 +        Locale locale = Locale.forLanguageTag("und-a-xx-yy-b-zz-ww");
 260.357 +        Set<Character> result = locale.getExtensionKeys();
 260.358 +        assertEquals("result size", 2, result.size());
 260.359 +        assertTrue("'a','b'", result.contains('a') && result.contains('b'));
 260.360 +
 260.361 +        // result is not mutable
 260.362 +        try {
 260.363 +            result.add('x');
 260.364 +            errln("expected exception on add to extension key set");
 260.365 +        }
 260.366 +        catch (UnsupportedOperationException e) {
 260.367 +            // ok
 260.368 +        }
 260.369 +
 260.370 +        // returns empty set if no extensions
 260.371 +        locale = Locale.forLanguageTag("und");
 260.372 +        assertTrue("empty result", locale.getExtensionKeys().isEmpty());
 260.373 +    }
 260.374 +
 260.375 +    public void testGetUnicodeLocaleAttributes() {
 260.376 +        Locale locale = Locale.forLanguageTag("en-US-u-abc-def");
 260.377 +        Set<String> attributes = locale.getUnicodeLocaleAttributes();
 260.378 +        assertEquals("number of attributes", 2, attributes.size());
 260.379 +        assertTrue("attribute abc", attributes.contains("abc"));
 260.380 +        assertTrue("attribute def", attributes.contains("def"));
 260.381 +
 260.382 +        locale = Locale.forLanguageTag("en-US-u-ca-gregory");
 260.383 +        attributes = locale.getUnicodeLocaleAttributes();
 260.384 +        assertTrue("empty attributes", attributes.isEmpty());
 260.385 +    }
 260.386 +
 260.387 +    public void testGetUnicodeLocaleType() {
 260.388 +        Locale locale = Locale.forLanguageTag("und-u-co-japanese-nu-thai");
 260.389 +        assertEquals("collation", "japanese", locale.getUnicodeLocaleType("co"));
 260.390 +        assertEquals("numbers", "thai", locale.getUnicodeLocaleType("nu"));
 260.391 +
 260.392 +        // Unicode locale extension key is case insensitive
 260.393 +        assertEquals("key case", "japanese", locale.getUnicodeLocaleType("Co"));
 260.394 +
 260.395 +        // if keyword is not present, returns null
 260.396 +        assertEquals("locale keyword not present", null, locale.getUnicodeLocaleType("xx"));
 260.397 +
 260.398 +        // if no locale extension is set, returns null
 260.399 +        locale = Locale.forLanguageTag("und");
 260.400 +        assertEquals("locale extension not present", null, locale.getUnicodeLocaleType("co"));
 260.401 +
 260.402 +        // typeless keyword
 260.403 +        locale = Locale.forLanguageTag("und-u-kn");
 260.404 +        assertEquals("typeless keyword", "", locale.getUnicodeLocaleType("kn"));
 260.405 +
 260.406 +        // invalid keys throw exception
 260.407 +        new ExpectIAE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType("q"); }};
 260.408 +        new ExpectIAE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType("abcdefghi"); }};
 260.409 +
 260.410 +        // null argument throws exception
 260.411 +        new ExpectNPE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType(null); }};
 260.412 +    }
 260.413 +
 260.414 +    public void testGetUnicodeLocaleKeys() {
 260.415 +        Locale locale = Locale.forLanguageTag("und-u-co-japanese-nu-thai");
 260.416 +        Set<String> result = locale.getUnicodeLocaleKeys();
 260.417 +        assertEquals("two keys", 2, result.size());
 260.418 +        assertTrue("co and nu", result.contains("co") && result.contains("nu"));
 260.419 +
 260.420 +        // result is not modifiable
 260.421 +        try {
 260.422 +            result.add("frobozz");
 260.423 +            errln("expected exception when add to locale key set");
 260.424 +        }
 260.425 +        catch (UnsupportedOperationException e) {
 260.426 +            // ok
 260.427 +        }
 260.428 +    }
 260.429 +
 260.430 +    public void testPrivateUseExtension() {
 260.431 +        Locale locale = Locale.forLanguageTag("x-y-x-blork-");
 260.432 +        assertEquals("blork", "y-x-blork", locale.getExtension(Locale.PRIVATE_USE_EXTENSION));
 260.433 +
 260.434 +        locale = Locale.forLanguageTag("und");
 260.435 +        assertEquals("no privateuse", null, locale.getExtension(Locale.PRIVATE_USE_EXTENSION));
 260.436 +    }
 260.437 +
 260.438 +    public void testToLanguageTag() {
 260.439 +        // lots of normalization to test here
 260.440 +        // test locales created using the constructor
 260.441 +        String[][] tests = {
 260.442 +            // empty locale canonicalizes to 'und'
 260.443 +            { "", "", "", "und" },
 260.444 +            // variant alone is not a valid Locale, but has a valid language tag
 260.445 +            { "", "", "NewYork", "und-NewYork" },
 260.446 +            // standard valid locales
 260.447 +            { "", "Us", "", "und-US" },
 260.448 +            { "", "US", "NewYork", "und-US-NewYork" },
 260.449 +            { "EN", "", "", "en" },
 260.450 +            { "EN", "", "NewYork", "en-NewYork" },
 260.451 +            { "EN", "US", "", "en-US" },
 260.452 +            { "EN", "US", "NewYork", "en-US-NewYork" },
 260.453 +            // underscore in variant will be emitted as multiple variant subtags
 260.454 +            { "en", "US", "Newer_Yorker", "en-US-Newer-Yorker" },
 260.455 +            // invalid variant subtags are appended as private use
 260.456 +            { "en", "US", "new_yorker", "en-US-x-lvariant-new-yorker" },
 260.457 +            // the first invalid variant subtags and following variant subtags are appended as private use
 260.458 +            { "en", "US", "Windows_XP_Home", "en-US-Windows-x-lvariant-XP-Home" },
 260.459 +            // too long variant and following variant subtags disappear
 260.460 +            { "en", "US", "WindowsVista_SP2", "en-US" },
 260.461 +            // invalid region subtag disappears
 260.462 +            { "en", "USA", "", "en" },
 260.463 +            // invalid language tag disappears
 260.464 +            { "e", "US", "", "und-US" },
 260.465 +            // three-letter language tags are not canonicalized
 260.466 +            { "Eng", "", "", "eng" },
 260.467 +            // legacy languages canonicalize to modern equivalents
 260.468 +            { "he", "IW", "", "he-IW" },
 260.469 +            { "iw", "IW", "", "he-IW" },
 260.470 +            { "yi", "DE", "", "yi-DE" },
 260.471 +            { "ji", "DE", "", "yi-DE" },
 260.472 +            { "id", "ID", "", "id-ID" },
 260.473 +            { "in", "ID", "", "id-ID" },
 260.474 +            // special values are converted on output
 260.475 +            { "ja", "JP", "JP", "ja-JP-u-ca-japanese-x-lvariant-JP" },
 260.476 +            { "th", "TH", "TH", "th-TH-u-nu-thai-x-lvariant-TH" },
 260.477 +            { "no", "NO", "NY", "nn-NO" }
 260.478 +        };
 260.479 +        for (int i = 0; i < tests.length; ++i) {
 260.480 +            String[] test = tests[i];
 260.481 +            Locale locale = new Locale(test[0], test[1], test[2]);
 260.482 +            assertEquals("case " + i, test[3], locale.toLanguageTag());
 260.483 +        }
 260.484 +    }
 260.485 +
 260.486 +    public void testForLanguageTag() {
 260.487 +        // forLanguageTag implements the 'Language-Tag' production of
 260.488 +        // BCP47, so it handles private use and grandfathered tags,
 260.489 +        // unlike locale builder.  Tags listed below (except for the
 260.490 +        // sample private use tags) come from 4646bis Feb 29, 2009.
 260.491 +
 260.492 +        String[][] tests = {
 260.493 +            // private use tags only
 260.494 +            { "x-abc", "und-x-abc" },
 260.495 +            { "x-a-b-c", "und-x-a-b-c" },
 260.496 +            { "x-a-12345678", "und-x-a-12345678" },
 260.497 +
 260.498 +            // grandfathered tags with preferred mappings
 260.499 +            { "i-ami", "ami" },
 260.500 +            { "i-bnn", "bnn" },
 260.501 +            { "i-hak", "hak" },
 260.502 +            { "i-klingon", "tlh" },
 260.503 +            { "i-lux", "lb" }, // two-letter tag
 260.504 +            { "i-navajo", "nv" }, // two-letter tag
 260.505 +            { "i-pwn", "pwn" },
 260.506 +            { "i-tao", "tao" },
 260.507 +            { "i-tay", "tay" },
 260.508 +            { "i-tsu", "tsu" },
 260.509 +            { "art-lojban", "jbo" },
 260.510 +            { "no-bok", "nb" },
 260.511 +            { "no-nyn", "nn" },
 260.512 +            { "sgn-BE-FR", "sfb" },
 260.513 +            { "sgn-BE-NL", "vgt" },
 260.514 +            { "sgn-CH-DE", "sgg" },
 260.515 +            { "zh-guoyu", "cmn" },
 260.516 +            { "zh-hakka", "hak" },
 260.517 +            { "zh-min-nan", "nan" },
 260.518 +            { "zh-xiang", "hsn" },
 260.519 +
 260.520 +            // grandfathered irregular tags, no preferred mappings, drop illegal fields
 260.521 +            // from end.  If no subtag is mappable, fallback to 'und'
 260.522 +            { "i-default", "en-x-i-default" },
 260.523 +            { "i-enochian", "und-x-i-enochian" },
 260.524 +            { "i-mingo", "see-x-i-mingo" },
 260.525 +            { "en-GB-oed", "en-GB-x-oed" },
 260.526 +            { "zh-min", "nan-x-zh-min" },
 260.527 +            { "cel-gaulish", "xtg-x-cel-gaulish" },
 260.528 +        };
 260.529 +        for (int i = 0; i < tests.length; ++i) {
 260.530 +            String[] test = tests[i];
 260.531 +            Locale locale = Locale.forLanguageTag(test[0]);
 260.532 +            assertEquals("grandfathered case " + i, test[1], locale.toLanguageTag());
 260.533 +        }
 260.534 +
 260.535 +        // forLanguageTag ignores everything past the first place it encounters
 260.536 +        // a syntax error
 260.537 +        tests = new String[][] {
 260.538 +            { "valid",
 260.539 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z",
 260.540 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z" },
 260.541 +            { "segment of private use tag too long",
 260.542 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-123456789-z",
 260.543 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y" },
 260.544 +            { "segment of private use tag is empty",
 260.545 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y--12345678-z",
 260.546 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y" },
 260.547 +            { "first segment of private use tag is empty",
 260.548 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x--y-12345678-z",
 260.549 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def" },
 260.550 +            { "illegal extension tag",
 260.551 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-\uD800-y-12345678-z",
 260.552 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def" },
 260.553 +            { "locale subtag with no value",
 260.554 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z",
 260.555 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z" },
 260.556 +            { "locale key subtag invalid",
 260.557 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-123456789-def-x-y-12345678-z",
 260.558 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc" },
 260.559 +            // locale key subtag invalid in earlier position, all following subtags
 260.560 +            // dropped (and so the locale extension dropped as well)
 260.561 +            { "locale key subtag invalid in earlier position",
 260.562 +              "en-US-Newer-Yorker-a-bb-cc-dd-u-123456789-abc-bb-def-x-y-12345678-z",
 260.563 +              "en-US-Newer-Yorker-a-bb-cc-dd" },
 260.564 +        };
 260.565 +        for (int i = 0; i < tests.length; ++i) {
 260.566 +            String[] test = tests[i];
 260.567 +            String msg = "syntax error case " + i + " " + test[0];
 260.568 +            try {
 260.569 +                Locale locale = Locale.forLanguageTag(test[1]);
 260.570 +                assertEquals(msg, test[2], locale.toLanguageTag());
 260.571 +            }
 260.572 +            catch (IllegalArgumentException e) {
 260.573 +                errln(msg + " caught exception: " + e);
 260.574 +            }
 260.575 +        }
 260.576 +
 260.577 +        // duplicated extension are just ignored
 260.578 +        Locale locale = Locale.forLanguageTag("und-d-aa-00-bb-01-D-AA-10-cc-11-c-1234");
 260.579 +        assertEquals("extension", "aa-00-bb-01", locale.getExtension('d'));
 260.580 +        assertEquals("extension c", "1234", locale.getExtension('c'));
 260.581 +
 260.582 +        // redundant Unicode locale keys in an extension are ignored
 260.583 +        locale = Locale.forLanguageTag("und-u-aa-000-bb-001-bB-002-cc-003-c-1234");
 260.584 +        assertEquals("Unicode keywords", "aa-000-bb-001-cc-003", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION));
 260.585 +        assertEquals("Duplicated Unicode locake key followed by an extension", "1234", locale.getExtension('c'));
 260.586 +    }
 260.587 +
 260.588 +    public void testGetDisplayScript() {
 260.589 +        Locale latnLocale = Locale.forLanguageTag("und-latn");
 260.590 +        Locale hansLocale = Locale.forLanguageTag("und-hans");
 260.591 +
 260.592 +        Locale oldLocale = Locale.getDefault();
 260.593 +
 260.594 +        Locale.setDefault(Locale.US);
 260.595 +        assertEquals("latn US", "Latin", latnLocale.getDisplayScript());
 260.596 +        assertEquals("hans US", "Simplified Han", hansLocale.getDisplayScript());
 260.597 +
 260.598 +        // note, no localization data yet other than US
 260.599 +        // this should break when we have localization data for DE
 260.600 +        Locale.setDefault(Locale.GERMANY);
 260.601 +        assertEquals("latn DE", "Latin", latnLocale.getDisplayScript());
 260.602 +        assertEquals("hans DE", "Simplified Han", hansLocale.getDisplayScript());
 260.603 +
 260.604 +        Locale.setDefault(oldLocale);
 260.605 +    }
 260.606 +
 260.607 +    public void testGetDisplayScriptWithLocale() {
 260.608 +        Locale latnLocale = Locale.forLanguageTag("und-latn");
 260.609 +        Locale hansLocale = Locale.forLanguageTag("und-hans");
 260.610 +
 260.611 +        assertEquals("latn US", "Latin", latnLocale.getDisplayScript(Locale.US));
 260.612 +        assertEquals("hans US", "Simplified Han", hansLocale.getDisplayScript(Locale.US));
 260.613 +
 260.614 +        // note, no localization data yet other than US
 260.615 +        // this should break when we have localization data for DE
 260.616 +        assertEquals("latn DE", "Latin", latnLocale.getDisplayScript(Locale.GERMANY));
 260.617 +        assertEquals("hans DE", "Simplified Han", hansLocale.getDisplayScript(Locale.GERMANY));
 260.618 +    }
 260.619 +
 260.620 +    ///
 260.621 +    /// Builder tests
 260.622 +    ///
 260.623 +
 260.624 +    public void testBuilderSetLocale() {
 260.625 +        Builder builder = new Builder();
 260.626 +        Builder lenientBuilder = new Builder();
 260.627 +
 260.628 +        String languageTag = "en-Latn-US-NewYork-a-bb-ccc-u-co-japanese-x-y-z";
 260.629 +        String target = "en-Latn-US-NewYork-a-bb-ccc-u-co-japanese-x-y-z";
 260.630 +
 260.631 +        Locale locale = Locale.forLanguageTag(languageTag);
 260.632 +        Locale result = lenientBuilder
 260.633 +            .setLocale(locale)
 260.634 +            .build();
 260.635 +        assertEquals("long tag", target, result.toLanguageTag());
 260.636 +        assertEquals("long tag", locale, result);
 260.637 +
 260.638 +        // null is illegal
 260.639 +        new BuilderNPE("locale") {
 260.640 +            public void call() { b.setLocale(null); }
 260.641 +        };
 260.642 +
 260.643 +        // builder canonicalizes the three legacy locales:
 260.644 +        // ja_JP_JP, th_TH_TH, no_NY_NO.
 260.645 +        locale = builder.setLocale(new Locale("ja", "JP", "JP")).build();
 260.646 +        assertEquals("ja_JP_JP languagetag", "ja-JP-u-ca-japanese", locale.toLanguageTag());
 260.647 +        assertEquals("ja_JP_JP variant", "", locale.getVariant());
 260.648 +
 260.649 +        locale = builder.setLocale(new Locale("th", "TH", "TH")).build();
 260.650 +        assertEquals("th_TH_TH languagetag", "th-TH-u-nu-thai", locale.toLanguageTag());
 260.651 +        assertEquals("th_TH_TH variant", "", locale.getVariant());
 260.652 +
 260.653 +        locale = builder.setLocale(new Locale("no", "NO", "NY")).build();
 260.654 +        assertEquals("no_NO_NY languagetag", "nn-NO", locale.toLanguageTag());
 260.655 +        assertEquals("no_NO_NY language", "nn", locale.getLanguage());
 260.656 +        assertEquals("no_NO_NY variant", "", locale.getVariant());
 260.657 +
 260.658 +        // non-canonical, non-legacy locales are invalid
 260.659 +        new BuilderILE("123_4567_89") {
 260.660 +            public void call() {
 260.661 +                b.setLocale(new Locale("123", "4567", "89"));
 260.662 +            }
 260.663 +        };
 260.664 +    }
 260.665 +
 260.666 +    public void testBuilderSetLanguageTag() {
 260.667 +        String source = "eN-LaTn-Us-NewYork-A-Xx-B-Yy-X-1-2-3";
 260.668 +        String target = "en-Latn-US-NewYork-a-xx-b-yy-x-1-2-3";
 260.669 +        Builder builder = new Builder();
 260.670 +        String result = builder
 260.671 +            .setLanguageTag(source)
 260.672 +            .build()
 260.673 +            .toLanguageTag();
 260.674 +        assertEquals("language", target, result);
 260.675 +
 260.676 +        // redundant extensions cause a failure
 260.677 +        new BuilderILE() { public void call() { b.setLanguageTag("und-a-xx-yy-b-ww-A-00-11-c-vv"); }};
 260.678 +
 260.679 +        // redundant Unicode locale extension keys within an Unicode locale extension cause a failure
 260.680 +        new BuilderILE() { public void call() { b.setLanguageTag("und-u-nu-thai-NU-chinese-xx-1234"); }};
 260.681 +    }
 260.682 +
 260.683 +    public void testBuilderSetLanguage() {
 260.684 +        // language is normalized to lower case
 260.685 +        String source = "eN";
 260.686 +        String target = "en";
 260.687 +        String defaulted = "";
 260.688 +        Builder builder = new Builder();
 260.689 +        String result = builder
 260.690 +            .setLanguage(source)
 260.691 +            .build()
 260.692 +            .getLanguage();
 260.693 +        assertEquals("en", target, result);
 260.694 +
 260.695 +        // setting with empty resets
 260.696 +        result = builder
 260.697 +            .setLanguage(target)
 260.698 +            .setLanguage("")
 260.699 +            .build()
 260.700 +            .getLanguage();
 260.701 +        assertEquals("empty", defaulted, result);
 260.702 +
 260.703 +        // setting with null resets too
 260.704 +        result = builder
 260.705 +                .setLanguage(target)
 260.706 +                .setLanguage(null)
 260.707 +                .build()
 260.708 +                .getLanguage();
 260.709 +        assertEquals("null", defaulted, result);
 260.710 +
 260.711 +        // language codes must be 2-8 alpha
 260.712 +        // for forwards compatibility, 4-alpha and 5-8 alpha (registered)
 260.713 +        // languages are accepted syntax
 260.714 +        new BuilderILE("q", "abcdefghi", "13") { public void call() { b.setLanguage(arg); }};
 260.715 +
 260.716 +        // language code validation is NOT performed, any 2-8-alpha passes
 260.717 +        assertNotNull("2alpha", builder.setLanguage("zz").build());
 260.718 +        assertNotNull("8alpha", builder.setLanguage("abcdefgh").build());
 260.719 +
 260.720 +        // three-letter language codes are NOT canonicalized to two-letter
 260.721 +        result = builder
 260.722 +            .setLanguage("eng")
 260.723 +            .build()
 260.724 +            .getLanguage();
 260.725 +        assertEquals("eng", "eng", result);
 260.726 +    }
 260.727 +
 260.728 +    public void testBuilderSetScript() {
 260.729 +        // script is normalized to title case
 260.730 +        String source = "lAtN";
 260.731 +        String target = "Latn";
 260.732 +        String defaulted = "";
 260.733 +        Builder builder = new Builder();
 260.734 +        String result = builder
 260.735 +            .setScript(source)
 260.736 +            .build()
 260.737 +            .getScript();
 260.738 +        assertEquals("script", target, result);
 260.739 +
 260.740 +        // setting with empty resets
 260.741 +        result = builder
 260.742 +            .setScript(target)
 260.743 +            .setScript("")
 260.744 +            .build()
 260.745 +            .getScript();
 260.746 +        assertEquals("empty", defaulted, result);
 260.747 +
 260.748 +        // settting with null also resets
 260.749 +        result = builder
 260.750 +                .setScript(target)
 260.751 +                .setScript(null)
 260.752 +                .build()
 260.753 +                .getScript();
 260.754 +        assertEquals("null", defaulted, result);
 260.755 +
 260.756 +        // ill-formed script codes throw IAE
 260.757 +        // must be 4alpha
 260.758 +        new BuilderILE("abc", "abcde", "l3tn") { public void call() { b.setScript(arg); }};
 260.759 +
 260.760 +        // script code validation is NOT performed, any 4-alpha passes
 260.761 +        assertEquals("4alpha", "Wxyz", builder.setScript("wxyz").build().getScript());
 260.762 +    }
 260.763 +
 260.764 +    public void testBuilderSetRegion() {
 260.765 +        // region is normalized to upper case
 260.766 +        String source = "uS";
 260.767 +        String target = "US";
 260.768 +        String defaulted = "";
 260.769 +        Builder builder = new Builder();
 260.770 +        String result = builder
 260.771 +            .setRegion(source)
 260.772 +            .build()
 260.773 +            .getCountry();
 260.774 +        assertEquals("us", target, result);
 260.775 +
 260.776 +        // setting with empty resets
 260.777 +        result = builder
 260.778 +            .setRegion(target)
 260.779 +            .setRegion("")
 260.780 +            .build()
 260.781 +            .getCountry();
 260.782 +        assertEquals("empty", defaulted, result);
 260.783 +
 260.784 +        // setting with null also resets
 260.785 +        result = builder
 260.786 +                .setRegion(target)
 260.787 +                .setRegion(null)
 260.788 +                .build()
 260.789 +                .getCountry();
 260.790 +        assertEquals("null", defaulted, result);
 260.791 +
 260.792 +        // ill-formed region codes throw IAE
 260.793 +        // 2 alpha or 3 numeric
 260.794 +        new BuilderILE("q", "abc", "12", "1234", "a3", "12a") { public void call() { b.setRegion(arg); }};
 260.795 +
 260.796 +        // region code validation is NOT performed, any 2-alpha or 3-digit passes
 260.797 +        assertEquals("2alpha", "ZZ", builder.setRegion("ZZ").build().getCountry());
 260.798 +        assertEquals("3digit", "000", builder.setRegion("000").build().getCountry());
 260.799 +    }
 260.800 +
 260.801 +    public void testBuilderSetVariant() {
 260.802 +        // Variant case is not normalized in lenient variant mode
 260.803 +        String source = "NewYork";
 260.804 +        String target = source;
 260.805 +        String defaulted = "";
 260.806 +        Builder builder = new Builder();
 260.807 +        String result = builder
 260.808 +            .setVariant(source)
 260.809 +            .build()
 260.810 +            .getVariant();
 260.811 +        assertEquals("NewYork", target, result);
 260.812 +
 260.813 +        result = builder
 260.814 +            .setVariant("NeWeR_YoRkEr")
 260.815 +            .build()
 260.816 +            .toLanguageTag();
 260.817 +        assertEquals("newer yorker", "und-NeWeR-YoRkEr", result);
 260.818 +
 260.819 +        // subtags of variant are NOT reordered
 260.820 +        result = builder
 260.821 +            .setVariant("zzzzz_yyyyy_xxxxx")
 260.822 +            .build()
 260.823 +            .getVariant();
 260.824 +        assertEquals("zyx", "zzzzz_yyyyy_xxxxx", result);
 260.825 +
 260.826 +        // setting to empty resets
 260.827 +        result = builder
 260.828 +            .setVariant(target)
 260.829 +            .setVariant("")
 260.830 +            .build()
 260.831 +            .getVariant();
 260.832 +        assertEquals("empty", defaulted, result);
 260.833 +
 260.834 +        // setting to null also resets
 260.835 +        result = builder
 260.836 +                .setVariant(target)
 260.837 +                .setVariant(null)
 260.838 +                .build()
 260.839 +                .getVariant();
 260.840 +        assertEquals("null", defaulted, result);
 260.841 +
 260.842 +        // ill-formed variants throw IAE
 260.843 +        // digit followed by 3-7 characters, or alpha followed by 4-8 characters.
 260.844 +        new BuilderILE("abcd", "abcdefghi", "1ab", "1abcdefgh") { public void call() { b.setVariant(arg); }};
 260.845 +
 260.846 +        // 4 characters is ok as long as the first is a digit
 260.847 +        assertEquals("digit+3alpha", "1abc", builder.setVariant("1abc").build().getVariant());
 260.848 +
 260.849 +        // all subfields must conform
 260.850 +        new BuilderILE("abcde-fg") { public void call() { b.setVariant(arg); }};
 260.851 +    }
 260.852 +
 260.853 +    public void testBuilderSetExtension() {
 260.854 +        // upper case characters are normalized to lower case
 260.855 +        final char sourceKey = 'a';
 260.856 +        final String sourceValue = "aB-aBcdefgh-12-12345678";
 260.857 +        String target = "ab-abcdefgh-12-12345678";
 260.858 +        Builder builder = new Builder();
 260.859 +        String result = builder
 260.860 +            .setExtension(sourceKey, sourceValue)
 260.861 +            .build()
 260.862 +            .getExtension(sourceKey);
 260.863 +        assertEquals("extension", target, result);
 260.864 +
 260.865 +        // setting with empty resets
 260.866 +        result = builder
 260.867 +            .setExtension(sourceKey, sourceValue)
 260.868 +            .setExtension(sourceKey, "")
 260.869 +            .build()
 260.870 +            .getExtension(sourceKey);
 260.871 +        assertEquals("empty", null, result);
 260.872 +
 260.873 +        // setting with null also resets
 260.874 +        result = builder
 260.875 +                .setExtension(sourceKey, sourceValue)
 260.876 +                .setExtension(sourceKey, null)
 260.877 +                .build()
 260.878 +                .getExtension(sourceKey);
 260.879 +        assertEquals("null", null, result);
 260.880 +
 260.881 +        // ill-formed extension keys throw IAE
 260.882 +        // must be in [0-9a-ZA-Z]
 260.883 +        new BuilderILE("$") { public void call() { b.setExtension('$', sourceValue); }};
 260.884 +
 260.885 +        // each segment of value must be 2-8 alphanum
 260.886 +        new BuilderILE("ab-cd-123456789") { public void call() { b.setExtension(sourceKey, arg); }};
 260.887 +
 260.888 +        // no multiple hyphens.
 260.889 +        new BuilderILE("ab--cd") { public void call() { b.setExtension(sourceKey, arg); }};
 260.890 +
 260.891 +        // locale extension key has special handling
 260.892 +        Locale locale = builder
 260.893 +            .setExtension('u', "co-japanese")
 260.894 +            .build();
 260.895 +        assertEquals("locale extension", "japanese", locale.getUnicodeLocaleType("co"));
 260.896 +
 260.897 +        // locale extension has same behavior with set locale keyword
 260.898 +        Locale locale2 = builder
 260.899 +            .setUnicodeLocaleKeyword("co", "japanese")
 260.900 +            .build();
 260.901 +        assertEquals("locales with extension", locale, locale2);
 260.902 +
 260.903 +        // setting locale extension overrides all previous calls to setLocaleKeyword
 260.904 +        Locale locale3 = builder
 260.905 +            .setExtension('u', "xxx-nu-thai")
 260.906 +            .build();
 260.907 +        assertEquals("remove co", null, locale3.getUnicodeLocaleType("co"));
 260.908 +        assertEquals("override thai", "thai", locale3.getUnicodeLocaleType("nu"));
 260.909 +        assertEquals("override attribute", 1, locale3.getUnicodeLocaleAttributes().size());
 260.910 +
 260.911 +        // setting locale keyword extends values already set by the locale extension
 260.912 +        Locale locale4 = builder
 260.913 +            .setUnicodeLocaleKeyword("co", "japanese")
 260.914 +            .build();
 260.915 +        assertEquals("extend", "japanese", locale4.getUnicodeLocaleType("co"));
 260.916 +        assertEquals("extend", "thai", locale4.getUnicodeLocaleType("nu"));
 260.917 +
 260.918 +        // locale extension subtags are reordered
 260.919 +        result = builder
 260.920 +            .clear()
 260.921 +            .setExtension('u', "456-123-zz-123-yy-456-xx-789")
 260.922 +            .build()
 260.923 +            .toLanguageTag();
 260.924 +        assertEquals("reorder", "und-u-123-456-xx-789-yy-456-zz-123", result);
 260.925 +
 260.926 +        // multiple keyword types
 260.927 +        result = builder
 260.928 +            .clear()
 260.929 +            .setExtension('u', "nu-thai-foobar")
 260.930 +            .build()
 260.931 +            .getUnicodeLocaleType("nu");
 260.932 +        assertEquals("multiple types", "thai-foobar", result);
 260.933 +
 260.934 +        // redundant locale extensions are ignored
 260.935 +        result = builder
 260.936 +            .clear()
 260.937 +            .setExtension('u', "nu-thai-NU-chinese-xx-1234")
 260.938 +            .build()
 260.939 +            .toLanguageTag();
 260.940 +        assertEquals("duplicate keys", "und-u-nu-thai-xx-1234", result);
 260.941 +    }
 260.942 +
 260.943 +    public void testBuilderAddUnicodeLocaleAttribute() {
 260.944 +        Builder builder = new Builder();
 260.945 +        Locale locale = builder
 260.946 +            .addUnicodeLocaleAttribute("def")
 260.947 +            .addUnicodeLocaleAttribute("abc")
 260.948 +            .build();
 260.949 +
 260.950 +        Set<String> uattrs = locale.getUnicodeLocaleAttributes();
 260.951 +        assertEquals("number of attributes", 2, uattrs.size());
 260.952 +        assertTrue("attribute abc", uattrs.contains("abc"));
 260.953 +        assertTrue("attribute def", uattrs.contains("def"));
 260.954 +
 260.955 +        // remove attribute
 260.956 +        locale = builder.removeUnicodeLocaleAttribute("xxx")
 260.957 +            .build();
 260.958 +
 260.959 +        assertEquals("remove bogus", 2, uattrs.size());
 260.960 +
 260.961 +        // add duplicate
 260.962 +        locale = builder.addUnicodeLocaleAttribute("abc")
 260.963 +            .build();
 260.964 +        assertEquals("add duplicate", 2, uattrs.size());
 260.965 +
 260.966 +        // null attribute throws NPE
 260.967 +        new BuilderNPE("null attribute") { public void call() { b.addUnicodeLocaleAttribute(null); }};
 260.968 +
 260.969 +        // illformed attribute throws IllformedLocaleException
 260.970 +        new BuilderILE("invalid attribute") { public void call() { b.addUnicodeLocaleAttribute("ca"); }};
 260.971 +    }
 260.972 +
 260.973 +    public void testBuildersetUnicodeLocaleKeyword() {
 260.974 +        // Note: most behavior is tested in testBuilderSetExtension
 260.975 +        Builder builder = new Builder();
 260.976 +        Locale locale = builder
 260.977 +            .setUnicodeLocaleKeyword("co", "japanese")
 260.978 +            .setUnicodeLocaleKeyword("nu", "thai")
 260.979 +            .build();
 260.980 +        assertEquals("co", "japanese", locale.getUnicodeLocaleType("co"));
 260.981 +        assertEquals("nu", "thai", locale.getUnicodeLocaleType("nu"));
 260.982 +        assertEquals("keys", 2, locale.getUnicodeLocaleKeys().size());
 260.983 +
 260.984 +        // can clear a keyword by setting to null, others remain
 260.985 +        String result = builder
 260.986 +            .setUnicodeLocaleKeyword("co", null)
 260.987 +            .build()
 260.988 +            .toLanguageTag();
 260.989 +        assertEquals("empty co", "und-u-nu-thai", result);
 260.990 +
 260.991 +        // locale keyword extension goes when all keywords are gone
 260.992 +        result = builder
 260.993 +            .setUnicodeLocaleKeyword("nu", null)
 260.994 +            .build()
 260.995 +            .toLanguageTag();
 260.996 +        assertEquals("empty nu", "und", result);
 260.997 +
 260.998 +        // locale keywords are ordered independent of order of addition
 260.999 +        result = builder
260.1000 +            .setUnicodeLocaleKeyword("zz", "012")
260.1001 +            .setUnicodeLocaleKeyword("aa", "345")
260.1002 +            .build()
260.1003 +            .toLanguageTag();
260.1004 +        assertEquals("reordered", "und-u-aa-345-zz-012", result);
260.1005 +
260.1006 +        // null keyword throws NPE
260.1007 +        new BuilderNPE("keyword") { public void call() { b.setUnicodeLocaleKeyword(null, "thai"); }};
260.1008 +
260.1009 +        // well-formed keywords are two alphanum
260.1010 +        new BuilderILE("a", "abc") { public void call() { b.setUnicodeLocaleKeyword(arg, "value"); }};
260.1011 +
260.1012 +        // well-formed values are 3-8 alphanum
260.1013 +        new BuilderILE("ab", "abcdefghi") { public void call() { b.setUnicodeLocaleKeyword("ab", arg); }};
260.1014 +    }
260.1015 +
260.1016 +    public void testBuilderPrivateUseExtension() {
260.1017 +        // normalizes hyphens to underscore, case to lower
260.1018 +        String source = "c-B-a";
260.1019 +        String target = "c-b-a";
260.1020 +        Builder builder = new Builder();
260.1021 +        String result = builder
260.1022 +            .setExtension(Locale.PRIVATE_USE_EXTENSION, source)
260.1023 +            .build()
260.1024 +            .getExtension(Locale.PRIVATE_USE_EXTENSION);
260.1025 +        assertEquals("abc", target, result);
260.1026 +
260.1027 +        // multiple hyphens are ill-formed
260.1028 +        new BuilderILE("a--b") { public void call() { b.setExtension(Locale.PRIVATE_USE_EXTENSION, arg); }};
260.1029 +    }
260.1030 +
260.1031 +    public void testBuilderClear() {
260.1032 +        String monster = "en-latn-US-NewYork-a-bb-cc-u-co-japanese-x-z-y-x-x";
260.1033 +        Builder builder = new Builder();
260.1034 +        Locale locale = Locale.forLanguageTag(monster);
260.1035 +        String result = builder
260.1036 +            .setLocale(locale)
260.1037 +            .clear()
260.1038 +            .build()
260.1039 +            .toLanguageTag();
260.1040 +        assertEquals("clear", "und", result);
260.1041 +    }
260.1042 +
260.1043 +    public void testBuilderRemoveUnicodeAttribute() {
260.1044 +        // tested in testBuilderAddUnicodeAttribute
260.1045 +    }
260.1046 +
260.1047 +    public void testBuilderBuild() {
260.1048 +        // tested in other test methods
260.1049 +    }
260.1050 +
260.1051 +    public void testSerialize() {
260.1052 +        final Locale[] testLocales = {
260.1053 +            Locale.ROOT,
260.1054 +            new Locale("en"),
260.1055 +            new Locale("en", "US"),
260.1056 +            new Locale("en", "US", "Win"),
260.1057 +            new Locale("en", "US", "Win_XP"),
260.1058 +            new Locale("ja", "JP"),
260.1059 +            new Locale("ja", "JP", "JP"),
260.1060 +            new Locale("th", "TH"),
260.1061 +            new Locale("th", "TH", "TH"),
260.1062 +            new Locale("no", "NO"),
260.1063 +            new Locale("nb", "NO"),
260.1064 +            new Locale("nn", "NO"),
260.1065 +            new Locale("no", "NO", "NY"),
260.1066 +            new Locale("nn", "NO", "NY"),
260.1067 +            new Locale("he", "IL"),
260.1068 +            new Locale("he", "IL", "var"),
260.1069 +            new Locale("Language", "Country", "Variant"),
260.1070 +            new Locale("", "US"),
260.1071 +            new Locale("", "", "Java"),
260.1072 +            Locale.forLanguageTag("en-Latn-US"),
260.1073 +            Locale.forLanguageTag("zh-Hans"),
260.1074 +            Locale.forLanguageTag("zh-Hant-TW"),
260.1075 +            Locale.forLanguageTag("ja-JP-u-ca-japanese"),
260.1076 +            Locale.forLanguageTag("und-Hant"),
260.1077 +            Locale.forLanguageTag("und-a-123-456"),
260.1078 +            Locale.forLanguageTag("en-x-java"),
260.1079 +            Locale.forLanguageTag("th-TH-u-ca-buddist-nu-thai-x-lvariant-TH"),
260.1080 +        };
260.1081 +
260.1082 +        for (Locale locale : testLocales) {
260.1083 +            try {
260.1084 +                // write
260.1085 +                ByteArrayOutputStream bos = new ByteArrayOutputStream();
260.1086 +                ObjectOutputStream oos = new ObjectOutputStream(bos);
260.1087 +                oos.writeObject(locale);
260.1088 +
260.1089 +                // read
260.1090 +                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
260.1091 +                ObjectInputStream ois = new ObjectInputStream(bis);
260.1092 +                Object o = ois.readObject();
260.1093 +
260.1094 +                assertEquals("roundtrip " + locale, locale, o);
260.1095 +            } catch (Exception e) {
260.1096 +                errln(locale + " encountered exception:" + e.getLocalizedMessage());
260.1097 +            }
260.1098 +        }
260.1099 +    }
260.1100 +
260.1101 +    public void testDeserialize6() {
260.1102 +        final String TESTFILEPREFIX = "java6locale_";
260.1103 +
260.1104 +        File dataDir = null;
260.1105 +        String dataDirName = System.getProperty("serialized.data.dir");
260.1106 +        if (dataDirName == null) {
260.1107 +            URL resdirUrl = getClass().getClassLoader().getResource("serialized");
260.1108 +            if (resdirUrl != null) {
260.1109 +                try {
260.1110 +                    dataDir = new File(resdirUrl.toURI());
260.1111 +                } catch (URISyntaxException urie) {
260.1112 +                }
260.1113 +            }
260.1114 +        } else {
260.1115 +            dataDir = new File(dataDirName);
260.1116 +        }
260.1117 +
260.1118 +        if (dataDir == null || !dataDir.isDirectory()) {
260.1119 +            errln("Could not locate the serialized test case data location");
260.1120 +            return;
260.1121 +        }
260.1122 +
260.1123 +        File[] files = dataDir.listFiles();
260.1124 +        for (File testfile : files) {
260.1125 +            if (testfile.isDirectory()) {
260.1126 +                continue;
260.1127 +            }
260.1128 +            String name = testfile.getName();
260.1129 +            if (!name.startsWith(TESTFILEPREFIX)) {
260.1130 +                continue;
260.1131 +            }
260.1132 +            Locale locale;
260.1133 +            String locStr = name.substring(TESTFILEPREFIX.length());
260.1134 +            if (locStr.equals("ROOT")) {
260.1135 +                locale = Locale.ROOT;
260.1136 +            } else {
260.1137 +                String[] fields = locStr.split("_", 3);
260.1138 +                String lang = fields[0];
260.1139 +                String country = (fields.length >= 2) ? fields[1] : "";
260.1140 +                String variant = (fields.length == 3) ? fields[2] : "";
260.1141 +                locale = new Locale(lang, country, variant);
260.1142 +            }
260.1143 +
260.1144 +            // desrialize
260.1145 +            try {
260.1146 +                FileInputStream fis = new FileInputStream(testfile);
260.1147 +                ObjectInputStream ois = new ObjectInputStream(fis);
260.1148 +
260.1149 +                Object o = ois.readObject();
260.1150 +                assertEquals("Deserialize Java 6 Locale " + locale, o, locale);
260.1151 +                ois.close();
260.1152 +            } catch (Exception e) {
260.1153 +                errln("Exception while reading " + testfile.getAbsolutePath() + " - " + e.getMessage());
260.1154 +            }
260.1155 +        }
260.1156 +    }
260.1157 +
260.1158 +    ///
260.1159 +    /// utility asserts
260.1160 +    ///
260.1161 +
260.1162 +    private void assertTrue(String msg, boolean v) {
260.1163 +        if (!v) {
260.1164 +            errln(msg + ": expected true");
260.1165 +        }
260.1166 +    }
260.1167 +
260.1168 +    private void assertFalse(String msg, boolean v) {
260.1169 +        if (v) {
260.1170 +            errln(msg + ": expected false");
260.1171 +        }
260.1172 +    }
260.1173 +
260.1174 +    private void assertEquals(String msg, Object e, Object v) {
260.1175 +        if (e == null ? v != null : !e.equals(v)) {
260.1176 +            if (e != null) {
260.1177 +                e = "'" + e + "'";
260.1178 +            }
260.1179 +            if (v != null) {
260.1180 +                v = "'" + v + "'";
260.1181 +            }
260.1182 +            errln(msg + ": expected " + e + " but got " + v);
260.1183 +        }
260.1184 +    }
260.1185 +
260.1186 +    private void assertNotEquals(String msg, Object e, Object v) {
260.1187 +        if (e == null ? v == null : e.equals(v)) {
260.1188 +            if (e != null) {
260.1189 +                e = "'" + e + "'";
260.1190 +            }
260.1191 +            errln(msg + ": expected not equal " + e);
260.1192 +        }
260.1193 +    }
260.1194 +
260.1195 +    private void assertNull(String msg, Object o) {
260.1196 +        if (o != null) {
260.1197 +            errln(msg + ": expected null but got '" + o + "'");
260.1198 +        }
260.1199 +    }
260.1200 +
260.1201 +    private void assertNotNull(String msg, Object o) {
260.1202 +        if (o == null) {
260.1203 +            errln(msg + ": expected non null");
260.1204 +        }
260.1205 +    }
260.1206 +
260.1207 +    // not currently used, might get rid of exceptions from the API
260.1208 +    private abstract class ExceptionTest {
260.1209 +        private final Class<? extends Exception> exceptionClass;
260.1210 +
260.1211 +        ExceptionTest(Class<? extends Exception> exceptionClass) {
260.1212 +            this.exceptionClass = exceptionClass;
260.1213 +        }
260.1214 +
260.1215 +        public void run() {
260.1216 +            String failMsg = null;
260.1217 +            try {
260.1218 +                call();
260.1219 +                failMsg = "expected " + exceptionClass.getName() + "  but no exception thrown.";
260.1220 +            }
260.1221 +            catch (Exception e) {
260.1222 +                if (!exceptionClass.isAssignableFrom(e.getClass())) {
260.1223 +                    failMsg = "expected " + exceptionClass.getName() + " but caught " + e;
260.1224 +                }
260.1225 +            }
260.1226 +            if (failMsg != null) {
260.1227 +                String msg = message();
260.1228 +                msg = msg == null ? "" : msg + " ";
260.1229 +                errln(msg + failMsg);
260.1230 +            }
260.1231 +        }
260.1232 +
260.1233 +        public String message() {
260.1234 +            return null;
260.1235 +        }
260.1236 +
260.1237 +        public abstract void call();
260.1238 +    }
260.1239 +
260.1240 +    private abstract class ExpectNPE extends ExceptionTest {
260.1241 +        ExpectNPE() {
260.1242 +            super(NullPointerException.class);
260.1243 +            run();
260.1244 +        }
260.1245 +    }
260.1246 +
260.1247 +    private abstract class BuilderNPE extends ExceptionTest {
260.1248 +        protected final String msg;
260.1249 +        protected final Builder b = new Builder();
260.1250 +
260.1251 +        BuilderNPE(String msg) {
260.1252 +            super(NullPointerException.class);
260.1253 +
260.1254 +            this.msg = msg;
260.1255 +
260.1256 +            run();
260.1257 +        }
260.1258 +
260.1259 +        public String message() {
260.1260 +            return msg;
260.1261 +        }
260.1262 +    }
260.1263 +
260.1264 +    private abstract class ExpectIAE extends ExceptionTest {
260.1265 +        ExpectIAE() {
260.1266 +            super(IllegalArgumentException.class);
260.1267 +            run();
260.1268 +        }
260.1269 +    }
260.1270 +
260.1271 +    private abstract class BuilderILE extends ExceptionTest {
260.1272 +        protected final String[] args;
260.1273 +        protected final Builder b = new Builder();
260.1274 +
260.1275 +        protected String arg; // mutates during call
260.1276 +
260.1277 +        BuilderILE(String... args) {
260.1278 +            super(IllformedLocaleException.class);
260.1279 +
260.1280 +            this.args = args;
260.1281 +
260.1282 +            run();
260.1283 +        }
260.1284 +
260.1285 +        public void run() {
260.1286 +            for (String arg : args) {
260.1287 +                this.arg = arg;
260.1288 +                super.run();
260.1289 +            }
260.1290 +        }
260.1291 +
260.1292 +        public String message() {
260.1293 +            return "arg: '" + arg + "'";
260.1294 +        }
260.1295 +    }
260.1296 +}
   261.1 --- a/test/java/util/Locale/LocaleTestFmwk.java	Thu Sep 23 17:33:40 2010 -0700
   261.2 +++ b/test/java/util/Locale/LocaleTestFmwk.java	Fri Sep 24 16:41:32 2010 -0700
   261.3 @@ -1,10 +1,12 @@
   261.4  /*
   261.5 - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
   261.6 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   261.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   261.8   *
   261.9   * This code is free software; you can redistribute it and/or modify it
  261.10   * under the terms of the GNU General Public License version 2 only, as
  261.11 - * published by the Free Software Foundation.
  261.12 + * published by the Free Software Foundation.  Oracle designates this
  261.13 + * particular file as subject to the "Classpath" exception as provided
  261.14 + * by Oracle in the LICENSE file that accompanied this code.
  261.15   *
  261.16   * This code is distributed in the hope that it will be useful, but WITHOUT
  261.17   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  261.18 @@ -20,6 +22,7 @@
  261.19   * or visit www.oracle.com if you need additional information or have any
  261.20   * questions.
  261.21   */
  261.22 +
  261.23  /*
  261.24   *
  261.25   *
  261.26 @@ -112,6 +115,8 @@
  261.27                  prompt = true;
  261.28              } else if (args[i].equals("-nothrow")) {
  261.29                  nothrow = true;
  261.30 +            } else if (args[i].equals("-exitcode")) {
  261.31 +                exitcode = true;
  261.32              } else {
  261.33                  Object m = testMethods.get( args[i] );
  261.34                  if( m != null ) {
  261.35 @@ -165,7 +170,12 @@
  261.36              }
  261.37          }
  261.38          if (nothrow) {
  261.39 -            System.exit(errorCount);
  261.40 +            if (exitcode) {
  261.41 +                System.exit(errorCount);
  261.42 +            }
  261.43 +            if (errorCount > 0) {
  261.44 +                throw new IllegalArgumentException("encountered " + errorCount + " errors");
  261.45 +            }
  261.46          }
  261.47      }
  261.48  
  261.49 @@ -235,7 +245,7 @@
  261.50       */
  261.51      void usage() {
  261.52          System.out.println(getClass().getName() +
  261.53 -                            ": [-verbose] [-nothrow] [-prompt] [test names]");
  261.54 +                            ": [-verbose] [-nothrow] [-exitcode] [-prompt] [test names]");
  261.55  
  261.56          System.out.println("test names:");
  261.57          Enumeration methodNames = testMethods.keys();
  261.58 @@ -246,6 +256,7 @@
  261.59  
  261.60      private boolean     prompt = false;
  261.61      private boolean     nothrow = false;
  261.62 +    private boolean     exitcode = false;
  261.63      protected boolean   verbose = false;
  261.64  
  261.65      private PrintWriter log;
   262.1 --- a/test/java/util/Locale/PrintDefaultLocale.java	Thu Sep 23 17:33:40 2010 -0700
   262.2 +++ b/test/java/util/Locale/PrintDefaultLocale.java	Fri Sep 24 16:41:32 2010 -0700
   262.3 @@ -231,8 +231,15 @@
   262.4  
   262.5  public class PrintDefaultLocale {
   262.6      public static void main(String[] args) {
   262.7 -        System.out.println(Locale.getDefault().toString());
   262.8 -        System.out.println(Locale.getDefault().getDisplayName(Locale.US));
   262.9 -        System.out.println(Charset.defaultCharset());
  262.10 +        System.out.printf("default locale: ID: %s, Name: %s\n",
  262.11 +            Locale.getDefault().toString(),
  262.12 +            Locale.getDefault().getDisplayName(Locale.US));
  262.13 +        System.out.printf("display locale: ID: %s, Name: %s\n",
  262.14 +            Locale.getDefault(Locale.Category.DISPLAY).toString(),
  262.15 +            Locale.getDefault(Locale.Category.DISPLAY).getDisplayName(Locale.US));
  262.16 +        System.out.printf("format locale: ID: %s, Name: %s\n",
  262.17 +            Locale.getDefault(Locale.Category.FORMAT).toString(),
  262.18 +            Locale.getDefault(Locale.Category.FORMAT).getDisplayName(Locale.US));
  262.19 +        System.out.printf("default charset: %s\n", Charset.defaultCharset());
  262.20      }
  262.21  }
   263.1 --- a/test/java/util/Locale/data/deflocale.c	Thu Sep 23 17:33:40 2010 -0700
   263.2 +++ b/test/java/util/Locale/data/deflocale.c	Fri Sep 24 16:41:32 2010 -0700
   263.3 @@ -29,100 +29,233 @@
   263.4   * WARNING:  This tool directly modifies the locale info in the Windows registry.
   263.5   * It may not work with the Windows versions after Windows XP SP2.  Also,
   263.6   * if the test did not complete or was manually killed, you will need to reset
   263.7 - * the user default locale in the Control Panel manually.
   263.8 + * the user default locale in the Control Panel manually. This executable has
   263.9 + * to be run with the "Administrator" privilege.
  263.10   *
  263.11   * Usage: "deflocale.exe <java launcher> PrintDefaultLocale
  263.12   *
  263.13 - * How to compile: "cl deflocale.c advapi32.lib"
  263.14 + * How to compile: "cl -DUNICODE -D_UNICODE deflocale.c user32.lib advapi32.lib"
  263.15   */
  263.16  #include <windows.h>
  263.17  #include <stdio.h>
  263.18  #include <memory.h>
  263.19  
  263.20 -char* launcher;
  263.21 -char szBuffer[MAX_PATH];
  263.22 +wchar_t* launcher;
  263.23 +wchar_t szBuffer[MAX_PATH];
  263.24  LCID LCIDArray[1024];
  263.25  int numLCIDs = 0;
  263.26 +BOOL isWin7orUp = FALSE;
  263.27  
  263.28 -void testLCID(int anLCID) {
  263.29 +// for Windows 7
  263.30 +BOOL (WINAPI * pfnEnumSystemLocalesEx)(LPVOID, DWORD, LPARAM, LPVOID);
  263.31 +BOOL (WINAPI * pfnEnumUILanguages)(LPVOID, DWORD, LPARAM);
  263.32 +LCID (WINAPI * pfnLocaleNameToLCID)(LPCWSTR, DWORD);
  263.33 +int (WINAPI * pfnLCIDToLocaleName)(LCID, LPWSTR, int, DWORD);
  263.34 +wchar_t* LocaleNamesArray[1024];
  263.35 +wchar_t* UILangNamesArray[1024];
  263.36 +int numLocaleNames = 0;
  263.37 +int numUILangNames = 0;
  263.38 +
  263.39 +void launchAndWait() {
  263.40 +    STARTUPINFO si;
  263.41 +    PROCESS_INFORMATION pi;
  263.42 +
  263.43 +    ZeroMemory(&si, sizeof(si));
  263.44 +    si.cb = sizeof(si);
  263.45 +    ZeroMemory(&pi, sizeof(pi));
  263.46 +    if (CreateProcess(NULL, launcher, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)==0) {
  263.47 +        wprintf(L"CreateProcess failed with the error code: %x\n", GetLastError());
  263.48 +    }
  263.49 +
  263.50 +    WaitForSingleObject( pi.hProcess, INFINITE );
  263.51 +}
  263.52 +
  263.53 +void testLocale(int anLCID, wchar_t* pName) {
  263.54      HKEY hk;
  263.55  
  263.56 -    printf("\n");
  263.57 -    printf("OS Locale (lcid: %x): ", anLCID);
  263.58 +    if (pName != NULL && wcslen(pName) == 2) {
  263.59 +        // ignore language only locale.
  263.60 +        return;
  263.61 +    }
  263.62 +
  263.63 +    wprintf(L"\n");
  263.64 +    wprintf(L"OS Locale (lcid: %x", anLCID);
  263.65 +    if (pName != NULL) {
  263.66 +        wprintf(L", name: %s", pName);
  263.67 +    }
  263.68      GetLocaleInfo(anLCID, LOCALE_SENGLANGUAGE, szBuffer, MAX_PATH);
  263.69 -    printf("%s (", szBuffer);
  263.70 +    wprintf(L"): %s (", szBuffer);
  263.71      GetLocaleInfo(anLCID, LOCALE_SENGCOUNTRY, szBuffer, MAX_PATH);
  263.72 -    printf("%s) - ", szBuffer);
  263.73 +    wprintf(L"%s) - ", szBuffer);
  263.74      GetLocaleInfo(anLCID, LOCALE_IDEFAULTANSICODEPAGE, szBuffer, MAX_PATH);
  263.75 -    printf("%s\n", szBuffer);
  263.76 +    wprintf(L"%s\n", szBuffer);
  263.77      fflush(0);
  263.78  
  263.79 -    if (RegOpenKeyEx(HKEY_CURRENT_USER, "Control Panel\\International", 0, KEY_READ | KEY_WRITE, &hk) == ERROR_SUCCESS) {
  263.80 -        BYTE original[16];
  263.81 -        BYTE test[16];
  263.82 -        DWORD cb = 16;
  263.83 -        STARTUPINFO si;
  263.84 -        PROCESS_INFORMATION pi;
  263.85 +    if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\International", 0, KEY_READ | KEY_WRITE, &hk) == ERROR_SUCCESS) {
  263.86 +        wchar_t originalLocale[16];
  263.87 +        wchar_t testLocale[16];
  263.88 +        wchar_t* pKeyName;
  263.89 +        DWORD cb = sizeof(originalLocale);
  263.90 +        DWORD cbTest;
  263.91  
  263.92 -        RegQueryValueEx(hk, "Locale", 0, 0, original, &cb);
  263.93 -        sprintf(test, "%08x", anLCID);
  263.94 -        RegSetValueEx(hk, "Locale", 0, REG_SZ, test, cb);
  263.95 -
  263.96 -        ZeroMemory(&si, sizeof(si));
  263.97 -        si.cb = sizeof(si);
  263.98 -        ZeroMemory(&pi, sizeof(pi));
  263.99 -        if (CreateProcess(NULL, launcher, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)==0) {
 263.100 -            printf("CreateProcess failed with the error code: %x\n", GetLastError());
 263.101 +        if (isWin7orUp) {
 263.102 +            pKeyName = L"LocaleName";
 263.103 +            wcscpy(testLocale, pName);
 263.104 +            cbTest = wcslen(pName) * sizeof(wchar_t);
 263.105 +        } else {
 263.106 +            pKeyName = L"Locale";
 263.107 +            swprintf(testLocale, L"%08x", anLCID);
 263.108 +            cbTest = sizeof(wchar_t) * 8;
 263.109          }
 263.110  
 263.111 -        WaitForSingleObject( pi.hProcess, INFINITE );
 263.112 -
 263.113 -        RegSetValueEx(hk, "Locale", 0, REG_SZ, original, cb);
 263.114 +        RegQueryValueEx(hk, pKeyName, 0, 0, (LPBYTE)originalLocale, &cb);
 263.115 +        RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)testLocale, cbTest );
 263.116 +        launchAndWait();
 263.117 +        RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)originalLocale, cb);
 263.118          RegCloseKey(hk);
 263.119      }
 263.120  }
 263.121  
 263.122 -BOOL CALLBACK EnumLocaleProc(LPTSTR lpLocaleStr) {
 263.123 -    sscanf(lpLocaleStr, "%08x", &LCIDArray[numLCIDs]);
 263.124 +void testUILang(wchar_t* pName) {
 263.125 +    HKEY hk;
 263.126 +
 263.127 +    wprintf(L"\n");
 263.128 +    wprintf(L"OS UI Language (name: %s)\n", pName);
 263.129 +    fflush(0);
 263.130 +
 263.131 +    if (RegOpenKeyEx(HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_READ | KEY_WRITE, &hk) == ERROR_SUCCESS) {
 263.132 +        wchar_t originalUILang[16];
 263.133 +        wchar_t testUILang[16];
 263.134 +        wchar_t* pKeyName;
 263.135 +        DWORD cb = sizeof(originalUILang);
 263.136 +        DWORD cbTest = wcslen(pName) * sizeof(wchar_t);
 263.137 +
 263.138 +        pKeyName = L"PreferredUILanguages";
 263.139 +        wcscpy(testUILang, pName);
 263.140 +        cbTest = wcslen(pName) * sizeof(wchar_t);
 263.141 +
 263.142 +        RegQueryValueEx(hk, pKeyName, 0, 0, (LPBYTE)originalUILang, &cb);
 263.143 +        RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)testUILang, cbTest);
 263.144 +        launchAndWait();
 263.145 +        RegSetValueEx(hk, pKeyName, 0, REG_SZ, (LPBYTE)originalUILang, cb);
 263.146 +        RegCloseKey(hk);
 263.147 +    }
 263.148 +}
 263.149 +
 263.150 +BOOL CALLBACK EnumLocalesProc(LPWSTR lpLocaleStr) {
 263.151 +    swscanf(lpLocaleStr, L"%08x", &LCIDArray[numLCIDs]);
 263.152      numLCIDs ++;
 263.153  
 263.154      return TRUE;
 263.155  }
 263.156  
 263.157 +BOOL CALLBACK EnumLocalesProcEx(LPWSTR lpLocaleStr, DWORD flags, LPARAM lp) {
 263.158 +    wchar_t* pName = malloc((wcslen(lpLocaleStr) + 1) * sizeof(wchar_t *));
 263.159 +    wcscpy(pName, lpLocaleStr);
 263.160 +    LocaleNamesArray[numLocaleNames] = pName;
 263.161 +    numLocaleNames ++;
 263.162 +
 263.163 +    return TRUE;
 263.164 +}
 263.165 +
 263.166 +BOOL CALLBACK EnumUILanguagesProc(LPWSTR lpUILangStr, LPARAM lp) {
 263.167 +    wchar_t* pName = malloc((wcslen(lpUILangStr) + 1) * sizeof(wchar_t *));
 263.168 +    wcscpy(pName, lpUILangStr);
 263.169 +    UILangNamesArray[numUILangNames] = pName;
 263.170 +    numUILangNames ++;
 263.171 +
 263.172 +    return TRUE;
 263.173 +}
 263.174 +
 263.175  int sortLCIDs(LCID * pLCID1, LCID * pLCID2) {
 263.176      if (*pLCID1 < *pLCID2) return (-1);
 263.177      if (*pLCID1 == *pLCID2) return 0;
 263.178 -    if (*pLCID1 > *pLCID2) return 1;
 263.179 +    return 1;
 263.180 +}
 263.181 +
 263.182 +int sortLocaleNames(wchar_t** ppName1, wchar_t** ppName2) {
 263.183 +    LCID l1 = pfnLocaleNameToLCID(*ppName1, 0);
 263.184 +    LCID l2 = pfnLocaleNameToLCID(*ppName2, 0);
 263.185 +    return sortLCIDs(&l1, &l2);
 263.186  }
 263.187  
 263.188  int main(int argc, char** argv) {
 263.189      OSVERSIONINFO osvi;
 263.190 -    LPTSTR commandline = GetCommandLine();
 263.191 +    LPWSTR commandline = GetCommandLine();
 263.192      int i;
 263.193  
 263.194      osvi.dwOSVersionInfoSize = sizeof(osvi);
 263.195      GetVersionEx(&osvi);
 263.196 -    printf("# OSVersionInfo\n");
 263.197 -    printf("# MajorVersion: %d\n", osvi.dwMajorVersion);
 263.198 -    printf("# MinorVersion: %d\n", osvi.dwMinorVersion);
 263.199 -    printf("# BuildNumber: %d\n", osvi.dwBuildNumber);
 263.200 -    printf("# CSDVersion: %s\n", osvi.szCSDVersion);
 263.201 -    printf("\n");
 263.202 +    wprintf(L"# OSVersionInfo\n");
 263.203 +    wprintf(L"# MajorVersion: %d\n", osvi.dwMajorVersion);
 263.204 +    wprintf(L"# MinorVersion: %d\n", osvi.dwMinorVersion);
 263.205 +    wprintf(L"# BuildNumber: %d\n", osvi.dwBuildNumber);
 263.206 +    wprintf(L"# CSDVersion: %s\n", osvi.szCSDVersion);
 263.207 +    wprintf(L"\n");
 263.208      fflush(0);
 263.209  
 263.210 -    launcher = strchr(commandline, ' ')+1;
 263.211 -    while (*launcher == ' ') {
 263.212 +    launcher = wcschr(commandline, L' ')+1;
 263.213 +    while (*launcher == L' ') {
 263.214          launcher++;
 263.215      }
 263.216  
 263.217 -    // Enumerate locales
 263.218 -    EnumSystemLocales(EnumLocaleProc, LCID_INSTALLED);
 263.219 +    isWin7orUp = (osvi.dwMajorVersion > 6) ||
 263.220 +                 (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 1);
 263.221  
 263.222 -    // Sort LCIDs
 263.223 -    qsort(LCIDArray, numLCIDs, sizeof(LCID), (void *)sortLCIDs);
 263.224 +    if (!isWin7orUp) {
 263.225 +        // Enumerate locales
 263.226 +        EnumSystemLocales(EnumLocalesProc, LCID_INSTALLED);
 263.227 +
 263.228 +        // Sort LCIDs
 263.229 +        qsort(LCIDArray, numLCIDs, sizeof(LCID), (void *)sortLCIDs);
 263.230 +    } else {
 263.231 +        // For Windows 7, use "LocaleName" registry key for the user locale
 263.232 +        // as they seem to switch from "Locale".
 263.233 +        HMODULE hmod = GetModuleHandle(L"kernel32");
 263.234 +        *(FARPROC*)&pfnEnumSystemLocalesEx =
 263.235 +            GetProcAddress(hmod, "EnumSystemLocalesEx");
 263.236 +        *(FARPROC*)&pfnEnumUILanguages =
 263.237 +            GetProcAddress(hmod, "EnumUILanguagesW");
 263.238 +        *(FARPROC*)&pfnLocaleNameToLCID =
 263.239 +            GetProcAddress(hmod, "LocaleNameToLCID");
 263.240 +        *(FARPROC*)&pfnLCIDToLocaleName =
 263.241 +            GetProcAddress(hmod, "LCIDToLocaleName");
 263.242 +        if (pfnEnumSystemLocalesEx != NULL &&
 263.243 +            pfnEnumUILanguages != NULL &&
 263.244 +            pfnLocaleNameToLCID != NULL &&
 263.245 +            pfnLCIDToLocaleName != NULL) {
 263.246 +            // Enumerate locales
 263.247 +            pfnEnumSystemLocalesEx(EnumLocalesProcEx,
 263.248 +                    1, // LOCALE_WINDOWS
 263.249 +                    (LPARAM)NULL, NULL);
 263.250 +            // Enumerate UI Languages.
 263.251 +            pfnEnumUILanguages(EnumUILanguagesProc,
 263.252 +                    0x8, // MUI_LANGUAGE_NAME
 263.253 +                    (LPARAM)NULL);
 263.254 +        } else {
 263.255 +            wprintf(L"Could not get needed entry points. quitting.\n");
 263.256 +            exit(-1);
 263.257 +        }
 263.258 +
 263.259 +        // Sort LocaleNames
 263.260 +        qsort(LocaleNamesArray, numLocaleNames,
 263.261 +              sizeof(wchar_t*), (void *)sortLocaleNames);
 263.262 +        qsort(UILangNamesArray, numUILangNames,
 263.263 +              sizeof(wchar_t*), (void *)sortLocaleNames);
 263.264 +    }
 263.265  
 263.266      // Execute enumeration of Java default locales
 263.267 -    for (i = 0; i < numLCIDs; i ++) {
 263.268 -        testLCID(LCIDArray[i]);
 263.269 +    if (isWin7orUp) {
 263.270 +        for (i = 0; i < numLocaleNames; i ++) {
 263.271 +            testLocale(pfnLocaleNameToLCID(LocaleNamesArray[i], 0),
 263.272 +                                     LocaleNamesArray[i]);
 263.273 +        }
 263.274 +        for (i = 0; i < numUILangNames; i ++) {
 263.275 +            testUILang(UILangNamesArray[i]);
 263.276 +        }
 263.277 +    } else {
 263.278 +        for (i = 0; i < numLCIDs; i ++) {
 263.279 +            testLocale(LCIDArray[i], NULL);
 263.280 +        }
 263.281      }
 263.282  }
   264.1 Binary file test/java/util/Locale/data/deflocale.exe has changed
   265.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   265.2 +++ b/test/java/util/Locale/data/deflocale.input	Fri Sep 24 16:41:32 2010 -0700
   265.3 @@ -0,0 +1,7 @@
   265.4 +# data file for deflocale.sh. Each line must have two locales in the following order.
   265.5 +#
   265.6 +#       LC_CTYPE        LC_MESSAGES
   265.7 + 
   265.8 +        ja_JP.UTF-8     zh_CN.UTF-8
   265.9 +        zh_CN.UTF-8     en_US.UTF-8
  265.10 +        C               zh_CN.UTF-8
   266.1 --- a/test/java/util/Locale/data/deflocale.jds3	Thu Sep 23 17:33:40 2010 -0700
   266.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   266.3 @@ -1,1793 +0,0 @@
   266.4 -Sun Java Desktop System, Release 3 - build 36
   266.5 -Assembled 23 May 2005
   266.6 -Linux dnm-dtf-012 2.6.5-7.139-default #1 Fri Jan 14 15:41:33 UTC 2005 i686 i686 i386 GNU/Linux
   266.7 -
   266.8 -OS Locale:  aa_DJ
   266.9 -aa_DJ
  266.10 -Afar (Djibouti)
  266.11 -ISO-8859-1
  266.12 -
  266.13 -OS Locale:  aa_ER
  266.14 -aa_ER
  266.15 -Afar (Eritrea)
  266.16 -UTF-8
  266.17 -
  266.18 -OS Locale:  aa_ER.utf8
  266.19 -aa_ER
  266.20 -Afar (Eritrea)
  266.21 -UTF-8
  266.22 -
  266.23 -OS Locale:  aa_ER@saaho
  266.24 -aa_ER
  266.25 -Afar (Eritrea)
  266.26 -UTF-8
  266.27 -
  266.28 -OS Locale:  aa_ET
  266.29 -aa_ET
  266.30 -Afar (Ethiopia)
  266.31 -UTF-8
  266.32 -
  266.33 -OS Locale:  aa_ET.utf8
  266.34 -aa_ET
  266.35 -Afar (Ethiopia)
  266.36 -UTF-8
  266.37 -
  266.38 -OS Locale:  af_ZA
  266.39 -af_ZA
  266.40 -Afrikaans (South Africa)
  266.41 -ISO-8859-1
  266.42 -
  266.43 -OS Locale:  am_ET
  266.44 -am_ET
  266.45 -Amharic (Ethiopia)
  266.46 -UTF-8
  266.47 -
  266.48 -OS Locale:  am_ET.utf8
  266.49 -am_ET
  266.50 -Amharic (Ethiopia)
  266.51 -UTF-8
  266.52 -
  266.53 -OS Locale:  an_ES
  266.54 -an_ES
  266.55 -Aragonese (Spain)
  266.56 -ISO-8859-15
  266.57 -
  266.58 -OS Locale:  ar_AE
  266.59 -ar_AE
  266.60 -Arabic (United Arab Emirates)
  266.61 -ISO-8859-6
  266.62 -
  266.63 -OS Locale:  ar_AE.utf8
  266.64 -ar_AE
  266.65 -Arabic (United Arab Emirates)
  266.66 -UTF-8
  266.67 -
  266.68 -OS Locale:  ar_BH
  266.69 -ar_BH
  266.70 -Arabic (Bahrain)
  266.71 -ISO-8859-6
  266.72 -
  266.73 -OS Locale:  ar_BH.utf8
  266.74 -ar_BH
  266.75 -Arabic (Bahrain)
  266.76 -UTF-8
  266.77 -
  266.78 -OS Locale:  ar_DZ
  266.79 -ar_DZ
  266.80 -Arabic (Algeria)
  266.81 -ISO-8859-6
  266.82 -
  266.83 -OS Locale:  ar_DZ.utf8
  266.84 -ar_DZ
  266.85 -Arabic (Algeria)
  266.86 -UTF-8
  266.87 -
  266.88 -OS Locale:  ar_EG
  266.89 -ar_EG
  266.90 -Arabic (Egypt)
  266.91 -ISO-8859-6
  266.92 -
  266.93 -OS Locale:  ar_EG.utf8
  266.94 -ar_EG
  266.95 -Arabic (Egypt)
  266.96 -UTF-8
  266.97 -
  266.98 -OS Locale:  ar_IN
  266.99 -ar_IN
 266.100 -Arabic (India)
 266.101 -UTF-8
 266.102 -
 266.103 -OS Locale:  ar_IN.utf8
 266.104 -ar_IN
 266.105 -Arabic (India)
 266.106 -UTF-8
 266.107 -
 266.108 -OS Locale:  ar_IQ
 266.109 -ar_IQ
 266.110 -Arabic (Iraq)
 266.111 -ISO-8859-6
 266.112 -
 266.113 -OS Locale:  ar_IQ.utf8
 266.114 -ar_IQ
 266.115 -Arabic (Iraq)
 266.116 -UTF-8
 266.117 -
 266.118 -OS Locale:  ar_JO
 266.119 -ar_JO
 266.120 -Arabic (Jordan)
 266.121 -ISO-8859-6
 266.122 -
 266.123 -OS Locale:  ar_JO.utf8
 266.124 -ar_JO
 266.125 -Arabic (Jordan)
 266.126 -UTF-8
 266.127 -
 266.128 -OS Locale:  ar_KW
 266.129 -ar_KW
 266.130 -Arabic (Kuwait)
 266.131 -ISO-8859-6
 266.132 -
 266.133 -OS Locale:  ar_KW.utf8
 266.134 -ar_KW
 266.135 -Arabic (Kuwait)
 266.136 -UTF-8
 266.137 -
 266.138 -OS Locale:  ar_LB
 266.139 -ar_LB
 266.140 -Arabic (Lebanon)
 266.141 -ISO-8859-6
 266.142 -
 266.143 -OS Locale:  ar_LB.utf8
 266.144 -ar_LB
 266.145 -Arabic (Lebanon)
 266.146 -UTF-8
 266.147 -
 266.148 -OS Locale:  ar_LY
 266.149 -ar_LY
 266.150 -Arabic (Libya)
 266.151 -ISO-8859-6
 266.152 -
 266.153 -OS Locale:  ar_LY.utf8
 266.154 -ar_LY
 266.155 -Arabic (Libya)
 266.156 -UTF-8
 266.157 -
 266.158 -OS Locale:  ar_MA
 266.159 -ar_MA
 266.160 -Arabic (Morocco)
 266.161 -ISO-8859-6
 266.162 -
 266.163 -OS Locale:  ar_MA.utf8
 266.164 -ar_MA
 266.165 -Arabic (Morocco)
 266.166 -UTF-8
 266.167 -
 266.168 -OS Locale:  ar_OM
 266.169 -ar_OM
 266.170 -Arabic (Oman)
 266.171 -ISO-8859-6
 266.172 -
 266.173 -OS Locale:  ar_OM.utf8
 266.174 -ar_OM
 266.175 -Arabic (Oman)
 266.176 -UTF-8
 266.177 -
 266.178 -OS Locale:  ar_QA
 266.179 -ar_QA
 266.180 -Arabic (Qatar)
 266.181 -ISO-8859-6
 266.182 -
 266.183 -OS Locale:  ar_QA.utf8
 266.184 -ar_QA
 266.185 -Arabic (Qatar)
 266.186 -UTF-8
 266.187 -
 266.188 -OS Locale:  ar_SA
 266.189 -ar_SA
 266.190 -Arabic (Saudi Arabia)
 266.191 -ISO-8859-6
 266.192 -
 266.193 -OS Locale:  ar_SA.utf8
 266.194 -ar_SA
 266.195 -Arabic (Saudi Arabia)
 266.196 -UTF-8
 266.197 -
 266.198 -OS Locale:  ar_SD
 266.199 -ar_SD
 266.200 -Arabic (Sudan)
 266.201 -ISO-8859-6
 266.202 -
 266.203 -OS Locale:  ar_SD.utf8
 266.204 -ar_SD
 266.205 -Arabic (Sudan)
 266.206 -UTF-8
 266.207 -
 266.208 -OS Locale:  ar_SY
 266.209 -ar_SY
 266.210 -Arabic (Syria)
 266.211 -ISO-8859-6
 266.212 -
 266.213 -OS Locale:  ar_SY.utf8
 266.214 -ar_SY
 266.215 -Arabic (Syria)
 266.216 -UTF-8
 266.217 -
 266.218 -OS Locale:  ar_TN
 266.219 -ar_TN
 266.220 -Arabic (Tunisia)
 266.221 -ISO-8859-6
 266.222 -
 266.223 -OS Locale:  ar_TN.utf8
 266.224 -ar_TN
 266.225 -Arabic (Tunisia)
 266.226 -UTF-8
 266.227 -
 266.228 -OS Locale:  ar_YE
 266.229 -ar_YE
 266.230 -Arabic (Yemen)
 266.231 -ISO-8859-6
 266.232 -
 266.233 -OS Locale:  ar_YE.utf8
 266.234 -ar_YE
 266.235 -Arabic (Yemen)
 266.236 -UTF-8
 266.237 -
 266.238 -OS Locale:  az_AZ.utf8
 266.239 -az_AZ
 266.240 -Azerbaijani (Azerbaijan)
 266.241 -UTF-8
 266.242 -
 266.243 -OS Locale:  be_BY
 266.244 -be_BY
 266.245 -Belarusian (Belarus)
 266.246 -windows-1251
 266.247 -
 266.248 -OS Locale:  be_BY.utf8
 266.249 -be_BY
 266.250 -Belarusian (Belarus)
 266.251 -UTF-8
 266.252 -
 266.253 -OS Locale:  bg_BG
 266.254 -bg_BG
 266.255 -Bulgarian (Bulgaria)
 266.256 -windows-1251
 266.257 -
 266.258 -OS Locale:  bg_BG.utf8
 266.259 -bg_BG
 266.260 -Bulgarian (Bulgaria)
 266.261 -UTF-8
 266.262 -
 266.263 -OS Locale:  bn_BD
 266.264 -bn_BD
 266.265 -Bengali (Bangladesh)
 266.266 -UTF-8
 266.267 -
 266.268 -OS Locale:  bn_BD.utf8
 266.269 -bn_BD
 266.270 -Bengali (Bangladesh)
 266.271 -UTF-8
 266.272 -
 266.273 -OS Locale:  bn_IN
 266.274 -bn_IN
 266.275 -Bengali (India)
 266.276 -UTF-8
 266.277 -
 266.278 -OS Locale:  bn_IN.utf8
 266.279 -bn_IN
 266.280 -Bengali (India)
 266.281 -UTF-8
 266.282 -
 266.283 -OS Locale:  br_FR
 266.284 -br_FR
 266.285 -Breton (France)
 266.286 -ISO-8859-1
 266.287 -
 266.288 -OS Locale:  br_FR@euro
 266.289 -br_FR
 266.290 -Breton (France)
 266.291 -ISO-8859-15
 266.292 -
 266.293 -OS Locale:  bs_BA
 266.294 -bs_BA
 266.295 -Bosnian (Bosnia and Herzegovina)
 266.296 -ISO-8859-2
 266.297 -
 266.298 -OS Locale:  byn_ER
 266.299 -en_ER
 266.300 -English (Eritrea)
 266.301 -UTF-8
 266.302 -
 266.303 -OS Locale:  byn_ER.utf8
 266.304 -en_ER
 266.305 -English (Eritrea)
 266.306 -UTF-8
 266.307 -
 266.308 -OS Locale:  ca_ES
 266.309 -ca_ES
 266.310 -Catalan (Spain)
 266.311 -ISO-8859-1
 266.312 -
 266.313 -OS Locale:  ca_ES.utf8
 266.314 -ca_ES
 266.315 -Catalan (Spain)
 266.316 -UTF-8
 266.317 -
 266.318 -OS Locale:  ca_ES@euro
 266.319 -ca_ES
 266.320 -Catalan (Spain)
 266.321 -ISO-8859-15
 266.322 -
 266.323 -OS Locale:  cs_CZ
 266.324 -cs_CZ
 266.325 -Czech (Czech Republic)
 266.326 -ISO-8859-2
 266.327 -
 266.328 -OS Locale:  cs_CZ.utf8
 266.329 -cs_CZ
 266.330 -Czech (Czech Republic)
 266.331 -UTF-8
 266.332 -
 266.333 -OS Locale:  cy_GB
 266.334 -cy_GB
 266.335 -Welsh (United Kingdom)
 266.336 -UTF-8
 266.337 -
 266.338 -OS Locale:  cy_GB.utf8
 266.339 -cy_GB
 266.340 -Welsh (United Kingdom)
 266.341 -UTF-8
 266.342 -
 266.343 -OS Locale:  da_DK
 266.344 -da_DK
 266.345 -Danish (Denmark)
 266.346 -ISO-8859-1
 266.347 -
 266.348 -OS Locale:  da_DK.utf8
 266.349 -da_DK
 266.350 -Danish (Denmark)
 266.351 -UTF-8
 266.352 -
 266.353 -OS Locale:  da_DK@euro
 266.354 -da_DK
 266.355 -Danish (Denmark)
 266.356 -ISO-8859-1
 266.357 -
 266.358 -OS Locale:  de_AT
 266.359 -de_AT
 266.360 -German (Austria)
 266.361 -ISO-8859-1
 266.362 -
 266.363 -OS Locale:  de_AT.utf8
 266.364 -de_AT
 266.365 -German (Austria)
 266.366 -UTF-8
 266.367 -
 266.368 -OS Locale:  de_AT@euro
 266.369 -de_AT
 266.370 -German (Austria)
 266.371 -ISO-8859-15
 266.372 -
 266.373 -OS Locale:  de_BE
 266.374 -de_BE
 266.375 -German (Belgium)
 266.376 -ISO-8859-1
 266.377 -
 266.378 -OS Locale:  de_BE.utf8
 266.379 -de_BE
 266.380 -German (Belgium)
 266.381 -UTF-8
 266.382 -
 266.383 -OS Locale:  de_BE@euro
 266.384 -de_BE
 266.385 -German (Belgium)
 266.386 -ISO-8859-15
 266.387 -
 266.388 -OS Locale:  de_CH
 266.389 -de_CH
 266.390 -German (Switzerland)
 266.391 -ISO-8859-1
 266.392 -
 266.393 -OS Locale:  de_CH.utf8
 266.394 -de_CH
 266.395 -German (Switzerland)
 266.396 -UTF-8
 266.397 -
 266.398 -OS Locale:  de_DE
 266.399 -de_DE
 266.400 -German (Germany)
 266.401 -ISO-8859-1
 266.402 -
 266.403 -OS Locale:  de_DE.utf8
 266.404 -de_DE
 266.405 -German (Germany)
 266.406 -UTF-8
 266.407 -
 266.408 -OS Locale:  de_DE@euro
 266.409 -de_DE
 266.410 -German (Germany)
 266.411 -ISO-8859-15
 266.412 -
 266.413 -OS Locale:  de_LU
 266.414 -de_LU
 266.415 -German (Luxembourg)
 266.416 -ISO-8859-1
 266.417 -
 266.418 -OS Locale:  de_LU.utf8
 266.419 -de_LU
 266.420 -German (Luxembourg)
 266.421 -UTF-8
 266.422 -
 266.423 -OS Locale:  de_LU@euro
 266.424 -de_LU
 266.425 -German (Luxembourg)
 266.426 -ISO-8859-15
 266.427 -
 266.428 -OS Locale:  el_GR
 266.429 -el_GR
 266.430 -Greek (Greece)
 266.431 -ISO-8859-7
 266.432 -
 266.433 -OS Locale:  el_GR.utf8
 266.434 -el_GR
 266.435 -Greek (Greece)
 266.436 -UTF-8
 266.437 -
 266.438 -OS Locale:  en_AU
 266.439 -en_AU
 266.440 -English (Australia)
 266.441 -ISO-8859-1
 266.442 -
 266.443 -OS Locale:  en_AU.utf8
 266.444 -en_AU
 266.445 -English (Australia)
 266.446 -UTF-8
 266.447 -
 266.448 -OS Locale:  en_BE
 266.449 -en_BE
 266.450 -English (Belgium)
 266.451 -ISO-8859-1
 266.452 -
 266.453 -OS Locale:  en_BE.utf8
 266.454 -en_BE
 266.455 -English (Belgium)
 266.456 -UTF-8
 266.457 -
 266.458 -OS Locale:  en_BE@euro
 266.459 -en_BE
 266.460 -English (Belgium)
 266.461 -ISO-8859-15
 266.462 -
 266.463 -OS Locale:  en_BW
 266.464 -en_BW
 266.465 -English (Botswana)
 266.466 -ISO-8859-1
 266.467 -
 266.468 -OS Locale:  en_BW.utf8
 266.469 -en_BW
 266.470 -English (Botswana)
 266.471 -UTF-8
 266.472 -
 266.473 -OS Locale:  en_CA
 266.474 -en_CA
 266.475 -English (Canada)
 266.476 -ISO-8859-1
 266.477 -
 266.478 -OS Locale:  en_CA.utf8
 266.479 -en_CA
 266.480 -English (Canada)
 266.481 -UTF-8
 266.482 -
 266.483 -OS Locale:  en_DK
 266.484 -en_DK
 266.485 -English (Denmark)
 266.486 -ISO-8859-1
 266.487 -
 266.488 -OS Locale:  en_DK.utf8
 266.489 -en_DK
 266.490 -English (Denmark)
 266.491 -UTF-8
 266.492 -
 266.493 -OS Locale:  en_GB
 266.494 -en_GB
 266.495 -English (United Kingdom)
 266.496 -ISO-8859-1
 266.497 -
 266.498 -OS Locale:  en_GB.iso885915
 266.499 -en_GB
 266.500 -English (United Kingdom)
 266.501 -ISO-8859-15
 266.502 -
 266.503 -OS Locale:  en_GB.utf8
 266.504 -en_GB
 266.505 -English (United Kingdom)
 266.506 -UTF-8
 266.507 -
 266.508 -OS Locale:  en_HK
 266.509 -en_HK
 266.510 -English (Hong Kong)
 266.511 -ISO-8859-1
 266.512 -
 266.513 -OS Locale:  en_HK.utf8
 266.514 -en_HK
 266.515 -English (Hong Kong)
 266.516 -UTF-8
 266.517 -
 266.518 -OS Locale:  en_IE
 266.519 -en_IE
 266.520 -English (Ireland)
 266.521 -ISO-8859-1
 266.522 -
 266.523 -OS Locale:  en_IE.utf8
 266.524 -en_IE
 266.525 -English (Ireland)
 266.526 -UTF-8
 266.527 -
 266.528 -OS Locale:  en_IE@euro
 266.529 -en_IE
 266.530 -English (Ireland)
 266.531 -ISO-8859-15
 266.532 -
 266.533 -OS Locale:  en_IN
 266.534 -en_IN
 266.535 -English (India)
 266.536 -UTF-8
 266.537 -
 266.538 -OS Locale:  en_NZ
 266.539 -en_NZ
 266.540 -English (New Zealand)
 266.541 -ISO-8859-1
 266.542 -
 266.543 -OS Locale:  en_NZ.utf8
 266.544 -en_NZ
 266.545 -English (New Zealand)
 266.546 -UTF-8
 266.547 -
 266.548 -OS Locale:  en_PH
 266.549 -en_PH
 266.550 -English (Philippines)
 266.551 -ISO-8859-1
 266.552 -
 266.553 -OS Locale:  en_PH.utf8
 266.554 -en_PH
 266.555 -English (Philippines)
 266.556 -UTF-8
 266.557 -
 266.558 -OS Locale:  en_SG
 266.559 -en_SG
 266.560 -English (Singapore)
 266.561 -ISO-8859-1
 266.562 -
 266.563 -OS Locale:  en_SG.utf8
 266.564 -en_SG
 266.565 -English (Singapore)
 266.566 -UTF-8
 266.567 -
 266.568 -OS Locale:  en_US
 266.569 -en_US
 266.570 -English (United States)
 266.571 -ISO-8859-1
 266.572 -
 266.573 -OS Locale:  en_US.iso885915
 266.574 -en_US
 266.575 -English (United States)
 266.576 -ISO-8859-15
 266.577 -
 266.578 -OS Locale:  en_US.utf8
 266.579 -en_US
 266.580 -English (United States)
 266.581 -UTF-8
 266.582 -
 266.583 -OS Locale:  en_ZA
 266.584 -en_ZA
 266.585 -English (South Africa)
 266.586 -ISO-8859-1
 266.587 -
 266.588 -OS Locale:  en_ZA.utf8
 266.589 -en_ZA
 266.590 -English (South Africa)
 266.591 -UTF-8
 266.592 -
 266.593 -OS Locale:  en_ZW
 266.594 -en_ZW
 266.595 -English (Zimbabwe)
 266.596 -ISO-8859-1
 266.597 -
 266.598 -OS Locale:  en_ZW.utf8
 266.599 -en_ZW
 266.600 -English (Zimbabwe)
 266.601 -UTF-8
 266.602 -
 266.603 -OS Locale:  es_AR
 266.604 -es_AR
 266.605 -Spanish (Argentina)
 266.606 -ISO-8859-1
 266.607 -
 266.608 -OS Locale:  es_AR.utf8
 266.609 -es_AR
 266.610 -Spanish (Argentina)
 266.611 -UTF-8
 266.612 -
 266.613 -OS Locale:  es_BO
 266.614 -es_BO
 266.615 -Spanish (Bolivia)
 266.616 -ISO-8859-1
 266.617 -
 266.618 -OS Locale:  es_BO.utf8
 266.619 -es_BO
 266.620 -Spanish (Bolivia)
 266.621 -UTF-8
 266.622 -
 266.623 -OS Locale:  es_CL
 266.624 -es_CL
 266.625 -Spanish (Chile)
 266.626 -ISO-8859-1
 266.627 -
 266.628 -OS Locale:  es_CL.utf8
 266.629 -es_CL
 266.630 -Spanish (Chile)
 266.631 -UTF-8
 266.632 -
 266.633 -OS Locale:  es_CO
 266.634 -es_CO
 266.635 -Spanish (Colombia)
 266.636 -ISO-8859-1
 266.637 -
 266.638 -OS Locale:  es_CO.utf8
 266.639 -es_CO
 266.640 -Spanish (Colombia)
 266.641 -UTF-8
 266.642 -
 266.643 -OS Locale:  es_CR
 266.644 -es_CR
 266.645 -Spanish (Costa Rica)
 266.646 -ISO-8859-1
 266.647 -
 266.648 -OS Locale:  es_CR.utf8
 266.649 -es_CR
 266.650 -Spanish (Costa Rica)
 266.651 -UTF-8
 266.652 -
 266.653 -OS Locale:  es_DO
 266.654 -es_DO
 266.655 -Spanish (Dominican Republic)
 266.656 -ISO-8859-1
 266.657 -
 266.658 -OS Locale:  es_DO.utf8
 266.659 -es_DO
 266.660 -Spanish (Dominican Republic)
 266.661 -UTF-8
 266.662 -
 266.663 -OS Locale:  es_EC
 266.664 -es_EC
 266.665 -Spanish (Ecuador)
 266.666 -ISO-8859-1
 266.667 -
 266.668 -OS Locale:  es_EC.utf8
 266.669 -es_EC
 266.670 -Spanish (Ecuador)
 266.671 -UTF-8
 266.672 -
 266.673 -OS Locale:  es_ES
 266.674 -es_ES
 266.675 -Spanish (Spain)
 266.676 -ISO-8859-1
 266.677 -
 266.678 -OS Locale:  es_ES.utf8
 266.679 -es_ES
 266.680 -Spanish (Spain)
 266.681 -UTF-8
 266.682 -
 266.683 -OS Locale:  es_ES@euro
 266.684 -es_ES
 266.685 -Spanish (Spain)
 266.686 -ISO-8859-15
 266.687 -
 266.688 -OS Locale:  es_GT
 266.689 -es_GT
 266.690 -Spanish (Guatemala)
 266.691 -ISO-8859-1
 266.692 -
 266.693 -OS Locale:  es_GT.utf8
 266.694 -es_GT
 266.695 -Spanish (Guatemala)
 266.696 -UTF-8
 266.697 -
 266.698 -OS Locale:  es_HN
 266.699 -es_HN
 266.700 -Spanish (Honduras)
 266.701 -ISO-8859-1
 266.702 -
 266.703 -OS Locale:  es_HN.utf8
 266.704 -es_HN
 266.705 -Spanish (Honduras)
 266.706 -UTF-8
 266.707 -
 266.708 -OS Locale:  es_MX
 266.709 -es_MX
 266.710 -Spanish (Mexico)
 266.711 -ISO-8859-1
 266.712 -
 266.713 -OS Locale:  es_MX.utf8
 266.714 -es_MX
 266.715 -Spanish (Mexico)
 266.716 -UTF-8
 266.717 -
 266.718 -OS Locale:  es_NI
 266.719 -es_NI
 266.720 -Spanish (Nicaragua)
 266.721 -ISO-8859-1
 266.722 -
 266.723 -OS Locale:  es_NI.utf8
 266.724 -es_NI
 266.725 -Spanish (Nicaragua)
 266.726 -UTF-8
 266.727 -
 266.728 -OS Locale:  es_PA
 266.729 -es_PA
 266.730 -Spanish (Panama)
 266.731 -ISO-8859-1
 266.732 -
 266.733 -OS Locale:  es_PA.utf8
 266.734 -es_PA
 266.735 -Spanish (Panama)
 266.736 -UTF-8
 266.737 -
 266.738 -OS Locale:  es_PE
 266.739 -es_PE
 266.740 -Spanish (Peru)
 266.741 -ISO-8859-1
 266.742 -
 266.743 -OS Locale:  es_PE.utf8
 266.744 -es_PE
 266.745 -Spanish (Peru)
 266.746 -UTF-8
 266.747 -
 266.748 -OS Locale:  es_PR
 266.749 -es_PR
 266.750 -Spanish (Puerto Rico)
 266.751 -ISO-8859-1
 266.752 -
 266.753 -OS Locale:  es_PR.utf8
 266.754 -es_PR
 266.755 -Spanish (Puerto Rico)
 266.756 -UTF-8
 266.757 -
 266.758 -OS Locale:  es_PY
 266.759 -es_PY
 266.760 -Spanish (Paraguay)
 266.761 -ISO-8859-1
 266.762 -
 266.763 -OS Locale:  es_PY.utf8
 266.764 -es_PY
 266.765 -Spanish (Paraguay)
 266.766 -UTF-8
 266.767 -
 266.768 -OS Locale:  es_SV
 266.769 -es_SV
 266.770 -Spanish (El Salvador)
 266.771 -ISO-8859-1
 266.772 -
 266.773 -OS Locale:  es_SV.utf8
 266.774 -es_SV
 266.775 -Spanish (El Salvador)
 266.776 -UTF-8
 266.777 -
 266.778 -OS Locale:  es_US
 266.779 -es_US
 266.780 -Spanish (United States)
 266.781 -ISO-8859-1
 266.782 -
 266.783 -OS Locale:  es_US.utf8
 266.784 -es_US
 266.785 -Spanish (United States)
 266.786 -UTF-8
 266.787 -
 266.788 -OS Locale:  es_UY
 266.789 -es_UY
 266.790 -Spanish (Uruguay)
 266.791 -ISO-8859-1
 266.792 -
 266.793 -OS Locale:  es_UY.utf8
 266.794 -es_UY
 266.795 -Spanish (Uruguay)
 266.796 -UTF-8
 266.797 -
 266.798 -OS Locale:  es_VE
 266.799 -es_VE
 266.800 -Spanish (Venezuela)
 266.801 -ISO-8859-1
 266.802 -
 266.803 -OS Locale:  es_VE.utf8
 266.804 -es_VE
 266.805 -Spanish (Venezuela)
 266.806 -UTF-8
 266.807 -
 266.808 -OS Locale:  et_EE
 266.809 -et_EE
 266.810 -Estonian (Estonia)
 266.811 -ISO-8859-1
 266.812 -
 266.813 -OS Locale:  et_EE.iso885915
 266.814 -et_EE
 266.815 -Estonian (Estonia)
 266.816 -ISO-8859-15
 266.817 -
 266.818 -OS Locale:  et_EE.utf8
 266.819 -et_EE
 266.820 -Estonian (Estonia)
 266.821 -UTF-8
 266.822 -
 266.823 -OS Locale:  eu_ES
 266.824 -eu_ES
 266.825 -Basque (Spain)
 266.826 -ISO-8859-1
 266.827 -
 266.828 -OS Locale:  eu_ES.utf8
 266.829 -eu_ES
 266.830 -Basque (Spain)
 266.831 -UTF-8
 266.832 -
 266.833 -OS Locale:  eu_ES@euro
 266.834 -eu_ES
 266.835 -Basque (Spain)
 266.836 -ISO-8859-15
 266.837 -
 266.838 -OS Locale:  fa_IR
 266.839 -fa_IR
 266.840 -Persian (Iran)
 266.841 -UTF-8
 266.842 -
 266.843 -OS Locale:  fa_IR.utf8
 266.844 -fa_IR
 266.845 -Persian (Iran)
 266.846 -UTF-8
 266.847 -
 266.848 -OS Locale:  fi_FI
 266.849 -fi_FI
 266.850 -Finnish (Finland)
 266.851 -ISO-8859-1
 266.852 -
 266.853 -OS Locale:  fi_FI.utf8
 266.854 -fi_FI
 266.855 -Finnish (Finland)
 266.856 -UTF-8
 266.857 -
 266.858 -OS Locale:  fi_FI@euro
 266.859 -fi_FI
 266.860 -Finnish (Finland)
 266.861 -ISO-8859-15
 266.862 -
 266.863 -OS Locale:  fo_FO
 266.864 -fo_FO
 266.865 -Faroese (Faroe Islands)
 266.866 -ISO-8859-1
 266.867 -
 266.868 -OS Locale:  fo_FO.utf8
 266.869 -fo_FO
 266.870 -Faroese (Faroe Islands)
 266.871 -UTF-8
 266.872 -
 266.873 -OS Locale:  fr_BE
 266.874 -fr_BE
 266.875 -French (Belgium)
 266.876 -ISO-8859-1
 266.877 -
 266.878 -OS Locale:  fr_BE.utf8
 266.879 -fr_BE
 266.880 -French (Belgium)
 266.881 -UTF-8
 266.882 -
 266.883 -OS Locale:  fr_BE@euro
 266.884 -fr_BE
 266.885 -French (Belgium)
 266.886 -ISO-8859-15
 266.887 -
 266.888 -OS Locale:  fr_CA
 266.889 -fr_CA
 266.890 -French (Canada)
 266.891 -ISO-8859-1
 266.892 -
 266.893 -OS Locale:  fr_CA.utf8
 266.894 -fr_CA
 266.895 -French (Canada)
 266.896 -UTF-8
 266.897 -
 266.898 -OS Locale:  fr_CH
 266.899 -fr_CH
 266.900 -French (Switzerland)
 266.901 -ISO-8859-1
 266.902 -
 266.903 -OS Locale:  fr_CH.utf8
 266.904 -fr_CH
 266.905 -French (Switzerland)
 266.906 -UTF-8
 266.907 -
 266.908 -OS Locale:  fr_FR
 266.909 -fr_FR
 266.910 -French (France)
 266.911 -ISO-8859-1
 266.912 -
 266.913 -OS Locale:  fr_FR.utf8
 266.914 -fr_FR
 266.915 -French (France)
 266.916 -UTF-8
 266.917 -
 266.918 -OS Locale:  fr_FR@euro
 266.919 -fr_FR
 266.920 -French (France)
 266.921 -ISO-8859-15
 266.922 -
 266.923 -OS Locale:  fr_LU
 266.924 -fr_LU
 266.925 -French (Luxembourg)
 266.926 -ISO-8859-1
 266.927 -
 266.928 -OS Locale:  fr_LU.utf8
 266.929 -fr_LU
 266.930 -French (Luxembourg)
 266.931 -UTF-8
 266.932 -
 266.933 -OS Locale:  fr_LU@euro
 266.934 -fr_LU
 266.935 -French (Luxembourg)
 266.936 -ISO-8859-15
 266.937 -
 266.938 -OS Locale:  ga_IE
 266.939 -ga_IE
 266.940 -Irish (Ireland)
 266.941 -ISO-8859-1
 266.942 -
 266.943 -OS Locale:  ga_IE.utf8
 266.944 -ga_IE
 266.945 -Irish (Ireland)
 266.946 -UTF-8
 266.947 -
 266.948 -OS Locale:  ga_IE@euro
 266.949 -ga_IE
 266.950 -Irish (Ireland)
 266.951 -ISO-8859-15
 266.952 -
 266.953 -OS Locale:  gd_GB
 266.954 -gd_GB
 266.955 -Scottish Gaelic (United Kingdom)
 266.956 -ISO-8859-15
 266.957 -
 266.958 -OS Locale:  gez_ER
 266.959 -en_ER
 266.960 -English (Eritrea)
 266.961 -UTF-8
 266.962 -
 266.963 -OS Locale:  gez_ER@abegede
 266.964 -en_ER
 266.965 -English (Eritrea)
 266.966 -UTF-8
 266.967 -
 266.968 -OS Locale:  gez_ET
 266.969 -en_ET
 266.970 -English (Ethiopia)
 266.971 -UTF-8
 266.972 -
 266.973 -OS Locale:  gez_ET@abegede
 266.974 -en_ET
 266.975 -English (Ethiopia)
 266.976 -UTF-8
 266.977 -
 266.978 -OS Locale:  gl_ES
 266.979 -gl_ES
 266.980 -Gallegan (Spain)
 266.981 -ISO-8859-1
 266.982 -
 266.983 -OS Locale:  gl_ES.utf8
 266.984 -gl_ES
 266.985 -Gallegan (Spain)
 266.986 -UTF-8
 266.987 -
 266.988 -OS Locale:  gl_ES@euro
 266.989 -gl_ES
 266.990 -Gallegan (Spain)
 266.991 -ISO-8859-15
 266.992 -
 266.993 -OS Locale:  gu_IN
 266.994 -gu_IN
 266.995 -Gujarati (India)
 266.996 -UTF-8
 266.997 -
 266.998 -OS Locale:  gv_GB
 266.999 -gv_GB
266.1000 -Manx (United Kingdom)
266.1001 -ISO-8859-1
266.1002 -
266.1003 -OS Locale:  gv_GB.utf8
266.1004 -gv_GB
266.1005 -Manx (United Kingdom)
266.1006 -UTF-8
266.1007 -
266.1008 -OS Locale:  he_IL
266.1009 -iw_IL
266.1010 -Hebrew (Israel)
266.1011 -ISO-8859-8
266.1012 -
266.1013 -OS Locale:  he_IL.utf8
266.1014 -iw_IL
266.1015 -Hebrew (Israel)
266.1016 -UTF-8
266.1017 -
266.1018 -OS Locale:  hi_IN
266.1019 -hi_IN
266.1020 -Hindi (India)
266.1021 -UTF-8
266.1022 -
266.1023 -OS Locale:  hi_IN.utf8
266.1024 -hi_IN
266.1025 -Hindi (India)
266.1026 -UTF-8
266.1027 -
266.1028 -OS Locale:  hr_HR
266.1029 -hr_HR
266.1030 -Croatian (Croatia)
266.1031 -ISO-8859-2
266.1032 -
266.1033 -OS Locale:  hr_HR.utf8
266.1034 -hr_HR
266.1035 -Croatian (Croatia)
266.1036 -UTF-8
266.1037 -
266.1038 -OS Locale:  hu_HU
266.1039 -hu_HU
266.1040 -Hungarian (Hungary)
266.1041 -ISO-8859-2
266.1042 -
266.1043 -OS Locale:  hu_HU.utf8
266.1044 -hu_HU
266.1045 -Hungarian (Hungary)
266.1046 -UTF-8
266.1047 -
266.1048 -OS Locale:  id_ID
266.1049 -in_ID
266.1050 -Indonesian (Indonesia)
266.1051 -ISO-8859-1
266.1052 -
266.1053 -OS Locale:  id_ID.utf8
266.1054 -in_ID
266.1055 -Indonesian (Indonesia)
266.1056 -UTF-8
266.1057 -
266.1058 -OS Locale:  is_IS
266.1059 -is_IS
266.1060 -Icelandic (Iceland)
266.1061 -ISO-8859-1
266.1062 -
266.1063 -OS Locale:  is_IS.utf8
266.1064 -is_IS
266.1065 -Icelandic (Iceland)
266.1066 -UTF-8
266.1067 -
266.1068 -OS Locale:  it_CH
266.1069 -it_CH
266.1070 -Italian (Switzerland)
266.1071 -ISO-8859-1
266.1072 -
266.1073 -OS Locale:  it_CH.utf8
266.1074 -it_CH
266.1075 -Italian (Switzerland)
266.1076 -UTF-8
266.1077 -
266.1078 -OS Locale:  it_IT
266.1079 -it_IT
266.1080 -Italian (Italy)
266.1081 -ISO-8859-1
266.1082 -
266.1083 -OS Locale:  it_IT.utf8
266.1084 -it_IT
266.1085 -Italian (Italy)
266.1086 -UTF-8
266.1087 -
266.1088 -OS Locale:  it_IT@euro
266.1089 -it_IT
266.1090 -Italian (Italy)
266.1091 -ISO-8859-15
266.1092 -
266.1093 -OS Locale:  iw_IL
266.1094 -iw_IL
266.1095 -Hebrew (Israel)
266.1096 -ISO-8859-8
266.1097 -
266.1098 -OS Locale:  iw_IL.utf8
266.1099 -iw_IL
266.1100 -Hebrew (Israel)
266.1101 -UTF-8
266.1102 -
266.1103 -OS Locale:  ja_JP.eucjp
266.1104 -ja_JP
266.1105 -Japanese (Japan)
266.1106 -x-euc-jp-linux
266.1107 -
266.1108 -OS Locale:  ja_JP.sjis
266.1109 -ja_JP
266.1110 -Japanese (Japan)
266.1111 -Shift_JIS
266.1112 -
266.1113 -OS Locale:  ja_JP.utf8
266.1114 -ja_JP
266.1115 -Japanese (Japan)
266.1116 -UTF-8
266.1117 -
266.1118 -OS Locale:  ka_GE
266.1119 -ka_GE
266.1120 -Georgian (Georgia)
266.1121 -UTF-8
266.1122 -
266.1123 -OS Locale:  kk_KZ
266.1124 -kk_KZ
266.1125 -Kazakh (Kazakhstan)
266.1126 -UTF-8
266.1127 -
266.1128 -OS Locale:  kl_GL
266.1129 -kl_GL
266.1130 -Greenlandic (Greenland)
266.1131 -ISO-8859-1
266.1132 -
266.1133 -OS Locale:  kl_GL.utf8
266.1134 -kl_GL
266.1135 -Greenlandic (Greenland)
266.1136 -UTF-8
266.1137 -
266.1138 -OS Locale:  kn_IN
266.1139 -kn_IN
266.1140 -Kannada (India)
266.1141 -UTF-8
266.1142 -
266.1143 -OS Locale:  ko_KR.euckr
266.1144 -ko_KR
266.1145 -Korean (South Korea)
266.1146 -EUC-KR
266.1147 -
266.1148 -OS Locale:  ko_KR.utf8
266.1149 -ko_KR
266.1150 -Korean (South Korea)
266.1151 -UTF-8
266.1152 -
266.1153 -OS Locale:  kw_GB
266.1154 -kw_GB
266.1155 -Cornish (United Kingdom)
266.1156 -ISO-8859-1
266.1157 -
266.1158 -OS Locale:  kw_GB.utf8
266.1159 -kw_GB
266.1160 -Cornish (United Kingdom)
266.1161 -UTF-8
266.1162 -
266.1163 -OS Locale:  lg_UG
266.1164 -lg_UG
266.1165 -Ganda (Uganda)
266.1166 -UTF-8
266.1167 -
266.1168 -OS Locale:  lo_LA
266.1169 -lo_LA
266.1170 -Lao (Laos)
266.1171 -UTF-8
266.1172 -
266.1173 -OS Locale:  lt_LT
266.1174 -lt_LT
266.1175 -Lithuanian (Lithuania)
266.1176 -ISO-8859-13
266.1177 -
266.1178 -OS Locale:  lt_LT.utf8
266.1179 -lt_LT
266.1180 -Lithuanian (Lithuania)
266.1181 -UTF-8
266.1182 -
266.1183 -OS Locale:  lv_LV
266.1184 -lv_LV
266.1185 -Latvian (Latvia)
266.1186 -ISO-8859-13
266.1187 -
266.1188 -OS Locale:  lv_LV.utf8
266.1189 -lv_LV
266.1190 -Latvian (Latvia)
266.1191 -UTF-8
266.1192 -
266.1193 -OS Locale:  mi_NZ
266.1194 -mi_NZ
266.1195 -Maori (New Zealand)
266.1196 -ISO-8859-13
266.1197 -
266.1198 -OS Locale:  mk_MK
266.1199 -mk_MK
266.1200 -Macedonian (Macedonia)
266.1201 -ISO-8859-5
266.1202 -
266.1203 -OS Locale:  mk_MK.utf8
266.1204 -mk_MK
266.1205 -Macedonian (Macedonia)
266.1206 -UTF-8
266.1207 -
266.1208 -OS Locale:  ml_IN
266.1209 -ml_IN
266.1210 -Malayalam (India)
266.1211 -UTF-8
266.1212 -
266.1213 -OS Locale:  ml_IN.utf8
266.1214 -ml_IN
266.1215 -Malayalam (India)
266.1216 -UTF-8
266.1217 -
266.1218 -OS Locale:  mn_MN
266.1219 -mn_MN
266.1220 -Mongolian (Mongolia)
266.1221 -UTF-8
266.1222 -
266.1223 -OS Locale:  mn_MN.utf8
266.1224 -mn_MN
266.1225 -Mongolian (Mongolia)
266.1226 -UTF-8
266.1227 -
266.1228 -OS Locale:  mr_IN
266.1229 -mr_IN
266.1230 -Marathi (India)
266.1231 -UTF-8
266.1232 -
266.1233 -OS Locale:  mr_IN.utf8
266.1234 -mr_IN
266.1235 -Marathi (India)
266.1236 -UTF-8
266.1237 -
266.1238 -OS Locale:  ms_MY
266.1239 -ms_MY
266.1240 -Malay (Malaysia)
266.1241 -ISO-8859-1
266.1242 -
266.1243 -OS Locale:  ms_MY.utf8
266.1244 -ms_MY
266.1245 -Malay (Malaysia)
266.1246 -UTF-8
266.1247 -
266.1248 -OS Locale:  mt_MT
266.1249 -mt_MT
266.1250 -Maltese (Malta)
266.1251 -ISO-8859-3
266.1252 -
266.1253 -OS Locale:  mt_MT.utf8
266.1254 -mt_MT
266.1255 -Maltese (Malta)
266.1256 -UTF-8
266.1257 -
266.1258 -OS Locale:  nb_NO
266.1259 -nb_NO
266.1260 -Norwegian Bokmål (Norway)
266.1261 -ISO-8859-1
266.1262 -
266.1263 -OS Locale:  nb_NO.utf8
266.1264 -nb_NO
266.1265 -Norwegian Bokmål (Norway)
266.1266 -UTF-8
266.1267 -
266.1268 -OS Locale:  ne_NP
266.1269 -ne_NP
266.1270 -Nepali (Nepal)
266.1271 -UTF-8
266.1272 -
266.1273 -OS Locale:  ne_NP.utf8
266.1274 -ne_NP
266.1275 -Nepali (Nepal)
266.1276 -UTF-8
266.1277 -
266.1278 -OS Locale:  nl_BE
266.1279 -nl_BE
266.1280 -Dutch (Belgium)
266.1281 -ISO-8859-1
266.1282 -
266.1283 -OS Locale:  nl_BE.utf8
266.1284 -nl_BE
266.1285 -Dutch (Belgium)
266.1286 -UTF-8
266.1287 -
266.1288 -OS Locale:  nl_BE@euro
266.1289 -nl_BE
266.1290 -Dutch (Belgium)
266.1291 -ISO-8859-15
266.1292 -
266.1293 -OS Locale:  nl_NL
266.1294 -nl_NL
266.1295 -Dutch (Netherlands)
266.1296 -ISO-8859-1
266.1297 -
266.1298 -OS Locale:  nl_NL.utf8
266.1299 -nl_NL
266.1300 -Dutch (Netherlands)
266.1301 -UTF-8
266.1302 -
266.1303 -OS Locale:  nl_NL@euro
266.1304 -nl_NL
266.1305 -Dutch (Netherlands)
266.1306 -ISO-8859-15
266.1307 -
266.1308 -OS Locale:  nn_NO
266.1309 -nn_NO
266.1310 -Norwegian Nynorsk (Norway)
266.1311 -ISO-8859-1
266.1312 -
266.1313 -OS Locale:  nn_NO.utf8
266.1314 -nn_NO
266.1315 -Norwegian Nynorsk (Norway)
266.1316 -UTF-8
266.1317 -
266.1318 -OS Locale:  no_NO
266.1319 -no_NO
266.1320 -Norwegian (Norway)
266.1321 -ISO-8859-1
266.1322 -
266.1323 -OS Locale:  no_NO.utf8
266.1324 -no_NO
266.1325 -Norwegian (Norway)
266.1326 -UTF-8
266.1327 -
266.1328 -OS Locale:  oc_FR
266.1329 -oc_FR
266.1330 -Occitan (France)
266.1331 -ISO-8859-1
266.1332 -
266.1333 -OS Locale:  om_ET
266.1334 -om_ET
266.1335 -Oromo (Ethiopia)
266.1336 -UTF-8
266.1337 -
266.1338 -OS Locale:  om_ET.utf8
266.1339 -om_ET
266.1340 -Oromo (Ethiopia)
266.1341 -UTF-8
266.1342 -
266.1343 -OS Locale:  om_KE
266.1344 -om_KE
266.1345 -Oromo (Kenya)
266.1346 -ISO-8859-1
266.1347 -
266.1348 -OS Locale:  pa_IN
266.1349 -pa_IN
266.1350 -Panjabi (India)
266.1351 -UTF-8
266.1352 -
266.1353 -OS Locale:  pa_IN.utf8
266.1354 -pa_IN
266.1355 -Panjabi (India)
266.1356 -UTF-8
266.1357 -
266.1358 -OS Locale:  pl_PL
266.1359 -pl_PL
266.1360 -Polish (Poland)
266.1361 -ISO-8859-2
266.1362 -
266.1363 -OS Locale:  pl_PL.utf8
266.1364 -pl_PL
266.1365 -Polish (Poland)
266.1366 -UTF-8
266.1367 -
266.1368 -OS Locale:  pt_BR
266.1369 -pt_BR
266.1370 -Portuguese (Brazil)
266.1371 -ISO-8859-1
266.1372 -
266.1373 -OS Locale:  pt_BR.utf8
266.1374 -pt_BR
266.1375 -Portuguese (Brazil)
266.1376 -UTF-8
266.1377 -
266.1378 -OS Locale:  pt_PT
266.1379 -pt_PT
266.1380 -Portuguese (Portugal)
266.1381 -ISO-8859-1
266.1382 -
266.1383 -OS Locale:  pt_PT.utf8
266.1384 -pt_PT
266.1385 -Portuguese (Portugal)
266.1386 -UTF-8
266.1387 -
266.1388 -OS Locale:  pt_PT@euro
266.1389 -pt_PT
266.1390 -Portuguese (Portugal)
266.1391 -ISO-8859-15
266.1392 -
266.1393 -OS Locale:  ro_RO
266.1394 -ro_RO
266.1395 -Romanian (Romania)
266.1396 -ISO-8859-2
266.1397 -
266.1398 -OS Locale:  ro_RO.utf8
266.1399 -ro_RO
266.1400 -Romanian (Romania)
266.1401 -UTF-8
266.1402 -
266.1403 -OS Locale:  ru_RU
266.1404 -ru_RU
266.1405 -Russian (Russia)
266.1406 -ISO-8859-5
266.1407 -
266.1408 -OS Locale:  ru_RU.koi8r
266.1409 -ru_RU
266.1410 -Russian (Russia)
266.1411 -KOI8-R
266.1412 -
266.1413 -OS Locale:  ru_RU.utf8
266.1414 -ru_RU
266.1415 -Russian (Russia)
266.1416 -UTF-8
266.1417 -
266.1418 -OS Locale:  ru_UA
266.1419 -ru_UA
266.1420 -Russian (Ukraine)
266.1421 -KOI8-U
266.1422 -
266.1423 -OS Locale:  ru_UA.utf8
266.1424 -ru_UA
266.1425 -Russian (Ukraine)
266.1426 -UTF-8
266.1427 -
266.1428 -OS Locale:  se_NO
266.1429 -se_NO
266.1430 -Northern Sami (Norway)
266.1431 -UTF-8
266.1432 -
266.1433 -OS Locale:  se_NO.utf8
266.1434 -se_NO
266.1435 -Northern Sami (Norway)
266.1436 -UTF-8
266.1437 -
266.1438 -OS Locale:  sh_YU
266.1439 -sr_CS
266.1440 -Serbian (Serbia and Montenegro)
266.1441 -ISO-8859-2
266.1442 -
266.1443 -OS Locale:  sh_YU.utf8
266.1444 -sr_CS
266.1445 -Serbian (Serbia and Montenegro)
266.1446 -UTF-8
266.1447 -
266.1448 -OS Locale:  sid_ET
266.1449 -en_ET
266.1450 -English (Ethiopia)
266.1451 -UTF-8
266.1452 -
266.1453 -OS Locale:  sid_ET.utf8
266.1454 -en_ET
266.1455 -English (Ethiopia)
266.1456 -UTF-8
266.1457 -
266.1458 -OS Locale:  sk_SK
266.1459 -sk_SK
266.1460 -Slovak (Slovakia)
266.1461 -ISO-8859-2
266.1462 -
266.1463 -OS Locale:  sk_SK.utf8
266.1464 -sk_SK
266.1465 -Slovak (Slovakia)
266.1466 -UTF-8
266.1467 -
266.1468 -OS Locale:  sl_SI
266.1469 -sl_SI
266.1470 -Slovenian (Slovenia)
266.1471 -ISO-8859-2
266.1472 -
266.1473 -OS Locale:  sl_SI.utf8
266.1474 -sl_SI
266.1475 -Slovenian (Slovenia)
266.1476 -UTF-8
266.1477 -
266.1478 -OS Locale:  so_DJ
266.1479 -so_DJ
266.1480 -Somali (Djibouti)
266.1481 -ISO-8859-1
266.1482 -
266.1483 -OS Locale:  so_ET
266.1484 -so_ET
266.1485 -Somali (Ethiopia)
266.1486 -UTF-8
266.1487 -
266.1488 -OS Locale:  so_ET.utf8
266.1489 -so_ET
266.1490 -Somali (Ethiopia)
266.1491 -UTF-8
266.1492 -
266.1493 -OS Locale:  so_KE
266.1494 -so_KE
266.1495 -Somali (Kenya)
266.1496 -ISO-8859-1
266.1497 -
266.1498 -OS Locale:  so_SO
266.1499 -so_SO
266.1500 -Somali (Somalia)
266.1501 -ISO-8859-1
266.1502 -
266.1503 -OS Locale:  sq_AL
266.1504 -sq_AL
266.1505 -Albanian (Albania)
266.1506 -ISO-8859-1
266.1507 -
266.1508 -OS Locale:  sq_AL.utf8
266.1509 -sq_AL
266.1510 -Albanian (Albania)
266.1511 -UTF-8
266.1512 -
266.1513 -OS Locale:  sr_YU
266.1514 -sr_CS
266.1515 -Serbian (Serbia and Montenegro)
266.1516 -ISO-8859-2
266.1517 -
266.1518 -OS Locale:  sr_YU.utf8
266.1519 -sr_CS
266.1520 -Serbian (Serbia and Montenegro)
266.1521 -UTF-8
266.1522 -
266.1523 -OS Locale:  sr_YU.utf8@cyrillic
266.1524 -sr_CS
266.1525 -Serbian (Serbia and Montenegro)
266.1526 -UTF-8
266.1527 -
266.1528 -OS Locale:  sr_YU@cyrillic
266.1529 -sr_CS
266.1530 -Serbian (Serbia and Montenegro)
266.1531 -ISO-8859-5
266.1532 -
266.1533 -OS Locale:  st_ZA
266.1534 -st_ZA
266.1535 -Southern Sotho (South Africa)
266.1536 -ISO-8859-1
266.1537 -
266.1538 -OS Locale:  st_ZA.utf8
266.1539 -st_ZA
266.1540 -Southern Sotho (South Africa)
266.1541 -UTF-8
266.1542 -
266.1543 -OS Locale:  sv_FI
266.1544 -sv_FI
266.1545 -Swedish (Finland)
266.1546 -ISO-8859-1
266.1547 -
266.1548 -OS Locale:  sv_FI.utf8
266.1549 -sv_FI
266.1550 -Swedish (Finland)
266.1551 -UTF-8
266.1552 -
266.1553 -OS Locale:  sv_FI@euro
266.1554 -sv_FI
266.1555 -Swedish (Finland)
266.1556 -ISO-8859-15
266.1557 -
266.1558 -OS Locale:  sv_SE
266.1559 -sv_SE
266.1560 -Swedish (Sweden)
266.1561 -ISO-8859-1
266.1562 -
266.1563 -OS Locale:  sv_SE.iso885915
266.1564 -sv_SE
266.1565 -Swedish (Sweden)
266.1566 -ISO-8859-15
266.1567 -
266.1568 -OS Locale:  sv_SE.utf8
266.1569 -sv_SE
266.1570 -Swedish (Sweden)
266.1571 -UTF-8
266.1572 -
266.1573 -OS Locale:  ta_IN
266.1574 -ta_IN
266.1575 -Tamil (India)
266.1576 -UTF-8
266.1577 -
266.1578 -OS Locale:  ta_IN.utf8
266.1579 -ta_IN
266.1580 -Tamil (India)
266.1581 -UTF-8
266.1582 -
266.1583 -OS Locale:  te_IN
266.1584 -te_IN
266.1585 -Telugu (India)
266.1586 -UTF-8
266.1587 -
266.1588 -OS Locale:  te_IN.utf8
266.1589 -te_IN
266.1590 -Telugu (India)
266.1591 -UTF-8
266.1592 -
266.1593 -OS Locale:  tg_TJ
266.1594 -tg_TJ
266.1595 -Tajik (Tajikistan)
266.1596 -UTF-8
266.1597 -
266.1598 -OS Locale:  th_TH
266.1599 -th_TH
266.1600 -Thai (Thailand)
266.1601 -TIS-620
266.1602 -
266.1603 -OS Locale:  th_TH.utf8
266.1604 -th_TH
266.1605 -Thai (Thailand)
266.1606 -UTF-8
266.1607 -
266.1608 -OS Locale:  ti_ER
266.1609 -ti_ER
266.1610 -Tigrinya (Eritrea)
266.1611 -UTF-8
266.1612 -
266.1613 -OS Locale:  ti_ER.utf8
266.1614 -ti_ER
266.1615 -Tigrinya (Eritrea)
266.1616 -UTF-8
266.1617 -
266.1618 -OS Locale:  ti_ET
266.1619 -ti_ET
266.1620 -Tigrinya (Ethiopia)
266.1621 -UTF-8
266.1622 -
266.1623 -OS Locale:  ti_ET.utf8
266.1624 -ti_ET
266.1625 -Tigrinya (Ethiopia)
266.1626 -UTF-8
266.1627 -
266.1628 -OS Locale:  tig_ER
266.1629 -en_ER
266.1630 -English (Eritrea)
266.1631 -UTF-8
266.1632 -
266.1633 -OS Locale:  tig_ER.utf8
266.1634 -en_ER
266.1635 -English (Eritrea)
266.1636 -UTF-8
266.1637 -
266.1638 -OS Locale:  tl_PH
266.1639 -tl_PH
266.1640 -Tagalog (Philippines)
266.1641 -ISO-8859-1
266.1642 -
266.1643 -OS Locale:  tr_TR
266.1644 -tr_TR
266.1645 -Turkish (Turkey)
266.1646 -ISO-8859-9
266.1647 -
266.1648 -OS Locale:  tr_TR.utf8
266.1649 -tr_TR
266.1650 -Turkish (Turkey)
266.1651 -UTF-8
266.1652 -
266.1653 -OS Locale:  tt_RU.utf8
266.1654 -tt_RU
266.1655 -Tatar (Russia)
266.1656 -UTF-8
266.1657 -
266.1658 -OS Locale:  uk_UA
266.1659 -uk_UA
266.1660 -Ukrainian (Ukraine)
266.1661 -KOI8-U
266.1662 -
266.1663 -OS Locale:  uk_UA.utf8
266.1664 -uk_UA
266.1665 -Ukrainian (Ukraine)
266.1666 -UTF-8
266.1667 -
266.1668 -OS Locale:  ur_PK
266.1669 -ur_PK
266.1670 -Urdu (Pakistan)
266.1671 -UTF-8
266.1672 -
266.1673 -OS Locale:  ur_PK.utf8
266.1674 -ur_PK
266.1675 -Urdu (Pakistan)
266.1676 -UTF-8
266.1677 -
266.1678 -OS Locale:  uz_UZ
266.1679 -uz_UZ
266.1680 -Uzbek (Uzbekistan)
266.1681 -ISO-8859-1
266.1682 -
266.1683 -OS Locale:  uz_UZ@cyrillic
266.1684 -uz_UZ
266.1685 -Uzbek (Uzbekistan)
266.1686 -UTF-8
266.1687 -
266.1688 -OS Locale:  vi_VN
266.1689 -vi_VN
266.1690 -Vietnamese (Vietnam)
266.1691 -UTF-8
266.1692 -
266.1693 -OS Locale:  vi_VN.tcvn
266.1694 -vi_VN
266.1695 -Vietnamese (Vietnam)
266.1696 -UTF-8
266.1697 -
266.1698 -OS Locale:  vi_VN.utf8
266.1699 -vi_VN
266.1700 -Vietnamese (Vietnam)
266.1701 -UTF-8
266.1702 -
266.1703 -OS Locale:  wa_BE
266.1704 -wa_BE
266.1705 -Walloon (Belgium)
266.1706 -ISO-8859-1
266.1707 -
266.1708 -OS Locale:  wa_BE.utf8
266.1709 -wa_BE
266.1710 -Walloon (Belgium)
266.1711 -UTF-8
266.1712 -
266.1713 -OS Locale:  wa_BE@euro
266.1714 -wa_BE
266.1715 -Walloon (Belgium)
266.1716 -ISO-8859-15
266.1717 -
266.1718 -OS Locale:  xh_ZA
266.1719 -xh_ZA
266.1720 -Xhosa (South Africa)
266.1721 -ISO-8859-1
266.1722 -
266.1723 -OS Locale:  xh_ZA.utf8
266.1724 -xh_ZA
266.1725 -Xhosa (South Africa)
266.1726 -UTF-8
266.1727 -
266.1728 -OS Locale:  yi_US
266.1729 -ji_US
266.1730 -Yiddish (United States)
266.1731 -windows-1255
266.1732 -
266.1733 -OS Locale:  zh_CN
266.1734 -zh_CN
266.1735 -Chinese (China)
266.1736 -GB2312
266.1737 -
266.1738 -OS Locale:  zh_CN.gb18030
266.1739 -zh_CN
266.1740 -Chinese (China)
266.1741 -GB18030
266.1742 -
266.1743 -OS Locale:  zh_CN.gbk
266.1744 -zh_CN
266.1745 -Chinese (China)
266.1746 -GBK
266.1747 -
266.1748 -OS Locale:  zh_CN.utf8
266.1749 -zh_CN
266.1750 -Chinese (China)
266.1751 -UTF-8
266.1752 -
266.1753 -OS Locale:  zh_HK
266.1754 -zh_HK
266.1755 -Chinese (Hong Kong)
266.1756 -Big5-HKSCS
266.1757 -
266.1758 -OS Locale:  zh_HK.utf8
266.1759 -zh_HK
266.1760 -Chinese (Hong Kong)
266.1761 -UTF-8
266.1762 -
266.1763 -OS Locale:  zh_SG
266.1764 -zh_SG
266.1765 -Chinese (Singapore)
266.1766 -GB2312
266.1767 -
266.1768 -OS Locale:  zh_SG.gbk
266.1769 -zh_SG
266.1770 -Chinese (Singapore)
266.1771 -GBK
266.1772 -
266.1773 -OS Locale:  zh_TW
266.1774 -zh_TW
266.1775 -Chinese (Taiwan)
266.1776 -Big5
266.1777 -
266.1778 -OS Locale:  zh_TW.euctw
266.1779 -zh_TW
266.1780 -Chinese (Taiwan)
266.1781 -x-EUC-TW
266.1782 -
266.1783 -OS Locale:  zh_TW.utf8
266.1784 -zh_TW
266.1785 -Chinese (Taiwan)
266.1786 -UTF-8
266.1787 -
266.1788 -OS Locale:  zu_ZA
266.1789 -zu_ZA
266.1790 -Zulu (South Africa)
266.1791 -ISO-8859-1
266.1792 -
266.1793 -OS Locale:  zu_ZA.utf8
266.1794 -zu_ZA
266.1795 -Zulu (South Africa)
266.1796 -UTF-8
   267.1 --- a/test/java/util/Locale/data/deflocale.rhel4	Thu Sep 23 17:33:40 2010 -0700
   267.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   267.3 @@ -1,1623 +0,0 @@
   267.4 -LSB_VERSION="1.3"
   267.5 -Red Hat Enterprise Linux AS release 4 (Nahant Update 1)
   267.6 -Linux i18n-hp733-6.sfbay.sun.com 2.6.9-6.37.EL #1 Tue Mar 29 15:34:14 EST 2005 i686 i686 i386 GNU/Linux
   267.7 -
   267.8 -OS Locale:  aa_DJ
   267.9 -aa_DJ
  267.10 -Afar (Djibouti)
  267.11 -ISO-8859-1
  267.12 -
  267.13 -OS Locale:  aa_ER
  267.14 -aa_ER
  267.15 -Afar (Eritrea)
  267.16 -UTF-8
  267.17 -
  267.18 -OS Locale:  aa_ER@saaho
  267.19 -aa_ER
  267.20 -Afar (Eritrea)
  267.21 -UTF-8
  267.22 -
  267.23 -OS Locale:  aa_ET
  267.24 -aa_ET
  267.25 -Afar (Ethiopia)
  267.26 -UTF-8
  267.27 -
  267.28 -OS Locale:  af_ZA
  267.29 -af_ZA
  267.30 -Afrikaans (South Africa)
  267.31 -ISO-8859-1
  267.32 -
  267.33 -OS Locale:  am_ET
  267.34 -am_ET
  267.35 -Amharic (Ethiopia)
  267.36 -UTF-8
  267.37 -
  267.38 -OS Locale:  an_ES
  267.39 -an_ES
  267.40 -Aragonese (Spain)
  267.41 -ISO-8859-15
  267.42 -
  267.43 -OS Locale:  ar_AE
  267.44 -ar_AE
  267.45 -Arabic (United Arab Emirates)
  267.46 -ISO-8859-6
  267.47 -
  267.48 -OS Locale:  ar_AE.utf8
  267.49 -ar_AE
  267.50 -Arabic (United Arab Emirates)
  267.51 -UTF-8
  267.52 -
  267.53 -OS Locale:  ar_BH
  267.54 -ar_BH
  267.55 -Arabic (Bahrain)
  267.56 -ISO-8859-6
  267.57 -
  267.58 -OS Locale:  ar_BH.utf8
  267.59 -ar_BH
  267.60 -Arabic (Bahrain)
  267.61 -UTF-8
  267.62 -
  267.63 -OS Locale:  ar_DZ
  267.64 -ar_DZ
  267.65 -Arabic (Algeria)
  267.66 -ISO-8859-6
  267.67 -
  267.68 -OS Locale:  ar_DZ.utf8
  267.69 -ar_DZ
  267.70 -Arabic (Algeria)
  267.71 -UTF-8
  267.72 -
  267.73 -OS Locale:  ar_EG
  267.74 -ar_EG
  267.75 -Arabic (Egypt)
  267.76 -ISO-8859-6
  267.77 -
  267.78 -OS Locale:  ar_EG.utf8
  267.79 -ar_EG
  267.80 -Arabic (Egypt)
  267.81 -UTF-8
  267.82 -
  267.83 -OS Locale:  ar_IN
  267.84 -ar_IN
  267.85 -Arabic (India)
  267.86 -UTF-8
  267.87 -
  267.88 -OS Locale:  ar_IQ
  267.89 -ar_IQ
  267.90 -Arabic (Iraq)
  267.91 -ISO-8859-6
  267.92 -
  267.93 -OS Locale:  ar_IQ.utf8
  267.94 -ar_IQ
  267.95 -Arabic (Iraq)
  267.96 -UTF-8
  267.97 -
  267.98 -OS Locale:  ar_JO
  267.99 -ar_JO
 267.100 -Arabic (Jordan)
 267.101 -ISO-8859-6
 267.102 -
 267.103 -OS Locale:  ar_JO.utf8
 267.104 -ar_JO
 267.105 -Arabic (Jordan)
 267.106 -UTF-8
 267.107 -
 267.108 -OS Locale:  ar_KW
 267.109 -ar_KW
 267.110 -Arabic (Kuwait)
 267.111 -ISO-8859-6
 267.112 -
 267.113 -OS Locale:  ar_KW.utf8
 267.114 -ar_KW
 267.115 -Arabic (Kuwait)
 267.116 -UTF-8
 267.117 -
 267.118 -OS Locale:  ar_LB
 267.119 -ar_LB
 267.120 -Arabic (Lebanon)
 267.121 -ISO-8859-6
 267.122 -
 267.123 -OS Locale:  ar_LB.utf8
 267.124 -ar_LB
 267.125 -Arabic (Lebanon)
 267.126 -UTF-8
 267.127 -
 267.128 -OS Locale:  ar_LY
 267.129 -ar_LY
 267.130 -Arabic (Libya)
 267.131 -ISO-8859-6
 267.132 -
 267.133 -OS Locale:  ar_LY.utf8
 267.134 -ar_LY
 267.135 -Arabic (Libya)
 267.136 -UTF-8
 267.137 -
 267.138 -OS Locale:  ar_MA
 267.139 -ar_MA
 267.140 -Arabic (Morocco)
 267.141 -ISO-8859-6
 267.142 -
 267.143 -OS Locale:  ar_MA.utf8
 267.144 -ar_MA
 267.145 -Arabic (Morocco)
 267.146 -UTF-8
 267.147 -
 267.148 -OS Locale:  ar_OM
 267.149 -ar_OM
 267.150 -Arabic (Oman)
 267.151 -ISO-8859-6
 267.152 -
 267.153 -OS Locale:  ar_OM.utf8
 267.154 -ar_OM
 267.155 -Arabic (Oman)
 267.156 -UTF-8
 267.157 -
 267.158 -OS Locale:  ar_QA
 267.159 -ar_QA
 267.160 -Arabic (Qatar)
 267.161 -ISO-8859-6
 267.162 -
 267.163 -OS Locale:  ar_QA.utf8
 267.164 -ar_QA
 267.165 -Arabic (Qatar)
 267.166 -UTF-8
 267.167 -
 267.168 -OS Locale:  ar_SA
 267.169 -ar_SA
 267.170 -Arabic (Saudi Arabia)
 267.171 -ISO-8859-6
 267.172 -
 267.173 -OS Locale:  ar_SA.utf8
 267.174 -ar_SA
 267.175 -Arabic (Saudi Arabia)
 267.176 -UTF-8
 267.177 -
 267.178 -OS Locale:  ar_SD
 267.179 -ar_SD
 267.180 -Arabic (Sudan)
 267.181 -ISO-8859-6
 267.182 -
 267.183 -OS Locale:  ar_SD.utf8
 267.184 -ar_SD
 267.185 -Arabic (Sudan)
 267.186 -UTF-8
 267.187 -
 267.188 -OS Locale:  ar_SY
 267.189 -ar_SY
 267.190 -Arabic (Syria)
 267.191 -ISO-8859-6
 267.192 -
 267.193 -OS Locale:  ar_SY.utf8
 267.194 -ar_SY
 267.195 -Arabic (Syria)
 267.196 -UTF-8
 267.197 -
 267.198 -OS Locale:  ar_TN
 267.199 -ar_TN
 267.200 -Arabic (Tunisia)
 267.201 -ISO-8859-6
 267.202 -
 267.203 -OS Locale:  ar_TN.utf8
 267.204 -ar_TN
 267.205 -Arabic (Tunisia)
 267.206 -UTF-8
 267.207 -
 267.208 -OS Locale:  ar_YE
 267.209 -ar_YE
 267.210 -Arabic (Yemen)
 267.211 -ISO-8859-6
 267.212 -
 267.213 -OS Locale:  ar_YE.utf8
 267.214 -ar_YE
 267.215 -Arabic (Yemen)
 267.216 -UTF-8
 267.217 -
 267.218 -OS Locale:  az_AZ.utf8
 267.219 -az_AZ
 267.220 -Azerbaijani (Azerbaijan)
 267.221 -UTF-8
 267.222 -
 267.223 -OS Locale:  be_BY
 267.224 -be_BY
 267.225 -Belarusian (Belarus)
 267.226 -windows-1251
 267.227 -
 267.228 -OS Locale:  be_BY.utf8
 267.229 -be_BY
 267.230 -Belarusian (Belarus)
 267.231 -UTF-8
 267.232 -
 267.233 -OS Locale:  bg_BG
 267.234 -bg_BG
 267.235 -Bulgarian (Bulgaria)
 267.236 -windows-1251
 267.237 -
 267.238 -OS Locale:  bg_BG.utf8
 267.239 -bg_BG
 267.240 -Bulgarian (Bulgaria)
 267.241 -UTF-8
 267.242 -
 267.243 -OS Locale:  bn_BD
 267.244 -bn_BD
 267.245 -Bengali (Bangladesh)
 267.246 -UTF-8
 267.247 -
 267.248 -OS Locale:  bn_IN
 267.249 -bn_IN
 267.250 -Bengali (India)
 267.251 -UTF-8
 267.252 -
 267.253 -OS Locale:  br_FR
 267.254 -br_FR
 267.255 -Breton (France)
 267.256 -ISO-8859-1
 267.257 -
 267.258 -OS Locale:  br_FR@euro
 267.259 -br_FR
 267.260 -Breton (France)
 267.261 -ISO-8859-15
 267.262 -
 267.263 -OS Locale:  bs_BA
 267.264 -bs_BA
 267.265 -Bosnian (Bosnia and Herzegovina)
 267.266 -ISO-8859-2
 267.267 -
 267.268 -OS Locale:  byn_ER
 267.269 -en_ER
 267.270 -English (Eritrea)
 267.271 -UTF-8
 267.272 -
 267.273 -OS Locale:  ca_ES
 267.274 -ca_ES
 267.275 -Catalan (Spain)
 267.276 -ISO-8859-1
 267.277 -
 267.278 -OS Locale:  ca_ES.utf8
 267.279 -ca_ES
 267.280 -Catalan (Spain)
 267.281 -UTF-8
 267.282 -
 267.283 -OS Locale:  ca_ES@euro
 267.284 -ca_ES
 267.285 -Catalan (Spain)
 267.286 -ISO-8859-15
 267.287 -
 267.288 -OS Locale:  cs_CZ
 267.289 -cs_CZ
 267.290 -Czech (Czech Republic)
 267.291 -ISO-8859-2
 267.292 -
 267.293 -OS Locale:  cs_CZ.utf8
 267.294 -cs_CZ
 267.295 -Czech (Czech Republic)
 267.296 -UTF-8
 267.297 -
 267.298 -OS Locale:  cy_GB
 267.299 -cy_GB
 267.300 -Welsh (United Kingdom)
 267.301 -UTF-8
 267.302 -
 267.303 -OS Locale:  cy_GB.utf8
 267.304 -cy_GB
 267.305 -Welsh (United Kingdom)
 267.306 -UTF-8
 267.307 -
 267.308 -OS Locale:  da_DK
 267.309 -da_DK
 267.310 -Danish (Denmark)
 267.311 -ISO-8859-1
 267.312 -
 267.313 -OS Locale:  da_DK.iso885915
 267.314 -da_DK
 267.315 -Danish (Denmark)
 267.316 -ISO-8859-15
 267.317 -
 267.318 -OS Locale:  da_DK.utf8
 267.319 -da_DK
 267.320 -Danish (Denmark)
 267.321 -UTF-8
 267.322 -
 267.323 -OS Locale:  de_AT
 267.324 -de_AT
 267.325 -German (Austria)
 267.326 -ISO-8859-1
 267.327 -
 267.328 -OS Locale:  de_AT.utf8
 267.329 -de_AT
 267.330 -German (Austria)
 267.331 -UTF-8
 267.332 -
 267.333 -OS Locale:  de_AT@euro
 267.334 -de_AT
 267.335 -German (Austria)
 267.336 -ISO-8859-15
 267.337 -
 267.338 -OS Locale:  de_BE
 267.339 -de_BE
 267.340 -German (Belgium)
 267.341 -ISO-8859-1
 267.342 -
 267.343 -OS Locale:  de_BE.utf8
 267.344 -de_BE
 267.345 -German (Belgium)
 267.346 -UTF-8
 267.347 -
 267.348 -OS Locale:  de_BE@euro
 267.349 -de_BE
 267.350 -German (Belgium)
 267.351 -ISO-8859-15
 267.352 -
 267.353 -OS Locale:  de_CH
 267.354 -de_CH
 267.355 -German (Switzerland)
 267.356 -ISO-8859-1
 267.357 -
 267.358 -OS Locale:  de_CH.utf8
 267.359 -de_CH
 267.360 -German (Switzerland)
 267.361 -UTF-8
 267.362 -
 267.363 -OS Locale:  de_DE
 267.364 -de_DE
 267.365 -German (Germany)
 267.366 -ISO-8859-1
 267.367 -
 267.368 -OS Locale:  de_DE.utf8
 267.369 -de_DE
 267.370 -German (Germany)
 267.371 -UTF-8
 267.372 -
 267.373 -OS Locale:  de_DE@euro
 267.374 -de_DE
 267.375 -German (Germany)
 267.376 -ISO-8859-15
 267.377 -
 267.378 -OS Locale:  de_LU
 267.379 -de_LU
 267.380 -German (Luxembourg)
 267.381 -ISO-8859-1
 267.382 -
 267.383 -OS Locale:  de_LU.utf8
 267.384 -de_LU
 267.385 -German (Luxembourg)
 267.386 -UTF-8
 267.387 -
 267.388 -OS Locale:  de_LU@euro
 267.389 -de_LU
 267.390 -German (Luxembourg)
 267.391 -ISO-8859-15
 267.392 -
 267.393 -OS Locale:  el_GR
 267.394 -el_GR
 267.395 -Greek (Greece)
 267.396 -ISO-8859-7
 267.397 -
 267.398 -OS Locale:  el_GR.utf8
 267.399 -el_GR
 267.400 -Greek (Greece)
 267.401 -UTF-8
 267.402 -
 267.403 -OS Locale:  en_AU
 267.404 -en_AU
 267.405 -English (Australia)
 267.406 -ISO-8859-1
 267.407 -
 267.408 -OS Locale:  en_AU.utf8
 267.409 -en_AU
 267.410 -English (Australia)
 267.411 -UTF-8
 267.412 -
 267.413 -OS Locale:  en_BW
 267.414 -en_BW
 267.415 -English (Botswana)
 267.416 -ISO-8859-1
 267.417 -
 267.418 -OS Locale:  en_BW.utf8
 267.419 -en_BW
 267.420 -English (Botswana)
 267.421 -UTF-8
 267.422 -
 267.423 -OS Locale:  en_CA
 267.424 -en_CA
 267.425 -English (Canada)
 267.426 -ISO-8859-1
 267.427 -
 267.428 -OS Locale:  en_CA.utf8
 267.429 -en_CA
 267.430 -English (Canada)
 267.431 -UTF-8
 267.432 -
 267.433 -OS Locale:  en_DK
 267.434 -en_DK
 267.435 -English (Denmark)
 267.436 -ISO-8859-1
 267.437 -
 267.438 -OS Locale:  en_DK.utf8
 267.439 -en_DK
 267.440 -English (Denmark)
 267.441 -UTF-8
 267.442 -
 267.443 -OS Locale:  en_GB
 267.444 -en_GB
 267.445 -English (United Kingdom)
 267.446 -ISO-8859-1
 267.447 -
 267.448 -OS Locale:  en_GB.iso885915
 267.449 -en_GB
 267.450 -English (United Kingdom)
 267.451 -ISO-8859-15
 267.452 -
 267.453 -OS Locale:  en_GB.utf8
 267.454 -en_GB
 267.455 -English (United Kingdom)
 267.456 -UTF-8
 267.457 -
 267.458 -OS Locale:  en_HK
 267.459 -en_HK
 267.460 -English (Hong Kong)
 267.461 -ISO-8859-1
 267.462 -
 267.463 -OS Locale:  en_HK.utf8
 267.464 -en_HK
 267.465 -English (Hong Kong)
 267.466 -UTF-8
 267.467 -
 267.468 -OS Locale:  en_IE
 267.469 -en_IE
 267.470 -English (Ireland)
 267.471 -ISO-8859-1
 267.472 -
 267.473 -OS Locale:  en_IE.utf8
 267.474 -en_IE
 267.475 -English (Ireland)
 267.476 -UTF-8
 267.477 -
 267.478 -OS Locale:  en_IE@euro
 267.479 -en_IE
 267.480 -English (Ireland)
 267.481 -ISO-8859-15
 267.482 -
 267.483 -OS Locale:  en_IN
 267.484 -en_IN
 267.485 -English (India)
 267.486 -UTF-8
 267.487 -
 267.488 -OS Locale:  en_NZ
 267.489 -en_NZ
 267.490 -English (New Zealand)
 267.491 -ISO-8859-1
 267.492 -
 267.493 -OS Locale:  en_NZ.utf8
 267.494 -en_NZ
 267.495 -English (New Zealand)
 267.496 -UTF-8
 267.497 -
 267.498 -OS Locale:  en_PH
 267.499 -en_PH
 267.500 -English (Philippines)
 267.501 -ISO-8859-1
 267.502 -
 267.503 -OS Locale:  en_PH.utf8
 267.504 -en_PH
 267.505 -English (Philippines)
 267.506 -UTF-8
 267.507 -
 267.508 -OS Locale:  en_SG
 267.509 -en_SG
 267.510 -English (Singapore)
 267.511 -ISO-8859-1
 267.512 -
 267.513 -OS Locale:  en_SG.utf8
 267.514 -en_SG
 267.515 -English (Singapore)
 267.516 -UTF-8
 267.517 -
 267.518 -OS Locale:  en_US
 267.519 -en_US
 267.520 -English (United States)
 267.521 -ISO-8859-1
 267.522 -
 267.523 -OS Locale:  en_US.iso885915
 267.524 -en_US
 267.525 -English (United States)
 267.526 -ISO-8859-15
 267.527 -
 267.528 -OS Locale:  en_US.utf8
 267.529 -en_US
 267.530 -English (United States)
 267.531 -UTF-8
 267.532 -
 267.533 -OS Locale:  en_ZA
 267.534 -en_ZA
 267.535 -English (South Africa)
 267.536 -ISO-8859-1
 267.537 -
 267.538 -OS Locale:  en_ZA.utf8
 267.539 -en_ZA
 267.540 -English (South Africa)
 267.541 -UTF-8
 267.542 -
 267.543 -OS Locale:  en_ZW
 267.544 -en_ZW
 267.545 -English (Zimbabwe)
 267.546 -ISO-8859-1
 267.547 -
 267.548 -OS Locale:  en_ZW.utf8
 267.549 -en_ZW
 267.550 -English (Zimbabwe)
 267.551 -UTF-8
 267.552 -
 267.553 -OS Locale:  es_AR
 267.554 -es_AR
 267.555 -Spanish (Argentina)
 267.556 -ISO-8859-1
 267.557 -
 267.558 -OS Locale:  es_AR.utf8
 267.559 -es_AR
 267.560 -Spanish (Argentina)
 267.561 -UTF-8
 267.562 -
 267.563 -OS Locale:  es_BO
 267.564 -es_BO
 267.565 -Spanish (Bolivia)
 267.566 -ISO-8859-1
 267.567 -
 267.568 -OS Locale:  es_BO.utf8
 267.569 -es_BO
 267.570 -Spanish (Bolivia)
 267.571 -UTF-8
 267.572 -
 267.573 -OS Locale:  es_CL
 267.574 -es_CL
 267.575 -Spanish (Chile)
 267.576 -ISO-8859-1
 267.577 -
 267.578 -OS Locale:  es_CL.utf8
 267.579 -es_CL
 267.580 -Spanish (Chile)
 267.581 -UTF-8
 267.582 -
 267.583 -OS Locale:  es_CO
 267.584 -es_CO
 267.585 -Spanish (Colombia)
 267.586 -ISO-8859-1
 267.587 -
 267.588 -OS Locale:  es_CO.utf8
 267.589 -es_CO
 267.590 -Spanish (Colombia)
 267.591 -UTF-8
 267.592 -
 267.593 -OS Locale:  es_CR
 267.594 -es_CR
 267.595 -Spanish (Costa Rica)
 267.596 -ISO-8859-1
 267.597 -
 267.598 -OS Locale:  es_CR.utf8
 267.599 -es_CR
 267.600 -Spanish (Costa Rica)
 267.601 -UTF-8
 267.602 -
 267.603 -OS Locale:  es_DO
 267.604 -es_DO
 267.605 -Spanish (Dominican Republic)
 267.606 -ISO-8859-1
 267.607 -
 267.608 -OS Locale:  es_DO.utf8
 267.609 -es_DO
 267.610 -Spanish (Dominican Republic)
 267.611 -UTF-8
 267.612 -
 267.613 -OS Locale:  es_EC
 267.614 -es_EC
 267.615 -Spanish (Ecuador)
 267.616 -ISO-8859-1
 267.617 -
 267.618 -OS Locale:  es_EC.utf8
 267.619 -es_EC
 267.620 -Spanish (Ecuador)
 267.621 -UTF-8
 267.622 -
 267.623 -OS Locale:  es_ES
 267.624 -es_ES
 267.625 -Spanish (Spain)
 267.626 -ISO-8859-1
 267.627 -
 267.628 -OS Locale:  es_ES.utf8
 267.629 -es_ES
 267.630 -Spanish (Spain)
 267.631 -UTF-8
 267.632 -
 267.633 -OS Locale:  es_ES@euro
 267.634 -es_ES
 267.635 -Spanish (Spain)
 267.636 -ISO-8859-15
 267.637 -
 267.638 -OS Locale:  es_GT
 267.639 -es_GT
 267.640 -Spanish (Guatemala)
 267.641 -ISO-8859-1
 267.642 -
 267.643 -OS Locale:  es_GT.utf8
 267.644 -es_GT
 267.645 -Spanish (Guatemala)
 267.646 -UTF-8
 267.647 -
 267.648 -OS Locale:  es_HN
 267.649 -es_HN
 267.650 -Spanish (Honduras)
 267.651 -ISO-8859-1
 267.652 -
 267.653 -OS Locale:  es_HN.utf8
 267.654 -es_HN
 267.655 -Spanish (Honduras)
 267.656 -UTF-8
 267.657 -
 267.658 -OS Locale:  es_MX
 267.659 -es_MX
 267.660 -Spanish (Mexico)
 267.661 -ISO-8859-1
 267.662 -
 267.663 -OS Locale:  es_MX.utf8
 267.664 -es_MX
 267.665 -Spanish (Mexico)
 267.666 -UTF-8
 267.667 -
 267.668 -OS Locale:  es_NI
 267.669 -es_NI
 267.670 -Spanish (Nicaragua)
 267.671 -ISO-8859-1
 267.672 -
 267.673 -OS Locale:  es_NI.utf8
 267.674 -es_NI
 267.675 -Spanish (Nicaragua)
 267.676 -UTF-8
 267.677 -
 267.678 -OS Locale:  es_PA
 267.679 -es_PA
 267.680 -Spanish (Panama)
 267.681 -ISO-8859-1
 267.682 -
 267.683 -OS Locale:  es_PA.utf8
 267.684 -es_PA
 267.685 -Spanish (Panama)
 267.686 -UTF-8
 267.687 -
 267.688 -OS Locale:  es_PE
 267.689 -es_PE
 267.690 -Spanish (Peru)
 267.691 -ISO-8859-1
 267.692 -
 267.693 -OS Locale:  es_PE.utf8
 267.694 -es_PE
 267.695 -Spanish (Peru)
 267.696 -UTF-8
 267.697 -
 267.698 -OS Locale:  es_PR
 267.699 -es_PR
 267.700 -Spanish (Puerto Rico)
 267.701 -ISO-8859-1
 267.702 -
 267.703 -OS Locale:  es_PR.utf8
 267.704 -es_PR
 267.705 -Spanish (Puerto Rico)
 267.706 -UTF-8
 267.707 -
 267.708 -OS Locale:  es_PY
 267.709 -es_PY
 267.710 -Spanish (Paraguay)
 267.711 -ISO-8859-1
 267.712 -
 267.713 -OS Locale:  es_PY.utf8
 267.714 -es_PY
 267.715 -Spanish (Paraguay)
 267.716 -UTF-8
 267.717 -
 267.718 -OS Locale:  es_SV
 267.719 -es_SV
 267.720 -Spanish (El Salvador)
 267.721 -ISO-8859-1
 267.722 -
 267.723 -OS Locale:  es_SV.utf8
 267.724 -es_SV
 267.725 -Spanish (El Salvador)
 267.726 -UTF-8
 267.727 -
 267.728 -OS Locale:  es_US
 267.729 -es_US
 267.730 -Spanish (United States)
 267.731 -ISO-8859-1
 267.732 -
 267.733 -OS Locale:  es_US.utf8
 267.734 -es_US
 267.735 -Spanish (United States)
 267.736 -UTF-8
 267.737 -
 267.738 -OS Locale:  es_UY
 267.739 -es_UY
 267.740 -Spanish (Uruguay)
 267.741 -ISO-8859-1
 267.742 -
 267.743 -OS Locale:  es_UY.utf8
 267.744 -es_UY
 267.745 -Spanish (Uruguay)
 267.746 -UTF-8
 267.747 -
 267.748 -OS Locale:  es_VE
 267.749 -es_VE
 267.750 -Spanish (Venezuela)
 267.751 -ISO-8859-1
 267.752 -
 267.753 -OS Locale:  es_VE.utf8
 267.754 -es_VE
 267.755 -Spanish (Venezuela)
 267.756 -UTF-8
 267.757 -
 267.758 -OS Locale:  et_EE
 267.759 -et_EE
 267.760 -Estonian (Estonia)
 267.761 -ISO-8859-1
 267.762 -
 267.763 -OS Locale:  et_EE.iso885915
 267.764 -et_EE
 267.765 -Estonian (Estonia)
 267.766 -ISO-8859-15
 267.767 -
 267.768 -OS Locale:  et_EE.utf8
 267.769 -et_EE
 267.770 -Estonian (Estonia)
 267.771 -UTF-8
 267.772 -
 267.773 -OS Locale:  eu_ES
 267.774 -eu_ES
 267.775 -Basque (Spain)
 267.776 -ISO-8859-1
 267.777 -
 267.778 -OS Locale:  eu_ES.utf8
 267.779 -eu_ES
 267.780 -Basque (Spain)
 267.781 -UTF-8
 267.782 -
 267.783 -OS Locale:  eu_ES@euro
 267.784 -eu_ES
 267.785 -Basque (Spain)
 267.786 -ISO-8859-15
 267.787 -
 267.788 -OS Locale:  fa_IR
 267.789 -fa_IR
 267.790 -Persian (Iran)
 267.791 -UTF-8
 267.792 -
 267.793 -OS Locale:  fi_FI
 267.794 -fi_FI
 267.795 -Finnish (Finland)
 267.796 -ISO-8859-1
 267.797 -
 267.798 -OS Locale:  fi_FI.utf8
 267.799 -fi_FI
 267.800 -Finnish (Finland)
 267.801 -UTF-8
 267.802 -
 267.803 -OS Locale:  fi_FI@euro
 267.804 -fi_FI
 267.805 -Finnish (Finland)
 267.806 -ISO-8859-15
 267.807 -
 267.808 -OS Locale:  fo_FO
 267.809 -fo_FO
 267.810 -Faroese (Faroe Islands)
 267.811 -ISO-8859-1
 267.812 -
 267.813 -OS Locale:  fo_FO.utf8
 267.814 -fo_FO
 267.815 -Faroese (Faroe Islands)
 267.816 -UTF-8
 267.817 -
 267.818 -OS Locale:  fr_BE
 267.819 -fr_BE
 267.820 -French (Belgium)
 267.821 -ISO-8859-1
 267.822 -
 267.823 -OS Locale:  fr_BE.utf8
 267.824 -fr_BE
 267.825 -French (Belgium)
 267.826 -UTF-8
 267.827 -
 267.828 -OS Locale:  fr_BE@euro
 267.829 -fr_BE
 267.830 -French (Belgium)
 267.831 -ISO-8859-15
 267.832 -
 267.833 -OS Locale:  fr_CA
 267.834 -fr_CA
 267.835 -French (Canada)
 267.836 -ISO-8859-1
 267.837 -
 267.838 -OS Locale:  fr_CA.utf8
 267.839 -fr_CA
 267.840 -French (Canada)
 267.841 -UTF-8
 267.842 -
 267.843 -OS Locale:  fr_CH
 267.844 -fr_CH
 267.845 -French (Switzerland)
 267.846 -ISO-8859-1
 267.847 -
 267.848 -OS Locale:  fr_CH.utf8
 267.849 -fr_CH
 267.850 -French (Switzerland)
 267.851 -UTF-8
 267.852 -
 267.853 -OS Locale:  fr_FR
 267.854 -fr_FR
 267.855 -French (France)
 267.856 -ISO-8859-1
 267.857 -
 267.858 -OS Locale:  fr_FR.utf8
 267.859 -fr_FR
 267.860 -French (France)
 267.861 -UTF-8
 267.862 -
 267.863 -OS Locale:  fr_FR@euro
 267.864 -fr_FR
 267.865 -French (France)
 267.866 -ISO-8859-15
 267.867 -
 267.868 -OS Locale:  fr_LU
 267.869 -fr_LU
 267.870 -French (Luxembourg)
 267.871 -ISO-8859-1
 267.872 -
 267.873 -OS Locale:  fr_LU.utf8
 267.874 -fr_LU
 267.875 -French (Luxembourg)
 267.876 -UTF-8
 267.877 -
 267.878 -OS Locale:  fr_LU@euro
 267.879 -fr_LU
 267.880 -French (Luxembourg)
 267.881 -ISO-8859-15
 267.882 -
 267.883 -OS Locale:  ga_IE
 267.884 -ga_IE
 267.885 -Irish (Ireland)
 267.886 -ISO-8859-1
 267.887 -
 267.888 -OS Locale:  ga_IE.utf8
 267.889 -ga_IE
 267.890 -Irish (Ireland)
 267.891 -UTF-8
 267.892 -
 267.893 -OS Locale:  ga_IE@euro
 267.894 -ga_IE
 267.895 -Irish (Ireland)
 267.896 -ISO-8859-15
 267.897 -
 267.898 -OS Locale:  gd_GB
 267.899 -gd_GB
 267.900 -Scottish Gaelic (United Kingdom)
 267.901 -ISO-8859-15
 267.902 -
 267.903 -OS Locale:  gez_ER
 267.904 -en_ER
 267.905 -English (Eritrea)
 267.906 -UTF-8
 267.907 -
 267.908 -OS Locale:  gez_ER@abegede
 267.909 -en_ER
 267.910 -English (Eritrea)
 267.911 -UTF-8
 267.912 -
 267.913 -OS Locale:  gez_ET
 267.914 -en_ET
 267.915 -English (Ethiopia)
 267.916 -UTF-8
 267.917 -
 267.918 -OS Locale:  gez_ET@abegede
 267.919 -en_ET
 267.920 -English (Ethiopia)
 267.921 -UTF-8
 267.922 -
 267.923 -OS Locale:  gl_ES
 267.924 -gl_ES
 267.925 -Gallegan (Spain)
 267.926 -ISO-8859-1
 267.927 -
 267.928 -OS Locale:  gl_ES.utf8
 267.929 -gl_ES
 267.930 -Gallegan (Spain)
 267.931 -UTF-8
 267.932 -
 267.933 -OS Locale:  gl_ES@euro
 267.934 -gl_ES
 267.935 -Gallegan (Spain)
 267.936 -ISO-8859-15
 267.937 -
 267.938 -OS Locale:  gu_IN
 267.939 -gu_IN
 267.940 -Gujarati (India)
 267.941 -UTF-8
 267.942 -
 267.943 -OS Locale:  gv_GB
 267.944 -gv_GB
 267.945 -Manx (United Kingdom)
 267.946 -ISO-8859-1
 267.947 -
 267.948 -OS Locale:  gv_GB.utf8
 267.949 -gv_GB
 267.950 -Manx (United Kingdom)
 267.951 -UTF-8
 267.952 -
 267.953 -OS Locale:  he_IL
 267.954 -iw_IL
 267.955 -Hebrew (Israel)
 267.956 -ISO-8859-8
 267.957 -
 267.958 -OS Locale:  he_IL.utf8
 267.959 -iw_IL
 267.960 -Hebrew (Israel)
 267.961 -UTF-8
 267.962 -
 267.963 -OS Locale:  hi_IN
 267.964 -hi_IN
 267.965 -Hindi (India)
 267.966 -UTF-8
 267.967 -
 267.968 -OS Locale:  hr_HR
 267.969 -hr_HR
 267.970 -Croatian (Croatia)
 267.971 -ISO-8859-2
 267.972 -
 267.973 -OS Locale:  hr_HR.utf8
 267.974 -hr_HR
 267.975 -Croatian (Croatia)
 267.976 -UTF-8
 267.977 -
 267.978 -OS Locale:  hu_HU
 267.979 -hu_HU
 267.980 -Hungarian (Hungary)
 267.981 -ISO-8859-2
 267.982 -
 267.983 -OS Locale:  hu_HU.utf8
 267.984 -hu_HU
 267.985 -Hungarian (Hungary)
 267.986 -UTF-8
 267.987 -
 267.988 -OS Locale:  id_ID
 267.989 -in_ID
 267.990 -Indonesian (Indonesia)
 267.991 -ISO-8859-1
 267.992 -
 267.993 -OS Locale:  id_ID.utf8
 267.994 -in_ID
 267.995 -Indonesian (Indonesia)
 267.996 -UTF-8
 267.997 -
 267.998 -OS Locale:  is_IS
 267.999 -is_IS
267.1000 -Icelandic (Iceland)
267.1001 -ISO-8859-1
267.1002 -
267.1003 -OS Locale:  is_IS.utf8
267.1004 -is_IS
267.1005 -Icelandic (Iceland)
267.1006 -UTF-8
267.1007 -
267.1008 -OS Locale:  it_CH
267.1009 -it_CH
267.1010 -Italian (Switzerland)
267.1011 -ISO-8859-1
267.1012 -
267.1013 -OS Locale:  it_CH.utf8
267.1014 -it_CH
267.1015 -Italian (Switzerland)
267.1016 -UTF-8
267.1017 -
267.1018 -OS Locale:  it_IT
267.1019 -it_IT
267.1020 -Italian (Italy)
267.1021 -ISO-8859-1
267.1022 -
267.1023 -OS Locale:  it_IT.utf8
267.1024 -it_IT
267.1025 -Italian (Italy)
267.1026 -UTF-8
267.1027 -
267.1028 -OS Locale:  it_IT@euro
267.1029 -it_IT
267.1030 -Italian (Italy)
267.1031 -ISO-8859-15
267.1032 -
267.1033 -OS Locale:  iw_IL
267.1034 -iw_IL
267.1035 -Hebrew (Israel)
267.1036 -ISO-8859-8
267.1037 -
267.1038 -OS Locale:  iw_IL.utf8
267.1039 -iw_IL
267.1040 -Hebrew (Israel)
267.1041 -UTF-8
267.1042 -
267.1043 -OS Locale:  ja_JP.eucjp
267.1044 -ja_JP
267.1045 -Japanese (Japan)
267.1046 -x-euc-jp-linux
267.1047 -
267.1048 -OS Locale:  ja_JP.utf8
267.1049 -ja_JP
267.1050 -Japanese (Japan)
267.1051 -UTF-8
267.1052 -
267.1053 -OS Locale:  ka_GE
267.1054 -ka_GE
267.1055 -Georgian (Georgia)
267.1056 -UTF-8
267.1057 -
267.1058 -OS Locale:  kk_KZ
267.1059 -kk_KZ
267.1060 -Kazakh (Kazakhstan)
267.1061 -UTF-8
267.1062 -
267.1063 -OS Locale:  kl_GL
267.1064 -kl_GL
267.1065 -Greenlandic (Greenland)
267.1066 -ISO-8859-1
267.1067 -
267.1068 -OS Locale:  kl_GL.utf8
267.1069 -kl_GL
267.1070 -Greenlandic (Greenland)
267.1071 -UTF-8
267.1072 -
267.1073 -OS Locale:  kn_IN
267.1074 -kn_IN
267.1075 -Kannada (India)
267.1076 -UTF-8
267.1077 -
267.1078 -OS Locale:  ko_KR.euckr
267.1079 -ko_KR
267.1080 -Korean (South Korea)
267.1081 -EUC-KR
267.1082 -
267.1083 -OS Locale:  ko_KR.utf8
267.1084 -ko_KR
267.1085 -Korean (South Korea)
267.1086 -UTF-8
267.1087 -
267.1088 -OS Locale:  kw_GB
267.1089 -kw_GB
267.1090 -Cornish (United Kingdom)
267.1091 -ISO-8859-1
267.1092 -
267.1093 -OS Locale:  kw_GB.utf8
267.1094 -kw_GB
267.1095 -Cornish (United Kingdom)
267.1096 -UTF-8
267.1097 -
267.1098 -OS Locale:  lg_UG
267.1099 -lg_UG
267.1100 -Ganda (Uganda)
267.1101 -UTF-8
267.1102 -
267.1103 -OS Locale:  lo_LA
267.1104 -lo_LA
267.1105 -Lao (Laos)
267.1106 -UTF-8
267.1107 -
267.1108 -OS Locale:  locale-archive
267.1109 -en_US
267.1110 -English (United States)
267.1111 -US-ASCII
267.1112 -
267.1113 -OS Locale:  lt_LT
267.1114 -lt_LT
267.1115 -Lithuanian (Lithuania)
267.1116 -ISO-8859-13
267.1117 -
267.1118 -OS Locale:  lt_LT.utf8
267.1119 -lt_LT
267.1120 -Lithuanian (Lithuania)
267.1121 -UTF-8
267.1122 -
267.1123 -OS Locale:  lv_LV
267.1124 -lv_LV
267.1125 -Latvian (Latvia)
267.1126 -ISO-8859-13
267.1127 -
267.1128 -OS Locale:  lv_LV.utf8
267.1129 -lv_LV
267.1130 -Latvian (Latvia)
267.1131 -UTF-8
267.1132 -
267.1133 -OS Locale:  mi_NZ
267.1134 -mi_NZ
267.1135 -Maori (New Zealand)
267.1136 -ISO-8859-13
267.1137 -
267.1138 -OS Locale:  mk_MK
267.1139 -mk_MK
267.1140 -Macedonian (Macedonia)
267.1141 -ISO-8859-5
267.1142 -
267.1143 -OS Locale:  mk_MK.utf8
267.1144 -mk_MK
267.1145 -Macedonian (Macedonia)
267.1146 -UTF-8
267.1147 -
267.1148 -OS Locale:  ml_IN
267.1149 -ml_IN
267.1150 -Malayalam (India)
267.1151 -UTF-8
267.1152 -
267.1153 -OS Locale:  mn_MN
267.1154 -mn_MN
267.1155 -Mongolian (Mongolia)
267.1156 -UTF-8
267.1157 -
267.1158 -OS Locale:  mr_IN
267.1159 -mr_IN
267.1160 -Marathi (India)
267.1161 -UTF-8
267.1162 -
267.1163 -OS Locale:  ms_MY
267.1164 -ms_MY
267.1165 -Malay (Malaysia)
267.1166 -ISO-8859-1
267.1167 -
267.1168 -OS Locale:  ms_MY.utf8
267.1169 -ms_MY
267.1170 -Malay (Malaysia)
267.1171 -UTF-8
267.1172 -
267.1173 -OS Locale:  mt_MT
267.1174 -mt_MT
267.1175 -Maltese (Malta)
267.1176 -ISO-8859-3
267.1177 -
267.1178 -OS Locale:  mt_MT.utf8
267.1179 -mt_MT
267.1180 -Maltese (Malta)
267.1181 -UTF-8
267.1182 -
267.1183 -OS Locale:  nb_NO
267.1184 -nb_NO
267.1185 -Norwegian Bokmål (Norway)
267.1186 -ISO-8859-1
267.1187 -
267.1188 -OS Locale:  nb_NO.utf8
267.1189 -nb_NO
267.1190 -Norwegian Bokmål (Norway)
267.1191 -UTF-8
267.1192 -
267.1193 -OS Locale:  ne_NP
267.1194 -ne_NP
267.1195 -Nepali (Nepal)
267.1196 -UTF-8
267.1197 -
267.1198 -OS Locale:  nl_BE
267.1199 -nl_BE
267.1200 -Dutch (Belgium)
267.1201 -ISO-8859-1
267.1202 -
267.1203 -OS Locale:  nl_BE.utf8
267.1204 -nl_BE
267.1205 -Dutch (Belgium)
267.1206 -UTF-8
267.1207 -
267.1208 -OS Locale:  nl_BE@euro
267.1209 -nl_BE
267.1210 -Dutch (Belgium)
267.1211 -ISO-8859-15
267.1212 -
267.1213 -OS Locale:  nl_NL
267.1214 -nl_NL
267.1215 -Dutch (Netherlands)
267.1216 -ISO-8859-1
267.1217 -
267.1218 -OS Locale:  nl_NL.utf8
267.1219 -nl_NL
267.1220 -Dutch (Netherlands)
267.1221 -UTF-8
267.1222 -
267.1223 -OS Locale:  nl_NL@euro
267.1224 -nl_NL
267.1225 -Dutch (Netherlands)
267.1226 -ISO-8859-15
267.1227 -
267.1228 -OS Locale:  nn_NO
267.1229 -nn_NO
267.1230 -Norwegian Nynorsk (Norway)
267.1231 -ISO-8859-1
267.1232 -
267.1233 -OS Locale:  nn_NO.utf8
267.1234 -nn_NO
267.1235 -Norwegian Nynorsk (Norway)
267.1236 -UTF-8
267.1237 -
267.1238 -OS Locale:  no_NO
267.1239 -no_NO
267.1240 -Norwegian (Norway)
267.1241 -ISO-8859-1
267.1242 -
267.1243 -OS Locale:  no_NO.utf8
267.1244 -no_NO
267.1245 -Norwegian (Norway)
267.1246 -UTF-8
267.1247 -
267.1248 -OS Locale:  oc_FR
267.1249 -oc_FR
267.1250 -Occitan (France)
267.1251 -ISO-8859-1
267.1252 -
267.1253 -OS Locale:  om_ET
267.1254 -om_ET
267.1255 -Oromo (Ethiopia)
267.1256 -UTF-8
267.1257 -
267.1258 -OS Locale:  om_KE
267.1259 -om_KE
267.1260 -Oromo (Kenya)
267.1261 -ISO-8859-1
267.1262 -
267.1263 -OS Locale:  pa_IN
267.1264 -pa_IN
267.1265 -Panjabi (India)
267.1266 -UTF-8
267.1267 -
267.1268 -OS Locale:  pl_PL
267.1269 -pl_PL
267.1270 -Polish (Poland)
267.1271 -ISO-8859-2
267.1272 -
267.1273 -OS Locale:  pl_PL.utf8
267.1274 -pl_PL
267.1275 -Polish (Poland)
267.1276 -UTF-8
267.1277 -
267.1278 -OS Locale:  pt_BR
267.1279 -pt_BR
267.1280 -Portuguese (Brazil)
267.1281 -ISO-8859-1
267.1282 -
267.1283 -OS Locale:  pt_BR.utf8
267.1284 -pt_BR
267.1285 -Portuguese (Brazil)
267.1286 -UTF-8
267.1287 -
267.1288 -OS Locale:  pt_PT
267.1289 -pt_PT
267.1290 -Portuguese (Portugal)
267.1291 -ISO-8859-1
267.1292 -
267.1293 -OS Locale:  pt_PT.utf8
267.1294 -pt_PT
267.1295 -Portuguese (Portugal)
267.1296 -UTF-8
267.1297 -
267.1298 -OS Locale:  pt_PT@euro
267.1299 -pt_PT
267.1300 -Portuguese (Portugal)
267.1301 -ISO-8859-15
267.1302 -
267.1303 -OS Locale:  ro_RO
267.1304 -ro_RO
267.1305 -Romanian (Romania)
267.1306 -ISO-8859-2
267.1307 -
267.1308 -OS Locale:  ro_RO.utf8
267.1309 -ro_RO
267.1310 -Romanian (Romania)
267.1311 -UTF-8
267.1312 -
267.1313 -OS Locale:  ru_RU
267.1314 -ru_RU
267.1315 -Russian (Russia)
267.1316 -ISO-8859-5
267.1317 -
267.1318 -OS Locale:  ru_RU.koi8r
267.1319 -ru_RU
267.1320 -Russian (Russia)
267.1321 -KOI8-R
267.1322 -
267.1323 -OS Locale:  ru_RU.utf8
267.1324 -ru_RU
267.1325 -Russian (Russia)
267.1326 -UTF-8
267.1327 -
267.1328 -OS Locale:  ru_UA
267.1329 -ru_UA
267.1330 -Russian (Ukraine)
267.1331 -KOI8-U
267.1332 -
267.1333 -OS Locale:  ru_UA.utf8
267.1334 -ru_UA
267.1335 -Russian (Ukraine)
267.1336 -UTF-8
267.1337 -
267.1338 -OS Locale:  se_NO
267.1339 -se_NO
267.1340 -Northern Sami (Norway)
267.1341 -UTF-8
267.1342 -
267.1343 -OS Locale:  sid_ET
267.1344 -en_ET
267.1345 -English (Ethiopia)
267.1346 -UTF-8
267.1347 -
267.1348 -OS Locale:  sk_SK
267.1349 -sk_SK
267.1350 -Slovak (Slovakia)
267.1351 -ISO-8859-2
267.1352 -
267.1353 -OS Locale:  sk_SK.utf8
267.1354 -sk_SK
267.1355 -Slovak (Slovakia)
267.1356 -UTF-8
267.1357 -
267.1358 -OS Locale:  sl_SI
267.1359 -sl_SI
267.1360 -Slovenian (Slovenia)
267.1361 -ISO-8859-2
267.1362 -
267.1363 -OS Locale:  sl_SI.utf8
267.1364 -sl_SI
267.1365 -Slovenian (Slovenia)
267.1366 -UTF-8
267.1367 -
267.1368 -OS Locale:  so_DJ
267.1369 -so_DJ
267.1370 -Somali (Djibouti)
267.1371 -ISO-8859-1
267.1372 -
267.1373 -OS Locale:  so_ET
267.1374 -so_ET
267.1375 -Somali (Ethiopia)
267.1376 -UTF-8
267.1377 -
267.1378 -OS Locale:  so_KE
267.1379 -so_KE
267.1380 -Somali (Kenya)
267.1381 -ISO-8859-1
267.1382 -
267.1383 -OS Locale:  so_SO
267.1384 -so_SO
267.1385 -Somali (Somalia)
267.1386 -ISO-8859-1
267.1387 -
267.1388 -OS Locale:  sq_AL
267.1389 -sq_AL
267.1390 -Albanian (Albania)
267.1391 -ISO-8859-1
267.1392 -
267.1393 -OS Locale:  sq_AL.utf8
267.1394 -sq_AL
267.1395 -Albanian (Albania)
267.1396 -UTF-8
267.1397 -
267.1398 -OS Locale:  st_ZA
267.1399 -st_ZA
267.1400 -Southern Sotho (South Africa)
267.1401 -ISO-8859-1
267.1402 -
267.1403 -OS Locale:  st_ZA.utf8
267.1404 -st_ZA
267.1405 -Southern Sotho (South Africa)
267.1406 -UTF-8
267.1407 -
267.1408 -OS Locale:  sv_FI
267.1409 -sv_FI
267.1410 -Swedish (Finland)
267.1411 -ISO-8859-1
267.1412 -
267.1413 -OS Locale:  sv_FI.utf8
267.1414 -sv_FI
267.1415 -Swedish (Finland)
267.1416 -UTF-8
267.1417 -
267.1418 -OS Locale:  sv_FI@euro
267.1419 -sv_FI
267.1420 -Swedish (Finland)
267.1421 -ISO-8859-15
267.1422 -
267.1423 -OS Locale:  sv_SE
267.1424 -sv_SE
267.1425 -Swedish (Sweden)
267.1426 -ISO-8859-1
267.1427 -
267.1428 -OS Locale:  sv_SE.iso885915
267.1429 -sv_SE
267.1430 -Swedish (Sweden)
267.1431 -ISO-8859-15
267.1432 -
267.1433 -OS Locale:  sv_SE.utf8
267.1434 -sv_SE
267.1435 -Swedish (Sweden)
267.1436 -UTF-8
267.1437 -
267.1438 -OS Locale:  ta_IN
267.1439 -ta_IN
267.1440 -Tamil (India)
267.1441 -UTF-8
267.1442 -
267.1443 -OS Locale:  te_IN
267.1444 -te_IN
267.1445 -Telugu (India)
267.1446 -UTF-8
267.1447 -
267.1448 -OS Locale:  tg_TJ
267.1449 -tg_TJ
267.1450 -Tajik (Tajikistan)
267.1451 -UTF-8
267.1452 -
267.1453 -OS Locale:  th_TH
267.1454 -th_TH
267.1455 -Thai (Thailand)
267.1456 -TIS-620
267.1457 -
267.1458 -OS Locale:  th_TH.utf8
267.1459 -th_TH
267.1460 -Thai (Thailand)
267.1461 -UTF-8
267.1462 -
267.1463 -OS Locale:  ti_ER
267.1464 -ti_ER
267.1465 -Tigrinya (Eritrea)
267.1466 -UTF-8
267.1467 -
267.1468 -OS Locale:  ti_ET
267.1469 -ti_ET
267.1470 -Tigrinya (Ethiopia)
267.1471 -UTF-8
267.1472 -
267.1473 -OS Locale:  tig_ER
267.1474 -en_ER
267.1475 -English (Eritrea)
267.1476 -UTF-8
267.1477 -
267.1478 -OS Locale:  tl_PH
267.1479 -tl_PH
267.1480 -Tagalog (Philippines)
267.1481 -ISO-8859-1
267.1482 -
267.1483 -OS Locale:  tr_TR
267.1484 -tr_TR
267.1485 -Turkish (Turkey)
267.1486 -ISO-8859-9
267.1487 -
267.1488 -OS Locale:  tr_TR.utf8
267.1489 -tr_TR
267.1490 -Turkish (Turkey)
267.1491 -UTF-8
267.1492 -
267.1493 -OS Locale:  tt_RU.utf8
267.1494 -tt_RU
267.1495 -Tatar (Russia)
267.1496 -UTF-8
267.1497 -
267.1498 -OS Locale:  uk_UA
267.1499 -uk_UA
267.1500 -Ukrainian (Ukraine)
267.1501 -KOI8-U
267.1502 -
267.1503 -OS Locale:  uk_UA.utf8
267.1504 -uk_UA
267.1505 -Ukrainian (Ukraine)
267.1506 -UTF-8
267.1507 -
267.1508 -OS Locale:  ur_PK
267.1509 -ur_PK
267.1510 -Urdu (Pakistan)
267.1511 -UTF-8
267.1512 -
267.1513 -OS Locale:  uz_UZ
267.1514 -uz_UZ
267.1515 -Uzbek (Uzbekistan)
267.1516 -ISO-8859-1
267.1517 -
267.1518 -OS Locale:  uz_UZ@cyrillic
267.1519 -uz_UZ
267.1520 -Uzbek (Uzbekistan)
267.1521 -UTF-8
267.1522 -
267.1523 -OS Locale:  vi_VN
267.1524 -vi_VN
267.1525 -Vietnamese (Vietnam)
267.1526 -UTF-8
267.1527 -
267.1528 -OS Locale:  vi_VN.tcvn
267.1529 -vi_VN
267.1530 -Vietnamese (Vietnam)
267.1531 -UTF-8
267.1532 -
267.1533 -OS Locale:  wa_BE
267.1534 -wa_BE
267.1535 -Walloon (Belgium)
267.1536 -ISO-8859-1
267.1537 -
267.1538 -OS Locale:  wa_BE.utf8
267.1539 -wa_BE
267.1540 -Walloon (Belgium)
267.1541 -UTF-8
267.1542 -
267.1543 -OS Locale:  wa_BE@euro
267.1544 -wa_BE
267.1545 -Walloon (Belgium)
267.1546 -ISO-8859-15
267.1547 -
267.1548 -OS Locale:  xh_ZA
267.1549 -xh_ZA
267.1550 -Xhosa (South Africa)
267.1551 -ISO-8859-1
267.1552 -
267.1553 -OS Locale:  xh_ZA.utf8
267.1554 -xh_ZA
267.1555 -Xhosa (South Africa)
267.1556 -UTF-8
267.1557 -
267.1558 -OS Locale:  yi_US
267.1559 -ji_US
267.1560 -Yiddish (United States)
267.1561 -windows-1255
267.1562 -
267.1563 -OS Locale:  zh_CN
267.1564 -zh_CN
267.1565 -Chinese (China)
267.1566 -GB2312
267.1567 -
267.1568 -OS Locale:  zh_CN.gb18030
267.1569 -zh_CN
267.1570 -Chinese (China)
267.1571 -GB18030
267.1572 -
267.1573 -OS Locale:  zh_CN.gbk
267.1574 -zh_CN
267.1575 -Chinese (China)
267.1576 -GBK
267.1577 -
267.1578 -OS Locale:  zh_CN.utf8
267.1579 -zh_CN
267.1580 -Chinese (China)
267.1581 -UTF-8
267.1582 -
267.1583 -OS Locale:  zh_HK
267.1584 -zh_HK
267.1585 -Chinese (Hong Kong)
267.1586 -Big5-HKSCS
267.1587 -
267.1588 -OS Locale:  zh_HK.utf8
267.1589 -zh_HK
267.1590 -Chinese (Hong Kong)
267.1591 -UTF-8
267.1592 -
267.1593 -OS Locale:  zh_SG
267.1594 -zh_SG
267.1595 -Chinese (Singapore)
267.1596 -GB2312
267.1597 -
267.1598 -OS Locale:  zh_SG.gbk
267.1599 -zh_SG
267.1600 -Chinese (Singapore)
267.1601 -GBK
267.1602 -
267.1603 -OS Locale:  zh_TW
267.1604 -zh_TW
267.1605 -Chinese (Taiwan)
267.1606 -Big5
267.1607 -
267.1608 -OS Locale:  zh_TW.euctw
267.1609 -zh_TW
267.1610 -Chinese (Taiwan)
267.1611 -x-EUC-TW
267.1612 -
267.1613 -OS Locale:  zh_TW.utf8
267.1614 -zh_TW
267.1615 -Chinese (Taiwan)
267.1616 -UTF-8
267.1617 -
267.1618 -OS Locale:  zu_ZA
267.1619 -zu_ZA
267.1620 -Zulu (South Africa)
267.1621 -ISO-8859-1
267.1622 -
267.1623 -OS Locale:  zu_ZA.utf8
267.1624 -zu_ZA
267.1625 -Zulu (South Africa)
267.1626 -UTF-8
   268.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   268.2 +++ b/test/java/util/Locale/data/deflocale.rhel5	Fri Sep 24 16:41:32 2010 -0700
   268.3 @@ -0,0 +1,3924 @@
   268.4 +Red Hat Enterprise Linux Server release 5.3 (Tikanga)
   268.5 +Linux localhost.localdomain 2.6.18-128.el5 #1 SMP Wed Dec 17 11:42:39 EST 2008 i686 i686 i386 GNU/Linux
   268.6 +Testing all available locales
   268.7 +
   268.8 +OS Locale:  C
   268.9 +default locale: ID: en_US, Name: English (United States)
  268.10 +display locale: ID: en_US, Name: English (United States)
  268.11 +format locale: ID: en_US, Name: English (United States)
  268.12 +default charset: US-ASCII
  268.13 +
  268.14 +OS Locale:  POSIX
  268.15 +default locale: ID: en_US, Name: English (United States)
  268.16 +display locale: ID: en_US, Name: English (United States)
  268.17 +format locale: ID: en_US, Name: English (United States)
  268.18 +default charset: US-ASCII
  268.19 +
  268.20 +OS Locale:  aa_DJ
  268.21 +default locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.22 +display locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.23 +format locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.24 +default charset: ISO-8859-1
  268.25 +
  268.26 +OS Locale:  aa_DJ.iso88591
  268.27 +default locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.28 +display locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.29 +format locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.30 +default charset: ISO-8859-1
  268.31 +
  268.32 +OS Locale:  aa_DJ.utf8
  268.33 +default locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.34 +display locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.35 +format locale: ID: aa_DJ, Name: Afar (Djibouti)
  268.36 +default charset: UTF-8
  268.37 +
  268.38 +OS Locale:  aa_ER
  268.39 +default locale: ID: aa_ER, Name: Afar (Eritrea)
  268.40 +display locale: ID: aa_ER, Name: Afar (Eritrea)
  268.41 +format locale: ID: aa_ER, Name: Afar (Eritrea)
  268.42 +default charset: UTF-8
  268.43 +
  268.44 +OS Locale:  aa_ER.utf8
  268.45 +default locale: ID: aa_ER, Name: Afar (Eritrea)
  268.46 +display locale: ID: aa_ER, Name: Afar (Eritrea)
  268.47 +format locale: ID: aa_ER, Name: Afar (Eritrea)
  268.48 +default charset: UTF-8
  268.49 +
  268.50 +OS Locale:  aa_ER.utf8@saaho
  268.51 +default locale: ID: aa_ER, Name: Afar (Eritrea)
  268.52 +display locale: ID: aa_ER, Name: Afar (Eritrea)
  268.53 +format locale: ID: aa_ER, Name: Afar (Eritrea)
  268.54 +default charset: UTF-8
  268.55 +
  268.56 +OS Locale:  aa_ER@saaho
  268.57 +default locale: ID: aa_ER, Name: Afar (Eritrea)
  268.58 +display locale: ID: aa_ER, Name: Afar (Eritrea)
  268.59 +format locale: ID: aa_ER, Name: Afar (Eritrea)
  268.60 +default charset: UTF-8
  268.61 +
  268.62 +OS Locale:  aa_ET
  268.63 +default locale: ID: aa_ET, Name: Afar (Ethiopia)
  268.64 +display locale: ID: aa_ET, Name: Afar (Ethiopia)
  268.65 +format locale: ID: aa_ET, Name: Afar (Ethiopia)
  268.66 +default charset: UTF-8
  268.67 +
  268.68 +OS Locale:  aa_ET.utf8
  268.69 +default locale: ID: aa_ET, Name: Afar (Ethiopia)
  268.70 +display locale: ID: aa_ET, Name: Afar (Ethiopia)
  268.71 +format locale: ID: aa_ET, Name: Afar (Ethiopia)
  268.72 +default charset: UTF-8
  268.73 +
  268.74 +OS Locale:  af_ZA
  268.75 +default locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.76 +display locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.77 +format locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.78 +default charset: ISO-8859-1
  268.79 +
  268.80 +OS Locale:  af_ZA.iso88591
  268.81 +default locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.82 +display locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.83 +format locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.84 +default charset: ISO-8859-1
  268.85 +
  268.86 +OS Locale:  af_ZA.utf8
  268.87 +default locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.88 +display locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.89 +format locale: ID: af_ZA, Name: Afrikaans (South Africa)
  268.90 +default charset: UTF-8
  268.91 +
  268.92 +OS Locale:  am_ET
  268.93 +default locale: ID: am_ET, Name: Amharic (Ethiopia)
  268.94 +display locale: ID: am_ET, Name: Amharic (Ethiopia)
  268.95 +format locale: ID: am_ET, Name: Amharic (Ethiopia)
  268.96 +default charset: UTF-8
  268.97 +
  268.98 +OS Locale:  am_ET.utf8
  268.99 +default locale: ID: am_ET, Name: Amharic (Ethiopia)
 268.100 +display locale: ID: am_ET, Name: Amharic (Ethiopia)
 268.101 +format locale: ID: am_ET, Name: Amharic (Ethiopia)
 268.102 +default charset: UTF-8
 268.103 +
 268.104 +OS Locale:  an_ES
 268.105 +default locale: ID: an_ES, Name: Aragonese (Spain)
 268.106 +display locale: ID: an_ES, Name: Aragonese (Spain)
 268.107 +format locale: ID: an_ES, Name: Aragonese (Spain)
 268.108 +default charset: ISO-8859-15
 268.109 +
 268.110 +OS Locale:  an_ES.iso885915
 268.111 +default locale: ID: an_ES, Name: Aragonese (Spain)
 268.112 +display locale: ID: an_ES, Name: Aragonese (Spain)
 268.113 +format locale: ID: an_ES, Name: Aragonese (Spain)
 268.114 +default charset: ISO-8859-15
 268.115 +
 268.116 +OS Locale:  an_ES.utf8
 268.117 +default locale: ID: an_ES, Name: Aragonese (Spain)
 268.118 +display locale: ID: an_ES, Name: Aragonese (Spain)
 268.119 +format locale: ID: an_ES, Name: Aragonese (Spain)
 268.120 +default charset: UTF-8
 268.121 +
 268.122 +OS Locale:  ar_AE
 268.123 +default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.124 +display locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.125 +format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.126 +default charset: ISO-8859-6
 268.127 +
 268.128 +OS Locale:  ar_AE.iso88596
 268.129 +default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.130 +display locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.131 +format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.132 +default charset: ISO-8859-6
 268.133 +
 268.134 +OS Locale:  ar_AE.utf8
 268.135 +default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.136 +display locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.137 +format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 268.138 +default charset: UTF-8
 268.139 +
 268.140 +OS Locale:  ar_BH
 268.141 +default locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.142 +display locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.143 +format locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.144 +default charset: ISO-8859-6
 268.145 +
 268.146 +OS Locale:  ar_BH.iso88596
 268.147 +default locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.148 +display locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.149 +format locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.150 +default charset: ISO-8859-6
 268.151 +
 268.152 +OS Locale:  ar_BH.utf8
 268.153 +default locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.154 +display locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.155 +format locale: ID: ar_BH, Name: Arabic (Bahrain)
 268.156 +default charset: UTF-8
 268.157 +
 268.158 +OS Locale:  ar_DZ
 268.159 +default locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.160 +display locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.161 +format locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.162 +default charset: ISO-8859-6
 268.163 +
 268.164 +OS Locale:  ar_DZ.iso88596
 268.165 +default locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.166 +display locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.167 +format locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.168 +default charset: ISO-8859-6
 268.169 +
 268.170 +OS Locale:  ar_DZ.utf8
 268.171 +default locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.172 +display locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.173 +format locale: ID: ar_DZ, Name: Arabic (Algeria)
 268.174 +default charset: UTF-8
 268.175 +
 268.176 +OS Locale:  ar_EG
 268.177 +default locale: ID: ar_EG, Name: Arabic (Egypt)
 268.178 +display locale: ID: ar_EG, Name: Arabic (Egypt)
 268.179 +format locale: ID: ar_EG, Name: Arabic (Egypt)
 268.180 +default charset: ISO-8859-6
 268.181 +
 268.182 +OS Locale:  ar_EG.iso88596
 268.183 +default locale: ID: ar_EG, Name: Arabic (Egypt)
 268.184 +display locale: ID: ar_EG, Name: Arabic (Egypt)
 268.185 +format locale: ID: ar_EG, Name: Arabic (Egypt)
 268.186 +default charset: ISO-8859-6
 268.187 +
 268.188 +OS Locale:  ar_EG.utf8
 268.189 +default locale: ID: ar_EG, Name: Arabic (Egypt)
 268.190 +display locale: ID: ar_EG, Name: Arabic (Egypt)
 268.191 +format locale: ID: ar_EG, Name: Arabic (Egypt)
 268.192 +default charset: UTF-8
 268.193 +
 268.194 +OS Locale:  ar_IN
 268.195 +default locale: ID: ar_IN, Name: Arabic (India)
 268.196 +display locale: ID: ar_IN, Name: Arabic (India)
 268.197 +format locale: ID: ar_IN, Name: Arabic (India)
 268.198 +default charset: UTF-8
 268.199 +
 268.200 +OS Locale:  ar_IN.utf8
 268.201 +default locale: ID: ar_IN, Name: Arabic (India)
 268.202 +display locale: ID: ar_IN, Name: Arabic (India)
 268.203 +format locale: ID: ar_IN, Name: Arabic (India)
 268.204 +default charset: UTF-8
 268.205 +
 268.206 +OS Locale:  ar_IQ
 268.207 +default locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.208 +display locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.209 +format locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.210 +default charset: ISO-8859-6
 268.211 +
 268.212 +OS Locale:  ar_IQ.iso88596
 268.213 +default locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.214 +display locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.215 +format locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.216 +default charset: ISO-8859-6
 268.217 +
 268.218 +OS Locale:  ar_IQ.utf8
 268.219 +default locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.220 +display locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.221 +format locale: ID: ar_IQ, Name: Arabic (Iraq)
 268.222 +default charset: UTF-8
 268.223 +
 268.224 +OS Locale:  ar_JO
 268.225 +default locale: ID: ar_JO, Name: Arabic (Jordan)
 268.226 +display locale: ID: ar_JO, Name: Arabic (Jordan)
 268.227 +format locale: ID: ar_JO, Name: Arabic (Jordan)
 268.228 +default charset: ISO-8859-6
 268.229 +
 268.230 +OS Locale:  ar_JO.iso88596
 268.231 +default locale: ID: ar_JO, Name: Arabic (Jordan)
 268.232 +display locale: ID: ar_JO, Name: Arabic (Jordan)
 268.233 +format locale: ID: ar_JO, Name: Arabic (Jordan)
 268.234 +default charset: ISO-8859-6
 268.235 +
 268.236 +OS Locale:  ar_JO.utf8
 268.237 +default locale: ID: ar_JO, Name: Arabic (Jordan)
 268.238 +display locale: ID: ar_JO, Name: Arabic (Jordan)
 268.239 +format locale: ID: ar_JO, Name: Arabic (Jordan)
 268.240 +default charset: UTF-8
 268.241 +
 268.242 +OS Locale:  ar_KW
 268.243 +default locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.244 +display locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.245 +format locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.246 +default charset: ISO-8859-6
 268.247 +
 268.248 +OS Locale:  ar_KW.iso88596
 268.249 +default locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.250 +display locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.251 +format locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.252 +default charset: ISO-8859-6
 268.253 +
 268.254 +OS Locale:  ar_KW.utf8
 268.255 +default locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.256 +display locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.257 +format locale: ID: ar_KW, Name: Arabic (Kuwait)
 268.258 +default charset: UTF-8
 268.259 +
 268.260 +OS Locale:  ar_LB
 268.261 +default locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.262 +display locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.263 +format locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.264 +default charset: ISO-8859-6
 268.265 +
 268.266 +OS Locale:  ar_LB.iso88596
 268.267 +default locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.268 +display locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.269 +format locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.270 +default charset: ISO-8859-6
 268.271 +
 268.272 +OS Locale:  ar_LB.utf8
 268.273 +default locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.274 +display locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.275 +format locale: ID: ar_LB, Name: Arabic (Lebanon)
 268.276 +default charset: UTF-8
 268.277 +
 268.278 +OS Locale:  ar_LY
 268.279 +default locale: ID: ar_LY, Name: Arabic (Libya)
 268.280 +display locale: ID: ar_LY, Name: Arabic (Libya)
 268.281 +format locale: ID: ar_LY, Name: Arabic (Libya)
 268.282 +default charset: ISO-8859-6
 268.283 +
 268.284 +OS Locale:  ar_LY.iso88596
 268.285 +default locale: ID: ar_LY, Name: Arabic (Libya)
 268.286 +display locale: ID: ar_LY, Name: Arabic (Libya)
 268.287 +format locale: ID: ar_LY, Name: Arabic (Libya)
 268.288 +default charset: ISO-8859-6
 268.289 +
 268.290 +OS Locale:  ar_LY.utf8
 268.291 +default locale: ID: ar_LY, Name: Arabic (Libya)
 268.292 +display locale: ID: ar_LY, Name: Arabic (Libya)
 268.293 +format locale: ID: ar_LY, Name: Arabic (Libya)
 268.294 +default charset: UTF-8
 268.295 +
 268.296 +OS Locale:  ar_MA
 268.297 +default locale: ID: ar_MA, Name: Arabic (Morocco)
 268.298 +display locale: ID: ar_MA, Name: Arabic (Morocco)
 268.299 +format locale: ID: ar_MA, Name: Arabic (Morocco)
 268.300 +default charset: ISO-8859-6
 268.301 +
 268.302 +OS Locale:  ar_MA.iso88596
 268.303 +default locale: ID: ar_MA, Name: Arabic (Morocco)
 268.304 +display locale: ID: ar_MA, Name: Arabic (Morocco)
 268.305 +format locale: ID: ar_MA, Name: Arabic (Morocco)
 268.306 +default charset: ISO-8859-6
 268.307 +
 268.308 +OS Locale:  ar_MA.utf8
 268.309 +default locale: ID: ar_MA, Name: Arabic (Morocco)
 268.310 +display locale: ID: ar_MA, Name: Arabic (Morocco)
 268.311 +format locale: ID: ar_MA, Name: Arabic (Morocco)
 268.312 +default charset: UTF-8
 268.313 +
 268.314 +OS Locale:  ar_OM
 268.315 +default locale: ID: ar_OM, Name: Arabic (Oman)
 268.316 +display locale: ID: ar_OM, Name: Arabic (Oman)
 268.317 +format locale: ID: ar_OM, Name: Arabic (Oman)
 268.318 +default charset: ISO-8859-6
 268.319 +
 268.320 +OS Locale:  ar_OM.iso88596
 268.321 +default locale: ID: ar_OM, Name: Arabic (Oman)
 268.322 +display locale: ID: ar_OM, Name: Arabic (Oman)
 268.323 +format locale: ID: ar_OM, Name: Arabic (Oman)
 268.324 +default charset: ISO-8859-6
 268.325 +
 268.326 +OS Locale:  ar_OM.utf8
 268.327 +default locale: ID: ar_OM, Name: Arabic (Oman)
 268.328 +display locale: ID: ar_OM, Name: Arabic (Oman)
 268.329 +format locale: ID: ar_OM, Name: Arabic (Oman)
 268.330 +default charset: UTF-8
 268.331 +
 268.332 +OS Locale:  ar_QA
 268.333 +default locale: ID: ar_QA, Name: Arabic (Qatar)
 268.334 +display locale: ID: ar_QA, Name: Arabic (Qatar)
 268.335 +format locale: ID: ar_QA, Name: Arabic (Qatar)
 268.336 +default charset: ISO-8859-6
 268.337 +
 268.338 +OS Locale:  ar_QA.iso88596
 268.339 +default locale: ID: ar_QA, Name: Arabic (Qatar)
 268.340 +display locale: ID: ar_QA, Name: Arabic (Qatar)
 268.341 +format locale: ID: ar_QA, Name: Arabic (Qatar)
 268.342 +default charset: ISO-8859-6
 268.343 +
 268.344 +OS Locale:  ar_QA.utf8
 268.345 +default locale: ID: ar_QA, Name: Arabic (Qatar)
 268.346 +display locale: ID: ar_QA, Name: Arabic (Qatar)
 268.347 +format locale: ID: ar_QA, Name: Arabic (Qatar)
 268.348 +default charset: UTF-8
 268.349 +
 268.350 +OS Locale:  ar_SA
 268.351 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.352 +display locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.353 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.354 +default charset: ISO-8859-6
 268.355 +
 268.356 +OS Locale:  ar_SA.iso88596
 268.357 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.358 +display locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.359 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.360 +default charset: ISO-8859-6
 268.361 +
 268.362 +OS Locale:  ar_SA.utf8
 268.363 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.364 +display locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.365 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 268.366 +default charset: UTF-8
 268.367 +
 268.368 +OS Locale:  ar_SD
 268.369 +default locale: ID: ar_SD, Name: Arabic (Sudan)
 268.370 +display locale: ID: ar_SD, Name: Arabic (Sudan)
 268.371 +format locale: ID: ar_SD, Name: Arabic (Sudan)
 268.372 +default charset: ISO-8859-6
 268.373 +
 268.374 +OS Locale:  ar_SD.iso88596
 268.375 +default locale: ID: ar_SD, Name: Arabic (Sudan)
 268.376 +display locale: ID: ar_SD, Name: Arabic (Sudan)
 268.377 +format locale: ID: ar_SD, Name: Arabic (Sudan)
 268.378 +default charset: ISO-8859-6
 268.379 +
 268.380 +OS Locale:  ar_SD.utf8
 268.381 +default locale: ID: ar_SD, Name: Arabic (Sudan)
 268.382 +display locale: ID: ar_SD, Name: Arabic (Sudan)
 268.383 +format locale: ID: ar_SD, Name: Arabic (Sudan)
 268.384 +default charset: UTF-8
 268.385 +
 268.386 +OS Locale:  ar_SY
 268.387 +default locale: ID: ar_SY, Name: Arabic (Syria)
 268.388 +display locale: ID: ar_SY, Name: Arabic (Syria)
 268.389 +format locale: ID: ar_SY, Name: Arabic (Syria)
 268.390 +default charset: ISO-8859-6
 268.391 +
 268.392 +OS Locale:  ar_SY.iso88596
 268.393 +default locale: ID: ar_SY, Name: Arabic (Syria)
 268.394 +display locale: ID: ar_SY, Name: Arabic (Syria)
 268.395 +format locale: ID: ar_SY, Name: Arabic (Syria)
 268.396 +default charset: ISO-8859-6
 268.397 +
 268.398 +OS Locale:  ar_SY.utf8
 268.399 +default locale: ID: ar_SY, Name: Arabic (Syria)
 268.400 +display locale: ID: ar_SY, Name: Arabic (Syria)
 268.401 +format locale: ID: ar_SY, Name: Arabic (Syria)
 268.402 +default charset: UTF-8
 268.403 +
 268.404 +OS Locale:  ar_TN
 268.405 +default locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.406 +display locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.407 +format locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.408 +default charset: ISO-8859-6
 268.409 +
 268.410 +OS Locale:  ar_TN.iso88596
 268.411 +default locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.412 +display locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.413 +format locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.414 +default charset: ISO-8859-6
 268.415 +
 268.416 +OS Locale:  ar_TN.utf8
 268.417 +default locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.418 +display locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.419 +format locale: ID: ar_TN, Name: Arabic (Tunisia)
 268.420 +default charset: UTF-8
 268.421 +
 268.422 +OS Locale:  ar_YE
 268.423 +default locale: ID: ar_YE, Name: Arabic (Yemen)
 268.424 +display locale: ID: ar_YE, Name: Arabic (Yemen)
 268.425 +format locale: ID: ar_YE, Name: Arabic (Yemen)
 268.426 +default charset: ISO-8859-6
 268.427 +
 268.428 +OS Locale:  ar_YE.iso88596
 268.429 +default locale: ID: ar_YE, Name: Arabic (Yemen)
 268.430 +display locale: ID: ar_YE, Name: Arabic (Yemen)
 268.431 +format locale: ID: ar_YE, Name: Arabic (Yemen)
 268.432 +default charset: ISO-8859-6
 268.433 +
 268.434 +OS Locale:  ar_YE.utf8
 268.435 +default locale: ID: ar_YE, Name: Arabic (Yemen)
 268.436 +display locale: ID: ar_YE, Name: Arabic (Yemen)
 268.437 +format locale: ID: ar_YE, Name: Arabic (Yemen)
 268.438 +default charset: UTF-8
 268.439 +
 268.440 +OS Locale:  as_IN.utf8
 268.441 +default locale: ID: as_IN, Name: Assamese (India)
 268.442 +display locale: ID: as_IN, Name: Assamese (India)
 268.443 +format locale: ID: as_IN, Name: Assamese (India)
 268.444 +default charset: UTF-8
 268.445 +
 268.446 +OS Locale:  az_AZ.utf8
 268.447 +default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 268.448 +display locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 268.449 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 268.450 +default charset: UTF-8
 268.451 +
 268.452 +OS Locale:  be_BY
 268.453 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 268.454 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 268.455 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 268.456 +default charset: windows-1251
 268.457 +
 268.458 +OS Locale:  be_BY.cp1251
 268.459 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 268.460 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 268.461 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 268.462 +default charset: windows-1251
 268.463 +
 268.464 +OS Locale:  be_BY.utf8
 268.465 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 268.466 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 268.467 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 268.468 +default charset: UTF-8
 268.469 +
 268.470 +OS Locale:  be_BY.utf8@latin
 268.471 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 268.472 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 268.473 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 268.474 +default charset: UTF-8
 268.475 +
 268.476 +OS Locale:  be_BY@latin
 268.477 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 268.478 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 268.479 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 268.480 +default charset: UTF-8
 268.481 +
 268.482 +OS Locale:  bg_BG
 268.483 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.484 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.485 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.486 +default charset: windows-1251
 268.487 +
 268.488 +OS Locale:  bg_BG.cp1251
 268.489 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.490 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.491 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.492 +default charset: windows-1251
 268.493 +
 268.494 +OS Locale:  bg_BG.utf8
 268.495 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.496 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.497 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 268.498 +default charset: UTF-8
 268.499 +
 268.500 +OS Locale:  bn_BD
 268.501 +default locale: ID: bn_BD, Name: Bengali (Bangladesh)
 268.502 +display locale: ID: bn_BD, Name: Bengali (Bangladesh)
 268.503 +format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 268.504 +default charset: UTF-8
 268.505 +
 268.506 +OS Locale:  bn_BD.utf8
 268.507 +default locale: ID: bn_BD, Name: Bengali (Bangladesh)
 268.508 +display locale: ID: bn_BD, Name: Bengali (Bangladesh)
 268.509 +format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 268.510 +default charset: UTF-8
 268.511 +
 268.512 +OS Locale:  bn_IN
 268.513 +default locale: ID: bn_IN, Name: Bengali (India)
 268.514 +display locale: ID: bn_IN, Name: Bengali (India)
 268.515 +format locale: ID: bn_IN, Name: Bengali (India)
 268.516 +default charset: UTF-8
 268.517 +
 268.518 +OS Locale:  bn_IN.utf8
 268.519 +default locale: ID: bn_IN, Name: Bengali (India)
 268.520 +display locale: ID: bn_IN, Name: Bengali (India)
 268.521 +format locale: ID: bn_IN, Name: Bengali (India)
 268.522 +default charset: UTF-8
 268.523 +
 268.524 +OS Locale:  bokmål
 268.525 +default locale: ID: en, Name: English
 268.526 +display locale: ID: en, Name: English
 268.527 +format locale: ID: en, Name: English
 268.528 +default charset: ISO-8859-1
 268.529 +
 268.530 +OS Locale:  bokmal
 268.531 +default locale: ID: en, Name: English
 268.532 +display locale: ID: en, Name: English
 268.533 +format locale: ID: en, Name: English
 268.534 +default charset: ISO-8859-1
 268.535 +
 268.536 +OS Locale:  br_FR
 268.537 +default locale: ID: br_FR, Name: Breton (France)
 268.538 +display locale: ID: br_FR, Name: Breton (France)
 268.539 +format locale: ID: br_FR, Name: Breton (France)
 268.540 +default charset: ISO-8859-1
 268.541 +
 268.542 +OS Locale:  br_FR.iso88591
 268.543 +default locale: ID: br_FR, Name: Breton (France)
 268.544 +display locale: ID: br_FR, Name: Breton (France)
 268.545 +format locale: ID: br_FR, Name: Breton (France)
 268.546 +default charset: ISO-8859-1
 268.547 +
 268.548 +OS Locale:  br_FR.iso885915@euro
 268.549 +default locale: ID: br_FR, Name: Breton (France)
 268.550 +display locale: ID: br_FR, Name: Breton (France)
 268.551 +format locale: ID: br_FR, Name: Breton (France)
 268.552 +default charset: ISO-8859-15
 268.553 +
 268.554 +OS Locale:  br_FR.utf8
 268.555 +default locale: ID: br_FR, Name: Breton (France)
 268.556 +display locale: ID: br_FR, Name: Breton (France)
 268.557 +format locale: ID: br_FR, Name: Breton (France)
 268.558 +default charset: UTF-8
 268.559 +
 268.560 +OS Locale:  br_FR@euro
 268.561 +default locale: ID: br_FR, Name: Breton (France)
 268.562 +display locale: ID: br_FR, Name: Breton (France)
 268.563 +format locale: ID: br_FR, Name: Breton (France)
 268.564 +default charset: ISO-8859-15
 268.565 +
 268.566 +OS Locale:  bs_BA
 268.567 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.568 +display locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.569 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.570 +default charset: ISO-8859-2
 268.571 +
 268.572 +OS Locale:  bs_BA.iso88592
 268.573 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.574 +display locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.575 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.576 +default charset: ISO-8859-2
 268.577 +
 268.578 +OS Locale:  bs_BA.utf8
 268.579 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.580 +display locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.581 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 268.582 +default charset: UTF-8
 268.583 +
 268.584 +OS Locale:  byn_ER
 268.585 +default locale: ID: en_ER, Name: English (Eritrea)
 268.586 +display locale: ID: en_ER, Name: English (Eritrea)
 268.587 +format locale: ID: en_ER, Name: English (Eritrea)
 268.588 +default charset: UTF-8
 268.589 +
 268.590 +OS Locale:  byn_ER.utf8
 268.591 +default locale: ID: en_ER, Name: English (Eritrea)
 268.592 +display locale: ID: en_ER, Name: English (Eritrea)
 268.593 +format locale: ID: en_ER, Name: English (Eritrea)
 268.594 +default charset: UTF-8
 268.595 +
 268.596 +OS Locale:  ca_AD
 268.597 +default locale: ID: ca_AD, Name: Catalan (Andorra)
 268.598 +display locale: ID: ca_AD, Name: Catalan (Andorra)
 268.599 +format locale: ID: ca_AD, Name: Catalan (Andorra)
 268.600 +default charset: ISO-8859-15
 268.601 +
 268.602 +OS Locale:  ca_AD.iso885915
 268.603 +default locale: ID: ca_AD, Name: Catalan (Andorra)
 268.604 +display locale: ID: ca_AD, Name: Catalan (Andorra)
 268.605 +format locale: ID: ca_AD, Name: Catalan (Andorra)
 268.606 +default charset: ISO-8859-15
 268.607 +
 268.608 +OS Locale:  ca_AD.utf8
 268.609 +default locale: ID: ca_AD, Name: Catalan (Andorra)
 268.610 +display locale: ID: ca_AD, Name: Catalan (Andorra)
 268.611 +format locale: ID: ca_AD, Name: Catalan (Andorra)
 268.612 +default charset: UTF-8
 268.613 +
 268.614 +OS Locale:  ca_ES
 268.615 +default locale: ID: ca_ES, Name: Catalan (Spain)
 268.616 +display locale: ID: ca_ES, Name: Catalan (Spain)
 268.617 +format locale: ID: ca_ES, Name: Catalan (Spain)
 268.618 +default charset: ISO-8859-1
 268.619 +
 268.620 +OS Locale:  ca_ES.iso88591
 268.621 +default locale: ID: ca_ES, Name: Catalan (Spain)
 268.622 +display locale: ID: ca_ES, Name: Catalan (Spain)
 268.623 +format locale: ID: ca_ES, Name: Catalan (Spain)
 268.624 +default charset: ISO-8859-1
 268.625 +
 268.626 +OS Locale:  ca_ES.iso885915@euro
 268.627 +default locale: ID: ca_ES, Name: Catalan (Spain)
 268.628 +display locale: ID: ca_ES, Name: Catalan (Spain)
 268.629 +format locale: ID: ca_ES, Name: Catalan (Spain)
 268.630 +default charset: ISO-8859-15
 268.631 +
 268.632 +OS Locale:  ca_ES.utf8
 268.633 +default locale: ID: ca_ES, Name: Catalan (Spain)
 268.634 +display locale: ID: ca_ES, Name: Catalan (Spain)
 268.635 +format locale: ID: ca_ES, Name: Catalan (Spain)
 268.636 +default charset: UTF-8
 268.637 +
 268.638 +OS Locale:  ca_ES@euro
 268.639 +default locale: ID: ca_ES, Name: Catalan (Spain)
 268.640 +display locale: ID: ca_ES, Name: Catalan (Spain)
 268.641 +format locale: ID: ca_ES, Name: Catalan (Spain)
 268.642 +default charset: ISO-8859-15
 268.643 +
 268.644 +OS Locale:  ca_FR
 268.645 +default locale: ID: ca_FR, Name: Catalan (France)
 268.646 +display locale: ID: ca_FR, Name: Catalan (France)
 268.647 +format locale: ID: ca_FR, Name: Catalan (France)
 268.648 +default charset: ISO-8859-15
 268.649 +
 268.650 +OS Locale:  ca_FR.iso885915
 268.651 +default locale: ID: ca_FR, Name: Catalan (France)
 268.652 +display locale: ID: ca_FR, Name: Catalan (France)
 268.653 +format locale: ID: ca_FR, Name: Catalan (France)
 268.654 +default charset: ISO-8859-15
 268.655 +
 268.656 +OS Locale:  ca_FR.utf8
 268.657 +default locale: ID: ca_FR, Name: Catalan (France)
 268.658 +display locale: ID: ca_FR, Name: Catalan (France)
 268.659 +format locale: ID: ca_FR, Name: Catalan (France)
 268.660 +default charset: UTF-8
 268.661 +
 268.662 +OS Locale:  ca_IT
 268.663 +default locale: ID: ca_IT, Name: Catalan (Italy)
 268.664 +display locale: ID: ca_IT, Name: Catalan (Italy)
 268.665 +format locale: ID: ca_IT, Name: Catalan (Italy)
 268.666 +default charset: ISO-8859-15
 268.667 +
 268.668 +OS Locale:  ca_IT.iso885915
 268.669 +default locale: ID: ca_IT, Name: Catalan (Italy)
 268.670 +display locale: ID: ca_IT, Name: Catalan (Italy)
 268.671 +format locale: ID: ca_IT, Name: Catalan (Italy)
 268.672 +default charset: ISO-8859-15
 268.673 +
 268.674 +OS Locale:  ca_IT.utf8
 268.675 +default locale: ID: ca_IT, Name: Catalan (Italy)
 268.676 +display locale: ID: ca_IT, Name: Catalan (Italy)
 268.677 +format locale: ID: ca_IT, Name: Catalan (Italy)
 268.678 +default charset: UTF-8
 268.679 +
 268.680 +OS Locale:  catalan
 268.681 +default locale: ID: ca_ES, Name: Catalan (Spain)
 268.682 +display locale: ID: ca_ES, Name: Catalan (Spain)
 268.683 +format locale: ID: ca_ES, Name: Catalan (Spain)
 268.684 +default charset: ISO-8859-1
 268.685 +
 268.686 +OS Locale:  croatian
 268.687 +default locale: ID: hr_HR, Name: Croatian (Croatia)
 268.688 +display locale: ID: hr_HR, Name: Croatian (Croatia)
 268.689 +format locale: ID: hr_HR, Name: Croatian (Croatia)
 268.690 +default charset: ISO-8859-2
 268.691 +
 268.692 +OS Locale:  cs_CZ
 268.693 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.694 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.695 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.696 +default charset: ISO-8859-2
 268.697 +
 268.698 +OS Locale:  cs_CZ.iso88592
 268.699 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.700 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.701 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.702 +default charset: ISO-8859-2
 268.703 +
 268.704 +OS Locale:  cs_CZ.utf8
 268.705 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.706 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.707 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.708 +default charset: UTF-8
 268.709 +
 268.710 +OS Locale:  csb_PL
 268.711 +default locale: ID: en_PL, Name: English (Poland)
 268.712 +display locale: ID: en_PL, Name: English (Poland)
 268.713 +format locale: ID: en_PL, Name: English (Poland)
 268.714 +default charset: UTF-8
 268.715 +
 268.716 +OS Locale:  csb_PL.utf8
 268.717 +default locale: ID: en_PL, Name: English (Poland)
 268.718 +display locale: ID: en_PL, Name: English (Poland)
 268.719 +format locale: ID: en_PL, Name: English (Poland)
 268.720 +default charset: UTF-8
 268.721 +
 268.722 +OS Locale:  cy_GB
 268.723 +default locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.724 +display locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.725 +format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.726 +default charset: UTF-8
 268.727 +
 268.728 +OS Locale:  cy_GB.iso885914
 268.729 +default locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.730 +display locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.731 +format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.732 +default charset: UTF-8
 268.733 +
 268.734 +OS Locale:  cy_GB.utf8
 268.735 +default locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.736 +display locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.737 +format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 268.738 +default charset: UTF-8
 268.739 +
 268.740 +OS Locale:  czech
 268.741 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.742 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.743 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 268.744 +default charset: ISO-8859-2
 268.745 +
 268.746 +OS Locale:  da_DK
 268.747 +default locale: ID: da_DK, Name: Danish (Denmark)
 268.748 +display locale: ID: da_DK, Name: Danish (Denmark)
 268.749 +format locale: ID: da_DK, Name: Danish (Denmark)
 268.750 +default charset: ISO-8859-1
 268.751 +
 268.752 +OS Locale:  da_DK.iso88591
 268.753 +default locale: ID: da_DK, Name: Danish (Denmark)
 268.754 +display locale: ID: da_DK, Name: Danish (Denmark)
 268.755 +format locale: ID: da_DK, Name: Danish (Denmark)
 268.756 +default charset: ISO-8859-1
 268.757 +
 268.758 +OS Locale:  da_DK.iso885915
 268.759 +default locale: ID: da_DK, Name: Danish (Denmark)
 268.760 +display locale: ID: da_DK, Name: Danish (Denmark)
 268.761 +format locale: ID: da_DK, Name: Danish (Denmark)
 268.762 +default charset: ISO-8859-15
 268.763 +
 268.764 +OS Locale:  da_DK.utf8
 268.765 +default locale: ID: da_DK, Name: Danish (Denmark)
 268.766 +display locale: ID: da_DK, Name: Danish (Denmark)
 268.767 +format locale: ID: da_DK, Name: Danish (Denmark)
 268.768 +default charset: UTF-8
 268.769 +
 268.770 +OS Locale:  danish
 268.771 +default locale: ID: da_DK, Name: Danish (Denmark)
 268.772 +display locale: ID: da_DK, Name: Danish (Denmark)
 268.773 +format locale: ID: da_DK, Name: Danish (Denmark)
 268.774 +default charset: ISO-8859-1
 268.775 +
 268.776 +OS Locale:  dansk
 268.777 +default locale: ID: da_DK, Name: Danish (Denmark)
 268.778 +display locale: ID: da_DK, Name: Danish (Denmark)
 268.779 +format locale: ID: da_DK, Name: Danish (Denmark)
 268.780 +default charset: ISO-8859-1
 268.781 +
 268.782 +OS Locale:  de_AT
 268.783 +default locale: ID: de_AT, Name: German (Austria)
 268.784 +display locale: ID: de_AT, Name: German (Austria)
 268.785 +format locale: ID: de_AT, Name: German (Austria)
 268.786 +default charset: ISO-8859-1
 268.787 +
 268.788 +OS Locale:  de_AT.iso88591
 268.789 +default locale: ID: de_AT, Name: German (Austria)
 268.790 +display locale: ID: de_AT, Name: German (Austria)
 268.791 +format locale: ID: de_AT, Name: German (Austria)
 268.792 +default charset: ISO-8859-1
 268.793 +
 268.794 +OS Locale:  de_AT.iso885915@euro
 268.795 +default locale: ID: de_AT, Name: German (Austria)
 268.796 +display locale: ID: de_AT, Name: German (Austria)
 268.797 +format locale: ID: de_AT, Name: German (Austria)
 268.798 +default charset: ISO-8859-15
 268.799 +
 268.800 +OS Locale:  de_AT.utf8
 268.801 +default locale: ID: de_AT, Name: German (Austria)
 268.802 +display locale: ID: de_AT, Name: German (Austria)
 268.803 +format locale: ID: de_AT, Name: German (Austria)
 268.804 +default charset: UTF-8
 268.805 +
 268.806 +OS Locale:  de_AT@euro
 268.807 +default locale: ID: de_AT, Name: German (Austria)
 268.808 +display locale: ID: de_AT, Name: German (Austria)
 268.809 +format locale: ID: de_AT, Name: German (Austria)
 268.810 +default charset: ISO-8859-15
 268.811 +
 268.812 +OS Locale:  de_BE
 268.813 +default locale: ID: de_BE, Name: German (Belgium)
 268.814 +display locale: ID: de_BE, Name: German (Belgium)
 268.815 +format locale: ID: de_BE, Name: German (Belgium)
 268.816 +default charset: ISO-8859-1
 268.817 +
 268.818 +OS Locale:  de_BE.iso88591
 268.819 +default locale: ID: de_BE, Name: German (Belgium)
 268.820 +display locale: ID: de_BE, Name: German (Belgium)
 268.821 +format locale: ID: de_BE, Name: German (Belgium)
 268.822 +default charset: ISO-8859-1
 268.823 +
 268.824 +OS Locale:  de_BE.iso885915@euro
 268.825 +default locale: ID: de_BE, Name: German (Belgium)
 268.826 +display locale: ID: de_BE, Name: German (Belgium)
 268.827 +format locale: ID: de_BE, Name: German (Belgium)
 268.828 +default charset: ISO-8859-15
 268.829 +
 268.830 +OS Locale:  de_BE.utf8
 268.831 +default locale: ID: de_BE, Name: German (Belgium)
 268.832 +display locale: ID: de_BE, Name: German (Belgium)
 268.833 +format locale: ID: de_BE, Name: German (Belgium)
 268.834 +default charset: UTF-8
 268.835 +
 268.836 +OS Locale:  de_BE@euro
 268.837 +default locale: ID: de_BE, Name: German (Belgium)
 268.838 +display locale: ID: de_BE, Name: German (Belgium)
 268.839 +format locale: ID: de_BE, Name: German (Belgium)
 268.840 +default charset: ISO-8859-15
 268.841 +
 268.842 +OS Locale:  de_CH
 268.843 +default locale: ID: de_CH, Name: German (Switzerland)
 268.844 +display locale: ID: de_CH, Name: German (Switzerland)
 268.845 +format locale: ID: de_CH, Name: German (Switzerland)
 268.846 +default charset: ISO-8859-1
 268.847 +
 268.848 +OS Locale:  de_CH.iso88591
 268.849 +default locale: ID: de_CH, Name: German (Switzerland)
 268.850 +display locale: ID: de_CH, Name: German (Switzerland)
 268.851 +format locale: ID: de_CH, Name: German (Switzerland)
 268.852 +default charset: ISO-8859-1
 268.853 +
 268.854 +OS Locale:  de_CH.utf8
 268.855 +default locale: ID: de_CH, Name: German (Switzerland)
 268.856 +display locale: ID: de_CH, Name: German (Switzerland)
 268.857 +format locale: ID: de_CH, Name: German (Switzerland)
 268.858 +default charset: UTF-8
 268.859 +
 268.860 +OS Locale:  de_DE
 268.861 +default locale: ID: de_DE, Name: German (Germany)
 268.862 +display locale: ID: de_DE, Name: German (Germany)
 268.863 +format locale: ID: de_DE, Name: German (Germany)
 268.864 +default charset: ISO-8859-1
 268.865 +
 268.866 +OS Locale:  de_DE.iso88591
 268.867 +default locale: ID: de_DE, Name: German (Germany)
 268.868 +display locale: ID: de_DE, Name: German (Germany)
 268.869 +format locale: ID: de_DE, Name: German (Germany)
 268.870 +default charset: ISO-8859-1
 268.871 +
 268.872 +OS Locale:  de_DE.iso885915@euro
 268.873 +default locale: ID: de_DE, Name: German (Germany)
 268.874 +display locale: ID: de_DE, Name: German (Germany)
 268.875 +format locale: ID: de_DE, Name: German (Germany)
 268.876 +default charset: ISO-8859-15
 268.877 +
 268.878 +OS Locale:  de_DE.utf8
 268.879 +default locale: ID: de_DE, Name: German (Germany)
 268.880 +display locale: ID: de_DE, Name: German (Germany)
 268.881 +format locale: ID: de_DE, Name: German (Germany)
 268.882 +default charset: UTF-8
 268.883 +
 268.884 +OS Locale:  de_DE@euro
 268.885 +default locale: ID: de_DE, Name: German (Germany)
 268.886 +display locale: ID: de_DE, Name: German (Germany)
 268.887 +format locale: ID: de_DE, Name: German (Germany)
 268.888 +default charset: ISO-8859-15
 268.889 +
 268.890 +OS Locale:  de_LU
 268.891 +default locale: ID: de_LU, Name: German (Luxembourg)
 268.892 +display locale: ID: de_LU, Name: German (Luxembourg)
 268.893 +format locale: ID: de_LU, Name: German (Luxembourg)
 268.894 +default charset: ISO-8859-1
 268.895 +
 268.896 +OS Locale:  de_LU.iso88591
 268.897 +default locale: ID: de_LU, Name: German (Luxembourg)
 268.898 +display locale: ID: de_LU, Name: German (Luxembourg)
 268.899 +format locale: ID: de_LU, Name: German (Luxembourg)
 268.900 +default charset: ISO-8859-1
 268.901 +
 268.902 +OS Locale:  de_LU.iso885915@euro
 268.903 +default locale: ID: de_LU, Name: German (Luxembourg)
 268.904 +display locale: ID: de_LU, Name: German (Luxembourg)
 268.905 +format locale: ID: de_LU, Name: German (Luxembourg)
 268.906 +default charset: ISO-8859-15
 268.907 +
 268.908 +OS Locale:  de_LU.utf8
 268.909 +default locale: ID: de_LU, Name: German (Luxembourg)
 268.910 +display locale: ID: de_LU, Name: German (Luxembourg)
 268.911 +format locale: ID: de_LU, Name: German (Luxembourg)
 268.912 +default charset: UTF-8
 268.913 +
 268.914 +OS Locale:  de_LU@euro
 268.915 +default locale: ID: de_LU, Name: German (Luxembourg)
 268.916 +display locale: ID: de_LU, Name: German (Luxembourg)
 268.917 +format locale: ID: de_LU, Name: German (Luxembourg)
 268.918 +default charset: ISO-8859-15
 268.919 +
 268.920 +OS Locale:  deutsch
 268.921 +default locale: ID: de_DE, Name: German (Germany)
 268.922 +display locale: ID: de_DE, Name: German (Germany)
 268.923 +format locale: ID: de_DE, Name: German (Germany)
 268.924 +default charset: ISO-8859-1
 268.925 +
 268.926 +OS Locale:  dutch
 268.927 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
 268.928 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
 268.929 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
 268.930 +default charset: ISO-8859-1
 268.931 +
 268.932 +OS Locale:  dz_BT
 268.933 +default locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 268.934 +display locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 268.935 +format locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 268.936 +default charset: UTF-8
 268.937 +
 268.938 +OS Locale:  dz_BT.utf8
 268.939 +default locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 268.940 +display locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 268.941 +format locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 268.942 +default charset: UTF-8
 268.943 +
 268.944 +OS Locale:  eesti
 268.945 +default locale: ID: en, Name: English
 268.946 +display locale: ID: en, Name: English
 268.947 +format locale: ID: en, Name: English
 268.948 +default charset: ISO-8859-1
 268.949 +
 268.950 +OS Locale:  el_CY
 268.951 +default locale: ID: el_CY, Name: Greek (Cyprus)
 268.952 +display locale: ID: el_CY, Name: Greek (Cyprus)
 268.953 +format locale: ID: el_CY, Name: Greek (Cyprus)
 268.954 +default charset: ISO-8859-7
 268.955 +
 268.956 +OS Locale:  el_CY.iso88597
 268.957 +default locale: ID: el_CY, Name: Greek (Cyprus)
 268.958 +display locale: ID: el_CY, Name: Greek (Cyprus)
 268.959 +format locale: ID: el_CY, Name: Greek (Cyprus)
 268.960 +default charset: ISO-8859-7
 268.961 +
 268.962 +OS Locale:  el_CY.utf8
 268.963 +default locale: ID: el_CY, Name: Greek (Cyprus)
 268.964 +display locale: ID: el_CY, Name: Greek (Cyprus)
 268.965 +format locale: ID: el_CY, Name: Greek (Cyprus)
 268.966 +default charset: UTF-8
 268.967 +
 268.968 +OS Locale:  el_GR
 268.969 +default locale: ID: el_GR, Name: Greek (Greece)
 268.970 +display locale: ID: el_GR, Name: Greek (Greece)
 268.971 +format locale: ID: el_GR, Name: Greek (Greece)
 268.972 +default charset: ISO-8859-7
 268.973 +
 268.974 +OS Locale:  el_GR.iso88597
 268.975 +default locale: ID: el_GR, Name: Greek (Greece)
 268.976 +display locale: ID: el_GR, Name: Greek (Greece)
 268.977 +format locale: ID: el_GR, Name: Greek (Greece)
 268.978 +default charset: ISO-8859-7
 268.979 +
 268.980 +OS Locale:  el_GR.utf8
 268.981 +default locale: ID: el_GR, Name: Greek (Greece)
 268.982 +display locale: ID: el_GR, Name: Greek (Greece)
 268.983 +format locale: ID: el_GR, Name: Greek (Greece)
 268.984 +default charset: UTF-8
 268.985 +
 268.986 +OS Locale:  en_AU
 268.987 +default locale: ID: en_AU, Name: English (Australia)
 268.988 +display locale: ID: en_AU, Name: English (Australia)
 268.989 +format locale: ID: en_AU, Name: English (Australia)
 268.990 +default charset: ISO-8859-1
 268.991 +
 268.992 +OS Locale:  en_AU.iso88591
 268.993 +default locale: ID: en_AU, Name: English (Australia)
 268.994 +display locale: ID: en_AU, Name: English (Australia)
 268.995 +format locale: ID: en_AU, Name: English (Australia)
 268.996 +default charset: ISO-8859-1
 268.997 +
 268.998 +OS Locale:  en_AU.utf8
 268.999 +default locale: ID: en_AU, Name: English (Australia)
268.1000 +display locale: ID: en_AU, Name: English (Australia)
268.1001 +format locale: ID: en_AU, Name: English (Australia)
268.1002 +default charset: UTF-8
268.1003 +
268.1004 +OS Locale:  en_BW
268.1005 +default locale: ID: en_BW, Name: English (Botswana)
268.1006 +display locale: ID: en_BW, Name: English (Botswana)
268.1007 +format locale: ID: en_BW, Name: English (Botswana)
268.1008 +default charset: ISO-8859-1
268.1009 +
268.1010 +OS Locale:  en_BW.iso88591
268.1011 +default locale: ID: en_BW, Name: English (Botswana)
268.1012 +display locale: ID: en_BW, Name: English (Botswana)
268.1013 +format locale: ID: en_BW, Name: English (Botswana)
268.1014 +default charset: ISO-8859-1
268.1015 +
268.1016 +OS Locale:  en_BW.utf8
268.1017 +default locale: ID: en_BW, Name: English (Botswana)
268.1018 +display locale: ID: en_BW, Name: English (Botswana)
268.1019 +format locale: ID: en_BW, Name: English (Botswana)
268.1020 +default charset: UTF-8
268.1021 +
268.1022 +OS Locale:  en_CA
268.1023 +default locale: ID: en_CA, Name: English (Canada)
268.1024 +display locale: ID: en_CA, Name: English (Canada)
268.1025 +format locale: ID: en_CA, Name: English (Canada)
268.1026 +default charset: ISO-8859-1
268.1027 +
268.1028 +OS Locale:  en_CA.iso88591
268.1029 +default locale: ID: en_CA, Name: English (Canada)
268.1030 +display locale: ID: en_CA, Name: English (Canada)
268.1031 +format locale: ID: en_CA, Name: English (Canada)
268.1032 +default charset: ISO-8859-1
268.1033 +
268.1034 +OS Locale:  en_CA.utf8
268.1035 +default locale: ID: en_CA, Name: English (Canada)
268.1036 +display locale: ID: en_CA, Name: English (Canada)
268.1037 +format locale: ID: en_CA, Name: English (Canada)
268.1038 +default charset: UTF-8
268.1039 +
268.1040 +OS Locale:  en_DK
268.1041 +default locale: ID: en_DK, Name: English (Denmark)
268.1042 +display locale: ID: en_DK, Name: English (Denmark)
268.1043 +format locale: ID: en_DK, Name: English (Denmark)
268.1044 +default charset: ISO-8859-1
268.1045 +
268.1046 +OS Locale:  en_DK.iso88591
268.1047 +default locale: ID: en_DK, Name: English (Denmark)
268.1048 +display locale: ID: en_DK, Name: English (Denmark)
268.1049 +format locale: ID: en_DK, Name: English (Denmark)
268.1050 +default charset: ISO-8859-1
268.1051 +
268.1052 +OS Locale:  en_DK.utf8
268.1053 +default locale: ID: en_DK, Name: English (Denmark)
268.1054 +display locale: ID: en_DK, Name: English (Denmark)
268.1055 +format locale: ID: en_DK, Name: English (Denmark)
268.1056 +default charset: UTF-8
268.1057 +
268.1058 +OS Locale:  en_GB
268.1059 +default locale: ID: en_GB, Name: English (United Kingdom)
268.1060 +display locale: ID: en_GB, Name: English (United Kingdom)
268.1061 +format locale: ID: en_GB, Name: English (United Kingdom)
268.1062 +default charset: ISO-8859-1
268.1063 +
268.1064 +OS Locale:  en_GB.iso88591
268.1065 +default locale: ID: en_GB, Name: English (United Kingdom)
268.1066 +display locale: ID: en_GB, Name: English (United Kingdom)
268.1067 +format locale: ID: en_GB, Name: English (United Kingdom)
268.1068 +default charset: ISO-8859-1
268.1069 +
268.1070 +OS Locale:  en_GB.iso885915
268.1071 +default locale: ID: en_GB, Name: English (United Kingdom)
268.1072 +display locale: ID: en_GB, Name: English (United Kingdom)
268.1073 +format locale: ID: en_GB, Name: English (United Kingdom)
268.1074 +default charset: ISO-8859-15
268.1075 +
268.1076 +OS Locale:  en_GB.utf8
268.1077 +default locale: ID: en_GB, Name: English (United Kingdom)
268.1078 +display locale: ID: en_GB, Name: English (United Kingdom)
268.1079 +format locale: ID: en_GB, Name: English (United Kingdom)
268.1080 +default charset: UTF-8
268.1081 +
268.1082 +OS Locale:  en_HK
268.1083 +default locale: ID: en_HK, Name: English (Hong Kong)
268.1084 +display locale: ID: en_HK, Name: English (Hong Kong)
268.1085 +format locale: ID: en_HK, Name: English (Hong Kong)
268.1086 +default charset: ISO-8859-1
268.1087 +
268.1088 +OS Locale:  en_HK.iso88591
268.1089 +default locale: ID: en_HK, Name: English (Hong Kong)
268.1090 +display locale: ID: en_HK, Name: English (Hong Kong)
268.1091 +format locale: ID: en_HK, Name: English (Hong Kong)
268.1092 +default charset: ISO-8859-1
268.1093 +
268.1094 +OS Locale:  en_HK.utf8
268.1095 +default locale: ID: en_HK, Name: English (Hong Kong)
268.1096 +display locale: ID: en_HK, Name: English (Hong Kong)
268.1097 +format locale: ID: en_HK, Name: English (Hong Kong)
268.1098 +default charset: UTF-8
268.1099 +
268.1100 +OS Locale:  en_IE
268.1101 +default locale: ID: en_IE, Name: English (Ireland)
268.1102 +display locale: ID: en_IE, Name: English (Ireland)
268.1103 +format locale: ID: en_IE, Name: English (Ireland)
268.1104 +default charset: ISO-8859-1
268.1105 +
268.1106 +OS Locale:  en_IE.iso88591
268.1107 +default locale: ID: en_IE, Name: English (Ireland)
268.1108 +display locale: ID: en_IE, Name: English (Ireland)
268.1109 +format locale: ID: en_IE, Name: English (Ireland)
268.1110 +default charset: ISO-8859-1
268.1111 +
268.1112 +OS Locale:  en_IE.iso885915@euro
268.1113 +default locale: ID: en_IE, Name: English (Ireland)
268.1114 +display locale: ID: en_IE, Name: English (Ireland)
268.1115 +format locale: ID: en_IE, Name: English (Ireland)
268.1116 +default charset: ISO-8859-15
268.1117 +
268.1118 +OS Locale:  en_IE.utf8
268.1119 +default locale: ID: en_IE, Name: English (Ireland)
268.1120 +display locale: ID: en_IE, Name: English (Ireland)
268.1121 +format locale: ID: en_IE, Name: English (Ireland)
268.1122 +default charset: UTF-8
268.1123 +
268.1124 +OS Locale:  en_IE@euro
268.1125 +default locale: ID: en_IE, Name: English (Ireland)
268.1126 +display locale: ID: en_IE, Name: English (Ireland)
268.1127 +format locale: ID: en_IE, Name: English (Ireland)
268.1128 +default charset: ISO-8859-15
268.1129 +
268.1130 +OS Locale:  en_IN
268.1131 +default locale: ID: en_IN, Name: English (India)
268.1132 +display locale: ID: en_IN, Name: English (India)
268.1133 +format locale: ID: en_IN, Name: English (India)
268.1134 +default charset: UTF-8
268.1135 +
268.1136 +OS Locale:  en_IN.utf8
268.1137 +default locale: ID: en_IN, Name: English (India)
268.1138 +display locale: ID: en_IN, Name: English (India)
268.1139 +format locale: ID: en_IN, Name: English (India)
268.1140 +default charset: UTF-8
268.1141 +
268.1142 +OS Locale:  en_NZ
268.1143 +default locale: ID: en_NZ, Name: English (New Zealand)
268.1144 +display locale: ID: en_NZ, Name: English (New Zealand)
268.1145 +format locale: ID: en_NZ, Name: English (New Zealand)
268.1146 +default charset: ISO-8859-1
268.1147 +
268.1148 +OS Locale:  en_NZ.iso88591
268.1149 +default locale: ID: en_NZ, Name: English (New Zealand)
268.1150 +display locale: ID: en_NZ, Name: English (New Zealand)
268.1151 +format locale: ID: en_NZ, Name: English (New Zealand)
268.1152 +default charset: ISO-8859-1
268.1153 +
268.1154 +OS Locale:  en_NZ.utf8
268.1155 +default locale: ID: en_NZ, Name: English (New Zealand)
268.1156 +display locale: ID: en_NZ, Name: English (New Zealand)
268.1157 +format locale: ID: en_NZ, Name: English (New Zealand)
268.1158 +default charset: UTF-8
268.1159 +
268.1160 +OS Locale:  en_PH
268.1161 +default locale: ID: en_PH, Name: English (Philippines)
268.1162 +display locale: ID: en_PH, Name: English (Philippines)
268.1163 +format locale: ID: en_PH, Name: English (Philippines)
268.1164 +default charset: ISO-8859-1
268.1165 +
268.1166 +OS Locale:  en_PH.iso88591
268.1167 +default locale: ID: en_PH, Name: English (Philippines)
268.1168 +display locale: ID: en_PH, Name: English (Philippines)
268.1169 +format locale: ID: en_PH, Name: English (Philippines)
268.1170 +default charset: ISO-8859-1
268.1171 +
268.1172 +OS Locale:  en_PH.utf8
268.1173 +default locale: ID: en_PH, Name: English (Philippines)
268.1174 +display locale: ID: en_PH, Name: English (Philippines)
268.1175 +format locale: ID: en_PH, Name: English (Philippines)
268.1176 +default charset: UTF-8
268.1177 +
268.1178 +OS Locale:  en_SG
268.1179 +default locale: ID: en_SG, Name: English (Singapore)
268.1180 +display locale: ID: en_SG, Name: English (Singapore)
268.1181 +format locale: ID: en_SG, Name: English (Singapore)
268.1182 +default charset: ISO-8859-1
268.1183 +
268.1184 +OS Locale:  en_SG.iso88591
268.1185 +default locale: ID: en_SG, Name: English (Singapore)
268.1186 +display locale: ID: en_SG, Name: English (Singapore)
268.1187 +format locale: ID: en_SG, Name: English (Singapore)
268.1188 +default charset: ISO-8859-1
268.1189 +
268.1190 +OS Locale:  en_SG.utf8
268.1191 +default locale: ID: en_SG, Name: English (Singapore)
268.1192 +display locale: ID: en_SG, Name: English (Singapore)
268.1193 +format locale: ID: en_SG, Name: English (Singapore)
268.1194 +default charset: UTF-8
268.1195 +
268.1196 +OS Locale:  en_US
268.1197 +default locale: ID: en_US, Name: English (United States)
268.1198 +display locale: ID: en_US, Name: English (United States)
268.1199 +format locale: ID: en_US, Name: English (United States)
268.1200 +default charset: ISO-8859-1
268.1201 +
268.1202 +OS Locale:  en_US.iso88591
268.1203 +default locale: ID: en_US, Name: English (United States)
268.1204 +display locale: ID: en_US, Name: English (United States)
268.1205 +format locale: ID: en_US, Name: English (United States)
268.1206 +default charset: ISO-8859-1
268.1207 +
268.1208 +OS Locale:  en_US.iso885915
268.1209 +default locale: ID: en_US, Name: English (United States)
268.1210 +display locale: ID: en_US, Name: English (United States)
268.1211 +format locale: ID: en_US, Name: English (United States)
268.1212 +default charset: ISO-8859-15
268.1213 +
268.1214 +OS Locale:  en_US.utf8
268.1215 +default locale: ID: en_US, Name: English (United States)
268.1216 +display locale: ID: en_US, Name: English (United States)
268.1217 +format locale: ID: en_US, Name: English (United States)
268.1218 +default charset: UTF-8
268.1219 +
268.1220 +OS Locale:  en_ZA
268.1221 +default locale: ID: en_ZA, Name: English (South Africa)
268.1222 +display locale: ID: en_ZA, Name: English (South Africa)
268.1223 +format locale: ID: en_ZA, Name: English (South Africa)
268.1224 +default charset: ISO-8859-1
268.1225 +
268.1226 +OS Locale:  en_ZA.iso88591
268.1227 +default locale: ID: en_ZA, Name: English (South Africa)
268.1228 +display locale: ID: en_ZA, Name: English (South Africa)
268.1229 +format locale: ID: en_ZA, Name: English (South Africa)
268.1230 +default charset: ISO-8859-1
268.1231 +
268.1232 +OS Locale:  en_ZA.utf8
268.1233 +default locale: ID: en_ZA, Name: English (South Africa)
268.1234 +display locale: ID: en_ZA, Name: English (South Africa)
268.1235 +format locale: ID: en_ZA, Name: English (South Africa)
268.1236 +default charset: UTF-8
268.1237 +
268.1238 +OS Locale:  en_ZW
268.1239 +default locale: ID: en_ZW, Name: English (Zimbabwe)
268.1240 +display locale: ID: en_ZW, Name: English (Zimbabwe)
268.1241 +format locale: ID: en_ZW, Name: English (Zimbabwe)
268.1242 +default charset: ISO-8859-1
268.1243 +
268.1244 +OS Locale:  en_ZW.iso88591
268.1245 +default locale: ID: en_ZW, Name: English (Zimbabwe)
268.1246 +display locale: ID: en_ZW, Name: English (Zimbabwe)
268.1247 +format locale: ID: en_ZW, Name: English (Zimbabwe)
268.1248 +default charset: ISO-8859-1
268.1249 +
268.1250 +OS Locale:  en_ZW.utf8
268.1251 +default locale: ID: en_ZW, Name: English (Zimbabwe)
268.1252 +display locale: ID: en_ZW, Name: English (Zimbabwe)
268.1253 +format locale: ID: en_ZW, Name: English (Zimbabwe)
268.1254 +default charset: UTF-8
268.1255 +
268.1256 +OS Locale:  es_AR
268.1257 +default locale: ID: es_AR, Name: Spanish (Argentina)
268.1258 +display locale: ID: es_AR, Name: Spanish (Argentina)
268.1259 +format locale: ID: es_AR, Name: Spanish (Argentina)
268.1260 +default charset: ISO-8859-1
268.1261 +
268.1262 +OS Locale:  es_AR.iso88591
268.1263 +default locale: ID: es_AR, Name: Spanish (Argentina)
268.1264 +display locale: ID: es_AR, Name: Spanish (Argentina)
268.1265 +format locale: ID: es_AR, Name: Spanish (Argentina)
268.1266 +default charset: ISO-8859-1
268.1267 +
268.1268 +OS Locale:  es_AR.utf8
268.1269 +default locale: ID: es_AR, Name: Spanish (Argentina)
268.1270 +display locale: ID: es_AR, Name: Spanish (Argentina)
268.1271 +format locale: ID: es_AR, Name: Spanish (Argentina)
268.1272 +default charset: UTF-8
268.1273 +
268.1274 +OS Locale:  es_BO
268.1275 +default locale: ID: es_BO, Name: Spanish (Bolivia)
268.1276 +display locale: ID: es_BO, Name: Spanish (Bolivia)
268.1277 +format locale: ID: es_BO, Name: Spanish (Bolivia)
268.1278 +default charset: ISO-8859-1
268.1279 +
268.1280 +OS Locale:  es_BO.iso88591
268.1281 +default locale: ID: es_BO, Name: Spanish (Bolivia)
268.1282 +display locale: ID: es_BO, Name: Spanish (Bolivia)
268.1283 +format locale: ID: es_BO, Name: Spanish (Bolivia)
268.1284 +default charset: ISO-8859-1
268.1285 +
268.1286 +OS Locale:  es_BO.utf8
268.1287 +default locale: ID: es_BO, Name: Spanish (Bolivia)
268.1288 +display locale: ID: es_BO, Name: Spanish (Bolivia)
268.1289 +format locale: ID: es_BO, Name: Spanish (Bolivia)
268.1290 +default charset: UTF-8
268.1291 +
268.1292 +OS Locale:  es_CL
268.1293 +default locale: ID: es_CL, Name: Spanish (Chile)
268.1294 +display locale: ID: es_CL, Name: Spanish (Chile)
268.1295 +format locale: ID: es_CL, Name: Spanish (Chile)
268.1296 +default charset: ISO-8859-1
268.1297 +
268.1298 +OS Locale:  es_CL.iso88591
268.1299 +default locale: ID: es_CL, Name: Spanish (Chile)
268.1300 +display locale: ID: es_CL, Name: Spanish (Chile)
268.1301 +format locale: ID: es_CL, Name: Spanish (Chile)
268.1302 +default charset: ISO-8859-1
268.1303 +
268.1304 +OS Locale:  es_CL.utf8
268.1305 +default locale: ID: es_CL, Name: Spanish (Chile)
268.1306 +display locale: ID: es_CL, Name: Spanish (Chile)
268.1307 +format locale: ID: es_CL, Name: Spanish (Chile)
268.1308 +default charset: UTF-8
268.1309 +
268.1310 +OS Locale:  es_CO
268.1311 +default locale: ID: es_CO, Name: Spanish (Colombia)
268.1312 +display locale: ID: es_CO, Name: Spanish (Colombia)
268.1313 +format locale: ID: es_CO, Name: Spanish (Colombia)
268.1314 +default charset: ISO-8859-1
268.1315 +
268.1316 +OS Locale:  es_CO.iso88591
268.1317 +default locale: ID: es_CO, Name: Spanish (Colombia)
268.1318 +display locale: ID: es_CO, Name: Spanish (Colombia)
268.1319 +format locale: ID: es_CO, Name: Spanish (Colombia)
268.1320 +default charset: ISO-8859-1
268.1321 +
268.1322 +OS Locale:  es_CO.utf8
268.1323 +default locale: ID: es_CO, Name: Spanish (Colombia)
268.1324 +display locale: ID: es_CO, Name: Spanish (Colombia)
268.1325 +format locale: ID: es_CO, Name: Spanish (Colombia)
268.1326 +default charset: UTF-8
268.1327 +
268.1328 +OS Locale:  es_CR
268.1329 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1330 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1331 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1332 +default charset: ISO-8859-1
268.1333 +
268.1334 +OS Locale:  es_CR.iso88591
268.1335 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1336 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1337 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1338 +default charset: ISO-8859-1
268.1339 +
268.1340 +OS Locale:  es_CR.utf8
268.1341 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1342 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1343 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
268.1344 +default charset: UTF-8
268.1345 +
268.1346 +OS Locale:  es_DO
268.1347 +default locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1348 +display locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1349 +format locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1350 +default charset: ISO-8859-1
268.1351 +
268.1352 +OS Locale:  es_DO.iso88591
268.1353 +default locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1354 +display locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1355 +format locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1356 +default charset: ISO-8859-1
268.1357 +
268.1358 +OS Locale:  es_DO.utf8
268.1359 +default locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1360 +display locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1361 +format locale: ID: es_DO, Name: Spanish (Dominican Republic)
268.1362 +default charset: UTF-8
268.1363 +
268.1364 +OS Locale:  es_EC
268.1365 +default locale: ID: es_EC, Name: Spanish (Ecuador)
268.1366 +display locale: ID: es_EC, Name: Spanish (Ecuador)
268.1367 +format locale: ID: es_EC, Name: Spanish (Ecuador)
268.1368 +default charset: ISO-8859-1
268.1369 +
268.1370 +OS Locale:  es_EC.iso88591
268.1371 +default locale: ID: es_EC, Name: Spanish (Ecuador)
268.1372 +display locale: ID: es_EC, Name: Spanish (Ecuador)
268.1373 +format locale: ID: es_EC, Name: Spanish (Ecuador)
268.1374 +default charset: ISO-8859-1
268.1375 +
268.1376 +OS Locale:  es_EC.utf8
268.1377 +default locale: ID: es_EC, Name: Spanish (Ecuador)
268.1378 +display locale: ID: es_EC, Name: Spanish (Ecuador)
268.1379 +format locale: ID: es_EC, Name: Spanish (Ecuador)
268.1380 +default charset: UTF-8
268.1381 +
268.1382 +OS Locale:  es_ES
268.1383 +default locale: ID: es_ES, Name: Spanish (Spain)
268.1384 +display locale: ID: es_ES, Name: Spanish (Spain)
268.1385 +format locale: ID: es_ES, Name: Spanish (Spain)
268.1386 +default charset: ISO-8859-1
268.1387 +
268.1388 +OS Locale:  es_ES.iso88591
268.1389 +default locale: ID: es_ES, Name: Spanish (Spain)
268.1390 +display locale: ID: es_ES, Name: Spanish (Spain)
268.1391 +format locale: ID: es_ES, Name: Spanish (Spain)
268.1392 +default charset: ISO-8859-1
268.1393 +
268.1394 +OS Locale:  es_ES.iso885915@euro
268.1395 +default locale: ID: es_ES, Name: Spanish (Spain)
268.1396 +display locale: ID: es_ES, Name: Spanish (Spain)
268.1397 +format locale: ID: es_ES, Name: Spanish (Spain)
268.1398 +default charset: ISO-8859-15
268.1399 +
268.1400 +OS Locale:  es_ES.utf8
268.1401 +default locale: ID: es_ES, Name: Spanish (Spain)
268.1402 +display locale: ID: es_ES, Name: Spanish (Spain)
268.1403 +format locale: ID: es_ES, Name: Spanish (Spain)
268.1404 +default charset: UTF-8
268.1405 +
268.1406 +OS Locale:  es_ES@euro
268.1407 +default locale: ID: es_ES, Name: Spanish (Spain)
268.1408 +display locale: ID: es_ES, Name: Spanish (Spain)
268.1409 +format locale: ID: es_ES, Name: Spanish (Spain)
268.1410 +default charset: ISO-8859-15
268.1411 +
268.1412 +OS Locale:  es_GT
268.1413 +default locale: ID: es_GT, Name: Spanish (Guatemala)
268.1414 +display locale: ID: es_GT, Name: Spanish (Guatemala)
268.1415 +format locale: ID: es_GT, Name: Spanish (Guatemala)
268.1416 +default charset: ISO-8859-1
268.1417 +
268.1418 +OS Locale:  es_GT.iso88591
268.1419 +default locale: ID: es_GT, Name: Spanish (Guatemala)
268.1420 +display locale: ID: es_GT, Name: Spanish (Guatemala)
268.1421 +format locale: ID: es_GT, Name: Spanish (Guatemala)
268.1422 +default charset: ISO-8859-1
268.1423 +
268.1424 +OS Locale:  es_GT.utf8
268.1425 +default locale: ID: es_GT, Name: Spanish (Guatemala)
268.1426 +display locale: ID: es_GT, Name: Spanish (Guatemala)
268.1427 +format locale: ID: es_GT, Name: Spanish (Guatemala)
268.1428 +default charset: UTF-8
268.1429 +
268.1430 +OS Locale:  es_HN
268.1431 +default locale: ID: es_HN, Name: Spanish (Honduras)
268.1432 +display locale: ID: es_HN, Name: Spanish (Honduras)
268.1433 +format locale: ID: es_HN, Name: Spanish (Honduras)
268.1434 +default charset: ISO-8859-1
268.1435 +
268.1436 +OS Locale:  es_HN.iso88591
268.1437 +default locale: ID: es_HN, Name: Spanish (Honduras)
268.1438 +display locale: ID: es_HN, Name: Spanish (Honduras)
268.1439 +format locale: ID: es_HN, Name: Spanish (Honduras)
268.1440 +default charset: ISO-8859-1
268.1441 +
268.1442 +OS Locale:  es_HN.utf8
268.1443 +default locale: ID: es_HN, Name: Spanish (Honduras)
268.1444 +display locale: ID: es_HN, Name: Spanish (Honduras)
268.1445 +format locale: ID: es_HN, Name: Spanish (Honduras)
268.1446 +default charset: UTF-8
268.1447 +
268.1448 +OS Locale:  es_MX
268.1449 +default locale: ID: es_MX, Name: Spanish (Mexico)
268.1450 +display locale: ID: es_MX, Name: Spanish (Mexico)
268.1451 +format locale: ID: es_MX, Name: Spanish (Mexico)
268.1452 +default charset: ISO-8859-1
268.1453 +
268.1454 +OS Locale:  es_MX.iso88591
268.1455 +default locale: ID: es_MX, Name: Spanish (Mexico)
268.1456 +display locale: ID: es_MX, Name: Spanish (Mexico)
268.1457 +format locale: ID: es_MX, Name: Spanish (Mexico)
268.1458 +default charset: ISO-8859-1
268.1459 +
268.1460 +OS Locale:  es_MX.utf8
268.1461 +default locale: ID: es_MX, Name: Spanish (Mexico)
268.1462 +display locale: ID: es_MX, Name: Spanish (Mexico)
268.1463 +format locale: ID: es_MX, Name: Spanish (Mexico)
268.1464 +default charset: UTF-8
268.1465 +
268.1466 +OS Locale:  es_NI
268.1467 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1468 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1469 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1470 +default charset: ISO-8859-1
268.1471 +
268.1472 +OS Locale:  es_NI.iso88591
268.1473 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1474 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1475 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1476 +default charset: ISO-8859-1
268.1477 +
268.1478 +OS Locale:  es_NI.utf8
268.1479 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1480 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1481 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
268.1482 +default charset: UTF-8
268.1483 +
268.1484 +OS Locale:  es_PA
268.1485 +default locale: ID: es_PA, Name: Spanish (Panama)
268.1486 +display locale: ID: es_PA, Name: Spanish (Panama)
268.1487 +format locale: ID: es_PA, Name: Spanish (Panama)
268.1488 +default charset: ISO-8859-1
268.1489 +
268.1490 +OS Locale:  es_PA.iso88591
268.1491 +default locale: ID: es_PA, Name: Spanish (Panama)
268.1492 +display locale: ID: es_PA, Name: Spanish (Panama)
268.1493 +format locale: ID: es_PA, Name: Spanish (Panama)
268.1494 +default charset: ISO-8859-1
268.1495 +
268.1496 +OS Locale:  es_PA.utf8
268.1497 +default locale: ID: es_PA, Name: Spanish (Panama)
268.1498 +display locale: ID: es_PA, Name: Spanish (Panama)
268.1499 +format locale: ID: es_PA, Name: Spanish (Panama)
268.1500 +default charset: UTF-8
268.1501 +
268.1502 +OS Locale:  es_PE
268.1503 +default locale: ID: es_PE, Name: Spanish (Peru)
268.1504 +display locale: ID: es_PE, Name: Spanish (Peru)
268.1505 +format locale: ID: es_PE, Name: Spanish (Peru)
268.1506 +default charset: ISO-8859-1
268.1507 +
268.1508 +OS Locale:  es_PE.iso88591
268.1509 +default locale: ID: es_PE, Name: Spanish (Peru)
268.1510 +display locale: ID: es_PE, Name: Spanish (Peru)
268.1511 +format locale: ID: es_PE, Name: Spanish (Peru)
268.1512 +default charset: ISO-8859-1
268.1513 +
268.1514 +OS Locale:  es_PE.utf8
268.1515 +default locale: ID: es_PE, Name: Spanish (Peru)
268.1516 +display locale: ID: es_PE, Name: Spanish (Peru)
268.1517 +format locale: ID: es_PE, Name: Spanish (Peru)
268.1518 +default charset: UTF-8
268.1519 +
268.1520 +OS Locale:  es_PR
268.1521 +default locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1522 +display locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1523 +format locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1524 +default charset: ISO-8859-1
268.1525 +
268.1526 +OS Locale:  es_PR.iso88591
268.1527 +default locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1528 +display locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1529 +format locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1530 +default charset: ISO-8859-1
268.1531 +
268.1532 +OS Locale:  es_PR.utf8
268.1533 +default locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1534 +display locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1535 +format locale: ID: es_PR, Name: Spanish (Puerto Rico)
268.1536 +default charset: UTF-8
268.1537 +
268.1538 +OS Locale:  es_PY
268.1539 +default locale: ID: es_PY, Name: Spanish (Paraguay)
268.1540 +display locale: ID: es_PY, Name: Spanish (Paraguay)
268.1541 +format locale: ID: es_PY, Name: Spanish (Paraguay)
268.1542 +default charset: ISO-8859-1
268.1543 +
268.1544 +OS Locale:  es_PY.iso88591
268.1545 +default locale: ID: es_PY, Name: Spanish (Paraguay)
268.1546 +display locale: ID: es_PY, Name: Spanish (Paraguay)
268.1547 +format locale: ID: es_PY, Name: Spanish (Paraguay)
268.1548 +default charset: ISO-8859-1
268.1549 +
268.1550 +OS Locale:  es_PY.utf8
268.1551 +default locale: ID: es_PY, Name: Spanish (Paraguay)
268.1552 +display locale: ID: es_PY, Name: Spanish (Paraguay)
268.1553 +format locale: ID: es_PY, Name: Spanish (Paraguay)
268.1554 +default charset: UTF-8
268.1555 +
268.1556 +OS Locale:  es_SV
268.1557 +default locale: ID: es_SV, Name: Spanish (El Salvador)
268.1558 +display locale: ID: es_SV, Name: Spanish (El Salvador)
268.1559 +format locale: ID: es_SV, Name: Spanish (El Salvador)
268.1560 +default charset: ISO-8859-1
268.1561 +
268.1562 +OS Locale:  es_SV.iso88591
268.1563 +default locale: ID: es_SV, Name: Spanish (El Salvador)
268.1564 +display locale: ID: es_SV, Name: Spanish (El Salvador)
268.1565 +format locale: ID: es_SV, Name: Spanish (El Salvador)
268.1566 +default charset: ISO-8859-1
268.1567 +
268.1568 +OS Locale:  es_SV.utf8
268.1569 +default locale: ID: es_SV, Name: Spanish (El Salvador)
268.1570 +display locale: ID: es_SV, Name: Spanish (El Salvador)
268.1571 +format locale: ID: es_SV, Name: Spanish (El Salvador)
268.1572 +default charset: UTF-8
268.1573 +
268.1574 +OS Locale:  es_US
268.1575 +default locale: ID: es_US, Name: Spanish (United States)
268.1576 +display locale: ID: es_US, Name: Spanish (United States)
268.1577 +format locale: ID: es_US, Name: Spanish (United States)
268.1578 +default charset: ISO-8859-1
268.1579 +
268.1580 +OS Locale:  es_US.iso88591
268.1581 +default locale: ID: es_US, Name: Spanish (United States)
268.1582 +display locale: ID: es_US, Name: Spanish (United States)
268.1583 +format locale: ID: es_US, Name: Spanish (United States)
268.1584 +default charset: ISO-8859-1
268.1585 +
268.1586 +OS Locale:  es_US.utf8
268.1587 +default locale: ID: es_US, Name: Spanish (United States)
268.1588 +display locale: ID: es_US, Name: Spanish (United States)
268.1589 +format locale: ID: es_US, Name: Spanish (United States)
268.1590 +default charset: UTF-8
268.1591 +
268.1592 +OS Locale:  es_UY
268.1593 +default locale: ID: es_UY, Name: Spanish (Uruguay)
268.1594 +display locale: ID: es_UY, Name: Spanish (Uruguay)
268.1595 +format locale: ID: es_UY, Name: Spanish (Uruguay)
268.1596 +default charset: ISO-8859-1
268.1597 +
268.1598 +OS Locale:  es_UY.iso88591
268.1599 +default locale: ID: es_UY, Name: Spanish (Uruguay)
268.1600 +display locale: ID: es_UY, Name: Spanish (Uruguay)
268.1601 +format locale: ID: es_UY, Name: Spanish (Uruguay)
268.1602 +default charset: ISO-8859-1
268.1603 +
268.1604 +OS Locale:  es_UY.utf8
268.1605 +default locale: ID: es_UY, Name: Spanish (Uruguay)
268.1606 +display locale: ID: es_UY, Name: Spanish (Uruguay)
268.1607 +format locale: ID: es_UY, Name: Spanish (Uruguay)
268.1608 +default charset: UTF-8
268.1609 +
268.1610 +OS Locale:  es_VE
268.1611 +default locale: ID: es_VE, Name: Spanish (Venezuela)
268.1612 +display locale: ID: es_VE, Name: Spanish (Venezuela)
268.1613 +format locale: ID: es_VE, Name: Spanish (Venezuela)
268.1614 +default charset: ISO-8859-1
268.1615 +
268.1616 +OS Locale:  es_VE.iso88591
268.1617 +default locale: ID: es_VE, Name: Spanish (Venezuela)
268.1618 +display locale: ID: es_VE, Name: Spanish (Venezuela)
268.1619 +format locale: ID: es_VE, Name: Spanish (Venezuela)
268.1620 +default charset: ISO-8859-1
268.1621 +
268.1622 +OS Locale:  es_VE.utf8
268.1623 +default locale: ID: es_VE, Name: Spanish (Venezuela)
268.1624 +display locale: ID: es_VE, Name: Spanish (Venezuela)
268.1625 +format locale: ID: es_VE, Name: Spanish (Venezuela)
268.1626 +default charset: UTF-8
268.1627 +
268.1628 +OS Locale:  estonian
268.1629 +default locale: ID: en, Name: English
268.1630 +display locale: ID: en, Name: English
268.1631 +format locale: ID: en, Name: English
268.1632 +default charset: ISO-8859-1
268.1633 +
268.1634 +OS Locale:  et_EE
268.1635 +default locale: ID: et_EE, Name: Estonian (Estonia)
268.1636 +display locale: ID: et_EE, Name: Estonian (Estonia)
268.1637 +format locale: ID: et_EE, Name: Estonian (Estonia)
268.1638 +default charset: ISO-8859-1
268.1639 +
268.1640 +OS Locale:  et_EE.iso88591
268.1641 +default locale: ID: et_EE, Name: Estonian (Estonia)
268.1642 +display locale: ID: et_EE, Name: Estonian (Estonia)
268.1643 +format locale: ID: et_EE, Name: Estonian (Estonia)
268.1644 +default charset: ISO-8859-1
268.1645 +
268.1646 +OS Locale:  et_EE.iso885915
268.1647 +default locale: ID: et_EE, Name: Estonian (Estonia)
268.1648 +display locale: ID: et_EE, Name: Estonian (Estonia)
268.1649 +format locale: ID: et_EE, Name: Estonian (Estonia)
268.1650 +default charset: ISO-8859-15
268.1651 +
268.1652 +OS Locale:  et_EE.utf8
268.1653 +default locale: ID: et_EE, Name: Estonian (Estonia)
268.1654 +display locale: ID: et_EE, Name: Estonian (Estonia)
268.1655 +format locale: ID: et_EE, Name: Estonian (Estonia)
268.1656 +default charset: UTF-8
268.1657 +
268.1658 +OS Locale:  eu_ES
268.1659 +default locale: ID: eu_ES, Name: Basque (Spain)
268.1660 +display locale: ID: eu_ES, Name: Basque (Spain)
268.1661 +format locale: ID: eu_ES, Name: Basque (Spain)
268.1662 +default charset: ISO-8859-1
268.1663 +
268.1664 +OS Locale:  eu_ES.iso88591
268.1665 +default locale: ID: eu_ES, Name: Basque (Spain)
268.1666 +display locale: ID: eu_ES, Name: Basque (Spain)
268.1667 +format locale: ID: eu_ES, Name: Basque (Spain)
268.1668 +default charset: ISO-8859-1
268.1669 +
268.1670 +OS Locale:  eu_ES.iso885915@euro
268.1671 +default locale: ID: eu_ES, Name: Basque (Spain)
268.1672 +display locale: ID: eu_ES, Name: Basque (Spain)
268.1673 +format locale: ID: eu_ES, Name: Basque (Spain)
268.1674 +default charset: ISO-8859-15
268.1675 +
268.1676 +OS Locale:  eu_ES.utf8
268.1677 +default locale: ID: eu_ES, Name: Basque (Spain)
268.1678 +display locale: ID: eu_ES, Name: Basque (Spain)
268.1679 +format locale: ID: eu_ES, Name: Basque (Spain)
268.1680 +default charset: UTF-8
268.1681 +
268.1682 +OS Locale:  eu_ES@euro
268.1683 +default locale: ID: eu_ES, Name: Basque (Spain)
268.1684 +display locale: ID: eu_ES, Name: Basque (Spain)
268.1685 +format locale: ID: eu_ES, Name: Basque (Spain)
268.1686 +default charset: ISO-8859-15
268.1687 +
268.1688 +OS Locale:  fa_IR
268.1689 +default locale: ID: fa_IR, Name: Persian (Iran)
268.1690 +display locale: ID: fa_IR, Name: Persian (Iran)
268.1691 +format locale: ID: fa_IR, Name: Persian (Iran)
268.1692 +default charset: UTF-8
268.1693 +
268.1694 +OS Locale:  fa_IR.utf8
268.1695 +default locale: ID: fa_IR, Name: Persian (Iran)
268.1696 +display locale: ID: fa_IR, Name: Persian (Iran)
268.1697 +format locale: ID: fa_IR, Name: Persian (Iran)
268.1698 +default charset: UTF-8
268.1699 +
268.1700 +OS Locale:  fi_FI
268.1701 +default locale: ID: fi_FI, Name: Finnish (Finland)
268.1702 +display locale: ID: fi_FI, Name: Finnish (Finland)
268.1703 +format locale: ID: fi_FI, Name: Finnish (Finland)
268.1704 +default charset: ISO-8859-1
268.1705 +
268.1706 +OS Locale:  fi_FI.iso88591
268.1707 +default locale: ID: fi_FI, Name: Finnish (Finland)
268.1708 +display locale: ID: fi_FI, Name: Finnish (Finland)
268.1709 +format locale: ID: fi_FI, Name: Finnish (Finland)
268.1710 +default charset: ISO-8859-1
268.1711 +
268.1712 +OS Locale:  fi_FI.iso885915@euro
268.1713 +default locale: ID: fi_FI, Name: Finnish (Finland)
268.1714 +display locale: ID: fi_FI, Name: Finnish (Finland)
268.1715 +format locale: ID: fi_FI, Name: Finnish (Finland)
268.1716 +default charset: ISO-8859-15
268.1717 +
268.1718 +OS Locale:  fi_FI.utf8
268.1719 +default locale: ID: fi_FI, Name: Finnish (Finland)
268.1720 +display locale: ID: fi_FI, Name: Finnish (Finland)
268.1721 +format locale: ID: fi_FI, Name: Finnish (Finland)
268.1722 +default charset: UTF-8
268.1723 +
268.1724 +OS Locale:  fi_FI@euro
268.1725 +default locale: ID: fi_FI, Name: Finnish (Finland)
268.1726 +display locale: ID: fi_FI, Name: Finnish (Finland)
268.1727 +format locale: ID: fi_FI, Name: Finnish (Finland)
268.1728 +default charset: ISO-8859-15
268.1729 +
268.1730 +OS Locale:  finnish
268.1731 +default locale: ID: fi_FI, Name: Finnish (Finland)
268.1732 +display locale: ID: fi_FI, Name: Finnish (Finland)
268.1733 +format locale: ID: fi_FI, Name: Finnish (Finland)
268.1734 +default charset: ISO-8859-1
268.1735 +
268.1736 +OS Locale:  fo_FO
268.1737 +default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1738 +display locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1739 +format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1740 +default charset: ISO-8859-1
268.1741 +
268.1742 +OS Locale:  fo_FO.iso88591
268.1743 +default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1744 +display locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1745 +format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1746 +default charset: ISO-8859-1
268.1747 +
268.1748 +OS Locale:  fo_FO.utf8
268.1749 +default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1750 +display locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1751 +format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
268.1752 +default charset: UTF-8
268.1753 +
268.1754 +OS Locale:  fr_BE
268.1755 +default locale: ID: fr_BE, Name: French (Belgium)
268.1756 +display locale: ID: fr_BE, Name: French (Belgium)
268.1757 +format locale: ID: fr_BE, Name: French (Belgium)
268.1758 +default charset: ISO-8859-1
268.1759 +
268.1760 +OS Locale:  fr_BE.iso88591
268.1761 +default locale: ID: fr_BE, Name: French (Belgium)
268.1762 +display locale: ID: fr_BE, Name: French (Belgium)
268.1763 +format locale: ID: fr_BE, Name: French (Belgium)
268.1764 +default charset: ISO-8859-1
268.1765 +
268.1766 +OS Locale:  fr_BE.iso885915@euro
268.1767 +default locale: ID: fr_BE, Name: French (Belgium)
268.1768 +display locale: ID: fr_BE, Name: French (Belgium)
268.1769 +format locale: ID: fr_BE, Name: French (Belgium)
268.1770 +default charset: ISO-8859-15
268.1771 +
268.1772 +OS Locale:  fr_BE.utf8
268.1773 +default locale: ID: fr_BE, Name: French (Belgium)
268.1774 +display locale: ID: fr_BE, Name: French (Belgium)
268.1775 +format locale: ID: fr_BE, Name: French (Belgium)
268.1776 +default charset: UTF-8
268.1777 +
268.1778 +OS Locale:  fr_BE@euro
268.1779 +default locale: ID: fr_BE, Name: French (Belgium)
268.1780 +display locale: ID: fr_BE, Name: French (Belgium)
268.1781 +format locale: ID: fr_BE, Name: French (Belgium)
268.1782 +default charset: ISO-8859-15
268.1783 +
268.1784 +OS Locale:  fr_CA
268.1785 +default locale: ID: fr_CA, Name: French (Canada)
268.1786 +display locale: ID: fr_CA, Name: French (Canada)
268.1787 +format locale: ID: fr_CA, Name: French (Canada)
268.1788 +default charset: ISO-8859-1
268.1789 +
268.1790 +OS Locale:  fr_CA.iso88591
268.1791 +default locale: ID: fr_CA, Name: French (Canada)
268.1792 +display locale: ID: fr_CA, Name: French (Canada)
268.1793 +format locale: ID: fr_CA, Name: French (Canada)
268.1794 +default charset: ISO-8859-1
268.1795 +
268.1796 +OS Locale:  fr_CA.utf8
268.1797 +default locale: ID: fr_CA, Name: French (Canada)
268.1798 +display locale: ID: fr_CA, Name: French (Canada)
268.1799 +format locale: ID: fr_CA, Name: French (Canada)
268.1800 +default charset: UTF-8
268.1801 +
268.1802 +OS Locale:  fr_CH
268.1803 +default locale: ID: fr_CH, Name: French (Switzerland)
268.1804 +display locale: ID: fr_CH, Name: French (Switzerland)
268.1805 +format locale: ID: fr_CH, Name: French (Switzerland)
268.1806 +default charset: ISO-8859-1
268.1807 +
268.1808 +OS Locale:  fr_CH.iso88591
268.1809 +default locale: ID: fr_CH, Name: French (Switzerland)
268.1810 +display locale: ID: fr_CH, Name: French (Switzerland)
268.1811 +format locale: ID: fr_CH, Name: French (Switzerland)
268.1812 +default charset: ISO-8859-1
268.1813 +
268.1814 +OS Locale:  fr_CH.utf8
268.1815 +default locale: ID: fr_CH, Name: French (Switzerland)
268.1816 +display locale: ID: fr_CH, Name: French (Switzerland)
268.1817 +format locale: ID: fr_CH, Name: French (Switzerland)
268.1818 +default charset: UTF-8
268.1819 +
268.1820 +OS Locale:  fr_FR
268.1821 +default locale: ID: fr_FR, Name: French (France)
268.1822 +display locale: ID: fr_FR, Name: French (France)
268.1823 +format locale: ID: fr_FR, Name: French (France)
268.1824 +default charset: ISO-8859-1
268.1825 +
268.1826 +OS Locale:  fr_FR.iso88591
268.1827 +default locale: ID: fr_FR, Name: French (France)
268.1828 +display locale: ID: fr_FR, Name: French (France)
268.1829 +format locale: ID: fr_FR, Name: French (France)
268.1830 +default charset: ISO-8859-1
268.1831 +
268.1832 +OS Locale:  fr_FR.iso885915@euro
268.1833 +default locale: ID: fr_FR, Name: French (France)
268.1834 +display locale: ID: fr_FR, Name: French (France)
268.1835 +format locale: ID: fr_FR, Name: French (France)
268.1836 +default charset: ISO-8859-15
268.1837 +
268.1838 +OS Locale:  fr_FR.utf8
268.1839 +default locale: ID: fr_FR, Name: French (France)
268.1840 +display locale: ID: fr_FR, Name: French (France)
268.1841 +format locale: ID: fr_FR, Name: French (France)
268.1842 +default charset: UTF-8
268.1843 +
268.1844 +OS Locale:  fr_FR@euro
268.1845 +default locale: ID: fr_FR, Name: French (France)
268.1846 +display locale: ID: fr_FR, Name: French (France)
268.1847 +format locale: ID: fr_FR, Name: French (France)
268.1848 +default charset: ISO-8859-15
268.1849 +
268.1850 +OS Locale:  fr_LU
268.1851 +default locale: ID: fr_LU, Name: French (Luxembourg)
268.1852 +display locale: ID: fr_LU, Name: French (Luxembourg)
268.1853 +format locale: ID: fr_LU, Name: French (Luxembourg)
268.1854 +default charset: ISO-8859-1
268.1855 +
268.1856 +OS Locale:  fr_LU.iso88591
268.1857 +default locale: ID: fr_LU, Name: French (Luxembourg)
268.1858 +display locale: ID: fr_LU, Name: French (Luxembourg)
268.1859 +format locale: ID: fr_LU, Name: French (Luxembourg)
268.1860 +default charset: ISO-8859-1
268.1861 +
268.1862 +OS Locale:  fr_LU.iso885915@euro
268.1863 +default locale: ID: fr_LU, Name: French (Luxembourg)
268.1864 +display locale: ID: fr_LU, Name: French (Luxembourg)
268.1865 +format locale: ID: fr_LU, Name: French (Luxembourg)
268.1866 +default charset: ISO-8859-15
268.1867 +
268.1868 +OS Locale:  fr_LU.utf8
268.1869 +default locale: ID: fr_LU, Name: French (Luxembourg)
268.1870 +display locale: ID: fr_LU, Name: French (Luxembourg)
268.1871 +format locale: ID: fr_LU, Name: French (Luxembourg)
268.1872 +default charset: UTF-8
268.1873 +
268.1874 +OS Locale:  fr_LU@euro
268.1875 +default locale: ID: fr_LU, Name: French (Luxembourg)
268.1876 +display locale: ID: fr_LU, Name: French (Luxembourg)
268.1877 +format locale: ID: fr_LU, Name: French (Luxembourg)
268.1878 +default charset: ISO-8859-15
268.1879 +
268.1880 +OS Locale:  français
268.1881 +default locale: ID: fr_FR, Name: French (France)
268.1882 +display locale: ID: fr_FR, Name: French (France)
268.1883 +format locale: ID: fr_FR, Name: French (France)
268.1884 +default charset: ISO-8859-1
268.1885 +
268.1886 +OS Locale:  french
268.1887 +default locale: ID: fr_FR, Name: French (France)
268.1888 +display locale: ID: fr_FR, Name: French (France)
268.1889 +format locale: ID: fr_FR, Name: French (France)
268.1890 +default charset: ISO-8859-1
268.1891 +
268.1892 +OS Locale:  fy_NL
268.1893 +default locale: ID: fy_NL, Name: Frisian (Netherlands)
268.1894 +display locale: ID: fy_NL, Name: Frisian (Netherlands)
268.1895 +format locale: ID: fy_NL, Name: Frisian (Netherlands)
268.1896 +default charset: UTF-8
268.1897 +
268.1898 +OS Locale:  fy_NL.utf8
268.1899 +default locale: ID: fy_NL, Name: Frisian (Netherlands)
268.1900 +display locale: ID: fy_NL, Name: Frisian (Netherlands)
268.1901 +format locale: ID: fy_NL, Name: Frisian (Netherlands)
268.1902 +default charset: UTF-8
268.1903 +
268.1904 +OS Locale:  ga_IE
268.1905 +default locale: ID: ga_IE, Name: Irish (Ireland)
268.1906 +display locale: ID: ga_IE, Name: Irish (Ireland)
268.1907 +format locale: ID: ga_IE, Name: Irish (Ireland)
268.1908 +default charset: ISO-8859-1
268.1909 +
268.1910 +OS Locale:  ga_IE.iso88591
268.1911 +default locale: ID: ga_IE, Name: Irish (Ireland)
268.1912 +display locale: ID: ga_IE, Name: Irish (Ireland)
268.1913 +format locale: ID: ga_IE, Name: Irish (Ireland)
268.1914 +default charset: ISO-8859-1
268.1915 +
268.1916 +OS Locale:  ga_IE.iso885915@euro
268.1917 +default locale: ID: ga_IE, Name: Irish (Ireland)
268.1918 +display locale: ID: ga_IE, Name: Irish (Ireland)
268.1919 +format locale: ID: ga_IE, Name: Irish (Ireland)
268.1920 +default charset: ISO-8859-15
268.1921 +
268.1922 +OS Locale:  ga_IE.utf8
268.1923 +default locale: ID: ga_IE, Name: Irish (Ireland)
268.1924 +display locale: ID: ga_IE, Name: Irish (Ireland)
268.1925 +format locale: ID: ga_IE, Name: Irish (Ireland)
268.1926 +default charset: UTF-8
268.1927 +
268.1928 +OS Locale:  ga_IE@euro
268.1929 +default locale: ID: ga_IE, Name: Irish (Ireland)
268.1930 +display locale: ID: ga_IE, Name: Irish (Ireland)
268.1931 +format locale: ID: ga_IE, Name: Irish (Ireland)
268.1932 +default charset: ISO-8859-15
268.1933 +
268.1934 +OS Locale:  galego
268.1935 +default locale: ID: en, Name: English
268.1936 +display locale: ID: en, Name: English
268.1937 +format locale: ID: en, Name: English
268.1938 +default charset: ISO-8859-1
268.1939 +
268.1940 +OS Locale:  galician
268.1941 +default locale: ID: en, Name: English
268.1942 +display locale: ID: en, Name: English
268.1943 +format locale: ID: en, Name: English
268.1944 +default charset: ISO-8859-1
268.1945 +
268.1946 +OS Locale:  gd_GB
268.1947 +default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1948 +display locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1949 +format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1950 +default charset: ISO-8859-15
268.1951 +
268.1952 +OS Locale:  gd_GB.iso885915
268.1953 +default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1954 +display locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1955 +format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1956 +default charset: ISO-8859-15
268.1957 +
268.1958 +OS Locale:  gd_GB.utf8
268.1959 +default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1960 +display locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1961 +format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
268.1962 +default charset: UTF-8
268.1963 +
268.1964 +OS Locale:  german
268.1965 +default locale: ID: de_DE, Name: German (Germany)
268.1966 +display locale: ID: de_DE, Name: German (Germany)
268.1967 +format locale: ID: de_DE, Name: German (Germany)
268.1968 +default charset: ISO-8859-1
268.1969 +
268.1970 +OS Locale:  gez_ER
268.1971 +default locale: ID: en_ER, Name: English (Eritrea)
268.1972 +display locale: ID: en_ER, Name: English (Eritrea)
268.1973 +format locale: ID: en_ER, Name: English (Eritrea)
268.1974 +default charset: UTF-8
268.1975 +
268.1976 +OS Locale:  gez_ER.utf8
268.1977 +default locale: ID: en_ER, Name: English (Eritrea)
268.1978 +display locale: ID: en_ER, Name: English (Eritrea)
268.1979 +format locale: ID: en_ER, Name: English (Eritrea)
268.1980 +default charset: UTF-8
268.1981 +
268.1982 +OS Locale:  gez_ER.utf8@abegede
268.1983 +default locale: ID: en_ER, Name: English (Eritrea)
268.1984 +display locale: ID: en_ER, Name: English (Eritrea)
268.1985 +format locale: ID: en_ER, Name: English (Eritrea)
268.1986 +default charset: UTF-8
268.1987 +
268.1988 +OS Locale:  gez_ER@abegede
268.1989 +default locale: ID: en_ER, Name: English (Eritrea)
268.1990 +display locale: ID: en_ER, Name: English (Eritrea)
268.1991 +format locale: ID: en_ER, Name: English (Eritrea)
268.1992 +default charset: UTF-8
268.1993 +
268.1994 +OS Locale:  gez_ET
268.1995 +default locale: ID: en_ET, Name: English (Ethiopia)
268.1996 +display locale: ID: en_ET, Name: English (Ethiopia)
268.1997 +format locale: ID: en_ET, Name: English (Ethiopia)
268.1998 +default charset: UTF-8
268.1999 +
268.2000 +OS Locale:  gez_ET.utf8
268.2001 +default locale: ID: en_ET, Name: English (Ethiopia)
268.2002 +display locale: ID: en_ET, Name: English (Ethiopia)
268.2003 +format locale: ID: en_ET, Name: English (Ethiopia)
268.2004 +default charset: UTF-8
268.2005 +
268.2006 +OS Locale:  gez_ET.utf8@abegede
268.2007 +default locale: ID: en_ET, Name: English (Ethiopia)
268.2008 +display locale: ID: en_ET, Name: English (Ethiopia)
268.2009 +format locale: ID: en_ET, Name: English (Ethiopia)
268.2010 +default charset: UTF-8
268.2011 +
268.2012 +OS Locale:  gez_ET@abegede
268.2013 +default locale: ID: en_ET, Name: English (Ethiopia)
268.2014 +display locale: ID: en_ET, Name: English (Ethiopia)
268.2015 +format locale: ID: en_ET, Name: English (Ethiopia)
268.2016 +default charset: UTF-8
268.2017 +
268.2018 +OS Locale:  gl_ES
268.2019 +default locale: ID: gl_ES, Name: Gallegan (Spain)
268.2020 +display locale: ID: gl_ES, Name: Gallegan (Spain)
268.2021 +format locale: ID: gl_ES, Name: Gallegan (Spain)
268.2022 +default charset: ISO-8859-1
268.2023 +
268.2024 +OS Locale:  gl_ES.iso88591
268.2025 +default locale: ID: gl_ES, Name: Gallegan (Spain)
268.2026 +display locale: ID: gl_ES, Name: Gallegan (Spain)
268.2027 +format locale: ID: gl_ES, Name: Gallegan (Spain)
268.2028 +default charset: ISO-8859-1
268.2029 +
268.2030 +OS Locale:  gl_ES.iso885915@euro
268.2031 +default locale: ID: gl_ES, Name: Gallegan (Spain)
268.2032 +display locale: ID: gl_ES, Name: Gallegan (Spain)
268.2033 +format locale: ID: gl_ES, Name: Gallegan (Spain)
268.2034 +default charset: ISO-8859-15
268.2035 +
268.2036 +OS Locale:  gl_ES.utf8
268.2037 +default locale: ID: gl_ES, Name: Gallegan (Spain)
268.2038 +display locale: ID: gl_ES, Name: Gallegan (Spain)
268.2039 +format locale: ID: gl_ES, Name: Gallegan (Spain)
268.2040 +default charset: UTF-8
268.2041 +
268.2042 +OS Locale:  gl_ES@euro
268.2043 +default locale: ID: gl_ES, Name: Gallegan (Spain)
268.2044 +display locale: ID: gl_ES, Name: Gallegan (Spain)
268.2045 +format locale: ID: gl_ES, Name: Gallegan (Spain)
268.2046 +default charset: ISO-8859-15
268.2047 +
268.2048 +OS Locale:  greek
268.2049 +default locale: ID: el_GR, Name: Greek (Greece)
268.2050 +display locale: ID: el_GR, Name: Greek (Greece)
268.2051 +format locale: ID: el_GR, Name: Greek (Greece)
268.2052 +default charset: ISO-8859-7
268.2053 +
268.2054 +OS Locale:  gu_IN
268.2055 +default locale: ID: gu_IN, Name: Gujarati (India)
268.2056 +display locale: ID: gu_IN, Name: Gujarati (India)
268.2057 +format locale: ID: gu_IN, Name: Gujarati (India)
268.2058 +default charset: UTF-8
268.2059 +
268.2060 +OS Locale:  gu_IN.utf8
268.2061 +default locale: ID: gu_IN, Name: Gujarati (India)
268.2062 +display locale: ID: gu_IN, Name: Gujarati (India)
268.2063 +format locale: ID: gu_IN, Name: Gujarati (India)
268.2064 +default charset: UTF-8
268.2065 +
268.2066 +OS Locale:  gv_GB
268.2067 +default locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2068 +display locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2069 +format locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2070 +default charset: ISO-8859-1
268.2071 +
268.2072 +OS Locale:  gv_GB.iso88591
268.2073 +default locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2074 +display locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2075 +format locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2076 +default charset: ISO-8859-1
268.2077 +
268.2078 +OS Locale:  gv_GB.utf8
268.2079 +default locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2080 +display locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2081 +format locale: ID: gv_GB, Name: Manx (United Kingdom)
268.2082 +default charset: UTF-8
268.2083 +
268.2084 +OS Locale:  he_IL
268.2085 +default locale: ID: iw_IL, Name: Hebrew (Israel)
268.2086 +display locale: ID: iw_IL, Name: Hebrew (Israel)
268.2087 +format locale: ID: iw_IL, Name: Hebrew (Israel)
268.2088 +default charset: ISO-8859-8
268.2089 +
268.2090 +OS Locale:  he_IL.iso88598
268.2091 +default locale: ID: iw_IL, Name: Hebrew (Israel)
268.2092 +display locale: ID: iw_IL, Name: Hebrew (Israel)
268.2093 +format locale: ID: iw_IL, Name: Hebrew (Israel)
268.2094 +default charset: ISO-8859-8
268.2095 +
268.2096 +OS Locale:  he_IL.utf8
268.2097 +default locale: ID: iw_IL, Name: Hebrew (Israel)
268.2098 +display locale: ID: iw_IL, Name: Hebrew (Israel)
268.2099 +format locale: ID: iw_IL, Name: Hebrew (Israel)
268.2100 +default charset: UTF-8
268.2101 +
268.2102 +OS Locale:  hebrew
268.2103 +default locale: ID: iw_IL, Name: Hebrew (Israel)
268.2104 +display locale: ID: iw_IL, Name: Hebrew (Israel)
268.2105 +format locale: ID: iw_IL, Name: Hebrew (Israel)
268.2106 +default charset: ISO-8859-8
268.2107 +
268.2108 +OS Locale:  hi_IN
268.2109 +default locale: ID: hi_IN, Name: Hindi (India)
268.2110 +display locale: ID: hi_IN, Name: Hindi (India)
268.2111 +format locale: ID: hi_IN, Name: Hindi (India)
268.2112 +default charset: UTF-8
268.2113 +
268.2114 +OS Locale:  hi_IN.utf8
268.2115 +default locale: ID: hi_IN, Name: Hindi (India)
268.2116 +display locale: ID: hi_IN, Name: Hindi (India)
268.2117 +format locale: ID: hi_IN, Name: Hindi (India)
268.2118 +default charset: UTF-8
268.2119 +
268.2120 +OS Locale:  hr_HR
268.2121 +default locale: ID: hr_HR, Name: Croatian (Croatia)
268.2122 +display locale: ID: hr_HR, Name: Croatian (Croatia)
268.2123 +format locale: ID: hr_HR, Name: Croatian (Croatia)
268.2124 +default charset: ISO-8859-2
268.2125 +
268.2126 +OS Locale:  hr_HR.iso88592
268.2127 +default locale: ID: hr_HR, Name: Croatian (Croatia)
268.2128 +display locale: ID: hr_HR, Name: Croatian (Croatia)
268.2129 +format locale: ID: hr_HR, Name: Croatian (Croatia)
268.2130 +default charset: ISO-8859-2
268.2131 +
268.2132 +OS Locale:  hr_HR.utf8
268.2133 +default locale: ID: hr_HR, Name: Croatian (Croatia)
268.2134 +display locale: ID: hr_HR, Name: Croatian (Croatia)
268.2135 +format locale: ID: hr_HR, Name: Croatian (Croatia)
268.2136 +default charset: UTF-8
268.2137 +
268.2138 +OS Locale:  hrvatski
268.2139 +default locale: ID: hr_HR, Name: Croatian (Croatia)
268.2140 +display locale: ID: hr_HR, Name: Croatian (Croatia)
268.2141 +format locale: ID: hr_HR, Name: Croatian (Croatia)
268.2142 +default charset: ISO-8859-2
268.2143 +
268.2144 +OS Locale:  hsb_DE
268.2145 +default locale: ID: en_DE, Name: English (Germany)
268.2146 +display locale: ID: en_DE, Name: English (Germany)
268.2147 +format locale: ID: en_DE, Name: English (Germany)
268.2148 +default charset: ISO-8859-2
268.2149 +
268.2150 +OS Locale:  hsb_DE.iso88592
268.2151 +default locale: ID: en_DE, Name: English (Germany)
268.2152 +display locale: ID: en_DE, Name: English (Germany)
268.2153 +format locale: ID: en_DE, Name: English (Germany)
268.2154 +default charset: ISO-8859-2
268.2155 +
268.2156 +OS Locale:  hsb_DE.utf8
268.2157 +default locale: ID: en_DE, Name: English (Germany)
268.2158 +display locale: ID: en_DE, Name: English (Germany)
268.2159 +format locale: ID: en_DE, Name: English (Germany)
268.2160 +default charset: UTF-8
268.2161 +
268.2162 +OS Locale:  hu_HU
268.2163 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2164 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2165 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2166 +default charset: ISO-8859-2
268.2167 +
268.2168 +OS Locale:  hu_HU.iso88592
268.2169 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2170 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2171 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2172 +default charset: ISO-8859-2
268.2173 +
268.2174 +OS Locale:  hu_HU.utf8
268.2175 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2176 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2177 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2178 +default charset: UTF-8
268.2179 +
268.2180 +OS Locale:  hungarian
268.2181 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2182 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2183 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
268.2184 +default charset: ISO-8859-2
268.2185 +
268.2186 +OS Locale:  hy_AM
268.2187 +default locale: ID: hy_AM, Name: Armenian (Armenia)
268.2188 +display locale: ID: hy_AM, Name: Armenian (Armenia)
268.2189 +format locale: ID: hy_AM, Name: Armenian (Armenia)
268.2190 +default charset: UTF-8
268.2191 +
268.2192 +OS Locale:  hy_AM.armscii8
268.2193 +default locale: ID: hy_AM, Name: Armenian (Armenia)
268.2194 +display locale: ID: hy_AM, Name: Armenian (Armenia)
268.2195 +format locale: ID: hy_AM, Name: Armenian (Armenia)
268.2196 +default charset: UTF-8
268.2197 +
268.2198 +OS Locale:  hy_AM.utf8
268.2199 +default locale: ID: hy_AM, Name: Armenian (Armenia)
268.2200 +display locale: ID: hy_AM, Name: Armenian (Armenia)
268.2201 +format locale: ID: hy_AM, Name: Armenian (Armenia)
268.2202 +default charset: UTF-8
268.2203 +
268.2204 +OS Locale:  icelandic
268.2205 +default locale: ID: is_IS, Name: Icelandic (Iceland)
268.2206 +display locale: ID: is_IS, Name: Icelandic (Iceland)
268.2207 +format locale: ID: is_IS, Name: Icelandic (Iceland)
268.2208 +default charset: ISO-8859-1
268.2209 +
268.2210 +OS Locale:  id_ID
268.2211 +default locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2212 +display locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2213 +format locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2214 +default charset: ISO-8859-1
268.2215 +
268.2216 +OS Locale:  id_ID.iso88591
268.2217 +default locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2218 +display locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2219 +format locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2220 +default charset: ISO-8859-1
268.2221 +
268.2222 +OS Locale:  id_ID.utf8
268.2223 +default locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2224 +display locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2225 +format locale: ID: in_ID, Name: Indonesian (Indonesia)
268.2226 +default charset: UTF-8
268.2227 +
268.2228 +OS Locale:  is_IS
268.2229 +default locale: ID: is_IS, Name: Icelandic (Iceland)
268.2230 +display locale: ID: is_IS, Name: Icelandic (Iceland)
268.2231 +format locale: ID: is_IS, Name: Icelandic (Iceland)
268.2232 +default charset: ISO-8859-1
268.2233 +
268.2234 +OS Locale:  is_IS.iso88591
268.2235 +default locale: ID: is_IS, Name: Icelandic (Iceland)
268.2236 +display locale: ID: is_IS, Name: Icelandic (Iceland)
268.2237 +format locale: ID: is_IS, Name: Icelandic (Iceland)
268.2238 +default charset: ISO-8859-1
268.2239 +
268.2240 +OS Locale:  is_IS.utf8
268.2241 +default locale: ID: is_IS, Name: Icelandic (Iceland)
268.2242 +display locale: ID: is_IS, Name: Icelandic (Iceland)
268.2243 +format locale: ID: is_IS, Name: Icelandic (Iceland)
268.2244 +default charset: UTF-8
268.2245 +
268.2246 +OS Locale:  it_CH
268.2247 +default locale: ID: it_CH, Name: Italian (Switzerland)
268.2248 +display locale: ID: it_CH, Name: Italian (Switzerland)
268.2249 +format locale: ID: it_CH, Name: Italian (Switzerland)
268.2250 +default charset: ISO-8859-1
268.2251 +
268.2252 +OS Locale:  it_CH.iso88591
268.2253 +default locale: ID: it_CH, Name: Italian (Switzerland)
268.2254 +display locale: ID: it_CH, Name: Italian (Switzerland)
268.2255 +format locale: ID: it_CH, Name: Italian (Switzerland)
268.2256 +default charset: ISO-8859-1
268.2257 +
268.2258 +OS Locale:  it_CH.utf8
268.2259 +default locale: ID: it_CH, Name: Italian (Switzerland)
268.2260 +display locale: ID: it_CH, Name: Italian (Switzerland)
268.2261 +format locale: ID: it_CH, Name: Italian (Switzerland)
268.2262 +default charset: UTF-8
268.2263 +
268.2264 +OS Locale:  it_IT
268.2265 +default locale: ID: it_IT, Name: Italian (Italy)
268.2266 +display locale: ID: it_IT, Name: Italian (Italy)
268.2267 +format locale: ID: it_IT, Name: Italian (Italy)
268.2268 +default charset: ISO-8859-1
268.2269 +
268.2270 +OS Locale:  it_IT.iso88591
268.2271 +default locale: ID: it_IT, Name: Italian (Italy)
268.2272 +display locale: ID: it_IT, Name: Italian (Italy)
268.2273 +format locale: ID: it_IT, Name: Italian (Italy)
268.2274 +default charset: ISO-8859-1
268.2275 +
268.2276 +OS Locale:  it_IT.iso885915@euro
268.2277 +default locale: ID: it_IT, Name: Italian (Italy)
268.2278 +display locale: ID: it_IT, Name: Italian (Italy)
268.2279 +format locale: ID: it_IT, Name: Italian (Italy)
268.2280 +default charset: ISO-8859-15
268.2281 +
268.2282 +OS Locale:  it_IT.utf8
268.2283 +default locale: ID: it_IT, Name: Italian (Italy)
268.2284 +display locale: ID: it_IT, Name: Italian (Italy)
268.2285 +format locale: ID: it_IT, Name: Italian (Italy)
268.2286 +default charset: UTF-8
268.2287 +
268.2288 +OS Locale:  it_IT@euro
268.2289 +default locale: ID: it_IT, Name: Italian (Italy)
268.2290 +display locale: ID: it_IT, Name: Italian (Italy)
268.2291 +format locale: ID: it_IT, Name: Italian (Italy)
268.2292 +default charset: ISO-8859-15
268.2293 +
268.2294 +OS Locale:  italian
268.2295 +default locale: ID: it_IT, Name: Italian (Italy)
268.2296 +display locale: ID: it_IT, Name: Italian (Italy)
268.2297 +format locale: ID: it_IT, Name: Italian (Italy)
268.2298 +default charset: ISO-8859-1
268.2299 +
268.2300 +OS Locale:  iw_IL
268.2301 +default locale: ID: iw_IL, Name: Hebrew (Israel)
268.2302 +display locale: ID: iw_IL, Name: Hebrew (Israel)
268.2303 +format locale: ID: iw_IL, Name: Hebrew (Israel)
268.2304 +default charset: ISO-8859-8
268.2305 +
268.2306 +OS Locale:  iw_IL.iso88598
268.2307 +default locale: ID: iw_IL, Name: Hebrew (Israel)
268.2308 +display locale: ID: iw_IL, Name: Hebrew (Israel)
268.2309 +format locale: ID: iw_IL, Name: Hebrew (Israel)
268.2310 +default charset: ISO-8859-8
268.2311 +
268.2312 +OS Locale:  iw_IL.utf8
268.2313 +default locale: ID: iw_IL, Name: Hebrew (Israel)
268.2314 +display locale: ID: iw_IL, Name: Hebrew (Israel)
268.2315 +format locale: ID: iw_IL, Name: Hebrew (Israel)
268.2316 +default charset: UTF-8
268.2317 +
268.2318 +OS Locale:  ja_JP
268.2319 +default locale: ID: ja_JP, Name: Japanese (Japan)
268.2320 +display locale: ID: ja_JP, Name: Japanese (Japan)
268.2321 +format locale: ID: ja_JP, Name: Japanese (Japan)
268.2322 +default charset: x-euc-jp-linux
268.2323 +
268.2324 +OS Locale:  ja_JP.eucjp
268.2325 +default locale: ID: ja_JP, Name: Japanese (Japan)
268.2326 +display locale: ID: ja_JP, Name: Japanese (Japan)
268.2327 +format locale: ID: ja_JP, Name: Japanese (Japan)
268.2328 +default charset: x-euc-jp-linux
268.2329 +
268.2330 +OS Locale:  ja_JP.ujis
268.2331 +default locale: ID: ja_JP, Name: Japanese (Japan)
268.2332 +display locale: ID: ja_JP, Name: Japanese (Japan)
268.2333 +format locale: ID: ja_JP, Name: Japanese (Japan)
268.2334 +default charset: x-euc-jp-linux
268.2335 +
268.2336 +OS Locale:  ja_JP.utf8
268.2337 +default locale: ID: ja_JP, Name: Japanese (Japan)
268.2338 +display locale: ID: ja_JP, Name: Japanese (Japan)
268.2339 +format locale: ID: ja_JP, Name: Japanese (Japan)
268.2340 +default charset: UTF-8
268.2341 +
268.2342 +OS Locale:  japanese
268.2343 +default locale: ID: ja_JP, Name: Japanese (Japan)
268.2344 +display locale: ID: ja_JP, Name: Japanese (Japan)
268.2345 +format locale: ID: ja_JP, Name: Japanese (Japan)
268.2346 +default charset: x-euc-jp-linux
268.2347 +
268.2348 +OS Locale:  japanese.euc
268.2349 +default locale: ID: ja_JP, Name: Japanese (Japan)
268.2350 +display locale: ID: ja_JP, Name: Japanese (Japan)
268.2351 +format locale: ID: ja_JP, Name: Japanese (Japan)
268.2352 +default charset: x-euc-jp-linux
268.2353 +
268.2354 +OS Locale:  ka_GE
268.2355 +default locale: ID: ka_GE, Name: Georgian (Georgia)
268.2356 +display locale: ID: ka_GE, Name: Georgian (Georgia)
268.2357 +format locale: ID: ka_GE, Name: Georgian (Georgia)
268.2358 +default charset: UTF-8
268.2359 +
268.2360 +OS Locale:  ka_GE.georgianps
268.2361 +default locale: ID: ka_GE, Name: Georgian (Georgia)
268.2362 +display locale: ID: ka_GE, Name: Georgian (Georgia)
268.2363 +format locale: ID: ka_GE, Name: Georgian (Georgia)
268.2364 +default charset: UTF-8
268.2365 +
268.2366 +OS Locale:  ka_GE.utf8
268.2367 +default locale: ID: ka_GE, Name: Georgian (Georgia)
268.2368 +display locale: ID: ka_GE, Name: Georgian (Georgia)
268.2369 +format locale: ID: ka_GE, Name: Georgian (Georgia)
268.2370 +default charset: UTF-8
268.2371 +
268.2372 +OS Locale:  kk_KZ
268.2373 +default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2374 +display locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2375 +format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2376 +default charset: UTF-8
268.2377 +
268.2378 +OS Locale:  kk_KZ.pt154
268.2379 +default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2380 +display locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2381 +format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2382 +default charset: UTF-8
268.2383 +
268.2384 +OS Locale:  kk_KZ.utf8
268.2385 +default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2386 +display locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2387 +format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
268.2388 +default charset: UTF-8
268.2389 +
268.2390 +OS Locale:  kl_GL
268.2391 +default locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2392 +display locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2393 +format locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2394 +default charset: ISO-8859-1
268.2395 +
268.2396 +OS Locale:  kl_GL.iso88591
268.2397 +default locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2398 +display locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2399 +format locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2400 +default charset: ISO-8859-1
268.2401 +
268.2402 +OS Locale:  kl_GL.utf8
268.2403 +default locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2404 +display locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2405 +format locale: ID: kl_GL, Name: Greenlandic (Greenland)
268.2406 +default charset: UTF-8
268.2407 +
268.2408 +OS Locale:  km_KH
268.2409 +default locale: ID: km_KH, Name: Khmer (Cambodia)
268.2410 +display locale: ID: km_KH, Name: Khmer (Cambodia)
268.2411 +format locale: ID: km_KH, Name: Khmer (Cambodia)
268.2412 +default charset: UTF-8
268.2413 +
268.2414 +OS Locale:  km_KH.utf8
268.2415 +default locale: ID: km_KH, Name: Khmer (Cambodia)
268.2416 +display locale: ID: km_KH, Name: Khmer (Cambodia)
268.2417 +format locale: ID: km_KH, Name: Khmer (Cambodia)
268.2418 +default charset: UTF-8
268.2419 +
268.2420 +OS Locale:  kn_IN
268.2421 +default locale: ID: kn_IN, Name: Kannada (India)
268.2422 +display locale: ID: kn_IN, Name: Kannada (India)
268.2423 +format locale: ID: kn_IN, Name: Kannada (India)
268.2424 +default charset: UTF-8
268.2425 +
268.2426 +OS Locale:  kn_IN.utf8
268.2427 +default locale: ID: kn_IN, Name: Kannada (India)
268.2428 +display locale: ID: kn_IN, Name: Kannada (India)
268.2429 +format locale: ID: kn_IN, Name: Kannada (India)
268.2430 +default charset: UTF-8
268.2431 +
268.2432 +OS Locale:  ko_KR
268.2433 +default locale: ID: ko_KR, Name: Korean (South Korea)
268.2434 +display locale: ID: ko_KR, Name: Korean (South Korea)
268.2435 +format locale: ID: ko_KR, Name: Korean (South Korea)
268.2436 +default charset: EUC-KR
268.2437 +
268.2438 +OS Locale:  ko_KR.euckr
268.2439 +default locale: ID: ko_KR, Name: Korean (South Korea)
268.2440 +display locale: ID: ko_KR, Name: Korean (South Korea)
268.2441 +format locale: ID: ko_KR, Name: Korean (South Korea)
268.2442 +default charset: EUC-KR
268.2443 +
268.2444 +OS Locale:  ko_KR.utf8
268.2445 +default locale: ID: ko_KR, Name: Korean (South Korea)
268.2446 +display locale: ID: ko_KR, Name: Korean (South Korea)
268.2447 +format locale: ID: ko_KR, Name: Korean (South Korea)
268.2448 +default charset: UTF-8
268.2449 +
268.2450 +OS Locale:  korean
268.2451 +default locale: ID: en, Name: English
268.2452 +display locale: ID: en, Name: English
268.2453 +format locale: ID: en, Name: English
268.2454 +default charset: EUC-KR
268.2455 +
268.2456 +OS Locale:  korean.euc
268.2457 +default locale: ID: en, Name: English
268.2458 +display locale: ID: en, Name: English
268.2459 +format locale: ID: en, Name: English
268.2460 +default charset: EUC-KR
268.2461 +
268.2462 +OS Locale:  ku_TR
268.2463 +default locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2464 +display locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2465 +format locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2466 +default charset: ISO-8859-9
268.2467 +
268.2468 +OS Locale:  ku_TR.iso88599
268.2469 +default locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2470 +display locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2471 +format locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2472 +default charset: ISO-8859-9
268.2473 +
268.2474 +OS Locale:  ku_TR.utf8
268.2475 +default locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2476 +display locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2477 +format locale: ID: ku_TR, Name: Kurdish (Turkey)
268.2478 +default charset: UTF-8
268.2479 +
268.2480 +OS Locale:  kw_GB
268.2481 +default locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2482 +display locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2483 +format locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2484 +default charset: ISO-8859-1
268.2485 +
268.2486 +OS Locale:  kw_GB.iso88591
268.2487 +default locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2488 +display locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2489 +format locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2490 +default charset: ISO-8859-1
268.2491 +
268.2492 +OS Locale:  kw_GB.utf8
268.2493 +default locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2494 +display locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2495 +format locale: ID: kw_GB, Name: Cornish (United Kingdom)
268.2496 +default charset: UTF-8
268.2497 +
268.2498 +OS Locale:  ky_KG
268.2499 +default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
268.2500 +display locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
268.2501 +format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
268.2502 +default charset: UTF-8
268.2503 +
268.2504 +OS Locale:  ky_KG.utf8
268.2505 +default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
268.2506 +display locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
268.2507 +format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
268.2508 +default charset: UTF-8
268.2509 +
268.2510 +OS Locale:  lg_UG
268.2511 +default locale: ID: lg_UG, Name: Ganda (Uganda)
268.2512 +display locale: ID: lg_UG, Name: Ganda (Uganda)
268.2513 +format locale: ID: lg_UG, Name: Ganda (Uganda)
268.2514 +default charset: UTF-8
268.2515 +
268.2516 +OS Locale:  lg_UG.iso885910
268.2517 +default locale: ID: lg_UG, Name: Ganda (Uganda)
268.2518 +display locale: ID: lg_UG, Name: Ganda (Uganda)
268.2519 +format locale: ID: lg_UG, Name: Ganda (Uganda)
268.2520 +default charset: UTF-8
268.2521 +
268.2522 +OS Locale:  lg_UG.utf8
268.2523 +default locale: ID: lg_UG, Name: Ganda (Uganda)
268.2524 +display locale: ID: lg_UG, Name: Ganda (Uganda)
268.2525 +format locale: ID: lg_UG, Name: Ganda (Uganda)
268.2526 +default charset: UTF-8
268.2527 +
268.2528 +OS Locale:  lithuanian
268.2529 +default locale: ID: en, Name: English
268.2530 +display locale: ID: en, Name: English
268.2531 +format locale: ID: en, Name: English
268.2532 +default charset: ISO-8859-13
268.2533 +
268.2534 +OS Locale:  lo_LA
268.2535 +default locale: ID: lo_LA, Name: Lao (Laos)
268.2536 +display locale: ID: lo_LA, Name: Lao (Laos)
268.2537 +format locale: ID: lo_LA, Name: Lao (Laos)
268.2538 +default charset: UTF-8
268.2539 +
268.2540 +OS Locale:  lo_LA.utf8
268.2541 +default locale: ID: lo_LA, Name: Lao (Laos)
268.2542 +display locale: ID: lo_LA, Name: Lao (Laos)
268.2543 +format locale: ID: lo_LA, Name: Lao (Laos)
268.2544 +default charset: UTF-8
268.2545 +
268.2546 +OS Locale:  lt_LT
268.2547 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2548 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2549 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2550 +default charset: ISO-8859-13
268.2551 +
268.2552 +OS Locale:  lt_LT.iso885913
268.2553 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2554 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2555 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2556 +default charset: ISO-8859-13
268.2557 +
268.2558 +OS Locale:  lt_LT.utf8
268.2559 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2560 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2561 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
268.2562 +default charset: UTF-8
268.2563 +
268.2564 +OS Locale:  lv_LV
268.2565 +default locale: ID: lv_LV, Name: Latvian (Latvia)
268.2566 +display locale: ID: lv_LV, Name: Latvian (Latvia)
268.2567 +format locale: ID: lv_LV, Name: Latvian (Latvia)
268.2568 +default charset: ISO-8859-13
268.2569 +
268.2570 +OS Locale:  lv_LV.iso885913
268.2571 +default locale: ID: lv_LV, Name: Latvian (Latvia)
268.2572 +display locale: ID: lv_LV, Name: Latvian (Latvia)
268.2573 +format locale: ID: lv_LV, Name: Latvian (Latvia)
268.2574 +default charset: ISO-8859-13
268.2575 +
268.2576 +OS Locale:  lv_LV.utf8
268.2577 +default locale: ID: lv_LV, Name: Latvian (Latvia)
268.2578 +display locale: ID: lv_LV, Name: Latvian (Latvia)
268.2579 +format locale: ID: lv_LV, Name: Latvian (Latvia)
268.2580 +default charset: UTF-8
268.2581 +
268.2582 +OS Locale:  mai_IN
268.2583 +default locale: ID: en_IN, Name: English (India)
268.2584 +display locale: ID: en_IN, Name: English (India)
268.2585 +format locale: ID: en_IN, Name: English (India)
268.2586 +default charset: UTF-8
268.2587 +
268.2588 +OS Locale:  mai_IN.utf8
268.2589 +default locale: ID: en_IN, Name: English (India)
268.2590 +display locale: ID: en_IN, Name: English (India)
268.2591 +format locale: ID: en_IN, Name: English (India)
268.2592 +default charset: UTF-8
268.2593 +
268.2594 +OS Locale:  mg_MG
268.2595 +default locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2596 +display locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2597 +format locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2598 +default charset: ISO-8859-15
268.2599 +
268.2600 +OS Locale:  mg_MG.iso885915
268.2601 +default locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2602 +display locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2603 +format locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2604 +default charset: ISO-8859-15
268.2605 +
268.2606 +OS Locale:  mg_MG.utf8
268.2607 +default locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2608 +display locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2609 +format locale: ID: mg_MG, Name: Malagasy (Madagascar)
268.2610 +default charset: UTF-8
268.2611 +
268.2612 +OS Locale:  mi_NZ
268.2613 +default locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2614 +display locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2615 +format locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2616 +default charset: ISO-8859-13
268.2617 +
268.2618 +OS Locale:  mi_NZ.iso885913
268.2619 +default locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2620 +display locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2621 +format locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2622 +default charset: ISO-8859-13
268.2623 +
268.2624 +OS Locale:  mi_NZ.utf8
268.2625 +default locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2626 +display locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2627 +format locale: ID: mi_NZ, Name: Maori (New Zealand)
268.2628 +default charset: UTF-8
268.2629 +
268.2630 +OS Locale:  mk_MK
268.2631 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2632 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2633 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2634 +default charset: ISO-8859-5
268.2635 +
268.2636 +OS Locale:  mk_MK.iso88595
268.2637 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2638 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2639 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2640 +default charset: ISO-8859-5
268.2641 +
268.2642 +OS Locale:  mk_MK.utf8
268.2643 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2644 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2645 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
268.2646 +default charset: UTF-8
268.2647 +
268.2648 +OS Locale:  ml_IN
268.2649 +default locale: ID: ml_IN, Name: Malayalam (India)
268.2650 +display locale: ID: ml_IN, Name: Malayalam (India)
268.2651 +format locale: ID: ml_IN, Name: Malayalam (India)
268.2652 +default charset: UTF-8
268.2653 +
268.2654 +OS Locale:  ml_IN.utf8
268.2655 +default locale: ID: ml_IN, Name: Malayalam (India)
268.2656 +display locale: ID: ml_IN, Name: Malayalam (India)
268.2657 +format locale: ID: ml_IN, Name: Malayalam (India)
268.2658 +default charset: UTF-8
268.2659 +
268.2660 +OS Locale:  mn_MN
268.2661 +default locale: ID: mn_MN, Name: Mongolian (Mongolia)
268.2662 +display locale: ID: mn_MN, Name: Mongolian (Mongolia)
268.2663 +format locale: ID: mn_MN, Name: Mongolian (Mongolia)
268.2664 +default charset: UTF-8
268.2665 +
268.2666 +OS Locale:  mn_MN.utf8
268.2667 +default locale: ID: mn_MN, Name: Mongolian (Mongolia)
268.2668 +display locale: ID: mn_MN, Name: Mongolian (Mongolia)
268.2669 +format locale: ID: mn_MN, Name: Mongolian (Mongolia)
268.2670 +default charset: UTF-8
268.2671 +
268.2672 +OS Locale:  mr_IN
268.2673 +default locale: ID: mr_IN, Name: Marathi (India)
268.2674 +display locale: ID: mr_IN, Name: Marathi (India)
268.2675 +format locale: ID: mr_IN, Name: Marathi (India)
268.2676 +default charset: UTF-8
268.2677 +
268.2678 +OS Locale:  mr_IN.utf8
268.2679 +default locale: ID: mr_IN, Name: Marathi (India)
268.2680 +display locale: ID: mr_IN, Name: Marathi (India)
268.2681 +format locale: ID: mr_IN, Name: Marathi (India)
268.2682 +default charset: UTF-8
268.2683 +
268.2684 +OS Locale:  ms_MY
268.2685 +default locale: ID: ms_MY, Name: Malay (Malaysia)
268.2686 +display locale: ID: ms_MY, Name: Malay (Malaysia)
268.2687 +format locale: ID: ms_MY, Name: Malay (Malaysia)
268.2688 +default charset: ISO-8859-1
268.2689 +
268.2690 +OS Locale:  ms_MY.iso88591
268.2691 +default locale: ID: ms_MY, Name: Malay (Malaysia)
268.2692 +display locale: ID: ms_MY, Name: Malay (Malaysia)
268.2693 +format locale: ID: ms_MY, Name: Malay (Malaysia)
268.2694 +default charset: ISO-8859-1
268.2695 +
268.2696 +OS Locale:  ms_MY.utf8
268.2697 +default locale: ID: ms_MY, Name: Malay (Malaysia)
268.2698 +display locale: ID: ms_MY, Name: Malay (Malaysia)
268.2699 +format locale: ID: ms_MY, Name: Malay (Malaysia)
268.2700 +default charset: UTF-8
268.2701 +
268.2702 +OS Locale:  mt_MT
268.2703 +default locale: ID: mt_MT, Name: Maltese (Malta)
268.2704 +display locale: ID: mt_MT, Name: Maltese (Malta)
268.2705 +format locale: ID: mt_MT, Name: Maltese (Malta)
268.2706 +default charset: ISO-8859-3
268.2707 +
268.2708 +OS Locale:  mt_MT.iso88593
268.2709 +default locale: ID: mt_MT, Name: Maltese (Malta)
268.2710 +display locale: ID: mt_MT, Name: Maltese (Malta)
268.2711 +format locale: ID: mt_MT, Name: Maltese (Malta)
268.2712 +default charset: ISO-8859-3
268.2713 +
268.2714 +OS Locale:  mt_MT.utf8
268.2715 +default locale: ID: mt_MT, Name: Maltese (Malta)
268.2716 +display locale: ID: mt_MT, Name: Maltese (Malta)
268.2717 +format locale: ID: mt_MT, Name: Maltese (Malta)
268.2718 +default charset: UTF-8
268.2719 +
268.2720 +OS Locale:  nb_NO
268.2721 +default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2722 +display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2723 +format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2724 +default charset: ISO-8859-1
268.2725 +
268.2726 +OS Locale:  nb_NO.iso88591
268.2727 +default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2728 +display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2729 +format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2730 +default charset: ISO-8859-1
268.2731 +
268.2732 +OS Locale:  nb_NO.utf8
268.2733 +default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2734 +display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2735 +format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
268.2736 +default charset: UTF-8
268.2737 +
268.2738 +OS Locale:  ne_NP
268.2739 +default locale: ID: ne_NP, Name: Nepali (Nepal)
268.2740 +display locale: ID: ne_NP, Name: Nepali (Nepal)
268.2741 +format locale: ID: ne_NP, Name: Nepali (Nepal)
268.2742 +default charset: UTF-8
268.2743 +
268.2744 +OS Locale:  ne_NP.utf8
268.2745 +default locale: ID: ne_NP, Name: Nepali (Nepal)
268.2746 +display locale: ID: ne_NP, Name: Nepali (Nepal)
268.2747 +format locale: ID: ne_NP, Name: Nepali (Nepal)
268.2748 +default charset: UTF-8
268.2749 +
268.2750 +OS Locale:  nl_BE
268.2751 +default locale: ID: nl_BE, Name: Dutch (Belgium)
268.2752 +display locale: ID: nl_BE, Name: Dutch (Belgium)
268.2753 +format locale: ID: nl_BE, Name: Dutch (Belgium)
268.2754 +default charset: ISO-8859-1
268.2755 +
268.2756 +OS Locale:  nl_BE.iso88591
268.2757 +default locale: ID: nl_BE, Name: Dutch (Belgium)
268.2758 +display locale: ID: nl_BE, Name: Dutch (Belgium)
268.2759 +format locale: ID: nl_BE, Name: Dutch (Belgium)
268.2760 +default charset: ISO-8859-1
268.2761 +
268.2762 +OS Locale:  nl_BE.iso885915@euro
268.2763 +default locale: ID: nl_BE, Name: Dutch (Belgium)
268.2764 +display locale: ID: nl_BE, Name: Dutch (Belgium)
268.2765 +format locale: ID: nl_BE, Name: Dutch (Belgium)
268.2766 +default charset: ISO-8859-15
268.2767 +
268.2768 +OS Locale:  nl_BE.utf8
268.2769 +default locale: ID: nl_BE, Name: Dutch (Belgium)
268.2770 +display locale: ID: nl_BE, Name: Dutch (Belgium)
268.2771 +format locale: ID: nl_BE, Name: Dutch (Belgium)
268.2772 +default charset: UTF-8
268.2773 +
268.2774 +OS Locale:  nl_BE@euro
268.2775 +default locale: ID: nl_BE, Name: Dutch (Belgium)
268.2776 +display locale: ID: nl_BE, Name: Dutch (Belgium)
268.2777 +format locale: ID: nl_BE, Name: Dutch (Belgium)
268.2778 +default charset: ISO-8859-15
268.2779 +
268.2780 +OS Locale:  nl_NL
268.2781 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2782 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2783 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2784 +default charset: ISO-8859-1
268.2785 +
268.2786 +OS Locale:  nl_NL.iso88591
268.2787 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2788 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2789 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2790 +default charset: ISO-8859-1
268.2791 +
268.2792 +OS Locale:  nl_NL.iso885915@euro
268.2793 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2794 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2795 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2796 +default charset: ISO-8859-15
268.2797 +
268.2798 +OS Locale:  nl_NL.utf8
268.2799 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2800 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2801 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2802 +default charset: UTF-8
268.2803 +
268.2804 +OS Locale:  nl_NL@euro
268.2805 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2806 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2807 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
268.2808 +default charset: ISO-8859-15
268.2809 +
268.2810 +OS Locale:  nn_NO
268.2811 +default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2812 +display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2813 +format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2814 +default charset: ISO-8859-1
268.2815 +
268.2816 +OS Locale:  nn_NO.iso88591
268.2817 +default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2818 +display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2819 +format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2820 +default charset: ISO-8859-1
268.2821 +
268.2822 +OS Locale:  nn_NO.utf8
268.2823 +default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2824 +display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2825 +format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
268.2826 +default charset: UTF-8
268.2827 +
268.2828 +OS Locale:  no_NO
268.2829 +default locale: ID: no_NO, Name: Norwegian (Norway)
268.2830 +display locale: ID: no_NO, Name: Norwegian (Norway)
268.2831 +format locale: ID: no_NO, Name: Norwegian (Norway)
268.2832 +default charset: ISO-8859-1
268.2833 +
268.2834 +OS Locale:  no_NO.iso88591
268.2835 +default locale: ID: no_NO, Name: Norwegian (Norway)
268.2836 +display locale: ID: no_NO, Name: Norwegian (Norway)
268.2837 +format locale: ID: no_NO, Name: Norwegian (Norway)
268.2838 +default charset: ISO-8859-1
268.2839 +
268.2840 +OS Locale:  no_NO.utf8
268.2841 +default locale: ID: no_NO, Name: Norwegian (Norway)
268.2842 +display locale: ID: no_NO, Name: Norwegian (Norway)
268.2843 +format locale: ID: no_NO, Name: Norwegian (Norway)
268.2844 +default charset: UTF-8
268.2845 +
268.2846 +OS Locale:  norwegian
268.2847 +default locale: ID: no_NO, Name: Norwegian (Norway)
268.2848 +display locale: ID: no_NO, Name: Norwegian (Norway)
268.2849 +format locale: ID: no_NO, Name: Norwegian (Norway)
268.2850 +default charset: ISO-8859-1
268.2851 +
268.2852 +OS Locale:  nr_ZA
268.2853 +default locale: ID: nr_ZA, Name: South Ndebele (South Africa)
268.2854 +display locale: ID: nr_ZA, Name: South Ndebele (South Africa)
268.2855 +format locale: ID: nr_ZA, Name: South Ndebele (South Africa)
268.2856 +default charset: UTF-8
268.2857 +
268.2858 +OS Locale:  nr_ZA.utf8
268.2859 +default locale: ID: nr_ZA, Name: South Ndebele (South Africa)
268.2860 +display locale: ID: nr_ZA, Name: South Ndebele (South Africa)
268.2861 +format locale: ID: nr_ZA, Name: South Ndebele (South Africa)
268.2862 +default charset: UTF-8
268.2863 +
268.2864 +OS Locale:  nso_ZA
268.2865 +default locale: ID: en_ZA, Name: English (South Africa)
268.2866 +display locale: ID: en_ZA, Name: English (South Africa)
268.2867 +format locale: ID: en_ZA, Name: English (South Africa)
268.2868 +default charset: UTF-8
268.2869 +
268.2870 +OS Locale:  nso_ZA.utf8
268.2871 +default locale: ID: en_ZA, Name: English (South Africa)
268.2872 +display locale: ID: en_ZA, Name: English (South Africa)
268.2873 +format locale: ID: en_ZA, Name: English (South Africa)
268.2874 +default charset: UTF-8
268.2875 +
268.2876 +OS Locale:  nynorsk
268.2877 +default locale: ID: en, Name: English
268.2878 +display locale: ID: en, Name: English
268.2879 +format locale: ID: en, Name: English
268.2880 +default charset: ISO-8859-1
268.2881 +
268.2882 +OS Locale:  oc_FR
268.2883 +default locale: ID: oc_FR, Name: Occitan (France)
268.2884 +display locale: ID: oc_FR, Name: Occitan (France)
268.2885 +format locale: ID: oc_FR, Name: Occitan (France)
268.2886 +default charset: ISO-8859-1
268.2887 +
268.2888 +OS Locale:  oc_FR.iso88591
268.2889 +default locale: ID: oc_FR, Name: Occitan (France)
268.2890 +display locale: ID: oc_FR, Name: Occitan (France)
268.2891 +format locale: ID: oc_FR, Name: Occitan (France)
268.2892 +default charset: ISO-8859-1
268.2893 +
268.2894 +OS Locale:  oc_FR.utf8
268.2895 +default locale: ID: oc_FR, Name: Occitan (France)
268.2896 +display locale: ID: oc_FR, Name: Occitan (France)
268.2897 +format locale: ID: oc_FR, Name: Occitan (France)
268.2898 +default charset: UTF-8
268.2899 +
268.2900 +OS Locale:  om_ET
268.2901 +default locale: ID: om_ET, Name: Oromo (Ethiopia)
268.2902 +display locale: ID: om_ET, Name: Oromo (Ethiopia)
268.2903 +format locale: ID: om_ET, Name: Oromo (Ethiopia)
268.2904 +default charset: UTF-8
268.2905 +
268.2906 +OS Locale:  om_ET.utf8
268.2907 +default locale: ID: om_ET, Name: Oromo (Ethiopia)
268.2908 +display locale: ID: om_ET, Name: Oromo (Ethiopia)
268.2909 +format locale: ID: om_ET, Name: Oromo (Ethiopia)
268.2910 +default charset: UTF-8
268.2911 +
268.2912 +OS Locale:  om_KE
268.2913 +default locale: ID: om_KE, Name: Oromo (Kenya)
268.2914 +display locale: ID: om_KE, Name: Oromo (Kenya)
268.2915 +format locale: ID: om_KE, Name: Oromo (Kenya)
268.2916 +default charset: ISO-8859-1
268.2917 +
268.2918 +OS Locale:  om_KE.iso88591
268.2919 +default locale: ID: om_KE, Name: Oromo (Kenya)
268.2920 +display locale: ID: om_KE, Name: Oromo (Kenya)
268.2921 +format locale: ID: om_KE, Name: Oromo (Kenya)
268.2922 +default charset: ISO-8859-1
268.2923 +
268.2924 +OS Locale:  om_KE.utf8
268.2925 +default locale: ID: om_KE, Name: Oromo (Kenya)
268.2926 +display locale: ID: om_KE, Name: Oromo (Kenya)
268.2927 +format locale: ID: om_KE, Name: Oromo (Kenya)
268.2928 +default charset: UTF-8
268.2929 +
268.2930 +OS Locale:  or_IN
268.2931 +default locale: ID: or_IN, Name: Oriya (India)
268.2932 +display locale: ID: or_IN, Name: Oriya (India)
268.2933 +format locale: ID: or_IN, Name: Oriya (India)
268.2934 +default charset: UTF-8
268.2935 +
268.2936 +OS Locale:  or_IN.utf8
268.2937 +default locale: ID: or_IN, Name: Oriya (India)
268.2938 +display locale: ID: or_IN, Name: Oriya (India)
268.2939 +format locale: ID: or_IN, Name: Oriya (India)
268.2940 +default charset: UTF-8
268.2941 +
268.2942 +OS Locale:  pa_IN
268.2943 +default locale: ID: pa_IN, Name: Panjabi (India)
268.2944 +display locale: ID: pa_IN, Name: Panjabi (India)
268.2945 +format locale: ID: pa_IN, Name: Panjabi (India)
268.2946 +default charset: UTF-8
268.2947 +
268.2948 +OS Locale:  pa_IN.utf8
268.2949 +default locale: ID: pa_IN, Name: Panjabi (India)
268.2950 +display locale: ID: pa_IN, Name: Panjabi (India)
268.2951 +format locale: ID: pa_IN, Name: Panjabi (India)
268.2952 +default charset: UTF-8
268.2953 +
268.2954 +OS Locale:  pa_PK
268.2955 +default locale: ID: pa_PK, Name: Panjabi (Pakistan)
268.2956 +display locale: ID: pa_PK, Name: Panjabi (Pakistan)
268.2957 +format locale: ID: pa_PK, Name: Panjabi (Pakistan)
268.2958 +default charset: UTF-8
268.2959 +
268.2960 +OS Locale:  pa_PK.utf8
268.2961 +default locale: ID: pa_PK, Name: Panjabi (Pakistan)
268.2962 +display locale: ID: pa_PK, Name: Panjabi (Pakistan)
268.2963 +format locale: ID: pa_PK, Name: Panjabi (Pakistan)
268.2964 +default charset: UTF-8
268.2965 +
268.2966 +OS Locale:  pl_PL
268.2967 +default locale: ID: pl_PL, Name: Polish (Poland)
268.2968 +display locale: ID: pl_PL, Name: Polish (Poland)
268.2969 +format locale: ID: pl_PL, Name: Polish (Poland)
268.2970 +default charset: ISO-8859-2
268.2971 +
268.2972 +OS Locale:  pl_PL.iso88592
268.2973 +default locale: ID: pl_PL, Name: Polish (Poland)
268.2974 +display locale: ID: pl_PL, Name: Polish (Poland)
268.2975 +format locale: ID: pl_PL, Name: Polish (Poland)
268.2976 +default charset: ISO-8859-2
268.2977 +
268.2978 +OS Locale:  pl_PL.utf8
268.2979 +default locale: ID: pl_PL, Name: Polish (Poland)
268.2980 +display locale: ID: pl_PL, Name: Polish (Poland)
268.2981 +format locale: ID: pl_PL, Name: Polish (Poland)
268.2982 +default charset: UTF-8
268.2983 +
268.2984 +OS Locale:  polish
268.2985 +default locale: ID: pl_PL, Name: Polish (Poland)
268.2986 +display locale: ID: pl_PL, Name: Polish (Poland)
268.2987 +format locale: ID: pl_PL, Name: Polish (Poland)
268.2988 +default charset: ISO-8859-2
268.2989 +
268.2990 +OS Locale:  portuguese
268.2991 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
268.2992 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
268.2993 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
268.2994 +default charset: ISO-8859-1
268.2995 +
268.2996 +OS Locale:  pt_BR
268.2997 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
268.2998 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
268.2999 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
268.3000 +default charset: ISO-8859-1
268.3001 +
268.3002 +OS Locale:  pt_BR.iso88591
268.3003 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
268.3004 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
268.3005 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
268.3006 +default charset: ISO-8859-1
268.3007 +
268.3008 +OS Locale:  pt_BR.utf8
268.3009 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
268.3010 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
268.3011 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
268.3012 +default charset: UTF-8
268.3013 +
268.3014 +OS Locale:  pt_PT
268.3015 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3016 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3017 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3018 +default charset: ISO-8859-1
268.3019 +
268.3020 +OS Locale:  pt_PT.iso88591
268.3021 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3022 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3023 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3024 +default charset: ISO-8859-1
268.3025 +
268.3026 +OS Locale:  pt_PT.iso885915@euro
268.3027 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3028 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3029 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3030 +default charset: ISO-8859-15
268.3031 +
268.3032 +OS Locale:  pt_PT.utf8
268.3033 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3034 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3035 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3036 +default charset: UTF-8
268.3037 +
268.3038 +OS Locale:  pt_PT@euro
268.3039 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3040 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3041 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
268.3042 +default charset: ISO-8859-15
268.3043 +
268.3044 +OS Locale:  ro_RO
268.3045 +default locale: ID: ro_RO, Name: Romanian (Romania)
268.3046 +display locale: ID: ro_RO, Name: Romanian (Romania)
268.3047 +format locale: ID: ro_RO, Name: Romanian (Romania)
268.3048 +default charset: ISO-8859-2
268.3049 +
268.3050 +OS Locale:  ro_RO.iso88592
268.3051 +default locale: ID: ro_RO, Name: Romanian (Romania)
268.3052 +display locale: ID: ro_RO, Name: Romanian (Romania)
268.3053 +format locale: ID: ro_RO, Name: Romanian (Romania)
268.3054 +default charset: ISO-8859-2
268.3055 +
268.3056 +OS Locale:  ro_RO.utf8
268.3057 +default locale: ID: ro_RO, Name: Romanian (Romania)
268.3058 +display locale: ID: ro_RO, Name: Romanian (Romania)
268.3059 +format locale: ID: ro_RO, Name: Romanian (Romania)
268.3060 +default charset: UTF-8
268.3061 +
268.3062 +OS Locale:  romanian
268.3063 +default locale: ID: ro_RO, Name: Romanian (Romania)
268.3064 +display locale: ID: ro_RO, Name: Romanian (Romania)
268.3065 +format locale: ID: ro_RO, Name: Romanian (Romania)
268.3066 +default charset: ISO-8859-2
268.3067 +
268.3068 +OS Locale:  ru_RU
268.3069 +default locale: ID: ru_RU, Name: Russian (Russia)
268.3070 +display locale: ID: ru_RU, Name: Russian (Russia)
268.3071 +format locale: ID: ru_RU, Name: Russian (Russia)
268.3072 +default charset: ISO-8859-5
268.3073 +
268.3074 +OS Locale:  ru_RU.iso88595
268.3075 +default locale: ID: ru_RU, Name: Russian (Russia)
268.3076 +display locale: ID: ru_RU, Name: Russian (Russia)
268.3077 +format locale: ID: ru_RU, Name: Russian (Russia)
268.3078 +default charset: ISO-8859-5
268.3079 +
268.3080 +OS Locale:  ru_RU.koi8r
268.3081 +default locale: ID: ru_RU, Name: Russian (Russia)
268.3082 +display locale: ID: ru_RU, Name: Russian (Russia)
268.3083 +format locale: ID: ru_RU, Name: Russian (Russia)
268.3084 +default charset: KOI8-R
268.3085 +
268.3086 +OS Locale:  ru_RU.utf8
268.3087 +default locale: ID: ru_RU, Name: Russian (Russia)
268.3088 +display locale: ID: ru_RU, Name: Russian (Russia)
268.3089 +format locale: ID: ru_RU, Name: Russian (Russia)
268.3090 +default charset: UTF-8
268.3091 +
268.3092 +OS Locale:  ru_UA
268.3093 +default locale: ID: ru_UA, Name: Russian (Ukraine)
268.3094 +display locale: ID: ru_UA, Name: Russian (Ukraine)
268.3095 +format locale: ID: ru_UA, Name: Russian (Ukraine)
268.3096 +default charset: KOI8-U
268.3097 +
268.3098 +OS Locale:  ru_UA.koi8u
268.3099 +default locale: ID: ru_UA, Name: Russian (Ukraine)
268.3100 +display locale: ID: ru_UA, Name: Russian (Ukraine)
268.3101 +format locale: ID: ru_UA, Name: Russian (Ukraine)
268.3102 +default charset: KOI8-U
268.3103 +
268.3104 +OS Locale:  ru_UA.utf8
268.3105 +default locale: ID: ru_UA, Name: Russian (Ukraine)
268.3106 +display locale: ID: ru_UA, Name: Russian (Ukraine)
268.3107 +format locale: ID: ru_UA, Name: Russian (Ukraine)
268.3108 +default charset: UTF-8
268.3109 +
268.3110 +OS Locale:  russian
268.3111 +default locale: ID: ru_RU, Name: Russian (Russia)
268.3112 +display locale: ID: ru_RU, Name: Russian (Russia)
268.3113 +format locale: ID: ru_RU, Name: Russian (Russia)
268.3114 +default charset: ISO-8859-5
268.3115 +
268.3116 +OS Locale:  rw_RW
268.3117 +default locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
268.3118 +display locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
268.3119 +format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
268.3120 +default charset: UTF-8
268.3121 +
268.3122 +OS Locale:  rw_RW.utf8
268.3123 +default locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
268.3124 +display locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
268.3125 +format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
268.3126 +default charset: UTF-8
268.3127 +
268.3128 +OS Locale:  se_NO
268.3129 +default locale: ID: se_NO, Name: Northern Sami (Norway)
268.3130 +display locale: ID: se_NO, Name: Northern Sami (Norway)
268.3131 +format locale: ID: se_NO, Name: Northern Sami (Norway)
268.3132 +default charset: UTF-8
268.3133 +
268.3134 +OS Locale:  se_NO.utf8
268.3135 +default locale: ID: se_NO, Name: Northern Sami (Norway)
268.3136 +display locale: ID: se_NO, Name: Northern Sami (Norway)
268.3137 +format locale: ID: se_NO, Name: Northern Sami (Norway)
268.3138 +default charset: UTF-8
268.3139 +
268.3140 +OS Locale:  si_LK
268.3141 +default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
268.3142 +display locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
268.3143 +format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
268.3144 +default charset: UTF-8
268.3145 +
268.3146 +OS Locale:  si_LK.utf8
268.3147 +default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
268.3148 +display locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
268.3149 +format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
268.3150 +default charset: UTF-8
268.3151 +
268.3152 +OS Locale:  sid_ET
268.3153 +default locale: ID: en_ET, Name: English (Ethiopia)
268.3154 +display locale: ID: en_ET, Name: English (Ethiopia)
268.3155 +format locale: ID: en_ET, Name: English (Ethiopia)
268.3156 +default charset: UTF-8
268.3157 +
268.3158 +OS Locale:  sid_ET.utf8
268.3159 +default locale: ID: en_ET, Name: English (Ethiopia)
268.3160 +display locale: ID: en_ET, Name: English (Ethiopia)
268.3161 +format locale: ID: en_ET, Name: English (Ethiopia)
268.3162 +default charset: UTF-8
268.3163 +
268.3164 +OS Locale:  sk_SK
268.3165 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3166 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3167 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3168 +default charset: ISO-8859-2
268.3169 +
268.3170 +OS Locale:  sk_SK.iso88592
268.3171 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3172 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3173 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3174 +default charset: ISO-8859-2
268.3175 +
268.3176 +OS Locale:  sk_SK.utf8
268.3177 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3178 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3179 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3180 +default charset: UTF-8
268.3181 +
268.3182 +OS Locale:  sl_SI
268.3183 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3184 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3185 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3186 +default charset: ISO-8859-2
268.3187 +
268.3188 +OS Locale:  sl_SI.iso88592
268.3189 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3190 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3191 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3192 +default charset: ISO-8859-2
268.3193 +
268.3194 +OS Locale:  sl_SI.utf8
268.3195 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3196 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3197 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3198 +default charset: UTF-8
268.3199 +
268.3200 +OS Locale:  slovak
268.3201 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3202 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3203 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
268.3204 +default charset: ISO-8859-2
268.3205 +
268.3206 +OS Locale:  slovene
268.3207 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3208 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3209 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3210 +default charset: ISO-8859-2
268.3211 +
268.3212 +OS Locale:  slovenian
268.3213 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3214 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3215 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
268.3216 +default charset: ISO-8859-2
268.3217 +
268.3218 +OS Locale:  so_DJ
268.3219 +default locale: ID: so_DJ, Name: Somali (Djibouti)
268.3220 +display locale: ID: so_DJ, Name: Somali (Djibouti)
268.3221 +format locale: ID: so_DJ, Name: Somali (Djibouti)
268.3222 +default charset: ISO-8859-1
268.3223 +
268.3224 +OS Locale:  so_DJ.iso88591
268.3225 +default locale: ID: so_DJ, Name: Somali (Djibouti)
268.3226 +display locale: ID: so_DJ, Name: Somali (Djibouti)
268.3227 +format locale: ID: so_DJ, Name: Somali (Djibouti)
268.3228 +default charset: ISO-8859-1
268.3229 +
268.3230 +OS Locale:  so_DJ.utf8
268.3231 +default locale: ID: so_DJ, Name: Somali (Djibouti)
268.3232 +display locale: ID: so_DJ, Name: Somali (Djibouti)
268.3233 +format locale: ID: so_DJ, Name: Somali (Djibouti)
268.3234 +default charset: UTF-8
268.3235 +
268.3236 +OS Locale:  so_ET
268.3237 +default locale: ID: so_ET, Name: Somali (Ethiopia)
268.3238 +display locale: ID: so_ET, Name: Somali (Ethiopia)
268.3239 +format locale: ID: so_ET, Name: Somali (Ethiopia)
268.3240 +default charset: UTF-8
268.3241 +
268.3242 +OS Locale:  so_ET.utf8
268.3243 +default locale: ID: so_ET, Name: Somali (Ethiopia)
268.3244 +display locale: ID: so_ET, Name: Somali (Ethiopia)
268.3245 +format locale: ID: so_ET, Name: Somali (Ethiopia)
268.3246 +default charset: UTF-8
268.3247 +
268.3248 +OS Locale:  so_KE
268.3249 +default locale: ID: so_KE, Name: Somali (Kenya)
268.3250 +display locale: ID: so_KE, Name: Somali (Kenya)
268.3251 +format locale: ID: so_KE, Name: Somali (Kenya)
268.3252 +default charset: ISO-8859-1
268.3253 +
268.3254 +OS Locale:  so_KE.iso88591
268.3255 +default locale: ID: so_KE, Name: Somali (Kenya)
268.3256 +display locale: ID: so_KE, Name: Somali (Kenya)
268.3257 +format locale: ID: so_KE, Name: Somali (Kenya)
268.3258 +default charset: ISO-8859-1
268.3259 +
268.3260 +OS Locale:  so_KE.utf8
268.3261 +default locale: ID: so_KE, Name: Somali (Kenya)
268.3262 +display locale: ID: so_KE, Name: Somali (Kenya)
268.3263 +format locale: ID: so_KE, Name: Somali (Kenya)
268.3264 +default charset: UTF-8
268.3265 +
268.3266 +OS Locale:  so_SO
268.3267 +default locale: ID: so_SO, Name: Somali (Somalia)
268.3268 +display locale: ID: so_SO, Name: Somali (Somalia)
268.3269 +format locale: ID: so_SO, Name: Somali (Somalia)
268.3270 +default charset: ISO-8859-1
268.3271 +
268.3272 +OS Locale:  so_SO.iso88591
268.3273 +default locale: ID: so_SO, Name: Somali (Somalia)
268.3274 +display locale: ID: so_SO, Name: Somali (Somalia)
268.3275 +format locale: ID: so_SO, Name: Somali (Somalia)
268.3276 +default charset: ISO-8859-1
268.3277 +
268.3278 +OS Locale:  so_SO.utf8
268.3279 +default locale: ID: so_SO, Name: Somali (Somalia)
268.3280 +display locale: ID: so_SO, Name: Somali (Somalia)
268.3281 +format locale: ID: so_SO, Name: Somali (Somalia)
268.3282 +default charset: UTF-8
268.3283 +
268.3284 +OS Locale:  spanish
268.3285 +default locale: ID: es_ES, Name: Spanish (Spain)
268.3286 +display locale: ID: es_ES, Name: Spanish (Spain)
268.3287 +format locale: ID: es_ES, Name: Spanish (Spain)
268.3288 +default charset: ISO-8859-1
268.3289 +
268.3290 +OS Locale:  sq_AL
268.3291 +default locale: ID: sq_AL, Name: Albanian (Albania)
268.3292 +display locale: ID: sq_AL, Name: Albanian (Albania)
268.3293 +format locale: ID: sq_AL, Name: Albanian (Albania)
268.3294 +default charset: ISO-8859-1
268.3295 +
268.3296 +OS Locale:  sq_AL.iso88591
268.3297 +default locale: ID: sq_AL, Name: Albanian (Albania)
268.3298 +display locale: ID: sq_AL, Name: Albanian (Albania)
268.3299 +format locale: ID: sq_AL, Name: Albanian (Albania)
268.3300 +default charset: ISO-8859-1
268.3301 +
268.3302 +OS Locale:  sq_AL.utf8
268.3303 +default locale: ID: sq_AL, Name: Albanian (Albania)
268.3304 +display locale: ID: sq_AL, Name: Albanian (Albania)
268.3305 +format locale: ID: sq_AL, Name: Albanian (Albania)
268.3306 +default charset: UTF-8
268.3307 +
268.3308 +OS Locale:  sr_CS
268.3309 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3310 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3311 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3312 +default charset: ISO-8859-5
268.3313 +
268.3314 +OS Locale:  sr_CS.iso88595
268.3315 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3316 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3317 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3318 +default charset: ISO-8859-5
268.3319 +
268.3320 +OS Locale:  sr_CS.utf8
268.3321 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3322 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3323 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
268.3324 +default charset: UTF-8
268.3325 +
268.3326 +OS Locale:  sr_ME
268.3327 +default locale: ID: sr, Name: Serbian
268.3328 +display locale: ID: sr, Name: Serbian
268.3329 +format locale: ID: sr, Name: Serbian
268.3330 +default charset: UTF-8
268.3331 +
268.3332 +OS Locale:  sr_ME.utf8
268.3333 +default locale: ID: sr, Name: Serbian
268.3334 +display locale: ID: sr, Name: Serbian
268.3335 +format locale: ID: sr, Name: Serbian
268.3336 +default charset: UTF-8
268.3337 +
268.3338 +OS Locale:  sr_RS
268.3339 +default locale: ID: sr, Name: Serbian
268.3340 +display locale: ID: sr, Name: Serbian
268.3341 +format locale: ID: sr, Name: Serbian
268.3342 +default charset: UTF-8
268.3343 +
268.3344 +OS Locale:  sr_RS.utf8
268.3345 +default locale: ID: sr, Name: Serbian
268.3346 +display locale: ID: sr, Name: Serbian
268.3347 +format locale: ID: sr, Name: Serbian
268.3348 +default charset: UTF-8
268.3349 +
268.3350 +OS Locale:  sr_RS.utf8@latin
268.3351 +default locale: ID: sr, Name: Serbian
268.3352 +display locale: ID: sr, Name: Serbian
268.3353 +format locale: ID: sr, Name: Serbian
268.3354 +default charset: UTF-8
268.3355 +
268.3356 +OS Locale:  sr_RS@latin
268.3357 +default locale: ID: sr, Name: Serbian
268.3358 +display locale: ID: sr, Name: Serbian
268.3359 +format locale: ID: sr, Name: Serbian
268.3360 +default charset: UTF-8
268.3361 +
268.3362 +OS Locale:  ss_ZA
268.3363 +default locale: ID: ss_ZA, Name: Swati (South Africa)
268.3364 +display locale: ID: ss_ZA, Name: Swati (South Africa)
268.3365 +format locale: ID: ss_ZA, Name: Swati (South Africa)
268.3366 +default charset: UTF-8
268.3367 +
268.3368 +OS Locale:  ss_ZA.utf8
268.3369 +default locale: ID: ss_ZA, Name: Swati (South Africa)
268.3370 +display locale: ID: ss_ZA, Name: Swati (South Africa)
268.3371 +format locale: ID: ss_ZA, Name: Swati (South Africa)
268.3372 +default charset: UTF-8
268.3373 +
268.3374 +OS Locale:  st_ZA
268.3375 +default locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3376 +display locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3377 +format locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3378 +default charset: ISO-8859-1
268.3379 +
268.3380 +OS Locale:  st_ZA.iso88591
268.3381 +default locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3382 +display locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3383 +format locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3384 +default charset: ISO-8859-1
268.3385 +
268.3386 +OS Locale:  st_ZA.utf8
268.3387 +default locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3388 +display locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3389 +format locale: ID: st_ZA, Name: Southern Sotho (South Africa)
268.3390 +default charset: UTF-8
268.3391 +
268.3392 +OS Locale:  sv_FI
268.3393 +default locale: ID: sv_FI, Name: Swedish (Finland)
268.3394 +display locale: ID: sv_FI, Name: Swedish (Finland)
268.3395 +format locale: ID: sv_FI, Name: Swedish (Finland)
268.3396 +default charset: ISO-8859-1
268.3397 +
268.3398 +OS Locale:  sv_FI.iso88591
268.3399 +default locale: ID: sv_FI, Name: Swedish (Finland)
268.3400 +display locale: ID: sv_FI, Name: Swedish (Finland)
268.3401 +format locale: ID: sv_FI, Name: Swedish (Finland)
268.3402 +default charset: ISO-8859-1
268.3403 +
268.3404 +OS Locale:  sv_FI.iso885915@euro
268.3405 +default locale: ID: sv_FI, Name: Swedish (Finland)
268.3406 +display locale: ID: sv_FI, Name: Swedish (Finland)
268.3407 +format locale: ID: sv_FI, Name: Swedish (Finland)
268.3408 +default charset: ISO-8859-15
268.3409 +
268.3410 +OS Locale:  sv_FI.utf8
268.3411 +default locale: ID: sv_FI, Name: Swedish (Finland)
268.3412 +display locale: ID: sv_FI, Name: Swedish (Finland)
268.3413 +format locale: ID: sv_FI, Name: Swedish (Finland)
268.3414 +default charset: UTF-8
268.3415 +
268.3416 +OS Locale:  sv_FI@euro
268.3417 +default locale: ID: sv_FI, Name: Swedish (Finland)
268.3418 +display locale: ID: sv_FI, Name: Swedish (Finland)
268.3419 +format locale: ID: sv_FI, Name: Swedish (Finland)
268.3420 +default charset: ISO-8859-15
268.3421 +
268.3422 +OS Locale:  sv_SE
268.3423 +default locale: ID: sv_SE, Name: Swedish (Sweden)
268.3424 +display locale: ID: sv_SE, Name: Swedish (Sweden)
268.3425 +format locale: ID: sv_SE, Name: Swedish (Sweden)
268.3426 +default charset: ISO-8859-1
268.3427 +
268.3428 +OS Locale:  sv_SE.iso88591
268.3429 +default locale: ID: sv_SE, Name: Swedish (Sweden)
268.3430 +display locale: ID: sv_SE, Name: Swedish (Sweden)
268.3431 +format locale: ID: sv_SE, Name: Swedish (Sweden)
268.3432 +default charset: ISO-8859-1
268.3433 +
268.3434 +OS Locale:  sv_SE.iso885915
268.3435 +default locale: ID: sv_SE, Name: Swedish (Sweden)
268.3436 +display locale: ID: sv_SE, Name: Swedish (Sweden)
268.3437 +format locale: ID: sv_SE, Name: Swedish (Sweden)
268.3438 +default charset: ISO-8859-15
268.3439 +
268.3440 +OS Locale:  sv_SE.utf8
268.3441 +default locale: ID: sv_SE, Name: Swedish (Sweden)
268.3442 +display locale: ID: sv_SE, Name: Swedish (Sweden)
268.3443 +format locale: ID: sv_SE, Name: Swedish (Sweden)
268.3444 +default charset: UTF-8
268.3445 +
268.3446 +OS Locale:  swedish
268.3447 +default locale: ID: sv_SE, Name: Swedish (Sweden)
268.3448 +display locale: ID: sv_SE, Name: Swedish (Sweden)
268.3449 +format locale: ID: sv_SE, Name: Swedish (Sweden)
268.3450 +default charset: ISO-8859-1
268.3451 +
268.3452 +OS Locale:  ta_IN
268.3453 +default locale: ID: ta_IN, Name: Tamil (India)
268.3454 +display locale: ID: ta_IN, Name: Tamil (India)
268.3455 +format locale: ID: ta_IN, Name: Tamil (India)
268.3456 +default charset: UTF-8
268.3457 +
268.3458 +OS Locale:  ta_IN.utf8
268.3459 +default locale: ID: ta_IN, Name: Tamil (India)
268.3460 +display locale: ID: ta_IN, Name: Tamil (India)
268.3461 +format locale: ID: ta_IN, Name: Tamil (India)
268.3462 +default charset: UTF-8
268.3463 +
268.3464 +OS Locale:  te_IN
268.3465 +default locale: ID: te_IN, Name: Telugu (India)
268.3466 +display locale: ID: te_IN, Name: Telugu (India)
268.3467 +format locale: ID: te_IN, Name: Telugu (India)
268.3468 +default charset: UTF-8
268.3469 +
268.3470 +OS Locale:  te_IN.utf8
268.3471 +default locale: ID: te_IN, Name: Telugu (India)
268.3472 +display locale: ID: te_IN, Name: Telugu (India)
268.3473 +format locale: ID: te_IN, Name: Telugu (India)
268.3474 +default charset: UTF-8
268.3475 +
268.3476 +OS Locale:  tg_TJ
268.3477 +default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3478 +display locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3479 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3480 +default charset: UTF-8
268.3481 +
268.3482 +OS Locale:  tg_TJ.koi8t
268.3483 +default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3484 +display locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3485 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3486 +default charset: UTF-8
268.3487 +
268.3488 +OS Locale:  tg_TJ.utf8
268.3489 +default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3490 +display locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3491 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
268.3492 +default charset: UTF-8
268.3493 +
268.3494 +OS Locale:  th_TH
268.3495 +default locale: ID: th_TH, Name: Thai (Thailand)
268.3496 +display locale: ID: th_TH, Name: Thai (Thailand)
268.3497 +format locale: ID: th_TH, Name: Thai (Thailand)
268.3498 +default charset: TIS-620
268.3499 +
268.3500 +OS Locale:  th_TH.tis620
268.3501 +default locale: ID: th_TH, Name: Thai (Thailand)
268.3502 +display locale: ID: th_TH, Name: Thai (Thailand)
268.3503 +format locale: ID: th_TH, Name: Thai (Thailand)
268.3504 +default charset: TIS-620
268.3505 +
268.3506 +OS Locale:  th_TH.utf8
268.3507 +default locale: ID: th_TH, Name: Thai (Thailand)
268.3508 +display locale: ID: th_TH, Name: Thai (Thailand)
268.3509 +format locale: ID: th_TH, Name: Thai (Thailand)
268.3510 +default charset: UTF-8
268.3511 +
268.3512 +OS Locale:  thai
268.3513 +default locale: ID: en, Name: English
268.3514 +display locale: ID: en, Name: English
268.3515 +format locale: ID: en, Name: English
268.3516 +default charset: TIS-620
268.3517 +
268.3518 +OS Locale:  ti_ER
268.3519 +default locale: ID: ti_ER, Name: Tigrinya (Eritrea)
268.3520 +display locale: ID: ti_ER, Name: Tigrinya (Eritrea)
268.3521 +format locale: ID: ti_ER, Name: Tigrinya (Eritrea)
268.3522 +default charset: UTF-8
268.3523 +
268.3524 +OS Locale:  ti_ER.utf8
268.3525 +default locale: ID: ti_ER, Name: Tigrinya (Eritrea)
268.3526 +display locale: ID: ti_ER, Name: Tigrinya (Eritrea)
268.3527 +format locale: ID: ti_ER, Name: Tigrinya (Eritrea)
268.3528 +default charset: UTF-8
268.3529 +
268.3530 +OS Locale:  ti_ET
268.3531 +default locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
268.3532 +display locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
268.3533 +format locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
268.3534 +default charset: UTF-8
268.3535 +
268.3536 +OS Locale:  ti_ET.utf8
268.3537 +default locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
268.3538 +display locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
268.3539 +format locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
268.3540 +default charset: UTF-8
268.3541 +
268.3542 +OS Locale:  tig_ER
268.3543 +default locale: ID: en_ER, Name: English (Eritrea)
268.3544 +display locale: ID: en_ER, Name: English (Eritrea)
268.3545 +format locale: ID: en_ER, Name: English (Eritrea)
268.3546 +default charset: UTF-8
268.3547 +
268.3548 +OS Locale:  tig_ER.utf8
268.3549 +default locale: ID: en_ER, Name: English (Eritrea)
268.3550 +display locale: ID: en_ER, Name: English (Eritrea)
268.3551 +format locale: ID: en_ER, Name: English (Eritrea)
268.3552 +default charset: UTF-8
268.3553 +
268.3554 +OS Locale:  tl_PH
268.3555 +default locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3556 +display locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3557 +format locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3558 +default charset: ISO-8859-1
268.3559 +
268.3560 +OS Locale:  tl_PH.iso88591
268.3561 +default locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3562 +display locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3563 +format locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3564 +default charset: ISO-8859-1
268.3565 +
268.3566 +OS Locale:  tl_PH.utf8
268.3567 +default locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3568 +display locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3569 +format locale: ID: tl_PH, Name: Tagalog (Philippines)
268.3570 +default charset: UTF-8
268.3571 +
268.3572 +OS Locale:  tn_ZA
268.3573 +default locale: ID: tn_ZA, Name: Tswana (South Africa)
268.3574 +display locale: ID: tn_ZA, Name: Tswana (South Africa)
268.3575 +format locale: ID: tn_ZA, Name: Tswana (South Africa)
268.3576 +default charset: UTF-8
268.3577 +
268.3578 +OS Locale:  tn_ZA.utf8
268.3579 +default locale: ID: tn_ZA, Name: Tswana (South Africa)
268.3580 +display locale: ID: tn_ZA, Name: Tswana (South Africa)
268.3581 +format locale: ID: tn_ZA, Name: Tswana (South Africa)
268.3582 +default charset: UTF-8
268.3583 +
268.3584 +OS Locale:  tr_CY
268.3585 +default locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3586 +display locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3587 +format locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3588 +default charset: ISO-8859-9
268.3589 +
268.3590 +OS Locale:  tr_CY.iso88599
268.3591 +default locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3592 +display locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3593 +format locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3594 +default charset: ISO-8859-9
268.3595 +
268.3596 +OS Locale:  tr_CY.utf8
268.3597 +default locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3598 +display locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3599 +format locale: ID: tr_CY, Name: Turkish (Cyprus)
268.3600 +default charset: UTF-8
268.3601 +
268.3602 +OS Locale:  tr_TR
268.3603 +default locale: ID: tr_TR, Name: Turkish (Turkey)
268.3604 +display locale: ID: tr_TR, Name: Turkish (Turkey)
268.3605 +format locale: ID: tr_TR, Name: Turkish (Turkey)
268.3606 +default charset: ISO-8859-9
268.3607 +
268.3608 +OS Locale:  tr_TR.iso88599
268.3609 +default locale: ID: tr_TR, Name: Turkish (Turkey)
268.3610 +display locale: ID: tr_TR, Name: Turkish (Turkey)
268.3611 +format locale: ID: tr_TR, Name: Turkish (Turkey)
268.3612 +default charset: ISO-8859-9
268.3613 +
268.3614 +OS Locale:  tr_TR.utf8
268.3615 +default locale: ID: tr_TR, Name: Turkish (Turkey)
268.3616 +display locale: ID: tr_TR, Name: Turkish (Turkey)
268.3617 +format locale: ID: tr_TR, Name: Turkish (Turkey)
268.3618 +default charset: UTF-8
268.3619 +
268.3620 +OS Locale:  ts_ZA
268.3621 +default locale: ID: ts_ZA, Name: Tsonga (South Africa)
268.3622 +display locale: ID: ts_ZA, Name: Tsonga (South Africa)
268.3623 +format locale: ID: ts_ZA, Name: Tsonga (South Africa)
268.3624 +default charset: UTF-8
268.3625 +
268.3626 +OS Locale:  ts_ZA.utf8
268.3627 +default locale: ID: ts_ZA, Name: Tsonga (South Africa)
268.3628 +display locale: ID: ts_ZA, Name: Tsonga (South Africa)
268.3629 +format locale: ID: ts_ZA, Name: Tsonga (South Africa)
268.3630 +default charset: UTF-8
268.3631 +
268.3632 +OS Locale:  tt_RU.utf8
268.3633 +default locale: ID: tt_RU, Name: Tatar (Russia)
268.3634 +display locale: ID: tt_RU, Name: Tatar (Russia)
268.3635 +format locale: ID: tt_RU, Name: Tatar (Russia)
268.3636 +default charset: UTF-8
268.3637 +
268.3638 +OS Locale:  turkish
268.3639 +default locale: ID: tr_TR, Name: Turkish (Turkey)
268.3640 +display locale: ID: tr_TR, Name: Turkish (Turkey)
268.3641 +format locale: ID: tr_TR, Name: Turkish (Turkey)
268.3642 +default charset: ISO-8859-9
268.3643 +
268.3644 +OS Locale:  uk_UA
268.3645 +default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3646 +display locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3647 +format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3648 +default charset: KOI8-U
268.3649 +
268.3650 +OS Locale:  uk_UA.koi8u
268.3651 +default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3652 +display locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3653 +format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3654 +default charset: KOI8-U
268.3655 +
268.3656 +OS Locale:  uk_UA.utf8
268.3657 +default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3658 +display locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3659 +format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
268.3660 +default charset: UTF-8
268.3661 +
268.3662 +OS Locale:  ur_PK
268.3663 +default locale: ID: ur_PK, Name: Urdu (Pakistan)
268.3664 +display locale: ID: ur_PK, Name: Urdu (Pakistan)
268.3665 +format locale: ID: ur_PK, Name: Urdu (Pakistan)
268.3666 +default charset: UTF-8
268.3667 +
268.3668 +OS Locale:  ur_PK.utf8
268.3669 +default locale: ID: ur_PK, Name: Urdu (Pakistan)
268.3670 +display locale: ID: ur_PK, Name: Urdu (Pakistan)
268.3671 +format locale: ID: ur_PK, Name: Urdu (Pakistan)
268.3672 +default charset: UTF-8
268.3673 +
268.3674 +OS Locale:  uz_UZ
268.3675 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3676 +display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3677 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3678 +default charset: ISO-8859-1
268.3679 +
268.3680 +OS Locale:  uz_UZ.iso88591
268.3681 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3682 +display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3683 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3684 +default charset: ISO-8859-1
268.3685 +
268.3686 +OS Locale:  uz_UZ.utf8@cyrillic
268.3687 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3688 +display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3689 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3690 +default charset: UTF-8
268.3691 +
268.3692 +OS Locale:  uz_UZ@cyrillic
268.3693 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3694 +display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3695 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
268.3696 +default charset: UTF-8
268.3697 +
268.3698 +OS Locale:  ve_ZA
268.3699 +default locale: ID: ve_ZA, Name: Venda (South Africa)
268.3700 +display locale: ID: ve_ZA, Name: Venda (South Africa)
268.3701 +format locale: ID: ve_ZA, Name: Venda (South Africa)
268.3702 +default charset: UTF-8
268.3703 +
268.3704 +OS Locale:  ve_ZA.utf8
268.3705 +default locale: ID: ve_ZA, Name: Venda (South Africa)
268.3706 +display locale: ID: ve_ZA, Name: Venda (South Africa)
268.3707 +format locale: ID: ve_ZA, Name: Venda (South Africa)
268.3708 +default charset: UTF-8
268.3709 +
268.3710 +OS Locale:  vi_VN
268.3711 +default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3712 +display locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3713 +format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3714 +default charset: UTF-8
268.3715 +
268.3716 +OS Locale:  vi_VN.tcvn
268.3717 +default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3718 +display locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3719 +format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3720 +default charset: UTF-8
268.3721 +
268.3722 +OS Locale:  vi_VN.utf8
268.3723 +default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3724 +display locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3725 +format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
268.3726 +default charset: UTF-8
268.3727 +
268.3728 +OS Locale:  wa_BE
268.3729 +default locale: ID: wa_BE, Name: Walloon (Belgium)
268.3730 +display locale: ID: wa_BE, Name: Walloon (Belgium)
268.3731 +format locale: ID: wa_BE, Name: Walloon (Belgium)
268.3732 +default charset: ISO-8859-1
268.3733 +
268.3734 +OS Locale:  wa_BE.iso88591
268.3735 +default locale: ID: wa_BE, Name: Walloon (Belgium)
268.3736 +display locale: ID: wa_BE, Name: Walloon (Belgium)
268.3737 +format locale: ID: wa_BE, Name: Walloon (Belgium)
268.3738 +default charset: ISO-8859-1
268.3739 +
268.3740 +OS Locale:  wa_BE.iso885915@euro
268.3741 +default locale: ID: wa_BE, Name: Walloon (Belgium)
268.3742 +display locale: ID: wa_BE, Name: Walloon (Belgium)
268.3743 +format locale: ID: wa_BE, Name: Walloon (Belgium)
268.3744 +default charset: ISO-8859-15
268.3745 +
268.3746 +OS Locale:  wa_BE.utf8
268.3747 +default locale: ID: wa_BE, Name: Walloon (Belgium)
268.3748 +display locale: ID: wa_BE, Name: Walloon (Belgium)
268.3749 +format locale: ID: wa_BE, Name: Walloon (Belgium)
268.3750 +default charset: UTF-8
268.3751 +
268.3752 +OS Locale:  wa_BE@euro
268.3753 +default locale: ID: wa_BE, Name: Walloon (Belgium)
268.3754 +display locale: ID: wa_BE, Name: Walloon (Belgium)
268.3755 +format locale: ID: wa_BE, Name: Walloon (Belgium)
268.3756 +default charset: ISO-8859-15
268.3757 +
268.3758 +OS Locale:  xh_ZA
268.3759 +default locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3760 +display locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3761 +format locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3762 +default charset: ISO-8859-1
268.3763 +
268.3764 +OS Locale:  xh_ZA.iso88591
268.3765 +default locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3766 +display locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3767 +format locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3768 +default charset: ISO-8859-1
268.3769 +
268.3770 +OS Locale:  xh_ZA.utf8
268.3771 +default locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3772 +display locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3773 +format locale: ID: xh_ZA, Name: Xhosa (South Africa)
268.3774 +default charset: UTF-8
268.3775 +
268.3776 +OS Locale:  yi_US
268.3777 +default locale: ID: ji_US, Name: Yiddish (United States)
268.3778 +display locale: ID: ji_US, Name: Yiddish (United States)
268.3779 +format locale: ID: ji_US, Name: Yiddish (United States)
268.3780 +default charset: windows-1255
268.3781 +
268.3782 +OS Locale:  yi_US.cp1255
268.3783 +default locale: ID: ji_US, Name: Yiddish (United States)
268.3784 +display locale: ID: ji_US, Name: Yiddish (United States)
268.3785 +format locale: ID: ji_US, Name: Yiddish (United States)
268.3786 +default charset: windows-1255
268.3787 +
268.3788 +OS Locale:  yi_US.utf8
268.3789 +default locale: ID: ji_US, Name: Yiddish (United States)
268.3790 +display locale: ID: ji_US, Name: Yiddish (United States)
268.3791 +format locale: ID: ji_US, Name: Yiddish (United States)
268.3792 +default charset: UTF-8
268.3793 +
268.3794 +OS Locale:  zh_CN
268.3795 +default locale: ID: zh_CN, Name: Chinese (China)
268.3796 +display locale: ID: zh_CN, Name: Chinese (China)
268.3797 +format locale: ID: zh_CN, Name: Chinese (China)
268.3798 +default charset: GB2312
268.3799 +
268.3800 +OS Locale:  zh_CN.gb18030
268.3801 +default locale: ID: zh_CN, Name: Chinese (China)
268.3802 +display locale: ID: zh_CN, Name: Chinese (China)
268.3803 +format locale: ID: zh_CN, Name: Chinese (China)
268.3804 +default charset: GB18030
268.3805 +
268.3806 +OS Locale:  zh_CN.gb2312
268.3807 +default locale: ID: zh_CN, Name: Chinese (China)
268.3808 +display locale: ID: zh_CN, Name: Chinese (China)
268.3809 +format locale: ID: zh_CN, Name: Chinese (China)
268.3810 +default charset: GB2312
268.3811 +
268.3812 +OS Locale:  zh_CN.gbk
268.3813 +default locale: ID: zh_CN, Name: Chinese (China)
268.3814 +display locale: ID: zh_CN, Name: Chinese (China)
268.3815 +format locale: ID: zh_CN, Name: Chinese (China)
268.3816 +default charset: GBK
268.3817 +
268.3818 +OS Locale:  zh_CN.utf8
268.3819 +default locale: ID: zh_CN, Name: Chinese (China)
268.3820 +display locale: ID: zh_CN, Name: Chinese (China)
268.3821 +format locale: ID: zh_CN, Name: Chinese (China)
268.3822 +default charset: UTF-8
268.3823 +
268.3824 +OS Locale:  zh_HK
268.3825 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3826 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3827 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3828 +default charset: Big5-HKSCS
268.3829 +
268.3830 +OS Locale:  zh_HK.big5hkscs
268.3831 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3832 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3833 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3834 +default charset: Big5-HKSCS
268.3835 +
268.3836 +OS Locale:  zh_HK.utf8
268.3837 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3838 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3839 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
268.3840 +default charset: UTF-8
268.3841 +
268.3842 +OS Locale:  zh_SG
268.3843 +default locale: ID: zh_SG, Name: Chinese (Singapore)
268.3844 +display locale: ID: zh_SG, Name: Chinese (Singapore)
268.3845 +format locale: ID: zh_SG, Name: Chinese (Singapore)
268.3846 +default charset: GB2312
268.3847 +
268.3848 +OS Locale:  zh_SG.gb2312
268.3849 +default locale: ID: zh_SG, Name: Chinese (Singapore)
268.3850 +display locale: ID: zh_SG, Name: Chinese (Singapore)
268.3851 +format locale: ID: zh_SG, Name: Chinese (Singapore)
268.3852 +default charset: GB2312
268.3853 +
268.3854 +OS Locale:  zh_SG.gbk
268.3855 +default locale: ID: zh_SG, Name: Chinese (Singapore)
268.3856 +display locale: ID: zh_SG, Name: Chinese (Singapore)
268.3857 +format locale: ID: zh_SG, Name: Chinese (Singapore)
268.3858 +default charset: GBK
268.3859 +
268.3860 +OS Locale:  zh_SG.utf8
268.3861 +default locale: ID: zh_SG, Name: Chinese (Singapore)
268.3862 +display locale: ID: zh_SG, Name: Chinese (Singapore)
268.3863 +format locale: ID: zh_SG, Name: Chinese (Singapore)
268.3864 +default charset: UTF-8
268.3865 +
268.3866 +OS Locale:  zh_TW
268.3867 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3868 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3869 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3870 +default charset: Big5
268.3871 +
268.3872 +OS Locale:  zh_TW.big5
268.3873 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3874 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3875 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3876 +default charset: Big5
268.3877 +
268.3878 +OS Locale:  zh_TW.euctw
268.3879 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3880 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3881 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3882 +default charset: x-EUC-TW
268.3883 +
268.3884 +OS Locale:  zh_TW.utf8
268.3885 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3886 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3887 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
268.3888 +default charset: UTF-8
268.3889 +
268.3890 +OS Locale:  zu_ZA
268.3891 +default locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3892 +display locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3893 +format locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3894 +default charset: ISO-8859-1
268.3895 +
268.3896 +OS Locale:  zu_ZA.iso88591
268.3897 +default locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3898 +display locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3899 +format locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3900 +default charset: ISO-8859-1
268.3901 +
268.3902 +OS Locale:  zu_ZA.utf8
268.3903 +default locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3904 +display locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3905 +format locale: ID: zu_ZA, Name: Zulu (South Africa)
268.3906 +default charset: UTF-8
268.3907 +
268.3908 +Testing some typical combinations
268.3909 +
268.3910 +
268.3911 +OS Locale (LC_CTYPE: ja_JP.UTF-8, LC_MESSAGES: zh_CN.UTF-8)
268.3912 +default locale: ID: zh_CN, Name: Chinese (China)
268.3913 +display locale: ID: zh_CN, Name: Chinese (China)
268.3914 +format locale: ID: ja_JP, Name: Japanese (Japan)
268.3915 +default charset: UTF-8
268.3916 +
268.3917 +OS Locale (LC_CTYPE: zh_CN.UTF-8, LC_MESSAGES: en_US.UTF-8)
268.3918 +default locale: ID: en_US, Name: English (United States)
268.3919 +display locale: ID: en_US, Name: English (United States)
268.3920 +format locale: ID: zh_CN, Name: Chinese (China)
268.3921 +default charset: UTF-8
268.3922 +
268.3923 +OS Locale (LC_CTYPE: C, LC_MESSAGES: zh_CN.UTF-8)
268.3924 +default locale: ID: zh_CN, Name: Chinese (China)
268.3925 +display locale: ID: zh_CN, Name: Chinese (China)
268.3926 +format locale: ID: en_US, Name: English (United States)
268.3927 +default charset: US-ASCII
   269.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   269.2 +++ b/test/java/util/Locale/data/deflocale.rhel5.fmtasdefault	Fri Sep 24 16:41:32 2010 -0700
   269.3 @@ -0,0 +1,3924 @@
   269.4 +Red Hat Enterprise Linux Server release 5.3 (Tikanga)
   269.5 +Linux localhost.localdomain 2.6.18-128.el5 #1 SMP Wed Dec 17 11:42:39 EST 2008 i686 i686 i386 GNU/Linux
   269.6 +Testing all available locales
   269.7 +
   269.8 +OS Locale:  C
   269.9 +default locale: ID: en_US, Name: English (United States)
  269.10 +display locale: ID: en_US, Name: English (United States)
  269.11 +format locale: ID: en_US, Name: English (United States)
  269.12 +default charset: US-ASCII
  269.13 +
  269.14 +OS Locale:  POSIX
  269.15 +default locale: ID: en_US, Name: English (United States)
  269.16 +display locale: ID: en_US, Name: English (United States)
  269.17 +format locale: ID: en_US, Name: English (United States)
  269.18 +default charset: US-ASCII
  269.19 +
  269.20 +OS Locale:  aa_DJ
  269.21 +default locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.22 +display locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.23 +format locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.24 +default charset: ISO-8859-1
  269.25 +
  269.26 +OS Locale:  aa_DJ.iso88591
  269.27 +default locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.28 +display locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.29 +format locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.30 +default charset: ISO-8859-1
  269.31 +
  269.32 +OS Locale:  aa_DJ.utf8
  269.33 +default locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.34 +display locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.35 +format locale: ID: aa_DJ, Name: Afar (Djibouti)
  269.36 +default charset: UTF-8
  269.37 +
  269.38 +OS Locale:  aa_ER
  269.39 +default locale: ID: aa_ER, Name: Afar (Eritrea)
  269.40 +display locale: ID: aa_ER, Name: Afar (Eritrea)
  269.41 +format locale: ID: aa_ER, Name: Afar (Eritrea)
  269.42 +default charset: UTF-8
  269.43 +
  269.44 +OS Locale:  aa_ER.utf8
  269.45 +default locale: ID: aa_ER, Name: Afar (Eritrea)
  269.46 +display locale: ID: aa_ER, Name: Afar (Eritrea)
  269.47 +format locale: ID: aa_ER, Name: Afar (Eritrea)
  269.48 +default charset: UTF-8
  269.49 +
  269.50 +OS Locale:  aa_ER.utf8@saaho
  269.51 +default locale: ID: aa_ER, Name: Afar (Eritrea)
  269.52 +display locale: ID: aa_ER, Name: Afar (Eritrea)
  269.53 +format locale: ID: aa_ER, Name: Afar (Eritrea)
  269.54 +default charset: UTF-8
  269.55 +
  269.56 +OS Locale:  aa_ER@saaho
  269.57 +default locale: ID: aa_ER, Name: Afar (Eritrea)
  269.58 +display locale: ID: aa_ER, Name: Afar (Eritrea)
  269.59 +format locale: ID: aa_ER, Name: Afar (Eritrea)
  269.60 +default charset: UTF-8
  269.61 +
  269.62 +OS Locale:  aa_ET
  269.63 +default locale: ID: aa_ET, Name: Afar (Ethiopia)
  269.64 +display locale: ID: aa_ET, Name: Afar (Ethiopia)
  269.65 +format locale: ID: aa_ET, Name: Afar (Ethiopia)
  269.66 +default charset: UTF-8
  269.67 +
  269.68 +OS Locale:  aa_ET.utf8
  269.69 +default locale: ID: aa_ET, Name: Afar (Ethiopia)
  269.70 +display locale: ID: aa_ET, Name: Afar (Ethiopia)
  269.71 +format locale: ID: aa_ET, Name: Afar (Ethiopia)
  269.72 +default charset: UTF-8
  269.73 +
  269.74 +OS Locale:  af_ZA
  269.75 +default locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.76 +display locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.77 +format locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.78 +default charset: ISO-8859-1
  269.79 +
  269.80 +OS Locale:  af_ZA.iso88591
  269.81 +default locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.82 +display locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.83 +format locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.84 +default charset: ISO-8859-1
  269.85 +
  269.86 +OS Locale:  af_ZA.utf8
  269.87 +default locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.88 +display locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.89 +format locale: ID: af_ZA, Name: Afrikaans (South Africa)
  269.90 +default charset: UTF-8
  269.91 +
  269.92 +OS Locale:  am_ET
  269.93 +default locale: ID: am_ET, Name: Amharic (Ethiopia)
  269.94 +display locale: ID: am_ET, Name: Amharic (Ethiopia)
  269.95 +format locale: ID: am_ET, Name: Amharic (Ethiopia)
  269.96 +default charset: UTF-8
  269.97 +
  269.98 +OS Locale:  am_ET.utf8
  269.99 +default locale: ID: am_ET, Name: Amharic (Ethiopia)
 269.100 +display locale: ID: am_ET, Name: Amharic (Ethiopia)
 269.101 +format locale: ID: am_ET, Name: Amharic (Ethiopia)
 269.102 +default charset: UTF-8
 269.103 +
 269.104 +OS Locale:  an_ES
 269.105 +default locale: ID: an_ES, Name: Aragonese (Spain)
 269.106 +display locale: ID: an_ES, Name: Aragonese (Spain)
 269.107 +format locale: ID: an_ES, Name: Aragonese (Spain)
 269.108 +default charset: ISO-8859-15
 269.109 +
 269.110 +OS Locale:  an_ES.iso885915
 269.111 +default locale: ID: an_ES, Name: Aragonese (Spain)
 269.112 +display locale: ID: an_ES, Name: Aragonese (Spain)
 269.113 +format locale: ID: an_ES, Name: Aragonese (Spain)
 269.114 +default charset: ISO-8859-15
 269.115 +
 269.116 +OS Locale:  an_ES.utf8
 269.117 +default locale: ID: an_ES, Name: Aragonese (Spain)
 269.118 +display locale: ID: an_ES, Name: Aragonese (Spain)
 269.119 +format locale: ID: an_ES, Name: Aragonese (Spain)
 269.120 +default charset: UTF-8
 269.121 +
 269.122 +OS Locale:  ar_AE
 269.123 +default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.124 +display locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.125 +format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.126 +default charset: ISO-8859-6
 269.127 +
 269.128 +OS Locale:  ar_AE.iso88596
 269.129 +default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.130 +display locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.131 +format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.132 +default charset: ISO-8859-6
 269.133 +
 269.134 +OS Locale:  ar_AE.utf8
 269.135 +default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.136 +display locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.137 +format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
 269.138 +default charset: UTF-8
 269.139 +
 269.140 +OS Locale:  ar_BH
 269.141 +default locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.142 +display locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.143 +format locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.144 +default charset: ISO-8859-6
 269.145 +
 269.146 +OS Locale:  ar_BH.iso88596
 269.147 +default locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.148 +display locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.149 +format locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.150 +default charset: ISO-8859-6
 269.151 +
 269.152 +OS Locale:  ar_BH.utf8
 269.153 +default locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.154 +display locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.155 +format locale: ID: ar_BH, Name: Arabic (Bahrain)
 269.156 +default charset: UTF-8
 269.157 +
 269.158 +OS Locale:  ar_DZ
 269.159 +default locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.160 +display locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.161 +format locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.162 +default charset: ISO-8859-6
 269.163 +
 269.164 +OS Locale:  ar_DZ.iso88596
 269.165 +default locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.166 +display locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.167 +format locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.168 +default charset: ISO-8859-6
 269.169 +
 269.170 +OS Locale:  ar_DZ.utf8
 269.171 +default locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.172 +display locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.173 +format locale: ID: ar_DZ, Name: Arabic (Algeria)
 269.174 +default charset: UTF-8
 269.175 +
 269.176 +OS Locale:  ar_EG
 269.177 +default locale: ID: ar_EG, Name: Arabic (Egypt)
 269.178 +display locale: ID: ar_EG, Name: Arabic (Egypt)
 269.179 +format locale: ID: ar_EG, Name: Arabic (Egypt)
 269.180 +default charset: ISO-8859-6
 269.181 +
 269.182 +OS Locale:  ar_EG.iso88596
 269.183 +default locale: ID: ar_EG, Name: Arabic (Egypt)
 269.184 +display locale: ID: ar_EG, Name: Arabic (Egypt)
 269.185 +format locale: ID: ar_EG, Name: Arabic (Egypt)
 269.186 +default charset: ISO-8859-6
 269.187 +
 269.188 +OS Locale:  ar_EG.utf8
 269.189 +default locale: ID: ar_EG, Name: Arabic (Egypt)
 269.190 +display locale: ID: ar_EG, Name: Arabic (Egypt)
 269.191 +format locale: ID: ar_EG, Name: Arabic (Egypt)
 269.192 +default charset: UTF-8
 269.193 +
 269.194 +OS Locale:  ar_IN
 269.195 +default locale: ID: ar_IN, Name: Arabic (India)
 269.196 +display locale: ID: ar_IN, Name: Arabic (India)
 269.197 +format locale: ID: ar_IN, Name: Arabic (India)
 269.198 +default charset: UTF-8
 269.199 +
 269.200 +OS Locale:  ar_IN.utf8
 269.201 +default locale: ID: ar_IN, Name: Arabic (India)
 269.202 +display locale: ID: ar_IN, Name: Arabic (India)
 269.203 +format locale: ID: ar_IN, Name: Arabic (India)
 269.204 +default charset: UTF-8
 269.205 +
 269.206 +OS Locale:  ar_IQ
 269.207 +default locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.208 +display locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.209 +format locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.210 +default charset: ISO-8859-6
 269.211 +
 269.212 +OS Locale:  ar_IQ.iso88596
 269.213 +default locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.214 +display locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.215 +format locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.216 +default charset: ISO-8859-6
 269.217 +
 269.218 +OS Locale:  ar_IQ.utf8
 269.219 +default locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.220 +display locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.221 +format locale: ID: ar_IQ, Name: Arabic (Iraq)
 269.222 +default charset: UTF-8
 269.223 +
 269.224 +OS Locale:  ar_JO
 269.225 +default locale: ID: ar_JO, Name: Arabic (Jordan)
 269.226 +display locale: ID: ar_JO, Name: Arabic (Jordan)
 269.227 +format locale: ID: ar_JO, Name: Arabic (Jordan)
 269.228 +default charset: ISO-8859-6
 269.229 +
 269.230 +OS Locale:  ar_JO.iso88596
 269.231 +default locale: ID: ar_JO, Name: Arabic (Jordan)
 269.232 +display locale: ID: ar_JO, Name: Arabic (Jordan)
 269.233 +format locale: ID: ar_JO, Name: Arabic (Jordan)
 269.234 +default charset: ISO-8859-6
 269.235 +
 269.236 +OS Locale:  ar_JO.utf8
 269.237 +default locale: ID: ar_JO, Name: Arabic (Jordan)
 269.238 +display locale: ID: ar_JO, Name: Arabic (Jordan)
 269.239 +format locale: ID: ar_JO, Name: Arabic (Jordan)
 269.240 +default charset: UTF-8
 269.241 +
 269.242 +OS Locale:  ar_KW
 269.243 +default locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.244 +display locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.245 +format locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.246 +default charset: ISO-8859-6
 269.247 +
 269.248 +OS Locale:  ar_KW.iso88596
 269.249 +default locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.250 +display locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.251 +format locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.252 +default charset: ISO-8859-6
 269.253 +
 269.254 +OS Locale:  ar_KW.utf8
 269.255 +default locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.256 +display locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.257 +format locale: ID: ar_KW, Name: Arabic (Kuwait)
 269.258 +default charset: UTF-8
 269.259 +
 269.260 +OS Locale:  ar_LB
 269.261 +default locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.262 +display locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.263 +format locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.264 +default charset: ISO-8859-6
 269.265 +
 269.266 +OS Locale:  ar_LB.iso88596
 269.267 +default locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.268 +display locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.269 +format locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.270 +default charset: ISO-8859-6
 269.271 +
 269.272 +OS Locale:  ar_LB.utf8
 269.273 +default locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.274 +display locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.275 +format locale: ID: ar_LB, Name: Arabic (Lebanon)
 269.276 +default charset: UTF-8
 269.277 +
 269.278 +OS Locale:  ar_LY
 269.279 +default locale: ID: ar_LY, Name: Arabic (Libya)
 269.280 +display locale: ID: ar_LY, Name: Arabic (Libya)
 269.281 +format locale: ID: ar_LY, Name: Arabic (Libya)
 269.282 +default charset: ISO-8859-6
 269.283 +
 269.284 +OS Locale:  ar_LY.iso88596
 269.285 +default locale: ID: ar_LY, Name: Arabic (Libya)
 269.286 +display locale: ID: ar_LY, Name: Arabic (Libya)
 269.287 +format locale: ID: ar_LY, Name: Arabic (Libya)
 269.288 +default charset: ISO-8859-6
 269.289 +
 269.290 +OS Locale:  ar_LY.utf8
 269.291 +default locale: ID: ar_LY, Name: Arabic (Libya)
 269.292 +display locale: ID: ar_LY, Name: Arabic (Libya)
 269.293 +format locale: ID: ar_LY, Name: Arabic (Libya)
 269.294 +default charset: UTF-8
 269.295 +
 269.296 +OS Locale:  ar_MA
 269.297 +default locale: ID: ar_MA, Name: Arabic (Morocco)
 269.298 +display locale: ID: ar_MA, Name: Arabic (Morocco)
 269.299 +format locale: ID: ar_MA, Name: Arabic (Morocco)
 269.300 +default charset: ISO-8859-6
 269.301 +
 269.302 +OS Locale:  ar_MA.iso88596
 269.303 +default locale: ID: ar_MA, Name: Arabic (Morocco)
 269.304 +display locale: ID: ar_MA, Name: Arabic (Morocco)
 269.305 +format locale: ID: ar_MA, Name: Arabic (Morocco)
 269.306 +default charset: ISO-8859-6
 269.307 +
 269.308 +OS Locale:  ar_MA.utf8
 269.309 +default locale: ID: ar_MA, Name: Arabic (Morocco)
 269.310 +display locale: ID: ar_MA, Name: Arabic (Morocco)
 269.311 +format locale: ID: ar_MA, Name: Arabic (Morocco)
 269.312 +default charset: UTF-8
 269.313 +
 269.314 +OS Locale:  ar_OM
 269.315 +default locale: ID: ar_OM, Name: Arabic (Oman)
 269.316 +display locale: ID: ar_OM, Name: Arabic (Oman)
 269.317 +format locale: ID: ar_OM, Name: Arabic (Oman)
 269.318 +default charset: ISO-8859-6
 269.319 +
 269.320 +OS Locale:  ar_OM.iso88596
 269.321 +default locale: ID: ar_OM, Name: Arabic (Oman)
 269.322 +display locale: ID: ar_OM, Name: Arabic (Oman)
 269.323 +format locale: ID: ar_OM, Name: Arabic (Oman)
 269.324 +default charset: ISO-8859-6
 269.325 +
 269.326 +OS Locale:  ar_OM.utf8
 269.327 +default locale: ID: ar_OM, Name: Arabic (Oman)
 269.328 +display locale: ID: ar_OM, Name: Arabic (Oman)
 269.329 +format locale: ID: ar_OM, Name: Arabic (Oman)
 269.330 +default charset: UTF-8
 269.331 +
 269.332 +OS Locale:  ar_QA
 269.333 +default locale: ID: ar_QA, Name: Arabic (Qatar)
 269.334 +display locale: ID: ar_QA, Name: Arabic (Qatar)
 269.335 +format locale: ID: ar_QA, Name: Arabic (Qatar)
 269.336 +default charset: ISO-8859-6
 269.337 +
 269.338 +OS Locale:  ar_QA.iso88596
 269.339 +default locale: ID: ar_QA, Name: Arabic (Qatar)
 269.340 +display locale: ID: ar_QA, Name: Arabic (Qatar)
 269.341 +format locale: ID: ar_QA, Name: Arabic (Qatar)
 269.342 +default charset: ISO-8859-6
 269.343 +
 269.344 +OS Locale:  ar_QA.utf8
 269.345 +default locale: ID: ar_QA, Name: Arabic (Qatar)
 269.346 +display locale: ID: ar_QA, Name: Arabic (Qatar)
 269.347 +format locale: ID: ar_QA, Name: Arabic (Qatar)
 269.348 +default charset: UTF-8
 269.349 +
 269.350 +OS Locale:  ar_SA
 269.351 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.352 +display locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.353 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.354 +default charset: ISO-8859-6
 269.355 +
 269.356 +OS Locale:  ar_SA.iso88596
 269.357 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.358 +display locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.359 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.360 +default charset: ISO-8859-6
 269.361 +
 269.362 +OS Locale:  ar_SA.utf8
 269.363 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.364 +display locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.365 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
 269.366 +default charset: UTF-8
 269.367 +
 269.368 +OS Locale:  ar_SD
 269.369 +default locale: ID: ar_SD, Name: Arabic (Sudan)
 269.370 +display locale: ID: ar_SD, Name: Arabic (Sudan)
 269.371 +format locale: ID: ar_SD, Name: Arabic (Sudan)
 269.372 +default charset: ISO-8859-6
 269.373 +
 269.374 +OS Locale:  ar_SD.iso88596
 269.375 +default locale: ID: ar_SD, Name: Arabic (Sudan)
 269.376 +display locale: ID: ar_SD, Name: Arabic (Sudan)
 269.377 +format locale: ID: ar_SD, Name: Arabic (Sudan)
 269.378 +default charset: ISO-8859-6
 269.379 +
 269.380 +OS Locale:  ar_SD.utf8
 269.381 +default locale: ID: ar_SD, Name: Arabic (Sudan)
 269.382 +display locale: ID: ar_SD, Name: Arabic (Sudan)
 269.383 +format locale: ID: ar_SD, Name: Arabic (Sudan)
 269.384 +default charset: UTF-8
 269.385 +
 269.386 +OS Locale:  ar_SY
 269.387 +default locale: ID: ar_SY, Name: Arabic (Syria)
 269.388 +display locale: ID: ar_SY, Name: Arabic (Syria)
 269.389 +format locale: ID: ar_SY, Name: Arabic (Syria)
 269.390 +default charset: ISO-8859-6
 269.391 +
 269.392 +OS Locale:  ar_SY.iso88596
 269.393 +default locale: ID: ar_SY, Name: Arabic (Syria)
 269.394 +display locale: ID: ar_SY, Name: Arabic (Syria)
 269.395 +format locale: ID: ar_SY, Name: Arabic (Syria)
 269.396 +default charset: ISO-8859-6
 269.397 +
 269.398 +OS Locale:  ar_SY.utf8
 269.399 +default locale: ID: ar_SY, Name: Arabic (Syria)
 269.400 +display locale: ID: ar_SY, Name: Arabic (Syria)
 269.401 +format locale: ID: ar_SY, Name: Arabic (Syria)
 269.402 +default charset: UTF-8
 269.403 +
 269.404 +OS Locale:  ar_TN
 269.405 +default locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.406 +display locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.407 +format locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.408 +default charset: ISO-8859-6
 269.409 +
 269.410 +OS Locale:  ar_TN.iso88596
 269.411 +default locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.412 +display locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.413 +format locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.414 +default charset: ISO-8859-6
 269.415 +
 269.416 +OS Locale:  ar_TN.utf8
 269.417 +default locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.418 +display locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.419 +format locale: ID: ar_TN, Name: Arabic (Tunisia)
 269.420 +default charset: UTF-8
 269.421 +
 269.422 +OS Locale:  ar_YE
 269.423 +default locale: ID: ar_YE, Name: Arabic (Yemen)
 269.424 +display locale: ID: ar_YE, Name: Arabic (Yemen)
 269.425 +format locale: ID: ar_YE, Name: Arabic (Yemen)
 269.426 +default charset: ISO-8859-6
 269.427 +
 269.428 +OS Locale:  ar_YE.iso88596
 269.429 +default locale: ID: ar_YE, Name: Arabic (Yemen)
 269.430 +display locale: ID: ar_YE, Name: Arabic (Yemen)
 269.431 +format locale: ID: ar_YE, Name: Arabic (Yemen)
 269.432 +default charset: ISO-8859-6
 269.433 +
 269.434 +OS Locale:  ar_YE.utf8
 269.435 +default locale: ID: ar_YE, Name: Arabic (Yemen)
 269.436 +display locale: ID: ar_YE, Name: Arabic (Yemen)
 269.437 +format locale: ID: ar_YE, Name: Arabic (Yemen)
 269.438 +default charset: UTF-8
 269.439 +
 269.440 +OS Locale:  as_IN.utf8
 269.441 +default locale: ID: as_IN, Name: Assamese (India)
 269.442 +display locale: ID: as_IN, Name: Assamese (India)
 269.443 +format locale: ID: as_IN, Name: Assamese (India)
 269.444 +default charset: UTF-8
 269.445 +
 269.446 +OS Locale:  az_AZ.utf8
 269.447 +default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 269.448 +display locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 269.449 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 269.450 +default charset: UTF-8
 269.451 +
 269.452 +OS Locale:  be_BY
 269.453 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 269.454 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 269.455 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 269.456 +default charset: windows-1251
 269.457 +
 269.458 +OS Locale:  be_BY.cp1251
 269.459 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 269.460 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 269.461 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 269.462 +default charset: windows-1251
 269.463 +
 269.464 +OS Locale:  be_BY.utf8
 269.465 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 269.466 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 269.467 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 269.468 +default charset: UTF-8
 269.469 +
 269.470 +OS Locale:  be_BY.utf8@latin
 269.471 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 269.472 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 269.473 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 269.474 +default charset: UTF-8
 269.475 +
 269.476 +OS Locale:  be_BY@latin
 269.477 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 269.478 +display locale: ID: be_BY, Name: Belarusian (Belarus)
 269.479 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 269.480 +default charset: UTF-8
 269.481 +
 269.482 +OS Locale:  bg_BG
 269.483 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.484 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.485 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.486 +default charset: windows-1251
 269.487 +
 269.488 +OS Locale:  bg_BG.cp1251
 269.489 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.490 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.491 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.492 +default charset: windows-1251
 269.493 +
 269.494 +OS Locale:  bg_BG.utf8
 269.495 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.496 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.497 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
 269.498 +default charset: UTF-8
 269.499 +
 269.500 +OS Locale:  bn_BD
 269.501 +default locale: ID: bn_BD, Name: Bengali (Bangladesh)
 269.502 +display locale: ID: bn_BD, Name: Bengali (Bangladesh)
 269.503 +format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 269.504 +default charset: UTF-8
 269.505 +
 269.506 +OS Locale:  bn_BD.utf8
 269.507 +default locale: ID: bn_BD, Name: Bengali (Bangladesh)
 269.508 +display locale: ID: bn_BD, Name: Bengali (Bangladesh)
 269.509 +format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 269.510 +default charset: UTF-8
 269.511 +
 269.512 +OS Locale:  bn_IN
 269.513 +default locale: ID: bn_IN, Name: Bengali (India)
 269.514 +display locale: ID: bn_IN, Name: Bengali (India)
 269.515 +format locale: ID: bn_IN, Name: Bengali (India)
 269.516 +default charset: UTF-8
 269.517 +
 269.518 +OS Locale:  bn_IN.utf8
 269.519 +default locale: ID: bn_IN, Name: Bengali (India)
 269.520 +display locale: ID: bn_IN, Name: Bengali (India)
 269.521 +format locale: ID: bn_IN, Name: Bengali (India)
 269.522 +default charset: UTF-8
 269.523 +
 269.524 +OS Locale:  bokmål
 269.525 +default locale: ID: en, Name: English
 269.526 +display locale: ID: en, Name: English
 269.527 +format locale: ID: en, Name: English
 269.528 +default charset: ISO-8859-1
 269.529 +
 269.530 +OS Locale:  bokmal
 269.531 +default locale: ID: en, Name: English
 269.532 +display locale: ID: en, Name: English
 269.533 +format locale: ID: en, Name: English
 269.534 +default charset: ISO-8859-1
 269.535 +
 269.536 +OS Locale:  br_FR
 269.537 +default locale: ID: br_FR, Name: Breton (France)
 269.538 +display locale: ID: br_FR, Name: Breton (France)
 269.539 +format locale: ID: br_FR, Name: Breton (France)
 269.540 +default charset: ISO-8859-1
 269.541 +
 269.542 +OS Locale:  br_FR.iso88591
 269.543 +default locale: ID: br_FR, Name: Breton (France)
 269.544 +display locale: ID: br_FR, Name: Breton (France)
 269.545 +format locale: ID: br_FR, Name: Breton (France)
 269.546 +default charset: ISO-8859-1
 269.547 +
 269.548 +OS Locale:  br_FR.iso885915@euro
 269.549 +default locale: ID: br_FR, Name: Breton (France)
 269.550 +display locale: ID: br_FR, Name: Breton (France)
 269.551 +format locale: ID: br_FR, Name: Breton (France)
 269.552 +default charset: ISO-8859-15
 269.553 +
 269.554 +OS Locale:  br_FR.utf8
 269.555 +default locale: ID: br_FR, Name: Breton (France)
 269.556 +display locale: ID: br_FR, Name: Breton (France)
 269.557 +format locale: ID: br_FR, Name: Breton (France)
 269.558 +default charset: UTF-8
 269.559 +
 269.560 +OS Locale:  br_FR@euro
 269.561 +default locale: ID: br_FR, Name: Breton (France)
 269.562 +display locale: ID: br_FR, Name: Breton (France)
 269.563 +format locale: ID: br_FR, Name: Breton (France)
 269.564 +default charset: ISO-8859-15
 269.565 +
 269.566 +OS Locale:  bs_BA
 269.567 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.568 +display locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.569 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.570 +default charset: ISO-8859-2
 269.571 +
 269.572 +OS Locale:  bs_BA.iso88592
 269.573 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.574 +display locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.575 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.576 +default charset: ISO-8859-2
 269.577 +
 269.578 +OS Locale:  bs_BA.utf8
 269.579 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.580 +display locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.581 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
 269.582 +default charset: UTF-8
 269.583 +
 269.584 +OS Locale:  byn_ER
 269.585 +default locale: ID: en_ER, Name: English (Eritrea)
 269.586 +display locale: ID: en_ER, Name: English (Eritrea)
 269.587 +format locale: ID: en_ER, Name: English (Eritrea)
 269.588 +default charset: UTF-8
 269.589 +
 269.590 +OS Locale:  byn_ER.utf8
 269.591 +default locale: ID: en_ER, Name: English (Eritrea)
 269.592 +display locale: ID: en_ER, Name: English (Eritrea)
 269.593 +format locale: ID: en_ER, Name: English (Eritrea)
 269.594 +default charset: UTF-8
 269.595 +
 269.596 +OS Locale:  ca_AD
 269.597 +default locale: ID: ca_AD, Name: Catalan (Andorra)
 269.598 +display locale: ID: ca_AD, Name: Catalan (Andorra)
 269.599 +format locale: ID: ca_AD, Name: Catalan (Andorra)
 269.600 +default charset: ISO-8859-15
 269.601 +
 269.602 +OS Locale:  ca_AD.iso885915
 269.603 +default locale: ID: ca_AD, Name: Catalan (Andorra)
 269.604 +display locale: ID: ca_AD, Name: Catalan (Andorra)
 269.605 +format locale: ID: ca_AD, Name: Catalan (Andorra)
 269.606 +default charset: ISO-8859-15
 269.607 +
 269.608 +OS Locale:  ca_AD.utf8
 269.609 +default locale: ID: ca_AD, Name: Catalan (Andorra)
 269.610 +display locale: ID: ca_AD, Name: Catalan (Andorra)
 269.611 +format locale: ID: ca_AD, Name: Catalan (Andorra)
 269.612 +default charset: UTF-8
 269.613 +
 269.614 +OS Locale:  ca_ES
 269.615 +default locale: ID: ca_ES, Name: Catalan (Spain)
 269.616 +display locale: ID: ca_ES, Name: Catalan (Spain)
 269.617 +format locale: ID: ca_ES, Name: Catalan (Spain)
 269.618 +default charset: ISO-8859-1
 269.619 +
 269.620 +OS Locale:  ca_ES.iso88591
 269.621 +default locale: ID: ca_ES, Name: Catalan (Spain)
 269.622 +display locale: ID: ca_ES, Name: Catalan (Spain)
 269.623 +format locale: ID: ca_ES, Name: Catalan (Spain)
 269.624 +default charset: ISO-8859-1
 269.625 +
 269.626 +OS Locale:  ca_ES.iso885915@euro
 269.627 +default locale: ID: ca_ES, Name: Catalan (Spain)
 269.628 +display locale: ID: ca_ES, Name: Catalan (Spain)
 269.629 +format locale: ID: ca_ES, Name: Catalan (Spain)
 269.630 +default charset: ISO-8859-15
 269.631 +
 269.632 +OS Locale:  ca_ES.utf8
 269.633 +default locale: ID: ca_ES, Name: Catalan (Spain)
 269.634 +display locale: ID: ca_ES, Name: Catalan (Spain)
 269.635 +format locale: ID: ca_ES, Name: Catalan (Spain)
 269.636 +default charset: UTF-8
 269.637 +
 269.638 +OS Locale:  ca_ES@euro
 269.639 +default locale: ID: ca_ES, Name: Catalan (Spain)
 269.640 +display locale: ID: ca_ES, Name: Catalan (Spain)
 269.641 +format locale: ID: ca_ES, Name: Catalan (Spain)
 269.642 +default charset: ISO-8859-15
 269.643 +
 269.644 +OS Locale:  ca_FR
 269.645 +default locale: ID: ca_FR, Name: Catalan (France)
 269.646 +display locale: ID: ca_FR, Name: Catalan (France)
 269.647 +format locale: ID: ca_FR, Name: Catalan (France)
 269.648 +default charset: ISO-8859-15
 269.649 +
 269.650 +OS Locale:  ca_FR.iso885915
 269.651 +default locale: ID: ca_FR, Name: Catalan (France)
 269.652 +display locale: ID: ca_FR, Name: Catalan (France)
 269.653 +format locale: ID: ca_FR, Name: Catalan (France)
 269.654 +default charset: ISO-8859-15
 269.655 +
 269.656 +OS Locale:  ca_FR.utf8
 269.657 +default locale: ID: ca_FR, Name: Catalan (France)
 269.658 +display locale: ID: ca_FR, Name: Catalan (France)
 269.659 +format locale: ID: ca_FR, Name: Catalan (France)
 269.660 +default charset: UTF-8
 269.661 +
 269.662 +OS Locale:  ca_IT
 269.663 +default locale: ID: ca_IT, Name: Catalan (Italy)
 269.664 +display locale: ID: ca_IT, Name: Catalan (Italy)
 269.665 +format locale: ID: ca_IT, Name: Catalan (Italy)
 269.666 +default charset: ISO-8859-15
 269.667 +
 269.668 +OS Locale:  ca_IT.iso885915
 269.669 +default locale: ID: ca_IT, Name: Catalan (Italy)
 269.670 +display locale: ID: ca_IT, Name: Catalan (Italy)
 269.671 +format locale: ID: ca_IT, Name: Catalan (Italy)
 269.672 +default charset: ISO-8859-15
 269.673 +
 269.674 +OS Locale:  ca_IT.utf8
 269.675 +default locale: ID: ca_IT, Name: Catalan (Italy)
 269.676 +display locale: ID: ca_IT, Name: Catalan (Italy)
 269.677 +format locale: ID: ca_IT, Name: Catalan (Italy)
 269.678 +default charset: UTF-8
 269.679 +
 269.680 +OS Locale:  catalan
 269.681 +default locale: ID: ca_ES, Name: Catalan (Spain)
 269.682 +display locale: ID: ca_ES, Name: Catalan (Spain)
 269.683 +format locale: ID: ca_ES, Name: Catalan (Spain)
 269.684 +default charset: ISO-8859-1
 269.685 +
 269.686 +OS Locale:  croatian
 269.687 +default locale: ID: hr_HR, Name: Croatian (Croatia)
 269.688 +display locale: ID: hr_HR, Name: Croatian (Croatia)
 269.689 +format locale: ID: hr_HR, Name: Croatian (Croatia)
 269.690 +default charset: ISO-8859-2
 269.691 +
 269.692 +OS Locale:  cs_CZ
 269.693 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.694 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.695 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.696 +default charset: ISO-8859-2
 269.697 +
 269.698 +OS Locale:  cs_CZ.iso88592
 269.699 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.700 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.701 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.702 +default charset: ISO-8859-2
 269.703 +
 269.704 +OS Locale:  cs_CZ.utf8
 269.705 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.706 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.707 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.708 +default charset: UTF-8
 269.709 +
 269.710 +OS Locale:  csb_PL
 269.711 +default locale: ID: en_PL, Name: English (Poland)
 269.712 +display locale: ID: en_PL, Name: English (Poland)
 269.713 +format locale: ID: en_PL, Name: English (Poland)
 269.714 +default charset: UTF-8
 269.715 +
 269.716 +OS Locale:  csb_PL.utf8
 269.717 +default locale: ID: en_PL, Name: English (Poland)
 269.718 +display locale: ID: en_PL, Name: English (Poland)
 269.719 +format locale: ID: en_PL, Name: English (Poland)
 269.720 +default charset: UTF-8
 269.721 +
 269.722 +OS Locale:  cy_GB
 269.723 +default locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.724 +display locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.725 +format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.726 +default charset: UTF-8
 269.727 +
 269.728 +OS Locale:  cy_GB.iso885914
 269.729 +default locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.730 +display locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.731 +format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.732 +default charset: UTF-8
 269.733 +
 269.734 +OS Locale:  cy_GB.utf8
 269.735 +default locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.736 +display locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.737 +format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 269.738 +default charset: UTF-8
 269.739 +
 269.740 +OS Locale:  czech
 269.741 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.742 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.743 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 269.744 +default charset: ISO-8859-2
 269.745 +
 269.746 +OS Locale:  da_DK
 269.747 +default locale: ID: da_DK, Name: Danish (Denmark)
 269.748 +display locale: ID: da_DK, Name: Danish (Denmark)
 269.749 +format locale: ID: da_DK, Name: Danish (Denmark)
 269.750 +default charset: ISO-8859-1
 269.751 +
 269.752 +OS Locale:  da_DK.iso88591
 269.753 +default locale: ID: da_DK, Name: Danish (Denmark)
 269.754 +display locale: ID: da_DK, Name: Danish (Denmark)
 269.755 +format locale: ID: da_DK, Name: Danish (Denmark)
 269.756 +default charset: ISO-8859-1
 269.757 +
 269.758 +OS Locale:  da_DK.iso885915
 269.759 +default locale: ID: da_DK, Name: Danish (Denmark)
 269.760 +display locale: ID: da_DK, Name: Danish (Denmark)
 269.761 +format locale: ID: da_DK, Name: Danish (Denmark)
 269.762 +default charset: ISO-8859-15
 269.763 +
 269.764 +OS Locale:  da_DK.utf8
 269.765 +default locale: ID: da_DK, Name: Danish (Denmark)
 269.766 +display locale: ID: da_DK, Name: Danish (Denmark)
 269.767 +format locale: ID: da_DK, Name: Danish (Denmark)
 269.768 +default charset: UTF-8
 269.769 +
 269.770 +OS Locale:  danish
 269.771 +default locale: ID: da_DK, Name: Danish (Denmark)
 269.772 +display locale: ID: da_DK, Name: Danish (Denmark)
 269.773 +format locale: ID: da_DK, Name: Danish (Denmark)
 269.774 +default charset: ISO-8859-1
 269.775 +
 269.776 +OS Locale:  dansk
 269.777 +default locale: ID: da_DK, Name: Danish (Denmark)
 269.778 +display locale: ID: da_DK, Name: Danish (Denmark)
 269.779 +format locale: ID: da_DK, Name: Danish (Denmark)
 269.780 +default charset: ISO-8859-1
 269.781 +
 269.782 +OS Locale:  de_AT
 269.783 +default locale: ID: de_AT, Name: German (Austria)
 269.784 +display locale: ID: de_AT, Name: German (Austria)
 269.785 +format locale: ID: de_AT, Name: German (Austria)
 269.786 +default charset: ISO-8859-1
 269.787 +
 269.788 +OS Locale:  de_AT.iso88591
 269.789 +default locale: ID: de_AT, Name: German (Austria)
 269.790 +display locale: ID: de_AT, Name: German (Austria)
 269.791 +format locale: ID: de_AT, Name: German (Austria)
 269.792 +default charset: ISO-8859-1
 269.793 +
 269.794 +OS Locale:  de_AT.iso885915@euro
 269.795 +default locale: ID: de_AT, Name: German (Austria)
 269.796 +display locale: ID: de_AT, Name: German (Austria)
 269.797 +format locale: ID: de_AT, Name: German (Austria)
 269.798 +default charset: ISO-8859-15
 269.799 +
 269.800 +OS Locale:  de_AT.utf8
 269.801 +default locale: ID: de_AT, Name: German (Austria)
 269.802 +display locale: ID: de_AT, Name: German (Austria)
 269.803 +format locale: ID: de_AT, Name: German (Austria)
 269.804 +default charset: UTF-8
 269.805 +
 269.806 +OS Locale:  de_AT@euro
 269.807 +default locale: ID: de_AT, Name: German (Austria)
 269.808 +display locale: ID: de_AT, Name: German (Austria)
 269.809 +format locale: ID: de_AT, Name: German (Austria)
 269.810 +default charset: ISO-8859-15
 269.811 +
 269.812 +OS Locale:  de_BE
 269.813 +default locale: ID: de_BE, Name: German (Belgium)
 269.814 +display locale: ID: de_BE, Name: German (Belgium)
 269.815 +format locale: ID: de_BE, Name: German (Belgium)
 269.816 +default charset: ISO-8859-1
 269.817 +
 269.818 +OS Locale:  de_BE.iso88591
 269.819 +default locale: ID: de_BE, Name: German (Belgium)
 269.820 +display locale: ID: de_BE, Name: German (Belgium)
 269.821 +format locale: ID: de_BE, Name: German (Belgium)
 269.822 +default charset: ISO-8859-1
 269.823 +
 269.824 +OS Locale:  de_BE.iso885915@euro
 269.825 +default locale: ID: de_BE, Name: German (Belgium)
 269.826 +display locale: ID: de_BE, Name: German (Belgium)
 269.827 +format locale: ID: de_BE, Name: German (Belgium)
 269.828 +default charset: ISO-8859-15
 269.829 +
 269.830 +OS Locale:  de_BE.utf8
 269.831 +default locale: ID: de_BE, Name: German (Belgium)
 269.832 +display locale: ID: de_BE, Name: German (Belgium)
 269.833 +format locale: ID: de_BE, Name: German (Belgium)
 269.834 +default charset: UTF-8
 269.835 +
 269.836 +OS Locale:  de_BE@euro
 269.837 +default locale: ID: de_BE, Name: German (Belgium)
 269.838 +display locale: ID: de_BE, Name: German (Belgium)
 269.839 +format locale: ID: de_BE, Name: German (Belgium)
 269.840 +default charset: ISO-8859-15
 269.841 +
 269.842 +OS Locale:  de_CH
 269.843 +default locale: ID: de_CH, Name: German (Switzerland)
 269.844 +display locale: ID: de_CH, Name: German (Switzerland)
 269.845 +format locale: ID: de_CH, Name: German (Switzerland)
 269.846 +default charset: ISO-8859-1
 269.847 +
 269.848 +OS Locale:  de_CH.iso88591
 269.849 +default locale: ID: de_CH, Name: German (Switzerland)
 269.850 +display locale: ID: de_CH, Name: German (Switzerland)
 269.851 +format locale: ID: de_CH, Name: German (Switzerland)
 269.852 +default charset: ISO-8859-1
 269.853 +
 269.854 +OS Locale:  de_CH.utf8
 269.855 +default locale: ID: de_CH, Name: German (Switzerland)
 269.856 +display locale: ID: de_CH, Name: German (Switzerland)
 269.857 +format locale: ID: de_CH, Name: German (Switzerland)
 269.858 +default charset: UTF-8
 269.859 +
 269.860 +OS Locale:  de_DE
 269.861 +default locale: ID: de_DE, Name: German (Germany)
 269.862 +display locale: ID: de_DE, Name: German (Germany)
 269.863 +format locale: ID: de_DE, Name: German (Germany)
 269.864 +default charset: ISO-8859-1
 269.865 +
 269.866 +OS Locale:  de_DE.iso88591
 269.867 +default locale: ID: de_DE, Name: German (Germany)
 269.868 +display locale: ID: de_DE, Name: German (Germany)
 269.869 +format locale: ID: de_DE, Name: German (Germany)
 269.870 +default charset: ISO-8859-1
 269.871 +
 269.872 +OS Locale:  de_DE.iso885915@euro
 269.873 +default locale: ID: de_DE, Name: German (Germany)
 269.874 +display locale: ID: de_DE, Name: German (Germany)
 269.875 +format locale: ID: de_DE, Name: German (Germany)
 269.876 +default charset: ISO-8859-15
 269.877 +
 269.878 +OS Locale:  de_DE.utf8
 269.879 +default locale: ID: de_DE, Name: German (Germany)
 269.880 +display locale: ID: de_DE, Name: German (Germany)
 269.881 +format locale: ID: de_DE, Name: German (Germany)
 269.882 +default charset: UTF-8
 269.883 +
 269.884 +OS Locale:  de_DE@euro
 269.885 +default locale: ID: de_DE, Name: German (Germany)
 269.886 +display locale: ID: de_DE, Name: German (Germany)
 269.887 +format locale: ID: de_DE, Name: German (Germany)
 269.888 +default charset: ISO-8859-15
 269.889 +
 269.890 +OS Locale:  de_LU
 269.891 +default locale: ID: de_LU, Name: German (Luxembourg)
 269.892 +display locale: ID: de_LU, Name: German (Luxembourg)
 269.893 +format locale: ID: de_LU, Name: German (Luxembourg)
 269.894 +default charset: ISO-8859-1
 269.895 +
 269.896 +OS Locale:  de_LU.iso88591
 269.897 +default locale: ID: de_LU, Name: German (Luxembourg)
 269.898 +display locale: ID: de_LU, Name: German (Luxembourg)
 269.899 +format locale: ID: de_LU, Name: German (Luxembourg)
 269.900 +default charset: ISO-8859-1
 269.901 +
 269.902 +OS Locale:  de_LU.iso885915@euro
 269.903 +default locale: ID: de_LU, Name: German (Luxembourg)
 269.904 +display locale: ID: de_LU, Name: German (Luxembourg)
 269.905 +format locale: ID: de_LU, Name: German (Luxembourg)
 269.906 +default charset: ISO-8859-15
 269.907 +
 269.908 +OS Locale:  de_LU.utf8
 269.909 +default locale: ID: de_LU, Name: German (Luxembourg)
 269.910 +display locale: ID: de_LU, Name: German (Luxembourg)
 269.911 +format locale: ID: de_LU, Name: German (Luxembourg)
 269.912 +default charset: UTF-8
 269.913 +
 269.914 +OS Locale:  de_LU@euro
 269.915 +default locale: ID: de_LU, Name: German (Luxembourg)
 269.916 +display locale: ID: de_LU, Name: German (Luxembourg)
 269.917 +format locale: ID: de_LU, Name: German (Luxembourg)
 269.918 +default charset: ISO-8859-15
 269.919 +
 269.920 +OS Locale:  deutsch
 269.921 +default locale: ID: de_DE, Name: German (Germany)
 269.922 +display locale: ID: de_DE, Name: German (Germany)
 269.923 +format locale: ID: de_DE, Name: German (Germany)
 269.924 +default charset: ISO-8859-1
 269.925 +
 269.926 +OS Locale:  dutch
 269.927 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
 269.928 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
 269.929 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
 269.930 +default charset: ISO-8859-1
 269.931 +
 269.932 +OS Locale:  dz_BT
 269.933 +default locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 269.934 +display locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 269.935 +format locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 269.936 +default charset: UTF-8
 269.937 +
 269.938 +OS Locale:  dz_BT.utf8
 269.939 +default locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 269.940 +display locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 269.941 +format locale: ID: dz_BT, Name: Dzongkha (Bhutan)
 269.942 +default charset: UTF-8
 269.943 +
 269.944 +OS Locale:  eesti
 269.945 +default locale: ID: en, Name: English
 269.946 +display locale: ID: en, Name: English
 269.947 +format locale: ID: en, Name: English
 269.948 +default charset: ISO-8859-1
 269.949 +
 269.950 +OS Locale:  el_CY
 269.951 +default locale: ID: el_CY, Name: Greek (Cyprus)
 269.952 +display locale: ID: el_CY, Name: Greek (Cyprus)
 269.953 +format locale: ID: el_CY, Name: Greek (Cyprus)
 269.954 +default charset: ISO-8859-7
 269.955 +
 269.956 +OS Locale:  el_CY.iso88597
 269.957 +default locale: ID: el_CY, Name: Greek (Cyprus)
 269.958 +display locale: ID: el_CY, Name: Greek (Cyprus)
 269.959 +format locale: ID: el_CY, Name: Greek (Cyprus)
 269.960 +default charset: ISO-8859-7
 269.961 +
 269.962 +OS Locale:  el_CY.utf8
 269.963 +default locale: ID: el_CY, Name: Greek (Cyprus)
 269.964 +display locale: ID: el_CY, Name: Greek (Cyprus)
 269.965 +format locale: ID: el_CY, Name: Greek (Cyprus)
 269.966 +default charset: UTF-8
 269.967 +
 269.968 +OS Locale:  el_GR
 269.969 +default locale: ID: el_GR, Name: Greek (Greece)
 269.970 +display locale: ID: el_GR, Name: Greek (Greece)
 269.971 +format locale: ID: el_GR, Name: Greek (Greece)
 269.972 +default charset: ISO-8859-7
 269.973 +
 269.974 +OS Locale:  el_GR.iso88597
 269.975 +default locale: ID: el_GR, Name: Greek (Greece)
 269.976 +display locale: ID: el_GR, Name: Greek (Greece)
 269.977 +format locale: ID: el_GR, Name: Greek (Greece)
 269.978 +default charset: ISO-8859-7
 269.979 +
 269.980 +OS Locale:  el_GR.utf8
 269.981 +default locale: ID: el_GR, Name: Greek (Greece)
 269.982 +display locale: ID: el_GR, Name: Greek (Greece)
 269.983 +format locale: ID: el_GR, Name: Greek (Greece)
 269.984 +default charset: UTF-8
 269.985 +
 269.986 +OS Locale:  en_AU
 269.987 +default locale: ID: en_AU, Name: English (Australia)
 269.988 +display locale: ID: en_AU, Name: English (Australia)
 269.989 +format locale: ID: en_AU, Name: English (Australia)
 269.990 +default charset: ISO-8859-1
 269.991 +
 269.992 +OS Locale:  en_AU.iso88591
 269.993 +default locale: ID: en_AU, Name: English (Australia)
 269.994 +display locale: ID: en_AU, Name: English (Australia)
 269.995 +format locale: ID: en_AU, Name: English (Australia)
 269.996 +default charset: ISO-8859-1
 269.997 +
 269.998 +OS Locale:  en_AU.utf8
 269.999 +default locale: ID: en_AU, Name: English (Australia)
269.1000 +display locale: ID: en_AU, Name: English (Australia)
269.1001 +format locale: ID: en_AU, Name: English (Australia)
269.1002 +default charset: UTF-8
269.1003 +
269.1004 +OS Locale:  en_BW
269.1005 +default locale: ID: en_BW, Name: English (Botswana)
269.1006 +display locale: ID: en_BW, Name: English (Botswana)
269.1007 +format locale: ID: en_BW, Name: English (Botswana)
269.1008 +default charset: ISO-8859-1
269.1009 +
269.1010 +OS Locale:  en_BW.iso88591
269.1011 +default locale: ID: en_BW, Name: English (Botswana)
269.1012 +display locale: ID: en_BW, Name: English (Botswana)
269.1013 +format locale: ID: en_BW, Name: English (Botswana)
269.1014 +default charset: ISO-8859-1
269.1015 +
269.1016 +OS Locale:  en_BW.utf8
269.1017 +default locale: ID: en_BW, Name: English (Botswana)
269.1018 +display locale: ID: en_BW, Name: English (Botswana)
269.1019 +format locale: ID: en_BW, Name: English (Botswana)
269.1020 +default charset: UTF-8
269.1021 +
269.1022 +OS Locale:  en_CA
269.1023 +default locale: ID: en_CA, Name: English (Canada)
269.1024 +display locale: ID: en_CA, Name: English (Canada)
269.1025 +format locale: ID: en_CA, Name: English (Canada)
269.1026 +default charset: ISO-8859-1
269.1027 +
269.1028 +OS Locale:  en_CA.iso88591
269.1029 +default locale: ID: en_CA, Name: English (Canada)
269.1030 +display locale: ID: en_CA, Name: English (Canada)
269.1031 +format locale: ID: en_CA, Name: English (Canada)
269.1032 +default charset: ISO-8859-1
269.1033 +
269.1034 +OS Locale:  en_CA.utf8
269.1035 +default locale: ID: en_CA, Name: English (Canada)
269.1036 +display locale: ID: en_CA, Name: English (Canada)
269.1037 +format locale: ID: en_CA, Name: English (Canada)
269.1038 +default charset: UTF-8
269.1039 +
269.1040 +OS Locale:  en_DK
269.1041 +default locale: ID: en_DK, Name: English (Denmark)
269.1042 +display locale: ID: en_DK, Name: English (Denmark)
269.1043 +format locale: ID: en_DK, Name: English (Denmark)
269.1044 +default charset: ISO-8859-1
269.1045 +
269.1046 +OS Locale:  en_DK.iso88591
269.1047 +default locale: ID: en_DK, Name: English (Denmark)
269.1048 +display locale: ID: en_DK, Name: English (Denmark)
269.1049 +format locale: ID: en_DK, Name: English (Denmark)
269.1050 +default charset: ISO-8859-1
269.1051 +
269.1052 +OS Locale:  en_DK.utf8
269.1053 +default locale: ID: en_DK, Name: English (Denmark)
269.1054 +display locale: ID: en_DK, Name: English (Denmark)
269.1055 +format locale: ID: en_DK, Name: English (Denmark)
269.1056 +default charset: UTF-8
269.1057 +
269.1058 +OS Locale:  en_GB
269.1059 +default locale: ID: en_GB, Name: English (United Kingdom)
269.1060 +display locale: ID: en_GB, Name: English (United Kingdom)
269.1061 +format locale: ID: en_GB, Name: English (United Kingdom)
269.1062 +default charset: ISO-8859-1
269.1063 +
269.1064 +OS Locale:  en_GB.iso88591
269.1065 +default locale: ID: en_GB, Name: English (United Kingdom)
269.1066 +display locale: ID: en_GB, Name: English (United Kingdom)
269.1067 +format locale: ID: en_GB, Name: English (United Kingdom)
269.1068 +default charset: ISO-8859-1
269.1069 +
269.1070 +OS Locale:  en_GB.iso885915
269.1071 +default locale: ID: en_GB, Name: English (United Kingdom)
269.1072 +display locale: ID: en_GB, Name: English (United Kingdom)
269.1073 +format locale: ID: en_GB, Name: English (United Kingdom)
269.1074 +default charset: ISO-8859-15
269.1075 +
269.1076 +OS Locale:  en_GB.utf8
269.1077 +default locale: ID: en_GB, Name: English (United Kingdom)
269.1078 +display locale: ID: en_GB, Name: English (United Kingdom)
269.1079 +format locale: ID: en_GB, Name: English (United Kingdom)
269.1080 +default charset: UTF-8
269.1081 +
269.1082 +OS Locale:  en_HK
269.1083 +default locale: ID: en_HK, Name: English (Hong Kong)
269.1084 +display locale: ID: en_HK, Name: English (Hong Kong)
269.1085 +format locale: ID: en_HK, Name: English (Hong Kong)
269.1086 +default charset: ISO-8859-1
269.1087 +
269.1088 +OS Locale:  en_HK.iso88591
269.1089 +default locale: ID: en_HK, Name: English (Hong Kong)
269.1090 +display locale: ID: en_HK, Name: English (Hong Kong)
269.1091 +format locale: ID: en_HK, Name: English (Hong Kong)
269.1092 +default charset: ISO-8859-1
269.1093 +
269.1094 +OS Locale:  en_HK.utf8
269.1095 +default locale: ID: en_HK, Name: English (Hong Kong)
269.1096 +display locale: ID: en_HK, Name: English (Hong Kong)
269.1097 +format locale: ID: en_HK, Name: English (Hong Kong)
269.1098 +default charset: UTF-8
269.1099 +
269.1100 +OS Locale:  en_IE
269.1101 +default locale: ID: en_IE, Name: English (Ireland)
269.1102 +display locale: ID: en_IE, Name: English (Ireland)
269.1103 +format locale: ID: en_IE, Name: English (Ireland)
269.1104 +default charset: ISO-8859-1
269.1105 +
269.1106 +OS Locale:  en_IE.iso88591
269.1107 +default locale: ID: en_IE, Name: English (Ireland)
269.1108 +display locale: ID: en_IE, Name: English (Ireland)
269.1109 +format locale: ID: en_IE, Name: English (Ireland)
269.1110 +default charset: ISO-8859-1
269.1111 +
269.1112 +OS Locale:  en_IE.iso885915@euro
269.1113 +default locale: ID: en_IE, Name: English (Ireland)
269.1114 +display locale: ID: en_IE, Name: English (Ireland)
269.1115 +format locale: ID: en_IE, Name: English (Ireland)
269.1116 +default charset: ISO-8859-15
269.1117 +
269.1118 +OS Locale:  en_IE.utf8
269.1119 +default locale: ID: en_IE, Name: English (Ireland)
269.1120 +display locale: ID: en_IE, Name: English (Ireland)
269.1121 +format locale: ID: en_IE, Name: English (Ireland)
269.1122 +default charset: UTF-8
269.1123 +
269.1124 +OS Locale:  en_IE@euro
269.1125 +default locale: ID: en_IE, Name: English (Ireland)
269.1126 +display locale: ID: en_IE, Name: English (Ireland)
269.1127 +format locale: ID: en_IE, Name: English (Ireland)
269.1128 +default charset: ISO-8859-15
269.1129 +
269.1130 +OS Locale:  en_IN
269.1131 +default locale: ID: en_IN, Name: English (India)
269.1132 +display locale: ID: en_IN, Name: English (India)
269.1133 +format locale: ID: en_IN, Name: English (India)
269.1134 +default charset: UTF-8
269.1135 +
269.1136 +OS Locale:  en_IN.utf8
269.1137 +default locale: ID: en_IN, Name: English (India)
269.1138 +display locale: ID: en_IN, Name: English (India)
269.1139 +format locale: ID: en_IN, Name: English (India)
269.1140 +default charset: UTF-8
269.1141 +
269.1142 +OS Locale:  en_NZ
269.1143 +default locale: ID: en_NZ, Name: English (New Zealand)
269.1144 +display locale: ID: en_NZ, Name: English (New Zealand)
269.1145 +format locale: ID: en_NZ, Name: English (New Zealand)
269.1146 +default charset: ISO-8859-1
269.1147 +
269.1148 +OS Locale:  en_NZ.iso88591
269.1149 +default locale: ID: en_NZ, Name: English (New Zealand)
269.1150 +display locale: ID: en_NZ, Name: English (New Zealand)
269.1151 +format locale: ID: en_NZ, Name: English (New Zealand)
269.1152 +default charset: ISO-8859-1
269.1153 +
269.1154 +OS Locale:  en_NZ.utf8
269.1155 +default locale: ID: en_NZ, Name: English (New Zealand)
269.1156 +display locale: ID: en_NZ, Name: English (New Zealand)
269.1157 +format locale: ID: en_NZ, Name: English (New Zealand)
269.1158 +default charset: UTF-8
269.1159 +
269.1160 +OS Locale:  en_PH
269.1161 +default locale: ID: en_PH, Name: English (Philippines)
269.1162 +display locale: ID: en_PH, Name: English (Philippines)
269.1163 +format locale: ID: en_PH, Name: English (Philippines)
269.1164 +default charset: ISO-8859-1
269.1165 +
269.1166 +OS Locale:  en_PH.iso88591
269.1167 +default locale: ID: en_PH, Name: English (Philippines)
269.1168 +display locale: ID: en_PH, Name: English (Philippines)
269.1169 +format locale: ID: en_PH, Name: English (Philippines)
269.1170 +default charset: ISO-8859-1
269.1171 +
269.1172 +OS Locale:  en_PH.utf8
269.1173 +default locale: ID: en_PH, Name: English (Philippines)
269.1174 +display locale: ID: en_PH, Name: English (Philippines)
269.1175 +format locale: ID: en_PH, Name: English (Philippines)
269.1176 +default charset: UTF-8
269.1177 +
269.1178 +OS Locale:  en_SG
269.1179 +default locale: ID: en_SG, Name: English (Singapore)
269.1180 +display locale: ID: en_SG, Name: English (Singapore)
269.1181 +format locale: ID: en_SG, Name: English (Singapore)
269.1182 +default charset: ISO-8859-1
269.1183 +
269.1184 +OS Locale:  en_SG.iso88591
269.1185 +default locale: ID: en_SG, Name: English (Singapore)
269.1186 +display locale: ID: en_SG, Name: English (Singapore)
269.1187 +format locale: ID: en_SG, Name: English (Singapore)
269.1188 +default charset: ISO-8859-1
269.1189 +
269.1190 +OS Locale:  en_SG.utf8
269.1191 +default locale: ID: en_SG, Name: English (Singapore)
269.1192 +display locale: ID: en_SG, Name: English (Singapore)
269.1193 +format locale: ID: en_SG, Name: English (Singapore)
269.1194 +default charset: UTF-8
269.1195 +
269.1196 +OS Locale:  en_US
269.1197 +default locale: ID: en_US, Name: English (United States)
269.1198 +display locale: ID: en_US, Name: English (United States)
269.1199 +format locale: ID: en_US, Name: English (United States)
269.1200 +default charset: ISO-8859-1
269.1201 +
269.1202 +OS Locale:  en_US.iso88591
269.1203 +default locale: ID: en_US, Name: English (United States)
269.1204 +display locale: ID: en_US, Name: English (United States)
269.1205 +format locale: ID: en_US, Name: English (United States)
269.1206 +default charset: ISO-8859-1
269.1207 +
269.1208 +OS Locale:  en_US.iso885915
269.1209 +default locale: ID: en_US, Name: English (United States)
269.1210 +display locale: ID: en_US, Name: English (United States)
269.1211 +format locale: ID: en_US, Name: English (United States)
269.1212 +default charset: ISO-8859-15
269.1213 +
269.1214 +OS Locale:  en_US.utf8
269.1215 +default locale: ID: en_US, Name: English (United States)
269.1216 +display locale: ID: en_US, Name: English (United States)
269.1217 +format locale: ID: en_US, Name: English (United States)
269.1218 +default charset: UTF-8
269.1219 +
269.1220 +OS Locale:  en_ZA
269.1221 +default locale: ID: en_ZA, Name: English (South Africa)
269.1222 +display locale: ID: en_ZA, Name: English (South Africa)
269.1223 +format locale: ID: en_ZA, Name: English (South Africa)
269.1224 +default charset: ISO-8859-1
269.1225 +
269.1226 +OS Locale:  en_ZA.iso88591
269.1227 +default locale: ID: en_ZA, Name: English (South Africa)
269.1228 +display locale: ID: en_ZA, Name: English (South Africa)
269.1229 +format locale: ID: en_ZA, Name: English (South Africa)
269.1230 +default charset: ISO-8859-1
269.1231 +
269.1232 +OS Locale:  en_ZA.utf8
269.1233 +default locale: ID: en_ZA, Name: English (South Africa)
269.1234 +display locale: ID: en_ZA, Name: English (South Africa)
269.1235 +format locale: ID: en_ZA, Name: English (South Africa)
269.1236 +default charset: UTF-8
269.1237 +
269.1238 +OS Locale:  en_ZW
269.1239 +default locale: ID: en_ZW, Name: English (Zimbabwe)
269.1240 +display locale: ID: en_ZW, Name: English (Zimbabwe)
269.1241 +format locale: ID: en_ZW, Name: English (Zimbabwe)
269.1242 +default charset: ISO-8859-1
269.1243 +
269.1244 +OS Locale:  en_ZW.iso88591
269.1245 +default locale: ID: en_ZW, Name: English (Zimbabwe)
269.1246 +display locale: ID: en_ZW, Name: English (Zimbabwe)
269.1247 +format locale: ID: en_ZW, Name: English (Zimbabwe)
269.1248 +default charset: ISO-8859-1
269.1249 +
269.1250 +OS Locale:  en_ZW.utf8
269.1251 +default locale: ID: en_ZW, Name: English (Zimbabwe)
269.1252 +display locale: ID: en_ZW, Name: English (Zimbabwe)
269.1253 +format locale: ID: en_ZW, Name: English (Zimbabwe)
269.1254 +default charset: UTF-8
269.1255 +
269.1256 +OS Locale:  es_AR
269.1257 +default locale: ID: es_AR, Name: Spanish (Argentina)
269.1258 +display locale: ID: es_AR, Name: Spanish (Argentina)
269.1259 +format locale: ID: es_AR, Name: Spanish (Argentina)
269.1260 +default charset: ISO-8859-1
269.1261 +
269.1262 +OS Locale:  es_AR.iso88591
269.1263 +default locale: ID: es_AR, Name: Spanish (Argentina)
269.1264 +display locale: ID: es_AR, Name: Spanish (Argentina)
269.1265 +format locale: ID: es_AR, Name: Spanish (Argentina)
269.1266 +default charset: ISO-8859-1
269.1267 +
269.1268 +OS Locale:  es_AR.utf8
269.1269 +default locale: ID: es_AR, Name: Spanish (Argentina)
269.1270 +display locale: ID: es_AR, Name: Spanish (Argentina)
269.1271 +format locale: ID: es_AR, Name: Spanish (Argentina)
269.1272 +default charset: UTF-8
269.1273 +
269.1274 +OS Locale:  es_BO
269.1275 +default locale: ID: es_BO, Name: Spanish (Bolivia)
269.1276 +display locale: ID: es_BO, Name: Spanish (Bolivia)
269.1277 +format locale: ID: es_BO, Name: Spanish (Bolivia)
269.1278 +default charset: ISO-8859-1
269.1279 +
269.1280 +OS Locale:  es_BO.iso88591
269.1281 +default locale: ID: es_BO, Name: Spanish (Bolivia)
269.1282 +display locale: ID: es_BO, Name: Spanish (Bolivia)
269.1283 +format locale: ID: es_BO, Name: Spanish (Bolivia)
269.1284 +default charset: ISO-8859-1
269.1285 +
269.1286 +OS Locale:  es_BO.utf8
269.1287 +default locale: ID: es_BO, Name: Spanish (Bolivia)
269.1288 +display locale: ID: es_BO, Name: Spanish (Bolivia)
269.1289 +format locale: ID: es_BO, Name: Spanish (Bolivia)
269.1290 +default charset: UTF-8
269.1291 +
269.1292 +OS Locale:  es_CL
269.1293 +default locale: ID: es_CL, Name: Spanish (Chile)
269.1294 +display locale: ID: es_CL, Name: Spanish (Chile)
269.1295 +format locale: ID: es_CL, Name: Spanish (Chile)
269.1296 +default charset: ISO-8859-1
269.1297 +
269.1298 +OS Locale:  es_CL.iso88591
269.1299 +default locale: ID: es_CL, Name: Spanish (Chile)
269.1300 +display locale: ID: es_CL, Name: Spanish (Chile)
269.1301 +format locale: ID: es_CL, Name: Spanish (Chile)
269.1302 +default charset: ISO-8859-1
269.1303 +
269.1304 +OS Locale:  es_CL.utf8
269.1305 +default locale: ID: es_CL, Name: Spanish (Chile)
269.1306 +display locale: ID: es_CL, Name: Spanish (Chile)
269.1307 +format locale: ID: es_CL, Name: Spanish (Chile)
269.1308 +default charset: UTF-8
269.1309 +
269.1310 +OS Locale:  es_CO
269.1311 +default locale: ID: es_CO, Name: Spanish (Colombia)
269.1312 +display locale: ID: es_CO, Name: Spanish (Colombia)
269.1313 +format locale: ID: es_CO, Name: Spanish (Colombia)
269.1314 +default charset: ISO-8859-1
269.1315 +
269.1316 +OS Locale:  es_CO.iso88591
269.1317 +default locale: ID: es_CO, Name: Spanish (Colombia)
269.1318 +display locale: ID: es_CO, Name: Spanish (Colombia)
269.1319 +format locale: ID: es_CO, Name: Spanish (Colombia)
269.1320 +default charset: ISO-8859-1
269.1321 +
269.1322 +OS Locale:  es_CO.utf8
269.1323 +default locale: ID: es_CO, Name: Spanish (Colombia)
269.1324 +display locale: ID: es_CO, Name: Spanish (Colombia)
269.1325 +format locale: ID: es_CO, Name: Spanish (Colombia)
269.1326 +default charset: UTF-8
269.1327 +
269.1328 +OS Locale:  es_CR
269.1329 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1330 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1331 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1332 +default charset: ISO-8859-1
269.1333 +
269.1334 +OS Locale:  es_CR.iso88591
269.1335 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1336 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1337 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1338 +default charset: ISO-8859-1
269.1339 +
269.1340 +OS Locale:  es_CR.utf8
269.1341 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1342 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1343 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
269.1344 +default charset: UTF-8
269.1345 +
269.1346 +OS Locale:  es_DO
269.1347 +default locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1348 +display locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1349 +format locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1350 +default charset: ISO-8859-1
269.1351 +
269.1352 +OS Locale:  es_DO.iso88591
269.1353 +default locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1354 +display locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1355 +format locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1356 +default charset: ISO-8859-1
269.1357 +
269.1358 +OS Locale:  es_DO.utf8
269.1359 +default locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1360 +display locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1361 +format locale: ID: es_DO, Name: Spanish (Dominican Republic)
269.1362 +default charset: UTF-8
269.1363 +
269.1364 +OS Locale:  es_EC
269.1365 +default locale: ID: es_EC, Name: Spanish (Ecuador)
269.1366 +display locale: ID: es_EC, Name: Spanish (Ecuador)
269.1367 +format locale: ID: es_EC, Name: Spanish (Ecuador)
269.1368 +default charset: ISO-8859-1
269.1369 +
269.1370 +OS Locale:  es_EC.iso88591
269.1371 +default locale: ID: es_EC, Name: Spanish (Ecuador)
269.1372 +display locale: ID: es_EC, Name: Spanish (Ecuador)
269.1373 +format locale: ID: es_EC, Name: Spanish (Ecuador)
269.1374 +default charset: ISO-8859-1
269.1375 +
269.1376 +OS Locale:  es_EC.utf8
269.1377 +default locale: ID: es_EC, Name: Spanish (Ecuador)
269.1378 +display locale: ID: es_EC, Name: Spanish (Ecuador)
269.1379 +format locale: ID: es_EC, Name: Spanish (Ecuador)
269.1380 +default charset: UTF-8
269.1381 +
269.1382 +OS Locale:  es_ES
269.1383 +default locale: ID: es_ES, Name: Spanish (Spain)
269.1384 +display locale: ID: es_ES, Name: Spanish (Spain)
269.1385 +format locale: ID: es_ES, Name: Spanish (Spain)
269.1386 +default charset: ISO-8859-1
269.1387 +
269.1388 +OS Locale:  es_ES.iso88591
269.1389 +default locale: ID: es_ES, Name: Spanish (Spain)
269.1390 +display locale: ID: es_ES, Name: Spanish (Spain)
269.1391 +format locale: ID: es_ES, Name: Spanish (Spain)
269.1392 +default charset: ISO-8859-1
269.1393 +
269.1394 +OS Locale:  es_ES.iso885915@euro
269.1395 +default locale: ID: es_ES, Name: Spanish (Spain)
269.1396 +display locale: ID: es_ES, Name: Spanish (Spain)
269.1397 +format locale: ID: es_ES, Name: Spanish (Spain)
269.1398 +default charset: ISO-8859-15
269.1399 +
269.1400 +OS Locale:  es_ES.utf8
269.1401 +default locale: ID: es_ES, Name: Spanish (Spain)
269.1402 +display locale: ID: es_ES, Name: Spanish (Spain)
269.1403 +format locale: ID: es_ES, Name: Spanish (Spain)
269.1404 +default charset: UTF-8
269.1405 +
269.1406 +OS Locale:  es_ES@euro
269.1407 +default locale: ID: es_ES, Name: Spanish (Spain)
269.1408 +display locale: ID: es_ES, Name: Spanish (Spain)
269.1409 +format locale: ID: es_ES, Name: Spanish (Spain)
269.1410 +default charset: ISO-8859-15
269.1411 +
269.1412 +OS Locale:  es_GT
269.1413 +default locale: ID: es_GT, Name: Spanish (Guatemala)
269.1414 +display locale: ID: es_GT, Name: Spanish (Guatemala)
269.1415 +format locale: ID: es_GT, Name: Spanish (Guatemala)
269.1416 +default charset: ISO-8859-1
269.1417 +
269.1418 +OS Locale:  es_GT.iso88591
269.1419 +default locale: ID: es_GT, Name: Spanish (Guatemala)
269.1420 +display locale: ID: es_GT, Name: Spanish (Guatemala)
269.1421 +format locale: ID: es_GT, Name: Spanish (Guatemala)
269.1422 +default charset: ISO-8859-1
269.1423 +
269.1424 +OS Locale:  es_GT.utf8
269.1425 +default locale: ID: es_GT, Name: Spanish (Guatemala)
269.1426 +display locale: ID: es_GT, Name: Spanish (Guatemala)
269.1427 +format locale: ID: es_GT, Name: Spanish (Guatemala)
269.1428 +default charset: UTF-8
269.1429 +
269.1430 +OS Locale:  es_HN
269.1431 +default locale: ID: es_HN, Name: Spanish (Honduras)
269.1432 +display locale: ID: es_HN, Name: Spanish (Honduras)
269.1433 +format locale: ID: es_HN, Name: Spanish (Honduras)
269.1434 +default charset: ISO-8859-1
269.1435 +
269.1436 +OS Locale:  es_HN.iso88591
269.1437 +default locale: ID: es_HN, Name: Spanish (Honduras)
269.1438 +display locale: ID: es_HN, Name: Spanish (Honduras)
269.1439 +format locale: ID: es_HN, Name: Spanish (Honduras)
269.1440 +default charset: ISO-8859-1
269.1441 +
269.1442 +OS Locale:  es_HN.utf8
269.1443 +default locale: ID: es_HN, Name: Spanish (Honduras)
269.1444 +display locale: ID: es_HN, Name: Spanish (Honduras)
269.1445 +format locale: ID: es_HN, Name: Spanish (Honduras)
269.1446 +default charset: UTF-8
269.1447 +
269.1448 +OS Locale:  es_MX
269.1449 +default locale: ID: es_MX, Name: Spanish (Mexico)
269.1450 +display locale: ID: es_MX, Name: Spanish (Mexico)
269.1451 +format locale: ID: es_MX, Name: Spanish (Mexico)
269.1452 +default charset: ISO-8859-1
269.1453 +
269.1454 +OS Locale:  es_MX.iso88591
269.1455 +default locale: ID: es_MX, Name: Spanish (Mexico)
269.1456 +display locale: ID: es_MX, Name: Spanish (Mexico)
269.1457 +format locale: ID: es_MX, Name: Spanish (Mexico)
269.1458 +default charset: ISO-8859-1
269.1459 +
269.1460 +OS Locale:  es_MX.utf8
269.1461 +default locale: ID: es_MX, Name: Spanish (Mexico)
269.1462 +display locale: ID: es_MX, Name: Spanish (Mexico)
269.1463 +format locale: ID: es_MX, Name: Spanish (Mexico)
269.1464 +default charset: UTF-8
269.1465 +
269.1466 +OS Locale:  es_NI
269.1467 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1468 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1469 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1470 +default charset: ISO-8859-1
269.1471 +
269.1472 +OS Locale:  es_NI.iso88591
269.1473 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1474 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1475 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1476 +default charset: ISO-8859-1
269.1477 +
269.1478 +OS Locale:  es_NI.utf8
269.1479 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1480 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1481 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
269.1482 +default charset: UTF-8
269.1483 +
269.1484 +OS Locale:  es_PA
269.1485 +default locale: ID: es_PA, Name: Spanish (Panama)
269.1486 +display locale: ID: es_PA, Name: Spanish (Panama)
269.1487 +format locale: ID: es_PA, Name: Spanish (Panama)
269.1488 +default charset: ISO-8859-1
269.1489 +
269.1490 +OS Locale:  es_PA.iso88591
269.1491 +default locale: ID: es_PA, Name: Spanish (Panama)
269.1492 +display locale: ID: es_PA, Name: Spanish (Panama)
269.1493 +format locale: ID: es_PA, Name: Spanish (Panama)
269.1494 +default charset: ISO-8859-1
269.1495 +
269.1496 +OS Locale:  es_PA.utf8
269.1497 +default locale: ID: es_PA, Name: Spanish (Panama)
269.1498 +display locale: ID: es_PA, Name: Spanish (Panama)
269.1499 +format locale: ID: es_PA, Name: Spanish (Panama)
269.1500 +default charset: UTF-8
269.1501 +
269.1502 +OS Locale:  es_PE
269.1503 +default locale: ID: es_PE, Name: Spanish (Peru)
269.1504 +display locale: ID: es_PE, Name: Spanish (Peru)
269.1505 +format locale: ID: es_PE, Name: Spanish (Peru)
269.1506 +default charset: ISO-8859-1
269.1507 +
269.1508 +OS Locale:  es_PE.iso88591
269.1509 +default locale: ID: es_PE, Name: Spanish (Peru)
269.1510 +display locale: ID: es_PE, Name: Spanish (Peru)
269.1511 +format locale: ID: es_PE, Name: Spanish (Peru)
269.1512 +default charset: ISO-8859-1
269.1513 +
269.1514 +OS Locale:  es_PE.utf8
269.1515 +default locale: ID: es_PE, Name: Spanish (Peru)
269.1516 +display locale: ID: es_PE, Name: Spanish (Peru)
269.1517 +format locale: ID: es_PE, Name: Spanish (Peru)
269.1518 +default charset: UTF-8
269.1519 +
269.1520 +OS Locale:  es_PR
269.1521 +default locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1522 +display locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1523 +format locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1524 +default charset: ISO-8859-1
269.1525 +
269.1526 +OS Locale:  es_PR.iso88591
269.1527 +default locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1528 +display locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1529 +format locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1530 +default charset: ISO-8859-1
269.1531 +
269.1532 +OS Locale:  es_PR.utf8
269.1533 +default locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1534 +display locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1535 +format locale: ID: es_PR, Name: Spanish (Puerto Rico)
269.1536 +default charset: UTF-8
269.1537 +
269.1538 +OS Locale:  es_PY
269.1539 +default locale: ID: es_PY, Name: Spanish (Paraguay)
269.1540 +display locale: ID: es_PY, Name: Spanish (Paraguay)
269.1541 +format locale: ID: es_PY, Name: Spanish (Paraguay)
269.1542 +default charset: ISO-8859-1
269.1543 +
269.1544 +OS Locale:  es_PY.iso88591
269.1545 +default locale: ID: es_PY, Name: Spanish (Paraguay)
269.1546 +display locale: ID: es_PY, Name: Spanish (Paraguay)
269.1547 +format locale: ID: es_PY, Name: Spanish (Paraguay)
269.1548 +default charset: ISO-8859-1
269.1549 +
269.1550 +OS Locale:  es_PY.utf8
269.1551 +default locale: ID: es_PY, Name: Spanish (Paraguay)
269.1552 +display locale: ID: es_PY, Name: Spanish (Paraguay)
269.1553 +format locale: ID: es_PY, Name: Spanish (Paraguay)
269.1554 +default charset: UTF-8
269.1555 +
269.1556 +OS Locale:  es_SV
269.1557 +default locale: ID: es_SV, Name: Spanish (El Salvador)
269.1558 +display locale: ID: es_SV, Name: Spanish (El Salvador)
269.1559 +format locale: ID: es_SV, Name: Spanish (El Salvador)
269.1560 +default charset: ISO-8859-1
269.1561 +
269.1562 +OS Locale:  es_SV.iso88591
269.1563 +default locale: ID: es_SV, Name: Spanish (El Salvador)
269.1564 +display locale: ID: es_SV, Name: Spanish (El Salvador)
269.1565 +format locale: ID: es_SV, Name: Spanish (El Salvador)
269.1566 +default charset: ISO-8859-1
269.1567 +
269.1568 +OS Locale:  es_SV.utf8
269.1569 +default locale: ID: es_SV, Name: Spanish (El Salvador)
269.1570 +display locale: ID: es_SV, Name: Spanish (El Salvador)
269.1571 +format locale: ID: es_SV, Name: Spanish (El Salvador)
269.1572 +default charset: UTF-8
269.1573 +
269.1574 +OS Locale:  es_US
269.1575 +default locale: ID: es_US, Name: Spanish (United States)
269.1576 +display locale: ID: es_US, Name: Spanish (United States)
269.1577 +format locale: ID: es_US, Name: Spanish (United States)
269.1578 +default charset: ISO-8859-1
269.1579 +
269.1580 +OS Locale:  es_US.iso88591
269.1581 +default locale: ID: es_US, Name: Spanish (United States)
269.1582 +display locale: ID: es_US, Name: Spanish (United States)
269.1583 +format locale: ID: es_US, Name: Spanish (United States)
269.1584 +default charset: ISO-8859-1
269.1585 +
269.1586 +OS Locale:  es_US.utf8
269.1587 +default locale: ID: es_US, Name: Spanish (United States)
269.1588 +display locale: ID: es_US, Name: Spanish (United States)
269.1589 +format locale: ID: es_US, Name: Spanish (United States)
269.1590 +default charset: UTF-8
269.1591 +
269.1592 +OS Locale:  es_UY
269.1593 +default locale: ID: es_UY, Name: Spanish (Uruguay)
269.1594 +display locale: ID: es_UY, Name: Spanish (Uruguay)
269.1595 +format locale: ID: es_UY, Name: Spanish (Uruguay)
269.1596 +default charset: ISO-8859-1
269.1597 +
269.1598 +OS Locale:  es_UY.iso88591
269.1599 +default locale: ID: es_UY, Name: Spanish (Uruguay)
269.1600 +display locale: ID: es_UY, Name: Spanish (Uruguay)
269.1601 +format locale: ID: es_UY, Name: Spanish (Uruguay)
269.1602 +default charset: ISO-8859-1
269.1603 +
269.1604 +OS Locale:  es_UY.utf8
269.1605 +default locale: ID: es_UY, Name: Spanish (Uruguay)
269.1606 +display locale: ID: es_UY, Name: Spanish (Uruguay)
269.1607 +format locale: ID: es_UY, Name: Spanish (Uruguay)
269.1608 +default charset: UTF-8
269.1609 +
269.1610 +OS Locale:  es_VE
269.1611 +default locale: ID: es_VE, Name: Spanish (Venezuela)
269.1612 +display locale: ID: es_VE, Name: Spanish (Venezuela)
269.1613 +format locale: ID: es_VE, Name: Spanish (Venezuela)
269.1614 +default charset: ISO-8859-1
269.1615 +
269.1616 +OS Locale:  es_VE.iso88591
269.1617 +default locale: ID: es_VE, Name: Spanish (Venezuela)
269.1618 +display locale: ID: es_VE, Name: Spanish (Venezuela)
269.1619 +format locale: ID: es_VE, Name: Spanish (Venezuela)
269.1620 +default charset: ISO-8859-1
269.1621 +
269.1622 +OS Locale:  es_VE.utf8
269.1623 +default locale: ID: es_VE, Name: Spanish (Venezuela)
269.1624 +display locale: ID: es_VE, Name: Spanish (Venezuela)
269.1625 +format locale: ID: es_VE, Name: Spanish (Venezuela)
269.1626 +default charset: UTF-8
269.1627 +
269.1628 +OS Locale:  estonian
269.1629 +default locale: ID: en, Name: English
269.1630 +display locale: ID: en, Name: English
269.1631 +format locale: ID: en, Name: English
269.1632 +default charset: ISO-8859-1
269.1633 +
269.1634 +OS Locale:  et_EE
269.1635 +default locale: ID: et_EE, Name: Estonian (Estonia)
269.1636 +display locale: ID: et_EE, Name: Estonian (Estonia)
269.1637 +format locale: ID: et_EE, Name: Estonian (Estonia)
269.1638 +default charset: ISO-8859-1
269.1639 +
269.1640 +OS Locale:  et_EE.iso88591
269.1641 +default locale: ID: et_EE, Name: Estonian (Estonia)
269.1642 +display locale: ID: et_EE, Name: Estonian (Estonia)
269.1643 +format locale: ID: et_EE, Name: Estonian (Estonia)
269.1644 +default charset: ISO-8859-1
269.1645 +
269.1646 +OS Locale:  et_EE.iso885915
269.1647 +default locale: ID: et_EE, Name: Estonian (Estonia)
269.1648 +display locale: ID: et_EE, Name: Estonian (Estonia)
269.1649 +format locale: ID: et_EE, Name: Estonian (Estonia)
269.1650 +default charset: ISO-8859-15
269.1651 +
269.1652 +OS Locale:  et_EE.utf8
269.1653 +default locale: ID: et_EE, Name: Estonian (Estonia)
269.1654 +display locale: ID: et_EE, Name: Estonian (Estonia)
269.1655 +format locale: ID: et_EE, Name: Estonian (Estonia)
269.1656 +default charset: UTF-8
269.1657 +
269.1658 +OS Locale:  eu_ES
269.1659 +default locale: ID: eu_ES, Name: Basque (Spain)
269.1660 +display locale: ID: eu_ES, Name: Basque (Spain)
269.1661 +format locale: ID: eu_ES, Name: Basque (Spain)
269.1662 +default charset: ISO-8859-1
269.1663 +
269.1664 +OS Locale:  eu_ES.iso88591
269.1665 +default locale: ID: eu_ES, Name: Basque (Spain)
269.1666 +display locale: ID: eu_ES, Name: Basque (Spain)
269.1667 +format locale: ID: eu_ES, Name: Basque (Spain)
269.1668 +default charset: ISO-8859-1
269.1669 +
269.1670 +OS Locale:  eu_ES.iso885915@euro
269.1671 +default locale: ID: eu_ES, Name: Basque (Spain)
269.1672 +display locale: ID: eu_ES, Name: Basque (Spain)
269.1673 +format locale: ID: eu_ES, Name: Basque (Spain)
269.1674 +default charset: ISO-8859-15
269.1675 +
269.1676 +OS Locale:  eu_ES.utf8
269.1677 +default locale: ID: eu_ES, Name: Basque (Spain)
269.1678 +display locale: ID: eu_ES, Name: Basque (Spain)
269.1679 +format locale: ID: eu_ES, Name: Basque (Spain)
269.1680 +default charset: UTF-8
269.1681 +
269.1682 +OS Locale:  eu_ES@euro
269.1683 +default locale: ID: eu_ES, Name: Basque (Spain)
269.1684 +display locale: ID: eu_ES, Name: Basque (Spain)
269.1685 +format locale: ID: eu_ES, Name: Basque (Spain)
269.1686 +default charset: ISO-8859-15
269.1687 +
269.1688 +OS Locale:  fa_IR
269.1689 +default locale: ID: fa_IR, Name: Persian (Iran)
269.1690 +display locale: ID: fa_IR, Name: Persian (Iran)
269.1691 +format locale: ID: fa_IR, Name: Persian (Iran)
269.1692 +default charset: UTF-8
269.1693 +
269.1694 +OS Locale:  fa_IR.utf8
269.1695 +default locale: ID: fa_IR, Name: Persian (Iran)
269.1696 +display locale: ID: fa_IR, Name: Persian (Iran)
269.1697 +format locale: ID: fa_IR, Name: Persian (Iran)
269.1698 +default charset: UTF-8
269.1699 +
269.1700 +OS Locale:  fi_FI
269.1701 +default locale: ID: fi_FI, Name: Finnish (Finland)
269.1702 +display locale: ID: fi_FI, Name: Finnish (Finland)
269.1703 +format locale: ID: fi_FI, Name: Finnish (Finland)
269.1704 +default charset: ISO-8859-1
269.1705 +
269.1706 +OS Locale:  fi_FI.iso88591
269.1707 +default locale: ID: fi_FI, Name: Finnish (Finland)
269.1708 +display locale: ID: fi_FI, Name: Finnish (Finland)
269.1709 +format locale: ID: fi_FI, Name: Finnish (Finland)
269.1710 +default charset: ISO-8859-1
269.1711 +
269.1712 +OS Locale:  fi_FI.iso885915@euro
269.1713 +default locale: ID: fi_FI, Name: Finnish (Finland)
269.1714 +display locale: ID: fi_FI, Name: Finnish (Finland)
269.1715 +format locale: ID: fi_FI, Name: Finnish (Finland)
269.1716 +default charset: ISO-8859-15
269.1717 +
269.1718 +OS Locale:  fi_FI.utf8
269.1719 +default locale: ID: fi_FI, Name: Finnish (Finland)
269.1720 +display locale: ID: fi_FI, Name: Finnish (Finland)
269.1721 +format locale: ID: fi_FI, Name: Finnish (Finland)
269.1722 +default charset: UTF-8
269.1723 +
269.1724 +OS Locale:  fi_FI@euro
269.1725 +default locale: ID: fi_FI, Name: Finnish (Finland)
269.1726 +display locale: ID: fi_FI, Name: Finnish (Finland)
269.1727 +format locale: ID: fi_FI, Name: Finnish (Finland)
269.1728 +default charset: ISO-8859-15
269.1729 +
269.1730 +OS Locale:  finnish
269.1731 +default locale: ID: fi_FI, Name: Finnish (Finland)
269.1732 +display locale: ID: fi_FI, Name: Finnish (Finland)
269.1733 +format locale: ID: fi_FI, Name: Finnish (Finland)
269.1734 +default charset: ISO-8859-1
269.1735 +
269.1736 +OS Locale:  fo_FO
269.1737 +default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1738 +display locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1739 +format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1740 +default charset: ISO-8859-1
269.1741 +
269.1742 +OS Locale:  fo_FO.iso88591
269.1743 +default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1744 +display locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1745 +format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1746 +default charset: ISO-8859-1
269.1747 +
269.1748 +OS Locale:  fo_FO.utf8
269.1749 +default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1750 +display locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1751 +format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
269.1752 +default charset: UTF-8
269.1753 +
269.1754 +OS Locale:  fr_BE
269.1755 +default locale: ID: fr_BE, Name: French (Belgium)
269.1756 +display locale: ID: fr_BE, Name: French (Belgium)
269.1757 +format locale: ID: fr_BE, Name: French (Belgium)
269.1758 +default charset: ISO-8859-1
269.1759 +
269.1760 +OS Locale:  fr_BE.iso88591
269.1761 +default locale: ID: fr_BE, Name: French (Belgium)
269.1762 +display locale: ID: fr_BE, Name: French (Belgium)
269.1763 +format locale: ID: fr_BE, Name: French (Belgium)
269.1764 +default charset: ISO-8859-1
269.1765 +
269.1766 +OS Locale:  fr_BE.iso885915@euro
269.1767 +default locale: ID: fr_BE, Name: French (Belgium)
269.1768 +display locale: ID: fr_BE, Name: French (Belgium)
269.1769 +format locale: ID: fr_BE, Name: French (Belgium)
269.1770 +default charset: ISO-8859-15
269.1771 +
269.1772 +OS Locale:  fr_BE.utf8
269.1773 +default locale: ID: fr_BE, Name: French (Belgium)
269.1774 +display locale: ID: fr_BE, Name: French (Belgium)
269.1775 +format locale: ID: fr_BE, Name: French (Belgium)
269.1776 +default charset: UTF-8
269.1777 +
269.1778 +OS Locale:  fr_BE@euro
269.1779 +default locale: ID: fr_BE, Name: French (Belgium)
269.1780 +display locale: ID: fr_BE, Name: French (Belgium)
269.1781 +format locale: ID: fr_BE, Name: French (Belgium)
269.1782 +default charset: ISO-8859-15
269.1783 +
269.1784 +OS Locale:  fr_CA
269.1785 +default locale: ID: fr_CA, Name: French (Canada)
269.1786 +display locale: ID: fr_CA, Name: French (Canada)
269.1787 +format locale: ID: fr_CA, Name: French (Canada)
269.1788 +default charset: ISO-8859-1
269.1789 +
269.1790 +OS Locale:  fr_CA.iso88591
269.1791 +default locale: ID: fr_CA, Name: French (Canada)
269.1792 +display locale: ID: fr_CA, Name: French (Canada)
269.1793 +format locale: ID: fr_CA, Name: French (Canada)
269.1794 +default charset: ISO-8859-1
269.1795 +
269.1796 +OS Locale:  fr_CA.utf8
269.1797 +default locale: ID: fr_CA, Name: French (Canada)
269.1798 +display locale: ID: fr_CA, Name: French (Canada)
269.1799 +format locale: ID: fr_CA, Name: French (Canada)
269.1800 +default charset: UTF-8
269.1801 +
269.1802 +OS Locale:  fr_CH
269.1803 +default locale: ID: fr_CH, Name: French (Switzerland)
269.1804 +display locale: ID: fr_CH, Name: French (Switzerland)
269.1805 +format locale: ID: fr_CH, Name: French (Switzerland)
269.1806 +default charset: ISO-8859-1
269.1807 +
269.1808 +OS Locale:  fr_CH.iso88591
269.1809 +default locale: ID: fr_CH, Name: French (Switzerland)
269.1810 +display locale: ID: fr_CH, Name: French (Switzerland)
269.1811 +format locale: ID: fr_CH, Name: French (Switzerland)
269.1812 +default charset: ISO-8859-1
269.1813 +
269.1814 +OS Locale:  fr_CH.utf8
269.1815 +default locale: ID: fr_CH, Name: French (Switzerland)
269.1816 +display locale: ID: fr_CH, Name: French (Switzerland)
269.1817 +format locale: ID: fr_CH, Name: French (Switzerland)
269.1818 +default charset: UTF-8
269.1819 +
269.1820 +OS Locale:  fr_FR
269.1821 +default locale: ID: fr_FR, Name: French (France)
269.1822 +display locale: ID: fr_FR, Name: French (France)
269.1823 +format locale: ID: fr_FR, Name: French (France)
269.1824 +default charset: ISO-8859-1
269.1825 +
269.1826 +OS Locale:  fr_FR.iso88591
269.1827 +default locale: ID: fr_FR, Name: French (France)
269.1828 +display locale: ID: fr_FR, Name: French (France)
269.1829 +format locale: ID: fr_FR, Name: French (France)
269.1830 +default charset: ISO-8859-1
269.1831 +
269.1832 +OS Locale:  fr_FR.iso885915@euro
269.1833 +default locale: ID: fr_FR, Name: French (France)
269.1834 +display locale: ID: fr_FR, Name: French (France)
269.1835 +format locale: ID: fr_FR, Name: French (France)
269.1836 +default charset: ISO-8859-15
269.1837 +
269.1838 +OS Locale:  fr_FR.utf8
269.1839 +default locale: ID: fr_FR, Name: French (France)
269.1840 +display locale: ID: fr_FR, Name: French (France)
269.1841 +format locale: ID: fr_FR, Name: French (France)
269.1842 +default charset: UTF-8
269.1843 +
269.1844 +OS Locale:  fr_FR@euro
269.1845 +default locale: ID: fr_FR, Name: French (France)
269.1846 +display locale: ID: fr_FR, Name: French (France)
269.1847 +format locale: ID: fr_FR, Name: French (France)
269.1848 +default charset: ISO-8859-15
269.1849 +
269.1850 +OS Locale:  fr_LU
269.1851 +default locale: ID: fr_LU, Name: French (Luxembourg)
269.1852 +display locale: ID: fr_LU, Name: French (Luxembourg)
269.1853 +format locale: ID: fr_LU, Name: French (Luxembourg)
269.1854 +default charset: ISO-8859-1
269.1855 +
269.1856 +OS Locale:  fr_LU.iso88591
269.1857 +default locale: ID: fr_LU, Name: French (Luxembourg)
269.1858 +display locale: ID: fr_LU, Name: French (Luxembourg)
269.1859 +format locale: ID: fr_LU, Name: French (Luxembourg)
269.1860 +default charset: ISO-8859-1
269.1861 +
269.1862 +OS Locale:  fr_LU.iso885915@euro
269.1863 +default locale: ID: fr_LU, Name: French (Luxembourg)
269.1864 +display locale: ID: fr_LU, Name: French (Luxembourg)
269.1865 +format locale: ID: fr_LU, Name: French (Luxembourg)
269.1866 +default charset: ISO-8859-15
269.1867 +
269.1868 +OS Locale:  fr_LU.utf8
269.1869 +default locale: ID: fr_LU, Name: French (Luxembourg)
269.1870 +display locale: ID: fr_LU, Name: French (Luxembourg)
269.1871 +format locale: ID: fr_LU, Name: French (Luxembourg)
269.1872 +default charset: UTF-8
269.1873 +
269.1874 +OS Locale:  fr_LU@euro
269.1875 +default locale: ID: fr_LU, Name: French (Luxembourg)
269.1876 +display locale: ID: fr_LU, Name: French (Luxembourg)
269.1877 +format locale: ID: fr_LU, Name: French (Luxembourg)
269.1878 +default charset: ISO-8859-15
269.1879 +
269.1880 +OS Locale:  français
269.1881 +default locale: ID: fr_FR, Name: French (France)
269.1882 +display locale: ID: fr_FR, Name: French (France)
269.1883 +format locale: ID: fr_FR, Name: French (France)
269.1884 +default charset: ISO-8859-1
269.1885 +
269.1886 +OS Locale:  french
269.1887 +default locale: ID: fr_FR, Name: French (France)
269.1888 +display locale: ID: fr_FR, Name: French (France)
269.1889 +format locale: ID: fr_FR, Name: French (France)
269.1890 +default charset: ISO-8859-1
269.1891 +
269.1892 +OS Locale:  fy_NL
269.1893 +default locale: ID: fy_NL, Name: Frisian (Netherlands)
269.1894 +display locale: ID: fy_NL, Name: Frisian (Netherlands)
269.1895 +format locale: ID: fy_NL, Name: Frisian (Netherlands)
269.1896 +default charset: UTF-8
269.1897 +
269.1898 +OS Locale:  fy_NL.utf8
269.1899 +default locale: ID: fy_NL, Name: Frisian (Netherlands)
269.1900 +display locale: ID: fy_NL, Name: Frisian (Netherlands)
269.1901 +format locale: ID: fy_NL, Name: Frisian (Netherlands)
269.1902 +default charset: UTF-8
269.1903 +
269.1904 +OS Locale:  ga_IE
269.1905 +default locale: ID: ga_IE, Name: Irish (Ireland)
269.1906 +display locale: ID: ga_IE, Name: Irish (Ireland)
269.1907 +format locale: ID: ga_IE, Name: Irish (Ireland)
269.1908 +default charset: ISO-8859-1
269.1909 +
269.1910 +OS Locale:  ga_IE.iso88591
269.1911 +default locale: ID: ga_IE, Name: Irish (Ireland)
269.1912 +display locale: ID: ga_IE, Name: Irish (Ireland)
269.1913 +format locale: ID: ga_IE, Name: Irish (Ireland)
269.1914 +default charset: ISO-8859-1
269.1915 +
269.1916 +OS Locale:  ga_IE.iso885915@euro
269.1917 +default locale: ID: ga_IE, Name: Irish (Ireland)
269.1918 +display locale: ID: ga_IE, Name: Irish (Ireland)
269.1919 +format locale: ID: ga_IE, Name: Irish (Ireland)
269.1920 +default charset: ISO-8859-15
269.1921 +
269.1922 +OS Locale:  ga_IE.utf8
269.1923 +default locale: ID: ga_IE, Name: Irish (Ireland)
269.1924 +display locale: ID: ga_IE, Name: Irish (Ireland)
269.1925 +format locale: ID: ga_IE, Name: Irish (Ireland)
269.1926 +default charset: UTF-8
269.1927 +
269.1928 +OS Locale:  ga_IE@euro
269.1929 +default locale: ID: ga_IE, Name: Irish (Ireland)
269.1930 +display locale: ID: ga_IE, Name: Irish (Ireland)
269.1931 +format locale: ID: ga_IE, Name: Irish (Ireland)
269.1932 +default charset: ISO-8859-15
269.1933 +
269.1934 +OS Locale:  galego
269.1935 +default locale: ID: en, Name: English
269.1936 +display locale: ID: en, Name: English
269.1937 +format locale: ID: en, Name: English
269.1938 +default charset: ISO-8859-1
269.1939 +
269.1940 +OS Locale:  galician
269.1941 +default locale: ID: en, Name: English
269.1942 +display locale: ID: en, Name: English
269.1943 +format locale: ID: en, Name: English
269.1944 +default charset: ISO-8859-1
269.1945 +
269.1946 +OS Locale:  gd_GB
269.1947 +default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1948 +display locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1949 +format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1950 +default charset: ISO-8859-15
269.1951 +
269.1952 +OS Locale:  gd_GB.iso885915
269.1953 +default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1954 +display locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1955 +format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1956 +default charset: ISO-8859-15
269.1957 +
269.1958 +OS Locale:  gd_GB.utf8
269.1959 +default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1960 +display locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1961 +format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
269.1962 +default charset: UTF-8
269.1963 +
269.1964 +OS Locale:  german
269.1965 +default locale: ID: de_DE, Name: German (Germany)
269.1966 +display locale: ID: de_DE, Name: German (Germany)
269.1967 +format locale: ID: de_DE, Name: German (Germany)
269.1968 +default charset: ISO-8859-1
269.1969 +
269.1970 +OS Locale:  gez_ER
269.1971 +default locale: ID: en_ER, Name: English (Eritrea)
269.1972 +display locale: ID: en_ER, Name: English (Eritrea)
269.1973 +format locale: ID: en_ER, Name: English (Eritrea)
269.1974 +default charset: UTF-8
269.1975 +
269.1976 +OS Locale:  gez_ER.utf8
269.1977 +default locale: ID: en_ER, Name: English (Eritrea)
269.1978 +display locale: ID: en_ER, Name: English (Eritrea)
269.1979 +format locale: ID: en_ER, Name: English (Eritrea)
269.1980 +default charset: UTF-8
269.1981 +
269.1982 +OS Locale:  gez_ER.utf8@abegede
269.1983 +default locale: ID: en_ER, Name: English (Eritrea)
269.1984 +display locale: ID: en_ER, Name: English (Eritrea)
269.1985 +format locale: ID: en_ER, Name: English (Eritrea)
269.1986 +default charset: UTF-8
269.1987 +
269.1988 +OS Locale:  gez_ER@abegede
269.1989 +default locale: ID: en_ER, Name: English (Eritrea)
269.1990 +display locale: ID: en_ER, Name: English (Eritrea)
269.1991 +format locale: ID: en_ER, Name: English (Eritrea)
269.1992 +default charset: UTF-8
269.1993 +
269.1994 +OS Locale:  gez_ET
269.1995 +default locale: ID: en_ET, Name: English (Ethiopia)
269.1996 +display locale: ID: en_ET, Name: English (Ethiopia)
269.1997 +format locale: ID: en_ET, Name: English (Ethiopia)
269.1998 +default charset: UTF-8
269.1999 +
269.2000 +OS Locale:  gez_ET.utf8
269.2001 +default locale: ID: en_ET, Name: English (Ethiopia)
269.2002 +display locale: ID: en_ET, Name: English (Ethiopia)
269.2003 +format locale: ID: en_ET, Name: English (Ethiopia)
269.2004 +default charset: UTF-8
269.2005 +
269.2006 +OS Locale:  gez_ET.utf8@abegede
269.2007 +default locale: ID: en_ET, Name: English (Ethiopia)
269.2008 +display locale: ID: en_ET, Name: English (Ethiopia)
269.2009 +format locale: ID: en_ET, Name: English (Ethiopia)
269.2010 +default charset: UTF-8
269.2011 +
269.2012 +OS Locale:  gez_ET@abegede
269.2013 +default locale: ID: en_ET, Name: English (Ethiopia)
269.2014 +display locale: ID: en_ET, Name: English (Ethiopia)
269.2015 +format locale: ID: en_ET, Name: English (Ethiopia)
269.2016 +default charset: UTF-8
269.2017 +
269.2018 +OS Locale:  gl_ES
269.2019 +default locale: ID: gl_ES, Name: Gallegan (Spain)
269.2020 +display locale: ID: gl_ES, Name: Gallegan (Spain)
269.2021 +format locale: ID: gl_ES, Name: Gallegan (Spain)
269.2022 +default charset: ISO-8859-1
269.2023 +
269.2024 +OS Locale:  gl_ES.iso88591
269.2025 +default locale: ID: gl_ES, Name: Gallegan (Spain)
269.2026 +display locale: ID: gl_ES, Name: Gallegan (Spain)
269.2027 +format locale: ID: gl_ES, Name: Gallegan (Spain)
269.2028 +default charset: ISO-8859-1
269.2029 +
269.2030 +OS Locale:  gl_ES.iso885915@euro
269.2031 +default locale: ID: gl_ES, Name: Gallegan (Spain)
269.2032 +display locale: ID: gl_ES, Name: Gallegan (Spain)
269.2033 +format locale: ID: gl_ES, Name: Gallegan (Spain)
269.2034 +default charset: ISO-8859-15
269.2035 +
269.2036 +OS Locale:  gl_ES.utf8
269.2037 +default locale: ID: gl_ES, Name: Gallegan (Spain)
269.2038 +display locale: ID: gl_ES, Name: Gallegan (Spain)
269.2039 +format locale: ID: gl_ES, Name: Gallegan (Spain)
269.2040 +default charset: UTF-8
269.2041 +
269.2042 +OS Locale:  gl_ES@euro
269.2043 +default locale: ID: gl_ES, Name: Gallegan (Spain)
269.2044 +display locale: ID: gl_ES, Name: Gallegan (Spain)
269.2045 +format locale: ID: gl_ES, Name: Gallegan (Spain)
269.2046 +default charset: ISO-8859-15
269.2047 +
269.2048 +OS Locale:  greek
269.2049 +default locale: ID: el_GR, Name: Greek (Greece)
269.2050 +display locale: ID: el_GR, Name: Greek (Greece)
269.2051 +format locale: ID: el_GR, Name: Greek (Greece)
269.2052 +default charset: ISO-8859-7
269.2053 +
269.2054 +OS Locale:  gu_IN
269.2055 +default locale: ID: gu_IN, Name: Gujarati (India)
269.2056 +display locale: ID: gu_IN, Name: Gujarati (India)
269.2057 +format locale: ID: gu_IN, Name: Gujarati (India)
269.2058 +default charset: UTF-8
269.2059 +
269.2060 +OS Locale:  gu_IN.utf8
269.2061 +default locale: ID: gu_IN, Name: Gujarati (India)
269.2062 +display locale: ID: gu_IN, Name: Gujarati (India)
269.2063 +format locale: ID: gu_IN, Name: Gujarati (India)
269.2064 +default charset: UTF-8
269.2065 +
269.2066 +OS Locale:  gv_GB
269.2067 +default locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2068 +display locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2069 +format locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2070 +default charset: ISO-8859-1
269.2071 +
269.2072 +OS Locale:  gv_GB.iso88591
269.2073 +default locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2074 +display locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2075 +format locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2076 +default charset: ISO-8859-1
269.2077 +
269.2078 +OS Locale:  gv_GB.utf8
269.2079 +default locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2080 +display locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2081 +format locale: ID: gv_GB, Name: Manx (United Kingdom)
269.2082 +default charset: UTF-8
269.2083 +
269.2084 +OS Locale:  he_IL
269.2085 +default locale: ID: iw_IL, Name: Hebrew (Israel)
269.2086 +display locale: ID: iw_IL, Name: Hebrew (Israel)
269.2087 +format locale: ID: iw_IL, Name: Hebrew (Israel)
269.2088 +default charset: ISO-8859-8
269.2089 +
269.2090 +OS Locale:  he_IL.iso88598
269.2091 +default locale: ID: iw_IL, Name: Hebrew (Israel)
269.2092 +display locale: ID: iw_IL, Name: Hebrew (Israel)
269.2093 +format locale: ID: iw_IL, Name: Hebrew (Israel)
269.2094 +default charset: ISO-8859-8
269.2095 +
269.2096 +OS Locale:  he_IL.utf8
269.2097 +default locale: ID: iw_IL, Name: Hebrew (Israel)
269.2098 +display locale: ID: iw_IL, Name: Hebrew (Israel)
269.2099 +format locale: ID: iw_IL, Name: Hebrew (Israel)
269.2100 +default charset: UTF-8
269.2101 +
269.2102 +OS Locale:  hebrew
269.2103 +default locale: ID: iw_IL, Name: Hebrew (Israel)
269.2104 +display locale: ID: iw_IL, Name: Hebrew (Israel)
269.2105 +format locale: ID: iw_IL, Name: Hebrew (Israel)
269.2106 +default charset: ISO-8859-8
269.2107 +
269.2108 +OS Locale:  hi_IN
269.2109 +default locale: ID: hi_IN, Name: Hindi (India)
269.2110 +display locale: ID: hi_IN, Name: Hindi (India)
269.2111 +format locale: ID: hi_IN, Name: Hindi (India)
269.2112 +default charset: UTF-8
269.2113 +
269.2114 +OS Locale:  hi_IN.utf8
269.2115 +default locale: ID: hi_IN, Name: Hindi (India)
269.2116 +display locale: ID: hi_IN, Name: Hindi (India)
269.2117 +format locale: ID: hi_IN, Name: Hindi (India)
269.2118 +default charset: UTF-8
269.2119 +
269.2120 +OS Locale:  hr_HR
269.2121 +default locale: ID: hr_HR, Name: Croatian (Croatia)
269.2122 +display locale: ID: hr_HR, Name: Croatian (Croatia)
269.2123 +format locale: ID: hr_HR, Name: Croatian (Croatia)
269.2124 +default charset: ISO-8859-2
269.2125 +
269.2126 +OS Locale:  hr_HR.iso88592
269.2127 +default locale: ID: hr_HR, Name: Croatian (Croatia)
269.2128 +display locale: ID: hr_HR, Name: Croatian (Croatia)
269.2129 +format locale: ID: hr_HR, Name: Croatian (Croatia)
269.2130 +default charset: ISO-8859-2
269.2131 +
269.2132 +OS Locale:  hr_HR.utf8
269.2133 +default locale: ID: hr_HR, Name: Croatian (Croatia)
269.2134 +display locale: ID: hr_HR, Name: Croatian (Croatia)
269.2135 +format locale: ID: hr_HR, Name: Croatian (Croatia)
269.2136 +default charset: UTF-8
269.2137 +
269.2138 +OS Locale:  hrvatski
269.2139 +default locale: ID: hr_HR, Name: Croatian (Croatia)
269.2140 +display locale: ID: hr_HR, Name: Croatian (Croatia)
269.2141 +format locale: ID: hr_HR, Name: Croatian (Croatia)
269.2142 +default charset: ISO-8859-2
269.2143 +
269.2144 +OS Locale:  hsb_DE
269.2145 +default locale: ID: en_DE, Name: English (Germany)
269.2146 +display locale: ID: en_DE, Name: English (Germany)
269.2147 +format locale: ID: en_DE, Name: English (Germany)
269.2148 +default charset: ISO-8859-2
269.2149 +
269.2150 +OS Locale:  hsb_DE.iso88592
269.2151 +default locale: ID: en_DE, Name: English (Germany)
269.2152 +display locale: ID: en_DE, Name: English (Germany)
269.2153 +format locale: ID: en_DE, Name: English (Germany)
269.2154 +default charset: ISO-8859-2
269.2155 +
269.2156 +OS Locale:  hsb_DE.utf8
269.2157 +default locale: ID: en_DE, Name: English (Germany)
269.2158 +display locale: ID: en_DE, Name: English (Germany)
269.2159 +format locale: ID: en_DE, Name: English (Germany)
269.2160 +default charset: UTF-8
269.2161 +
269.2162 +OS Locale:  hu_HU
269.2163 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2164 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2165 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2166 +default charset: ISO-8859-2
269.2167 +
269.2168 +OS Locale:  hu_HU.iso88592
269.2169 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2170 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2171 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2172 +default charset: ISO-8859-2
269.2173 +
269.2174 +OS Locale:  hu_HU.utf8
269.2175 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2176 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2177 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2178 +default charset: UTF-8
269.2179 +
269.2180 +OS Locale:  hungarian
269.2181 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2182 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2183 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
269.2184 +default charset: ISO-8859-2
269.2185 +
269.2186 +OS Locale:  hy_AM
269.2187 +default locale: ID: hy_AM, Name: Armenian (Armenia)
269.2188 +display locale: ID: hy_AM, Name: Armenian (Armenia)
269.2189 +format locale: ID: hy_AM, Name: Armenian (Armenia)
269.2190 +default charset: UTF-8
269.2191 +
269.2192 +OS Locale:  hy_AM.armscii8
269.2193 +default locale: ID: hy_AM, Name: Armenian (Armenia)
269.2194 +display locale: ID: hy_AM, Name: Armenian (Armenia)
269.2195 +format locale: ID: hy_AM, Name: Armenian (Armenia)
269.2196 +default charset: UTF-8
269.2197 +
269.2198 +OS Locale:  hy_AM.utf8
269.2199 +default locale: ID: hy_AM, Name: Armenian (Armenia)
269.2200 +display locale: ID: hy_AM, Name: Armenian (Armenia)
269.2201 +format locale: ID: hy_AM, Name: Armenian (Armenia)
269.2202 +default charset: UTF-8
269.2203 +
269.2204 +OS Locale:  icelandic
269.2205 +default locale: ID: is_IS, Name: Icelandic (Iceland)
269.2206 +display locale: ID: is_IS, Name: Icelandic (Iceland)
269.2207 +format locale: ID: is_IS, Name: Icelandic (Iceland)
269.2208 +default charset: ISO-8859-1
269.2209 +
269.2210 +OS Locale:  id_ID
269.2211 +default locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2212 +display locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2213 +format locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2214 +default charset: ISO-8859-1
269.2215 +
269.2216 +OS Locale:  id_ID.iso88591
269.2217 +default locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2218 +display locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2219 +format locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2220 +default charset: ISO-8859-1
269.2221 +
269.2222 +OS Locale:  id_ID.utf8
269.2223 +default locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2224 +display locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2225 +format locale: ID: in_ID, Name: Indonesian (Indonesia)
269.2226 +default charset: UTF-8
269.2227 +
269.2228 +OS Locale:  is_IS
269.2229 +default locale: ID: is_IS, Name: Icelandic (Iceland)
269.2230 +display locale: ID: is_IS, Name: Icelandic (Iceland)
269.2231 +format locale: ID: is_IS, Name: Icelandic (Iceland)
269.2232 +default charset: ISO-8859-1
269.2233 +
269.2234 +OS Locale:  is_IS.iso88591
269.2235 +default locale: ID: is_IS, Name: Icelandic (Iceland)
269.2236 +display locale: ID: is_IS, Name: Icelandic (Iceland)
269.2237 +format locale: ID: is_IS, Name: Icelandic (Iceland)
269.2238 +default charset: ISO-8859-1
269.2239 +
269.2240 +OS Locale:  is_IS.utf8
269.2241 +default locale: ID: is_IS, Name: Icelandic (Iceland)
269.2242 +display locale: ID: is_IS, Name: Icelandic (Iceland)
269.2243 +format locale: ID: is_IS, Name: Icelandic (Iceland)
269.2244 +default charset: UTF-8
269.2245 +
269.2246 +OS Locale:  it_CH
269.2247 +default locale: ID: it_CH, Name: Italian (Switzerland)
269.2248 +display locale: ID: it_CH, Name: Italian (Switzerland)
269.2249 +format locale: ID: it_CH, Name: Italian (Switzerland)
269.2250 +default charset: ISO-8859-1
269.2251 +
269.2252 +OS Locale:  it_CH.iso88591
269.2253 +default locale: ID: it_CH, Name: Italian (Switzerland)
269.2254 +display locale: ID: it_CH, Name: Italian (Switzerland)
269.2255 +format locale: ID: it_CH, Name: Italian (Switzerland)
269.2256 +default charset: ISO-8859-1
269.2257 +
269.2258 +OS Locale:  it_CH.utf8
269.2259 +default locale: ID: it_CH, Name: Italian (Switzerland)
269.2260 +display locale: ID: it_CH, Name: Italian (Switzerland)
269.2261 +format locale: ID: it_CH, Name: Italian (Switzerland)
269.2262 +default charset: UTF-8
269.2263 +
269.2264 +OS Locale:  it_IT
269.2265 +default locale: ID: it_IT, Name: Italian (Italy)
269.2266 +display locale: ID: it_IT, Name: Italian (Italy)
269.2267 +format locale: ID: it_IT, Name: Italian (Italy)
269.2268 +default charset: ISO-8859-1
269.2269 +
269.2270 +OS Locale:  it_IT.iso88591
269.2271 +default locale: ID: it_IT, Name: Italian (Italy)
269.2272 +display locale: ID: it_IT, Name: Italian (Italy)
269.2273 +format locale: ID: it_IT, Name: Italian (Italy)
269.2274 +default charset: ISO-8859-1
269.2275 +
269.2276 +OS Locale:  it_IT.iso885915@euro
269.2277 +default locale: ID: it_IT, Name: Italian (Italy)
269.2278 +display locale: ID: it_IT, Name: Italian (Italy)
269.2279 +format locale: ID: it_IT, Name: Italian (Italy)
269.2280 +default charset: ISO-8859-15
269.2281 +
269.2282 +OS Locale:  it_IT.utf8
269.2283 +default locale: ID: it_IT, Name: Italian (Italy)
269.2284 +display locale: ID: it_IT, Name: Italian (Italy)
269.2285 +format locale: ID: it_IT, Name: Italian (Italy)
269.2286 +default charset: UTF-8
269.2287 +
269.2288 +OS Locale:  it_IT@euro
269.2289 +default locale: ID: it_IT, Name: Italian (Italy)
269.2290 +display locale: ID: it_IT, Name: Italian (Italy)
269.2291 +format locale: ID: it_IT, Name: Italian (Italy)
269.2292 +default charset: ISO-8859-15
269.2293 +
269.2294 +OS Locale:  italian
269.2295 +default locale: ID: it_IT, Name: Italian (Italy)
269.2296 +display locale: ID: it_IT, Name: Italian (Italy)
269.2297 +format locale: ID: it_IT, Name: Italian (Italy)
269.2298 +default charset: ISO-8859-1
269.2299 +
269.2300 +OS Locale:  iw_IL
269.2301 +default locale: ID: iw_IL, Name: Hebrew (Israel)
269.2302 +display locale: ID: iw_IL, Name: Hebrew (Israel)
269.2303 +format locale: ID: iw_IL, Name: Hebrew (Israel)
269.2304 +default charset: ISO-8859-8
269.2305 +
269.2306 +OS Locale:  iw_IL.iso88598
269.2307 +default locale: ID: iw_IL, Name: Hebrew (Israel)
269.2308 +display locale: ID: iw_IL, Name: Hebrew (Israel)
269.2309 +format locale: ID: iw_IL, Name: Hebrew (Israel)
269.2310 +default charset: ISO-8859-8
269.2311 +
269.2312 +OS Locale:  iw_IL.utf8
269.2313 +default locale: ID: iw_IL, Name: Hebrew (Israel)
269.2314 +display locale: ID: iw_IL, Name: Hebrew (Israel)
269.2315 +format locale: ID: iw_IL, Name: Hebrew (Israel)
269.2316 +default charset: UTF-8
269.2317 +
269.2318 +OS Locale:  ja_JP
269.2319 +default locale: ID: ja_JP, Name: Japanese (Japan)
269.2320 +display locale: ID: ja_JP, Name: Japanese (Japan)
269.2321 +format locale: ID: ja_JP, Name: Japanese (Japan)
269.2322 +default charset: x-euc-jp-linux
269.2323 +
269.2324 +OS Locale:  ja_JP.eucjp
269.2325 +default locale: ID: ja_JP, Name: Japanese (Japan)
269.2326 +display locale: ID: ja_JP, Name: Japanese (Japan)
269.2327 +format locale: ID: ja_JP, Name: Japanese (Japan)
269.2328 +default charset: x-euc-jp-linux
269.2329 +
269.2330 +OS Locale:  ja_JP.ujis
269.2331 +default locale: ID: ja_JP, Name: Japanese (Japan)
269.2332 +display locale: ID: ja_JP, Name: Japanese (Japan)
269.2333 +format locale: ID: ja_JP, Name: Japanese (Japan)
269.2334 +default charset: x-euc-jp-linux
269.2335 +
269.2336 +OS Locale:  ja_JP.utf8
269.2337 +default locale: ID: ja_JP, Name: Japanese (Japan)
269.2338 +display locale: ID: ja_JP, Name: Japanese (Japan)
269.2339 +format locale: ID: ja_JP, Name: Japanese (Japan)
269.2340 +default charset: UTF-8
269.2341 +
269.2342 +OS Locale:  japanese
269.2343 +default locale: ID: ja_JP, Name: Japanese (Japan)
269.2344 +display locale: ID: ja_JP, Name: Japanese (Japan)
269.2345 +format locale: ID: ja_JP, Name: Japanese (Japan)
269.2346 +default charset: x-euc-jp-linux
269.2347 +
269.2348 +OS Locale:  japanese.euc
269.2349 +default locale: ID: ja_JP, Name: Japanese (Japan)
269.2350 +display locale: ID: ja_JP, Name: Japanese (Japan)
269.2351 +format locale: ID: ja_JP, Name: Japanese (Japan)
269.2352 +default charset: x-euc-jp-linux
269.2353 +
269.2354 +OS Locale:  ka_GE
269.2355 +default locale: ID: ka_GE, Name: Georgian (Georgia)
269.2356 +display locale: ID: ka_GE, Name: Georgian (Georgia)
269.2357 +format locale: ID: ka_GE, Name: Georgian (Georgia)
269.2358 +default charset: UTF-8
269.2359 +
269.2360 +OS Locale:  ka_GE.georgianps
269.2361 +default locale: ID: ka_GE, Name: Georgian (Georgia)
269.2362 +display locale: ID: ka_GE, Name: Georgian (Georgia)
269.2363 +format locale: ID: ka_GE, Name: Georgian (Georgia)
269.2364 +default charset: UTF-8
269.2365 +
269.2366 +OS Locale:  ka_GE.utf8
269.2367 +default locale: ID: ka_GE, Name: Georgian (Georgia)
269.2368 +display locale: ID: ka_GE, Name: Georgian (Georgia)
269.2369 +format locale: ID: ka_GE, Name: Georgian (Georgia)
269.2370 +default charset: UTF-8
269.2371 +
269.2372 +OS Locale:  kk_KZ
269.2373 +default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2374 +display locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2375 +format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2376 +default charset: UTF-8
269.2377 +
269.2378 +OS Locale:  kk_KZ.pt154
269.2379 +default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2380 +display locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2381 +format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2382 +default charset: UTF-8
269.2383 +
269.2384 +OS Locale:  kk_KZ.utf8
269.2385 +default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2386 +display locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2387 +format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
269.2388 +default charset: UTF-8
269.2389 +
269.2390 +OS Locale:  kl_GL
269.2391 +default locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2392 +display locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2393 +format locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2394 +default charset: ISO-8859-1
269.2395 +
269.2396 +OS Locale:  kl_GL.iso88591
269.2397 +default locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2398 +display locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2399 +format locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2400 +default charset: ISO-8859-1
269.2401 +
269.2402 +OS Locale:  kl_GL.utf8
269.2403 +default locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2404 +display locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2405 +format locale: ID: kl_GL, Name: Greenlandic (Greenland)
269.2406 +default charset: UTF-8
269.2407 +
269.2408 +OS Locale:  km_KH
269.2409 +default locale: ID: km_KH, Name: Khmer (Cambodia)
269.2410 +display locale: ID: km_KH, Name: Khmer (Cambodia)
269.2411 +format locale: ID: km_KH, Name: Khmer (Cambodia)
269.2412 +default charset: UTF-8
269.2413 +
269.2414 +OS Locale:  km_KH.utf8
269.2415 +default locale: ID: km_KH, Name: Khmer (Cambodia)
269.2416 +display locale: ID: km_KH, Name: Khmer (Cambodia)
269.2417 +format locale: ID: km_KH, Name: Khmer (Cambodia)
269.2418 +default charset: UTF-8
269.2419 +
269.2420 +OS Locale:  kn_IN
269.2421 +default locale: ID: kn_IN, Name: Kannada (India)
269.2422 +display locale: ID: kn_IN, Name: Kannada (India)
269.2423 +format locale: ID: kn_IN, Name: Kannada (India)
269.2424 +default charset: UTF-8
269.2425 +
269.2426 +OS Locale:  kn_IN.utf8
269.2427 +default locale: ID: kn_IN, Name: Kannada (India)
269.2428 +display locale: ID: kn_IN, Name: Kannada (India)
269.2429 +format locale: ID: kn_IN, Name: Kannada (India)
269.2430 +default charset: UTF-8
269.2431 +
269.2432 +OS Locale:  ko_KR
269.2433 +default locale: ID: ko_KR, Name: Korean (South Korea)
269.2434 +display locale: ID: ko_KR, Name: Korean (South Korea)
269.2435 +format locale: ID: ko_KR, Name: Korean (South Korea)
269.2436 +default charset: EUC-KR
269.2437 +
269.2438 +OS Locale:  ko_KR.euckr
269.2439 +default locale: ID: ko_KR, Name: Korean (South Korea)
269.2440 +display locale: ID: ko_KR, Name: Korean (South Korea)
269.2441 +format locale: ID: ko_KR, Name: Korean (South Korea)
269.2442 +default charset: EUC-KR
269.2443 +
269.2444 +OS Locale:  ko_KR.utf8
269.2445 +default locale: ID: ko_KR, Name: Korean (South Korea)
269.2446 +display locale: ID: ko_KR, Name: Korean (South Korea)
269.2447 +format locale: ID: ko_KR, Name: Korean (South Korea)
269.2448 +default charset: UTF-8
269.2449 +
269.2450 +OS Locale:  korean
269.2451 +default locale: ID: en, Name: English
269.2452 +display locale: ID: en, Name: English
269.2453 +format locale: ID: en, Name: English
269.2454 +default charset: EUC-KR
269.2455 +
269.2456 +OS Locale:  korean.euc
269.2457 +default locale: ID: en, Name: English
269.2458 +display locale: ID: en, Name: English
269.2459 +format locale: ID: en, Name: English
269.2460 +default charset: EUC-KR
269.2461 +
269.2462 +OS Locale:  ku_TR
269.2463 +default locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2464 +display locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2465 +format locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2466 +default charset: ISO-8859-9
269.2467 +
269.2468 +OS Locale:  ku_TR.iso88599
269.2469 +default locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2470 +display locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2471 +format locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2472 +default charset: ISO-8859-9
269.2473 +
269.2474 +OS Locale:  ku_TR.utf8
269.2475 +default locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2476 +display locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2477 +format locale: ID: ku_TR, Name: Kurdish (Turkey)
269.2478 +default charset: UTF-8
269.2479 +
269.2480 +OS Locale:  kw_GB
269.2481 +default locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2482 +display locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2483 +format locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2484 +default charset: ISO-8859-1
269.2485 +
269.2486 +OS Locale:  kw_GB.iso88591
269.2487 +default locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2488 +display locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2489 +format locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2490 +default charset: ISO-8859-1
269.2491 +
269.2492 +OS Locale:  kw_GB.utf8
269.2493 +default locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2494 +display locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2495 +format locale: ID: kw_GB, Name: Cornish (United Kingdom)
269.2496 +default charset: UTF-8
269.2497 +
269.2498 +OS Locale:  ky_KG
269.2499 +default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
269.2500 +display locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
269.2501 +format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
269.2502 +default charset: UTF-8
269.2503 +
269.2504 +OS Locale:  ky_KG.utf8
269.2505 +default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
269.2506 +display locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
269.2507 +format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
269.2508 +default charset: UTF-8
269.2509 +
269.2510 +OS Locale:  lg_UG
269.2511 +default locale: ID: lg_UG, Name: Ganda (Uganda)
269.2512 +display locale: ID: lg_UG, Name: Ganda (Uganda)
269.2513 +format locale: ID: lg_UG, Name: Ganda (Uganda)
269.2514 +default charset: UTF-8
269.2515 +
269.2516 +OS Locale:  lg_UG.iso885910
269.2517 +default locale: ID: lg_UG, Name: Ganda (Uganda)
269.2518 +display locale: ID: lg_UG, Name: Ganda (Uganda)
269.2519 +format locale: ID: lg_UG, Name: Ganda (Uganda)
269.2520 +default charset: UTF-8
269.2521 +
269.2522 +OS Locale:  lg_UG.utf8
269.2523 +default locale: ID: lg_UG, Name: Ganda (Uganda)
269.2524 +display locale: ID: lg_UG, Name: Ganda (Uganda)
269.2525 +format locale: ID: lg_UG, Name: Ganda (Uganda)
269.2526 +default charset: UTF-8
269.2527 +
269.2528 +OS Locale:  lithuanian
269.2529 +default locale: ID: en, Name: English
269.2530 +display locale: ID: en, Name: English
269.2531 +format locale: ID: en, Name: English
269.2532 +default charset: ISO-8859-13
269.2533 +
269.2534 +OS Locale:  lo_LA
269.2535 +default locale: ID: lo_LA, Name: Lao (Laos)
269.2536 +display locale: ID: lo_LA, Name: Lao (Laos)
269.2537 +format locale: ID: lo_LA, Name: Lao (Laos)
269.2538 +default charset: UTF-8
269.2539 +
269.2540 +OS Locale:  lo_LA.utf8
269.2541 +default locale: ID: lo_LA, Name: Lao (Laos)
269.2542 +display locale: ID: lo_LA, Name: Lao (Laos)
269.2543 +format locale: ID: lo_LA, Name: Lao (Laos)
269.2544 +default charset: UTF-8
269.2545 +
269.2546 +OS Locale:  lt_LT
269.2547 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2548 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2549 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2550 +default charset: ISO-8859-13
269.2551 +
269.2552 +OS Locale:  lt_LT.iso885913
269.2553 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2554 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2555 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2556 +default charset: ISO-8859-13
269.2557 +
269.2558 +OS Locale:  lt_LT.utf8
269.2559 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2560 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2561 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
269.2562 +default charset: UTF-8
269.2563 +
269.2564 +OS Locale:  lv_LV
269.2565 +default locale: ID: lv_LV, Name: Latvian (Latvia)
269.2566 +display locale: ID: lv_LV, Name: Latvian (Latvia)
269.2567 +format locale: ID: lv_LV, Name: Latvian (Latvia)
269.2568 +default charset: ISO-8859-13
269.2569 +
269.2570 +OS Locale:  lv_LV.iso885913
269.2571 +default locale: ID: lv_LV, Name: Latvian (Latvia)
269.2572 +display locale: ID: lv_LV, Name: Latvian (Latvia)
269.2573 +format locale: ID: lv_LV, Name: Latvian (Latvia)
269.2574 +default charset: ISO-8859-13
269.2575 +
269.2576 +OS Locale:  lv_LV.utf8
269.2577 +default locale: ID: lv_LV, Name: Latvian (Latvia)
269.2578 +display locale: ID: lv_LV, Name: Latvian (Latvia)
269.2579 +format locale: ID: lv_LV, Name: Latvian (Latvia)
269.2580 +default charset: UTF-8
269.2581 +
269.2582 +OS Locale:  mai_IN
269.2583 +default locale: ID: en_IN, Name: English (India)
269.2584 +display locale: ID: en_IN, Name: English (India)
269.2585 +format locale: ID: en_IN, Name: English (India)
269.2586 +default charset: UTF-8
269.2587 +
269.2588 +OS Locale:  mai_IN.utf8
269.2589 +default locale: ID: en_IN, Name: English (India)
269.2590 +display locale: ID: en_IN, Name: English (India)
269.2591 +format locale: ID: en_IN, Name: English (India)
269.2592 +default charset: UTF-8
269.2593 +
269.2594 +OS Locale:  mg_MG
269.2595 +default locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2596 +display locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2597 +format locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2598 +default charset: ISO-8859-15
269.2599 +
269.2600 +OS Locale:  mg_MG.iso885915
269.2601 +default locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2602 +display locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2603 +format locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2604 +default charset: ISO-8859-15
269.2605 +
269.2606 +OS Locale:  mg_MG.utf8
269.2607 +default locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2608 +display locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2609 +format locale: ID: mg_MG, Name: Malagasy (Madagascar)
269.2610 +default charset: UTF-8
269.2611 +
269.2612 +OS Locale:  mi_NZ
269.2613 +default locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2614 +display locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2615 +format locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2616 +default charset: ISO-8859-13
269.2617 +
269.2618 +OS Locale:  mi_NZ.iso885913
269.2619 +default locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2620 +display locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2621 +format locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2622 +default charset: ISO-8859-13
269.2623 +
269.2624 +OS Locale:  mi_NZ.utf8
269.2625 +default locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2626 +display locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2627 +format locale: ID: mi_NZ, Name: Maori (New Zealand)
269.2628 +default charset: UTF-8
269.2629 +
269.2630 +OS Locale:  mk_MK
269.2631 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2632 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2633 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2634 +default charset: ISO-8859-5
269.2635 +
269.2636 +OS Locale:  mk_MK.iso88595
269.2637 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2638 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2639 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2640 +default charset: ISO-8859-5
269.2641 +
269.2642 +OS Locale:  mk_MK.utf8
269.2643 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2644 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2645 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
269.2646 +default charset: UTF-8
269.2647 +
269.2648 +OS Locale:  ml_IN
269.2649 +default locale: ID: ml_IN, Name: Malayalam (India)
269.2650 +display locale: ID: ml_IN, Name: Malayalam (India)
269.2651 +format locale: ID: ml_IN, Name: Malayalam (India)
269.2652 +default charset: UTF-8
269.2653 +
269.2654 +OS Locale:  ml_IN.utf8
269.2655 +default locale: ID: ml_IN, Name: Malayalam (India)
269.2656 +display locale: ID: ml_IN, Name: Malayalam (India)
269.2657 +format locale: ID: ml_IN, Name: Malayalam (India)
269.2658 +default charset: UTF-8
269.2659 +
269.2660 +OS Locale:  mn_MN
269.2661 +default locale: ID: mn_MN, Name: Mongolian (Mongolia)
269.2662 +display locale: ID: mn_MN, Name: Mongolian (Mongolia)
269.2663 +format locale: ID: mn_MN, Name: Mongolian (Mongolia)
269.2664 +default charset: UTF-8
269.2665 +
269.2666 +OS Locale:  mn_MN.utf8
269.2667 +default locale: ID: mn_MN, Name: Mongolian (Mongolia)
269.2668 +display locale: ID: mn_MN, Name: Mongolian (Mongolia)
269.2669 +format locale: ID: mn_MN, Name: Mongolian (Mongolia)
269.2670 +default charset: UTF-8
269.2671 +
269.2672 +OS Locale:  mr_IN
269.2673 +default locale: ID: mr_IN, Name: Marathi (India)
269.2674 +display locale: ID: mr_IN, Name: Marathi (India)
269.2675 +format locale: ID: mr_IN, Name: Marathi (India)
269.2676 +default charset: UTF-8
269.2677 +
269.2678 +OS Locale:  mr_IN.utf8
269.2679 +default locale: ID: mr_IN, Name: Marathi (India)
269.2680 +display locale: ID: mr_IN, Name: Marathi (India)
269.2681 +format locale: ID: mr_IN, Name: Marathi (India)
269.2682 +default charset: UTF-8
269.2683 +
269.2684 +OS Locale:  ms_MY
269.2685 +default locale: ID: ms_MY, Name: Malay (Malaysia)
269.2686 +display locale: ID: ms_MY, Name: Malay (Malaysia)
269.2687 +format locale: ID: ms_MY, Name: Malay (Malaysia)
269.2688 +default charset: ISO-8859-1
269.2689 +
269.2690 +OS Locale:  ms_MY.iso88591
269.2691 +default locale: ID: ms_MY, Name: Malay (Malaysia)
269.2692 +display locale: ID: ms_MY, Name: Malay (Malaysia)
269.2693 +format locale: ID: ms_MY, Name: Malay (Malaysia)
269.2694 +default charset: ISO-8859-1
269.2695 +
269.2696 +OS Locale:  ms_MY.utf8
269.2697 +default locale: ID: ms_MY, Name: Malay (Malaysia)
269.2698 +display locale: ID: ms_MY, Name: Malay (Malaysia)
269.2699 +format locale: ID: ms_MY, Name: Malay (Malaysia)
269.2700 +default charset: UTF-8
269.2701 +
269.2702 +OS Locale:  mt_MT
269.2703 +default locale: ID: mt_MT, Name: Maltese (Malta)
269.2704 +display locale: ID: mt_MT, Name: Maltese (Malta)
269.2705 +format locale: ID: mt_MT, Name: Maltese (Malta)
269.2706 +default charset: ISO-8859-3
269.2707 +
269.2708 +OS Locale:  mt_MT.iso88593
269.2709 +default locale: ID: mt_MT, Name: Maltese (Malta)
269.2710 +display locale: ID: mt_MT, Name: Maltese (Malta)
269.2711 +format locale: ID: mt_MT, Name: Maltese (Malta)
269.2712 +default charset: ISO-8859-3
269.2713 +
269.2714 +OS Locale:  mt_MT.utf8
269.2715 +default locale: ID: mt_MT, Name: Maltese (Malta)
269.2716 +display locale: ID: mt_MT, Name: Maltese (Malta)
269.2717 +format locale: ID: mt_MT, Name: Maltese (Malta)
269.2718 +default charset: UTF-8
269.2719 +
269.2720 +OS Locale:  nb_NO
269.2721 +default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2722 +display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2723 +format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2724 +default charset: ISO-8859-1
269.2725 +
269.2726 +OS Locale:  nb_NO.iso88591
269.2727 +default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2728 +display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2729 +format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2730 +default charset: ISO-8859-1
269.2731 +
269.2732 +OS Locale:  nb_NO.utf8
269.2733 +default locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2734 +display locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2735 +format locale: ID: nb_NO, Name: Norwegian Bokmål (Norway)
269.2736 +default charset: UTF-8
269.2737 +
269.2738 +OS Locale:  ne_NP
269.2739 +default locale: ID: ne_NP, Name: Nepali (Nepal)
269.2740 +display locale: ID: ne_NP, Name: Nepali (Nepal)
269.2741 +format locale: ID: ne_NP, Name: Nepali (Nepal)
269.2742 +default charset: UTF-8
269.2743 +
269.2744 +OS Locale:  ne_NP.utf8
269.2745 +default locale: ID: ne_NP, Name: Nepali (Nepal)
269.2746 +display locale: ID: ne_NP, Name: Nepali (Nepal)
269.2747 +format locale: ID: ne_NP, Name: Nepali (Nepal)
269.2748 +default charset: UTF-8
269.2749 +
269.2750 +OS Locale:  nl_BE
269.2751 +default locale: ID: nl_BE, Name: Dutch (Belgium)
269.2752 +display locale: ID: nl_BE, Name: Dutch (Belgium)
269.2753 +format locale: ID: nl_BE, Name: Dutch (Belgium)
269.2754 +default charset: ISO-8859-1
269.2755 +
269.2756 +OS Locale:  nl_BE.iso88591
269.2757 +default locale: ID: nl_BE, Name: Dutch (Belgium)
269.2758 +display locale: ID: nl_BE, Name: Dutch (Belgium)
269.2759 +format locale: ID: nl_BE, Name: Dutch (Belgium)
269.2760 +default charset: ISO-8859-1
269.2761 +
269.2762 +OS Locale:  nl_BE.iso885915@euro
269.2763 +default locale: ID: nl_BE, Name: Dutch (Belgium)
269.2764 +display locale: ID: nl_BE, Name: Dutch (Belgium)
269.2765 +format locale: ID: nl_BE, Name: Dutch (Belgium)
269.2766 +default charset: ISO-8859-15
269.2767 +
269.2768 +OS Locale:  nl_BE.utf8
269.2769 +default locale: ID: nl_BE, Name: Dutch (Belgium)
269.2770 +display locale: ID: nl_BE, Name: Dutch (Belgium)
269.2771 +format locale: ID: nl_BE, Name: Dutch (Belgium)
269.2772 +default charset: UTF-8
269.2773 +
269.2774 +OS Locale:  nl_BE@euro
269.2775 +default locale: ID: nl_BE, Name: Dutch (Belgium)
269.2776 +display locale: ID: nl_BE, Name: Dutch (Belgium)
269.2777 +format locale: ID: nl_BE, Name: Dutch (Belgium)
269.2778 +default charset: ISO-8859-15
269.2779 +
269.2780 +OS Locale:  nl_NL
269.2781 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2782 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2783 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2784 +default charset: ISO-8859-1
269.2785 +
269.2786 +OS Locale:  nl_NL.iso88591
269.2787 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2788 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2789 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2790 +default charset: ISO-8859-1
269.2791 +
269.2792 +OS Locale:  nl_NL.iso885915@euro
269.2793 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2794 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2795 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2796 +default charset: ISO-8859-15
269.2797 +
269.2798 +OS Locale:  nl_NL.utf8
269.2799 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2800 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2801 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2802 +default charset: UTF-8
269.2803 +
269.2804 +OS Locale:  nl_NL@euro
269.2805 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2806 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2807 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
269.2808 +default charset: ISO-8859-15
269.2809 +
269.2810 +OS Locale:  nn_NO
269.2811 +default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2812 +display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2813 +format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2814 +default charset: ISO-8859-1
269.2815 +
269.2816 +OS Locale:  nn_NO.iso88591
269.2817 +default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2818 +display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2819 +format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2820 +default charset: ISO-8859-1
269.2821 +
269.2822 +OS Locale:  nn_NO.utf8
269.2823 +default locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2824 +display locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2825 +format locale: ID: nn_NO, Name: Norwegian Nynorsk (Norway)
269.2826 +default charset: UTF-8
269.2827 +
269.2828 +OS Locale:  no_NO
269.2829 +default locale: ID: no_NO, Name: Norwegian (Norway)
269.2830 +display locale: ID: no_NO, Name: Norwegian (Norway)
269.2831 +format locale: ID: no_NO, Name: Norwegian (Norway)
269.2832 +default charset: ISO-8859-1
269.2833 +
269.2834 +OS Locale:  no_NO.iso88591
269.2835 +default locale: ID: no_NO, Name: Norwegian (Norway)
269.2836 +display locale: ID: no_NO, Name: Norwegian (Norway)
269.2837 +format locale: ID: no_NO, Name: Norwegian (Norway)
269.2838 +default charset: ISO-8859-1
269.2839 +
269.2840 +OS Locale:  no_NO.utf8
269.2841 +default locale: ID: no_NO, Name: Norwegian (Norway)
269.2842 +display locale: ID: no_NO, Name: Norwegian (Norway)
269.2843 +format locale: ID: no_NO, Name: Norwegian (Norway)
269.2844 +default charset: UTF-8
269.2845 +
269.2846 +OS Locale:  norwegian
269.2847 +default locale: ID: no_NO, Name: Norwegian (Norway)
269.2848 +display locale: ID: no_NO, Name: Norwegian (Norway)
269.2849 +format locale: ID: no_NO, Name: Norwegian (Norway)
269.2850 +default charset: ISO-8859-1
269.2851 +
269.2852 +OS Locale:  nr_ZA
269.2853 +default locale: ID: nr_ZA, Name: South Ndebele (South Africa)
269.2854 +display locale: ID: nr_ZA, Name: South Ndebele (South Africa)
269.2855 +format locale: ID: nr_ZA, Name: South Ndebele (South Africa)
269.2856 +default charset: UTF-8
269.2857 +
269.2858 +OS Locale:  nr_ZA.utf8
269.2859 +default locale: ID: nr_ZA, Name: South Ndebele (South Africa)
269.2860 +display locale: ID: nr_ZA, Name: South Ndebele (South Africa)
269.2861 +format locale: ID: nr_ZA, Name: South Ndebele (South Africa)
269.2862 +default charset: UTF-8
269.2863 +
269.2864 +OS Locale:  nso_ZA
269.2865 +default locale: ID: en_ZA, Name: English (South Africa)
269.2866 +display locale: ID: en_ZA, Name: English (South Africa)
269.2867 +format locale: ID: en_ZA, Name: English (South Africa)
269.2868 +default charset: UTF-8
269.2869 +
269.2870 +OS Locale:  nso_ZA.utf8
269.2871 +default locale: ID: en_ZA, Name: English (South Africa)
269.2872 +display locale: ID: en_ZA, Name: English (South Africa)
269.2873 +format locale: ID: en_ZA, Name: English (South Africa)
269.2874 +default charset: UTF-8
269.2875 +
269.2876 +OS Locale:  nynorsk
269.2877 +default locale: ID: en, Name: English
269.2878 +display locale: ID: en, Name: English
269.2879 +format locale: ID: en, Name: English
269.2880 +default charset: ISO-8859-1
269.2881 +
269.2882 +OS Locale:  oc_FR
269.2883 +default locale: ID: oc_FR, Name: Occitan (France)
269.2884 +display locale: ID: oc_FR, Name: Occitan (France)
269.2885 +format locale: ID: oc_FR, Name: Occitan (France)
269.2886 +default charset: ISO-8859-1
269.2887 +
269.2888 +OS Locale:  oc_FR.iso88591
269.2889 +default locale: ID: oc_FR, Name: Occitan (France)
269.2890 +display locale: ID: oc_FR, Name: Occitan (France)
269.2891 +format locale: ID: oc_FR, Name: Occitan (France)
269.2892 +default charset: ISO-8859-1
269.2893 +
269.2894 +OS Locale:  oc_FR.utf8
269.2895 +default locale: ID: oc_FR, Name: Occitan (France)
269.2896 +display locale: ID: oc_FR, Name: Occitan (France)
269.2897 +format locale: ID: oc_FR, Name: Occitan (France)
269.2898 +default charset: UTF-8
269.2899 +
269.2900 +OS Locale:  om_ET
269.2901 +default locale: ID: om_ET, Name: Oromo (Ethiopia)
269.2902 +display locale: ID: om_ET, Name: Oromo (Ethiopia)
269.2903 +format locale: ID: om_ET, Name: Oromo (Ethiopia)
269.2904 +default charset: UTF-8
269.2905 +
269.2906 +OS Locale:  om_ET.utf8
269.2907 +default locale: ID: om_ET, Name: Oromo (Ethiopia)
269.2908 +display locale: ID: om_ET, Name: Oromo (Ethiopia)
269.2909 +format locale: ID: om_ET, Name: Oromo (Ethiopia)
269.2910 +default charset: UTF-8
269.2911 +
269.2912 +OS Locale:  om_KE
269.2913 +default locale: ID: om_KE, Name: Oromo (Kenya)
269.2914 +display locale: ID: om_KE, Name: Oromo (Kenya)
269.2915 +format locale: ID: om_KE, Name: Oromo (Kenya)
269.2916 +default charset: ISO-8859-1
269.2917 +
269.2918 +OS Locale:  om_KE.iso88591
269.2919 +default locale: ID: om_KE, Name: Oromo (Kenya)
269.2920 +display locale: ID: om_KE, Name: Oromo (Kenya)
269.2921 +format locale: ID: om_KE, Name: Oromo (Kenya)
269.2922 +default charset: ISO-8859-1
269.2923 +
269.2924 +OS Locale:  om_KE.utf8
269.2925 +default locale: ID: om_KE, Name: Oromo (Kenya)
269.2926 +display locale: ID: om_KE, Name: Oromo (Kenya)
269.2927 +format locale: ID: om_KE, Name: Oromo (Kenya)
269.2928 +default charset: UTF-8
269.2929 +
269.2930 +OS Locale:  or_IN
269.2931 +default locale: ID: or_IN, Name: Oriya (India)
269.2932 +display locale: ID: or_IN, Name: Oriya (India)
269.2933 +format locale: ID: or_IN, Name: Oriya (India)
269.2934 +default charset: UTF-8
269.2935 +
269.2936 +OS Locale:  or_IN.utf8
269.2937 +default locale: ID: or_IN, Name: Oriya (India)
269.2938 +display locale: ID: or_IN, Name: Oriya (India)
269.2939 +format locale: ID: or_IN, Name: Oriya (India)
269.2940 +default charset: UTF-8
269.2941 +
269.2942 +OS Locale:  pa_IN
269.2943 +default locale: ID: pa_IN, Name: Panjabi (India)
269.2944 +display locale: ID: pa_IN, Name: Panjabi (India)
269.2945 +format locale: ID: pa_IN, Name: Panjabi (India)
269.2946 +default charset: UTF-8
269.2947 +
269.2948 +OS Locale:  pa_IN.utf8
269.2949 +default locale: ID: pa_IN, Name: Panjabi (India)
269.2950 +display locale: ID: pa_IN, Name: Panjabi (India)
269.2951 +format locale: ID: pa_IN, Name: Panjabi (India)
269.2952 +default charset: UTF-8
269.2953 +
269.2954 +OS Locale:  pa_PK
269.2955 +default locale: ID: pa_PK, Name: Panjabi (Pakistan)
269.2956 +display locale: ID: pa_PK, Name: Panjabi (Pakistan)
269.2957 +format locale: ID: pa_PK, Name: Panjabi (Pakistan)
269.2958 +default charset: UTF-8
269.2959 +
269.2960 +OS Locale:  pa_PK.utf8
269.2961 +default locale: ID: pa_PK, Name: Panjabi (Pakistan)
269.2962 +display locale: ID: pa_PK, Name: Panjabi (Pakistan)
269.2963 +format locale: ID: pa_PK, Name: Panjabi (Pakistan)
269.2964 +default charset: UTF-8
269.2965 +
269.2966 +OS Locale:  pl_PL
269.2967 +default locale: ID: pl_PL, Name: Polish (Poland)
269.2968 +display locale: ID: pl_PL, Name: Polish (Poland)
269.2969 +format locale: ID: pl_PL, Name: Polish (Poland)
269.2970 +default charset: ISO-8859-2
269.2971 +
269.2972 +OS Locale:  pl_PL.iso88592
269.2973 +default locale: ID: pl_PL, Name: Polish (Poland)
269.2974 +display locale: ID: pl_PL, Name: Polish (Poland)
269.2975 +format locale: ID: pl_PL, Name: Polish (Poland)
269.2976 +default charset: ISO-8859-2
269.2977 +
269.2978 +OS Locale:  pl_PL.utf8
269.2979 +default locale: ID: pl_PL, Name: Polish (Poland)
269.2980 +display locale: ID: pl_PL, Name: Polish (Poland)
269.2981 +format locale: ID: pl_PL, Name: Polish (Poland)
269.2982 +default charset: UTF-8
269.2983 +
269.2984 +OS Locale:  polish
269.2985 +default locale: ID: pl_PL, Name: Polish (Poland)
269.2986 +display locale: ID: pl_PL, Name: Polish (Poland)
269.2987 +format locale: ID: pl_PL, Name: Polish (Poland)
269.2988 +default charset: ISO-8859-2
269.2989 +
269.2990 +OS Locale:  portuguese
269.2991 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
269.2992 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
269.2993 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
269.2994 +default charset: ISO-8859-1
269.2995 +
269.2996 +OS Locale:  pt_BR
269.2997 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
269.2998 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
269.2999 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
269.3000 +default charset: ISO-8859-1
269.3001 +
269.3002 +OS Locale:  pt_BR.iso88591
269.3003 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
269.3004 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
269.3005 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
269.3006 +default charset: ISO-8859-1
269.3007 +
269.3008 +OS Locale:  pt_BR.utf8
269.3009 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
269.3010 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
269.3011 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
269.3012 +default charset: UTF-8
269.3013 +
269.3014 +OS Locale:  pt_PT
269.3015 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3016 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3017 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3018 +default charset: ISO-8859-1
269.3019 +
269.3020 +OS Locale:  pt_PT.iso88591
269.3021 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3022 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3023 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3024 +default charset: ISO-8859-1
269.3025 +
269.3026 +OS Locale:  pt_PT.iso885915@euro
269.3027 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3028 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3029 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3030 +default charset: ISO-8859-15
269.3031 +
269.3032 +OS Locale:  pt_PT.utf8
269.3033 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3034 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3035 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3036 +default charset: UTF-8
269.3037 +
269.3038 +OS Locale:  pt_PT@euro
269.3039 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3040 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3041 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
269.3042 +default charset: ISO-8859-15
269.3043 +
269.3044 +OS Locale:  ro_RO
269.3045 +default locale: ID: ro_RO, Name: Romanian (Romania)
269.3046 +display locale: ID: ro_RO, Name: Romanian (Romania)
269.3047 +format locale: ID: ro_RO, Name: Romanian (Romania)
269.3048 +default charset: ISO-8859-2
269.3049 +
269.3050 +OS Locale:  ro_RO.iso88592
269.3051 +default locale: ID: ro_RO, Name: Romanian (Romania)
269.3052 +display locale: ID: ro_RO, Name: Romanian (Romania)
269.3053 +format locale: ID: ro_RO, Name: Romanian (Romania)
269.3054 +default charset: ISO-8859-2
269.3055 +
269.3056 +OS Locale:  ro_RO.utf8
269.3057 +default locale: ID: ro_RO, Name: Romanian (Romania)
269.3058 +display locale: ID: ro_RO, Name: Romanian (Romania)
269.3059 +format locale: ID: ro_RO, Name: Romanian (Romania)
269.3060 +default charset: UTF-8
269.3061 +
269.3062 +OS Locale:  romanian
269.3063 +default locale: ID: ro_RO, Name: Romanian (Romania)
269.3064 +display locale: ID: ro_RO, Name: Romanian (Romania)
269.3065 +format locale: ID: ro_RO, Name: Romanian (Romania)
269.3066 +default charset: ISO-8859-2
269.3067 +
269.3068 +OS Locale:  ru_RU
269.3069 +default locale: ID: ru_RU, Name: Russian (Russia)
269.3070 +display locale: ID: ru_RU, Name: Russian (Russia)
269.3071 +format locale: ID: ru_RU, Name: Russian (Russia)
269.3072 +default charset: ISO-8859-5
269.3073 +
269.3074 +OS Locale:  ru_RU.iso88595
269.3075 +default locale: ID: ru_RU, Name: Russian (Russia)
269.3076 +display locale: ID: ru_RU, Name: Russian (Russia)
269.3077 +format locale: ID: ru_RU, Name: Russian (Russia)
269.3078 +default charset: ISO-8859-5
269.3079 +
269.3080 +OS Locale:  ru_RU.koi8r
269.3081 +default locale: ID: ru_RU, Name: Russian (Russia)
269.3082 +display locale: ID: ru_RU, Name: Russian (Russia)
269.3083 +format locale: ID: ru_RU, Name: Russian (Russia)
269.3084 +default charset: KOI8-R
269.3085 +
269.3086 +OS Locale:  ru_RU.utf8
269.3087 +default locale: ID: ru_RU, Name: Russian (Russia)
269.3088 +display locale: ID: ru_RU, Name: Russian (Russia)
269.3089 +format locale: ID: ru_RU, Name: Russian (Russia)
269.3090 +default charset: UTF-8
269.3091 +
269.3092 +OS Locale:  ru_UA
269.3093 +default locale: ID: ru_UA, Name: Russian (Ukraine)
269.3094 +display locale: ID: ru_UA, Name: Russian (Ukraine)
269.3095 +format locale: ID: ru_UA, Name: Russian (Ukraine)
269.3096 +default charset: KOI8-U
269.3097 +
269.3098 +OS Locale:  ru_UA.koi8u
269.3099 +default locale: ID: ru_UA, Name: Russian (Ukraine)
269.3100 +display locale: ID: ru_UA, Name: Russian (Ukraine)
269.3101 +format locale: ID: ru_UA, Name: Russian (Ukraine)
269.3102 +default charset: KOI8-U
269.3103 +
269.3104 +OS Locale:  ru_UA.utf8
269.3105 +default locale: ID: ru_UA, Name: Russian (Ukraine)
269.3106 +display locale: ID: ru_UA, Name: Russian (Ukraine)
269.3107 +format locale: ID: ru_UA, Name: Russian (Ukraine)
269.3108 +default charset: UTF-8
269.3109 +
269.3110 +OS Locale:  russian
269.3111 +default locale: ID: ru_RU, Name: Russian (Russia)
269.3112 +display locale: ID: ru_RU, Name: Russian (Russia)
269.3113 +format locale: ID: ru_RU, Name: Russian (Russia)
269.3114 +default charset: ISO-8859-5
269.3115 +
269.3116 +OS Locale:  rw_RW
269.3117 +default locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
269.3118 +display locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
269.3119 +format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
269.3120 +default charset: UTF-8
269.3121 +
269.3122 +OS Locale:  rw_RW.utf8
269.3123 +default locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
269.3124 +display locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
269.3125 +format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
269.3126 +default charset: UTF-8
269.3127 +
269.3128 +OS Locale:  se_NO
269.3129 +default locale: ID: se_NO, Name: Northern Sami (Norway)
269.3130 +display locale: ID: se_NO, Name: Northern Sami (Norway)
269.3131 +format locale: ID: se_NO, Name: Northern Sami (Norway)
269.3132 +default charset: UTF-8
269.3133 +
269.3134 +OS Locale:  se_NO.utf8
269.3135 +default locale: ID: se_NO, Name: Northern Sami (Norway)
269.3136 +display locale: ID: se_NO, Name: Northern Sami (Norway)
269.3137 +format locale: ID: se_NO, Name: Northern Sami (Norway)
269.3138 +default charset: UTF-8
269.3139 +
269.3140 +OS Locale:  si_LK
269.3141 +default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
269.3142 +display locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
269.3143 +format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
269.3144 +default charset: UTF-8
269.3145 +
269.3146 +OS Locale:  si_LK.utf8
269.3147 +default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
269.3148 +display locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
269.3149 +format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
269.3150 +default charset: UTF-8
269.3151 +
269.3152 +OS Locale:  sid_ET
269.3153 +default locale: ID: en_ET, Name: English (Ethiopia)
269.3154 +display locale: ID: en_ET, Name: English (Ethiopia)
269.3155 +format locale: ID: en_ET, Name: English (Ethiopia)
269.3156 +default charset: UTF-8
269.3157 +
269.3158 +OS Locale:  sid_ET.utf8
269.3159 +default locale: ID: en_ET, Name: English (Ethiopia)
269.3160 +display locale: ID: en_ET, Name: English (Ethiopia)
269.3161 +format locale: ID: en_ET, Name: English (Ethiopia)
269.3162 +default charset: UTF-8
269.3163 +
269.3164 +OS Locale:  sk_SK
269.3165 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3166 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3167 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3168 +default charset: ISO-8859-2
269.3169 +
269.3170 +OS Locale:  sk_SK.iso88592
269.3171 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3172 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3173 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3174 +default charset: ISO-8859-2
269.3175 +
269.3176 +OS Locale:  sk_SK.utf8
269.3177 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3178 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3179 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3180 +default charset: UTF-8
269.3181 +
269.3182 +OS Locale:  sl_SI
269.3183 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3184 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3185 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3186 +default charset: ISO-8859-2
269.3187 +
269.3188 +OS Locale:  sl_SI.iso88592
269.3189 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3190 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3191 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3192 +default charset: ISO-8859-2
269.3193 +
269.3194 +OS Locale:  sl_SI.utf8
269.3195 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3196 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3197 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3198 +default charset: UTF-8
269.3199 +
269.3200 +OS Locale:  slovak
269.3201 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3202 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3203 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
269.3204 +default charset: ISO-8859-2
269.3205 +
269.3206 +OS Locale:  slovene
269.3207 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3208 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3209 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3210 +default charset: ISO-8859-2
269.3211 +
269.3212 +OS Locale:  slovenian
269.3213 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3214 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3215 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
269.3216 +default charset: ISO-8859-2
269.3217 +
269.3218 +OS Locale:  so_DJ
269.3219 +default locale: ID: so_DJ, Name: Somali (Djibouti)
269.3220 +display locale: ID: so_DJ, Name: Somali (Djibouti)
269.3221 +format locale: ID: so_DJ, Name: Somali (Djibouti)
269.3222 +default charset: ISO-8859-1
269.3223 +
269.3224 +OS Locale:  so_DJ.iso88591
269.3225 +default locale: ID: so_DJ, Name: Somali (Djibouti)
269.3226 +display locale: ID: so_DJ, Name: Somali (Djibouti)
269.3227 +format locale: ID: so_DJ, Name: Somali (Djibouti)
269.3228 +default charset: ISO-8859-1
269.3229 +
269.3230 +OS Locale:  so_DJ.utf8
269.3231 +default locale: ID: so_DJ, Name: Somali (Djibouti)
269.3232 +display locale: ID: so_DJ, Name: Somali (Djibouti)
269.3233 +format locale: ID: so_DJ, Name: Somali (Djibouti)
269.3234 +default charset: UTF-8
269.3235 +
269.3236 +OS Locale:  so_ET
269.3237 +default locale: ID: so_ET, Name: Somali (Ethiopia)
269.3238 +display locale: ID: so_ET, Name: Somali (Ethiopia)
269.3239 +format locale: ID: so_ET, Name: Somali (Ethiopia)
269.3240 +default charset: UTF-8
269.3241 +
269.3242 +OS Locale:  so_ET.utf8
269.3243 +default locale: ID: so_ET, Name: Somali (Ethiopia)
269.3244 +display locale: ID: so_ET, Name: Somali (Ethiopia)
269.3245 +format locale: ID: so_ET, Name: Somali (Ethiopia)
269.3246 +default charset: UTF-8
269.3247 +
269.3248 +OS Locale:  so_KE
269.3249 +default locale: ID: so_KE, Name: Somali (Kenya)
269.3250 +display locale: ID: so_KE, Name: Somali (Kenya)
269.3251 +format locale: ID: so_KE, Name: Somali (Kenya)
269.3252 +default charset: ISO-8859-1
269.3253 +
269.3254 +OS Locale:  so_KE.iso88591
269.3255 +default locale: ID: so_KE, Name: Somali (Kenya)
269.3256 +display locale: ID: so_KE, Name: Somali (Kenya)
269.3257 +format locale: ID: so_KE, Name: Somali (Kenya)
269.3258 +default charset: ISO-8859-1
269.3259 +
269.3260 +OS Locale:  so_KE.utf8
269.3261 +default locale: ID: so_KE, Name: Somali (Kenya)
269.3262 +display locale: ID: so_KE, Name: Somali (Kenya)
269.3263 +format locale: ID: so_KE, Name: Somali (Kenya)
269.3264 +default charset: UTF-8
269.3265 +
269.3266 +OS Locale:  so_SO
269.3267 +default locale: ID: so_SO, Name: Somali (Somalia)
269.3268 +display locale: ID: so_SO, Name: Somali (Somalia)
269.3269 +format locale: ID: so_SO, Name: Somali (Somalia)
269.3270 +default charset: ISO-8859-1
269.3271 +
269.3272 +OS Locale:  so_SO.iso88591
269.3273 +default locale: ID: so_SO, Name: Somali (Somalia)
269.3274 +display locale: ID: so_SO, Name: Somali (Somalia)
269.3275 +format locale: ID: so_SO, Name: Somali (Somalia)
269.3276 +default charset: ISO-8859-1
269.3277 +
269.3278 +OS Locale:  so_SO.utf8
269.3279 +default locale: ID: so_SO, Name: Somali (Somalia)
269.3280 +display locale: ID: so_SO, Name: Somali (Somalia)
269.3281 +format locale: ID: so_SO, Name: Somali (Somalia)
269.3282 +default charset: UTF-8
269.3283 +
269.3284 +OS Locale:  spanish
269.3285 +default locale: ID: es_ES, Name: Spanish (Spain)
269.3286 +display locale: ID: es_ES, Name: Spanish (Spain)
269.3287 +format locale: ID: es_ES, Name: Spanish (Spain)
269.3288 +default charset: ISO-8859-1
269.3289 +
269.3290 +OS Locale:  sq_AL
269.3291 +default locale: ID: sq_AL, Name: Albanian (Albania)
269.3292 +display locale: ID: sq_AL, Name: Albanian (Albania)
269.3293 +format locale: ID: sq_AL, Name: Albanian (Albania)
269.3294 +default charset: ISO-8859-1
269.3295 +
269.3296 +OS Locale:  sq_AL.iso88591
269.3297 +default locale: ID: sq_AL, Name: Albanian (Albania)
269.3298 +display locale: ID: sq_AL, Name: Albanian (Albania)
269.3299 +format locale: ID: sq_AL, Name: Albanian (Albania)
269.3300 +default charset: ISO-8859-1
269.3301 +
269.3302 +OS Locale:  sq_AL.utf8
269.3303 +default locale: ID: sq_AL, Name: Albanian (Albania)
269.3304 +display locale: ID: sq_AL, Name: Albanian (Albania)
269.3305 +format locale: ID: sq_AL, Name: Albanian (Albania)
269.3306 +default charset: UTF-8
269.3307 +
269.3308 +OS Locale:  sr_CS
269.3309 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3310 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3311 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3312 +default charset: ISO-8859-5
269.3313 +
269.3314 +OS Locale:  sr_CS.iso88595
269.3315 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3316 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3317 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3318 +default charset: ISO-8859-5
269.3319 +
269.3320 +OS Locale:  sr_CS.utf8
269.3321 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3322 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3323 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
269.3324 +default charset: UTF-8
269.3325 +
269.3326 +OS Locale:  sr_ME
269.3327 +default locale: ID: sr, Name: Serbian
269.3328 +display locale: ID: sr, Name: Serbian
269.3329 +format locale: ID: sr, Name: Serbian
269.3330 +default charset: UTF-8
269.3331 +
269.3332 +OS Locale:  sr_ME.utf8
269.3333 +default locale: ID: sr, Name: Serbian
269.3334 +display locale: ID: sr, Name: Serbian
269.3335 +format locale: ID: sr, Name: Serbian
269.3336 +default charset: UTF-8
269.3337 +
269.3338 +OS Locale:  sr_RS
269.3339 +default locale: ID: sr, Name: Serbian
269.3340 +display locale: ID: sr, Name: Serbian
269.3341 +format locale: ID: sr, Name: Serbian
269.3342 +default charset: UTF-8
269.3343 +
269.3344 +OS Locale:  sr_RS.utf8
269.3345 +default locale: ID: sr, Name: Serbian
269.3346 +display locale: ID: sr, Name: Serbian
269.3347 +format locale: ID: sr, Name: Serbian
269.3348 +default charset: UTF-8
269.3349 +
269.3350 +OS Locale:  sr_RS.utf8@latin
269.3351 +default locale: ID: sr, Name: Serbian
269.3352 +display locale: ID: sr, Name: Serbian
269.3353 +format locale: ID: sr, Name: Serbian
269.3354 +default charset: UTF-8
269.3355 +
269.3356 +OS Locale:  sr_RS@latin
269.3357 +default locale: ID: sr, Name: Serbian
269.3358 +display locale: ID: sr, Name: Serbian
269.3359 +format locale: ID: sr, Name: Serbian
269.3360 +default charset: UTF-8
269.3361 +
269.3362 +OS Locale:  ss_ZA
269.3363 +default locale: ID: ss_ZA, Name: Swati (South Africa)
269.3364 +display locale: ID: ss_ZA, Name: Swati (South Africa)
269.3365 +format locale: ID: ss_ZA, Name: Swati (South Africa)
269.3366 +default charset: UTF-8
269.3367 +
269.3368 +OS Locale:  ss_ZA.utf8
269.3369 +default locale: ID: ss_ZA, Name: Swati (South Africa)
269.3370 +display locale: ID: ss_ZA, Name: Swati (South Africa)
269.3371 +format locale: ID: ss_ZA, Name: Swati (South Africa)
269.3372 +default charset: UTF-8
269.3373 +
269.3374 +OS Locale:  st_ZA
269.3375 +default locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3376 +display locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3377 +format locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3378 +default charset: ISO-8859-1
269.3379 +
269.3380 +OS Locale:  st_ZA.iso88591
269.3381 +default locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3382 +display locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3383 +format locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3384 +default charset: ISO-8859-1
269.3385 +
269.3386 +OS Locale:  st_ZA.utf8
269.3387 +default locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3388 +display locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3389 +format locale: ID: st_ZA, Name: Southern Sotho (South Africa)
269.3390 +default charset: UTF-8
269.3391 +
269.3392 +OS Locale:  sv_FI
269.3393 +default locale: ID: sv_FI, Name: Swedish (Finland)
269.3394 +display locale: ID: sv_FI, Name: Swedish (Finland)
269.3395 +format locale: ID: sv_FI, Name: Swedish (Finland)
269.3396 +default charset: ISO-8859-1
269.3397 +
269.3398 +OS Locale:  sv_FI.iso88591
269.3399 +default locale: ID: sv_FI, Name: Swedish (Finland)
269.3400 +display locale: ID: sv_FI, Name: Swedish (Finland)
269.3401 +format locale: ID: sv_FI, Name: Swedish (Finland)
269.3402 +default charset: ISO-8859-1
269.3403 +
269.3404 +OS Locale:  sv_FI.iso885915@euro
269.3405 +default locale: ID: sv_FI, Name: Swedish (Finland)
269.3406 +display locale: ID: sv_FI, Name: Swedish (Finland)
269.3407 +format locale: ID: sv_FI, Name: Swedish (Finland)
269.3408 +default charset: ISO-8859-15
269.3409 +
269.3410 +OS Locale:  sv_FI.utf8
269.3411 +default locale: ID: sv_FI, Name: Swedish (Finland)
269.3412 +display locale: ID: sv_FI, Name: Swedish (Finland)
269.3413 +format locale: ID: sv_FI, Name: Swedish (Finland)
269.3414 +default charset: UTF-8
269.3415 +
269.3416 +OS Locale:  sv_FI@euro
269.3417 +default locale: ID: sv_FI, Name: Swedish (Finland)
269.3418 +display locale: ID: sv_FI, Name: Swedish (Finland)
269.3419 +format locale: ID: sv_FI, Name: Swedish (Finland)
269.3420 +default charset: ISO-8859-15
269.3421 +
269.3422 +OS Locale:  sv_SE
269.3423 +default locale: ID: sv_SE, Name: Swedish (Sweden)
269.3424 +display locale: ID: sv_SE, Name: Swedish (Sweden)
269.3425 +format locale: ID: sv_SE, Name: Swedish (Sweden)
269.3426 +default charset: ISO-8859-1
269.3427 +
269.3428 +OS Locale:  sv_SE.iso88591
269.3429 +default locale: ID: sv_SE, Name: Swedish (Sweden)
269.3430 +display locale: ID: sv_SE, Name: Swedish (Sweden)
269.3431 +format locale: ID: sv_SE, Name: Swedish (Sweden)
269.3432 +default charset: ISO-8859-1
269.3433 +
269.3434 +OS Locale:  sv_SE.iso885915
269.3435 +default locale: ID: sv_SE, Name: Swedish (Sweden)
269.3436 +display locale: ID: sv_SE, Name: Swedish (Sweden)
269.3437 +format locale: ID: sv_SE, Name: Swedish (Sweden)
269.3438 +default charset: ISO-8859-15
269.3439 +
269.3440 +OS Locale:  sv_SE.utf8
269.3441 +default locale: ID: sv_SE, Name: Swedish (Sweden)
269.3442 +display locale: ID: sv_SE, Name: Swedish (Sweden)
269.3443 +format locale: ID: sv_SE, Name: Swedish (Sweden)
269.3444 +default charset: UTF-8
269.3445 +
269.3446 +OS Locale:  swedish
269.3447 +default locale: ID: sv_SE, Name: Swedish (Sweden)
269.3448 +display locale: ID: sv_SE, Name: Swedish (Sweden)
269.3449 +format locale: ID: sv_SE, Name: Swedish (Sweden)
269.3450 +default charset: ISO-8859-1
269.3451 +
269.3452 +OS Locale:  ta_IN
269.3453 +default locale: ID: ta_IN, Name: Tamil (India)
269.3454 +display locale: ID: ta_IN, Name: Tamil (India)
269.3455 +format locale: ID: ta_IN, Name: Tamil (India)
269.3456 +default charset: UTF-8
269.3457 +
269.3458 +OS Locale:  ta_IN.utf8
269.3459 +default locale: ID: ta_IN, Name: Tamil (India)
269.3460 +display locale: ID: ta_IN, Name: Tamil (India)
269.3461 +format locale: ID: ta_IN, Name: Tamil (India)
269.3462 +default charset: UTF-8
269.3463 +
269.3464 +OS Locale:  te_IN
269.3465 +default locale: ID: te_IN, Name: Telugu (India)
269.3466 +display locale: ID: te_IN, Name: Telugu (India)
269.3467 +format locale: ID: te_IN, Name: Telugu (India)
269.3468 +default charset: UTF-8
269.3469 +
269.3470 +OS Locale:  te_IN.utf8
269.3471 +default locale: ID: te_IN, Name: Telugu (India)
269.3472 +display locale: ID: te_IN, Name: Telugu (India)
269.3473 +format locale: ID: te_IN, Name: Telugu (India)
269.3474 +default charset: UTF-8
269.3475 +
269.3476 +OS Locale:  tg_TJ
269.3477 +default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3478 +display locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3479 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3480 +default charset: UTF-8
269.3481 +
269.3482 +OS Locale:  tg_TJ.koi8t
269.3483 +default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3484 +display locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3485 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3486 +default charset: UTF-8
269.3487 +
269.3488 +OS Locale:  tg_TJ.utf8
269.3489 +default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3490 +display locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3491 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
269.3492 +default charset: UTF-8
269.3493 +
269.3494 +OS Locale:  th_TH
269.3495 +default locale: ID: th_TH, Name: Thai (Thailand)
269.3496 +display locale: ID: th_TH, Name: Thai (Thailand)
269.3497 +format locale: ID: th_TH, Name: Thai (Thailand)
269.3498 +default charset: TIS-620
269.3499 +
269.3500 +OS Locale:  th_TH.tis620
269.3501 +default locale: ID: th_TH, Name: Thai (Thailand)
269.3502 +display locale: ID: th_TH, Name: Thai (Thailand)
269.3503 +format locale: ID: th_TH, Name: Thai (Thailand)
269.3504 +default charset: TIS-620
269.3505 +
269.3506 +OS Locale:  th_TH.utf8
269.3507 +default locale: ID: th_TH, Name: Thai (Thailand)
269.3508 +display locale: ID: th_TH, Name: Thai (Thailand)
269.3509 +format locale: ID: th_TH, Name: Thai (Thailand)
269.3510 +default charset: UTF-8
269.3511 +
269.3512 +OS Locale:  thai
269.3513 +default locale: ID: en, Name: English
269.3514 +display locale: ID: en, Name: English
269.3515 +format locale: ID: en, Name: English
269.3516 +default charset: TIS-620
269.3517 +
269.3518 +OS Locale:  ti_ER
269.3519 +default locale: ID: ti_ER, Name: Tigrinya (Eritrea)
269.3520 +display locale: ID: ti_ER, Name: Tigrinya (Eritrea)
269.3521 +format locale: ID: ti_ER, Name: Tigrinya (Eritrea)
269.3522 +default charset: UTF-8
269.3523 +
269.3524 +OS Locale:  ti_ER.utf8
269.3525 +default locale: ID: ti_ER, Name: Tigrinya (Eritrea)
269.3526 +display locale: ID: ti_ER, Name: Tigrinya (Eritrea)
269.3527 +format locale: ID: ti_ER, Name: Tigrinya (Eritrea)
269.3528 +default charset: UTF-8
269.3529 +
269.3530 +OS Locale:  ti_ET
269.3531 +default locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
269.3532 +display locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
269.3533 +format locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
269.3534 +default charset: UTF-8
269.3535 +
269.3536 +OS Locale:  ti_ET.utf8
269.3537 +default locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
269.3538 +display locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
269.3539 +format locale: ID: ti_ET, Name: Tigrinya (Ethiopia)
269.3540 +default charset: UTF-8
269.3541 +
269.3542 +OS Locale:  tig_ER
269.3543 +default locale: ID: en_ER, Name: English (Eritrea)
269.3544 +display locale: ID: en_ER, Name: English (Eritrea)
269.3545 +format locale: ID: en_ER, Name: English (Eritrea)
269.3546 +default charset: UTF-8
269.3547 +
269.3548 +OS Locale:  tig_ER.utf8
269.3549 +default locale: ID: en_ER, Name: English (Eritrea)
269.3550 +display locale: ID: en_ER, Name: English (Eritrea)
269.3551 +format locale: ID: en_ER, Name: English (Eritrea)
269.3552 +default charset: UTF-8
269.3553 +
269.3554 +OS Locale:  tl_PH
269.3555 +default locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3556 +display locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3557 +format locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3558 +default charset: ISO-8859-1
269.3559 +
269.3560 +OS Locale:  tl_PH.iso88591
269.3561 +default locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3562 +display locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3563 +format locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3564 +default charset: ISO-8859-1
269.3565 +
269.3566 +OS Locale:  tl_PH.utf8
269.3567 +default locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3568 +display locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3569 +format locale: ID: tl_PH, Name: Tagalog (Philippines)
269.3570 +default charset: UTF-8
269.3571 +
269.3572 +OS Locale:  tn_ZA
269.3573 +default locale: ID: tn_ZA, Name: Tswana (South Africa)
269.3574 +display locale: ID: tn_ZA, Name: Tswana (South Africa)
269.3575 +format locale: ID: tn_ZA, Name: Tswana (South Africa)
269.3576 +default charset: UTF-8
269.3577 +
269.3578 +OS Locale:  tn_ZA.utf8
269.3579 +default locale: ID: tn_ZA, Name: Tswana (South Africa)
269.3580 +display locale: ID: tn_ZA, Name: Tswana (South Africa)
269.3581 +format locale: ID: tn_ZA, Name: Tswana (South Africa)
269.3582 +default charset: UTF-8
269.3583 +
269.3584 +OS Locale:  tr_CY
269.3585 +default locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3586 +display locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3587 +format locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3588 +default charset: ISO-8859-9
269.3589 +
269.3590 +OS Locale:  tr_CY.iso88599
269.3591 +default locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3592 +display locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3593 +format locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3594 +default charset: ISO-8859-9
269.3595 +
269.3596 +OS Locale:  tr_CY.utf8
269.3597 +default locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3598 +display locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3599 +format locale: ID: tr_CY, Name: Turkish (Cyprus)
269.3600 +default charset: UTF-8
269.3601 +
269.3602 +OS Locale:  tr_TR
269.3603 +default locale: ID: tr_TR, Name: Turkish (Turkey)
269.3604 +display locale: ID: tr_TR, Name: Turkish (Turkey)
269.3605 +format locale: ID: tr_TR, Name: Turkish (Turkey)
269.3606 +default charset: ISO-8859-9
269.3607 +
269.3608 +OS Locale:  tr_TR.iso88599
269.3609 +default locale: ID: tr_TR, Name: Turkish (Turkey)
269.3610 +display locale: ID: tr_TR, Name: Turkish (Turkey)
269.3611 +format locale: ID: tr_TR, Name: Turkish (Turkey)
269.3612 +default charset: ISO-8859-9
269.3613 +
269.3614 +OS Locale:  tr_TR.utf8
269.3615 +default locale: ID: tr_TR, Name: Turkish (Turkey)
269.3616 +display locale: ID: tr_TR, Name: Turkish (Turkey)
269.3617 +format locale: ID: tr_TR, Name: Turkish (Turkey)
269.3618 +default charset: UTF-8
269.3619 +
269.3620 +OS Locale:  ts_ZA
269.3621 +default locale: ID: ts_ZA, Name: Tsonga (South Africa)
269.3622 +display locale: ID: ts_ZA, Name: Tsonga (South Africa)
269.3623 +format locale: ID: ts_ZA, Name: Tsonga (South Africa)
269.3624 +default charset: UTF-8
269.3625 +
269.3626 +OS Locale:  ts_ZA.utf8
269.3627 +default locale: ID: ts_ZA, Name: Tsonga (South Africa)
269.3628 +display locale: ID: ts_ZA, Name: Tsonga (South Africa)
269.3629 +format locale: ID: ts_ZA, Name: Tsonga (South Africa)
269.3630 +default charset: UTF-8
269.3631 +
269.3632 +OS Locale:  tt_RU.utf8
269.3633 +default locale: ID: tt_RU, Name: Tatar (Russia)
269.3634 +display locale: ID: tt_RU, Name: Tatar (Russia)
269.3635 +format locale: ID: tt_RU, Name: Tatar (Russia)
269.3636 +default charset: UTF-8
269.3637 +
269.3638 +OS Locale:  turkish
269.3639 +default locale: ID: tr_TR, Name: Turkish (Turkey)
269.3640 +display locale: ID: tr_TR, Name: Turkish (Turkey)
269.3641 +format locale: ID: tr_TR, Name: Turkish (Turkey)
269.3642 +default charset: ISO-8859-9
269.3643 +
269.3644 +OS Locale:  uk_UA
269.3645 +default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3646 +display locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3647 +format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3648 +default charset: KOI8-U
269.3649 +
269.3650 +OS Locale:  uk_UA.koi8u
269.3651 +default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3652 +display locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3653 +format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3654 +default charset: KOI8-U
269.3655 +
269.3656 +OS Locale:  uk_UA.utf8
269.3657 +default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3658 +display locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3659 +format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
269.3660 +default charset: UTF-8
269.3661 +
269.3662 +OS Locale:  ur_PK
269.3663 +default locale: ID: ur_PK, Name: Urdu (Pakistan)
269.3664 +display locale: ID: ur_PK, Name: Urdu (Pakistan)
269.3665 +format locale: ID: ur_PK, Name: Urdu (Pakistan)
269.3666 +default charset: UTF-8
269.3667 +
269.3668 +OS Locale:  ur_PK.utf8
269.3669 +default locale: ID: ur_PK, Name: Urdu (Pakistan)
269.3670 +display locale: ID: ur_PK, Name: Urdu (Pakistan)
269.3671 +format locale: ID: ur_PK, Name: Urdu (Pakistan)
269.3672 +default charset: UTF-8
269.3673 +
269.3674 +OS Locale:  uz_UZ
269.3675 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3676 +display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3677 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3678 +default charset: ISO-8859-1
269.3679 +
269.3680 +OS Locale:  uz_UZ.iso88591
269.3681 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3682 +display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3683 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3684 +default charset: ISO-8859-1
269.3685 +
269.3686 +OS Locale:  uz_UZ.utf8@cyrillic
269.3687 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3688 +display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3689 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3690 +default charset: UTF-8
269.3691 +
269.3692 +OS Locale:  uz_UZ@cyrillic
269.3693 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3694 +display locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3695 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
269.3696 +default charset: UTF-8
269.3697 +
269.3698 +OS Locale:  ve_ZA
269.3699 +default locale: ID: ve_ZA, Name: Venda (South Africa)
269.3700 +display locale: ID: ve_ZA, Name: Venda (South Africa)
269.3701 +format locale: ID: ve_ZA, Name: Venda (South Africa)
269.3702 +default charset: UTF-8
269.3703 +
269.3704 +OS Locale:  ve_ZA.utf8
269.3705 +default locale: ID: ve_ZA, Name: Venda (South Africa)
269.3706 +display locale: ID: ve_ZA, Name: Venda (South Africa)
269.3707 +format locale: ID: ve_ZA, Name: Venda (South Africa)
269.3708 +default charset: UTF-8
269.3709 +
269.3710 +OS Locale:  vi_VN
269.3711 +default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3712 +display locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3713 +format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3714 +default charset: UTF-8
269.3715 +
269.3716 +OS Locale:  vi_VN.tcvn
269.3717 +default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3718 +display locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3719 +format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3720 +default charset: UTF-8
269.3721 +
269.3722 +OS Locale:  vi_VN.utf8
269.3723 +default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3724 +display locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3725 +format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
269.3726 +default charset: UTF-8
269.3727 +
269.3728 +OS Locale:  wa_BE
269.3729 +default locale: ID: wa_BE, Name: Walloon (Belgium)
269.3730 +display locale: ID: wa_BE, Name: Walloon (Belgium)
269.3731 +format locale: ID: wa_BE, Name: Walloon (Belgium)
269.3732 +default charset: ISO-8859-1
269.3733 +
269.3734 +OS Locale:  wa_BE.iso88591
269.3735 +default locale: ID: wa_BE, Name: Walloon (Belgium)
269.3736 +display locale: ID: wa_BE, Name: Walloon (Belgium)
269.3737 +format locale: ID: wa_BE, Name: Walloon (Belgium)
269.3738 +default charset: ISO-8859-1
269.3739 +
269.3740 +OS Locale:  wa_BE.iso885915@euro
269.3741 +default locale: ID: wa_BE, Name: Walloon (Belgium)
269.3742 +display locale: ID: wa_BE, Name: Walloon (Belgium)
269.3743 +format locale: ID: wa_BE, Name: Walloon (Belgium)
269.3744 +default charset: ISO-8859-15
269.3745 +
269.3746 +OS Locale:  wa_BE.utf8
269.3747 +default locale: ID: wa_BE, Name: Walloon (Belgium)
269.3748 +display locale: ID: wa_BE, Name: Walloon (Belgium)
269.3749 +format locale: ID: wa_BE, Name: Walloon (Belgium)
269.3750 +default charset: UTF-8
269.3751 +
269.3752 +OS Locale:  wa_BE@euro
269.3753 +default locale: ID: wa_BE, Name: Walloon (Belgium)
269.3754 +display locale: ID: wa_BE, Name: Walloon (Belgium)
269.3755 +format locale: ID: wa_BE, Name: Walloon (Belgium)
269.3756 +default charset: ISO-8859-15
269.3757 +
269.3758 +OS Locale:  xh_ZA
269.3759 +default locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3760 +display locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3761 +format locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3762 +default charset: ISO-8859-1
269.3763 +
269.3764 +OS Locale:  xh_ZA.iso88591
269.3765 +default locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3766 +display locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3767 +format locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3768 +default charset: ISO-8859-1
269.3769 +
269.3770 +OS Locale:  xh_ZA.utf8
269.3771 +default locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3772 +display locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3773 +format locale: ID: xh_ZA, Name: Xhosa (South Africa)
269.3774 +default charset: UTF-8
269.3775 +
269.3776 +OS Locale:  yi_US
269.3777 +default locale: ID: ji_US, Name: Yiddish (United States)
269.3778 +display locale: ID: ji_US, Name: Yiddish (United States)
269.3779 +format locale: ID: ji_US, Name: Yiddish (United States)
269.3780 +default charset: windows-1255
269.3781 +
269.3782 +OS Locale:  yi_US.cp1255
269.3783 +default locale: ID: ji_US, Name: Yiddish (United States)
269.3784 +display locale: ID: ji_US, Name: Yiddish (United States)
269.3785 +format locale: ID: ji_US, Name: Yiddish (United States)
269.3786 +default charset: windows-1255
269.3787 +
269.3788 +OS Locale:  yi_US.utf8
269.3789 +default locale: ID: ji_US, Name: Yiddish (United States)
269.3790 +display locale: ID: ji_US, Name: Yiddish (United States)
269.3791 +format locale: ID: ji_US, Name: Yiddish (United States)
269.3792 +default charset: UTF-8
269.3793 +
269.3794 +OS Locale:  zh_CN
269.3795 +default locale: ID: zh_CN, Name: Chinese (China)
269.3796 +display locale: ID: zh_CN, Name: Chinese (China)
269.3797 +format locale: ID: zh_CN, Name: Chinese (China)
269.3798 +default charset: GB2312
269.3799 +
269.3800 +OS Locale:  zh_CN.gb18030
269.3801 +default locale: ID: zh_CN, Name: Chinese (China)
269.3802 +display locale: ID: zh_CN, Name: Chinese (China)
269.3803 +format locale: ID: zh_CN, Name: Chinese (China)
269.3804 +default charset: GB18030
269.3805 +
269.3806 +OS Locale:  zh_CN.gb2312
269.3807 +default locale: ID: zh_CN, Name: Chinese (China)
269.3808 +display locale: ID: zh_CN, Name: Chinese (China)
269.3809 +format locale: ID: zh_CN, Name: Chinese (China)
269.3810 +default charset: GB2312
269.3811 +
269.3812 +OS Locale:  zh_CN.gbk
269.3813 +default locale: ID: zh_CN, Name: Chinese (China)
269.3814 +display locale: ID: zh_CN, Name: Chinese (China)
269.3815 +format locale: ID: zh_CN, Name: Chinese (China)
269.3816 +default charset: GBK
269.3817 +
269.3818 +OS Locale:  zh_CN.utf8
269.3819 +default locale: ID: zh_CN, Name: Chinese (China)
269.3820 +display locale: ID: zh_CN, Name: Chinese (China)
269.3821 +format locale: ID: zh_CN, Name: Chinese (China)
269.3822 +default charset: UTF-8
269.3823 +
269.3824 +OS Locale:  zh_HK
269.3825 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3826 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3827 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3828 +default charset: Big5-HKSCS
269.3829 +
269.3830 +OS Locale:  zh_HK.big5hkscs
269.3831 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3832 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3833 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3834 +default charset: Big5-HKSCS
269.3835 +
269.3836 +OS Locale:  zh_HK.utf8
269.3837 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3838 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3839 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
269.3840 +default charset: UTF-8
269.3841 +
269.3842 +OS Locale:  zh_SG
269.3843 +default locale: ID: zh_SG, Name: Chinese (Singapore)
269.3844 +display locale: ID: zh_SG, Name: Chinese (Singapore)
269.3845 +format locale: ID: zh_SG, Name: Chinese (Singapore)
269.3846 +default charset: GB2312
269.3847 +
269.3848 +OS Locale:  zh_SG.gb2312
269.3849 +default locale: ID: zh_SG, Name: Chinese (Singapore)
269.3850 +display locale: ID: zh_SG, Name: Chinese (Singapore)
269.3851 +format locale: ID: zh_SG, Name: Chinese (Singapore)
269.3852 +default charset: GB2312
269.3853 +
269.3854 +OS Locale:  zh_SG.gbk
269.3855 +default locale: ID: zh_SG, Name: Chinese (Singapore)
269.3856 +display locale: ID: zh_SG, Name: Chinese (Singapore)
269.3857 +format locale: ID: zh_SG, Name: Chinese (Singapore)
269.3858 +default charset: GBK
269.3859 +
269.3860 +OS Locale:  zh_SG.utf8
269.3861 +default locale: ID: zh_SG, Name: Chinese (Singapore)
269.3862 +display locale: ID: zh_SG, Name: Chinese (Singapore)
269.3863 +format locale: ID: zh_SG, Name: Chinese (Singapore)
269.3864 +default charset: UTF-8
269.3865 +
269.3866 +OS Locale:  zh_TW
269.3867 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3868 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3869 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3870 +default charset: Big5
269.3871 +
269.3872 +OS Locale:  zh_TW.big5
269.3873 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3874 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3875 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3876 +default charset: Big5
269.3877 +
269.3878 +OS Locale:  zh_TW.euctw
269.3879 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3880 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3881 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3882 +default charset: x-EUC-TW
269.3883 +
269.3884 +OS Locale:  zh_TW.utf8
269.3885 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3886 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3887 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
269.3888 +default charset: UTF-8
269.3889 +
269.3890 +OS Locale:  zu_ZA
269.3891 +default locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3892 +display locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3893 +format locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3894 +default charset: ISO-8859-1
269.3895 +
269.3896 +OS Locale:  zu_ZA.iso88591
269.3897 +default locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3898 +display locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3899 +format locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3900 +default charset: ISO-8859-1
269.3901 +
269.3902 +OS Locale:  zu_ZA.utf8
269.3903 +default locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3904 +display locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3905 +format locale: ID: zu_ZA, Name: Zulu (South Africa)
269.3906 +default charset: UTF-8
269.3907 +
269.3908 +Testing some typical combinations
269.3909 +
269.3910 +
269.3911 +OS Locale (LC_CTYPE: ja_JP.UTF-8, LC_MESSAGES: zh_CN.UTF-8)
269.3912 +default locale: ID: ja_JP, Name: Japanese (Japan)
269.3913 +display locale: ID: zh_CN, Name: Chinese (China)
269.3914 +format locale: ID: ja_JP, Name: Japanese (Japan)
269.3915 +default charset: UTF-8
269.3916 +
269.3917 +OS Locale (LC_CTYPE: zh_CN.UTF-8, LC_MESSAGES: en_US.UTF-8)
269.3918 +default locale: ID: zh_CN, Name: Chinese (China)
269.3919 +display locale: ID: en_US, Name: English (United States)
269.3920 +format locale: ID: zh_CN, Name: Chinese (China)
269.3921 +default charset: UTF-8
269.3922 +
269.3923 +OS Locale (LC_CTYPE: C, LC_MESSAGES: zh_CN.UTF-8)
269.3924 +default locale: ID: en_US, Name: English (United States)
269.3925 +display locale: ID: zh_CN, Name: Chinese (China)
269.3926 +format locale: ID: en_US, Name: English (United States)
269.3927 +default charset: US-ASCII
   270.1 --- a/test/java/util/Locale/data/deflocale.sh	Thu Sep 23 17:33:40 2010 -0700
   270.2 +++ b/test/java/util/Locale/data/deflocale.sh	Fri Sep 24 16:41:32 2010 -0700
   270.3 @@ -31,8 +31,21 @@
   270.4  #
   270.5  cat /etc/*release
   270.6  uname -a
   270.7 -env LC_COLLATE=C ls /usr/lib/locale | while read line; do
   270.8 +echo "Testing all available locales"
   270.9 +/usr/bin/locale -a | while read line; do
  270.10      echo ""
  270.11      echo "OS Locale: " $line
  270.12 -    env LANG=$line LC_ALL=$line $1 PrintDefaultLocale
  270.13 +    env LC_ALL= LC_CTYPE= LC_MESSAGES= LANG=$line $1 $2 $3 $4 $5 $6 $7 $8 $9 PrintDefaultLocale
  270.14  done
  270.15 +
  270.16 +echo ""
  270.17 +echo "Testing some typical combinations"
  270.18 +echo ""
  270.19 +while read lcctype lcmessages; do
  270.20 +    if [ "$lcctype" = "#" -o "$lcctype" = "" ]; then
  270.21 +        continue
  270.22 +    fi
  270.23 +    echo ""
  270.24 +    echo "OS Locale (LC_CTYPE: "$lcctype", LC_MESSAGES: "$lcmessages")"
  270.25 +    env LC_ALL= LC_CTYPE=$lcctype LC_MESSAGES=$lcmessages $1 $2 $3 $4 $5 $6 $7 $8 $9 PrintDefaultLocale
  270.26 +done < deflocale.input
   271.1 --- a/test/java/util/Locale/data/deflocale.sol10	Thu Sep 23 17:33:40 2010 -0700
   271.2 +++ b/test/java/util/Locale/data/deflocale.sol10	Fri Sep 24 16:41:32 2010 -0700
   271.3 @@ -2,1449 +2,1724 @@
   271.4  
   271.5                        (copyright from `uname -a` goes here)
   271.6  
   271.7 -SunOS deltas4 5.10 Generic_118833-03 sun4u sparc SUNW,Sun-Blade-2500
   271.8 +SunOS deltas4 5.10 Generic_142900-03 sun4u sparc SUNW,Sun-Blade-2500
   271.9 +Testing all available locales
  271.10  
  271.11  OS Locale:  C
  271.12 -en
  271.13 -English
  271.14 -US-ASCII
  271.15 +default locale: ID: en, Name: English
  271.16 +display locale: ID: en, Name: English
  271.17 +format locale: ID: en, Name: English
  271.18 +default charset: US-ASCII
  271.19  
  271.20  OS Locale:  POSIX
  271.21 -en
  271.22 -English
  271.23 -US-ASCII
  271.24 +default locale: ID: en, Name: English
  271.25 +display locale: ID: en, Name: English
  271.26 +format locale: ID: en, Name: English
  271.27 +default charset: US-ASCII
  271.28  
  271.29  OS Locale:  ar
  271.30 -ar_EG
  271.31 -Arabic (Egypt)
  271.32 -ISO-8859-6
  271.33 +default locale: ID: ar_EG, Name: Arabic (Egypt)
  271.34 +display locale: ID: ar_EG, Name: Arabic (Egypt)
  271.35 +format locale: ID: ar_EG, Name: Arabic (Egypt)
  271.36 +default charset: ISO-8859-6
  271.37  
  271.38  OS Locale:  ar_EG.UTF-8
  271.39 -ar_EG
  271.40 -Arabic (Egypt)
  271.41 -UTF-8
  271.42 +default locale: ID: ar_EG, Name: Arabic (Egypt)
  271.43 +display locale: ID: ar_EG, Name: Arabic (Egypt)
  271.44 +format locale: ID: ar_EG, Name: Arabic (Egypt)
  271.45 +default charset: UTF-8
  271.46  
  271.47  OS Locale:  ar_SA.UTF-8
  271.48 -ar_SA
  271.49 -Arabic (Saudi Arabia)
  271.50 -UTF-8
  271.51 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  271.52 +display locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  271.53 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  271.54 +default charset: UTF-8
  271.55  
  271.56  OS Locale:  bg_BG
  271.57 -bg_BG
  271.58 -Bulgarian (Bulgaria)
  271.59 -ISO-8859-5
  271.60 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  271.61 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  271.62 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  271.63 +default charset: ISO-8859-5
  271.64  
  271.65  OS Locale:  bg_BG.ISO8859-5
  271.66 -bg_BG
  271.67 -Bulgarian (Bulgaria)
  271.68 -ISO-8859-5
  271.69 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  271.70 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  271.71 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  271.72 +default charset: ISO-8859-5
  271.73  
  271.74  OS Locale:  ca
  271.75 -ca_ES
  271.76 -Catalan (Spain)
  271.77 -ISO-8859-1
  271.78 +default locale: ID: ca_ES, Name: Catalan (Spain)
  271.79 +display locale: ID: ca_ES, Name: Catalan (Spain)
  271.80 +format locale: ID: ca_ES, Name: Catalan (Spain)
  271.81 +default charset: ISO-8859-1
  271.82  
  271.83  OS Locale:  ca_ES
  271.84 -ca_ES
  271.85 -Catalan (Spain)
  271.86 -ISO-8859-1
  271.87 +default locale: ID: ca_ES, Name: Catalan (Spain)
  271.88 +display locale: ID: ca_ES, Name: Catalan (Spain)
  271.89 +format locale: ID: ca_ES, Name: Catalan (Spain)
  271.90 +default charset: ISO-8859-1
  271.91  
  271.92  OS Locale:  ca_ES.ISO8859-1
  271.93 -ca_ES
  271.94 -Catalan (Spain)
  271.95 -ISO-8859-1
  271.96 +default locale: ID: ca_ES, Name: Catalan (Spain)
  271.97 +display locale: ID: ca_ES, Name: Catalan (Spain)
  271.98 +format locale: ID: ca_ES, Name: Catalan (Spain)
  271.99 +default charset: ISO-8859-1
 271.100  
 271.101  OS Locale:  ca_ES.ISO8859-15
 271.102 -ca_ES
 271.103 -Catalan (Spain)
 271.104 -ISO-8859-15
 271.105 +default locale: ID: ca_ES, Name: Catalan (Spain)
 271.106 +display locale: ID: ca_ES, Name: Catalan (Spain)
 271.107 +format locale: ID: ca_ES, Name: Catalan (Spain)
 271.108 +default charset: ISO-8859-15
 271.109  
 271.110  OS Locale:  ca_ES.ISO8859-15@euro
 271.111 -ca_ES
 271.112 -Catalan (Spain)
 271.113 -ISO-8859-15
 271.114 -
 271.115 -OS Locale:  common
 271.116 -en
 271.117 -English
 271.118 -ISO-8859-1
 271.119 +default locale: ID: ca_ES, Name: Catalan (Spain)
 271.120 +display locale: ID: ca_ES, Name: Catalan (Spain)
 271.121 +format locale: ID: ca_ES, Name: Catalan (Spain)
 271.122 +default charset: ISO-8859-15
 271.123  
 271.124  OS Locale:  cs_CZ
 271.125 -cs_CZ
 271.126 -Czech (Czech Republic)
 271.127 -ISO-8859-2
 271.128 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.129 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.130 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.131 +default charset: ISO-8859-2
 271.132  
 271.133  OS Locale:  cs_CZ.ISO8859-2
 271.134 -cs_CZ
 271.135 -Czech (Czech Republic)
 271.136 -ISO-8859-2
 271.137 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.138 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.139 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.140 +default charset: ISO-8859-2
 271.141  
 271.142  OS Locale:  cs_CZ.UTF-8
 271.143 -cs_CZ
 271.144 -Czech (Czech Republic)
 271.145 -UTF-8
 271.146 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.147 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.148 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.149 +default charset: UTF-8
 271.150  
 271.151  OS Locale:  cs_CZ.UTF-8@euro
 271.152 -cs_CZ
 271.153 -Czech (Czech Republic)
 271.154 -UTF-8
 271.155 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.156 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.157 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.158 +default charset: UTF-8
 271.159  
 271.160  OS Locale:  cz
 271.161 -cs_CZ
 271.162 -Czech (Czech Republic)
 271.163 -ISO-8859-2
 271.164 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.165 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.166 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 271.167 +default charset: ISO-8859-2
 271.168  
 271.169  OS Locale:  da
 271.170 -da_DK
 271.171 -Danish (Denmark)
 271.172 -ISO-8859-1
 271.173 +default locale: ID: da_DK, Name: Danish (Denmark)
 271.174 +display locale: ID: da_DK, Name: Danish (Denmark)
 271.175 +format locale: ID: da_DK, Name: Danish (Denmark)
 271.176 +default charset: ISO-8859-1
 271.177  
 271.178  OS Locale:  da.ISO8859-15
 271.179 -da_DK
 271.180 -Danish (Denmark)
 271.181 -ISO-8859-15
 271.182 +default locale: ID: da_DK, Name: Danish (Denmark)
 271.183 +display locale: ID: da_DK, Name: Danish (Denmark)
 271.184 +format locale: ID: da_DK, Name: Danish (Denmark)
 271.185 +default charset: ISO-8859-15
 271.186  
 271.187  OS Locale:  da_DK
 271.188 -da_DK
 271.189 -Danish (Denmark)
 271.190 -ISO-8859-1
 271.191 +default locale: ID: da_DK, Name: Danish (Denmark)
 271.192 +display locale: ID: da_DK, Name: Danish (Denmark)
 271.193 +format locale: ID: da_DK, Name: Danish (Denmark)
 271.194 +default charset: ISO-8859-1
 271.195  
 271.196  OS Locale:  da_DK.ISO8859-1
 271.197 -da_DK
 271.198 -Danish (Denmark)
 271.199 -ISO-8859-1
 271.200 +default locale: ID: da_DK, Name: Danish (Denmark)
 271.201 +display locale: ID: da_DK, Name: Danish (Denmark)
 271.202 +format locale: ID: da_DK, Name: Danish (Denmark)
 271.203 +default charset: ISO-8859-1
 271.204  
 271.205  OS Locale:  da_DK.ISO8859-15
 271.206 -da_DK
 271.207 -Danish (Denmark)
 271.208 -ISO-8859-15
 271.209 +default locale: ID: da_DK, Name: Danish (Denmark)
 271.210 +display locale: ID: da_DK, Name: Danish (Denmark)
 271.211 +format locale: ID: da_DK, Name: Danish (Denmark)
 271.212 +default charset: ISO-8859-15
 271.213  
 271.214  OS Locale:  da_DK.ISO8859-15@euro
 271.215 -da_DK
 271.216 -Danish (Denmark)
 271.217 -ISO-8859-15
 271.218 +default locale: ID: da_DK, Name: Danish (Denmark)
 271.219 +display locale: ID: da_DK, Name: Danish (Denmark)
 271.220 +format locale: ID: da_DK, Name: Danish (Denmark)
 271.221 +default charset: ISO-8859-15
 271.222  
 271.223  OS Locale:  de
 271.224 -de_DE
 271.225 -German (Germany)
 271.226 -ISO-8859-1
 271.227 +default locale: ID: de_DE, Name: German (Germany)
 271.228 +display locale: ID: de_DE, Name: German (Germany)
 271.229 +format locale: ID: de_DE, Name: German (Germany)
 271.230 +default charset: ISO-8859-1
 271.231  
 271.232  OS Locale:  de.ISO8859-15
 271.233 -de_DE
 271.234 -German (Germany)
 271.235 -ISO-8859-15
 271.236 +default locale: ID: de_DE, Name: German (Germany)
 271.237 +display locale: ID: de_DE, Name: German (Germany)
 271.238 +format locale: ID: de_DE, Name: German (Germany)
 271.239 +default charset: ISO-8859-15
 271.240  
 271.241  OS Locale:  de.UTF-8
 271.242 -de_DE
 271.243 -German (Germany)
 271.244 -UTF-8
 271.245 +default locale: ID: de_DE, Name: German (Germany)
 271.246 +display locale: ID: de_DE, Name: German (Germany)
 271.247 +format locale: ID: de_DE, Name: German (Germany)
 271.248 +default charset: UTF-8
 271.249  
 271.250  OS Locale:  de_AT
 271.251 -de_AT
 271.252 -German (Austria)
 271.253 -ISO-8859-1
 271.254 +default locale: ID: de_AT, Name: German (Austria)
 271.255 +display locale: ID: de_AT, Name: German (Austria)
 271.256 +format locale: ID: de_AT, Name: German (Austria)
 271.257 +default charset: ISO-8859-1
 271.258  
 271.259  OS Locale:  de_AT.ISO8859-1
 271.260 -de_AT
 271.261 -German (Austria)
 271.262 -ISO-8859-1
 271.263 +default locale: ID: de_AT, Name: German (Austria)
 271.264 +display locale: ID: de_AT, Name: German (Austria)
 271.265 +format locale: ID: de_AT, Name: German (Austria)
 271.266 +default charset: ISO-8859-1
 271.267  
 271.268  OS Locale:  de_AT.ISO8859-15
 271.269 -de_AT
 271.270 -German (Austria)
 271.271 -ISO-8859-15
 271.272 +default locale: ID: de_AT, Name: German (Austria)
 271.273 +display locale: ID: de_AT, Name: German (Austria)
 271.274 +format locale: ID: de_AT, Name: German (Austria)
 271.275 +default charset: ISO-8859-15
 271.276  
 271.277  OS Locale:  de_AT.ISO8859-15@euro
 271.278 -de_AT
 271.279 -German (Austria)
 271.280 -ISO-8859-15
 271.281 +default locale: ID: de_AT, Name: German (Austria)
 271.282 +display locale: ID: de_AT, Name: German (Austria)
 271.283 +format locale: ID: de_AT, Name: German (Austria)
 271.284 +default charset: ISO-8859-15
 271.285  
 271.286  OS Locale:  de_CH
 271.287 -de_CH
 271.288 -German (Switzerland)
 271.289 -ISO-8859-1
 271.290 +default locale: ID: de_CH, Name: German (Switzerland)
 271.291 +display locale: ID: de_CH, Name: German (Switzerland)
 271.292 +format locale: ID: de_CH, Name: German (Switzerland)
 271.293 +default charset: ISO-8859-1
 271.294  
 271.295  OS Locale:  de_CH.ISO8859-1
 271.296 -de_CH
 271.297 -German (Switzerland)
 271.298 -ISO-8859-1
 271.299 +default locale: ID: de_CH, Name: German (Switzerland)
 271.300 +display locale: ID: de_CH, Name: German (Switzerland)
 271.301 +format locale: ID: de_CH, Name: German (Switzerland)
 271.302 +default charset: ISO-8859-1
 271.303  
 271.304  OS Locale:  de_DE
 271.305 -de_DE
 271.306 -German (Germany)
 271.307 -ISO-8859-1
 271.308 +default locale: ID: de_DE, Name: German (Germany)
 271.309 +display locale: ID: de_DE, Name: German (Germany)
 271.310 +format locale: ID: de_DE, Name: German (Germany)
 271.311 +default charset: ISO-8859-1
 271.312  
 271.313  OS Locale:  de_DE.ISO8859-1
 271.314 -de_DE
 271.315 -German (Germany)
 271.316 -ISO-8859-1
 271.317 +default locale: ID: de_DE, Name: German (Germany)
 271.318 +display locale: ID: de_DE, Name: German (Germany)
 271.319 +format locale: ID: de_DE, Name: German (Germany)
 271.320 +default charset: ISO-8859-1
 271.321  
 271.322  OS Locale:  de_DE.ISO8859-15
 271.323 -de_DE
 271.324 -German (Germany)
 271.325 -ISO-8859-15
 271.326 +default locale: ID: de_DE, Name: German (Germany)
 271.327 +display locale: ID: de_DE, Name: German (Germany)
 271.328 +format locale: ID: de_DE, Name: German (Germany)
 271.329 +default charset: ISO-8859-15
 271.330  
 271.331  OS Locale:  de_DE.ISO8859-15@euro
 271.332 -de_DE
 271.333 -German (Germany)
 271.334 -ISO-8859-15
 271.335 +default locale: ID: de_DE, Name: German (Germany)
 271.336 +display locale: ID: de_DE, Name: German (Germany)
 271.337 +format locale: ID: de_DE, Name: German (Germany)
 271.338 +default charset: ISO-8859-15
 271.339  
 271.340  OS Locale:  de_DE.UTF-8
 271.341 -de_DE
 271.342 -German (Germany)
 271.343 -UTF-8
 271.344 +default locale: ID: de_DE, Name: German (Germany)
 271.345 +display locale: ID: de_DE, Name: German (Germany)
 271.346 +format locale: ID: de_DE, Name: German (Germany)
 271.347 +default charset: UTF-8
 271.348  
 271.349  OS Locale:  de_DE.UTF-8@euro
 271.350 -de_DE
 271.351 -German (Germany)
 271.352 -UTF-8
 271.353 +default locale: ID: de_DE, Name: German (Germany)
 271.354 +display locale: ID: de_DE, Name: German (Germany)
 271.355 +format locale: ID: de_DE, Name: German (Germany)
 271.356 +default charset: UTF-8
 271.357  
 271.358  OS Locale:  el
 271.359 -el_GR
 271.360 -Greek (Greece)
 271.361 -ISO-8859-7
 271.362 +default locale: ID: el_GR, Name: Greek (Greece)
 271.363 +display locale: ID: el_GR, Name: Greek (Greece)
 271.364 +format locale: ID: el_GR, Name: Greek (Greece)
 271.365 +default charset: ISO-8859-7
 271.366  
 271.367  OS Locale:  el.sun_eu_greek
 271.368 -el_GR
 271.369 -Greek (Greece)
 271.370 -ISO-8859-7
 271.371 +default locale: ID: el_GR, Name: Greek (Greece)
 271.372 +display locale: ID: el_GR, Name: Greek (Greece)
 271.373 +format locale: ID: el_GR, Name: Greek (Greece)
 271.374 +default charset: ISO-8859-7
 271.375  
 271.376  OS Locale:  el_GR
 271.377 -el_GR
 271.378 -Greek (Greece)
 271.379 -ISO-8859-7
 271.380 +default locale: ID: el_GR, Name: Greek (Greece)
 271.381 +display locale: ID: el_GR, Name: Greek (Greece)
 271.382 +format locale: ID: el_GR, Name: Greek (Greece)
 271.383 +default charset: ISO-8859-7
 271.384  
 271.385  OS Locale:  el_GR.ISO8859-7
 271.386 -el_GR
 271.387 -Greek (Greece)
 271.388 -ISO-8859-7
 271.389 +default locale: ID: el_GR, Name: Greek (Greece)
 271.390 +display locale: ID: el_GR, Name: Greek (Greece)
 271.391 +format locale: ID: el_GR, Name: Greek (Greece)
 271.392 +default charset: ISO-8859-7
 271.393  
 271.394  OS Locale:  el_GR.ISO8859-7@euro
 271.395 -el_GR
 271.396 -Greek (Greece)
 271.397 -ISO-8859-7
 271.398 +default locale: ID: el_GR, Name: Greek (Greece)
 271.399 +display locale: ID: el_GR, Name: Greek (Greece)
 271.400 +format locale: ID: el_GR, Name: Greek (Greece)
 271.401 +default charset: ISO-8859-7
 271.402  
 271.403  OS Locale:  en_AU
 271.404 -en_AU
 271.405 -English (Australia)
 271.406 -ISO-8859-1
 271.407 +default locale: ID: en_AU, Name: English (Australia)
 271.408 +display locale: ID: en_AU, Name: English (Australia)
 271.409 +format locale: ID: en_AU, Name: English (Australia)
 271.410 +default charset: ISO-8859-1
 271.411  
 271.412  OS Locale:  en_AU.ISO8859-1
 271.413 -en_AU
 271.414 -English (Australia)
 271.415 -ISO-8859-1
 271.416 +default locale: ID: en_AU, Name: English (Australia)
 271.417 +display locale: ID: en_AU, Name: English (Australia)
 271.418 +format locale: ID: en_AU, Name: English (Australia)
 271.419 +default charset: ISO-8859-1
 271.420  
 271.421  OS Locale:  en_CA
 271.422 -en_CA
 271.423 -English (Canada)
 271.424 -ISO-8859-1
 271.425 +default locale: ID: en_CA, Name: English (Canada)
 271.426 +display locale: ID: en_CA, Name: English (Canada)
 271.427 +format locale: ID: en_CA, Name: English (Canada)
 271.428 +default charset: ISO-8859-1
 271.429  
 271.430  OS Locale:  en_CA.ISO8859-1
 271.431 -en_CA
 271.432 -English (Canada)
 271.433 -ISO-8859-1
 271.434 +default locale: ID: en_CA, Name: English (Canada)
 271.435 +display locale: ID: en_CA, Name: English (Canada)
 271.436 +format locale: ID: en_CA, Name: English (Canada)
 271.437 +default charset: ISO-8859-1
 271.438 +
 271.439 +OS Locale:  en_CA.UTF-8
 271.440 +default locale: ID: en_CA, Name: English (Canada)
 271.441 +display locale: ID: en_CA, Name: English (Canada)
 271.442 +format locale: ID: en_CA, Name: English (Canada)
 271.443 +default charset: UTF-8
 271.444  
 271.445  OS Locale:  en_GB
 271.446 -en_GB
 271.447 -English (United Kingdom)
 271.448 -ISO-8859-1
 271.449 +default locale: ID: en_GB, Name: English (United Kingdom)
 271.450 +display locale: ID: en_GB, Name: English (United Kingdom)
 271.451 +format locale: ID: en_GB, Name: English (United Kingdom)
 271.452 +default charset: ISO-8859-1
 271.453  
 271.454  OS Locale:  en_GB.ISO8859-1
 271.455 -en_GB
 271.456 -English (United Kingdom)
 271.457 -ISO-8859-1
 271.458 +default locale: ID: en_GB, Name: English (United Kingdom)
 271.459 +display locale: ID: en_GB, Name: English (United Kingdom)
 271.460 +format locale: ID: en_GB, Name: English (United Kingdom)
 271.461 +default charset: ISO-8859-1
 271.462  
 271.463  OS Locale:  en_GB.ISO8859-15
 271.464 -en_GB
 271.465 -English (United Kingdom)
 271.466 -ISO-8859-15
 271.467 +default locale: ID: en_GB, Name: English (United Kingdom)
 271.468 +display locale: ID: en_GB, Name: English (United Kingdom)
 271.469 +format locale: ID: en_GB, Name: English (United Kingdom)
 271.470 +default charset: ISO-8859-15
 271.471  
 271.472  OS Locale:  en_GB.ISO8859-15@euro
 271.473 -en_GB
 271.474 -English (United Kingdom)
 271.475 -ISO-8859-15
 271.476 +default locale: ID: en_GB, Name: English (United Kingdom)
 271.477 +display locale: ID: en_GB, Name: English (United Kingdom)
 271.478 +format locale: ID: en_GB, Name: English (United Kingdom)
 271.479 +default charset: ISO-8859-15
 271.480  
 271.481  OS Locale:  en_IE
 271.482 -en_IE
 271.483 -English (Ireland)
 271.484 -ISO-8859-1
 271.485 +default locale: ID: en_IE, Name: English (Ireland)
 271.486 +display locale: ID: en_IE, Name: English (Ireland)
 271.487 +format locale: ID: en_IE, Name: English (Ireland)
 271.488 +default charset: ISO-8859-1
 271.489  
 271.490  OS Locale:  en_IE.ISO8859-1
 271.491 -en_IE
 271.492 -English (Ireland)
 271.493 -ISO-8859-1
 271.494 +default locale: ID: en_IE, Name: English (Ireland)
 271.495 +display locale: ID: en_IE, Name: English (Ireland)
 271.496 +format locale: ID: en_IE, Name: English (Ireland)
 271.497 +default charset: ISO-8859-1
 271.498  
 271.499  OS Locale:  en_IE.ISO8859-15
 271.500 -en_IE
 271.501 -English (Ireland)
 271.502 -ISO-8859-15
 271.503 +default locale: ID: en_IE, Name: English (Ireland)
 271.504 +display locale: ID: en_IE, Name: English (Ireland)
 271.505 +format locale: ID: en_IE, Name: English (Ireland)
 271.506 +default charset: ISO-8859-15
 271.507  
 271.508  OS Locale:  en_IE.ISO8859-15@euro
 271.509 -en_IE
 271.510 -English (Ireland)
 271.511 -ISO-8859-15
 271.512 +default locale: ID: en_IE, Name: English (Ireland)
 271.513 +display locale: ID: en_IE, Name: English (Ireland)
 271.514 +format locale: ID: en_IE, Name: English (Ireland)
 271.515 +default charset: ISO-8859-15
 271.516  
 271.517  OS Locale:  en_NZ
 271.518 -en_NZ
 271.519 -English (New Zealand)
 271.520 -ISO-8859-1
 271.521 +default locale: ID: en_NZ, Name: English (New Zealand)
 271.522 +display locale: ID: en_NZ, Name: English (New Zealand)
 271.523 +format locale: ID: en_NZ, Name: English (New Zealand)
 271.524 +default charset: ISO-8859-1
 271.525  
 271.526  OS Locale:  en_NZ.ISO8859-1
 271.527 -en_NZ
 271.528 -English (New Zealand)
 271.529 -ISO-8859-1
 271.530 +default locale: ID: en_NZ, Name: English (New Zealand)
 271.531 +display locale: ID: en_NZ, Name: English (New Zealand)
 271.532 +format locale: ID: en_NZ, Name: English (New Zealand)
 271.533 +default charset: ISO-8859-1
 271.534  
 271.535  OS Locale:  en_US
 271.536 -en_US
 271.537 -English (United States)
 271.538 -ISO-8859-1
 271.539 +default locale: ID: en_US, Name: English (United States)
 271.540 +display locale: ID: en_US, Name: English (United States)
 271.541 +format locale: ID: en_US, Name: English (United States)
 271.542 +default charset: ISO-8859-1
 271.543  
 271.544  OS Locale:  en_US.ISO8859-1
 271.545 -en_US
 271.546 -English (United States)
 271.547 -ISO-8859-1
 271.548 +default locale: ID: en_US, Name: English (United States)
 271.549 +display locale: ID: en_US, Name: English (United States)
 271.550 +format locale: ID: en_US, Name: English (United States)
 271.551 +default charset: ISO-8859-1
 271.552  
 271.553  OS Locale:  en_US.ISO8859-15
 271.554 -en_US
 271.555 -English (United States)
 271.556 -ISO-8859-15
 271.557 +default locale: ID: en_US, Name: English (United States)
 271.558 +display locale: ID: en_US, Name: English (United States)
 271.559 +format locale: ID: en_US, Name: English (United States)
 271.560 +default charset: ISO-8859-15
 271.561  
 271.562  OS Locale:  en_US.ISO8859-15@euro
 271.563 -en_US
 271.564 -English (United States)
 271.565 -ISO-8859-15
 271.566 +default locale: ID: en_US, Name: English (United States)
 271.567 +display locale: ID: en_US, Name: English (United States)
 271.568 +format locale: ID: en_US, Name: English (United States)
 271.569 +default charset: ISO-8859-15
 271.570  
 271.571  OS Locale:  en_US.UTF-8
 271.572 -en_US
 271.573 -English (United States)
 271.574 -UTF-8
 271.575 +default locale: ID: en_US, Name: English (United States)
 271.576 +display locale: ID: en_US, Name: English (United States)
 271.577 +format locale: ID: en_US, Name: English (United States)
 271.578 +default charset: UTF-8
 271.579  
 271.580  OS Locale:  es
 271.581 -es_ES
 271.582 -Spanish (Spain)
 271.583 -ISO-8859-1
 271.584 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.585 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.586 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.587 +default charset: ISO-8859-1
 271.588  
 271.589  OS Locale:  es.ISO8859-15
 271.590 -es_ES
 271.591 -Spanish (Spain)
 271.592 -ISO-8859-15
 271.593 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.594 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.595 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.596 +default charset: ISO-8859-15
 271.597  
 271.598  OS Locale:  es.UTF-8
 271.599 -es_ES
 271.600 -Spanish (Spain)
 271.601 -UTF-8
 271.602 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.603 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.604 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.605 +default charset: UTF-8
 271.606  
 271.607  OS Locale:  es_AR
 271.608 -es_AR
 271.609 -Spanish (Argentina)
 271.610 -ISO-8859-1
 271.611 +default locale: ID: es_AR, Name: Spanish (Argentina)
 271.612 +display locale: ID: es_AR, Name: Spanish (Argentina)
 271.613 +format locale: ID: es_AR, Name: Spanish (Argentina)
 271.614 +default charset: ISO-8859-1
 271.615  
 271.616  OS Locale:  es_AR.ISO8859-1
 271.617 -es_AR
 271.618 -Spanish (Argentina)
 271.619 -ISO-8859-1
 271.620 +default locale: ID: es_AR, Name: Spanish (Argentina)
 271.621 +display locale: ID: es_AR, Name: Spanish (Argentina)
 271.622 +format locale: ID: es_AR, Name: Spanish (Argentina)
 271.623 +default charset: ISO-8859-1
 271.624  
 271.625  OS Locale:  es_BO
 271.626 -es_BO
 271.627 -Spanish (Bolivia)
 271.628 -ISO-8859-1
 271.629 +default locale: ID: es_BO, Name: Spanish (Bolivia)
 271.630 +display locale: ID: es_BO, Name: Spanish (Bolivia)
 271.631 +format locale: ID: es_BO, Name: Spanish (Bolivia)
 271.632 +default charset: ISO-8859-1
 271.633  
 271.634  OS Locale:  es_BO.ISO8859-1
 271.635 -es_BO
 271.636 -Spanish (Bolivia)
 271.637 -ISO-8859-1
 271.638 +default locale: ID: es_BO, Name: Spanish (Bolivia)
 271.639 +display locale: ID: es_BO, Name: Spanish (Bolivia)
 271.640 +format locale: ID: es_BO, Name: Spanish (Bolivia)
 271.641 +default charset: ISO-8859-1
 271.642  
 271.643  OS Locale:  es_CL
 271.644 -es_CL
 271.645 -Spanish (Chile)
 271.646 -ISO-8859-1
 271.647 +default locale: ID: es_CL, Name: Spanish (Chile)
 271.648 +display locale: ID: es_CL, Name: Spanish (Chile)
 271.649 +format locale: ID: es_CL, Name: Spanish (Chile)
 271.650 +default charset: ISO-8859-1
 271.651  
 271.652  OS Locale:  es_CL.ISO8859-1
 271.653 -es_CL
 271.654 -Spanish (Chile)
 271.655 -ISO-8859-1
 271.656 +default locale: ID: es_CL, Name: Spanish (Chile)
 271.657 +display locale: ID: es_CL, Name: Spanish (Chile)
 271.658 +format locale: ID: es_CL, Name: Spanish (Chile)
 271.659 +default charset: ISO-8859-1
 271.660  
 271.661  OS Locale:  es_CO
 271.662 -es_CO
 271.663 -Spanish (Colombia)
 271.664 -ISO-8859-1
 271.665 +default locale: ID: es_CO, Name: Spanish (Colombia)
 271.666 +display locale: ID: es_CO, Name: Spanish (Colombia)
 271.667 +format locale: ID: es_CO, Name: Spanish (Colombia)
 271.668 +default charset: ISO-8859-1
 271.669  
 271.670  OS Locale:  es_CO.ISO8859-1
 271.671 -es_CO
 271.672 -Spanish (Colombia)
 271.673 -ISO-8859-1
 271.674 +default locale: ID: es_CO, Name: Spanish (Colombia)
 271.675 +display locale: ID: es_CO, Name: Spanish (Colombia)
 271.676 +format locale: ID: es_CO, Name: Spanish (Colombia)
 271.677 +default charset: ISO-8859-1
 271.678  
 271.679  OS Locale:  es_CR
 271.680 -es_CR
 271.681 -Spanish (Costa Rica)
 271.682 -ISO-8859-1
 271.683 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
 271.684 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
 271.685 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
 271.686 +default charset: ISO-8859-1
 271.687  
 271.688  OS Locale:  es_CR.ISO8859-1
 271.689 -es_CR
 271.690 -Spanish (Costa Rica)
 271.691 -ISO-8859-1
 271.692 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
 271.693 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
 271.694 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
 271.695 +default charset: ISO-8859-1
 271.696  
 271.697  OS Locale:  es_EC
 271.698 -es_EC
 271.699 -Spanish (Ecuador)
 271.700 -ISO-8859-1
 271.701 +default locale: ID: es_EC, Name: Spanish (Ecuador)
 271.702 +display locale: ID: es_EC, Name: Spanish (Ecuador)
 271.703 +format locale: ID: es_EC, Name: Spanish (Ecuador)
 271.704 +default charset: ISO-8859-1
 271.705  
 271.706  OS Locale:  es_EC.ISO8859-1
 271.707 -es_EC
 271.708 -Spanish (Ecuador)
 271.709 -ISO-8859-1
 271.710 +default locale: ID: es_EC, Name: Spanish (Ecuador)
 271.711 +display locale: ID: es_EC, Name: Spanish (Ecuador)
 271.712 +format locale: ID: es_EC, Name: Spanish (Ecuador)
 271.713 +default charset: ISO-8859-1
 271.714  
 271.715  OS Locale:  es_ES
 271.716 -es_ES
 271.717 -Spanish (Spain)
 271.718 -ISO-8859-1
 271.719 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.720 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.721 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.722 +default charset: ISO-8859-1
 271.723  
 271.724  OS Locale:  es_ES.ISO8859-1
 271.725 -es_ES
 271.726 -Spanish (Spain)
 271.727 -ISO-8859-1
 271.728 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.729 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.730 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.731 +default charset: ISO-8859-1
 271.732  
 271.733  OS Locale:  es_ES.ISO8859-15
 271.734 -es_ES
 271.735 -Spanish (Spain)
 271.736 -ISO-8859-15
 271.737 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.738 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.739 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.740 +default charset: ISO-8859-15
 271.741  
 271.742  OS Locale:  es_ES.ISO8859-15@euro
 271.743 -es_ES
 271.744 -Spanish (Spain)
 271.745 -ISO-8859-15
 271.746 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.747 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.748 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.749 +default charset: ISO-8859-15
 271.750  
 271.751  OS Locale:  es_ES.UTF-8
 271.752 -es_ES
 271.753 -Spanish (Spain)
 271.754 -UTF-8
 271.755 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.756 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.757 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.758 +default charset: UTF-8
 271.759  
 271.760  OS Locale:  es_ES.UTF-8@euro
 271.761 -es_ES
 271.762 -Spanish (Spain)
 271.763 -UTF-8
 271.764 +default locale: ID: es_ES, Name: Spanish (Spain)
 271.765 +display locale: ID: es_ES, Name: Spanish (Spain)
 271.766 +format locale: ID: es_ES, Name: Spanish (Spain)
 271.767 +default charset: UTF-8
 271.768  
 271.769  OS Locale:  es_GT
 271.770 -es_GT
 271.771 -Spanish (Guatemala)
 271.772 -ISO-8859-1
 271.773 +default locale: ID: es_GT, Name: Spanish (Guatemala)
 271.774 +display locale: ID: es_GT, Name: Spanish (Guatemala)
 271.775 +format locale: ID: es_GT, Name: Spanish (Guatemala)
 271.776 +default charset: ISO-8859-1
 271.777  
 271.778  OS Locale:  es_GT.ISO8859-1
 271.779 -es_GT
 271.780 -Spanish (Guatemala)
 271.781 -ISO-8859-1
 271.782 +default locale: ID: es_GT, Name: Spanish (Guatemala)
 271.783 +display locale: ID: es_GT, Name: Spanish (Guatemala)
 271.784 +format locale: ID: es_GT, Name: Spanish (Guatemala)
 271.785 +default charset: ISO-8859-1
 271.786  
 271.787  OS Locale:  es_MX
 271.788 -es_MX
 271.789 -Spanish (Mexico)
 271.790 -ISO-8859-1
 271.791 +default locale: ID: es_MX, Name: Spanish (Mexico)
 271.792 +display locale: ID: es_MX, Name: Spanish (Mexico)
 271.793 +format locale: ID: es_MX, Name: Spanish (Mexico)
 271.794 +default charset: ISO-8859-1
 271.795  
 271.796  OS Locale:  es_MX.ISO8859-1
 271.797 -es_MX
 271.798 -Spanish (Mexico)
 271.799 -ISO-8859-1
 271.800 +default locale: ID: es_MX, Name: Spanish (Mexico)
 271.801 +display locale: ID: es_MX, Name: Spanish (Mexico)
 271.802 +format locale: ID: es_MX, Name: Spanish (Mexico)
 271.803 +default charset: ISO-8859-1
 271.804 +
 271.805 +OS Locale:  es_MX.UTF-8
 271.806 +default locale: ID: es_MX, Name: Spanish (Mexico)
 271.807 +display locale: ID: es_MX, Name: Spanish (Mexico)
 271.808 +format locale: ID: es_MX, Name: Spanish (Mexico)
 271.809 +default charset: UTF-8
 271.810  
 271.811  OS Locale:  es_NI
 271.812 -es_NI
 271.813 -Spanish (Nicaragua)
 271.814 -ISO-8859-1
 271.815 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
 271.816 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
 271.817 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
 271.818 +default charset: ISO-8859-1
 271.819  
 271.820  OS Locale:  es_NI.ISO8859-1
 271.821 -es_NI
 271.822 -Spanish (Nicaragua)
 271.823 -ISO-8859-1
 271.824 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
 271.825 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
 271.826 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
 271.827 +default charset: ISO-8859-1
 271.828  
 271.829  OS Locale:  es_PA
 271.830 -es_PA
 271.831 -Spanish (Panama)
 271.832 -ISO-8859-1
 271.833 +default locale: ID: es_PA, Name: Spanish (Panama)
 271.834 +display locale: ID: es_PA, Name: Spanish (Panama)
 271.835 +format locale: ID: es_PA, Name: Spanish (Panama)
 271.836 +default charset: ISO-8859-1
 271.837  
 271.838  OS Locale:  es_PA.ISO8859-1
 271.839 -es_PA
 271.840 -Spanish (Panama)
 271.841 -ISO-8859-1
 271.842 +default locale: ID: es_PA, Name: Spanish (Panama)
 271.843 +display locale: ID: es_PA, Name: Spanish (Panama)
 271.844 +format locale: ID: es_PA, Name: Spanish (Panama)
 271.845 +default charset: ISO-8859-1
 271.846  
 271.847  OS Locale:  es_PE
 271.848 -es_PE
 271.849 -Spanish (Peru)
 271.850 -ISO-8859-1
 271.851 +default locale: ID: es_PE, Name: Spanish (Peru)
 271.852 +display locale: ID: es_PE, Name: Spanish (Peru)
 271.853 +format locale: ID: es_PE, Name: Spanish (Peru)
 271.854 +default charset: ISO-8859-1
 271.855  
 271.856  OS Locale:  es_PE.ISO8859-1
 271.857 -es_PE
 271.858 -Spanish (Peru)
 271.859 -ISO-8859-1
 271.860 +default locale: ID: es_PE, Name: Spanish (Peru)
 271.861 +display locale: ID: es_PE, Name: Spanish (Peru)
 271.862 +format locale: ID: es_PE, Name: Spanish (Peru)
 271.863 +default charset: ISO-8859-1
 271.864  
 271.865  OS Locale:  es_PY
 271.866 -es_PY
 271.867 -Spanish (Paraguay)
 271.868 -ISO-8859-1
 271.869 +default locale: ID: es_PY, Name: Spanish (Paraguay)
 271.870 +display locale: ID: es_PY, Name: Spanish (Paraguay)
 271.871 +format locale: ID: es_PY, Name: Spanish (Paraguay)
 271.872 +default charset: ISO-8859-1
 271.873  
 271.874  OS Locale:  es_PY.ISO8859-1
 271.875 -es_PY
 271.876 -Spanish (Paraguay)
 271.877 -ISO-8859-1
 271.878 +default locale: ID: es_PY, Name: Spanish (Paraguay)
 271.879 +display locale: ID: es_PY, Name: Spanish (Paraguay)
 271.880 +format locale: ID: es_PY, Name: Spanish (Paraguay)
 271.881 +default charset: ISO-8859-1
 271.882  
 271.883  OS Locale:  es_SV
 271.884 -es_SV
 271.885 -Spanish (El Salvador)
 271.886 -ISO-8859-1
 271.887 +default locale: ID: es_SV, Name: Spanish (El Salvador)
 271.888 +display locale: ID: es_SV, Name: Spanish (El Salvador)
 271.889 +format locale: ID: es_SV, Name: Spanish (El Salvador)
 271.890 +default charset: ISO-8859-1
 271.891  
 271.892  OS Locale:  es_SV.ISO8859-1
 271.893 -es_SV
 271.894 -Spanish (El Salvador)
 271.895 -ISO-8859-1
 271.896 +default locale: ID: es_SV, Name: Spanish (El Salvador)
 271.897 +display locale: ID: es_SV, Name: Spanish (El Salvador)
 271.898 +format locale: ID: es_SV, Name: Spanish (El Salvador)
 271.899 +default charset: ISO-8859-1
 271.900  
 271.901  OS Locale:  es_UY
 271.902 -es_UY
 271.903 -Spanish (Uruguay)
 271.904 -ISO-8859-1
 271.905 +default locale: ID: es_UY, Name: Spanish (Uruguay)
 271.906 +display locale: ID: es_UY, Name: Spanish (Uruguay)
 271.907 +format locale: ID: es_UY, Name: Spanish (Uruguay)
 271.908 +default charset: ISO-8859-1
 271.909  
 271.910  OS Locale:  es_UY.ISO8859-1
 271.911 -es_UY
 271.912 -Spanish (Uruguay)
 271.913 -ISO-8859-1
 271.914 +default locale: ID: es_UY, Name: Spanish (Uruguay)
 271.915 +display locale: ID: es_UY, Name: Spanish (Uruguay)
 271.916 +format locale: ID: es_UY, Name: Spanish (Uruguay)
 271.917 +default charset: ISO-8859-1
 271.918  
 271.919  OS Locale:  es_VE
 271.920 -es_VE
 271.921 -Spanish (Venezuela)
 271.922 -ISO-8859-1
 271.923 +default locale: ID: es_VE, Name: Spanish (Venezuela)
 271.924 +display locale: ID: es_VE, Name: Spanish (Venezuela)
 271.925 +format locale: ID: es_VE, Name: Spanish (Venezuela)
 271.926 +default charset: ISO-8859-1
 271.927  
 271.928  OS Locale:  es_VE.ISO8859-1
 271.929 -es_VE
 271.930 -Spanish (Venezuela)
 271.931 -ISO-8859-1
 271.932 +default locale: ID: es_VE, Name: Spanish (Venezuela)
 271.933 +display locale: ID: es_VE, Name: Spanish (Venezuela)
 271.934 +format locale: ID: es_VE, Name: Spanish (Venezuela)
 271.935 +default charset: ISO-8859-1
 271.936  
 271.937  OS Locale:  et
 271.938 -et_EE
 271.939 -Estonian (Estonia)
 271.940 -ISO-8859-15
 271.941 +default locale: ID: et_EE, Name: Estonian (Estonia)
 271.942 +display locale: ID: et_EE, Name: Estonian (Estonia)
 271.943 +format locale: ID: et_EE, Name: Estonian (Estonia)
 271.944 +default charset: ISO-8859-15
 271.945  
 271.946  OS Locale:  et_EE
 271.947 -et_EE
 271.948 -Estonian (Estonia)
 271.949 -ISO-8859-15
 271.950 +default locale: ID: et_EE, Name: Estonian (Estonia)
 271.951 +display locale: ID: et_EE, Name: Estonian (Estonia)
 271.952 +format locale: ID: et_EE, Name: Estonian (Estonia)
 271.953 +default charset: ISO-8859-15
 271.954  
 271.955  OS Locale:  et_EE.ISO8859-15
 271.956 -et_EE
 271.957 -Estonian (Estonia)
 271.958 -ISO-8859-15
 271.959 +default locale: ID: et_EE, Name: Estonian (Estonia)
 271.960 +display locale: ID: et_EE, Name: Estonian (Estonia)
 271.961 +format locale: ID: et_EE, Name: Estonian (Estonia)
 271.962 +default charset: ISO-8859-15
 271.963  
 271.964  OS Locale:  fi
 271.965 -fi_FI
 271.966 -Finnish (Finland)
 271.967 -ISO-8859-1
 271.968 +default locale: ID: fi_FI, Name: Finnish (Finland)
 271.969 +display locale: ID: fi_FI, Name: Finnish (Finland)
 271.970 +format locale: ID: fi_FI, Name: Finnish (Finland)
 271.971 +default charset: ISO-8859-1
 271.972  
 271.973  OS Locale:  fi.ISO8859-15
 271.974 -fi_FI
 271.975 -Finnish (Finland)
 271.976 -ISO-8859-15
 271.977 +default locale: ID: fi_FI, Name: Finnish (Finland)
 271.978 +display locale: ID: fi_FI, Name: Finnish (Finland)
 271.979 +format locale: ID: fi_FI, Name: Finnish (Finland)
 271.980 +default charset: ISO-8859-15
 271.981  
 271.982  OS Locale:  fi_FI
 271.983 -fi_FI
 271.984 -Finnish (Finland)
 271.985 -ISO-8859-1
 271.986 +default locale: ID: fi_FI, Name: Finnish (Finland)
 271.987 +display locale: ID: fi_FI, Name: Finnish (Finland)
 271.988 +format locale: ID: fi_FI, Name: Finnish (Finland)
 271.989 +default charset: ISO-8859-1
 271.990  
 271.991  OS Locale:  fi_FI.ISO8859-1
 271.992 -fi_FI
 271.993 -Finnish (Finland)
 271.994 -ISO-8859-1
 271.995 +default locale: ID: fi_FI, Name: Finnish (Finland)
 271.996 +display locale: ID: fi_FI, Name: Finnish (Finland)
 271.997 +format locale: ID: fi_FI, Name: Finnish (Finland)
 271.998 +default charset: ISO-8859-1
 271.999  
271.1000  OS Locale:  fi_FI.ISO8859-15
271.1001 -fi_FI
271.1002 -Finnish (Finland)
271.1003 -ISO-8859-15
271.1004 +default locale: ID: fi_FI, Name: Finnish (Finland)
271.1005 +display locale: ID: fi_FI, Name: Finnish (Finland)
271.1006 +format locale: ID: fi_FI, Name: Finnish (Finland)
271.1007 +default charset: ISO-8859-15
271.1008  
271.1009  OS Locale:  fi_FI.ISO8859-15@euro
271.1010 -fi_FI
271.1011 -Finnish (Finland)
271.1012 -ISO-8859-15
271.1013 +default locale: ID: fi_FI, Name: Finnish (Finland)
271.1014 +display locale: ID: fi_FI, Name: Finnish (Finland)
271.1015 +format locale: ID: fi_FI, Name: Finnish (Finland)
271.1016 +default charset: ISO-8859-15
271.1017  
271.1018  OS Locale:  fi_FI.UTF-8
271.1019 -fi_FI
271.1020 -Finnish (Finland)
271.1021 -UTF-8
271.1022 +default locale: ID: fi_FI, Name: Finnish (Finland)
271.1023 +display locale: ID: fi_FI, Name: Finnish (Finland)
271.1024 +format locale: ID: fi_FI, Name: Finnish (Finland)
271.1025 +default charset: UTF-8
271.1026  
271.1027  OS Locale:  fr
271.1028 -fr_FR
271.1029 -French (France)
271.1030 -ISO-8859-1
271.1031 +default locale: ID: fr_FR, Name: French (France)
271.1032 +display locale: ID: fr_FR, Name: French (France)
271.1033 +format locale: ID: fr_FR, Name: French (France)
271.1034 +default charset: ISO-8859-1
271.1035  
271.1036  OS Locale:  fr.ISO8859-15
271.1037 -fr_FR
271.1038 -French (France)
271.1039 -ISO-8859-15
271.1040 +default locale: ID: fr_FR, Name: French (France)
271.1041 +display locale: ID: fr_FR, Name: French (France)
271.1042 +format locale: ID: fr_FR, Name: French (France)
271.1043 +default charset: ISO-8859-15
271.1044  
271.1045  OS Locale:  fr.UTF-8
271.1046 -fr_FR
271.1047 -French (France)
271.1048 -UTF-8
271.1049 +default locale: ID: fr_FR, Name: French (France)
271.1050 +display locale: ID: fr_FR, Name: French (France)
271.1051 +format locale: ID: fr_FR, Name: French (France)
271.1052 +default charset: UTF-8
271.1053  
271.1054  OS Locale:  fr_BE
271.1055 -fr_BE
271.1056 -French (Belgium)
271.1057 -ISO-8859-1
271.1058 +default locale: ID: fr_BE, Name: French (Belgium)
271.1059 +display locale: ID: fr_BE, Name: French (Belgium)
271.1060 +format locale: ID: fr_BE, Name: French (Belgium)
271.1061 +default charset: ISO-8859-1
271.1062  
271.1063  OS Locale:  fr_BE.ISO8859-1
271.1064 -fr_BE
271.1065 -French (Belgium)
271.1066 -ISO-8859-1
271.1067 +default locale: ID: fr_BE, Name: French (Belgium)
271.1068 +display locale: ID: fr_BE, Name: French (Belgium)
271.1069 +format locale: ID: fr_BE, Name: French (Belgium)
271.1070 +default charset: ISO-8859-1
271.1071  
271.1072  OS Locale:  fr_BE.ISO8859-15
271.1073 -fr_BE
271.1074 -French (Belgium)
271.1075 -ISO-8859-15
271.1076 +default locale: ID: fr_BE, Name: French (Belgium)
271.1077 +display locale: ID: fr_BE, Name: French (Belgium)
271.1078 +format locale: ID: fr_BE, Name: French (Belgium)
271.1079 +default charset: ISO-8859-15
271.1080  
271.1081  OS Locale:  fr_BE.ISO8859-15@euro
271.1082 -fr_BE
271.1083 -French (Belgium)
271.1084 -ISO-8859-15
271.1085 +default locale: ID: fr_BE, Name: French (Belgium)
271.1086 +display locale: ID: fr_BE, Name: French (Belgium)
271.1087 +format locale: ID: fr_BE, Name: French (Belgium)
271.1088 +default charset: ISO-8859-15
271.1089  
271.1090  OS Locale:  fr_BE.UTF-8
271.1091 -fr_BE
271.1092 -French (Belgium)
271.1093 -UTF-8
271.1094 +default locale: ID: fr_BE, Name: French (Belgium)
271.1095 +display locale: ID: fr_BE, Name: French (Belgium)
271.1096 +format locale: ID: fr_BE, Name: French (Belgium)
271.1097 +default charset: UTF-8
271.1098  
271.1099  OS Locale:  fr_BE.UTF-8@euro
271.1100 -fr_BE
271.1101 -French (Belgium)
271.1102 -UTF-8
271.1103 +default locale: ID: fr_BE, Name: French (Belgium)
271.1104 +display locale: ID: fr_BE, Name: French (Belgium)
271.1105 +format locale: ID: fr_BE, Name: French (Belgium)
271.1106 +default charset: UTF-8
271.1107  
271.1108  OS Locale:  fr_CA
271.1109 -fr_CA
271.1110 -French (Canada)
271.1111 -ISO-8859-1
271.1112 +default locale: ID: fr_CA, Name: French (Canada)
271.1113 +display locale: ID: fr_CA, Name: French (Canada)
271.1114 +format locale: ID: fr_CA, Name: French (Canada)
271.1115 +default charset: ISO-8859-1
271.1116  
271.1117  OS Locale:  fr_CA.ISO8859-1
271.1118 -fr_CA
271.1119 -French (Canada)
271.1120 -ISO-8859-1
271.1121 +default locale: ID: fr_CA, Name: French (Canada)
271.1122 +display locale: ID: fr_CA, Name: French (Canada)
271.1123 +format locale: ID: fr_CA, Name: French (Canada)
271.1124 +default charset: ISO-8859-1
271.1125 +
271.1126 +OS Locale:  fr_CA.UTF-8
271.1127 +default locale: ID: fr_CA, Name: French (Canada)
271.1128 +display locale: ID: fr_CA, Name: French (Canada)
271.1129 +format locale: ID: fr_CA, Name: French (Canada)
271.1130 +default charset: UTF-8
271.1131  
271.1132  OS Locale:  fr_CH
271.1133 -fr_CH
271.1134 -French (Switzerland)
271.1135 -ISO-8859-1
271.1136 +default locale: ID: fr_CH, Name: French (Switzerland)
271.1137 +display locale: ID: fr_CH, Name: French (Switzerland)
271.1138 +format locale: ID: fr_CH, Name: French (Switzerland)
271.1139 +default charset: ISO-8859-1
271.1140  
271.1141  OS Locale:  fr_CH.ISO8859-1
271.1142 -fr_CH
271.1143 -French (Switzerland)
271.1144 -ISO-8859-1
271.1145 +default locale: ID: fr_CH, Name: French (Switzerland)
271.1146 +display locale: ID: fr_CH, Name: French (Switzerland)
271.1147 +format locale: ID: fr_CH, Name: French (Switzerland)
271.1148 +default charset: ISO-8859-1
271.1149  
271.1150  OS Locale:  fr_FR
271.1151 -fr_FR
271.1152 -French (France)
271.1153 -ISO-8859-1
271.1154 +default locale: ID: fr_FR, Name: French (France)
271.1155 +display locale: ID: fr_FR, Name: French (France)
271.1156 +format locale: ID: fr_FR, Name: French (France)
271.1157 +default charset: ISO-8859-1
271.1158  
271.1159  OS Locale:  fr_FR.ISO8859-1
271.1160 -fr_FR
271.1161 -French (France)
271.1162 -ISO-8859-1
271.1163 +default locale: ID: fr_FR, Name: French (France)
271.1164 +display locale: ID: fr_FR, Name: French (France)
271.1165 +format locale: ID: fr_FR, Name: French (France)
271.1166 +default charset: ISO-8859-1
271.1167  
271.1168  OS Locale:  fr_FR.ISO8859-15
271.1169 -fr_FR
271.1170 -French (France)
271.1171 -ISO-8859-15
271.1172 +default locale: ID: fr_FR, Name: French (France)
271.1173 +display locale: ID: fr_FR, Name: French (France)
271.1174 +format locale: ID: fr_FR, Name: French (France)
271.1175 +default charset: ISO-8859-15
271.1176  
271.1177  OS Locale:  fr_FR.ISO8859-15@euro
271.1178 -fr_FR
271.1179 -French (France)
271.1180 -ISO-8859-15
271.1181 +default locale: ID: fr_FR, Name: French (France)
271.1182 +display locale: ID: fr_FR, Name: French (France)
271.1183 +format locale: ID: fr_FR, Name: French (France)
271.1184 +default charset: ISO-8859-15
271.1185  
271.1186  OS Locale:  fr_FR.UTF-8
271.1187 -fr_FR
271.1188 -French (France)
271.1189 -UTF-8
271.1190 +default locale: ID: fr_FR, Name: French (France)
271.1191 +display locale: ID: fr_FR, Name: French (France)
271.1192 +format locale: ID: fr_FR, Name: French (France)
271.1193 +default charset: UTF-8
271.1194  
271.1195  OS Locale:  fr_FR.UTF-8@euro
271.1196 -fr_FR
271.1197 -French (France)
271.1198 -UTF-8
271.1199 -
271.1200 -OS Locale:  geo
271.1201 -en
271.1202 -English
271.1203 -ISO-8859-1
271.1204 +default locale: ID: fr_FR, Name: French (France)
271.1205 +display locale: ID: fr_FR, Name: French (France)
271.1206 +format locale: ID: fr_FR, Name: French (France)
271.1207 +default charset: UTF-8
271.1208  
271.1209  OS Locale:  he
271.1210 -iw_IL
271.1211 -Hebrew (Israel)
271.1212 -ISO-8859-8
271.1213 +default locale: ID: iw_IL, Name: Hebrew (Israel)
271.1214 +display locale: ID: iw_IL, Name: Hebrew (Israel)
271.1215 +format locale: ID: iw_IL, Name: Hebrew (Israel)
271.1216 +default charset: ISO-8859-8
271.1217  
271.1218  OS Locale:  he_IL
271.1219 -iw_IL
271.1220 -Hebrew (Israel)
271.1221 -ISO-8859-8
271.1222 +default locale: ID: iw_IL, Name: Hebrew (Israel)
271.1223 +display locale: ID: iw_IL, Name: Hebrew (Israel)
271.1224 +format locale: ID: iw_IL, Name: Hebrew (Israel)
271.1225 +default charset: ISO-8859-8
271.1226  
271.1227  OS Locale:  he_IL.UTF-8
271.1228 -iw_IL
271.1229 -Hebrew (Israel)
271.1230 -UTF-8
271.1231 +default locale: ID: iw_IL, Name: Hebrew (Israel)
271.1232 +display locale: ID: iw_IL, Name: Hebrew (Israel)
271.1233 +format locale: ID: iw_IL, Name: Hebrew (Israel)
271.1234 +default charset: UTF-8
271.1235  
271.1236  OS Locale:  hi_IN.UTF-8
271.1237 -hi_IN
271.1238 -Hindi (India)
271.1239 -UTF-8
271.1240 +default locale: ID: hi_IN, Name: Hindi (India)
271.1241 +display locale: ID: hi_IN, Name: Hindi (India)
271.1242 +format locale: ID: hi_IN, Name: Hindi (India)
271.1243 +default charset: UTF-8
271.1244  
271.1245  OS Locale:  hr_HR
271.1246 -hr_HR
271.1247 -Croatian (Croatia)
271.1248 -ISO-8859-2
271.1249 +default locale: ID: hr_HR, Name: Croatian (Croatia)
271.1250 +display locale: ID: hr_HR, Name: Croatian (Croatia)
271.1251 +format locale: ID: hr_HR, Name: Croatian (Croatia)
271.1252 +default charset: ISO-8859-2
271.1253  
271.1254  OS Locale:  hr_HR.ISO8859-2
271.1255 -hr_HR
271.1256 -Croatian (Croatia)
271.1257 -ISO-8859-2
271.1258 +default locale: ID: hr_HR, Name: Croatian (Croatia)
271.1259 +display locale: ID: hr_HR, Name: Croatian (Croatia)
271.1260 +format locale: ID: hr_HR, Name: Croatian (Croatia)
271.1261 +default charset: ISO-8859-2
271.1262  
271.1263  OS Locale:  hu
271.1264 -hu_HU
271.1265 -Hungarian (Hungary)
271.1266 -ISO-8859-2
271.1267 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1268 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1269 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1270 +default charset: ISO-8859-2
271.1271  
271.1272  OS Locale:  hu_HU
271.1273 -hu_HU
271.1274 -Hungarian (Hungary)
271.1275 -ISO-8859-2
271.1276 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1277 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1278 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1279 +default charset: ISO-8859-2
271.1280  
271.1281  OS Locale:  hu_HU.ISO8859-2
271.1282 -hu_HU
271.1283 -Hungarian (Hungary)
271.1284 -ISO-8859-2
271.1285 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1286 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1287 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1288 +default charset: ISO-8859-2
271.1289  
271.1290  OS Locale:  hu_HU.UTF-8
271.1291 -hu_HU
271.1292 -Hungarian (Hungary)
271.1293 -UTF-8
271.1294 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1295 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1296 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
271.1297 +default charset: UTF-8
271.1298  
271.1299  OS Locale:  is_IS
271.1300 -is_IS
271.1301 -Icelandic (Iceland)
271.1302 -ISO-8859-1
271.1303 +default locale: ID: is_IS, Name: Icelandic (Iceland)
271.1304 +display locale: ID: is_IS, Name: Icelandic (Iceland)
271.1305 +format locale: ID: is_IS, Name: Icelandic (Iceland)
271.1306 +default charset: ISO-8859-1
271.1307  
271.1308  OS Locale:  is_IS.ISO8859-1
271.1309 -is_IS
271.1310 -Icelandic (Iceland)
271.1311 -ISO-8859-1
271.1312 +default locale: ID: is_IS, Name: Icelandic (Iceland)
271.1313 +display locale: ID: is_IS, Name: Icelandic (Iceland)
271.1314 +format locale: ID: is_IS, Name: Icelandic (Iceland)
271.1315 +default charset: ISO-8859-1
271.1316  
271.1317  OS Locale:  iso_8859_1
271.1318 -en_8859_1
271.1319 -English (8859_1)
271.1320 -ISO-8859-1
271.1321 -
271.1322 -OS Locale:  iso_8859_13
271.1323 -en
271.1324 -English
271.1325 -ISO-8859-1
271.1326 -
271.1327 -OS Locale:  iso_8859_15
271.1328 -en
271.1329 -English
271.1330 -ISO-8859-1
271.1331 -
271.1332 -OS Locale:  iso_8859_2
271.1333 -en
271.1334 -English
271.1335 -ISO-8859-1
271.1336 -
271.1337 -OS Locale:  iso_8859_5
271.1338 -en
271.1339 -English
271.1340 -ISO-8859-1
271.1341 -
271.1342 -OS Locale:  iso_8859_7
271.1343 -en
271.1344 -English
271.1345 -ISO-8859-1
271.1346 -
271.1347 -OS Locale:  iso_8859_9
271.1348 -en
271.1349 -English
271.1350 -ISO-8859-1
271.1351 +default locale: ID: en, Name: English
271.1352 +display locale: ID: en, Name: English
271.1353 +format locale: ID: en, Name: English
271.1354 +default charset: US-ASCII
271.1355  
271.1356  OS Locale:  it
271.1357 -it_IT
271.1358 -Italian (Italy)
271.1359 -ISO-8859-1
271.1360 +default locale: ID: it_IT, Name: Italian (Italy)
271.1361 +display locale: ID: it_IT, Name: Italian (Italy)
271.1362 +format locale: ID: it_IT, Name: Italian (Italy)
271.1363 +default charset: ISO-8859-1
271.1364  
271.1365  OS Locale:  it.ISO8859-15
271.1366 -it_IT
271.1367 -Italian (Italy)
271.1368 -ISO-8859-15
271.1369 +default locale: ID: it_IT, Name: Italian (Italy)
271.1370 +display locale: ID: it_IT, Name: Italian (Italy)
271.1371 +format locale: ID: it_IT, Name: Italian (Italy)
271.1372 +default charset: ISO-8859-15
271.1373  
271.1374  OS Locale:  it.UTF-8
271.1375 -it_IT
271.1376 -Italian (Italy)
271.1377 -UTF-8
271.1378 +default locale: ID: it_IT, Name: Italian (Italy)
271.1379 +display locale: ID: it_IT, Name: Italian (Italy)
271.1380 +format locale: ID: it_IT, Name: Italian (Italy)
271.1381 +default charset: UTF-8
271.1382  
271.1383  OS Locale:  it_IT
271.1384 -it_IT
271.1385 -Italian (Italy)
271.1386 -ISO-8859-1
271.1387 +default locale: ID: it_IT, Name: Italian (Italy)
271.1388 +display locale: ID: it_IT, Name: Italian (Italy)
271.1389 +format locale: ID: it_IT, Name: Italian (Italy)
271.1390 +default charset: ISO-8859-1
271.1391  
271.1392  OS Locale:  it_IT.ISO8859-1
271.1393 -it_IT
271.1394 -Italian (Italy)
271.1395 -ISO-8859-1
271.1396 +default locale: ID: it_IT, Name: Italian (Italy)
271.1397 +display locale: ID: it_IT, Name: Italian (Italy)
271.1398 +format locale: ID: it_IT, Name: Italian (Italy)
271.1399 +default charset: ISO-8859-1
271.1400  
271.1401  OS Locale:  it_IT.ISO8859-15
271.1402 -it_IT
271.1403 -Italian (Italy)
271.1404 -ISO-8859-15
271.1405 +default locale: ID: it_IT, Name: Italian (Italy)
271.1406 +display locale: ID: it_IT, Name: Italian (Italy)
271.1407 +format locale: ID: it_IT, Name: Italian (Italy)
271.1408 +default charset: ISO-8859-15
271.1409  
271.1410  OS Locale:  it_IT.ISO8859-15@euro
271.1411 -it_IT
271.1412 -Italian (Italy)
271.1413 -ISO-8859-15
271.1414 +default locale: ID: it_IT, Name: Italian (Italy)
271.1415 +display locale: ID: it_IT, Name: Italian (Italy)
271.1416 +format locale: ID: it_IT, Name: Italian (Italy)
271.1417 +default charset: ISO-8859-15
271.1418  
271.1419  OS Locale:  it_IT.UTF-8
271.1420 -it_IT
271.1421 -Italian (Italy)
271.1422 -UTF-8
271.1423 +default locale: ID: it_IT, Name: Italian (Italy)
271.1424 +display locale: ID: it_IT, Name: Italian (Italy)
271.1425 +format locale: ID: it_IT, Name: Italian (Italy)
271.1426 +default charset: UTF-8
271.1427  
271.1428  OS Locale:  it_IT.UTF-8@euro
271.1429 -it_IT
271.1430 -Italian (Italy)
271.1431 -UTF-8
271.1432 +default locale: ID: it_IT, Name: Italian (Italy)
271.1433 +display locale: ID: it_IT, Name: Italian (Italy)
271.1434 +format locale: ID: it_IT, Name: Italian (Italy)
271.1435 +default charset: UTF-8
271.1436  
271.1437  OS Locale:  ja
271.1438 -ja_JP
271.1439 -Japanese (Japan)
271.1440 -x-eucJP-Open
271.1441 +default locale: ID: ja_JP, Name: Japanese (Japan)
271.1442 +display locale: ID: ja_JP, Name: Japanese (Japan)
271.1443 +format locale: ID: ja_JP, Name: Japanese (Japan)
271.1444 +default charset: x-eucJP-Open
271.1445  
271.1446  OS Locale:  ja_JP.PCK
271.1447 -ja_JP
271.1448 -Japanese (Japan)
271.1449 -x-PCK
271.1450 +default locale: ID: ja_JP, Name: Japanese (Japan)
271.1451 +display locale: ID: ja_JP, Name: Japanese (Japan)
271.1452 +format locale: ID: ja_JP, Name: Japanese (Japan)
271.1453 +default charset: x-PCK
271.1454  
271.1455  OS Locale:  ja_JP.UTF-8
271.1456 -ja_JP
271.1457 -Japanese (Japan)
271.1458 -UTF-8
271.1459 +default locale: ID: ja_JP, Name: Japanese (Japan)
271.1460 +display locale: ID: ja_JP, Name: Japanese (Japan)
271.1461 +format locale: ID: ja_JP, Name: Japanese (Japan)
271.1462 +default charset: UTF-8
271.1463  
271.1464  OS Locale:  ja_JP.eucJP
271.1465 -ja_JP
271.1466 -Japanese (Japan)
271.1467 -x-eucJP-Open
271.1468 +default locale: ID: ja_JP, Name: Japanese (Japan)
271.1469 +display locale: ID: ja_JP, Name: Japanese (Japan)
271.1470 +format locale: ID: ja_JP, Name: Japanese (Japan)
271.1471 +default charset: x-eucJP-Open
271.1472  
271.1473  OS Locale:  ko
271.1474 -ko_KR
271.1475 -Korean (South Korea)
271.1476 -EUC-KR
271.1477 +default locale: ID: ko_KR, Name: Korean (South Korea)
271.1478 +display locale: ID: ko_KR, Name: Korean (South Korea)
271.1479 +format locale: ID: ko_KR, Name: Korean (South Korea)
271.1480 +default charset: EUC-KR
271.1481  
271.1482  OS Locale:  ko.UTF-8
271.1483 -ko_KR
271.1484 -Korean (South Korea)
271.1485 -UTF-8
271.1486 +default locale: ID: ko_KR, Name: Korean (South Korea)
271.1487 +display locale: ID: ko_KR, Name: Korean (South Korea)
271.1488 +format locale: ID: ko_KR, Name: Korean (South Korea)
271.1489 +default charset: UTF-8
271.1490  
271.1491  OS Locale:  ko_KR.EUC
271.1492 -ko_KR
271.1493 -Korean (South Korea)
271.1494 -EUC-KR
271.1495 +default locale: ID: ko_KR, Name: Korean (South Korea)
271.1496 +display locale: ID: ko_KR, Name: Korean (South Korea)
271.1497 +format locale: ID: ko_KR, Name: Korean (South Korea)
271.1498 +default charset: EUC-KR
271.1499  
271.1500  OS Locale:  ko_KR.EUC@dict
271.1501 -ko_KR
271.1502 -Korean (South Korea)
271.1503 -EUC-KR
271.1504 +default locale: ID: ko_KR, Name: Korean (South Korea)
271.1505 +display locale: ID: ko_KR, Name: Korean (South Korea)
271.1506 +format locale: ID: ko_KR, Name: Korean (South Korea)
271.1507 +default charset: EUC-KR
271.1508  
271.1509  OS Locale:  ko_KR.UTF-8
271.1510 -ko_KR
271.1511 -Korean (South Korea)
271.1512 -UTF-8
271.1513 +default locale: ID: ko_KR, Name: Korean (South Korea)
271.1514 +display locale: ID: ko_KR, Name: Korean (South Korea)
271.1515 +format locale: ID: ko_KR, Name: Korean (South Korea)
271.1516 +default charset: UTF-8
271.1517  
271.1518  OS Locale:  ko_KR.UTF-8@dict
271.1519 -ko_KR
271.1520 -Korean (South Korea)
271.1521 -UTF-8
271.1522 -
271.1523 -OS Locale:  lcttab
271.1524 -en
271.1525 -English
271.1526 -ISO-8859-1
271.1527 +default locale: ID: ko_KR, Name: Korean (South Korea)
271.1528 +display locale: ID: ko_KR, Name: Korean (South Korea)
271.1529 +format locale: ID: ko_KR, Name: Korean (South Korea)
271.1530 +default charset: UTF-8
271.1531  
271.1532  OS Locale:  lt
271.1533 -lt_LT
271.1534 -Lithuanian (Lithuania)
271.1535 -ISO-8859-13
271.1536 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1537 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1538 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1539 +default charset: ISO-8859-13
271.1540  
271.1541  OS Locale:  lt_LT
271.1542 -lt_LT
271.1543 -Lithuanian (Lithuania)
271.1544 -ISO-8859-13
271.1545 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1546 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1547 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1548 +default charset: ISO-8859-13
271.1549  
271.1550  OS Locale:  lt_LT.ISO8859-13
271.1551 -lt_LT
271.1552 -Lithuanian (Lithuania)
271.1553 -ISO-8859-13
271.1554 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1555 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1556 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
271.1557 +default charset: ISO-8859-13
271.1558  
271.1559  OS Locale:  lv
271.1560 -lv_LV
271.1561 -Latvian (Latvia)
271.1562 -ISO-8859-13
271.1563 +default locale: ID: lv_LV, Name: Latvian (Latvia)
271.1564 +display locale: ID: lv_LV, Name: Latvian (Latvia)
271.1565 +format locale: ID: lv_LV, Name: Latvian (Latvia)
271.1566 +default charset: ISO-8859-13
271.1567  
271.1568  OS Locale:  lv_LV
271.1569 -lv_LV
271.1570 -Latvian (Latvia)
271.1571 -ISO-8859-13
271.1572 +default locale: ID: lv_LV, Name: Latvian (Latvia)
271.1573 +display locale: ID: lv_LV, Name: Latvian (Latvia)
271.1574 +format locale: ID: lv_LV, Name: Latvian (Latvia)
271.1575 +default charset: ISO-8859-13
271.1576  
271.1577  OS Locale:  lv_LV.ISO8859-13
271.1578 -lv_LV
271.1579 -Latvian (Latvia)
271.1580 -ISO-8859-13
271.1581 +default locale: ID: lv_LV, Name: Latvian (Latvia)
271.1582 +display locale: ID: lv_LV, Name: Latvian (Latvia)
271.1583 +format locale: ID: lv_LV, Name: Latvian (Latvia)
271.1584 +default charset: ISO-8859-13
271.1585  
271.1586  OS Locale:  mk_MK
271.1587 -mk_MK
271.1588 -Macedonian (Macedonia)
271.1589 -ISO-8859-5
271.1590 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
271.1591 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
271.1592 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
271.1593 +default charset: ISO-8859-5
271.1594  
271.1595  OS Locale:  mk_MK.ISO8859-5
271.1596 -mk_MK
271.1597 -Macedonian (Macedonia)
271.1598 -ISO-8859-5
271.1599 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
271.1600 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
271.1601 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
271.1602 +default charset: ISO-8859-5
271.1603  
271.1604  OS Locale:  nl
271.1605 -nl_NL
271.1606 -Dutch (Netherlands)
271.1607 -ISO-8859-1
271.1608 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1609 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1610 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1611 +default charset: ISO-8859-1
271.1612  
271.1613  OS Locale:  nl.ISO8859-15
271.1614 -nl_NL
271.1615 -Dutch (Netherlands)
271.1616 -ISO-8859-15
271.1617 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1618 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1619 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1620 +default charset: ISO-8859-15
271.1621  
271.1622  OS Locale:  nl_BE
271.1623 -nl_BE
271.1624 -Dutch (Belgium)
271.1625 -ISO-8859-1
271.1626 +default locale: ID: nl_BE, Name: Dutch (Belgium)
271.1627 +display locale: ID: nl_BE, Name: Dutch (Belgium)
271.1628 +format locale: ID: nl_BE, Name: Dutch (Belgium)
271.1629 +default charset: ISO-8859-1
271.1630  
271.1631  OS Locale:  nl_BE.ISO8859-1
271.1632 -nl_BE
271.1633 -Dutch (Belgium)
271.1634 -ISO-8859-1
271.1635 +default locale: ID: nl_BE, Name: Dutch (Belgium)
271.1636 +display locale: ID: nl_BE, Name: Dutch (Belgium)
271.1637 +format locale: ID: nl_BE, Name: Dutch (Belgium)
271.1638 +default charset: ISO-8859-1
271.1639  
271.1640  OS Locale:  nl_BE.ISO8859-15
271.1641 -nl_BE
271.1642 -Dutch (Belgium)
271.1643 -ISO-8859-15
271.1644 +default locale: ID: nl_BE, Name: Dutch (Belgium)
271.1645 +display locale: ID: nl_BE, Name: Dutch (Belgium)
271.1646 +format locale: ID: nl_BE, Name: Dutch (Belgium)
271.1647 +default charset: ISO-8859-15
271.1648  
271.1649  OS Locale:  nl_BE.ISO8859-15@euro
271.1650 -nl_BE
271.1651 -Dutch (Belgium)
271.1652 -ISO-8859-15
271.1653 +default locale: ID: nl_BE, Name: Dutch (Belgium)
271.1654 +display locale: ID: nl_BE, Name: Dutch (Belgium)
271.1655 +format locale: ID: nl_BE, Name: Dutch (Belgium)
271.1656 +default charset: ISO-8859-15
271.1657  
271.1658  OS Locale:  nl_NL
271.1659 -nl_NL
271.1660 -Dutch (Netherlands)
271.1661 -ISO-8859-1
271.1662 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1663 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1664 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1665 +default charset: ISO-8859-1
271.1666  
271.1667  OS Locale:  nl_NL.ISO8859-1
271.1668 -nl_NL
271.1669 -Dutch (Netherlands)
271.1670 -ISO-8859-1
271.1671 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1672 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1673 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1674 +default charset: ISO-8859-1
271.1675  
271.1676  OS Locale:  nl_NL.ISO8859-15
271.1677 -nl_NL
271.1678 -Dutch (Netherlands)
271.1679 -ISO-8859-15
271.1680 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1681 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1682 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1683 +default charset: ISO-8859-15
271.1684  
271.1685  OS Locale:  nl_NL.ISO8859-15@euro
271.1686 -nl_NL
271.1687 -Dutch (Netherlands)
271.1688 -ISO-8859-15
271.1689 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1690 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1691 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
271.1692 +default charset: ISO-8859-15
271.1693  
271.1694  OS Locale:  no
271.1695 -no_NO
271.1696 -Norwegian (Norway)
271.1697 -ISO-8859-1
271.1698 +default locale: ID: no_NO, Name: Norwegian (Norway)
271.1699 +display locale: ID: no_NO, Name: Norwegian (Norway)
271.1700 +format locale: ID: no_NO, Name: Norwegian (Norway)
271.1701 +default charset: ISO-8859-1
271.1702  
271.1703  OS Locale:  no_NO
271.1704 -no_NO
271.1705 -Norwegian (Norway)
271.1706 -ISO-8859-1
271.1707 +default locale: ID: no_NO, Name: Norwegian (Norway)
271.1708 +display locale: ID: no_NO, Name: Norwegian (Norway)
271.1709 +format locale: ID: no_NO, Name: Norwegian (Norway)
271.1710 +default charset: ISO-8859-1
271.1711  
271.1712  OS Locale:  no_NO.ISO8859-1@bokmal
271.1713 -no_NO
271.1714 -Norwegian (Norway)
271.1715 -ISO-8859-1
271.1716 +default locale: ID: no_NO, Name: Norwegian (Norway)
271.1717 +display locale: ID: no_NO, Name: Norwegian (Norway)
271.1718 +format locale: ID: no_NO, Name: Norwegian (Norway)
271.1719 +default charset: ISO-8859-1
271.1720  
271.1721  OS Locale:  no_NO.ISO8859-1@nynorsk
271.1722 -no_NO_NY
271.1723 -Norwegian (Norway,Nynorsk)
271.1724 -ISO-8859-1
271.1725 +default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
271.1726 +display locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
271.1727 +format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
271.1728 +default charset: ISO-8859-1
271.1729  
271.1730  OS Locale:  no_NY
271.1731 -no_NY
271.1732 -Norwegian (NY)
271.1733 -ISO-8859-1
271.1734 +default locale: ID: no_, Name: Norwegian ()
271.1735 +display locale: ID: no_, Name: Norwegian ()
271.1736 +format locale: ID: no_, Name: Norwegian ()
271.1737 +default charset: ISO-8859-1
271.1738  
271.1739  OS Locale:  nr
271.1740 -nr
271.1741 -South Ndebele
271.1742 -ISO-8859-2
271.1743 +default locale: ID: nr, Name: South Ndebele
271.1744 +display locale: ID: nr, Name: South Ndebele
271.1745 +format locale: ID: nr, Name: South Ndebele
271.1746 +default charset: ISO-8859-2
271.1747  
271.1748  OS Locale:  pl
271.1749 -pl_PL
271.1750 -Polish (Poland)
271.1751 -ISO-8859-2
271.1752 +default locale: ID: pl_PL, Name: Polish (Poland)
271.1753 +display locale: ID: pl_PL, Name: Polish (Poland)
271.1754 +format locale: ID: pl_PL, Name: Polish (Poland)
271.1755 +default charset: ISO-8859-2
271.1756  
271.1757  OS Locale:  pl.UTF-8
271.1758 -pl_PL
271.1759 -Polish (Poland)
271.1760 -UTF-8
271.1761 +default locale: ID: pl_PL, Name: Polish (Poland)
271.1762 +display locale: ID: pl_PL, Name: Polish (Poland)
271.1763 +format locale: ID: pl_PL, Name: Polish (Poland)
271.1764 +default charset: UTF-8
271.1765  
271.1766  OS Locale:  pl_PL
271.1767 -pl_PL
271.1768 -Polish (Poland)
271.1769 -ISO-8859-2
271.1770 +default locale: ID: pl_PL, Name: Polish (Poland)
271.1771 +display locale: ID: pl_PL, Name: Polish (Poland)
271.1772 +format locale: ID: pl_PL, Name: Polish (Poland)
271.1773 +default charset: ISO-8859-2
271.1774  
271.1775  OS Locale:  pl_PL.ISO8859-2
271.1776 -pl_PL
271.1777 -Polish (Poland)
271.1778 -ISO-8859-2
271.1779 +default locale: ID: pl_PL, Name: Polish (Poland)
271.1780 +display locale: ID: pl_PL, Name: Polish (Poland)
271.1781 +format locale: ID: pl_PL, Name: Polish (Poland)
271.1782 +default charset: ISO-8859-2
271.1783  
271.1784  OS Locale:  pl_PL.UTF-8
271.1785 -pl_PL
271.1786 -Polish (Poland)
271.1787 -UTF-8
271.1788 +default locale: ID: pl_PL, Name: Polish (Poland)
271.1789 +display locale: ID: pl_PL, Name: Polish (Poland)
271.1790 +format locale: ID: pl_PL, Name: Polish (Poland)
271.1791 +default charset: UTF-8
271.1792  
271.1793  OS Locale:  pt
271.1794 -pt_PT
271.1795 -Portuguese (Portugal)
271.1796 -ISO-8859-1
271.1797 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1798 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1799 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1800 +default charset: ISO-8859-1
271.1801  
271.1802  OS Locale:  pt.ISO8859-15
271.1803 -pt_PT
271.1804 -Portuguese (Portugal)
271.1805 -ISO-8859-15
271.1806 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1807 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1808 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1809 +default charset: ISO-8859-15
271.1810  
271.1811  OS Locale:  pt_BR
271.1812 -pt_BR
271.1813 -Portuguese (Brazil)
271.1814 -ISO-8859-1
271.1815 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1816 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1817 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1818 +default charset: ISO-8859-1
271.1819  
271.1820  OS Locale:  pt_BR.ISO8859-1
271.1821 -pt_BR
271.1822 -Portuguese (Brazil)
271.1823 -ISO-8859-1
271.1824 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1825 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1826 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1827 +default charset: ISO-8859-1
271.1828  
271.1829  OS Locale:  pt_BR.UTF-8
271.1830 -pt_BR
271.1831 -Portuguese (Brazil)
271.1832 -UTF-8
271.1833 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1834 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1835 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
271.1836 +default charset: UTF-8
271.1837  
271.1838  OS Locale:  pt_PT
271.1839 -pt_PT
271.1840 -Portuguese (Portugal)
271.1841 -ISO-8859-1
271.1842 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1843 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1844 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1845 +default charset: ISO-8859-1
271.1846  
271.1847  OS Locale:  pt_PT.ISO8859-1
271.1848 -pt_PT
271.1849 -Portuguese (Portugal)
271.1850 -ISO-8859-1
271.1851 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1852 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1853 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1854 +default charset: ISO-8859-1
271.1855  
271.1856  OS Locale:  pt_PT.ISO8859-15
271.1857 -pt_PT
271.1858 -Portuguese (Portugal)
271.1859 -ISO-8859-15
271.1860 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1861 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1862 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1863 +default charset: ISO-8859-15
271.1864  
271.1865  OS Locale:  pt_PT.ISO8859-15@euro
271.1866 -pt_PT
271.1867 -Portuguese (Portugal)
271.1868 -ISO-8859-15
271.1869 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1870 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1871 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
271.1872 +default charset: ISO-8859-15
271.1873  
271.1874  OS Locale:  ro_RO
271.1875 -ro_RO
271.1876 -Romanian (Romania)
271.1877 -ISO-8859-2
271.1878 +default locale: ID: ro_RO, Name: Romanian (Romania)
271.1879 +display locale: ID: ro_RO, Name: Romanian (Romania)
271.1880 +format locale: ID: ro_RO, Name: Romanian (Romania)
271.1881 +default charset: ISO-8859-2
271.1882  
271.1883  OS Locale:  ro_RO.ISO8859-2
271.1884 -ro_RO
271.1885 -Romanian (Romania)
271.1886 -ISO-8859-2
271.1887 +default locale: ID: ro_RO, Name: Romanian (Romania)
271.1888 +display locale: ID: ro_RO, Name: Romanian (Romania)
271.1889 +format locale: ID: ro_RO, Name: Romanian (Romania)
271.1890 +default charset: ISO-8859-2
271.1891  
271.1892  OS Locale:  ru
271.1893 -ru_RU
271.1894 -Russian (Russia)
271.1895 -ISO-8859-5
271.1896 +default locale: ID: ru_RU, Name: Russian (Russia)
271.1897 +display locale: ID: ru_RU, Name: Russian (Russia)
271.1898 +format locale: ID: ru_RU, Name: Russian (Russia)
271.1899 +default charset: ISO-8859-5
271.1900  
271.1901  OS Locale:  ru.UTF-8
271.1902 -ru_RU
271.1903 -Russian (Russia)
271.1904 -UTF-8
271.1905 +default locale: ID: ru_RU, Name: Russian (Russia)
271.1906 +display locale: ID: ru_RU, Name: Russian (Russia)
271.1907 +format locale: ID: ru_RU, Name: Russian (Russia)
271.1908 +default charset: UTF-8
271.1909  
271.1910  OS Locale:  ru.koi8-r
271.1911 -ru_RU
271.1912 -Russian (Russia)
271.1913 -KOI8-R
271.1914 +default locale: ID: ru_RU, Name: Russian (Russia)
271.1915 +display locale: ID: ru_RU, Name: Russian (Russia)
271.1916 +format locale: ID: ru_RU, Name: Russian (Russia)
271.1917 +default charset: KOI8-R
271.1918  
271.1919  OS Locale:  ru_RU
271.1920 -ru_RU
271.1921 -Russian (Russia)
271.1922 -ISO-8859-5
271.1923 +default locale: ID: ru_RU, Name: Russian (Russia)
271.1924 +display locale: ID: ru_RU, Name: Russian (Russia)
271.1925 +format locale: ID: ru_RU, Name: Russian (Russia)
271.1926 +default charset: ISO-8859-5
271.1927  
271.1928  OS Locale:  ru_RU.ANSI1251
271.1929 -ru_RU
271.1930 -Russian (Russia)
271.1931 -windows-1251
271.1932 +default locale: ID: ru_RU, Name: Russian (Russia)
271.1933 +display locale: ID: ru_RU, Name: Russian (Russia)
271.1934 +format locale: ID: ru_RU, Name: Russian (Russia)
271.1935 +default charset: windows-1251
271.1936  
271.1937  OS Locale:  ru_RU.ISO8859-5
271.1938 -ru_RU
271.1939 -Russian (Russia)
271.1940 -ISO-8859-5
271.1941 +default locale: ID: ru_RU, Name: Russian (Russia)
271.1942 +display locale: ID: ru_RU, Name: Russian (Russia)
271.1943 +format locale: ID: ru_RU, Name: Russian (Russia)
271.1944 +default charset: ISO-8859-5
271.1945  
271.1946  OS Locale:  ru_RU.KOI8-R
271.1947 -ru_RU
271.1948 -Russian (Russia)
271.1949 -KOI8-R
271.1950 +default locale: ID: ru_RU, Name: Russian (Russia)
271.1951 +display locale: ID: ru_RU, Name: Russian (Russia)
271.1952 +format locale: ID: ru_RU, Name: Russian (Russia)
271.1953 +default charset: KOI8-R
271.1954  
271.1955  OS Locale:  ru_RU.UTF-8
271.1956 -ru_RU
271.1957 -Russian (Russia)
271.1958 -UTF-8
271.1959 +default locale: ID: ru_RU, Name: Russian (Russia)
271.1960 +display locale: ID: ru_RU, Name: Russian (Russia)
271.1961 +format locale: ID: ru_RU, Name: Russian (Russia)
271.1962 +default charset: UTF-8
271.1963  
271.1964  OS Locale:  sh_BA
271.1965 -sr_BA
271.1966 -Serbian (Bosnia and Herzegovina)
271.1967 -ISO-8859-2
271.1968 +default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
271.1969 +display locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
271.1970 +format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
271.1971 +default charset: ISO-8859-2
271.1972  
271.1973  OS Locale:  sh_BA.ISO8859-2@bosnia
271.1974 -sr_BA
271.1975 -Serbian (Bosnia and Herzegovina)
271.1976 -ISO-8859-2
271.1977 +default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
271.1978 +display locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
271.1979 +format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
271.1980 +default charset: ISO-8859-2
271.1981  
271.1982  OS Locale:  sk_SK
271.1983 -sk_SK
271.1984 -Slovak (Slovakia)
271.1985 -ISO-8859-2
271.1986 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
271.1987 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
271.1988 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
271.1989 +default charset: ISO-8859-2
271.1990  
271.1991  OS Locale:  sk_SK.ISO8859-2
271.1992 -sk_SK
271.1993 -Slovak (Slovakia)
271.1994 -ISO-8859-2
271.1995 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
271.1996 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
271.1997 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
271.1998 +default charset: ISO-8859-2
271.1999  
271.2000  OS Locale:  sl_SI
271.2001 -sl_SI
271.2002 -Slovenian (Slovenia)
271.2003 -ISO-8859-2
271.2004 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
271.2005 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
271.2006 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
271.2007 +default charset: ISO-8859-2
271.2008  
271.2009  OS Locale:  sl_SI.ISO8859-2
271.2010 -sl_SI
271.2011 -Slovenian (Slovenia)
271.2012 -ISO-8859-2
271.2013 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
271.2014 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
271.2015 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
271.2016 +default charset: ISO-8859-2
271.2017  
271.2018  OS Locale:  sq_AL
271.2019 -sq_AL
271.2020 -Albanian (Albania)
271.2021 -ISO-8859-2
271.2022 +default locale: ID: sq_AL, Name: Albanian (Albania)
271.2023 +display locale: ID: sq_AL, Name: Albanian (Albania)
271.2024 +format locale: ID: sq_AL, Name: Albanian (Albania)
271.2025 +default charset: ISO-8859-2
271.2026  
271.2027  OS Locale:  sq_AL.ISO8859-2
271.2028 -sq_AL
271.2029 -Albanian (Albania)
271.2030 -ISO-8859-2
271.2031 +default locale: ID: sq_AL, Name: Albanian (Albania)
271.2032 +display locale: ID: sq_AL, Name: Albanian (Albania)
271.2033 +format locale: ID: sq_AL, Name: Albanian (Albania)
271.2034 +default charset: ISO-8859-2
271.2035  
271.2036  OS Locale:  sr_SP
271.2037 -sr_SP
271.2038 -Serbian (SP)
271.2039 -ISO-8859-5
271.2040 +default locale: ID: sr, Name: Serbian
271.2041 +display locale: ID: sr, Name: Serbian
271.2042 +format locale: ID: sr, Name: Serbian
271.2043 +default charset: ISO-8859-5
271.2044  
271.2045  OS Locale:  sr_YU
271.2046 -sr_CS
271.2047 -Serbian (Serbia and Montenegro)
271.2048 -ISO-8859-5
271.2049 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
271.2050 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
271.2051 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
271.2052 +default charset: ISO-8859-5
271.2053  
271.2054  OS Locale:  sr_YU.ISO8859-5
271.2055 -sr_CS
271.2056 -Serbian (Serbia and Montenegro)
271.2057 -ISO-8859-5
271.2058 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
271.2059 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
271.2060 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
271.2061 +default charset: ISO-8859-5
271.2062  
271.2063  OS Locale:  sv
271.2064 -sv_SE
271.2065 -Swedish (Sweden)
271.2066 -ISO-8859-1
271.2067 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2068 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2069 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2070 +default charset: ISO-8859-1
271.2071  
271.2072  OS Locale:  sv.ISO8859-15
271.2073 -sv_SE
271.2074 -Swedish (Sweden)
271.2075 -ISO-8859-15
271.2076 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2077 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2078 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2079 +default charset: ISO-8859-15
271.2080  
271.2081  OS Locale:  sv.UTF-8
271.2082 -sv_SE
271.2083 -Swedish (Sweden)
271.2084 -UTF-8
271.2085 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2086 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2087 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2088 +default charset: UTF-8
271.2089  
271.2090  OS Locale:  sv_SE
271.2091 -sv_SE
271.2092 -Swedish (Sweden)
271.2093 -ISO-8859-1
271.2094 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2095 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2096 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2097 +default charset: ISO-8859-1
271.2098  
271.2099  OS Locale:  sv_SE.ISO8859-1
271.2100 -sv_SE
271.2101 -Swedish (Sweden)
271.2102 -ISO-8859-1
271.2103 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2104 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2105 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2106 +default charset: ISO-8859-1
271.2107  
271.2108  OS Locale:  sv_SE.ISO8859-15
271.2109 -sv_SE
271.2110 -Swedish (Sweden)
271.2111 -ISO-8859-15
271.2112 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2113 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2114 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2115 +default charset: ISO-8859-15
271.2116  
271.2117  OS Locale:  sv_SE.ISO8859-15@euro
271.2118 -sv_SE
271.2119 -Swedish (Sweden)
271.2120 -ISO-8859-15
271.2121 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2122 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2123 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2124 +default charset: ISO-8859-15
271.2125  
271.2126  OS Locale:  sv_SE.UTF-8
271.2127 -sv_SE
271.2128 -Swedish (Sweden)
271.2129 -UTF-8
271.2130 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2131 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2132 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2133 +default charset: UTF-8
271.2134  
271.2135  OS Locale:  sv_SE.UTF-8@euro
271.2136 -sv_SE
271.2137 -Swedish (Sweden)
271.2138 -UTF-8
271.2139 +default locale: ID: sv_SE, Name: Swedish (Sweden)
271.2140 +display locale: ID: sv_SE, Name: Swedish (Sweden)
271.2141 +format locale: ID: sv_SE, Name: Swedish (Sweden)
271.2142 +default charset: UTF-8
271.2143  
271.2144  OS Locale:  th
271.2145 -th_TH
271.2146 -Thai (Thailand)
271.2147 -TIS-620
271.2148 +default locale: ID: th_TH, Name: Thai (Thailand)
271.2149 +display locale: ID: th_TH, Name: Thai (Thailand)
271.2150 +format locale: ID: th_TH, Name: Thai (Thailand)
271.2151 +default charset: TIS-620
271.2152  
271.2153  OS Locale:  th_TH
271.2154 -th_TH
271.2155 -Thai (Thailand)
271.2156 -TIS-620
271.2157 +default locale: ID: th_TH, Name: Thai (Thailand)
271.2158 +display locale: ID: th_TH, Name: Thai (Thailand)
271.2159 +format locale: ID: th_TH, Name: Thai (Thailand)
271.2160 +default charset: TIS-620
271.2161  
271.2162  OS Locale:  th_TH.ISO8859-11
271.2163 -th_TH
271.2164 -Thai (Thailand)
271.2165 -TIS-620
271.2166 +default locale: ID: th_TH, Name: Thai (Thailand)
271.2167 +display locale: ID: th_TH, Name: Thai (Thailand)
271.2168 +format locale: ID: th_TH, Name: Thai (Thailand)
271.2169 +default charset: TIS-620
271.2170  
271.2171  OS Locale:  th_TH.TIS620
271.2172 -th_TH
271.2173 -Thai (Thailand)
271.2174 -TIS-620
271.2175 +default locale: ID: th_TH, Name: Thai (Thailand)
271.2176 +display locale: ID: th_TH, Name: Thai (Thailand)
271.2177 +format locale: ID: th_TH, Name: Thai (Thailand)
271.2178 +default charset: TIS-620
271.2179  
271.2180  OS Locale:  th_TH.UTF-8
271.2181 -th_TH
271.2182 -Thai (Thailand)
271.2183 -UTF-8
271.2184 +default locale: ID: th_TH, Name: Thai (Thailand)
271.2185 +display locale: ID: th_TH, Name: Thai (Thailand)
271.2186 +format locale: ID: th_TH, Name: Thai (Thailand)
271.2187 +default charset: UTF-8
271.2188  
271.2189  OS Locale:  tr
271.2190 -tr_TR
271.2191 -Turkish (Turkey)
271.2192 -ISO-8859-9
271.2193 +default locale: ID: tr_TR, Name: Turkish (Turkey)
271.2194 +display locale: ID: tr_TR, Name: Turkish (Turkey)
271.2195 +format locale: ID: tr_TR, Name: Turkish (Turkey)
271.2196 +default charset: ISO-8859-9
271.2197  
271.2198  OS Locale:  tr_TR
271.2199 -tr_TR
271.2200 -Turkish (Turkey)
271.2201 -ISO-8859-9
271.2202 +default locale: ID: tr_TR, Name: Turkish (Turkey)
271.2203 +display locale: ID: tr_TR, Name: Turkish (Turkey)
271.2204 +format locale: ID: tr_TR, Name: Turkish (Turkey)
271.2205 +default charset: ISO-8859-9
271.2206  
271.2207  OS Locale:  tr_TR.ISO8859-9
271.2208 -tr_TR
271.2209 -Turkish (Turkey)
271.2210 -ISO-8859-9
271.2211 +default locale: ID: tr_TR, Name: Turkish (Turkey)
271.2212 +display locale: ID: tr_TR, Name: Turkish (Turkey)
271.2213 +format locale: ID: tr_TR, Name: Turkish (Turkey)
271.2214 +default charset: ISO-8859-9
271.2215  
271.2216  OS Locale:  tr_TR.UTF-8
271.2217 -tr_TR
271.2218 -Turkish (Turkey)
271.2219 -UTF-8
271.2220 +default locale: ID: tr_TR, Name: Turkish (Turkey)
271.2221 +display locale: ID: tr_TR, Name: Turkish (Turkey)
271.2222 +format locale: ID: tr_TR, Name: Turkish (Turkey)
271.2223 +default charset: UTF-8
271.2224  
271.2225  OS Locale:  zh
271.2226 -zh_CN
271.2227 -Chinese (China)
271.2228 -GB2312
271.2229 +default locale: ID: zh_CN, Name: Chinese (China)
271.2230 +display locale: ID: zh_CN, Name: Chinese (China)
271.2231 +format locale: ID: zh_CN, Name: Chinese (China)
271.2232 +default charset: GB2312
271.2233  
271.2234  OS Locale:  zh.GBK
271.2235 -zh_CN
271.2236 -Chinese (China)
271.2237 -GBK
271.2238 +default locale: ID: zh_CN, Name: Chinese (China)
271.2239 +display locale: ID: zh_CN, Name: Chinese (China)
271.2240 +format locale: ID: zh_CN, Name: Chinese (China)
271.2241 +default charset: GBK
271.2242  
271.2243  OS Locale:  zh.UTF-8
271.2244 -zh_CN
271.2245 -Chinese (China)
271.2246 -UTF-8
271.2247 +default locale: ID: zh_CN, Name: Chinese (China)
271.2248 +display locale: ID: zh_CN, Name: Chinese (China)
271.2249 +format locale: ID: zh_CN, Name: Chinese (China)
271.2250 +default charset: UTF-8
271.2251  
271.2252  OS Locale:  zh_CN.EUC
271.2253 -zh_CN
271.2254 -Chinese (China)
271.2255 -GB2312
271.2256 +default locale: ID: zh_CN, Name: Chinese (China)
271.2257 +display locale: ID: zh_CN, Name: Chinese (China)
271.2258 +format locale: ID: zh_CN, Name: Chinese (China)
271.2259 +default charset: GB2312
271.2260  
271.2261  OS Locale:  zh_CN.EUC@pinyin
271.2262 -zh_CN
271.2263 -Chinese (China)
271.2264 -GB2312
271.2265 +default locale: ID: zh_CN, Name: Chinese (China)
271.2266 +display locale: ID: zh_CN, Name: Chinese (China)
271.2267 +format locale: ID: zh_CN, Name: Chinese (China)
271.2268 +default charset: GB2312
271.2269  
271.2270  OS Locale:  zh_CN.EUC@radical
271.2271 -zh_CN
271.2272 -Chinese (China)
271.2273 -GB2312
271.2274 +default locale: ID: zh_CN, Name: Chinese (China)
271.2275 +display locale: ID: zh_CN, Name: Chinese (China)
271.2276 +format locale: ID: zh_CN, Name: Chinese (China)
271.2277 +default charset: GB2312
271.2278  
271.2279  OS Locale:  zh_CN.EUC@stroke
271.2280 -zh_CN
271.2281 -Chinese (China)
271.2282 -GB2312
271.2283 +default locale: ID: zh_CN, Name: Chinese (China)
271.2284 +display locale: ID: zh_CN, Name: Chinese (China)
271.2285 +format locale: ID: zh_CN, Name: Chinese (China)
271.2286 +default charset: GB2312
271.2287  
271.2288  OS Locale:  zh_CN.GB18030
271.2289 -zh_CN
271.2290 -Chinese (China)
271.2291 -GB18030
271.2292 +default locale: ID: zh_CN, Name: Chinese (China)
271.2293 +display locale: ID: zh_CN, Name: Chinese (China)
271.2294 +format locale: ID: zh_CN, Name: Chinese (China)
271.2295 +default charset: GB18030
271.2296  
271.2297  OS Locale:  zh_CN.GB18030@pinyin
271.2298 -zh_CN
271.2299 -Chinese (China)
271.2300 -GB18030
271.2301 +default locale: ID: zh_CN, Name: Chinese (China)
271.2302 +display locale: ID: zh_CN, Name: Chinese (China)
271.2303 +format locale: ID: zh_CN, Name: Chinese (China)
271.2304 +default charset: GB18030
271.2305  
271.2306  OS Locale:  zh_CN.GB18030@radical
271.2307 -zh_CN
271.2308 -Chinese (China)
271.2309 -GB18030
271.2310 +default locale: ID: zh_CN, Name: Chinese (China)
271.2311 +display locale: ID: zh_CN, Name: Chinese (China)
271.2312 +format locale: ID: zh_CN, Name: Chinese (China)
271.2313 +default charset: GB18030
271.2314  
271.2315  OS Locale:  zh_CN.GB18030@stroke
271.2316 -zh_CN
271.2317 -Chinese (China)
271.2318 -GB18030
271.2319 +default locale: ID: zh_CN, Name: Chinese (China)
271.2320 +display locale: ID: zh_CN, Name: Chinese (China)
271.2321 +format locale: ID: zh_CN, Name: Chinese (China)
271.2322 +default charset: GB18030
271.2323  
271.2324  OS Locale:  zh_CN.GBK
271.2325 -zh_CN
271.2326 -Chinese (China)
271.2327 -GBK
271.2328 +default locale: ID: zh_CN, Name: Chinese (China)
271.2329 +display locale: ID: zh_CN, Name: Chinese (China)
271.2330 +format locale: ID: zh_CN, Name: Chinese (China)
271.2331 +default charset: GBK
271.2332  
271.2333  OS Locale:  zh_CN.GBK@pinyin
271.2334 -zh_CN
271.2335 -Chinese (China)
271.2336 -GBK
271.2337 +default locale: ID: zh_CN, Name: Chinese (China)
271.2338 +display locale: ID: zh_CN, Name: Chinese (China)
271.2339 +format locale: ID: zh_CN, Name: Chinese (China)
271.2340 +default charset: GBK
271.2341  
271.2342  OS Locale:  zh_CN.GBK@radical
271.2343 -zh_CN
271.2344 -Chinese (China)
271.2345 -GBK
271.2346 +default locale: ID: zh_CN, Name: Chinese (China)
271.2347 +display locale: ID: zh_CN, Name: Chinese (China)
271.2348 +format locale: ID: zh_CN, Name: Chinese (China)
271.2349 +default charset: GBK
271.2350  
271.2351  OS Locale:  zh_CN.GBK@stroke
271.2352 -zh_CN
271.2353 -Chinese (China)
271.2354 -GBK
271.2355 +default locale: ID: zh_CN, Name: Chinese (China)
271.2356 +display locale: ID: zh_CN, Name: Chinese (China)
271.2357 +format locale: ID: zh_CN, Name: Chinese (China)
271.2358 +default charset: GBK
271.2359  
271.2360  OS Locale:  zh_CN.UTF-8
271.2361 -zh_CN
271.2362 -Chinese (China)
271.2363 -UTF-8
271.2364 +default locale: ID: zh_CN, Name: Chinese (China)
271.2365 +display locale: ID: zh_CN, Name: Chinese (China)
271.2366 +format locale: ID: zh_CN, Name: Chinese (China)
271.2367 +default charset: UTF-8
271.2368  
271.2369  OS Locale:  zh_CN.UTF-8@pinyin
271.2370 -zh_CN
271.2371 -Chinese (China)
271.2372 -UTF-8
271.2373 +default locale: ID: zh_CN, Name: Chinese (China)
271.2374 +display locale: ID: zh_CN, Name: Chinese (China)
271.2375 +format locale: ID: zh_CN, Name: Chinese (China)
271.2376 +default charset: UTF-8
271.2377  
271.2378  OS Locale:  zh_CN.UTF-8@radical
271.2379 -zh_CN
271.2380 -Chinese (China)
271.2381 -UTF-8
271.2382 +default locale: ID: zh_CN, Name: Chinese (China)
271.2383 +display locale: ID: zh_CN, Name: Chinese (China)
271.2384 +format locale: ID: zh_CN, Name: Chinese (China)
271.2385 +default charset: UTF-8
271.2386  
271.2387  OS Locale:  zh_CN.UTF-8@stroke
271.2388 -zh_CN
271.2389 -Chinese (China)
271.2390 -UTF-8
271.2391 +default locale: ID: zh_CN, Name: Chinese (China)
271.2392 +display locale: ID: zh_CN, Name: Chinese (China)
271.2393 +format locale: ID: zh_CN, Name: Chinese (China)
271.2394 +default charset: UTF-8
271.2395  
271.2396  OS Locale:  zh_HK.BIG5HK
271.2397 -zh_HK
271.2398 -Chinese (Hong Kong)
271.2399 -Big5-HKSCS
271.2400 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2401 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2402 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2403 +default charset: x-Big5-HKSCS-2001
271.2404  
271.2405  OS Locale:  zh_HK.BIG5HK@radical
271.2406 -zh_HK
271.2407 -Chinese (Hong Kong)
271.2408 -Big5-HKSCS
271.2409 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2410 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2411 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2412 +default charset: x-Big5-HKSCS-2001
271.2413  
271.2414  OS Locale:  zh_HK.BIG5HK@stroke
271.2415 -zh_HK
271.2416 -Chinese (Hong Kong)
271.2417 -Big5-HKSCS
271.2418 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2419 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2420 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2421 +default charset: x-Big5-HKSCS-2001
271.2422  
271.2423  OS Locale:  zh_HK.UTF-8
271.2424 -zh_HK
271.2425 -Chinese (Hong Kong)
271.2426 -UTF-8
271.2427 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2428 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2429 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2430 +default charset: UTF-8
271.2431  
271.2432  OS Locale:  zh_HK.UTF-8@radical
271.2433 -zh_HK
271.2434 -Chinese (Hong Kong)
271.2435 -UTF-8
271.2436 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2437 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2438 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2439 +default charset: UTF-8
271.2440  
271.2441  OS Locale:  zh_HK.UTF-8@stroke
271.2442 -zh_HK
271.2443 -Chinese (Hong Kong)
271.2444 -UTF-8
271.2445 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2446 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2447 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
271.2448 +default charset: UTF-8
271.2449  
271.2450  OS Locale:  zh_TW
271.2451 -zh_TW
271.2452 -Chinese (Taiwan)
271.2453 -x-EUC-TW
271.2454 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2455 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2456 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2457 +default charset: x-EUC-TW
271.2458  
271.2459  OS Locale:  zh_TW.BIG5
271.2460 -zh_TW
271.2461 -Chinese (Taiwan)
271.2462 -Big5
271.2463 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2464 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2465 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2466 +default charset: x-Big5-Solaris
271.2467  
271.2468  OS Locale:  zh_TW.BIG5@pinyin
271.2469 -zh_TW
271.2470 -Chinese (Taiwan)
271.2471 -Big5
271.2472 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2473 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2474 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2475 +default charset: x-Big5-Solaris
271.2476  
271.2477  OS Locale:  zh_TW.BIG5@radical
271.2478 -zh_TW
271.2479 -Chinese (Taiwan)
271.2480 -Big5
271.2481 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2482 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2483 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2484 +default charset: x-Big5-Solaris
271.2485  
271.2486  OS Locale:  zh_TW.BIG5@stroke
271.2487 -zh_TW
271.2488 -Chinese (Taiwan)
271.2489 -Big5
271.2490 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2491 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2492 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2493 +default charset: x-Big5-Solaris
271.2494  
271.2495  OS Locale:  zh_TW.BIG5@zhuyin
271.2496 -zh_TW
271.2497 -Chinese (Taiwan)
271.2498 -Big5
271.2499 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2500 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2501 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2502 +default charset: x-Big5-Solaris
271.2503  
271.2504  OS Locale:  zh_TW.EUC
271.2505 -zh_TW
271.2506 -Chinese (Taiwan)
271.2507 -x-EUC-TW
271.2508 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2509 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2510 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2511 +default charset: x-EUC-TW
271.2512  
271.2513  OS Locale:  zh_TW.EUC@pinyin
271.2514 -zh_TW
271.2515 -Chinese (Taiwan)
271.2516 -x-EUC-TW
271.2517 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2518 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2519 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2520 +default charset: x-EUC-TW
271.2521  
271.2522  OS Locale:  zh_TW.EUC@radical
271.2523 -zh_TW
271.2524 -Chinese (Taiwan)
271.2525 -x-EUC-TW
271.2526 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2527 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2528 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2529 +default charset: x-EUC-TW
271.2530  
271.2531  OS Locale:  zh_TW.EUC@stroke
271.2532 -zh_TW
271.2533 -Chinese (Taiwan)
271.2534 -x-EUC-TW
271.2535 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2536 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2537 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2538 +default charset: x-EUC-TW
271.2539  
271.2540  OS Locale:  zh_TW.EUC@zhuyin
271.2541 -zh_TW
271.2542 -Chinese (Taiwan)
271.2543 -x-EUC-TW
271.2544 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2545 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2546 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2547 +default charset: x-EUC-TW
271.2548  
271.2549  OS Locale:  zh_TW.UTF-8
271.2550 -zh_TW
271.2551 -Chinese (Taiwan)
271.2552 -UTF-8
271.2553 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2554 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2555 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2556 +default charset: UTF-8
271.2557  
271.2558  OS Locale:  zh_TW.UTF-8@pinyin
271.2559 -zh_TW
271.2560 -Chinese (Taiwan)
271.2561 -UTF-8
271.2562 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2563 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2564 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2565 +default charset: UTF-8
271.2566  
271.2567  OS Locale:  zh_TW.UTF-8@radical
271.2568 -zh_TW
271.2569 -Chinese (Taiwan)
271.2570 -UTF-8
271.2571 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2572 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2573 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2574 +default charset: UTF-8
271.2575  
271.2576  OS Locale:  zh_TW.UTF-8@stroke
271.2577 -zh_TW
271.2578 -Chinese (Taiwan)
271.2579 -UTF-8
271.2580 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2581 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2582 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2583 +default charset: UTF-8
271.2584  
271.2585  OS Locale:  zh_TW.UTF-8@zhuyin
271.2586 -zh_TW
271.2587 -Chinese (Taiwan)
271.2588 -UTF-8
271.2589 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2590 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2591 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
271.2592 +default charset: UTF-8
271.2593 +
271.2594 +Testing some typical combinations
271.2595 +
271.2596 +
271.2597 +OS Locale (LC_CTYPE: ja_JP.UTF-8, LC_MESSAGES: zh_CN.UTF-8)
271.2598 +default locale: ID: zh_CN, Name: Chinese (China)
271.2599 +display locale: ID: zh_CN, Name: Chinese (China)
271.2600 +format locale: ID: ja_JP, Name: Japanese (Japan)
271.2601 +default charset: UTF-8
271.2602 +
271.2603 +OS Locale (LC_CTYPE: zh_CN.UTF-8, LC_MESSAGES: en_US.UTF-8)
271.2604 +default locale: ID: en_US, Name: English (United States)
271.2605 +display locale: ID: en_US, Name: English (United States)
271.2606 +format locale: ID: zh_CN, Name: Chinese (China)
271.2607 +default charset: UTF-8
271.2608 +
271.2609 +OS Locale (LC_CTYPE: C, LC_MESSAGES: zh_CN.UTF-8)
271.2610 +default locale: ID: zh_CN, Name: Chinese (China)
271.2611 +display locale: ID: zh_CN, Name: Chinese (China)
271.2612 +format locale: ID: en, Name: English
271.2613 +default charset: US-ASCII
   272.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   272.2 +++ b/test/java/util/Locale/data/deflocale.sol10.fmtasdefault	Fri Sep 24 16:41:32 2010 -0700
   272.3 @@ -0,0 +1,1725 @@
   272.4 +                         Solaris 10 3/05 s10_74L2a SPARC
   272.5 +
   272.6 +                      (copyright from `uname -a` goes here)
   272.7 +
   272.8 +SunOS deltas4 5.10 Generic_142900-03 sun4u sparc SUNW,Sun-Blade-2500
   272.9 +Testing all available locales
  272.10 +
  272.11 +OS Locale:  C
  272.12 +default locale: ID: en, Name: English
  272.13 +display locale: ID: en, Name: English
  272.14 +format locale: ID: en, Name: English
  272.15 +default charset: US-ASCII
  272.16 +
  272.17 +OS Locale:  POSIX
  272.18 +default locale: ID: en, Name: English
  272.19 +display locale: ID: en, Name: English
  272.20 +format locale: ID: en, Name: English
  272.21 +default charset: US-ASCII
  272.22 +
  272.23 +OS Locale:  ar
  272.24 +default locale: ID: ar_EG, Name: Arabic (Egypt)
  272.25 +display locale: ID: ar_EG, Name: Arabic (Egypt)
  272.26 +format locale: ID: ar_EG, Name: Arabic (Egypt)
  272.27 +default charset: ISO-8859-6
  272.28 +
  272.29 +OS Locale:  ar_EG.UTF-8
  272.30 +default locale: ID: ar_EG, Name: Arabic (Egypt)
  272.31 +display locale: ID: ar_EG, Name: Arabic (Egypt)
  272.32 +format locale: ID: ar_EG, Name: Arabic (Egypt)
  272.33 +default charset: UTF-8
  272.34 +
  272.35 +OS Locale:  ar_SA.UTF-8
  272.36 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  272.37 +display locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  272.38 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  272.39 +default charset: UTF-8
  272.40 +
  272.41 +OS Locale:  bg_BG
  272.42 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  272.43 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  272.44 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  272.45 +default charset: ISO-8859-5
  272.46 +
  272.47 +OS Locale:  bg_BG.ISO8859-5
  272.48 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  272.49 +display locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  272.50 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  272.51 +default charset: ISO-8859-5
  272.52 +
  272.53 +OS Locale:  ca
  272.54 +default locale: ID: ca_ES, Name: Catalan (Spain)
  272.55 +display locale: ID: ca_ES, Name: Catalan (Spain)
  272.56 +format locale: ID: ca_ES, Name: Catalan (Spain)
  272.57 +default charset: ISO-8859-1
  272.58 +
  272.59 +OS Locale:  ca_ES
  272.60 +default locale: ID: ca_ES, Name: Catalan (Spain)
  272.61 +display locale: ID: ca_ES, Name: Catalan (Spain)
  272.62 +format locale: ID: ca_ES, Name: Catalan (Spain)
  272.63 +default charset: ISO-8859-1
  272.64 +
  272.65 +OS Locale:  ca_ES.ISO8859-1
  272.66 +default locale: ID: ca_ES, Name: Catalan (Spain)
  272.67 +display locale: ID: ca_ES, Name: Catalan (Spain)
  272.68 +format locale: ID: ca_ES, Name: Catalan (Spain)
  272.69 +default charset: ISO-8859-1
  272.70 +
  272.71 +OS Locale:  ca_ES.ISO8859-15
  272.72 +default locale: ID: ca_ES, Name: Catalan (Spain)
  272.73 +display locale: ID: ca_ES, Name: Catalan (Spain)
  272.74 +format locale: ID: ca_ES, Name: Catalan (Spain)
  272.75 +default charset: ISO-8859-15
  272.76 +
  272.77 +OS Locale:  ca_ES.ISO8859-15@euro
  272.78 +default locale: ID: ca_ES, Name: Catalan (Spain)
  272.79 +display locale: ID: ca_ES, Name: Catalan (Spain)
  272.80 +format locale: ID: ca_ES, Name: Catalan (Spain)
  272.81 +default charset: ISO-8859-15
  272.82 +
  272.83 +OS Locale:  cs_CZ
  272.84 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.85 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.86 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.87 +default charset: ISO-8859-2
  272.88 +
  272.89 +OS Locale:  cs_CZ.ISO8859-2
  272.90 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.91 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.92 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.93 +default charset: ISO-8859-2
  272.94 +
  272.95 +OS Locale:  cs_CZ.UTF-8
  272.96 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.97 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.98 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
  272.99 +default charset: UTF-8
 272.100 +
 272.101 +OS Locale:  cs_CZ.UTF-8@euro
 272.102 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 272.103 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 272.104 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 272.105 +default charset: UTF-8
 272.106 +
 272.107 +OS Locale:  cz
 272.108 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
 272.109 +display locale: ID: cs_CZ, Name: Czech (Czech Republic)
 272.110 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
 272.111 +default charset: ISO-8859-2
 272.112 +
 272.113 +OS Locale:  da
 272.114 +default locale: ID: da_DK, Name: Danish (Denmark)
 272.115 +display locale: ID: da_DK, Name: Danish (Denmark)
 272.116 +format locale: ID: da_DK, Name: Danish (Denmark)
 272.117 +default charset: ISO-8859-1
 272.118 +
 272.119 +OS Locale:  da.ISO8859-15
 272.120 +default locale: ID: da_DK, Name: Danish (Denmark)
 272.121 +display locale: ID: da_DK, Name: Danish (Denmark)
 272.122 +format locale: ID: da_DK, Name: Danish (Denmark)
 272.123 +default charset: ISO-8859-15
 272.124 +
 272.125 +OS Locale:  da_DK
 272.126 +default locale: ID: da_DK, Name: Danish (Denmark)
 272.127 +display locale: ID: da_DK, Name: Danish (Denmark)
 272.128 +format locale: ID: da_DK, Name: Danish (Denmark)
 272.129 +default charset: ISO-8859-1
 272.130 +
 272.131 +OS Locale:  da_DK.ISO8859-1
 272.132 +default locale: ID: da_DK, Name: Danish (Denmark)
 272.133 +display locale: ID: da_DK, Name: Danish (Denmark)
 272.134 +format locale: ID: da_DK, Name: Danish (Denmark)
 272.135 +default charset: ISO-8859-1
 272.136 +
 272.137 +OS Locale:  da_DK.ISO8859-15
 272.138 +default locale: ID: da_DK, Name: Danish (Denmark)
 272.139 +display locale: ID: da_DK, Name: Danish (Denmark)
 272.140 +format locale: ID: da_DK, Name: Danish (Denmark)
 272.141 +default charset: ISO-8859-15
 272.142 +
 272.143 +OS Locale:  da_DK.ISO8859-15@euro
 272.144 +default locale: ID: da_DK, Name: Danish (Denmark)
 272.145 +display locale: ID: da_DK, Name: Danish (Denmark)
 272.146 +format locale: ID: da_DK, Name: Danish (Denmark)
 272.147 +default charset: ISO-8859-15
 272.148 +
 272.149 +OS Locale:  de
 272.150 +default locale: ID: de_DE, Name: German (Germany)
 272.151 +display locale: ID: de_DE, Name: German (Germany)
 272.152 +format locale: ID: de_DE, Name: German (Germany)
 272.153 +default charset: ISO-8859-1
 272.154 +
 272.155 +OS Locale:  de.ISO8859-15
 272.156 +default locale: ID: de_DE, Name: German (Germany)
 272.157 +display locale: ID: de_DE, Name: German (Germany)
 272.158 +format locale: ID: de_DE, Name: German (Germany)
 272.159 +default charset: ISO-8859-15
 272.160 +
 272.161 +OS Locale:  de.UTF-8
 272.162 +default locale: ID: de_DE, Name: German (Germany)
 272.163 +display locale: ID: de_DE, Name: German (Germany)
 272.164 +format locale: ID: de_DE, Name: German (Germany)
 272.165 +default charset: UTF-8
 272.166 +
 272.167 +OS Locale:  de_AT
 272.168 +default locale: ID: de_AT, Name: German (Austria)
 272.169 +display locale: ID: de_AT, Name: German (Austria)
 272.170 +format locale: ID: de_AT, Name: German (Austria)
 272.171 +default charset: ISO-8859-1
 272.172 +
 272.173 +OS Locale:  de_AT.ISO8859-1
 272.174 +default locale: ID: de_AT, Name: German (Austria)
 272.175 +display locale: ID: de_AT, Name: German (Austria)
 272.176 +format locale: ID: de_AT, Name: German (Austria)
 272.177 +default charset: ISO-8859-1
 272.178 +
 272.179 +OS Locale:  de_AT.ISO8859-15
 272.180 +default locale: ID: de_AT, Name: German (Austria)
 272.181 +display locale: ID: de_AT, Name: German (Austria)
 272.182 +format locale: ID: de_AT, Name: German (Austria)
 272.183 +default charset: ISO-8859-15
 272.184 +
 272.185 +OS Locale:  de_AT.ISO8859-15@euro
 272.186 +default locale: ID: de_AT, Name: German (Austria)
 272.187 +display locale: ID: de_AT, Name: German (Austria)
 272.188 +format locale: ID: de_AT, Name: German (Austria)
 272.189 +default charset: ISO-8859-15
 272.190 +
 272.191 +OS Locale:  de_CH
 272.192 +default locale: ID: de_CH, Name: German (Switzerland)
 272.193 +display locale: ID: de_CH, Name: German (Switzerland)
 272.194 +format locale: ID: de_CH, Name: German (Switzerland)
 272.195 +default charset: ISO-8859-1
 272.196 +
 272.197 +OS Locale:  de_CH.ISO8859-1
 272.198 +default locale: ID: de_CH, Name: German (Switzerland)
 272.199 +display locale: ID: de_CH, Name: German (Switzerland)
 272.200 +format locale: ID: de_CH, Name: German (Switzerland)
 272.201 +default charset: ISO-8859-1
 272.202 +
 272.203 +OS Locale:  de_DE
 272.204 +default locale: ID: de_DE, Name: German (Germany)
 272.205 +display locale: ID: de_DE, Name: German (Germany)
 272.206 +format locale: ID: de_DE, Name: German (Germany)
 272.207 +default charset: ISO-8859-1
 272.208 +
 272.209 +OS Locale:  de_DE.ISO8859-1
 272.210 +default locale: ID: de_DE, Name: German (Germany)
 272.211 +display locale: ID: de_DE, Name: German (Germany)
 272.212 +format locale: ID: de_DE, Name: German (Germany)
 272.213 +default charset: ISO-8859-1
 272.214 +
 272.215 +OS Locale:  de_DE.ISO8859-15
 272.216 +default locale: ID: de_DE, Name: German (Germany)
 272.217 +display locale: ID: de_DE, Name: German (Germany)
 272.218 +format locale: ID: de_DE, Name: German (Germany)
 272.219 +default charset: ISO-8859-15
 272.220 +
 272.221 +OS Locale:  de_DE.ISO8859-15@euro
 272.222 +default locale: ID: de_DE, Name: German (Germany)
 272.223 +display locale: ID: de_DE, Name: German (Germany)
 272.224 +format locale: ID: de_DE, Name: German (Germany)
 272.225 +default charset: ISO-8859-15
 272.226 +
 272.227 +OS Locale:  de_DE.UTF-8
 272.228 +default locale: ID: de_DE, Name: German (Germany)
 272.229 +display locale: ID: de_DE, Name: German (Germany)
 272.230 +format locale: ID: de_DE, Name: German (Germany)
 272.231 +default charset: UTF-8
 272.232 +
 272.233 +OS Locale:  de_DE.UTF-8@euro
 272.234 +default locale: ID: de_DE, Name: German (Germany)
 272.235 +display locale: ID: de_DE, Name: German (Germany)
 272.236 +format locale: ID: de_DE, Name: German (Germany)
 272.237 +default charset: UTF-8
 272.238 +
 272.239 +OS Locale:  el
 272.240 +default locale: ID: el_GR, Name: Greek (Greece)
 272.241 +display locale: ID: el_GR, Name: Greek (Greece)
 272.242 +format locale: ID: el_GR, Name: Greek (Greece)
 272.243 +default charset: ISO-8859-7
 272.244 +
 272.245 +OS Locale:  el.sun_eu_greek
 272.246 +default locale: ID: el_GR, Name: Greek (Greece)
 272.247 +display locale: ID: el_GR, Name: Greek (Greece)
 272.248 +format locale: ID: el_GR, Name: Greek (Greece)
 272.249 +default charset: ISO-8859-7
 272.250 +
 272.251 +OS Locale:  el_GR
 272.252 +default locale: ID: el_GR, Name: Greek (Greece)
 272.253 +display locale: ID: el_GR, Name: Greek (Greece)
 272.254 +format locale: ID: el_GR, Name: Greek (Greece)
 272.255 +default charset: ISO-8859-7
 272.256 +
 272.257 +OS Locale:  el_GR.ISO8859-7
 272.258 +default locale: ID: el_GR, Name: Greek (Greece)
 272.259 +display locale: ID: el_GR, Name: Greek (Greece)
 272.260 +format locale: ID: el_GR, Name: Greek (Greece)
 272.261 +default charset: ISO-8859-7
 272.262 +
 272.263 +OS Locale:  el_GR.ISO8859-7@euro
 272.264 +default locale: ID: el_GR, Name: Greek (Greece)
 272.265 +display locale: ID: el_GR, Name: Greek (Greece)
 272.266 +format locale: ID: el_GR, Name: Greek (Greece)
 272.267 +default charset: ISO-8859-7
 272.268 +
 272.269 +OS Locale:  en_AU
 272.270 +default locale: ID: en_AU, Name: English (Australia)
 272.271 +display locale: ID: en_AU, Name: English (Australia)
 272.272 +format locale: ID: en_AU, Name: English (Australia)
 272.273 +default charset: ISO-8859-1
 272.274 +
 272.275 +OS Locale:  en_AU.ISO8859-1
 272.276 +default locale: ID: en_AU, Name: English (Australia)
 272.277 +display locale: ID: en_AU, Name: English (Australia)
 272.278 +format locale: ID: en_AU, Name: English (Australia)
 272.279 +default charset: ISO-8859-1
 272.280 +
 272.281 +OS Locale:  en_CA
 272.282 +default locale: ID: en_CA, Name: English (Canada)
 272.283 +display locale: ID: en_CA, Name: English (Canada)
 272.284 +format locale: ID: en_CA, Name: English (Canada)
 272.285 +default charset: ISO-8859-1
 272.286 +
 272.287 +OS Locale:  en_CA.ISO8859-1
 272.288 +default locale: ID: en_CA, Name: English (Canada)
 272.289 +display locale: ID: en_CA, Name: English (Canada)
 272.290 +format locale: ID: en_CA, Name: English (Canada)
 272.291 +default charset: ISO-8859-1
 272.292 +
 272.293 +OS Locale:  en_CA.UTF-8
 272.294 +default locale: ID: en_CA, Name: English (Canada)
 272.295 +display locale: ID: en_CA, Name: English (Canada)
 272.296 +format locale: ID: en_CA, Name: English (Canada)
 272.297 +default charset: UTF-8
 272.298 +
 272.299 +OS Locale:  en_GB
 272.300 +default locale: ID: en_GB, Name: English (United Kingdom)
 272.301 +display locale: ID: en_GB, Name: English (United Kingdom)
 272.302 +format locale: ID: en_GB, Name: English (United Kingdom)
 272.303 +default charset: ISO-8859-1
 272.304 +
 272.305 +OS Locale:  en_GB.ISO8859-1
 272.306 +default locale: ID: en_GB, Name: English (United Kingdom)
 272.307 +display locale: ID: en_GB, Name: English (United Kingdom)
 272.308 +format locale: ID: en_GB, Name: English (United Kingdom)
 272.309 +default charset: ISO-8859-1
 272.310 +
 272.311 +OS Locale:  en_GB.ISO8859-15
 272.312 +default locale: ID: en_GB, Name: English (United Kingdom)
 272.313 +display locale: ID: en_GB, Name: English (United Kingdom)
 272.314 +format locale: ID: en_GB, Name: English (United Kingdom)
 272.315 +default charset: ISO-8859-15
 272.316 +
 272.317 +OS Locale:  en_GB.ISO8859-15@euro
 272.318 +default locale: ID: en_GB, Name: English (United Kingdom)
 272.319 +display locale: ID: en_GB, Name: English (United Kingdom)
 272.320 +format locale: ID: en_GB, Name: English (United Kingdom)
 272.321 +default charset: ISO-8859-15
 272.322 +
 272.323 +OS Locale:  en_IE
 272.324 +default locale: ID: en_IE, Name: English (Ireland)
 272.325 +display locale: ID: en_IE, Name: English (Ireland)
 272.326 +format locale: ID: en_IE, Name: English (Ireland)
 272.327 +default charset: ISO-8859-1
 272.328 +
 272.329 +OS Locale:  en_IE.ISO8859-1
 272.330 +default locale: ID: en_IE, Name: English (Ireland)
 272.331 +display locale: ID: en_IE, Name: English (Ireland)
 272.332 +format locale: ID: en_IE, Name: English (Ireland)
 272.333 +default charset: ISO-8859-1
 272.334 +
 272.335 +OS Locale:  en_IE.ISO8859-15
 272.336 +default locale: ID: en_IE, Name: English (Ireland)
 272.337 +display locale: ID: en_IE, Name: English (Ireland)
 272.338 +format locale: ID: en_IE, Name: English (Ireland)
 272.339 +default charset: ISO-8859-15
 272.340 +
 272.341 +OS Locale:  en_IE.ISO8859-15@euro
 272.342 +default locale: ID: en_IE, Name: English (Ireland)
 272.343 +display locale: ID: en_IE, Name: English (Ireland)
 272.344 +format locale: ID: en_IE, Name: English (Ireland)
 272.345 +default charset: ISO-8859-15
 272.346 +
 272.347 +OS Locale:  en_NZ
 272.348 +default locale: ID: en_NZ, Name: English (New Zealand)
 272.349 +display locale: ID: en_NZ, Name: English (New Zealand)
 272.350 +format locale: ID: en_NZ, Name: English (New Zealand)
 272.351 +default charset: ISO-8859-1
 272.352 +
 272.353 +OS Locale:  en_NZ.ISO8859-1
 272.354 +default locale: ID: en_NZ, Name: English (New Zealand)
 272.355 +display locale: ID: en_NZ, Name: English (New Zealand)
 272.356 +format locale: ID: en_NZ, Name: English (New Zealand)
 272.357 +default charset: ISO-8859-1
 272.358 +
 272.359 +OS Locale:  en_US
 272.360 +default locale: ID: en_US, Name: English (United States)
 272.361 +display locale: ID: en_US, Name: English (United States)
 272.362 +format locale: ID: en_US, Name: English (United States)
 272.363 +default charset: ISO-8859-1
 272.364 +
 272.365 +OS Locale:  en_US.ISO8859-1
 272.366 +default locale: ID: en_US, Name: English (United States)
 272.367 +display locale: ID: en_US, Name: English (United States)
 272.368 +format locale: ID: en_US, Name: English (United States)
 272.369 +default charset: ISO-8859-1
 272.370 +
 272.371 +OS Locale:  en_US.ISO8859-15
 272.372 +default locale: ID: en_US, Name: English (United States)
 272.373 +display locale: ID: en_US, Name: English (United States)
 272.374 +format locale: ID: en_US, Name: English (United States)
 272.375 +default charset: ISO-8859-15
 272.376 +
 272.377 +OS Locale:  en_US.ISO8859-15@euro
 272.378 +default locale: ID: en_US, Name: English (United States)
 272.379 +display locale: ID: en_US, Name: English (United States)
 272.380 +format locale: ID: en_US, Name: English (United States)
 272.381 +default charset: ISO-8859-15
 272.382 +
 272.383 +OS Locale:  en_US.UTF-8
 272.384 +default locale: ID: en_US, Name: English (United States)
 272.385 +display locale: ID: en_US, Name: English (United States)
 272.386 +format locale: ID: en_US, Name: English (United States)
 272.387 +default charset: UTF-8
 272.388 +
 272.389 +OS Locale:  es
 272.390 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.391 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.392 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.393 +default charset: ISO-8859-1
 272.394 +
 272.395 +OS Locale:  es.ISO8859-15
 272.396 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.397 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.398 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.399 +default charset: ISO-8859-15
 272.400 +
 272.401 +OS Locale:  es.UTF-8
 272.402 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.403 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.404 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.405 +default charset: UTF-8
 272.406 +
 272.407 +OS Locale:  es_AR
 272.408 +default locale: ID: es_AR, Name: Spanish (Argentina)
 272.409 +display locale: ID: es_AR, Name: Spanish (Argentina)
 272.410 +format locale: ID: es_AR, Name: Spanish (Argentina)
 272.411 +default charset: ISO-8859-1
 272.412 +
 272.413 +OS Locale:  es_AR.ISO8859-1
 272.414 +default locale: ID: es_AR, Name: Spanish (Argentina)
 272.415 +display locale: ID: es_AR, Name: Spanish (Argentina)
 272.416 +format locale: ID: es_AR, Name: Spanish (Argentina)
 272.417 +default charset: ISO-8859-1
 272.418 +
 272.419 +OS Locale:  es_BO
 272.420 +default locale: ID: es_BO, Name: Spanish (Bolivia)
 272.421 +display locale: ID: es_BO, Name: Spanish (Bolivia)
 272.422 +format locale: ID: es_BO, Name: Spanish (Bolivia)
 272.423 +default charset: ISO-8859-1
 272.424 +
 272.425 +OS Locale:  es_BO.ISO8859-1
 272.426 +default locale: ID: es_BO, Name: Spanish (Bolivia)
 272.427 +display locale: ID: es_BO, Name: Spanish (Bolivia)
 272.428 +format locale: ID: es_BO, Name: Spanish (Bolivia)
 272.429 +default charset: ISO-8859-1
 272.430 +
 272.431 +OS Locale:  es_CL
 272.432 +default locale: ID: es_CL, Name: Spanish (Chile)
 272.433 +display locale: ID: es_CL, Name: Spanish (Chile)
 272.434 +format locale: ID: es_CL, Name: Spanish (Chile)
 272.435 +default charset: ISO-8859-1
 272.436 +
 272.437 +OS Locale:  es_CL.ISO8859-1
 272.438 +default locale: ID: es_CL, Name: Spanish (Chile)
 272.439 +display locale: ID: es_CL, Name: Spanish (Chile)
 272.440 +format locale: ID: es_CL, Name: Spanish (Chile)
 272.441 +default charset: ISO-8859-1
 272.442 +
 272.443 +OS Locale:  es_CO
 272.444 +default locale: ID: es_CO, Name: Spanish (Colombia)
 272.445 +display locale: ID: es_CO, Name: Spanish (Colombia)
 272.446 +format locale: ID: es_CO, Name: Spanish (Colombia)
 272.447 +default charset: ISO-8859-1
 272.448 +
 272.449 +OS Locale:  es_CO.ISO8859-1
 272.450 +default locale: ID: es_CO, Name: Spanish (Colombia)
 272.451 +display locale: ID: es_CO, Name: Spanish (Colombia)
 272.452 +format locale: ID: es_CO, Name: Spanish (Colombia)
 272.453 +default charset: ISO-8859-1
 272.454 +
 272.455 +OS Locale:  es_CR
 272.456 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
 272.457 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
 272.458 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
 272.459 +default charset: ISO-8859-1
 272.460 +
 272.461 +OS Locale:  es_CR.ISO8859-1
 272.462 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
 272.463 +display locale: ID: es_CR, Name: Spanish (Costa Rica)
 272.464 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
 272.465 +default charset: ISO-8859-1
 272.466 +
 272.467 +OS Locale:  es_EC
 272.468 +default locale: ID: es_EC, Name: Spanish (Ecuador)
 272.469 +display locale: ID: es_EC, Name: Spanish (Ecuador)
 272.470 +format locale: ID: es_EC, Name: Spanish (Ecuador)
 272.471 +default charset: ISO-8859-1
 272.472 +
 272.473 +OS Locale:  es_EC.ISO8859-1
 272.474 +default locale: ID: es_EC, Name: Spanish (Ecuador)
 272.475 +display locale: ID: es_EC, Name: Spanish (Ecuador)
 272.476 +format locale: ID: es_EC, Name: Spanish (Ecuador)
 272.477 +default charset: ISO-8859-1
 272.478 +
 272.479 +OS Locale:  es_ES
 272.480 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.481 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.482 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.483 +default charset: ISO-8859-1
 272.484 +
 272.485 +OS Locale:  es_ES.ISO8859-1
 272.486 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.487 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.488 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.489 +default charset: ISO-8859-1
 272.490 +
 272.491 +OS Locale:  es_ES.ISO8859-15
 272.492 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.493 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.494 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.495 +default charset: ISO-8859-15
 272.496 +
 272.497 +OS Locale:  es_ES.ISO8859-15@euro
 272.498 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.499 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.500 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.501 +default charset: ISO-8859-15
 272.502 +
 272.503 +OS Locale:  es_ES.UTF-8
 272.504 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.505 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.506 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.507 +default charset: UTF-8
 272.508 +
 272.509 +OS Locale:  es_ES.UTF-8@euro
 272.510 +default locale: ID: es_ES, Name: Spanish (Spain)
 272.511 +display locale: ID: es_ES, Name: Spanish (Spain)
 272.512 +format locale: ID: es_ES, Name: Spanish (Spain)
 272.513 +default charset: UTF-8
 272.514 +
 272.515 +OS Locale:  es_GT
 272.516 +default locale: ID: es_GT, Name: Spanish (Guatemala)
 272.517 +display locale: ID: es_GT, Name: Spanish (Guatemala)
 272.518 +format locale: ID: es_GT, Name: Spanish (Guatemala)
 272.519 +default charset: ISO-8859-1
 272.520 +
 272.521 +OS Locale:  es_GT.ISO8859-1
 272.522 +default locale: ID: es_GT, Name: Spanish (Guatemala)
 272.523 +display locale: ID: es_GT, Name: Spanish (Guatemala)
 272.524 +format locale: ID: es_GT, Name: Spanish (Guatemala)
 272.525 +default charset: ISO-8859-1
 272.526 +
 272.527 +OS Locale:  es_MX
 272.528 +default locale: ID: es_MX, Name: Spanish (Mexico)
 272.529 +display locale: ID: es_MX, Name: Spanish (Mexico)
 272.530 +format locale: ID: es_MX, Name: Spanish (Mexico)
 272.531 +default charset: ISO-8859-1
 272.532 +
 272.533 +OS Locale:  es_MX.ISO8859-1
 272.534 +default locale: ID: es_MX, Name: Spanish (Mexico)
 272.535 +display locale: ID: es_MX, Name: Spanish (Mexico)
 272.536 +format locale: ID: es_MX, Name: Spanish (Mexico)
 272.537 +default charset: ISO-8859-1
 272.538 +
 272.539 +OS Locale:  es_MX.UTF-8
 272.540 +default locale: ID: es_MX, Name: Spanish (Mexico)
 272.541 +display locale: ID: es_MX, Name: Spanish (Mexico)
 272.542 +format locale: ID: es_MX, Name: Spanish (Mexico)
 272.543 +default charset: UTF-8
 272.544 +
 272.545 +OS Locale:  es_NI
 272.546 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
 272.547 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
 272.548 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
 272.549 +default charset: ISO-8859-1
 272.550 +
 272.551 +OS Locale:  es_NI.ISO8859-1
 272.552 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
 272.553 +display locale: ID: es_NI, Name: Spanish (Nicaragua)
 272.554 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
 272.555 +default charset: ISO-8859-1
 272.556 +
 272.557 +OS Locale:  es_PA
 272.558 +default locale: ID: es_PA, Name: Spanish (Panama)
 272.559 +display locale: ID: es_PA, Name: Spanish (Panama)
 272.560 +format locale: ID: es_PA, Name: Spanish (Panama)
 272.561 +default charset: ISO-8859-1
 272.562 +
 272.563 +OS Locale:  es_PA.ISO8859-1
 272.564 +default locale: ID: es_PA, Name: Spanish (Panama)
 272.565 +display locale: ID: es_PA, Name: Spanish (Panama)
 272.566 +format locale: ID: es_PA, Name: Spanish (Panama)
 272.567 +default charset: ISO-8859-1
 272.568 +
 272.569 +OS Locale:  es_PE
 272.570 +default locale: ID: es_PE, Name: Spanish (Peru)
 272.571 +display locale: ID: es_PE, Name: Spanish (Peru)
 272.572 +format locale: ID: es_PE, Name: Spanish (Peru)
 272.573 +default charset: ISO-8859-1
 272.574 +
 272.575 +OS Locale:  es_PE.ISO8859-1
 272.576 +default locale: ID: es_PE, Name: Spanish (Peru)
 272.577 +display locale: ID: es_PE, Name: Spanish (Peru)
 272.578 +format locale: ID: es_PE, Name: Spanish (Peru)
 272.579 +default charset: ISO-8859-1
 272.580 +
 272.581 +OS Locale:  es_PY
 272.582 +default locale: ID: es_PY, Name: Spanish (Paraguay)
 272.583 +display locale: ID: es_PY, Name: Spanish (Paraguay)
 272.584 +format locale: ID: es_PY, Name: Spanish (Paraguay)
 272.585 +default charset: ISO-8859-1
 272.586 +
 272.587 +OS Locale:  es_PY.ISO8859-1
 272.588 +default locale: ID: es_PY, Name: Spanish (Paraguay)
 272.589 +display locale: ID: es_PY, Name: Spanish (Paraguay)
 272.590 +format locale: ID: es_PY, Name: Spanish (Paraguay)
 272.591 +default charset: ISO-8859-1
 272.592 +
 272.593 +OS Locale:  es_SV
 272.594 +default locale: ID: es_SV, Name: Spanish (El Salvador)
 272.595 +display locale: ID: es_SV, Name: Spanish (El Salvador)
 272.596 +format locale: ID: es_SV, Name: Spanish (El Salvador)
 272.597 +default charset: ISO-8859-1
 272.598 +
 272.599 +OS Locale:  es_SV.ISO8859-1
 272.600 +default locale: ID: es_SV, Name: Spanish (El Salvador)
 272.601 +display locale: ID: es_SV, Name: Spanish (El Salvador)
 272.602 +format locale: ID: es_SV, Name: Spanish (El Salvador)
 272.603 +default charset: ISO-8859-1
 272.604 +
 272.605 +OS Locale:  es_UY
 272.606 +default locale: ID: es_UY, Name: Spanish (Uruguay)
 272.607 +display locale: ID: es_UY, Name: Spanish (Uruguay)
 272.608 +format locale: ID: es_UY, Name: Spanish (Uruguay)
 272.609 +default charset: ISO-8859-1
 272.610 +
 272.611 +OS Locale:  es_UY.ISO8859-1
 272.612 +default locale: ID: es_UY, Name: Spanish (Uruguay)
 272.613 +display locale: ID: es_UY, Name: Spanish (Uruguay)
 272.614 +format locale: ID: es_UY, Name: Spanish (Uruguay)
 272.615 +default charset: ISO-8859-1
 272.616 +
 272.617 +OS Locale:  es_VE
 272.618 +default locale: ID: es_VE, Name: Spanish (Venezuela)
 272.619 +display locale: ID: es_VE, Name: Spanish (Venezuela)
 272.620 +format locale: ID: es_VE, Name: Spanish (Venezuela)
 272.621 +default charset: ISO-8859-1
 272.622 +
 272.623 +OS Locale:  es_VE.ISO8859-1
 272.624 +default locale: ID: es_VE, Name: Spanish (Venezuela)
 272.625 +display locale: ID: es_VE, Name: Spanish (Venezuela)
 272.626 +format locale: ID: es_VE, Name: Spanish (Venezuela)
 272.627 +default charset: ISO-8859-1
 272.628 +
 272.629 +OS Locale:  et
 272.630 +default locale: ID: et_EE, Name: Estonian (Estonia)
 272.631 +display locale: ID: et_EE, Name: Estonian (Estonia)
 272.632 +format locale: ID: et_EE, Name: Estonian (Estonia)
 272.633 +default charset: ISO-8859-15
 272.634 +
 272.635 +OS Locale:  et_EE
 272.636 +default locale: ID: et_EE, Name: Estonian (Estonia)
 272.637 +display locale: ID: et_EE, Name: Estonian (Estonia)
 272.638 +format locale: ID: et_EE, Name: Estonian (Estonia)
 272.639 +default charset: ISO-8859-15
 272.640 +
 272.641 +OS Locale:  et_EE.ISO8859-15
 272.642 +default locale: ID: et_EE, Name: Estonian (Estonia)
 272.643 +display locale: ID: et_EE, Name: Estonian (Estonia)
 272.644 +format locale: ID: et_EE, Name: Estonian (Estonia)
 272.645 +default charset: ISO-8859-15
 272.646 +
 272.647 +OS Locale:  fi
 272.648 +default locale: ID: fi_FI, Name: Finnish (Finland)
 272.649 +display locale: ID: fi_FI, Name: Finnish (Finland)
 272.650 +format locale: ID: fi_FI, Name: Finnish (Finland)
 272.651 +default charset: ISO-8859-1
 272.652 +
 272.653 +OS Locale:  fi.ISO8859-15
 272.654 +default locale: ID: fi_FI, Name: Finnish (Finland)
 272.655 +display locale: ID: fi_FI, Name: Finnish (Finland)
 272.656 +format locale: ID: fi_FI, Name: Finnish (Finland)
 272.657 +default charset: ISO-8859-15
 272.658 +
 272.659 +OS Locale:  fi_FI
 272.660 +default locale: ID: fi_FI, Name: Finnish (Finland)
 272.661 +display locale: ID: fi_FI, Name: Finnish (Finland)
 272.662 +format locale: ID: fi_FI, Name: Finnish (Finland)
 272.663 +default charset: ISO-8859-1
 272.664 +
 272.665 +OS Locale:  fi_FI.ISO8859-1
 272.666 +default locale: ID: fi_FI, Name: Finnish (Finland)
 272.667 +display locale: ID: fi_FI, Name: Finnish (Finland)
 272.668 +format locale: ID: fi_FI, Name: Finnish (Finland)
 272.669 +default charset: ISO-8859-1
 272.670 +
 272.671 +OS Locale:  fi_FI.ISO8859-15
 272.672 +default locale: ID: fi_FI, Name: Finnish (Finland)
 272.673 +display locale: ID: fi_FI, Name: Finnish (Finland)
 272.674 +format locale: ID: fi_FI, Name: Finnish (Finland)
 272.675 +default charset: ISO-8859-15
 272.676 +
 272.677 +OS Locale:  fi_FI.ISO8859-15@euro
 272.678 +default locale: ID: fi_FI, Name: Finnish (Finland)
 272.679 +display locale: ID: fi_FI, Name: Finnish (Finland)
 272.680 +format locale: ID: fi_FI, Name: Finnish (Finland)
 272.681 +default charset: ISO-8859-15
 272.682 +
 272.683 +OS Locale:  fi_FI.UTF-8
 272.684 +default locale: ID: fi_FI, Name: Finnish (Finland)
 272.685 +display locale: ID: fi_FI, Name: Finnish (Finland)
 272.686 +format locale: ID: fi_FI, Name: Finnish (Finland)
 272.687 +default charset: UTF-8
 272.688 +
 272.689 +OS Locale:  fr
 272.690 +default locale: ID: fr_FR, Name: French (France)
 272.691 +display locale: ID: fr_FR, Name: French (France)
 272.692 +format locale: ID: fr_FR, Name: French (France)
 272.693 +default charset: ISO-8859-1
 272.694 +
 272.695 +OS Locale:  fr.ISO8859-15
 272.696 +default locale: ID: fr_FR, Name: French (France)
 272.697 +display locale: ID: fr_FR, Name: French (France)
 272.698 +format locale: ID: fr_FR, Name: French (France)
 272.699 +default charset: ISO-8859-15
 272.700 +
 272.701 +OS Locale:  fr.UTF-8
 272.702 +default locale: ID: fr_FR, Name: French (France)
 272.703 +display locale: ID: fr_FR, Name: French (France)
 272.704 +format locale: ID: fr_FR, Name: French (France)
 272.705 +default charset: UTF-8
 272.706 +
 272.707 +OS Locale:  fr_BE
 272.708 +default locale: ID: fr_BE, Name: French (Belgium)
 272.709 +display locale: ID: fr_BE, Name: French (Belgium)
 272.710 +format locale: ID: fr_BE, Name: French (Belgium)
 272.711 +default charset: ISO-8859-1
 272.712 +
 272.713 +OS Locale:  fr_BE.ISO8859-1
 272.714 +default locale: ID: fr_BE, Name: French (Belgium)
 272.715 +display locale: ID: fr_BE, Name: French (Belgium)
 272.716 +format locale: ID: fr_BE, Name: French (Belgium)
 272.717 +default charset: ISO-8859-1
 272.718 +
 272.719 +OS Locale:  fr_BE.ISO8859-15
 272.720 +default locale: ID: fr_BE, Name: French (Belgium)
 272.721 +display locale: ID: fr_BE, Name: French (Belgium)
 272.722 +format locale: ID: fr_BE, Name: French (Belgium)
 272.723 +default charset: ISO-8859-15
 272.724 +
 272.725 +OS Locale:  fr_BE.ISO8859-15@euro
 272.726 +default locale: ID: fr_BE, Name: French (Belgium)
 272.727 +display locale: ID: fr_BE, Name: French (Belgium)
 272.728 +format locale: ID: fr_BE, Name: French (Belgium)
 272.729 +default charset: ISO-8859-15
 272.730 +
 272.731 +OS Locale:  fr_BE.UTF-8
 272.732 +default locale: ID: fr_BE, Name: French (Belgium)
 272.733 +display locale: ID: fr_BE, Name: French (Belgium)
 272.734 +format locale: ID: fr_BE, Name: French (Belgium)
 272.735 +default charset: UTF-8
 272.736 +
 272.737 +OS Locale:  fr_BE.UTF-8@euro
 272.738 +default locale: ID: fr_BE, Name: French (Belgium)
 272.739 +display locale: ID: fr_BE, Name: French (Belgium)
 272.740 +format locale: ID: fr_BE, Name: French (Belgium)
 272.741 +default charset: UTF-8
 272.742 +
 272.743 +OS Locale:  fr_CA
 272.744 +default locale: ID: fr_CA, Name: French (Canada)
 272.745 +display locale: ID: fr_CA, Name: French (Canada)
 272.746 +format locale: ID: fr_CA, Name: French (Canada)
 272.747 +default charset: ISO-8859-1
 272.748 +
 272.749 +OS Locale:  fr_CA.ISO8859-1
 272.750 +default locale: ID: fr_CA, Name: French (Canada)
 272.751 +display locale: ID: fr_CA, Name: French (Canada)
 272.752 +format locale: ID: fr_CA, Name: French (Canada)
 272.753 +default charset: ISO-8859-1
 272.754 +
 272.755 +OS Locale:  fr_CA.UTF-8
 272.756 +default locale: ID: fr_CA, Name: French (Canada)
 272.757 +display locale: ID: fr_CA, Name: French (Canada)
 272.758 +format locale: ID: fr_CA, Name: French (Canada)
 272.759 +default charset: UTF-8
 272.760 +
 272.761 +OS Locale:  fr_CH
 272.762 +default locale: ID: fr_CH, Name: French (Switzerland)
 272.763 +display locale: ID: fr_CH, Name: French (Switzerland)
 272.764 +format locale: ID: fr_CH, Name: French (Switzerland)
 272.765 +default charset: ISO-8859-1
 272.766 +
 272.767 +OS Locale:  fr_CH.ISO8859-1
 272.768 +default locale: ID: fr_CH, Name: French (Switzerland)
 272.769 +display locale: ID: fr_CH, Name: French (Switzerland)
 272.770 +format locale: ID: fr_CH, Name: French (Switzerland)
 272.771 +default charset: ISO-8859-1
 272.772 +
 272.773 +OS Locale:  fr_FR
 272.774 +default locale: ID: fr_FR, Name: French (France)
 272.775 +display locale: ID: fr_FR, Name: French (France)
 272.776 +format locale: ID: fr_FR, Name: French (France)
 272.777 +default charset: ISO-8859-1
 272.778 +
 272.779 +OS Locale:  fr_FR.ISO8859-1
 272.780 +default locale: ID: fr_FR, Name: French (France)
 272.781 +display locale: ID: fr_FR, Name: French (France)
 272.782 +format locale: ID: fr_FR, Name: French (France)
 272.783 +default charset: ISO-8859-1
 272.784 +
 272.785 +OS Locale:  fr_FR.ISO8859-15
 272.786 +default locale: ID: fr_FR, Name: French (France)
 272.787 +display locale: ID: fr_FR, Name: French (France)
 272.788 +format locale: ID: fr_FR, Name: French (France)
 272.789 +default charset: ISO-8859-15
 272.790 +
 272.791 +OS Locale:  fr_FR.ISO8859-15@euro
 272.792 +default locale: ID: fr_FR, Name: French (France)
 272.793 +display locale: ID: fr_FR, Name: French (France)
 272.794 +format locale: ID: fr_FR, Name: French (France)
 272.795 +default charset: ISO-8859-15
 272.796 +
 272.797 +OS Locale:  fr_FR.UTF-8
 272.798 +default locale: ID: fr_FR, Name: French (France)
 272.799 +display locale: ID: fr_FR, Name: French (France)
 272.800 +format locale: ID: fr_FR, Name: French (France)
 272.801 +default charset: UTF-8
 272.802 +
 272.803 +OS Locale:  fr_FR.UTF-8@euro
 272.804 +default locale: ID: fr_FR, Name: French (France)
 272.805 +display locale: ID: fr_FR, Name: French (France)
 272.806 +format locale: ID: fr_FR, Name: French (France)
 272.807 +default charset: UTF-8
 272.808 +
 272.809 +OS Locale:  he
 272.810 +default locale: ID: iw_IL, Name: Hebrew (Israel)
 272.811 +display locale: ID: iw_IL, Name: Hebrew (Israel)
 272.812 +format locale: ID: iw_IL, Name: Hebrew (Israel)
 272.813 +default charset: ISO-8859-8
 272.814 +
 272.815 +OS Locale:  he_IL
 272.816 +default locale: ID: iw_IL, Name: Hebrew (Israel)
 272.817 +display locale: ID: iw_IL, Name: Hebrew (Israel)
 272.818 +format locale: ID: iw_IL, Name: Hebrew (Israel)
 272.819 +default charset: ISO-8859-8
 272.820 +
 272.821 +OS Locale:  he_IL.UTF-8
 272.822 +default locale: ID: iw_IL, Name: Hebrew (Israel)
 272.823 +display locale: ID: iw_IL, Name: Hebrew (Israel)
 272.824 +format locale: ID: iw_IL, Name: Hebrew (Israel)
 272.825 +default charset: UTF-8
 272.826 +
 272.827 +OS Locale:  hi_IN.UTF-8
 272.828 +default locale: ID: hi_IN, Name: Hindi (India)
 272.829 +display locale: ID: hi_IN, Name: Hindi (India)
 272.830 +format locale: ID: hi_IN, Name: Hindi (India)
 272.831 +default charset: UTF-8
 272.832 +
 272.833 +OS Locale:  hr_HR
 272.834 +default locale: ID: hr_HR, Name: Croatian (Croatia)
 272.835 +display locale: ID: hr_HR, Name: Croatian (Croatia)
 272.836 +format locale: ID: hr_HR, Name: Croatian (Croatia)
 272.837 +default charset: ISO-8859-2
 272.838 +
 272.839 +OS Locale:  hr_HR.ISO8859-2
 272.840 +default locale: ID: hr_HR, Name: Croatian (Croatia)
 272.841 +display locale: ID: hr_HR, Name: Croatian (Croatia)
 272.842 +format locale: ID: hr_HR, Name: Croatian (Croatia)
 272.843 +default charset: ISO-8859-2
 272.844 +
 272.845 +OS Locale:  hu
 272.846 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.847 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.848 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.849 +default charset: ISO-8859-2
 272.850 +
 272.851 +OS Locale:  hu_HU
 272.852 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.853 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.854 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.855 +default charset: ISO-8859-2
 272.856 +
 272.857 +OS Locale:  hu_HU.ISO8859-2
 272.858 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.859 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.860 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.861 +default charset: ISO-8859-2
 272.862 +
 272.863 +OS Locale:  hu_HU.UTF-8
 272.864 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.865 +display locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.866 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
 272.867 +default charset: UTF-8
 272.868 +
 272.869 +OS Locale:  is_IS
 272.870 +default locale: ID: is_IS, Name: Icelandic (Iceland)
 272.871 +display locale: ID: is_IS, Name: Icelandic (Iceland)
 272.872 +format locale: ID: is_IS, Name: Icelandic (Iceland)
 272.873 +default charset: ISO-8859-1
 272.874 +
 272.875 +OS Locale:  is_IS.ISO8859-1
 272.876 +default locale: ID: is_IS, Name: Icelandic (Iceland)
 272.877 +display locale: ID: is_IS, Name: Icelandic (Iceland)
 272.878 +format locale: ID: is_IS, Name: Icelandic (Iceland)
 272.879 +default charset: ISO-8859-1
 272.880 +
 272.881 +OS Locale:  iso_8859_1
 272.882 +default locale: ID: en, Name: English
 272.883 +display locale: ID: en, Name: English
 272.884 +format locale: ID: en, Name: English
 272.885 +default charset: US-ASCII
 272.886 +
 272.887 +OS Locale:  it
 272.888 +default locale: ID: it_IT, Name: Italian (Italy)
 272.889 +display locale: ID: it_IT, Name: Italian (Italy)
 272.890 +format locale: ID: it_IT, Name: Italian (Italy)
 272.891 +default charset: ISO-8859-1
 272.892 +
 272.893 +OS Locale:  it.ISO8859-15
 272.894 +default locale: ID: it_IT, Name: Italian (Italy)
 272.895 +display locale: ID: it_IT, Name: Italian (Italy)
 272.896 +format locale: ID: it_IT, Name: Italian (Italy)
 272.897 +default charset: ISO-8859-15
 272.898 +
 272.899 +OS Locale:  it.UTF-8
 272.900 +default locale: ID: it_IT, Name: Italian (Italy)
 272.901 +display locale: ID: it_IT, Name: Italian (Italy)
 272.902 +format locale: ID: it_IT, Name: Italian (Italy)
 272.903 +default charset: UTF-8
 272.904 +
 272.905 +OS Locale:  it_IT
 272.906 +default locale: ID: it_IT, Name: Italian (Italy)
 272.907 +display locale: ID: it_IT, Name: Italian (Italy)
 272.908 +format locale: ID: it_IT, Name: Italian (Italy)
 272.909 +default charset: ISO-8859-1
 272.910 +
 272.911 +OS Locale:  it_IT.ISO8859-1
 272.912 +default locale: ID: it_IT, Name: Italian (Italy)
 272.913 +display locale: ID: it_IT, Name: Italian (Italy)
 272.914 +format locale: ID: it_IT, Name: Italian (Italy)
 272.915 +default charset: ISO-8859-1
 272.916 +
 272.917 +OS Locale:  it_IT.ISO8859-15
 272.918 +default locale: ID: it_IT, Name: Italian (Italy)
 272.919 +display locale: ID: it_IT, Name: Italian (Italy)
 272.920 +format locale: ID: it_IT, Name: Italian (Italy)
 272.921 +default charset: ISO-8859-15
 272.922 +
 272.923 +OS Locale:  it_IT.ISO8859-15@euro
 272.924 +default locale: ID: it_IT, Name: Italian (Italy)
 272.925 +display locale: ID: it_IT, Name: Italian (Italy)
 272.926 +format locale: ID: it_IT, Name: Italian (Italy)
 272.927 +default charset: ISO-8859-15
 272.928 +
 272.929 +OS Locale:  it_IT.UTF-8
 272.930 +default locale: ID: it_IT, Name: Italian (Italy)
 272.931 +display locale: ID: it_IT, Name: Italian (Italy)
 272.932 +format locale: ID: it_IT, Name: Italian (Italy)
 272.933 +default charset: UTF-8
 272.934 +
 272.935 +OS Locale:  it_IT.UTF-8@euro
 272.936 +default locale: ID: it_IT, Name: Italian (Italy)
 272.937 +display locale: ID: it_IT, Name: Italian (Italy)
 272.938 +format locale: ID: it_IT, Name: Italian (Italy)
 272.939 +default charset: UTF-8
 272.940 +
 272.941 +OS Locale:  ja
 272.942 +default locale: ID: ja_JP, Name: Japanese (Japan)
 272.943 +display locale: ID: ja_JP, Name: Japanese (Japan)
 272.944 +format locale: ID: ja_JP, Name: Japanese (Japan)
 272.945 +default charset: x-eucJP-Open
 272.946 +
 272.947 +OS Locale:  ja_JP.PCK
 272.948 +default locale: ID: ja_JP, Name: Japanese (Japan)
 272.949 +display locale: ID: ja_JP, Name: Japanese (Japan)
 272.950 +format locale: ID: ja_JP, Name: Japanese (Japan)
 272.951 +default charset: x-PCK
 272.952 +
 272.953 +OS Locale:  ja_JP.UTF-8
 272.954 +default locale: ID: ja_JP, Name: Japanese (Japan)
 272.955 +display locale: ID: ja_JP, Name: Japanese (Japan)
 272.956 +format locale: ID: ja_JP, Name: Japanese (Japan)
 272.957 +default charset: UTF-8
 272.958 +
 272.959 +OS Locale:  ja_JP.eucJP
 272.960 +default locale: ID: ja_JP, Name: Japanese (Japan)
 272.961 +display locale: ID: ja_JP, Name: Japanese (Japan)
 272.962 +format locale: ID: ja_JP, Name: Japanese (Japan)
 272.963 +default charset: x-eucJP-Open
 272.964 +
 272.965 +OS Locale:  ko
 272.966 +default locale: ID: ko_KR, Name: Korean (South Korea)
 272.967 +display locale: ID: ko_KR, Name: Korean (South Korea)
 272.968 +format locale: ID: ko_KR, Name: Korean (South Korea)
 272.969 +default charset: EUC-KR
 272.970 +
 272.971 +OS Locale:  ko.UTF-8
 272.972 +default locale: ID: ko_KR, Name: Korean (South Korea)
 272.973 +display locale: ID: ko_KR, Name: Korean (South Korea)
 272.974 +format locale: ID: ko_KR, Name: Korean (South Korea)
 272.975 +default charset: UTF-8
 272.976 +
 272.977 +OS Locale:  ko_KR.EUC
 272.978 +default locale: ID: ko_KR, Name: Korean (South Korea)
 272.979 +display locale: ID: ko_KR, Name: Korean (South Korea)
 272.980 +format locale: ID: ko_KR, Name: Korean (South Korea)
 272.981 +default charset: EUC-KR
 272.982 +
 272.983 +OS Locale:  ko_KR.EUC@dict
 272.984 +default locale: ID: ko_KR, Name: Korean (South Korea)
 272.985 +display locale: ID: ko_KR, Name: Korean (South Korea)
 272.986 +format locale: ID: ko_KR, Name: Korean (South Korea)
 272.987 +default charset: EUC-KR
 272.988 +
 272.989 +OS Locale:  ko_KR.UTF-8
 272.990 +default locale: ID: ko_KR, Name: Korean (South Korea)
 272.991 +display locale: ID: ko_KR, Name: Korean (South Korea)
 272.992 +format locale: ID: ko_KR, Name: Korean (South Korea)
 272.993 +default charset: UTF-8
 272.994 +
 272.995 +OS Locale:  ko_KR.UTF-8@dict
 272.996 +default locale: ID: ko_KR, Name: Korean (South Korea)
 272.997 +display locale: ID: ko_KR, Name: Korean (South Korea)
 272.998 +format locale: ID: ko_KR, Name: Korean (South Korea)
 272.999 +default charset: UTF-8
272.1000 +
272.1001 +OS Locale:  lt
272.1002 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1003 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1004 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1005 +default charset: ISO-8859-13
272.1006 +
272.1007 +OS Locale:  lt_LT
272.1008 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1009 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1010 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1011 +default charset: ISO-8859-13
272.1012 +
272.1013 +OS Locale:  lt_LT.ISO8859-13
272.1014 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1015 +display locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1016 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
272.1017 +default charset: ISO-8859-13
272.1018 +
272.1019 +OS Locale:  lv
272.1020 +default locale: ID: lv_LV, Name: Latvian (Latvia)
272.1021 +display locale: ID: lv_LV, Name: Latvian (Latvia)
272.1022 +format locale: ID: lv_LV, Name: Latvian (Latvia)
272.1023 +default charset: ISO-8859-13
272.1024 +
272.1025 +OS Locale:  lv_LV
272.1026 +default locale: ID: lv_LV, Name: Latvian (Latvia)
272.1027 +display locale: ID: lv_LV, Name: Latvian (Latvia)
272.1028 +format locale: ID: lv_LV, Name: Latvian (Latvia)
272.1029 +default charset: ISO-8859-13
272.1030 +
272.1031 +OS Locale:  lv_LV.ISO8859-13
272.1032 +default locale: ID: lv_LV, Name: Latvian (Latvia)
272.1033 +display locale: ID: lv_LV, Name: Latvian (Latvia)
272.1034 +format locale: ID: lv_LV, Name: Latvian (Latvia)
272.1035 +default charset: ISO-8859-13
272.1036 +
272.1037 +OS Locale:  mk_MK
272.1038 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
272.1039 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
272.1040 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
272.1041 +default charset: ISO-8859-5
272.1042 +
272.1043 +OS Locale:  mk_MK.ISO8859-5
272.1044 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
272.1045 +display locale: ID: mk_MK, Name: Macedonian (Macedonia)
272.1046 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
272.1047 +default charset: ISO-8859-5
272.1048 +
272.1049 +OS Locale:  nl
272.1050 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1051 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1052 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1053 +default charset: ISO-8859-1
272.1054 +
272.1055 +OS Locale:  nl.ISO8859-15
272.1056 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1057 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1058 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1059 +default charset: ISO-8859-15
272.1060 +
272.1061 +OS Locale:  nl_BE
272.1062 +default locale: ID: nl_BE, Name: Dutch (Belgium)
272.1063 +display locale: ID: nl_BE, Name: Dutch (Belgium)
272.1064 +format locale: ID: nl_BE, Name: Dutch (Belgium)
272.1065 +default charset: ISO-8859-1
272.1066 +
272.1067 +OS Locale:  nl_BE.ISO8859-1
272.1068 +default locale: ID: nl_BE, Name: Dutch (Belgium)
272.1069 +display locale: ID: nl_BE, Name: Dutch (Belgium)
272.1070 +format locale: ID: nl_BE, Name: Dutch (Belgium)
272.1071 +default charset: ISO-8859-1
272.1072 +
272.1073 +OS Locale:  nl_BE.ISO8859-15
272.1074 +default locale: ID: nl_BE, Name: Dutch (Belgium)
272.1075 +display locale: ID: nl_BE, Name: Dutch (Belgium)
272.1076 +format locale: ID: nl_BE, Name: Dutch (Belgium)
272.1077 +default charset: ISO-8859-15
272.1078 +
272.1079 +OS Locale:  nl_BE.ISO8859-15@euro
272.1080 +default locale: ID: nl_BE, Name: Dutch (Belgium)
272.1081 +display locale: ID: nl_BE, Name: Dutch (Belgium)
272.1082 +format locale: ID: nl_BE, Name: Dutch (Belgium)
272.1083 +default charset: ISO-8859-15
272.1084 +
272.1085 +OS Locale:  nl_NL
272.1086 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1087 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1088 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1089 +default charset: ISO-8859-1
272.1090 +
272.1091 +OS Locale:  nl_NL.ISO8859-1
272.1092 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1093 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1094 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1095 +default charset: ISO-8859-1
272.1096 +
272.1097 +OS Locale:  nl_NL.ISO8859-15
272.1098 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1099 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1100 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1101 +default charset: ISO-8859-15
272.1102 +
272.1103 +OS Locale:  nl_NL.ISO8859-15@euro
272.1104 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1105 +display locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1106 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
272.1107 +default charset: ISO-8859-15
272.1108 +
272.1109 +OS Locale:  no
272.1110 +default locale: ID: no_NO, Name: Norwegian (Norway)
272.1111 +display locale: ID: no_NO, Name: Norwegian (Norway)
272.1112 +format locale: ID: no_NO, Name: Norwegian (Norway)
272.1113 +default charset: ISO-8859-1
272.1114 +
272.1115 +OS Locale:  no_NO
272.1116 +default locale: ID: no_NO, Name: Norwegian (Norway)
272.1117 +display locale: ID: no_NO, Name: Norwegian (Norway)
272.1118 +format locale: ID: no_NO, Name: Norwegian (Norway)
272.1119 +default charset: ISO-8859-1
272.1120 +
272.1121 +OS Locale:  no_NO.ISO8859-1@bokmal
272.1122 +default locale: ID: no_NO, Name: Norwegian (Norway)
272.1123 +display locale: ID: no_NO, Name: Norwegian (Norway)
272.1124 +format locale: ID: no_NO, Name: Norwegian (Norway)
272.1125 +default charset: ISO-8859-1
272.1126 +
272.1127 +OS Locale:  no_NO.ISO8859-1@nynorsk
272.1128 +default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
272.1129 +display locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
272.1130 +format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
272.1131 +default charset: ISO-8859-1
272.1132 +
272.1133 +OS Locale:  no_NY
272.1134 +default locale: ID: no_, Name: Norwegian ()
272.1135 +display locale: ID: no_, Name: Norwegian ()
272.1136 +format locale: ID: no_, Name: Norwegian ()
272.1137 +default charset: ISO-8859-1
272.1138 +
272.1139 +OS Locale:  nr
272.1140 +default locale: ID: nr, Name: South Ndebele
272.1141 +display locale: ID: nr, Name: South Ndebele
272.1142 +format locale: ID: nr, Name: South Ndebele
272.1143 +default charset: ISO-8859-2
272.1144 +
272.1145 +OS Locale:  pl
272.1146 +default locale: ID: pl_PL, Name: Polish (Poland)
272.1147 +display locale: ID: pl_PL, Name: Polish (Poland)
272.1148 +format locale: ID: pl_PL, Name: Polish (Poland)
272.1149 +default charset: ISO-8859-2
272.1150 +
272.1151 +OS Locale:  pl.UTF-8
272.1152 +default locale: ID: pl_PL, Name: Polish (Poland)
272.1153 +display locale: ID: pl_PL, Name: Polish (Poland)
272.1154 +format locale: ID: pl_PL, Name: Polish (Poland)
272.1155 +default charset: UTF-8
272.1156 +
272.1157 +OS Locale:  pl_PL
272.1158 +default locale: ID: pl_PL, Name: Polish (Poland)
272.1159 +display locale: ID: pl_PL, Name: Polish (Poland)
272.1160 +format locale: ID: pl_PL, Name: Polish (Poland)
272.1161 +default charset: ISO-8859-2
272.1162 +
272.1163 +OS Locale:  pl_PL.ISO8859-2
272.1164 +default locale: ID: pl_PL, Name: Polish (Poland)
272.1165 +display locale: ID: pl_PL, Name: Polish (Poland)
272.1166 +format locale: ID: pl_PL, Name: Polish (Poland)
272.1167 +default charset: ISO-8859-2
272.1168 +
272.1169 +OS Locale:  pl_PL.UTF-8
272.1170 +default locale: ID: pl_PL, Name: Polish (Poland)
272.1171 +display locale: ID: pl_PL, Name: Polish (Poland)
272.1172 +format locale: ID: pl_PL, Name: Polish (Poland)
272.1173 +default charset: UTF-8
272.1174 +
272.1175 +OS Locale:  pt
272.1176 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1177 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1178 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1179 +default charset: ISO-8859-1
272.1180 +
272.1181 +OS Locale:  pt.ISO8859-15
272.1182 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1183 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1184 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1185 +default charset: ISO-8859-15
272.1186 +
272.1187 +OS Locale:  pt_BR
272.1188 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1189 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1190 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1191 +default charset: ISO-8859-1
272.1192 +
272.1193 +OS Locale:  pt_BR.ISO8859-1
272.1194 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1195 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1196 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1197 +default charset: ISO-8859-1
272.1198 +
272.1199 +OS Locale:  pt_BR.UTF-8
272.1200 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1201 +display locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1202 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
272.1203 +default charset: UTF-8
272.1204 +
272.1205 +OS Locale:  pt_PT
272.1206 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1207 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1208 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1209 +default charset: ISO-8859-1
272.1210 +
272.1211 +OS Locale:  pt_PT.ISO8859-1
272.1212 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1213 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1214 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1215 +default charset: ISO-8859-1
272.1216 +
272.1217 +OS Locale:  pt_PT.ISO8859-15
272.1218 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1219 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1220 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1221 +default charset: ISO-8859-15
272.1222 +
272.1223 +OS Locale:  pt_PT.ISO8859-15@euro
272.1224 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1225 +display locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1226 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
272.1227 +default charset: ISO-8859-15
272.1228 +
272.1229 +OS Locale:  ro_RO
272.1230 +default locale: ID: ro_RO, Name: Romanian (Romania)
272.1231 +display locale: ID: ro_RO, Name: Romanian (Romania)
272.1232 +format locale: ID: ro_RO, Name: Romanian (Romania)
272.1233 +default charset: ISO-8859-2
272.1234 +
272.1235 +OS Locale:  ro_RO.ISO8859-2
272.1236 +default locale: ID: ro_RO, Name: Romanian (Romania)
272.1237 +display locale: ID: ro_RO, Name: Romanian (Romania)
272.1238 +format locale: ID: ro_RO, Name: Romanian (Romania)
272.1239 +default charset: ISO-8859-2
272.1240 +
272.1241 +OS Locale:  ru
272.1242 +default locale: ID: ru_RU, Name: Russian (Russia)
272.1243 +display locale: ID: ru_RU, Name: Russian (Russia)
272.1244 +format locale: ID: ru_RU, Name: Russian (Russia)
272.1245 +default charset: ISO-8859-5
272.1246 +
272.1247 +OS Locale:  ru.UTF-8
272.1248 +default locale: ID: ru_RU, Name: Russian (Russia)
272.1249 +display locale: ID: ru_RU, Name: Russian (Russia)
272.1250 +format locale: ID: ru_RU, Name: Russian (Russia)
272.1251 +default charset: UTF-8
272.1252 +
272.1253 +OS Locale:  ru.koi8-r
272.1254 +default locale: ID: ru_RU, Name: Russian (Russia)
272.1255 +display locale: ID: ru_RU, Name: Russian (Russia)
272.1256 +format locale: ID: ru_RU, Name: Russian (Russia)
272.1257 +default charset: KOI8-R
272.1258 +
272.1259 +OS Locale:  ru_RU
272.1260 +default locale: ID: ru_RU, Name: Russian (Russia)
272.1261 +display locale: ID: ru_RU, Name: Russian (Russia)
272.1262 +format locale: ID: ru_RU, Name: Russian (Russia)
272.1263 +default charset: ISO-8859-5
272.1264 +
272.1265 +OS Locale:  ru_RU.ANSI1251
272.1266 +default locale: ID: ru_RU, Name: Russian (Russia)
272.1267 +display locale: ID: ru_RU, Name: Russian (Russia)
272.1268 +format locale: ID: ru_RU, Name: Russian (Russia)
272.1269 +default charset: windows-1251
272.1270 +
272.1271 +OS Locale:  ru_RU.ISO8859-5
272.1272 +default locale: ID: ru_RU, Name: Russian (Russia)
272.1273 +display locale: ID: ru_RU, Name: Russian (Russia)
272.1274 +format locale: ID: ru_RU, Name: Russian (Russia)
272.1275 +default charset: ISO-8859-5
272.1276 +
272.1277 +OS Locale:  ru_RU.KOI8-R
272.1278 +default locale: ID: ru_RU, Name: Russian (Russia)
272.1279 +display locale: ID: ru_RU, Name: Russian (Russia)
272.1280 +format locale: ID: ru_RU, Name: Russian (Russia)
272.1281 +default charset: KOI8-R
272.1282 +
272.1283 +OS Locale:  ru_RU.UTF-8
272.1284 +default locale: ID: ru_RU, Name: Russian (Russia)
272.1285 +display locale: ID: ru_RU, Name: Russian (Russia)
272.1286 +format locale: ID: ru_RU, Name: Russian (Russia)
272.1287 +default charset: UTF-8
272.1288 +
272.1289 +OS Locale:  sh_BA
272.1290 +default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
272.1291 +display locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
272.1292 +format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
272.1293 +default charset: ISO-8859-2
272.1294 +
272.1295 +OS Locale:  sh_BA.ISO8859-2@bosnia
272.1296 +default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
272.1297 +display locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
272.1298 +format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
272.1299 +default charset: ISO-8859-2
272.1300 +
272.1301 +OS Locale:  sk_SK
272.1302 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
272.1303 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
272.1304 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
272.1305 +default charset: ISO-8859-2
272.1306 +
272.1307 +OS Locale:  sk_SK.ISO8859-2
272.1308 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
272.1309 +display locale: ID: sk_SK, Name: Slovak (Slovakia)
272.1310 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
272.1311 +default charset: ISO-8859-2
272.1312 +
272.1313 +OS Locale:  sl_SI
272.1314 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
272.1315 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
272.1316 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
272.1317 +default charset: ISO-8859-2
272.1318 +
272.1319 +OS Locale:  sl_SI.ISO8859-2
272.1320 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
272.1321 +display locale: ID: sl_SI, Name: Slovenian (Slovenia)
272.1322 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
272.1323 +default charset: ISO-8859-2
272.1324 +
272.1325 +OS Locale:  sq_AL
272.1326 +default locale: ID: sq_AL, Name: Albanian (Albania)
272.1327 +display locale: ID: sq_AL, Name: Albanian (Albania)
272.1328 +format locale: ID: sq_AL, Name: Albanian (Albania)
272.1329 +default charset: ISO-8859-2
272.1330 +
272.1331 +OS Locale:  sq_AL.ISO8859-2
272.1332 +default locale: ID: sq_AL, Name: Albanian (Albania)
272.1333 +display locale: ID: sq_AL, Name: Albanian (Albania)
272.1334 +format locale: ID: sq_AL, Name: Albanian (Albania)
272.1335 +default charset: ISO-8859-2
272.1336 +
272.1337 +OS Locale:  sr_SP
272.1338 +default locale: ID: sr, Name: Serbian
272.1339 +display locale: ID: sr, Name: Serbian
272.1340 +format locale: ID: sr, Name: Serbian
272.1341 +default charset: ISO-8859-5
272.1342 +
272.1343 +OS Locale:  sr_YU
272.1344 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
272.1345 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
272.1346 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
272.1347 +default charset: ISO-8859-5
272.1348 +
272.1349 +OS Locale:  sr_YU.ISO8859-5
272.1350 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
272.1351 +display locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
272.1352 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
272.1353 +default charset: ISO-8859-5
272.1354 +
272.1355 +OS Locale:  sv
272.1356 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1357 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1358 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1359 +default charset: ISO-8859-1
272.1360 +
272.1361 +OS Locale:  sv.ISO8859-15
272.1362 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1363 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1364 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1365 +default charset: ISO-8859-15
272.1366 +
272.1367 +OS Locale:  sv.UTF-8
272.1368 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1369 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1370 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1371 +default charset: UTF-8
272.1372 +
272.1373 +OS Locale:  sv_SE
272.1374 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1375 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1376 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1377 +default charset: ISO-8859-1
272.1378 +
272.1379 +OS Locale:  sv_SE.ISO8859-1
272.1380 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1381 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1382 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1383 +default charset: ISO-8859-1
272.1384 +
272.1385 +OS Locale:  sv_SE.ISO8859-15
272.1386 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1387 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1388 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1389 +default charset: ISO-8859-15
272.1390 +
272.1391 +OS Locale:  sv_SE.ISO8859-15@euro
272.1392 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1393 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1394 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1395 +default charset: ISO-8859-15
272.1396 +
272.1397 +OS Locale:  sv_SE.UTF-8
272.1398 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1399 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1400 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1401 +default charset: UTF-8
272.1402 +
272.1403 +OS Locale:  sv_SE.UTF-8@euro
272.1404 +default locale: ID: sv_SE, Name: Swedish (Sweden)
272.1405 +display locale: ID: sv_SE, Name: Swedish (Sweden)
272.1406 +format locale: ID: sv_SE, Name: Swedish (Sweden)
272.1407 +default charset: UTF-8
272.1408 +
272.1409 +OS Locale:  th
272.1410 +default locale: ID: th_TH, Name: Thai (Thailand)
272.1411 +display locale: ID: th_TH, Name: Thai (Thailand)
272.1412 +format locale: ID: th_TH, Name: Thai (Thailand)
272.1413 +default charset: TIS-620
272.1414 +
272.1415 +OS Locale:  th_TH
272.1416 +default locale: ID: th_TH, Name: Thai (Thailand)
272.1417 +display locale: ID: th_TH, Name: Thai (Thailand)
272.1418 +format locale: ID: th_TH, Name: Thai (Thailand)
272.1419 +default charset: TIS-620
272.1420 +
272.1421 +OS Locale:  th_TH.ISO8859-11
272.1422 +default locale: ID: th_TH, Name: Thai (Thailand)
272.1423 +display locale: ID: th_TH, Name: Thai (Thailand)
272.1424 +format locale: ID: th_TH, Name: Thai (Thailand)
272.1425 +default charset: TIS-620
272.1426 +
272.1427 +OS Locale:  th_TH.TIS620
272.1428 +default locale: ID: th_TH, Name: Thai (Thailand)
272.1429 +display locale: ID: th_TH, Name: Thai (Thailand)
272.1430 +format locale: ID: th_TH, Name: Thai (Thailand)
272.1431 +default charset: TIS-620
272.1432 +
272.1433 +OS Locale:  th_TH.UTF-8
272.1434 +default locale: ID: th_TH, Name: Thai (Thailand)
272.1435 +display locale: ID: th_TH, Name: Thai (Thailand)
272.1436 +format locale: ID: th_TH, Name: Thai (Thailand)
272.1437 +default charset: UTF-8
272.1438 +
272.1439 +OS Locale:  tr
272.1440 +default locale: ID: tr_TR, Name: Turkish (Turkey)
272.1441 +display locale: ID: tr_TR, Name: Turkish (Turkey)
272.1442 +format locale: ID: tr_TR, Name: Turkish (Turkey)
272.1443 +default charset: ISO-8859-9
272.1444 +
272.1445 +OS Locale:  tr_TR
272.1446 +default locale: ID: tr_TR, Name: Turkish (Turkey)
272.1447 +display locale: ID: tr_TR, Name: Turkish (Turkey)
272.1448 +format locale: ID: tr_TR, Name: Turkish (Turkey)
272.1449 +default charset: ISO-8859-9
272.1450 +
272.1451 +OS Locale:  tr_TR.ISO8859-9
272.1452 +default locale: ID: tr_TR, Name: Turkish (Turkey)
272.1453 +display locale: ID: tr_TR, Name: Turkish (Turkey)
272.1454 +format locale: ID: tr_TR, Name: Turkish (Turkey)
272.1455 +default charset: ISO-8859-9
272.1456 +
272.1457 +OS Locale:  tr_TR.UTF-8
272.1458 +default locale: ID: tr_TR, Name: Turkish (Turkey)
272.1459 +display locale: ID: tr_TR, Name: Turkish (Turkey)
272.1460 +format locale: ID: tr_TR, Name: Turkish (Turkey)
272.1461 +default charset: UTF-8
272.1462 +
272.1463 +OS Locale:  zh
272.1464 +default locale: ID: zh_CN, Name: Chinese (China)
272.1465 +display locale: ID: zh_CN, Name: Chinese (China)
272.1466 +format locale: ID: zh_CN, Name: Chinese (China)
272.1467 +default charset: GB2312
272.1468 +
272.1469 +OS Locale:  zh.GBK
272.1470 +default locale: ID: zh_CN, Name: Chinese (China)
272.1471 +display locale: ID: zh_CN, Name: Chinese (China)
272.1472 +format locale: ID: zh_CN, Name: Chinese (China)
272.1473 +default charset: GBK
272.1474 +
272.1475 +OS Locale:  zh.UTF-8
272.1476 +default locale: ID: zh_CN, Name: Chinese (China)
272.1477 +display locale: ID: zh_CN, Name: Chinese (China)
272.1478 +format locale: ID: zh_CN, Name: Chinese (China)
272.1479 +default charset: UTF-8
272.1480 +
272.1481 +OS Locale:  zh_CN.EUC
272.1482 +default locale: ID: zh_CN, Name: Chinese (China)
272.1483 +display locale: ID: zh_CN, Name: Chinese (China)
272.1484 +format locale: ID: zh_CN, Name: Chinese (China)
272.1485 +default charset: GB2312
272.1486 +
272.1487 +OS Locale:  zh_CN.EUC@pinyin
272.1488 +default locale: ID: zh_CN, Name: Chinese (China)
272.1489 +display locale: ID: zh_CN, Name: Chinese (China)
272.1490 +format locale: ID: zh_CN, Name: Chinese (China)
272.1491 +default charset: GB2312
272.1492 +
272.1493 +OS Locale:  zh_CN.EUC@radical
272.1494 +default locale: ID: zh_CN, Name: Chinese (China)
272.1495 +display locale: ID: zh_CN, Name: Chinese (China)
272.1496 +format locale: ID: zh_CN, Name: Chinese (China)
272.1497 +default charset: GB2312
272.1498 +
272.1499 +OS Locale:  zh_CN.EUC@stroke
272.1500 +default locale: ID: zh_CN, Name: Chinese (China)
272.1501 +display locale: ID: zh_CN, Name: Chinese (China)
272.1502 +format locale: ID: zh_CN, Name: Chinese (China)
272.1503 +default charset: GB2312
272.1504 +
272.1505 +OS Locale:  zh_CN.GB18030
272.1506 +default locale: ID: zh_CN, Name: Chinese (China)
272.1507 +display locale: ID: zh_CN, Name: Chinese (China)
272.1508 +format locale: ID: zh_CN, Name: Chinese (China)
272.1509 +default charset: GB18030
272.1510 +
272.1511 +OS Locale:  zh_CN.GB18030@pinyin
272.1512 +default locale: ID: zh_CN, Name: Chinese (China)
272.1513 +display locale: ID: zh_CN, Name: Chinese (China)
272.1514 +format locale: ID: zh_CN, Name: Chinese (China)
272.1515 +default charset: GB18030
272.1516 +
272.1517 +OS Locale:  zh_CN.GB18030@radical
272.1518 +default locale: ID: zh_CN, Name: Chinese (China)
272.1519 +display locale: ID: zh_CN, Name: Chinese (China)
272.1520 +format locale: ID: zh_CN, Name: Chinese (China)
272.1521 +default charset: GB18030
272.1522 +
272.1523 +OS Locale:  zh_CN.GB18030@stroke
272.1524 +default locale: ID: zh_CN, Name: Chinese (China)
272.1525 +display locale: ID: zh_CN, Name: Chinese (China)
272.1526 +format locale: ID: zh_CN, Name: Chinese (China)
272.1527 +default charset: GB18030
272.1528 +
272.1529 +OS Locale:  zh_CN.GBK
272.1530 +default locale: ID: zh_CN, Name: Chinese (China)
272.1531 +display locale: ID: zh_CN, Name: Chinese (China)
272.1532 +format locale: ID: zh_CN, Name: Chinese (China)
272.1533 +default charset: GBK
272.1534 +
272.1535 +OS Locale:  zh_CN.GBK@pinyin
272.1536 +default locale: ID: zh_CN, Name: Chinese (China)
272.1537 +display locale: ID: zh_CN, Name: Chinese (China)
272.1538 +format locale: ID: zh_CN, Name: Chinese (China)
272.1539 +default charset: GBK
272.1540 +
272.1541 +OS Locale:  zh_CN.GBK@radical
272.1542 +default locale: ID: zh_CN, Name: Chinese (China)
272.1543 +display locale: ID: zh_CN, Name: Chinese (China)
272.1544 +format locale: ID: zh_CN, Name: Chinese (China)
272.1545 +default charset: GBK
272.1546 +
272.1547 +OS Locale:  zh_CN.GBK@stroke
272.1548 +default locale: ID: zh_CN, Name: Chinese (China)
272.1549 +display locale: ID: zh_CN, Name: Chinese (China)
272.1550 +format locale: ID: zh_CN, Name: Chinese (China)
272.1551 +default charset: GBK
272.1552 +
272.1553 +OS Locale:  zh_CN.UTF-8
272.1554 +default locale: ID: zh_CN, Name: Chinese (China)
272.1555 +display locale: ID: zh_CN, Name: Chinese (China)
272.1556 +format locale: ID: zh_CN, Name: Chinese (China)
272.1557 +default charset: UTF-8
272.1558 +
272.1559 +OS Locale:  zh_CN.UTF-8@pinyin
272.1560 +default locale: ID: zh_CN, Name: Chinese (China)
272.1561 +display locale: ID: zh_CN, Name: Chinese (China)
272.1562 +format locale: ID: zh_CN, Name: Chinese (China)
272.1563 +default charset: UTF-8
272.1564 +
272.1565 +OS Locale:  zh_CN.UTF-8@radical
272.1566 +default locale: ID: zh_CN, Name: Chinese (China)
272.1567 +display locale: ID: zh_CN, Name: Chinese (China)
272.1568 +format locale: ID: zh_CN, Name: Chinese (China)
272.1569 +default charset: UTF-8
272.1570 +
272.1571 +OS Locale:  zh_CN.UTF-8@stroke
272.1572 +default locale: ID: zh_CN, Name: Chinese (China)
272.1573 +display locale: ID: zh_CN, Name: Chinese (China)
272.1574 +format locale: ID: zh_CN, Name: Chinese (China)
272.1575 +default charset: UTF-8
272.1576 +
272.1577 +OS Locale:  zh_HK.BIG5HK
272.1578 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1579 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1580 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1581 +default charset: x-Big5-HKSCS-2001
272.1582 +
272.1583 +OS Locale:  zh_HK.BIG5HK@radical
272.1584 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1585 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1586 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1587 +default charset: x-Big5-HKSCS-2001
272.1588 +
272.1589 +OS Locale:  zh_HK.BIG5HK@stroke
272.1590 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1591 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1592 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1593 +default charset: x-Big5-HKSCS-2001
272.1594 +
272.1595 +OS Locale:  zh_HK.UTF-8
272.1596 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1597 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1598 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1599 +default charset: UTF-8
272.1600 +
272.1601 +OS Locale:  zh_HK.UTF-8@radical
272.1602 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1603 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1604 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1605 +default charset: UTF-8
272.1606 +
272.1607 +OS Locale:  zh_HK.UTF-8@stroke
272.1608 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1609 +display locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1610 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
272.1611 +default charset: UTF-8
272.1612 +
272.1613 +OS Locale:  zh_TW
272.1614 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1615 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1616 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1617 +default charset: x-EUC-TW
272.1618 +
272.1619 +OS Locale:  zh_TW.BIG5
272.1620 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1621 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1622 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1623 +default charset: x-Big5-Solaris
272.1624 +
272.1625 +OS Locale:  zh_TW.BIG5@pinyin
272.1626 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1627 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1628 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1629 +default charset: x-Big5-Solaris
272.1630 +
272.1631 +OS Locale:  zh_TW.BIG5@radical
272.1632 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1633 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1634 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1635 +default charset: x-Big5-Solaris
272.1636 +
272.1637 +OS Locale:  zh_TW.BIG5@stroke
272.1638 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1639 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1640 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1641 +default charset: x-Big5-Solaris
272.1642 +
272.1643 +OS Locale:  zh_TW.BIG5@zhuyin
272.1644 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1645 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1646 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1647 +default charset: x-Big5-Solaris
272.1648 +
272.1649 +OS Locale:  zh_TW.EUC
272.1650 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1651 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1652 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1653 +default charset: x-EUC-TW
272.1654 +
272.1655 +OS Locale:  zh_TW.EUC@pinyin
272.1656 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1657 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1658 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1659 +default charset: x-EUC-TW
272.1660 +
272.1661 +OS Locale:  zh_TW.EUC@radical
272.1662 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1663 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1664 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1665 +default charset: x-EUC-TW
272.1666 +
272.1667 +OS Locale:  zh_TW.EUC@stroke
272.1668 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1669 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1670 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1671 +default charset: x-EUC-TW
272.1672 +
272.1673 +OS Locale:  zh_TW.EUC@zhuyin
272.1674 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1675 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1676 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1677 +default charset: x-EUC-TW
272.1678 +
272.1679 +OS Locale:  zh_TW.UTF-8
272.1680 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1681 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1682 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1683 +default charset: UTF-8
272.1684 +
272.1685 +OS Locale:  zh_TW.UTF-8@pinyin
272.1686 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1687 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1688 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1689 +default charset: UTF-8
272.1690 +
272.1691 +OS Locale:  zh_TW.UTF-8@radical
272.1692 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1693 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1694 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1695 +default charset: UTF-8
272.1696 +
272.1697 +OS Locale:  zh_TW.UTF-8@stroke
272.1698 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1699 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1700 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1701 +default charset: UTF-8
272.1702 +
272.1703 +OS Locale:  zh_TW.UTF-8@zhuyin
272.1704 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1705 +display locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1706 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
272.1707 +default charset: UTF-8
272.1708 +
272.1709 +Testing some typical combinations
272.1710 +
272.1711 +
272.1712 +OS Locale (LC_CTYPE: ja_JP.UTF-8, LC_MESSAGES: zh_CN.UTF-8)
272.1713 +default locale: ID: ja_JP, Name: Japanese (Japan)
272.1714 +display locale: ID: zh_CN, Name: Chinese (China)
272.1715 +format locale: ID: ja_JP, Name: Japanese (Japan)
272.1716 +default charset: UTF-8
272.1717 +
272.1718 +OS Locale (LC_CTYPE: zh_CN.UTF-8, LC_MESSAGES: en_US.UTF-8)
272.1719 +default locale: ID: zh_CN, Name: Chinese (China)
272.1720 +display locale: ID: en_US, Name: English (United States)
272.1721 +format locale: ID: zh_CN, Name: Chinese (China)
272.1722 +default charset: UTF-8
272.1723 +
272.1724 +OS Locale (LC_CTYPE: C, LC_MESSAGES: zh_CN.UTF-8)
272.1725 +default locale: ID: en, Name: English
272.1726 +display locale: ID: zh_CN, Name: Chinese (China)
272.1727 +format locale: ID: en, Name: English
272.1728 +default charset: US-ASCII
   273.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   273.2 +++ b/test/java/util/Locale/data/deflocale.win7	Fri Sep 24 16:41:32 2010 -0700
   273.3 @@ -0,0 +1,1494 @@
   273.4 +# OSVersionInfo
   273.5 +# MajorVersion: 6
   273.6 +# MinorVersion: 1
   273.7 +# BuildNumber: 7600
   273.8 +# CSDVersion: 
   273.9 +
  273.10 +
  273.11 +OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
  273.12 +default locale: ID: en_US, Name: English (United States)
  273.13 +display locale: ID: en_US, Name: English (United States)
  273.14 +format locale: ID: en_US, Name: English (United States)
  273.15 +default charset: windows-1252
  273.16 +
  273.17 +OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
  273.18 +default locale: ID: en_US, Name: English (United States)
  273.19 +display locale: ID: en_US, Name: English (United States)
  273.20 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  273.21 +default charset: windows-1252
  273.22 +
  273.23 +OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
  273.24 +default locale: ID: en_US, Name: English (United States)
  273.25 +display locale: ID: en_US, Name: English (United States)
  273.26 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  273.27 +default charset: windows-1252
  273.28 +
  273.29 +OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
  273.30 +default locale: ID: en_US, Name: English (United States)
  273.31 +display locale: ID: en_US, Name: English (United States)
  273.32 +format locale: ID: ca_ES, Name: Catalan (Spain)
  273.33 +default charset: windows-1252
  273.34 +
  273.35 +OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
  273.36 +default locale: ID: en_US, Name: English (United States)
  273.37 +display locale: ID: en_US, Name: English (United States)
  273.38 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
  273.39 +default charset: windows-1252
  273.40 +
  273.41 +OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
  273.42 +default locale: ID: en_US, Name: English (United States)
  273.43 +display locale: ID: en_US, Name: English (United States)
  273.44 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
  273.45 +default charset: windows-1252
  273.46 +
  273.47 +OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
  273.48 +default locale: ID: en_US, Name: English (United States)
  273.49 +display locale: ID: en_US, Name: English (United States)
  273.50 +format locale: ID: da_DK, Name: Danish (Denmark)
  273.51 +default charset: windows-1252
  273.52 +
  273.53 +OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
  273.54 +default locale: ID: en_US, Name: English (United States)
  273.55 +display locale: ID: en_US, Name: English (United States)
  273.56 +format locale: ID: de_DE, Name: German (Germany)
  273.57 +default charset: windows-1252
  273.58 +
  273.59 +OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
  273.60 +default locale: ID: en_US, Name: English (United States)
  273.61 +display locale: ID: en_US, Name: English (United States)
  273.62 +format locale: ID: el_GR, Name: Greek (Greece)
  273.63 +default charset: windows-1252
  273.64 +
  273.65 +OS Locale (lcid: 409, name: en-US): English (United States) - 1252
  273.66 +default locale: ID: en_US, Name: English (United States)
  273.67 +display locale: ID: en_US, Name: English (United States)
  273.68 +format locale: ID: en_US, Name: English (United States)
  273.69 +default charset: windows-1252
  273.70 +
  273.71 +OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
  273.72 +default locale: ID: en_US, Name: English (United States)
  273.73 +display locale: ID: en_US, Name: English (United States)
  273.74 +format locale: ID: fi_FI, Name: Finnish (Finland)
  273.75 +default charset: windows-1252
  273.76 +
  273.77 +OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
  273.78 +default locale: ID: en_US, Name: English (United States)
  273.79 +display locale: ID: en_US, Name: English (United States)
  273.80 +format locale: ID: fr_FR, Name: French (France)
  273.81 +default charset: windows-1252
  273.82 +
  273.83 +OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
  273.84 +default locale: ID: en_US, Name: English (United States)
  273.85 +display locale: ID: en_US, Name: English (United States)
  273.86 +format locale: ID: iw_IL, Name: Hebrew (Israel)
  273.87 +default charset: windows-1252
  273.88 +
  273.89 +OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
  273.90 +default locale: ID: en_US, Name: English (United States)
  273.91 +display locale: ID: en_US, Name: English (United States)
  273.92 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
  273.93 +default charset: windows-1252
  273.94 +
  273.95 +OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
  273.96 +default locale: ID: en_US, Name: English (United States)
  273.97 +display locale: ID: en_US, Name: English (United States)
  273.98 +format locale: ID: is_IS, Name: Icelandic (Iceland)
  273.99 +default charset: windows-1252
 273.100 +
 273.101 +OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
 273.102 +default locale: ID: en_US, Name: English (United States)
 273.103 +display locale: ID: en_US, Name: English (United States)
 273.104 +format locale: ID: it_IT, Name: Italian (Italy)
 273.105 +default charset: windows-1252
 273.106 +
 273.107 +OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
 273.108 +default locale: ID: en_US, Name: English (United States)
 273.109 +display locale: ID: en_US, Name: English (United States)
 273.110 +format locale: ID: ja_JP, Name: Japanese (Japan)
 273.111 +default charset: windows-1252
 273.112 +
 273.113 +OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
 273.114 +default locale: ID: en_US, Name: English (United States)
 273.115 +display locale: ID: en_US, Name: English (United States)
 273.116 +format locale: ID: ko_KR, Name: Korean (South Korea)
 273.117 +default charset: windows-1252
 273.118 +
 273.119 +OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
 273.120 +default locale: ID: en_US, Name: English (United States)
 273.121 +display locale: ID: en_US, Name: English (United States)
 273.122 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
 273.123 +default charset: windows-1252
 273.124 +
 273.125 +OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokmål) (Norway) - 1252
 273.126 +default locale: ID: en_US, Name: English (United States)
 273.127 +display locale: ID: en_US, Name: English (United States)
 273.128 +format locale: ID: no_NO, Name: Norwegian (Norway)
 273.129 +default charset: windows-1252
 273.130 +
 273.131 +OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
 273.132 +default locale: ID: en_US, Name: English (United States)
 273.133 +display locale: ID: en_US, Name: English (United States)
 273.134 +format locale: ID: pl_PL, Name: Polish (Poland)
 273.135 +default charset: windows-1252
 273.136 +
 273.137 +OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
 273.138 +default locale: ID: en_US, Name: English (United States)
 273.139 +display locale: ID: en_US, Name: English (United States)
 273.140 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
 273.141 +default charset: windows-1252
 273.142 +
 273.143 +OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
 273.144 +default locale: ID: en_US, Name: English (United States)
 273.145 +display locale: ID: en_US, Name: English (United States)
 273.146 +format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
 273.147 +default charset: windows-1252
 273.148 +
 273.149 +OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
 273.150 +default locale: ID: en_US, Name: English (United States)
 273.151 +display locale: ID: en_US, Name: English (United States)
 273.152 +format locale: ID: ro_RO, Name: Romanian (Romania)
 273.153 +default charset: windows-1252
 273.154 +
 273.155 +OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
 273.156 +default locale: ID: en_US, Name: English (United States)
 273.157 +display locale: ID: en_US, Name: English (United States)
 273.158 +format locale: ID: ru_RU, Name: Russian (Russia)
 273.159 +default charset: windows-1252
 273.160 +
 273.161 +OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
 273.162 +default locale: ID: en_US, Name: English (United States)
 273.163 +display locale: ID: en_US, Name: English (United States)
 273.164 +format locale: ID: hr_HR, Name: Croatian (Croatia)
 273.165 +default charset: windows-1252
 273.166 +
 273.167 +OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
 273.168 +default locale: ID: en_US, Name: English (United States)
 273.169 +display locale: ID: en_US, Name: English (United States)
 273.170 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
 273.171 +default charset: windows-1252
 273.172 +
 273.173 +OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
 273.174 +default locale: ID: en_US, Name: English (United States)
 273.175 +display locale: ID: en_US, Name: English (United States)
 273.176 +format locale: ID: sq_AL, Name: Albanian (Albania)
 273.177 +default charset: windows-1252
 273.178 +
 273.179 +OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
 273.180 +default locale: ID: en_US, Name: English (United States)
 273.181 +display locale: ID: en_US, Name: English (United States)
 273.182 +format locale: ID: sv_SE, Name: Swedish (Sweden)
 273.183 +default charset: windows-1252
 273.184 +
 273.185 +OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
 273.186 +default locale: ID: en_US, Name: English (United States)
 273.187 +display locale: ID: en_US, Name: English (United States)
 273.188 +format locale: ID: th_TH, Name: Thai (Thailand)
 273.189 +default charset: windows-1252
 273.190 +
 273.191 +OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
 273.192 +default locale: ID: en_US, Name: English (United States)
 273.193 +display locale: ID: en_US, Name: English (United States)
 273.194 +format locale: ID: tr_TR, Name: Turkish (Turkey)
 273.195 +default charset: windows-1252
 273.196 +
 273.197 +OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
 273.198 +default locale: ID: en_US, Name: English (United States)
 273.199 +display locale: ID: en_US, Name: English (United States)
 273.200 +format locale: ID: ur_PK, Name: Urdu (Pakistan)
 273.201 +default charset: windows-1252
 273.202 +
 273.203 +OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
 273.204 +default locale: ID: en_US, Name: English (United States)
 273.205 +display locale: ID: en_US, Name: English (United States)
 273.206 +format locale: ID: in_ID, Name: Indonesian (Indonesia)
 273.207 +default charset: windows-1252
 273.208 +
 273.209 +OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
 273.210 +default locale: ID: en_US, Name: English (United States)
 273.211 +display locale: ID: en_US, Name: English (United States)
 273.212 +format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
 273.213 +default charset: windows-1252
 273.214 +
 273.215 +OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
 273.216 +default locale: ID: en_US, Name: English (United States)
 273.217 +display locale: ID: en_US, Name: English (United States)
 273.218 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 273.219 +default charset: windows-1252
 273.220 +
 273.221 +OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
 273.222 +default locale: ID: en_US, Name: English (United States)
 273.223 +display locale: ID: en_US, Name: English (United States)
 273.224 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
 273.225 +default charset: windows-1252
 273.226 +
 273.227 +OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
 273.228 +default locale: ID: en_US, Name: English (United States)
 273.229 +display locale: ID: en_US, Name: English (United States)
 273.230 +format locale: ID: et_EE, Name: Estonian (Estonia)
 273.231 +default charset: windows-1252
 273.232 +
 273.233 +OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
 273.234 +default locale: ID: en_US, Name: English (United States)
 273.235 +display locale: ID: en_US, Name: English (United States)
 273.236 +format locale: ID: lv_LV, Name: Latvian (Latvia)
 273.237 +default charset: windows-1252
 273.238 +
 273.239 +OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
 273.240 +default locale: ID: en_US, Name: English (United States)
 273.241 +display locale: ID: en_US, Name: English (United States)
 273.242 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
 273.243 +default charset: windows-1252
 273.244 +
 273.245 +OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
 273.246 +default locale: ID: en_US, Name: English (United States)
 273.247 +display locale: ID: en_US, Name: English (United States)
 273.248 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
 273.249 +default charset: windows-1252
 273.250 +
 273.251 +OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
 273.252 +default locale: ID: en_US, Name: English (United States)
 273.253 +display locale: ID: en_US, Name: English (United States)
 273.254 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
 273.255 +default charset: windows-1252
 273.256 +
 273.257 +OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
 273.258 +default locale: ID: en_US, Name: English (United States)
 273.259 +display locale: ID: en_US, Name: English (United States)
 273.260 +format locale: ID: fa_IR, Name: Persian (Iran)
 273.261 +default charset: windows-1252
 273.262 +
 273.263 +OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
 273.264 +default locale: ID: en_US, Name: English (United States)
 273.265 +display locale: ID: en_US, Name: English (United States)
 273.266 +format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
 273.267 +default charset: windows-1252
 273.268 +
 273.269 +OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
 273.270 +default locale: ID: en_US, Name: English (United States)
 273.271 +display locale: ID: en_US, Name: English (United States)
 273.272 +format locale: ID: hy_AM, Name: Armenian (Armenia)
 273.273 +default charset: windows-1252
 273.274 +
 273.275 +OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
 273.276 +default locale: ID: en_US, Name: English (United States)
 273.277 +display locale: ID: en_US, Name: English (United States)
 273.278 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 273.279 +default charset: windows-1252
 273.280 +
 273.281 +OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
 273.282 +default locale: ID: en_US, Name: English (United States)
 273.283 +display locale: ID: en_US, Name: English (United States)
 273.284 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 273.285 +default charset: windows-1252
 273.286 +
 273.287 +OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
 273.288 +default locale: ID: en_US, Name: English (United States)
 273.289 +display locale: ID: en_US, Name: English (United States)
 273.290 +format locale: ID: eu_ES, Name: Basque (Spain)
 273.291 +default charset: windows-1252
 273.292 +
 273.293 +OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
 273.294 +default locale: ID: en_US, Name: English (United States)
 273.295 +display locale: ID: en_US, Name: English (United States)
 273.296 +format locale: ID: en_US, Name: English (United States)
 273.297 +default charset: windows-1252
 273.298 +
 273.299 +OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
 273.300 +default locale: ID: en_US, Name: English (United States)
 273.301 +display locale: ID: en_US, Name: English (United States)
 273.302 +format locale: ID: en_US, Name: English (United States)
 273.303 +default charset: windows-1252
 273.304 +
 273.305 +OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
 273.306 +default locale: ID: en_US, Name: English (United States)
 273.307 +display locale: ID: en_US, Name: English (United States)
 273.308 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
 273.309 +default charset: windows-1252
 273.310 +
 273.311 +OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
 273.312 +default locale: ID: en_US, Name: English (United States)
 273.313 +display locale: ID: en_US, Name: English (United States)
 273.314 +format locale: ID: tn_ZA, Name: Tswana (South Africa)
 273.315 +default charset: windows-1252
 273.316 +
 273.317 +OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
 273.318 +default locale: ID: en_US, Name: English (United States)
 273.319 +display locale: ID: en_US, Name: English (United States)
 273.320 +format locale: ID: xh_ZA, Name: Xhosa (South Africa)
 273.321 +default charset: windows-1252
 273.322 +
 273.323 +OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
 273.324 +default locale: ID: en_US, Name: English (United States)
 273.325 +display locale: ID: en_US, Name: English (United States)
 273.326 +format locale: ID: zu_ZA, Name: Zulu (South Africa)
 273.327 +default charset: windows-1252
 273.328 +
 273.329 +OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
 273.330 +default locale: ID: en_US, Name: English (United States)
 273.331 +display locale: ID: en_US, Name: English (United States)
 273.332 +format locale: ID: af_ZA, Name: Afrikaans (South Africa)
 273.333 +default charset: windows-1252
 273.334 +
 273.335 +OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
 273.336 +default locale: ID: en_US, Name: English (United States)
 273.337 +display locale: ID: en_US, Name: English (United States)
 273.338 +format locale: ID: ka_GE, Name: Georgian (Georgia)
 273.339 +default charset: windows-1252
 273.340 +
 273.341 +OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
 273.342 +default locale: ID: en_US, Name: English (United States)
 273.343 +display locale: ID: en_US, Name: English (United States)
 273.344 +format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
 273.345 +default charset: windows-1252
 273.346 +
 273.347 +OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
 273.348 +default locale: ID: en_US, Name: English (United States)
 273.349 +display locale: ID: en_US, Name: English (United States)
 273.350 +format locale: ID: hi_IN, Name: Hindi (India)
 273.351 +default charset: windows-1252
 273.352 +
 273.353 +OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
 273.354 +default locale: ID: en_US, Name: English (United States)
 273.355 +display locale: ID: en_US, Name: English (United States)
 273.356 +format locale: ID: mt_MT, Name: Maltese (Malta)
 273.357 +default charset: windows-1252
 273.358 +
 273.359 +OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
 273.360 +default locale: ID: en_US, Name: English (United States)
 273.361 +display locale: ID: en_US, Name: English (United States)
 273.362 +format locale: ID: se_NO, Name: Northern Sami (Norway)
 273.363 +default charset: windows-1252
 273.364 +
 273.365 +OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
 273.366 +default locale: ID: en_US, Name: English (United States)
 273.367 +display locale: ID: en_US, Name: English (United States)
 273.368 +format locale: ID: ms_MY, Name: Malay (Malaysia)
 273.369 +default charset: windows-1252
 273.370 +
 273.371 +OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
 273.372 +default locale: ID: en_US, Name: English (United States)
 273.373 +display locale: ID: en_US, Name: English (United States)
 273.374 +format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
 273.375 +default charset: windows-1252
 273.376 +
 273.377 +OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
 273.378 +default locale: ID: en_US, Name: English (United States)
 273.379 +display locale: ID: en_US, Name: English (United States)
 273.380 +format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
 273.381 +default charset: windows-1252
 273.382 +
 273.383 +OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
 273.384 +default locale: ID: en_US, Name: English (United States)
 273.385 +display locale: ID: en_US, Name: English (United States)
 273.386 +format locale: ID: sw_KE, Name: Swahili (Kenya)
 273.387 +default charset: windows-1252
 273.388 +
 273.389 +OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
 273.390 +default locale: ID: en_US, Name: English (United States)
 273.391 +display locale: ID: en_US, Name: English (United States)
 273.392 +format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
 273.393 +default charset: windows-1252
 273.394 +
 273.395 +OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
 273.396 +default locale: ID: en_US, Name: English (United States)
 273.397 +display locale: ID: en_US, Name: English (United States)
 273.398 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 273.399 +default charset: windows-1252
 273.400 +
 273.401 +OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
 273.402 +default locale: ID: en_US, Name: English (United States)
 273.403 +display locale: ID: en_US, Name: English (United States)
 273.404 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 273.405 +default charset: windows-1252
 273.406 +
 273.407 +OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
 273.408 +default locale: ID: en_US, Name: English (United States)
 273.409 +display locale: ID: en_US, Name: English (United States)
 273.410 +format locale: ID: tt_RU, Name: Tatar (Russia)
 273.411 +default charset: windows-1252
 273.412 +
 273.413 +OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
 273.414 +default locale: ID: en_US, Name: English (United States)
 273.415 +display locale: ID: en_US, Name: English (United States)
 273.416 +format locale: ID: bn_IN, Name: Bengali (India)
 273.417 +default charset: windows-1252
 273.418 +
 273.419 +OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
 273.420 +default locale: ID: en_US, Name: English (United States)
 273.421 +display locale: ID: en_US, Name: English (United States)
 273.422 +format locale: ID: pa_IN, Name: Panjabi (India)
 273.423 +default charset: windows-1252
 273.424 +
 273.425 +OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
 273.426 +default locale: ID: en_US, Name: English (United States)
 273.427 +display locale: ID: en_US, Name: English (United States)
 273.428 +format locale: ID: gu_IN, Name: Gujarati (India)
 273.429 +default charset: windows-1252
 273.430 +
 273.431 +OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
 273.432 +default locale: ID: en_US, Name: English (United States)
 273.433 +display locale: ID: en_US, Name: English (United States)
 273.434 +format locale: ID: or_IN, Name: Oriya (India)
 273.435 +default charset: windows-1252
 273.436 +
 273.437 +OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
 273.438 +default locale: ID: en_US, Name: English (United States)
 273.439 +display locale: ID: en_US, Name: English (United States)
 273.440 +format locale: ID: ta_IN, Name: Tamil (India)
 273.441 +default charset: windows-1252
 273.442 +
 273.443 +OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
 273.444 +default locale: ID: en_US, Name: English (United States)
 273.445 +display locale: ID: en_US, Name: English (United States)
 273.446 +format locale: ID: te_IN, Name: Telugu (India)
 273.447 +default charset: windows-1252
 273.448 +
 273.449 +OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
 273.450 +default locale: ID: en_US, Name: English (United States)
 273.451 +display locale: ID: en_US, Name: English (United States)
 273.452 +format locale: ID: kn_IN, Name: Kannada (India)
 273.453 +default charset: windows-1252
 273.454 +
 273.455 +OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
 273.456 +default locale: ID: en_US, Name: English (United States)
 273.457 +display locale: ID: en_US, Name: English (United States)
 273.458 +format locale: ID: ml_IN, Name: Malayalam (India)
 273.459 +default charset: windows-1252
 273.460 +
 273.461 +OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
 273.462 +default locale: ID: en_US, Name: English (United States)
 273.463 +display locale: ID: en_US, Name: English (United States)
 273.464 +format locale: ID: as_IN, Name: Assamese (India)
 273.465 +default charset: windows-1252
 273.466 +
 273.467 +OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
 273.468 +default locale: ID: en_US, Name: English (United States)
 273.469 +display locale: ID: en_US, Name: English (United States)
 273.470 +format locale: ID: mr_IN, Name: Marathi (India)
 273.471 +default charset: windows-1252
 273.472 +
 273.473 +OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
 273.474 +default locale: ID: en_US, Name: English (United States)
 273.475 +display locale: ID: en_US, Name: English (United States)
 273.476 +format locale: ID: sa_IN, Name: Sanskrit (India)
 273.477 +default charset: windows-1252
 273.478 +
 273.479 +OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
 273.480 +default locale: ID: en_US, Name: English (United States)
 273.481 +display locale: ID: en_US, Name: English (United States)
 273.482 +format locale: ID: mn_MN, Name: Mongolian (Mongolia)
 273.483 +default charset: windows-1252
 273.484 +
 273.485 +OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
 273.486 +default locale: ID: en_US, Name: English (United States)
 273.487 +display locale: ID: en_US, Name: English (United States)
 273.488 +format locale: ID: mn_MN, Name: Mongolian (Mongolia)
 273.489 +default charset: windows-1252
 273.490 +
 273.491 +OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
 273.492 +default locale: ID: en_US, Name: English (United States)
 273.493 +display locale: ID: en_US, Name: English (United States)
 273.494 +format locale: ID: bo_CN, Name: Tibetan (China)
 273.495 +default charset: windows-1252
 273.496 +
 273.497 +OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
 273.498 +default locale: ID: en_US, Name: English (United States)
 273.499 +display locale: ID: en_US, Name: English (United States)
 273.500 +format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 273.501 +default charset: windows-1252
 273.502 +
 273.503 +OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
 273.504 +default locale: ID: en_US, Name: English (United States)
 273.505 +display locale: ID: en_US, Name: English (United States)
 273.506 +format locale: ID: km_KH, Name: Khmer (Cambodia)
 273.507 +default charset: windows-1252
 273.508 +
 273.509 +OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
 273.510 +default locale: ID: en_US, Name: English (United States)
 273.511 +display locale: ID: en_US, Name: English (United States)
 273.512 +format locale: ID: lo_LA, Name: Lao (Laos)
 273.513 +default charset: windows-1252
 273.514 +
 273.515 +OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
 273.516 +default locale: ID: en_US, Name: English (United States)
 273.517 +display locale: ID: en_US, Name: English (United States)
 273.518 +format locale: ID: gl_ES, Name: Gallegan (Spain)
 273.519 +default charset: windows-1252
 273.520 +
 273.521 +OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
 273.522 +default locale: ID: en_US, Name: English (United States)
 273.523 +display locale: ID: en_US, Name: English (United States)
 273.524 +format locale: ID: en_US, Name: English (United States)
 273.525 +default charset: windows-1252
 273.526 +
 273.527 +OS Locale (lcid: 457, name: kok): Konkani (India) - 0
 273.528 +default locale: ID: en_US, Name: English (United States)
 273.529 +display locale: ID: en_US, Name: English (United States)
 273.530 +format locale: ID: en_US, Name: English (United States)
 273.531 +default charset: windows-1252
 273.532 +
 273.533 +OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
 273.534 +default locale: ID: en_US, Name: English (United States)
 273.535 +display locale: ID: en_US, Name: English (United States)
 273.536 +format locale: ID: en_US, Name: English (United States)
 273.537 +default charset: windows-1252
 273.538 +
 273.539 +OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
 273.540 +default locale: ID: en_US, Name: English (United States)
 273.541 +display locale: ID: en_US, Name: English (United States)
 273.542 +format locale: ID: en_US, Name: English (United States)
 273.543 +default charset: windows-1252
 273.544 +
 273.545 +OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
 273.546 +default locale: ID: en_US, Name: English (United States)
 273.547 +display locale: ID: en_US, Name: English (United States)
 273.548 +format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
 273.549 +default charset: windows-1252
 273.550 +
 273.551 +OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
 273.552 +default locale: ID: en_US, Name: English (United States)
 273.553 +display locale: ID: en_US, Name: English (United States)
 273.554 +format locale: ID: iu_CA, Name: Inuktitut (Canada)
 273.555 +default charset: windows-1252
 273.556 +
 273.557 +OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
 273.558 +default locale: ID: en_US, Name: English (United States)
 273.559 +display locale: ID: en_US, Name: English (United States)
 273.560 +format locale: ID: iu_CA, Name: Inuktitut (Canada)
 273.561 +default charset: windows-1252
 273.562 +
 273.563 +OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
 273.564 +default locale: ID: en_US, Name: English (United States)
 273.565 +display locale: ID: en_US, Name: English (United States)
 273.566 +format locale: ID: am_ET, Name: Amharic (Ethiopia)
 273.567 +default charset: windows-1252
 273.568 +
 273.569 +OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
 273.570 +default locale: ID: en_US, Name: English (United States)
 273.571 +display locale: ID: en_US, Name: English (United States)
 273.572 +format locale: ID: ne_NP, Name: Nepali (Nepal)
 273.573 +default charset: windows-1252
 273.574 +
 273.575 +OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
 273.576 +default locale: ID: en_US, Name: English (United States)
 273.577 +display locale: ID: en_US, Name: English (United States)
 273.578 +format locale: ID: fy_NL, Name: Frisian (Netherlands)
 273.579 +default charset: windows-1252
 273.580 +
 273.581 +OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
 273.582 +default locale: ID: en_US, Name: English (United States)
 273.583 +display locale: ID: en_US, Name: English (United States)
 273.584 +format locale: ID: ps_AF, Name: Pushto (Afghanistan)
 273.585 +default charset: windows-1252
 273.586 +
 273.587 +OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
 273.588 +default locale: ID: en_US, Name: English (United States)
 273.589 +display locale: ID: en_US, Name: English (United States)
 273.590 +format locale: ID: en_US, Name: English (United States)
 273.591 +default charset: windows-1252
 273.592 +
 273.593 +OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
 273.594 +default locale: ID: en_US, Name: English (United States)
 273.595 +display locale: ID: en_US, Name: English (United States)
 273.596 +format locale: ID: en_US, Name: English (United States)
 273.597 +default charset: windows-1252
 273.598 +
 273.599 +OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
 273.600 +default locale: ID: en_US, Name: English (United States)
 273.601 +display locale: ID: en_US, Name: English (United States)
 273.602 +format locale: ID: dv_MV, Name: Divehi (Maldives)
 273.603 +default charset: windows-1252
 273.604 +
 273.605 +OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
 273.606 +default locale: ID: en_US, Name: English (United States)
 273.607 +display locale: ID: en_US, Name: English (United States)
 273.608 +format locale: ID: ha_NG, Name: Hausa (Nigeria)
 273.609 +default charset: windows-1252
 273.610 +
 273.611 +OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
 273.612 +default locale: ID: en_US, Name: English (United States)
 273.613 +display locale: ID: en_US, Name: English (United States)
 273.614 +format locale: ID: ha_NG, Name: Hausa (Nigeria)
 273.615 +default charset: windows-1252
 273.616 +
 273.617 +OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
 273.618 +default locale: ID: en_US, Name: English (United States)
 273.619 +display locale: ID: en_US, Name: English (United States)
 273.620 +format locale: ID: yo_NG, Name: Yoruba (Nigeria)
 273.621 +default charset: windows-1252
 273.622 +
 273.623 +OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
 273.624 +default locale: ID: en_US, Name: English (United States)
 273.625 +display locale: ID: en_US, Name: English (United States)
 273.626 +format locale: ID: en_US, Name: English (United States)
 273.627 +default charset: windows-1252
 273.628 +
 273.629 +OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
 273.630 +default locale: ID: en_US, Name: English (United States)
 273.631 +display locale: ID: en_US, Name: English (United States)
 273.632 +format locale: ID: en_US, Name: English (United States)
 273.633 +default charset: windows-1252
 273.634 +
 273.635 +OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
 273.636 +default locale: ID: en_US, Name: English (United States)
 273.637 +display locale: ID: en_US, Name: English (United States)
 273.638 +format locale: ID: en_US, Name: English (United States)
 273.639 +default charset: windows-1252
 273.640 +
 273.641 +OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
 273.642 +default locale: ID: en_US, Name: English (United States)
 273.643 +display locale: ID: en_US, Name: English (United States)
 273.644 +format locale: ID: en_US, Name: English (United States)
 273.645 +default charset: windows-1252
 273.646 +
 273.647 +OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
 273.648 +default locale: ID: en_US, Name: English (United States)
 273.649 +display locale: ID: en_US, Name: English (United States)
 273.650 +format locale: ID: ba_RU, Name: Bashkir (Russia)
 273.651 +default charset: windows-1252
 273.652 +
 273.653 +OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
 273.654 +default locale: ID: en_US, Name: English (United States)
 273.655 +display locale: ID: en_US, Name: English (United States)
 273.656 +format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
 273.657 +default charset: windows-1252
 273.658 +
 273.659 +OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
 273.660 +default locale: ID: en_US, Name: English (United States)
 273.661 +display locale: ID: en_US, Name: English (United States)
 273.662 +format locale: ID: kl_GL, Name: Greenlandic (Greenland)
 273.663 +default charset: windows-1252
 273.664 +
 273.665 +OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
 273.666 +default locale: ID: en_US, Name: English (United States)
 273.667 +display locale: ID: en_US, Name: English (United States)
 273.668 +format locale: ID: ig_NG, Name: Igbo (Nigeria)
 273.669 +default charset: windows-1252
 273.670 +
 273.671 +OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
 273.672 +default locale: ID: en_US, Name: English (United States)
 273.673 +display locale: ID: en_US, Name: English (United States)
 273.674 +format locale: ID: ii_CN, Name: Sichuan Yi (China)
 273.675 +default charset: windows-1252
 273.676 +
 273.677 +OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
 273.678 +default locale: ID: en_US, Name: English (United States)
 273.679 +display locale: ID: en_US, Name: English (United States)
 273.680 +format locale: ID: en_US, Name: English (United States)
 273.681 +default charset: windows-1252
 273.682 +
 273.683 +OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
 273.684 +default locale: ID: en_US, Name: English (United States)
 273.685 +display locale: ID: en_US, Name: English (United States)
 273.686 +format locale: ID: en_US, Name: English (United States)
 273.687 +default charset: windows-1252
 273.688 +
 273.689 +OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
 273.690 +default locale: ID: en_US, Name: English (United States)
 273.691 +display locale: ID: en_US, Name: English (United States)
 273.692 +format locale: ID: en_US, Name: English (United States)
 273.693 +default charset: windows-1252
 273.694 +
 273.695 +OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
 273.696 +default locale: ID: en_US, Name: English (United States)
 273.697 +display locale: ID: en_US, Name: English (United States)
 273.698 +format locale: ID: en_US, Name: English (United States)
 273.699 +default charset: windows-1252
 273.700 +
 273.701 +OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
 273.702 +default locale: ID: en_US, Name: English (United States)
 273.703 +display locale: ID: en_US, Name: English (United States)
 273.704 +format locale: ID: br_FR, Name: Breton (France)
 273.705 +default charset: windows-1252
 273.706 +
 273.707 +OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
 273.708 +default locale: ID: en_US, Name: English (United States)
 273.709 +display locale: ID: en_US, Name: English (United States)
 273.710 +format locale: ID: ug_CN, Name: Uighur (China)
 273.711 +default charset: windows-1252
 273.712 +
 273.713 +OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
 273.714 +default locale: ID: en_US, Name: English (United States)
 273.715 +display locale: ID: en_US, Name: English (United States)
 273.716 +format locale: ID: mi_NZ, Name: Maori (New Zealand)
 273.717 +default charset: windows-1252
 273.718 +
 273.719 +OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
 273.720 +default locale: ID: en_US, Name: English (United States)
 273.721 +display locale: ID: en_US, Name: English (United States)
 273.722 +format locale: ID: oc_FR, Name: Occitan (France)
 273.723 +default charset: windows-1252
 273.724 +
 273.725 +OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
 273.726 +default locale: ID: en_US, Name: English (United States)
 273.727 +display locale: ID: en_US, Name: English (United States)
 273.728 +format locale: ID: co_FR, Name: Corsican (France)
 273.729 +default charset: windows-1252
 273.730 +
 273.731 +OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
 273.732 +default locale: ID: en_US, Name: English (United States)
 273.733 +display locale: ID: en_US, Name: English (United States)
 273.734 +format locale: ID: en_US, Name: English (United States)
 273.735 +default charset: windows-1252
 273.736 +
 273.737 +OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
 273.738 +default locale: ID: en_US, Name: English (United States)
 273.739 +display locale: ID: en_US, Name: English (United States)
 273.740 +format locale: ID: en_US, Name: English (United States)
 273.741 +default charset: windows-1252
 273.742 +
 273.743 +OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
 273.744 +default locale: ID: en_US, Name: English (United States)
 273.745 +display locale: ID: en_US, Name: English (United States)
 273.746 +format locale: ID: en_US, Name: English (United States)
 273.747 +default charset: windows-1252
 273.748 +
 273.749 +OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
 273.750 +default locale: ID: en_US, Name: English (United States)
 273.751 +display locale: ID: en_US, Name: English (United States)
 273.752 +format locale: ID: en_US, Name: English (United States)
 273.753 +default charset: windows-1252
 273.754 +
 273.755 +OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
 273.756 +default locale: ID: en_US, Name: English (United States)
 273.757 +display locale: ID: en_US, Name: English (United States)
 273.758 +format locale: ID: en_US, Name: English (United States)
 273.759 +default charset: windows-1252
 273.760 +
 273.761 +OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
 273.762 +default locale: ID: en_US, Name: English (United States)
 273.763 +display locale: ID: en_US, Name: English (United States)
 273.764 +format locale: ID: en_US, Name: English (United States)
 273.765 +default charset: windows-1252
 273.766 +
 273.767 +OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
 273.768 +default locale: ID: en_US, Name: English (United States)
 273.769 +display locale: ID: en_US, Name: English (United States)
 273.770 +format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 273.771 +default charset: windows-1252
 273.772 +
 273.773 +OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
 273.774 +default locale: ID: en_US, Name: English (United States)
 273.775 +display locale: ID: en_US, Name: English (United States)
 273.776 +format locale: ID: wo_SN, Name: Wolof (Senegal)
 273.777 +default charset: windows-1252
 273.778 +
 273.779 +OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
 273.780 +default locale: ID: en_US, Name: English (United States)
 273.781 +display locale: ID: en_US, Name: English (United States)
 273.782 +format locale: ID: en_US, Name: English (United States)
 273.783 +default charset: windows-1252
 273.784 +
 273.785 +OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
 273.786 +default locale: ID: en_US, Name: English (United States)
 273.787 +display locale: ID: en_US, Name: English (United States)
 273.788 +format locale: ID: en_US, Name: English (United States)
 273.789 +default charset: windows-1252
 273.790 +
 273.791 +OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
 273.792 +default locale: ID: en_US, Name: English (United States)
 273.793 +display locale: ID: en_US, Name: English (United States)
 273.794 +format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 273.795 +default charset: windows-1252
 273.796 +
 273.797 +OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
 273.798 +default locale: ID: en_US, Name: English (United States)
 273.799 +display locale: ID: en_US, Name: English (United States)
 273.800 +format locale: ID: ar_IQ, Name: Arabic (Iraq)
 273.801 +default charset: windows-1252
 273.802 +
 273.803 +OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
 273.804 +default locale: ID: en_US, Name: English (United States)
 273.805 +display locale: ID: en_US, Name: English (United States)
 273.806 +format locale: ID: zh_CN, Name: Chinese (China)
 273.807 +default charset: windows-1252
 273.808 +
 273.809 +OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
 273.810 +default locale: ID: en_US, Name: English (United States)
 273.811 +display locale: ID: en_US, Name: English (United States)
 273.812 +format locale: ID: zh_CN, Name: Chinese (China)
 273.813 +default charset: windows-1252
 273.814 +
 273.815 +OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
 273.816 +default locale: ID: en_US, Name: English (United States)
 273.817 +display locale: ID: en_US, Name: English (United States)
 273.818 +format locale: ID: de_CH, Name: German (Switzerland)
 273.819 +default charset: windows-1252
 273.820 +
 273.821 +OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
 273.822 +default locale: ID: en_US, Name: English (United States)
 273.823 +display locale: ID: en_US, Name: English (United States)
 273.824 +format locale: ID: en_US, Name: English (United States)
 273.825 +default charset: windows-1252
 273.826 +
 273.827 +OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
 273.828 +default locale: ID: en_US, Name: English (United States)
 273.829 +display locale: ID: en_US, Name: English (United States)
 273.830 +format locale: ID: es_MX, Name: Spanish (Mexico)
 273.831 +default charset: windows-1252
 273.832 +
 273.833 +OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
 273.834 +default locale: ID: en_US, Name: English (United States)
 273.835 +display locale: ID: en_US, Name: English (United States)
 273.836 +format locale: ID: fr_BE, Name: French (Belgium)
 273.837 +default charset: windows-1252
 273.838 +
 273.839 +OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
 273.840 +default locale: ID: en_US, Name: English (United States)
 273.841 +display locale: ID: en_US, Name: English (United States)
 273.842 +format locale: ID: it_CH, Name: Italian (Switzerland)
 273.843 +default charset: windows-1252
 273.844 +
 273.845 +OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
 273.846 +default locale: ID: en_US, Name: English (United States)
 273.847 +display locale: ID: en_US, Name: English (United States)
 273.848 +format locale: ID: nl_BE, Name: Dutch (Belgium)
 273.849 +default charset: windows-1252
 273.850 +
 273.851 +OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
 273.852 +default locale: ID: en_US, Name: English (United States)
 273.853 +display locale: ID: en_US, Name: English (United States)
 273.854 +format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 273.855 +default charset: windows-1252
 273.856 +
 273.857 +OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
 273.858 +default locale: ID: en_US, Name: English (United States)
 273.859 +display locale: ID: en_US, Name: English (United States)
 273.860 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
 273.861 +default charset: windows-1252
 273.862 +
 273.863 +OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
 273.864 +default locale: ID: en_US, Name: English (United States)
 273.865 +display locale: ID: en_US, Name: English (United States)
 273.866 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
 273.867 +default charset: windows-1252
 273.868 +
 273.869 +OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
 273.870 +default locale: ID: en_US, Name: English (United States)
 273.871 +display locale: ID: en_US, Name: English (United States)
 273.872 +format locale: ID: sv_FI, Name: Swedish (Finland)
 273.873 +default charset: windows-1252
 273.874 +
 273.875 +OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
 273.876 +default locale: ID: en_US, Name: English (United States)
 273.877 +display locale: ID: en_US, Name: English (United States)
 273.878 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 273.879 +default charset: windows-1252
 273.880 +
 273.881 +OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
 273.882 +default locale: ID: en_US, Name: English (United States)
 273.883 +display locale: ID: en_US, Name: English (United States)
 273.884 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 273.885 +default charset: windows-1252
 273.886 +
 273.887 +OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
 273.888 +default locale: ID: en_US, Name: English (United States)
 273.889 +display locale: ID: en_US, Name: English (United States)
 273.890 +format locale: ID: en_US, Name: English (United States)
 273.891 +default charset: windows-1252
 273.892 +
 273.893 +OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
 273.894 +default locale: ID: en_US, Name: English (United States)
 273.895 +display locale: ID: en_US, Name: English (United States)
 273.896 +format locale: ID: en_US, Name: English (United States)
 273.897 +default charset: windows-1252
 273.898 +
 273.899 +OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
 273.900 +default locale: ID: en_US, Name: English (United States)
 273.901 +display locale: ID: en_US, Name: English (United States)
 273.902 +format locale: ID: se_SE, Name: Northern Sami (Sweden)
 273.903 +default charset: windows-1252
 273.904 +
 273.905 +OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
 273.906 +default locale: ID: en_US, Name: English (United States)
 273.907 +display locale: ID: en_US, Name: English (United States)
 273.908 +format locale: ID: ga_IE, Name: Irish (Ireland)
 273.909 +default charset: windows-1252
 273.910 +
 273.911 +OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
 273.912 +default locale: ID: en_US, Name: English (United States)
 273.913 +display locale: ID: en_US, Name: English (United States)
 273.914 +format locale: ID: ms_BN, Name: Malay (Brunei)
 273.915 +default charset: windows-1252
 273.916 +
 273.917 +OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
 273.918 +default locale: ID: en_US, Name: English (United States)
 273.919 +display locale: ID: en_US, Name: English (United States)
 273.920 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 273.921 +default charset: windows-1252
 273.922 +
 273.923 +OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
 273.924 +default locale: ID: en_US, Name: English (United States)
 273.925 +display locale: ID: en_US, Name: English (United States)
 273.926 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 273.927 +default charset: windows-1252
 273.928 +
 273.929 +OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
 273.930 +default locale: ID: en_US, Name: English (United States)
 273.931 +display locale: ID: en_US, Name: English (United States)
 273.932 +format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 273.933 +default charset: windows-1252
 273.934 +
 273.935 +OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 273.936 +default locale: ID: en_US, Name: English (United States)
 273.937 +display locale: ID: en_US, Name: English (United States)
 273.938 +format locale: ID: mn_CN, Name: Mongolian (China)
 273.939 +default charset: windows-1252
 273.940 +
 273.941 +OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 273.942 +default locale: ID: en_US, Name: English (United States)
 273.943 +display locale: ID: en_US, Name: English (United States)
 273.944 +format locale: ID: mn_CN, Name: Mongolian (China)
 273.945 +default charset: windows-1252
 273.946 +
 273.947 +OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
 273.948 +default locale: ID: en_US, Name: English (United States)
 273.949 +display locale: ID: en_US, Name: English (United States)
 273.950 +format locale: ID: iu_CA, Name: Inuktitut (Canada)
 273.951 +default charset: windows-1252
 273.952 +
 273.953 +OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
 273.954 +default locale: ID: en_US, Name: English (United States)
 273.955 +display locale: ID: en_US, Name: English (United States)
 273.956 +format locale: ID: iu_CA, Name: Inuktitut (Canada)
 273.957 +default charset: windows-1252
 273.958 +
 273.959 +OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
 273.960 +default locale: ID: en_US, Name: English (United States)
 273.961 +display locale: ID: en_US, Name: English (United States)
 273.962 +format locale: ID: en_US, Name: English (United States)
 273.963 +default charset: windows-1252
 273.964 +
 273.965 +OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
 273.966 +default locale: ID: en_US, Name: English (United States)
 273.967 +display locale: ID: en_US, Name: English (United States)
 273.968 +format locale: ID: en_US, Name: English (United States)
 273.969 +default charset: windows-1252
 273.970 +
 273.971 +OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
 273.972 +default locale: ID: en_US, Name: English (United States)
 273.973 +display locale: ID: en_US, Name: English (United States)
 273.974 +format locale: ID: en_US, Name: English (United States)
 273.975 +default charset: windows-1252
 273.976 +
 273.977 +OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
 273.978 +default locale: ID: en_US, Name: English (United States)
 273.979 +display locale: ID: en_US, Name: English (United States)
 273.980 +format locale: ID: en_US, Name: English (United States)
 273.981 +default charset: windows-1252
 273.982 +
 273.983 +OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
 273.984 +default locale: ID: en_US, Name: English (United States)
 273.985 +display locale: ID: en_US, Name: English (United States)
 273.986 +format locale: ID: ar_EG, Name: Arabic (Egypt)
 273.987 +default charset: windows-1252
 273.988 +
 273.989 +OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 273.990 +default locale: ID: en_US, Name: English (United States)
 273.991 +display locale: ID: en_US, Name: English (United States)
 273.992 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 273.993 +default charset: x-MS950-HKSCS
 273.994 +
 273.995 +OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 273.996 +default locale: ID: en_US, Name: English (United States)
 273.997 +display locale: ID: en_US, Name: English (United States)
 273.998 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 273.999 +default charset: windows-1252
273.1000 +
273.1001 +OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
273.1002 +default locale: ID: en_US, Name: English (United States)
273.1003 +display locale: ID: en_US, Name: English (United States)
273.1004 +format locale: ID: de_AT, Name: German (Austria)
273.1005 +default charset: windows-1252
273.1006 +
273.1007 +OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
273.1008 +default locale: ID: en_US, Name: English (United States)
273.1009 +display locale: ID: en_US, Name: English (United States)
273.1010 +format locale: ID: en_US, Name: English (United States)
273.1011 +default charset: windows-1252
273.1012 +
273.1013 +OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
273.1014 +default locale: ID: en_US, Name: English (United States)
273.1015 +display locale: ID: en_US, Name: English (United States)
273.1016 +format locale: ID: es_ES, Name: Spanish (Spain)
273.1017 +default charset: windows-1252
273.1018 +
273.1019 +OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
273.1020 +default locale: ID: en_US, Name: English (United States)
273.1021 +display locale: ID: en_US, Name: English (United States)
273.1022 +format locale: ID: fr_CA, Name: French (Canada)
273.1023 +default charset: windows-1252
273.1024 +
273.1025 +OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
273.1026 +default locale: ID: en_US, Name: English (United States)
273.1027 +display locale: ID: en_US, Name: English (United States)
273.1028 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
273.1029 +default charset: windows-1252
273.1030 +
273.1031 +OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
273.1032 +default locale: ID: en_US, Name: English (United States)
273.1033 +display locale: ID: en_US, Name: English (United States)
273.1034 +format locale: ID: se_FI, Name: Northern Sami (Finland)
273.1035 +default charset: windows-1252
273.1036 +
273.1037 +OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
273.1038 +default locale: ID: en_US, Name: English (United States)
273.1039 +display locale: ID: en_US, Name: English (United States)
273.1040 +format locale: ID: en_US, Name: English (United States)
273.1041 +default charset: windows-1252
273.1042 +
273.1043 +OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
273.1044 +default locale: ID: en_US, Name: English (United States)
273.1045 +display locale: ID: en_US, Name: English (United States)
273.1046 +format locale: ID: ar_LY, Name: Arabic (Libya)
273.1047 +default charset: windows-1252
273.1048 +
273.1049 +OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
273.1050 +default locale: ID: en_US, Name: English (United States)
273.1051 +display locale: ID: en_US, Name: English (United States)
273.1052 +format locale: ID: zh_SG, Name: Chinese (Singapore)
273.1053 +default charset: windows-1252
273.1054 +
273.1055 +OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
273.1056 +default locale: ID: en_US, Name: English (United States)
273.1057 +display locale: ID: en_US, Name: English (United States)
273.1058 +format locale: ID: de_LU, Name: German (Luxembourg)
273.1059 +default charset: windows-1252
273.1060 +
273.1061 +OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
273.1062 +default locale: ID: en_US, Name: English (United States)
273.1063 +display locale: ID: en_US, Name: English (United States)
273.1064 +format locale: ID: en_US, Name: English (United States)
273.1065 +default charset: windows-1252
273.1066 +
273.1067 +OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
273.1068 +default locale: ID: en_US, Name: English (United States)
273.1069 +display locale: ID: en_US, Name: English (United States)
273.1070 +format locale: ID: es_GT, Name: Spanish (Guatemala)
273.1071 +default charset: windows-1252
273.1072 +
273.1073 +OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
273.1074 +default locale: ID: en_US, Name: English (United States)
273.1075 +display locale: ID: en_US, Name: English (United States)
273.1076 +format locale: ID: fr_CH, Name: French (Switzerland)
273.1077 +default charset: windows-1252
273.1078 +
273.1079 +OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
273.1080 +default locale: ID: en_US, Name: English (United States)
273.1081 +display locale: ID: en_US, Name: English (United States)
273.1082 +format locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
273.1083 +default charset: windows-1252
273.1084 +
273.1085 +OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
273.1086 +default locale: ID: en_US, Name: English (United States)
273.1087 +display locale: ID: en_US, Name: English (United States)
273.1088 +format locale: ID: en_US, Name: English (United States)
273.1089 +default charset: windows-1252
273.1090 +
273.1091 +OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
273.1092 +default locale: ID: en_US, Name: English (United States)
273.1093 +display locale: ID: en_US, Name: English (United States)
273.1094 +format locale: ID: ar_DZ, Name: Arabic (Algeria)
273.1095 +default charset: windows-1252
273.1096 +
273.1097 +OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
273.1098 +default locale: ID: en_US, Name: English (United States)
273.1099 +display locale: ID: en_US, Name: English (United States)
273.1100 +format locale: ID: zh_MO, Name: Chinese (Macao)
273.1101 +default charset: windows-1252
273.1102 +
273.1103 +OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
273.1104 +default locale: ID: en_US, Name: English (United States)
273.1105 +display locale: ID: en_US, Name: English (United States)
273.1106 +format locale: ID: de_LI, Name: German (Liechtenstein)
273.1107 +default charset: windows-1252
273.1108 +
273.1109 +OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
273.1110 +default locale: ID: en_US, Name: English (United States)
273.1111 +display locale: ID: en_US, Name: English (United States)
273.1112 +format locale: ID: en_US, Name: English (United States)
273.1113 +default charset: windows-1252
273.1114 +
273.1115 +OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
273.1116 +default locale: ID: en_US, Name: English (United States)
273.1117 +display locale: ID: en_US, Name: English (United States)
273.1118 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
273.1119 +default charset: windows-1252
273.1120 +
273.1121 +OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
273.1122 +default locale: ID: en_US, Name: English (United States)
273.1123 +display locale: ID: en_US, Name: English (United States)
273.1124 +format locale: ID: fr_LU, Name: French (Luxembourg)
273.1125 +default charset: windows-1252
273.1126 +
273.1127 +OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
273.1128 +default locale: ID: en_US, Name: English (United States)
273.1129 +display locale: ID: en_US, Name: English (United States)
273.1130 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
273.1131 +default charset: windows-1252
273.1132 +
273.1133 +OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
273.1134 +default locale: ID: en_US, Name: English (United States)
273.1135 +display locale: ID: en_US, Name: English (United States)
273.1136 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
273.1137 +default charset: windows-1252
273.1138 +
273.1139 +OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
273.1140 +default locale: ID: en_US, Name: English (United States)
273.1141 +display locale: ID: en_US, Name: English (United States)
273.1142 +format locale: ID: en_US, Name: English (United States)
273.1143 +default charset: windows-1252
273.1144 +
273.1145 +OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
273.1146 +default locale: ID: en_US, Name: English (United States)
273.1147 +display locale: ID: en_US, Name: English (United States)
273.1148 +format locale: ID: en_US, Name: English (United States)
273.1149 +default charset: windows-1252
273.1150 +
273.1151 +OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
273.1152 +default locale: ID: en_US, Name: English (United States)
273.1153 +display locale: ID: en_US, Name: English (United States)
273.1154 +format locale: ID: ar_MA, Name: Arabic (Morocco)
273.1155 +default charset: windows-1252
273.1156 +
273.1157 +OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
273.1158 +default locale: ID: en_US, Name: English (United States)
273.1159 +display locale: ID: en_US, Name: English (United States)
273.1160 +format locale: ID: en_US, Name: English (United States)
273.1161 +default charset: windows-1252
273.1162 +
273.1163 +OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
273.1164 +default locale: ID: en_US, Name: English (United States)
273.1165 +display locale: ID: en_US, Name: English (United States)
273.1166 +format locale: ID: es_PA, Name: Spanish (Panama)
273.1167 +default charset: windows-1252
273.1168 +
273.1169 +OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
273.1170 +default locale: ID: en_US, Name: English (United States)
273.1171 +display locale: ID: en_US, Name: English (United States)
273.1172 +format locale: ID: fr_MC, Name: French (Monaco)
273.1173 +default charset: windows-1252
273.1174 +
273.1175 +OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
273.1176 +default locale: ID: en_US, Name: English (United States)
273.1177 +display locale: ID: en_US, Name: English (United States)
273.1178 +format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
273.1179 +default charset: windows-1252
273.1180 +
273.1181 +OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
273.1182 +default locale: ID: en_US, Name: English (United States)
273.1183 +display locale: ID: en_US, Name: English (United States)
273.1184 +format locale: ID: en_US, Name: English (United States)
273.1185 +default charset: windows-1252
273.1186 +
273.1187 +OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
273.1188 +default locale: ID: en_US, Name: English (United States)
273.1189 +display locale: ID: en_US, Name: English (United States)
273.1190 +format locale: ID: ar_TN, Name: Arabic (Tunisia)
273.1191 +default charset: windows-1252
273.1192 +
273.1193 +OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
273.1194 +default locale: ID: en_US, Name: English (United States)
273.1195 +display locale: ID: en_US, Name: English (United States)
273.1196 +format locale: ID: en_US, Name: English (United States)
273.1197 +default charset: windows-1252
273.1198 +
273.1199 +OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
273.1200 +default locale: ID: en_US, Name: English (United States)
273.1201 +display locale: ID: en_US, Name: English (United States)
273.1202 +format locale: ID: es_DO, Name: Spanish (Dominican Republic)
273.1203 +default charset: windows-1252
273.1204 +
273.1205 +OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
273.1206 +default locale: ID: en_US, Name: English (United States)
273.1207 +display locale: ID: en_US, Name: English (United States)
273.1208 +format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
273.1209 +default charset: windows-1252
273.1210 +
273.1211 +OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
273.1212 +default locale: ID: en_US, Name: English (United States)
273.1213 +display locale: ID: en_US, Name: English (United States)
273.1214 +format locale: ID: en_US, Name: English (United States)
273.1215 +default charset: windows-1252
273.1216 +
273.1217 +OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
273.1218 +default locale: ID: en_US, Name: English (United States)
273.1219 +display locale: ID: en_US, Name: English (United States)
273.1220 +format locale: ID: en_US, Name: English (United States)
273.1221 +default charset: windows-1252
273.1222 +
273.1223 +OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
273.1224 +default locale: ID: en_US, Name: English (United States)
273.1225 +display locale: ID: en_US, Name: English (United States)
273.1226 +format locale: ID: ar_OM, Name: Arabic (Oman)
273.1227 +default charset: windows-1252
273.1228 +
273.1229 +OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
273.1230 +default locale: ID: en_US, Name: English (United States)
273.1231 +display locale: ID: en_US, Name: English (United States)
273.1232 +format locale: ID: en_US, Name: English (United States)
273.1233 +default charset: windows-1252
273.1234 +
273.1235 +OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
273.1236 +default locale: ID: en_US, Name: English (United States)
273.1237 +display locale: ID: en_US, Name: English (United States)
273.1238 +format locale: ID: es_VE, Name: Spanish (Venezuela)
273.1239 +default charset: windows-1252
273.1240 +
273.1241 +OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
273.1242 +default locale: ID: en_US, Name: English (United States)
273.1243 +display locale: ID: en_US, Name: English (United States)
273.1244 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
273.1245 +default charset: windows-1252
273.1246 +
273.1247 +OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
273.1248 +default locale: ID: en_US, Name: English (United States)
273.1249 +display locale: ID: en_US, Name: English (United States)
273.1250 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
273.1251 +default charset: windows-1252
273.1252 +
273.1253 +OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
273.1254 +default locale: ID: en_US, Name: English (United States)
273.1255 +display locale: ID: en_US, Name: English (United States)
273.1256 +format locale: ID: en_US, Name: English (United States)
273.1257 +default charset: windows-1252
273.1258 +
273.1259 +OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
273.1260 +default locale: ID: en_US, Name: English (United States)
273.1261 +display locale: ID: en_US, Name: English (United States)
273.1262 +format locale: ID: en_US, Name: English (United States)
273.1263 +default charset: windows-1252
273.1264 +
273.1265 +OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
273.1266 +default locale: ID: en_US, Name: English (United States)
273.1267 +display locale: ID: en_US, Name: English (United States)
273.1268 +format locale: ID: ar_YE, Name: Arabic (Yemen)
273.1269 +default charset: windows-1252
273.1270 +
273.1271 +OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
273.1272 +default locale: ID: en_US, Name: English (United States)
273.1273 +display locale: ID: en_US, Name: English (United States)
273.1274 +format locale: ID: en_US, Name: English (United States)
273.1275 +default charset: windows-1252
273.1276 +
273.1277 +OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
273.1278 +default locale: ID: en_US, Name: English (United States)
273.1279 +display locale: ID: en_US, Name: English (United States)
273.1280 +format locale: ID: es_CO, Name: Spanish (Colombia)
273.1281 +default charset: windows-1252
273.1282 +
273.1283 +OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
273.1284 +default locale: ID: en_US, Name: English (United States)
273.1285 +display locale: ID: en_US, Name: English (United States)
273.1286 +format locale: ID: sr_RS, Name: Serbian (Serbia)
273.1287 +default charset: windows-1252
273.1288 +
273.1289 +OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
273.1290 +default locale: ID: en_US, Name: English (United States)
273.1291 +display locale: ID: en_US, Name: English (United States)
273.1292 +format locale: ID: sr_RS, Name: Serbian (Serbia)
273.1293 +default charset: windows-1252
273.1294 +
273.1295 +OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
273.1296 +default locale: ID: en_US, Name: English (United States)
273.1297 +display locale: ID: en_US, Name: English (United States)
273.1298 +format locale: ID: en_US, Name: English (United States)
273.1299 +default charset: windows-1252
273.1300 +
273.1301 +OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
273.1302 +default locale: ID: en_US, Name: English (United States)
273.1303 +display locale: ID: en_US, Name: English (United States)
273.1304 +format locale: ID: en_US, Name: English (United States)
273.1305 +default charset: windows-1252
273.1306 +
273.1307 +OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
273.1308 +default locale: ID: en_US, Name: English (United States)
273.1309 +display locale: ID: en_US, Name: English (United States)
273.1310 +format locale: ID: ar_SY, Name: Arabic (Syria)
273.1311 +default charset: windows-1252
273.1312 +
273.1313 +OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
273.1314 +default locale: ID: en_US, Name: English (United States)
273.1315 +display locale: ID: en_US, Name: English (United States)
273.1316 +format locale: ID: en_US, Name: English (United States)
273.1317 +default charset: windows-1252
273.1318 +
273.1319 +OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
273.1320 +default locale: ID: en_US, Name: English (United States)
273.1321 +display locale: ID: en_US, Name: English (United States)
273.1322 +format locale: ID: es_PE, Name: Spanish (Peru)
273.1323 +default charset: windows-1252
273.1324 +
273.1325 +OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
273.1326 +default locale: ID: en_US, Name: English (United States)
273.1327 +display locale: ID: en_US, Name: English (United States)
273.1328 +format locale: ID: sr_RS, Name: Serbian (Serbia)
273.1329 +default charset: windows-1252
273.1330 +
273.1331 +OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
273.1332 +default locale: ID: en_US, Name: English (United States)
273.1333 +display locale: ID: en_US, Name: English (United States)
273.1334 +format locale: ID: sr_RS, Name: Serbian (Serbia)
273.1335 +default charset: windows-1252
273.1336 +
273.1337 +OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
273.1338 +default locale: ID: en_US, Name: English (United States)
273.1339 +display locale: ID: en_US, Name: English (United States)
273.1340 +format locale: ID: ar_JO, Name: Arabic (Jordan)
273.1341 +default charset: windows-1252
273.1342 +
273.1343 +OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
273.1344 +default locale: ID: en_US, Name: English (United States)
273.1345 +display locale: ID: en_US, Name: English (United States)
273.1346 +format locale: ID: en_US, Name: English (United States)
273.1347 +default charset: windows-1252
273.1348 +
273.1349 +OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
273.1350 +default locale: ID: en_US, Name: English (United States)
273.1351 +display locale: ID: en_US, Name: English (United States)
273.1352 +format locale: ID: es_AR, Name: Spanish (Argentina)
273.1353 +default charset: windows-1252
273.1354 +
273.1355 +OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
273.1356 +default locale: ID: en_US, Name: English (United States)
273.1357 +display locale: ID: en_US, Name: English (United States)
273.1358 +format locale: ID: sr_ME, Name: Serbian (Montenegro)
273.1359 +default charset: windows-1252
273.1360 +
273.1361 +OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
273.1362 +default locale: ID: en_US, Name: English (United States)
273.1363 +display locale: ID: en_US, Name: English (United States)
273.1364 +format locale: ID: ar_LB, Name: Arabic (Lebanon)
273.1365 +default charset: windows-1252
273.1366 +
273.1367 +OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
273.1368 +default locale: ID: en_US, Name: English (United States)
273.1369 +display locale: ID: en_US, Name: English (United States)
273.1370 +format locale: ID: en_US, Name: English (United States)
273.1371 +default charset: windows-1252
273.1372 +
273.1373 +OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
273.1374 +default locale: ID: en_US, Name: English (United States)
273.1375 +display locale: ID: en_US, Name: English (United States)
273.1376 +format locale: ID: es_EC, Name: Spanish (Ecuador)
273.1377 +default charset: windows-1252
273.1378 +
273.1379 +OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
273.1380 +default locale: ID: en_US, Name: English (United States)
273.1381 +display locale: ID: en_US, Name: English (United States)
273.1382 +format locale: ID: sr_ME, Name: Serbian (Montenegro)
273.1383 +default charset: windows-1252
273.1384 +
273.1385 +OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
273.1386 +default locale: ID: en_US, Name: English (United States)
273.1387 +display locale: ID: en_US, Name: English (United States)
273.1388 +format locale: ID: ar_KW, Name: Arabic (Kuwait)
273.1389 +default charset: windows-1252
273.1390 +
273.1391 +OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
273.1392 +default locale: ID: en_US, Name: English (United States)
273.1393 +display locale: ID: en_US, Name: English (United States)
273.1394 +format locale: ID: en_US, Name: English (United States)
273.1395 +default charset: windows-1252
273.1396 +
273.1397 +OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
273.1398 +default locale: ID: en_US, Name: English (United States)
273.1399 +display locale: ID: en_US, Name: English (United States)
273.1400 +format locale: ID: es_CL, Name: Spanish (Chile)
273.1401 +default charset: windows-1252
273.1402 +
273.1403 +OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
273.1404 +default locale: ID: en_US, Name: English (United States)
273.1405 +display locale: ID: en_US, Name: English (United States)
273.1406 +format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
273.1407 +default charset: windows-1252
273.1408 +
273.1409 +OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
273.1410 +default locale: ID: en_US, Name: English (United States)
273.1411 +display locale: ID: en_US, Name: English (United States)
273.1412 +format locale: ID: es_UY, Name: Spanish (Uruguay)
273.1413 +default charset: windows-1252
273.1414 +
273.1415 +OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
273.1416 +default locale: ID: en_US, Name: English (United States)
273.1417 +display locale: ID: en_US, Name: English (United States)
273.1418 +format locale: ID: ar_BH, Name: Arabic (Bahrain)
273.1419 +default charset: windows-1252
273.1420 +
273.1421 +OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
273.1422 +default locale: ID: en_US, Name: English (United States)
273.1423 +display locale: ID: en_US, Name: English (United States)
273.1424 +format locale: ID: es_PY, Name: Spanish (Paraguay)
273.1425 +default charset: windows-1252
273.1426 +
273.1427 +OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
273.1428 +default locale: ID: en_US, Name: English (United States)
273.1429 +display locale: ID: en_US, Name: English (United States)
273.1430 +format locale: ID: ar_QA, Name: Arabic (Qatar)
273.1431 +default charset: windows-1252
273.1432 +
273.1433 +OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
273.1434 +default locale: ID: en_US, Name: English (United States)
273.1435 +display locale: ID: en_US, Name: English (United States)
273.1436 +format locale: ID: en_US, Name: English (United States)
273.1437 +default charset: windows-1252
273.1438 +
273.1439 +OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
273.1440 +default locale: ID: en_US, Name: English (United States)
273.1441 +display locale: ID: en_US, Name: English (United States)
273.1442 +format locale: ID: es_BO, Name: Spanish (Bolivia)
273.1443 +default charset: windows-1252
273.1444 +
273.1445 +OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
273.1446 +default locale: ID: en_US, Name: English (United States)
273.1447 +display locale: ID: en_US, Name: English (United States)
273.1448 +format locale: ID: en_US, Name: English (United States)
273.1449 +default charset: windows-1252
273.1450 +
273.1451 +OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
273.1452 +default locale: ID: en_US, Name: English (United States)
273.1453 +display locale: ID: en_US, Name: English (United States)
273.1454 +format locale: ID: es_SV, Name: Spanish (El Salvador)
273.1455 +default charset: windows-1252
273.1456 +
273.1457 +OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
273.1458 +default locale: ID: en_US, Name: English (United States)
273.1459 +display locale: ID: en_US, Name: English (United States)
273.1460 +format locale: ID: en_US, Name: English (United States)
273.1461 +default charset: windows-1252
273.1462 +
273.1463 +OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
273.1464 +default locale: ID: en_US, Name: English (United States)
273.1465 +display locale: ID: en_US, Name: English (United States)
273.1466 +format locale: ID: es_HN, Name: Spanish (Honduras)
273.1467 +default charset: windows-1252
273.1468 +
273.1469 +OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
273.1470 +default locale: ID: en_US, Name: English (United States)
273.1471 +display locale: ID: en_US, Name: English (United States)
273.1472 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
273.1473 +default charset: windows-1252
273.1474 +
273.1475 +OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
273.1476 +default locale: ID: en_US, Name: English (United States)
273.1477 +display locale: ID: en_US, Name: English (United States)
273.1478 +format locale: ID: es_PR, Name: Spanish (Puerto Rico)
273.1479 +default charset: windows-1252
273.1480 +
273.1481 +OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
273.1482 +default locale: ID: en_US, Name: English (United States)
273.1483 +display locale: ID: en_US, Name: English (United States)
273.1484 +format locale: ID: es, Name: Spanish
273.1485 +default charset: windows-1252
273.1486 +
273.1487 +OS UI Language (name: en-US)
273.1488 +default locale: ID: en_US, Name: English (United States)
273.1489 +display locale: ID: en_US, Name: English (United States)
273.1490 +format locale: ID: en_US, Name: English (United States)
273.1491 +default charset: windows-1252
273.1492 +
273.1493 +OS UI Language (name: ja-JP)
273.1494 +default locale: ID: ja_JP, Name: Japanese (Japan)
273.1495 +display locale: ID: ja_JP, Name: Japanese (Japan)
273.1496 +format locale: ID: en_US, Name: English (United States)
273.1497 +default charset: windows-1252
   274.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   274.2 +++ b/test/java/util/Locale/data/deflocale.win7.fmtasdefault	Fri Sep 24 16:41:32 2010 -0700
   274.3 @@ -0,0 +1,1494 @@
   274.4 +# OSVersionInfo
   274.5 +# MajorVersion: 6
   274.6 +# MinorVersion: 1
   274.7 +# BuildNumber: 7600
   274.8 +# CSDVersion: 
   274.9 +
  274.10 +
  274.11 +OS Locale (lcid: 7f, name: ): Invariant Language (Invariant Country) - 1252
  274.12 +default locale: ID: en_US, Name: English (United States)
  274.13 +display locale: ID: en_US, Name: English (United States)
  274.14 +format locale: ID: en_US, Name: English (United States)
  274.15 +default charset: windows-1252
  274.16 +
  274.17 +OS Locale (lcid: 401, name: ar-SA): Arabic (Saudi Arabia) - 1256
  274.18 +default locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  274.19 +display locale: ID: en_US, Name: English (United States)
  274.20 +format locale: ID: ar_SA, Name: Arabic (Saudi Arabia)
  274.21 +default charset: windows-1256
  274.22 +
  274.23 +OS Locale (lcid: 402, name: bg-BG): Bulgarian (Bulgaria) - 1251
  274.24 +default locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  274.25 +display locale: ID: en_US, Name: English (United States)
  274.26 +format locale: ID: bg_BG, Name: Bulgarian (Bulgaria)
  274.27 +default charset: windows-1251
  274.28 +
  274.29 +OS Locale (lcid: 403, name: ca-ES): Catalan (Spain) - 1252
  274.30 +default locale: ID: ca_ES, Name: Catalan (Spain)
  274.31 +display locale: ID: en_US, Name: English (United States)
  274.32 +format locale: ID: ca_ES, Name: Catalan (Spain)
  274.33 +default charset: windows-1252
  274.34 +
  274.35 +OS Locale (lcid: 404, name: zh-TW): Chinese (Traditional) (Taiwan) - 950
  274.36 +default locale: ID: zh_TW, Name: Chinese (Taiwan)
  274.37 +display locale: ID: en_US, Name: English (United States)
  274.38 +format locale: ID: zh_TW, Name: Chinese (Taiwan)
  274.39 +default charset: x-windows-950
  274.40 +
  274.41 +OS Locale (lcid: 405, name: cs-CZ): Czech (Czech Republic) - 1250
  274.42 +default locale: ID: cs_CZ, Name: Czech (Czech Republic)
  274.43 +display locale: ID: en_US, Name: English (United States)
  274.44 +format locale: ID: cs_CZ, Name: Czech (Czech Republic)
  274.45 +default charset: windows-1250
  274.46 +
  274.47 +OS Locale (lcid: 406, name: da-DK): Danish (Denmark) - 1252
  274.48 +default locale: ID: da_DK, Name: Danish (Denmark)
  274.49 +display locale: ID: en_US, Name: English (United States)
  274.50 +format locale: ID: da_DK, Name: Danish (Denmark)
  274.51 +default charset: windows-1252
  274.52 +
  274.53 +OS Locale (lcid: 407, name: de-DE): German (Germany) - 1252
  274.54 +default locale: ID: de_DE, Name: German (Germany)
  274.55 +display locale: ID: en_US, Name: English (United States)
  274.56 +format locale: ID: de_DE, Name: German (Germany)
  274.57 +default charset: windows-1252
  274.58 +
  274.59 +OS Locale (lcid: 408, name: el-GR): Greek (Greece) - 1253
  274.60 +default locale: ID: el_GR, Name: Greek (Greece)
  274.61 +display locale: ID: en_US, Name: English (United States)
  274.62 +format locale: ID: el_GR, Name: Greek (Greece)
  274.63 +default charset: windows-1253
  274.64 +
  274.65 +OS Locale (lcid: 409, name: en-US): English (United States) - 1252
  274.66 +default locale: ID: en_US, Name: English (United States)
  274.67 +display locale: ID: en_US, Name: English (United States)
  274.68 +format locale: ID: en_US, Name: English (United States)
  274.69 +default charset: windows-1252
  274.70 +
  274.71 +OS Locale (lcid: 40b, name: fi-FI): Finnish (Finland) - 1252
  274.72 +default locale: ID: fi_FI, Name: Finnish (Finland)
  274.73 +display locale: ID: en_US, Name: English (United States)
  274.74 +format locale: ID: fi_FI, Name: Finnish (Finland)
  274.75 +default charset: windows-1252
  274.76 +
  274.77 +OS Locale (lcid: 40c, name: fr-FR): French (France) - 1252
  274.78 +default locale: ID: fr_FR, Name: French (France)
  274.79 +display locale: ID: en_US, Name: English (United States)
  274.80 +format locale: ID: fr_FR, Name: French (France)
  274.81 +default charset: windows-1252
  274.82 +
  274.83 +OS Locale (lcid: 40d, name: he-IL): Hebrew (Israel) - 1255
  274.84 +default locale: ID: iw_IL, Name: Hebrew (Israel)
  274.85 +display locale: ID: en_US, Name: English (United States)
  274.86 +format locale: ID: iw_IL, Name: Hebrew (Israel)
  274.87 +default charset: windows-1255
  274.88 +
  274.89 +OS Locale (lcid: 40e, name: hu-HU): Hungarian (Hungary) - 1250
  274.90 +default locale: ID: hu_HU, Name: Hungarian (Hungary)
  274.91 +display locale: ID: en_US, Name: English (United States)
  274.92 +format locale: ID: hu_HU, Name: Hungarian (Hungary)
  274.93 +default charset: windows-1250
  274.94 +
  274.95 +OS Locale (lcid: 40f, name: is-IS): Icelandic (Iceland) - 1252
  274.96 +default locale: ID: is_IS, Name: Icelandic (Iceland)
  274.97 +display locale: ID: en_US, Name: English (United States)
  274.98 +format locale: ID: is_IS, Name: Icelandic (Iceland)
  274.99 +default charset: windows-1252
 274.100 +
 274.101 +OS Locale (lcid: 410, name: it-IT): Italian (Italy) - 1252
 274.102 +default locale: ID: it_IT, Name: Italian (Italy)
 274.103 +display locale: ID: en_US, Name: English (United States)
 274.104 +format locale: ID: it_IT, Name: Italian (Italy)
 274.105 +default charset: windows-1252
 274.106 +
 274.107 +OS Locale (lcid: 411, name: ja-JP): Japanese (Japan) - 932
 274.108 +default locale: ID: ja_JP, Name: Japanese (Japan)
 274.109 +display locale: ID: en_US, Name: English (United States)
 274.110 +format locale: ID: ja_JP, Name: Japanese (Japan)
 274.111 +default charset: windows-31j
 274.112 +
 274.113 +OS Locale (lcid: 412, name: ko-KR): Korean (Korea) - 949
 274.114 +default locale: ID: ko_KR, Name: Korean (South Korea)
 274.115 +display locale: ID: en_US, Name: English (United States)
 274.116 +format locale: ID: ko_KR, Name: Korean (South Korea)
 274.117 +default charset: x-windows-949
 274.118 +
 274.119 +OS Locale (lcid: 413, name: nl-NL): Dutch (Netherlands) - 1252
 274.120 +default locale: ID: nl_NL, Name: Dutch (Netherlands)
 274.121 +display locale: ID: en_US, Name: English (United States)
 274.122 +format locale: ID: nl_NL, Name: Dutch (Netherlands)
 274.123 +default charset: windows-1252
 274.124 +
 274.125 +OS Locale (lcid: 414, name: nb-NO): Norwegian (Bokmål) (Norway) - 1252
 274.126 +default locale: ID: no_NO, Name: Norwegian (Norway)
 274.127 +display locale: ID: en_US, Name: English (United States)
 274.128 +format locale: ID: no_NO, Name: Norwegian (Norway)
 274.129 +default charset: windows-1252
 274.130 +
 274.131 +OS Locale (lcid: 415, name: pl-PL): Polish (Poland) - 1250
 274.132 +default locale: ID: pl_PL, Name: Polish (Poland)
 274.133 +display locale: ID: en_US, Name: English (United States)
 274.134 +format locale: ID: pl_PL, Name: Polish (Poland)
 274.135 +default charset: windows-1250
 274.136 +
 274.137 +OS Locale (lcid: 416, name: pt-BR): Portuguese (Brazil) - 1252
 274.138 +default locale: ID: pt_BR, Name: Portuguese (Brazil)
 274.139 +display locale: ID: en_US, Name: English (United States)
 274.140 +format locale: ID: pt_BR, Name: Portuguese (Brazil)
 274.141 +default charset: windows-1252
 274.142 +
 274.143 +OS Locale (lcid: 417, name: rm-CH): Romansh (Switzerland) - 1252
 274.144 +default locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
 274.145 +display locale: ID: en_US, Name: English (United States)
 274.146 +format locale: ID: rm_CH, Name: Raeto-Romance (Switzerland)
 274.147 +default charset: windows-1252
 274.148 +
 274.149 +OS Locale (lcid: 418, name: ro-RO): Romanian (Romania) - 1250
 274.150 +default locale: ID: ro_RO, Name: Romanian (Romania)
 274.151 +display locale: ID: en_US, Name: English (United States)
 274.152 +format locale: ID: ro_RO, Name: Romanian (Romania)
 274.153 +default charset: windows-1250
 274.154 +
 274.155 +OS Locale (lcid: 419, name: ru-RU): Russian (Russia) - 1251
 274.156 +default locale: ID: ru_RU, Name: Russian (Russia)
 274.157 +display locale: ID: en_US, Name: English (United States)
 274.158 +format locale: ID: ru_RU, Name: Russian (Russia)
 274.159 +default charset: windows-1251
 274.160 +
 274.161 +OS Locale (lcid: 41a, name: hr-HR): Croatian (Croatia) - 1250
 274.162 +default locale: ID: hr_HR, Name: Croatian (Croatia)
 274.163 +display locale: ID: en_US, Name: English (United States)
 274.164 +format locale: ID: hr_HR, Name: Croatian (Croatia)
 274.165 +default charset: windows-1250
 274.166 +
 274.167 +OS Locale (lcid: 41b, name: sk-SK): Slovak (Slovakia) - 1250
 274.168 +default locale: ID: sk_SK, Name: Slovak (Slovakia)
 274.169 +display locale: ID: en_US, Name: English (United States)
 274.170 +format locale: ID: sk_SK, Name: Slovak (Slovakia)
 274.171 +default charset: windows-1250
 274.172 +
 274.173 +OS Locale (lcid: 41c, name: sq-AL): Albanian (Albania) - 1250
 274.174 +default locale: ID: sq_AL, Name: Albanian (Albania)
 274.175 +display locale: ID: en_US, Name: English (United States)
 274.176 +format locale: ID: sq_AL, Name: Albanian (Albania)
 274.177 +default charset: windows-1250
 274.178 +
 274.179 +OS Locale (lcid: 41d, name: sv-SE): Swedish (Sweden) - 1252
 274.180 +default locale: ID: sv_SE, Name: Swedish (Sweden)
 274.181 +display locale: ID: en_US, Name: English (United States)
 274.182 +format locale: ID: sv_SE, Name: Swedish (Sweden)
 274.183 +default charset: windows-1252
 274.184 +
 274.185 +OS Locale (lcid: 41e, name: th-TH): Thai (Thailand) - 874
 274.186 +default locale: ID: th_TH, Name: Thai (Thailand)
 274.187 +display locale: ID: en_US, Name: English (United States)
 274.188 +format locale: ID: th_TH, Name: Thai (Thailand)
 274.189 +default charset: x-windows-874
 274.190 +
 274.191 +OS Locale (lcid: 41f, name: tr-TR): Turkish (Turkey) - 1254
 274.192 +default locale: ID: tr_TR, Name: Turkish (Turkey)
 274.193 +display locale: ID: en_US, Name: English (United States)
 274.194 +format locale: ID: tr_TR, Name: Turkish (Turkey)
 274.195 +default charset: windows-1254
 274.196 +
 274.197 +OS Locale (lcid: 420, name: ur-PK): Urdu (Islamic Republic of Pakistan) - 1256
 274.198 +default locale: ID: ur_PK, Name: Urdu (Pakistan)
 274.199 +display locale: ID: en_US, Name: English (United States)
 274.200 +format locale: ID: ur_PK, Name: Urdu (Pakistan)
 274.201 +default charset: windows-1256
 274.202 +
 274.203 +OS Locale (lcid: 421, name: id-ID): Indonesian (Indonesia) - 1252
 274.204 +default locale: ID: in_ID, Name: Indonesian (Indonesia)
 274.205 +display locale: ID: en_US, Name: English (United States)
 274.206 +format locale: ID: in_ID, Name: Indonesian (Indonesia)
 274.207 +default charset: windows-1252
 274.208 +
 274.209 +OS Locale (lcid: 422, name: uk-UA): Ukrainian (Ukraine) - 1251
 274.210 +default locale: ID: uk_UA, Name: Ukrainian (Ukraine)
 274.211 +display locale: ID: en_US, Name: English (United States)
 274.212 +format locale: ID: uk_UA, Name: Ukrainian (Ukraine)
 274.213 +default charset: windows-1251
 274.214 +
 274.215 +OS Locale (lcid: 423, name: be-BY): Belarusian (Belarus) - 1251
 274.216 +default locale: ID: be_BY, Name: Belarusian (Belarus)
 274.217 +display locale: ID: en_US, Name: English (United States)
 274.218 +format locale: ID: be_BY, Name: Belarusian (Belarus)
 274.219 +default charset: windows-1251
 274.220 +
 274.221 +OS Locale (lcid: 424, name: sl-SI): Slovenian (Slovenia) - 1250
 274.222 +default locale: ID: sl_SI, Name: Slovenian (Slovenia)
 274.223 +display locale: ID: en_US, Name: English (United States)
 274.224 +format locale: ID: sl_SI, Name: Slovenian (Slovenia)
 274.225 +default charset: windows-1250
 274.226 +
 274.227 +OS Locale (lcid: 425, name: et-EE): Estonian (Estonia) - 1257
 274.228 +default locale: ID: et_EE, Name: Estonian (Estonia)
 274.229 +display locale: ID: en_US, Name: English (United States)
 274.230 +format locale: ID: et_EE, Name: Estonian (Estonia)
 274.231 +default charset: windows-1257
 274.232 +
 274.233 +OS Locale (lcid: 426, name: lv-LV): Latvian (Latvia) - 1257
 274.234 +default locale: ID: lv_LV, Name: Latvian (Latvia)
 274.235 +display locale: ID: en_US, Name: English (United States)
 274.236 +format locale: ID: lv_LV, Name: Latvian (Latvia)
 274.237 +default charset: windows-1257
 274.238 +
 274.239 +OS Locale (lcid: 427, name: lt-LT): Lithuanian (Lithuania) - 1257
 274.240 +default locale: ID: lt_LT, Name: Lithuanian (Lithuania)
 274.241 +display locale: ID: en_US, Name: English (United States)
 274.242 +format locale: ID: lt_LT, Name: Lithuanian (Lithuania)
 274.243 +default charset: windows-1257
 274.244 +
 274.245 +OS Locale (lcid: 428, name: tg-Cyrl-TJ): Tajik (Cyrillic) (Tajikistan) - 1251
 274.246 +default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
 274.247 +display locale: ID: en_US, Name: English (United States)
 274.248 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
 274.249 +default charset: windows-1251
 274.250 +
 274.251 +OS Locale (lcid: 428, name: tg-Cyrl): Tajik (Cyrillic) (Tajikistan) - 1251
 274.252 +default locale: ID: tg_TJ, Name: Tajik (Tajikistan)
 274.253 +display locale: ID: en_US, Name: English (United States)
 274.254 +format locale: ID: tg_TJ, Name: Tajik (Tajikistan)
 274.255 +default charset: windows-1251
 274.256 +
 274.257 +OS Locale (lcid: 429, name: fa-IR): Persian (Iran) - 1256
 274.258 +default locale: ID: fa_IR, Name: Persian (Iran)
 274.259 +display locale: ID: en_US, Name: English (United States)
 274.260 +format locale: ID: fa_IR, Name: Persian (Iran)
 274.261 +default charset: windows-1256
 274.262 +
 274.263 +OS Locale (lcid: 42a, name: vi-VN): Vietnamese (Vietnam) - 1258
 274.264 +default locale: ID: vi_VN, Name: Vietnamese (Vietnam)
 274.265 +display locale: ID: en_US, Name: English (United States)
 274.266 +format locale: ID: vi_VN, Name: Vietnamese (Vietnam)
 274.267 +default charset: windows-1258
 274.268 +
 274.269 +OS Locale (lcid: 42b, name: hy-AM): Armenian (Armenia) - 0
 274.270 +default locale: ID: hy_AM, Name: Armenian (Armenia)
 274.271 +display locale: ID: en_US, Name: English (United States)
 274.272 +format locale: ID: hy_AM, Name: Armenian (Armenia)
 274.273 +default charset: UTF-8
 274.274 +
 274.275 +OS Locale (lcid: 42c, name: az-Latn-AZ): Azeri (Latin) (Azerbaijan) - 1254
 274.276 +default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 274.277 +display locale: ID: en_US, Name: English (United States)
 274.278 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 274.279 +default charset: windows-1254
 274.280 +
 274.281 +OS Locale (lcid: 42c, name: az-Latn): Azeri (Latin) (Azerbaijan) - 1254
 274.282 +default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 274.283 +display locale: ID: en_US, Name: English (United States)
 274.284 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 274.285 +default charset: windows-1254
 274.286 +
 274.287 +OS Locale (lcid: 42d, name: eu-ES): Basque (Spain) - 1252
 274.288 +default locale: ID: eu_ES, Name: Basque (Spain)
 274.289 +display locale: ID: en_US, Name: English (United States)
 274.290 +format locale: ID: eu_ES, Name: Basque (Spain)
 274.291 +default charset: windows-1252
 274.292 +
 274.293 +OS Locale (lcid: 42e, name: hsb-DE): Upper Sorbian (Germany) - 1252
 274.294 +default locale: ID: en_US, Name: English (United States)
 274.295 +display locale: ID: en_US, Name: English (United States)
 274.296 +format locale: ID: en_US, Name: English (United States)
 274.297 +default charset: windows-1252
 274.298 +
 274.299 +OS Locale (lcid: 42e, name: hsb): Upper Sorbian (Germany) - 1252
 274.300 +default locale: ID: en_US, Name: English (United States)
 274.301 +display locale: ID: en_US, Name: English (United States)
 274.302 +format locale: ID: en_US, Name: English (United States)
 274.303 +default charset: windows-1252
 274.304 +
 274.305 +OS Locale (lcid: 42f, name: mk-MK): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
 274.306 +default locale: ID: mk_MK, Name: Macedonian (Macedonia)
 274.307 +display locale: ID: en_US, Name: English (United States)
 274.308 +format locale: ID: mk_MK, Name: Macedonian (Macedonia)
 274.309 +default charset: windows-1251
 274.310 +
 274.311 +OS Locale (lcid: 432, name: tn-ZA): Setswana (South Africa) - 1252
 274.312 +default locale: ID: tn_ZA, Name: Tswana (South Africa)
 274.313 +display locale: ID: en_US, Name: English (United States)
 274.314 +format locale: ID: tn_ZA, Name: Tswana (South Africa)
 274.315 +default charset: windows-1252
 274.316 +
 274.317 +OS Locale (lcid: 434, name: xh-ZA): isiXhosa (South Africa) - 1252
 274.318 +default locale: ID: xh_ZA, Name: Xhosa (South Africa)
 274.319 +display locale: ID: en_US, Name: English (United States)
 274.320 +format locale: ID: xh_ZA, Name: Xhosa (South Africa)
 274.321 +default charset: windows-1252
 274.322 +
 274.323 +OS Locale (lcid: 435, name: zu-ZA): isiZulu (South Africa) - 1252
 274.324 +default locale: ID: zu_ZA, Name: Zulu (South Africa)
 274.325 +display locale: ID: en_US, Name: English (United States)
 274.326 +format locale: ID: zu_ZA, Name: Zulu (South Africa)
 274.327 +default charset: windows-1252
 274.328 +
 274.329 +OS Locale (lcid: 436, name: af-ZA): Afrikaans (South Africa) - 1252
 274.330 +default locale: ID: af_ZA, Name: Afrikaans (South Africa)
 274.331 +display locale: ID: en_US, Name: English (United States)
 274.332 +format locale: ID: af_ZA, Name: Afrikaans (South Africa)
 274.333 +default charset: windows-1252
 274.334 +
 274.335 +OS Locale (lcid: 437, name: ka-GE): Georgian (Georgia) - 0
 274.336 +default locale: ID: ka_GE, Name: Georgian (Georgia)
 274.337 +display locale: ID: en_US, Name: English (United States)
 274.338 +format locale: ID: ka_GE, Name: Georgian (Georgia)
 274.339 +default charset: UTF-8
 274.340 +
 274.341 +OS Locale (lcid: 438, name: fo-FO): Faroese (Faroe Islands) - 1252
 274.342 +default locale: ID: fo_FO, Name: Faroese (Faroe Islands)
 274.343 +display locale: ID: en_US, Name: English (United States)
 274.344 +format locale: ID: fo_FO, Name: Faroese (Faroe Islands)
 274.345 +default charset: windows-1252
 274.346 +
 274.347 +OS Locale (lcid: 439, name: hi-IN): Hindi (India) - 0
 274.348 +default locale: ID: hi_IN, Name: Hindi (India)
 274.349 +display locale: ID: en_US, Name: English (United States)
 274.350 +format locale: ID: hi_IN, Name: Hindi (India)
 274.351 +default charset: UTF-8
 274.352 +
 274.353 +OS Locale (lcid: 43a, name: mt-MT): Maltese (Malta) - 0
 274.354 +default locale: ID: mt_MT, Name: Maltese (Malta)
 274.355 +display locale: ID: en_US, Name: English (United States)
 274.356 +format locale: ID: mt_MT, Name: Maltese (Malta)
 274.357 +default charset: UTF-8
 274.358 +
 274.359 +OS Locale (lcid: 43b, name: se-NO): Sami (Northern) (Norway) - 1252
 274.360 +default locale: ID: se_NO, Name: Northern Sami (Norway)
 274.361 +display locale: ID: en_US, Name: English (United States)
 274.362 +format locale: ID: se_NO, Name: Northern Sami (Norway)
 274.363 +default charset: windows-1252
 274.364 +
 274.365 +OS Locale (lcid: 43e, name: ms-MY): Malay (Malaysia) - 1252
 274.366 +default locale: ID: ms_MY, Name: Malay (Malaysia)
 274.367 +display locale: ID: en_US, Name: English (United States)
 274.368 +format locale: ID: ms_MY, Name: Malay (Malaysia)
 274.369 +default charset: windows-1252
 274.370 +
 274.371 +OS Locale (lcid: 43f, name: kk-KZ): Kazakh (Kazakhstan) - 0
 274.372 +default locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
 274.373 +display locale: ID: en_US, Name: English (United States)
 274.374 +format locale: ID: kk_KZ, Name: Kazakh (Kazakhstan)
 274.375 +default charset: UTF-8
 274.376 +
 274.377 +OS Locale (lcid: 440, name: ky-KG): Kyrgyz (Kyrgyzstan) - 1251
 274.378 +default locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
 274.379 +display locale: ID: en_US, Name: English (United States)
 274.380 +format locale: ID: ky_KG, Name: Kirghiz (Kyrgyzstan)
 274.381 +default charset: windows-1251
 274.382 +
 274.383 +OS Locale (lcid: 441, name: sw-KE): Kiswahili (Kenya) - 1252
 274.384 +default locale: ID: sw_KE, Name: Swahili (Kenya)
 274.385 +display locale: ID: en_US, Name: English (United States)
 274.386 +format locale: ID: sw_KE, Name: Swahili (Kenya)
 274.387 +default charset: windows-1252
 274.388 +
 274.389 +OS Locale (lcid: 442, name: tk-TM): Turkmen (Turkmenistan) - 1250
 274.390 +default locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
 274.391 +display locale: ID: en_US, Name: English (United States)
 274.392 +format locale: ID: tk_TM, Name: Turkmen (Turkmenistan)
 274.393 +default charset: windows-1250
 274.394 +
 274.395 +OS Locale (lcid: 443, name: uz-Latn): Uzbek (Latin) (Uzbekistan) - 1254
 274.396 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 274.397 +display locale: ID: en_US, Name: English (United States)
 274.398 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 274.399 +default charset: windows-1254
 274.400 +
 274.401 +OS Locale (lcid: 443, name: uz-Latn-UZ): Uzbek (Latin) (Uzbekistan) - 1254
 274.402 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 274.403 +display locale: ID: en_US, Name: English (United States)
 274.404 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 274.405 +default charset: windows-1254
 274.406 +
 274.407 +OS Locale (lcid: 444, name: tt-RU): Tatar (Russia) - 1251
 274.408 +default locale: ID: tt_RU, Name: Tatar (Russia)
 274.409 +display locale: ID: en_US, Name: English (United States)
 274.410 +format locale: ID: tt_RU, Name: Tatar (Russia)
 274.411 +default charset: windows-1251
 274.412 +
 274.413 +OS Locale (lcid: 445, name: bn-IN): Bengali (India) - 0
 274.414 +default locale: ID: bn_IN, Name: Bengali (India)
 274.415 +display locale: ID: en_US, Name: English (United States)
 274.416 +format locale: ID: bn_IN, Name: Bengali (India)
 274.417 +default charset: UTF-8
 274.418 +
 274.419 +OS Locale (lcid: 446, name: pa-IN): Punjabi (India) - 0
 274.420 +default locale: ID: pa_IN, Name: Panjabi (India)
 274.421 +display locale: ID: en_US, Name: English (United States)
 274.422 +format locale: ID: pa_IN, Name: Panjabi (India)
 274.423 +default charset: UTF-8
 274.424 +
 274.425 +OS Locale (lcid: 447, name: gu-IN): Gujarati (India) - 0
 274.426 +default locale: ID: gu_IN, Name: Gujarati (India)
 274.427 +display locale: ID: en_US, Name: English (United States)
 274.428 +format locale: ID: gu_IN, Name: Gujarati (India)
 274.429 +default charset: UTF-8
 274.430 +
 274.431 +OS Locale (lcid: 448, name: or-IN): Oriya (India) - 0
 274.432 +default locale: ID: or_IN, Name: Oriya (India)
 274.433 +display locale: ID: en_US, Name: English (United States)
 274.434 +format locale: ID: or_IN, Name: Oriya (India)
 274.435 +default charset: UTF-8
 274.436 +
 274.437 +OS Locale (lcid: 449, name: ta-IN): Tamil (India) - 0
 274.438 +default locale: ID: ta_IN, Name: Tamil (India)
 274.439 +display locale: ID: en_US, Name: English (United States)
 274.440 +format locale: ID: ta_IN, Name: Tamil (India)
 274.441 +default charset: UTF-8
 274.442 +
 274.443 +OS Locale (lcid: 44a, name: te-IN): Telugu (India) - 0
 274.444 +default locale: ID: te_IN, Name: Telugu (India)
 274.445 +display locale: ID: en_US, Name: English (United States)
 274.446 +format locale: ID: te_IN, Name: Telugu (India)
 274.447 +default charset: UTF-8
 274.448 +
 274.449 +OS Locale (lcid: 44b, name: kn-IN): Kannada (India) - 0
 274.450 +default locale: ID: kn_IN, Name: Kannada (India)
 274.451 +display locale: ID: en_US, Name: English (United States)
 274.452 +format locale: ID: kn_IN, Name: Kannada (India)
 274.453 +default charset: UTF-8
 274.454 +
 274.455 +OS Locale (lcid: 44c, name: ml-IN): Malayalam (India) - 0
 274.456 +default locale: ID: ml_IN, Name: Malayalam (India)
 274.457 +display locale: ID: en_US, Name: English (United States)
 274.458 +format locale: ID: ml_IN, Name: Malayalam (India)
 274.459 +default charset: UTF-8
 274.460 +
 274.461 +OS Locale (lcid: 44d, name: as-IN): Assamese (India) - 0
 274.462 +default locale: ID: as_IN, Name: Assamese (India)
 274.463 +display locale: ID: en_US, Name: English (United States)
 274.464 +format locale: ID: as_IN, Name: Assamese (India)
 274.465 +default charset: UTF-8
 274.466 +
 274.467 +OS Locale (lcid: 44e, name: mr-IN): Marathi (India) - 0
 274.468 +default locale: ID: mr_IN, Name: Marathi (India)
 274.469 +display locale: ID: en_US, Name: English (United States)
 274.470 +format locale: ID: mr_IN, Name: Marathi (India)
 274.471 +default charset: UTF-8
 274.472 +
 274.473 +OS Locale (lcid: 44f, name: sa-IN): Sanskrit (India) - 0
 274.474 +default locale: ID: sa_IN, Name: Sanskrit (India)
 274.475 +display locale: ID: en_US, Name: English (United States)
 274.476 +format locale: ID: sa_IN, Name: Sanskrit (India)
 274.477 +default charset: UTF-8
 274.478 +
 274.479 +OS Locale (lcid: 450, name: mn-MN): Mongolian (Cyrillic) (Mongolia) - 1251
 274.480 +default locale: ID: mn_MN, Name: Mongolian (Mongolia)
 274.481 +display locale: ID: en_US, Name: English (United States)
 274.482 +format locale: ID: mn_MN, Name: Mongolian (Mongolia)
 274.483 +default charset: windows-1251
 274.484 +
 274.485 +OS Locale (lcid: 450, name: mn-Cyrl): Mongolian (Cyrillic) (Mongolia) - 1251
 274.486 +default locale: ID: mn_MN, Name: Mongolian (Mongolia)
 274.487 +display locale: ID: en_US, Name: English (United States)
 274.488 +format locale: ID: mn_MN, Name: Mongolian (Mongolia)
 274.489 +default charset: windows-1251
 274.490 +
 274.491 +OS Locale (lcid: 451, name: bo-CN): Tibetan (People's Republic of China) - 0
 274.492 +default locale: ID: bo_CN, Name: Tibetan (China)
 274.493 +display locale: ID: en_US, Name: English (United States)
 274.494 +format locale: ID: bo_CN, Name: Tibetan (China)
 274.495 +default charset: UTF-8
 274.496 +
 274.497 +OS Locale (lcid: 452, name: cy-GB): Welsh (United Kingdom) - 1252
 274.498 +default locale: ID: cy_GB, Name: Welsh (United Kingdom)
 274.499 +display locale: ID: en_US, Name: English (United States)
 274.500 +format locale: ID: cy_GB, Name: Welsh (United Kingdom)
 274.501 +default charset: windows-1252
 274.502 +
 274.503 +OS Locale (lcid: 453, name: km-KH): Khmer (Cambodia) - 0
 274.504 +default locale: ID: km_KH, Name: Khmer (Cambodia)
 274.505 +display locale: ID: en_US, Name: English (United States)
 274.506 +format locale: ID: km_KH, Name: Khmer (Cambodia)
 274.507 +default charset: UTF-8
 274.508 +
 274.509 +OS Locale (lcid: 454, name: lo-LA): Lao (Lao P.D.R.) - 0
 274.510 +default locale: ID: lo_LA, Name: Lao (Laos)
 274.511 +display locale: ID: en_US, Name: English (United States)
 274.512 +format locale: ID: lo_LA, Name: Lao (Laos)
 274.513 +default charset: UTF-8
 274.514 +
 274.515 +OS Locale (lcid: 456, name: gl-ES): Galician (Spain) - 1252
 274.516 +default locale: ID: gl_ES, Name: Gallegan (Spain)
 274.517 +display locale: ID: en_US, Name: English (United States)
 274.518 +format locale: ID: gl_ES, Name: Gallegan (Spain)
 274.519 +default charset: windows-1252
 274.520 +
 274.521 +OS Locale (lcid: 457, name: kok-IN): Konkani (India) - 0
 274.522 +default locale: ID: en_US, Name: English (United States)
 274.523 +display locale: ID: en_US, Name: English (United States)
 274.524 +format locale: ID: en_US, Name: English (United States)
 274.525 +default charset: UTF-8
 274.526 +
 274.527 +OS Locale (lcid: 457, name: kok): Konkani (India) - 0
 274.528 +default locale: ID: en_US, Name: English (United States)
 274.529 +display locale: ID: en_US, Name: English (United States)
 274.530 +format locale: ID: en_US, Name: English (United States)
 274.531 +default charset: UTF-8
 274.532 +
 274.533 +OS Locale (lcid: 45a, name: syr): Syriac (Syria) - 0
 274.534 +default locale: ID: en_US, Name: English (United States)
 274.535 +display locale: ID: en_US, Name: English (United States)
 274.536 +format locale: ID: en_US, Name: English (United States)
 274.537 +default charset: UTF-8
 274.538 +
 274.539 +OS Locale (lcid: 45a, name: syr-SY): Syriac (Syria) - 0
 274.540 +default locale: ID: en_US, Name: English (United States)
 274.541 +display locale: ID: en_US, Name: English (United States)
 274.542 +format locale: ID: en_US, Name: English (United States)
 274.543 +default charset: UTF-8
 274.544 +
 274.545 +OS Locale (lcid: 45b, name: si-LK): Sinhala (Sri Lanka) - 0
 274.546 +default locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
 274.547 +display locale: ID: en_US, Name: English (United States)
 274.548 +format locale: ID: si_LK, Name: Sinhalese (Sri Lanka)
 274.549 +default charset: UTF-8
 274.550 +
 274.551 +OS Locale (lcid: 45d, name: iu-Cans-CA): Inuktitut (Syllabics) (Canada) - 0
 274.552 +default locale: ID: iu_CA, Name: Inuktitut (Canada)
 274.553 +display locale: ID: en_US, Name: English (United States)
 274.554 +format locale: ID: iu_CA, Name: Inuktitut (Canada)
 274.555 +default charset: UTF-8
 274.556 +
 274.557 +OS Locale (lcid: 45d, name: iu-Cans): Inuktitut (Syllabics) (Canada) - 0
 274.558 +default locale: ID: iu_CA, Name: Inuktitut (Canada)
 274.559 +display locale: ID: en_US, Name: English (United States)
 274.560 +format locale: ID: iu_CA, Name: Inuktitut (Canada)
 274.561 +default charset: UTF-8
 274.562 +
 274.563 +OS Locale (lcid: 45e, name: am-ET): Amharic (Ethiopia) - 0
 274.564 +default locale: ID: am_ET, Name: Amharic (Ethiopia)
 274.565 +display locale: ID: en_US, Name: English (United States)
 274.566 +format locale: ID: am_ET, Name: Amharic (Ethiopia)
 274.567 +default charset: UTF-8
 274.568 +
 274.569 +OS Locale (lcid: 461, name: ne-NP): Nepali (Nepal) - 0
 274.570 +default locale: ID: ne_NP, Name: Nepali (Nepal)
 274.571 +display locale: ID: en_US, Name: English (United States)
 274.572 +format locale: ID: ne_NP, Name: Nepali (Nepal)
 274.573 +default charset: UTF-8
 274.574 +
 274.575 +OS Locale (lcid: 462, name: fy-NL): Frisian (Netherlands) - 1252
 274.576 +default locale: ID: fy_NL, Name: Frisian (Netherlands)
 274.577 +display locale: ID: en_US, Name: English (United States)
 274.578 +format locale: ID: fy_NL, Name: Frisian (Netherlands)
 274.579 +default charset: windows-1252
 274.580 +
 274.581 +OS Locale (lcid: 463, name: ps-AF): Pashto (Afghanistan) - 0
 274.582 +default locale: ID: ps_AF, Name: Pushto (Afghanistan)
 274.583 +display locale: ID: en_US, Name: English (United States)
 274.584 +format locale: ID: ps_AF, Name: Pushto (Afghanistan)
 274.585 +default charset: UTF-8
 274.586 +
 274.587 +OS Locale (lcid: 464, name: fil-PH): Filipino (Philippines) - 1252
 274.588 +default locale: ID: en_US, Name: English (United States)
 274.589 +display locale: ID: en_US, Name: English (United States)
 274.590 +format locale: ID: en_US, Name: English (United States)
 274.591 +default charset: windows-1252
 274.592 +
 274.593 +OS Locale (lcid: 464, name: fil): Filipino (Philippines) - 1252
 274.594 +default locale: ID: en_US, Name: English (United States)
 274.595 +display locale: ID: en_US, Name: English (United States)
 274.596 +format locale: ID: en_US, Name: English (United States)
 274.597 +default charset: windows-1252
 274.598 +
 274.599 +OS Locale (lcid: 465, name: dv-MV): Divehi (Maldives) - 0
 274.600 +default locale: ID: dv_MV, Name: Divehi (Maldives)
 274.601 +display locale: ID: en_US, Name: English (United States)
 274.602 +format locale: ID: dv_MV, Name: Divehi (Maldives)
 274.603 +default charset: UTF-8
 274.604 +
 274.605 +OS Locale (lcid: 468, name: ha-Latn-NG): Hausa (Latin) (Nigeria) - 1252
 274.606 +default locale: ID: ha_NG, Name: Hausa (Nigeria)
 274.607 +display locale: ID: en_US, Name: English (United States)
 274.608 +format locale: ID: ha_NG, Name: Hausa (Nigeria)
 274.609 +default charset: windows-1252
 274.610 +
 274.611 +OS Locale (lcid: 468, name: ha-Latn): Hausa (Latin) (Nigeria) - 1252
 274.612 +default locale: ID: ha_NG, Name: Hausa (Nigeria)
 274.613 +display locale: ID: en_US, Name: English (United States)
 274.614 +format locale: ID: ha_NG, Name: Hausa (Nigeria)
 274.615 +default charset: windows-1252
 274.616 +
 274.617 +OS Locale (lcid: 46a, name: yo-NG): Yoruba (Nigeria) - 1252
 274.618 +default locale: ID: yo_NG, Name: Yoruba (Nigeria)
 274.619 +display locale: ID: en_US, Name: English (United States)
 274.620 +format locale: ID: yo_NG, Name: Yoruba (Nigeria)
 274.621 +default charset: windows-1252
 274.622 +
 274.623 +OS Locale (lcid: 46b, name: quz): Quechua (Bolivia) - 1252
 274.624 +default locale: ID: en_US, Name: English (United States)
 274.625 +display locale: ID: en_US, Name: English (United States)
 274.626 +format locale: ID: en_US, Name: English (United States)
 274.627 +default charset: windows-1252
 274.628 +
 274.629 +OS Locale (lcid: 46b, name: quz-BO): Quechua (Bolivia) - 1252
 274.630 +default locale: ID: en_US, Name: English (United States)
 274.631 +display locale: ID: en_US, Name: English (United States)
 274.632 +format locale: ID: en_US, Name: English (United States)
 274.633 +default charset: windows-1252
 274.634 +
 274.635 +OS Locale (lcid: 46c, name: nso): Sesotho sa Leboa (South Africa) - 1252
 274.636 +default locale: ID: en_US, Name: English (United States)
 274.637 +display locale: ID: en_US, Name: English (United States)
 274.638 +format locale: ID: en_US, Name: English (United States)
 274.639 +default charset: windows-1252
 274.640 +
 274.641 +OS Locale (lcid: 46c, name: nso-ZA): Sesotho sa Leboa (South Africa) - 1252
 274.642 +default locale: ID: en_US, Name: English (United States)
 274.643 +display locale: ID: en_US, Name: English (United States)
 274.644 +format locale: ID: en_US, Name: English (United States)
 274.645 +default charset: windows-1252
 274.646 +
 274.647 +OS Locale (lcid: 46d, name: ba-RU): Bashkir (Russia) - 1251
 274.648 +default locale: ID: ba_RU, Name: Bashkir (Russia)
 274.649 +display locale: ID: en_US, Name: English (United States)
 274.650 +format locale: ID: ba_RU, Name: Bashkir (Russia)
 274.651 +default charset: windows-1251
 274.652 +
 274.653 +OS Locale (lcid: 46e, name: lb-LU): Luxembourgish (Luxembourg) - 1252
 274.654 +default locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
 274.655 +display locale: ID: en_US, Name: English (United States)
 274.656 +format locale: ID: lb_LU, Name: Luxembourgish (Luxembourg)
 274.657 +default charset: windows-1252
 274.658 +
 274.659 +OS Locale (lcid: 46f, name: kl-GL): Greenlandic (Greenland) - 1252
 274.660 +default locale: ID: kl_GL, Name: Greenlandic (Greenland)
 274.661 +display locale: ID: en_US, Name: English (United States)
 274.662 +format locale: ID: kl_GL, Name: Greenlandic (Greenland)
 274.663 +default charset: windows-1252
 274.664 +
 274.665 +OS Locale (lcid: 470, name: ig-NG): Igbo (Nigeria) - 1252
 274.666 +default locale: ID: ig_NG, Name: Igbo (Nigeria)
 274.667 +display locale: ID: en_US, Name: English (United States)
 274.668 +format locale: ID: ig_NG, Name: Igbo (Nigeria)
 274.669 +default charset: windows-1252
 274.670 +
 274.671 +OS Locale (lcid: 478, name: ii-CN): Yi (People's Republic of China) - 0
 274.672 +default locale: ID: ii_CN, Name: Sichuan Yi (China)
 274.673 +display locale: ID: en_US, Name: English (United States)
 274.674 +format locale: ID: ii_CN, Name: Sichuan Yi (China)
 274.675 +default charset: UTF-8
 274.676 +
 274.677 +OS Locale (lcid: 47a, name: arn): Mapudungun (Chile) - 1252
 274.678 +default locale: ID: en_US, Name: English (United States)
 274.679 +display locale: ID: en_US, Name: English (United States)
 274.680 +format locale: ID: en_US, Name: English (United States)
 274.681 +default charset: windows-1252
 274.682 +
 274.683 +OS Locale (lcid: 47a, name: arn-CL): Mapudungun (Chile) - 1252
 274.684 +default locale: ID: en_US, Name: English (United States)
 274.685 +display locale: ID: en_US, Name: English (United States)
 274.686 +format locale: ID: en_US, Name: English (United States)
 274.687 +default charset: windows-1252
 274.688 +
 274.689 +OS Locale (lcid: 47c, name: moh): Mohawk (Canada) - 1252
 274.690 +default locale: ID: en_US, Name: English (United States)
 274.691 +display locale: ID: en_US, Name: English (United States)
 274.692 +format locale: ID: en_US, Name: English (United States)
 274.693 +default charset: windows-1252
 274.694 +
 274.695 +OS Locale (lcid: 47c, name: moh-CA): Mohawk (Canada) - 1252
 274.696 +default locale: ID: en_US, Name: English (United States)
 274.697 +display locale: ID: en_US, Name: English (United States)
 274.698 +format locale: ID: en_US, Name: English (United States)
 274.699 +default charset: windows-1252
 274.700 +
 274.701 +OS Locale (lcid: 47e, name: br-FR): Breton (France) - 1252
 274.702 +default locale: ID: br_FR, Name: Breton (France)
 274.703 +display locale: ID: en_US, Name: English (United States)
 274.704 +format locale: ID: br_FR, Name: Breton (France)
 274.705 +default charset: windows-1252
 274.706 +
 274.707 +OS Locale (lcid: 480, name: ug-CN): Uyghur (People's Republic of China) - 1256
 274.708 +default locale: ID: ug_CN, Name: Uighur (China)
 274.709 +display locale: ID: en_US, Name: English (United States)
 274.710 +format locale: ID: ug_CN, Name: Uighur (China)
 274.711 +default charset: windows-1256
 274.712 +
 274.713 +OS Locale (lcid: 481, name: mi-NZ): Maori (New Zealand) - 0
 274.714 +default locale: ID: mi_NZ, Name: Maori (New Zealand)
 274.715 +display locale: ID: en_US, Name: English (United States)
 274.716 +format locale: ID: mi_NZ, Name: Maori (New Zealand)
 274.717 +default charset: UTF-8
 274.718 +
 274.719 +OS Locale (lcid: 482, name: oc-FR): Occitan (France) - 1252
 274.720 +default locale: ID: oc_FR, Name: Occitan (France)
 274.721 +display locale: ID: en_US, Name: English (United States)
 274.722 +format locale: ID: oc_FR, Name: Occitan (France)
 274.723 +default charset: windows-1252
 274.724 +
 274.725 +OS Locale (lcid: 483, name: co-FR): Corsican (France) - 1252
 274.726 +default locale: ID: co_FR, Name: Corsican (France)
 274.727 +display locale: ID: en_US, Name: English (United States)
 274.728 +format locale: ID: co_FR, Name: Corsican (France)
 274.729 +default charset: windows-1252
 274.730 +
 274.731 +OS Locale (lcid: 484, name: gsw): Alsatian (France) - 1252
 274.732 +default locale: ID: en_US, Name: English (United States)
 274.733 +display locale: ID: en_US, Name: English (United States)
 274.734 +format locale: ID: en_US, Name: English (United States)
 274.735 +default charset: windows-1252
 274.736 +
 274.737 +OS Locale (lcid: 484, name: gsw-FR): Alsatian (France) - 1252
 274.738 +default locale: ID: en_US, Name: English (United States)
 274.739 +display locale: ID: en_US, Name: English (United States)
 274.740 +format locale: ID: en_US, Name: English (United States)
 274.741 +default charset: windows-1252
 274.742 +
 274.743 +OS Locale (lcid: 485, name: sah): Yakut (Russia) - 1251
 274.744 +default locale: ID: en_US, Name: English (United States)
 274.745 +display locale: ID: en_US, Name: English (United States)
 274.746 +format locale: ID: en_US, Name: English (United States)
 274.747 +default charset: windows-1251
 274.748 +
 274.749 +OS Locale (lcid: 485, name: sah-RU): Yakut (Russia) - 1251
 274.750 +default locale: ID: en_US, Name: English (United States)
 274.751 +display locale: ID: en_US, Name: English (United States)
 274.752 +format locale: ID: en_US, Name: English (United States)
 274.753 +default charset: windows-1251
 274.754 +
 274.755 +OS Locale (lcid: 486, name: qut): K'iche (Guatemala) - 1252
 274.756 +default locale: ID: en_US, Name: English (United States)
 274.757 +display locale: ID: en_US, Name: English (United States)
 274.758 +format locale: ID: en_US, Name: English (United States)
 274.759 +default charset: windows-1252
 274.760 +
 274.761 +OS Locale (lcid: 486, name: qut-GT): K'iche (Guatemala) - 1252
 274.762 +default locale: ID: en_US, Name: English (United States)
 274.763 +display locale: ID: en_US, Name: English (United States)
 274.764 +format locale: ID: en_US, Name: English (United States)
 274.765 +default charset: windows-1252
 274.766 +
 274.767 +OS Locale (lcid: 487, name: rw-RW): Kinyarwanda (Rwanda) - 1252
 274.768 +default locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 274.769 +display locale: ID: en_US, Name: English (United States)
 274.770 +format locale: ID: rw_RW, Name: Kinyarwanda (Rwanda)
 274.771 +default charset: windows-1252
 274.772 +
 274.773 +OS Locale (lcid: 488, name: wo-SN): Wolof (Senegal) - 1252
 274.774 +default locale: ID: wo_SN, Name: Wolof (Senegal)
 274.775 +display locale: ID: en_US, Name: English (United States)
 274.776 +format locale: ID: wo_SN, Name: Wolof (Senegal)
 274.777 +default charset: windows-1252
 274.778 +
 274.779 +OS Locale (lcid: 48c, name: prs): Dari (Afghanistan) - 1256
 274.780 +default locale: ID: en_US, Name: English (United States)
 274.781 +display locale: ID: en_US, Name: English (United States)
 274.782 +format locale: ID: en_US, Name: English (United States)
 274.783 +default charset: windows-1256
 274.784 +
 274.785 +OS Locale (lcid: 48c, name: prs-AF): Dari (Afghanistan) - 1256
 274.786 +default locale: ID: en_US, Name: English (United States)
 274.787 +display locale: ID: en_US, Name: English (United States)
 274.788 +format locale: ID: en_US, Name: English (United States)
 274.789 +default charset: windows-1256
 274.790 +
 274.791 +OS Locale (lcid: 491, name: gd-GB): Scottish Gaelic (United Kingdom) - 1252
 274.792 +default locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 274.793 +display locale: ID: en_US, Name: English (United States)
 274.794 +format locale: ID: gd_GB, Name: Scottish Gaelic (United Kingdom)
 274.795 +default charset: windows-1252
 274.796 +
 274.797 +OS Locale (lcid: 801, name: ar-IQ): Arabic (Iraq) - 1256
 274.798 +default locale: ID: ar_IQ, Name: Arabic (Iraq)
 274.799 +display locale: ID: en_US, Name: English (United States)
 274.800 +format locale: ID: ar_IQ, Name: Arabic (Iraq)
 274.801 +default charset: windows-1256
 274.802 +
 274.803 +OS Locale (lcid: 804, name: zh-Hans): Chinese (Simplified) (People's Republic of China) - 936
 274.804 +default locale: ID: zh_CN, Name: Chinese (China)
 274.805 +display locale: ID: en_US, Name: English (United States)
 274.806 +format locale: ID: zh_CN, Name: Chinese (China)
 274.807 +default charset: GBK
 274.808 +
 274.809 +OS Locale (lcid: 804, name: zh-CN): Chinese (Simplified) (People's Republic of China) - 936
 274.810 +default locale: ID: zh_CN, Name: Chinese (China)
 274.811 +display locale: ID: en_US, Name: English (United States)
 274.812 +format locale: ID: zh_CN, Name: Chinese (China)
 274.813 +default charset: GBK
 274.814 +
 274.815 +OS Locale (lcid: 807, name: de-CH): German (Switzerland) - 1252
 274.816 +default locale: ID: de_CH, Name: German (Switzerland)
 274.817 +display locale: ID: en_US, Name: English (United States)
 274.818 +format locale: ID: de_CH, Name: German (Switzerland)
 274.819 +default charset: windows-1252
 274.820 +
 274.821 +OS Locale (lcid: 809, name: en-GB): English (United Kingdom) - 1252
 274.822 +default locale: ID: en_GB, Name: English (United Kingdom)
 274.823 +display locale: ID: en_GB, Name: English (United Kingdom)
 274.824 +format locale: ID: en_GB, Name: English (United Kingdom)
 274.825 +default charset: windows-1252
 274.826 +
 274.827 +OS Locale (lcid: 80a, name: es-MX): Spanish (Mexico) - 1252
 274.828 +default locale: ID: es_MX, Name: Spanish (Mexico)
 274.829 +display locale: ID: en_US, Name: English (United States)
 274.830 +format locale: ID: es_MX, Name: Spanish (Mexico)
 274.831 +default charset: windows-1252
 274.832 +
 274.833 +OS Locale (lcid: 80c, name: fr-BE): French (Belgium) - 1252
 274.834 +default locale: ID: fr_BE, Name: French (Belgium)
 274.835 +display locale: ID: en_US, Name: English (United States)
 274.836 +format locale: ID: fr_BE, Name: French (Belgium)
 274.837 +default charset: windows-1252
 274.838 +
 274.839 +OS Locale (lcid: 810, name: it-CH): Italian (Switzerland) - 1252
 274.840 +default locale: ID: it_CH, Name: Italian (Switzerland)
 274.841 +display locale: ID: en_US, Name: English (United States)
 274.842 +format locale: ID: it_CH, Name: Italian (Switzerland)
 274.843 +default charset: windows-1252
 274.844 +
 274.845 +OS Locale (lcid: 813, name: nl-BE): Dutch (Belgium) - 1252
 274.846 +default locale: ID: nl_BE, Name: Dutch (Belgium)
 274.847 +display locale: ID: en_US, Name: English (United States)
 274.848 +format locale: ID: nl_BE, Name: Dutch (Belgium)
 274.849 +default charset: windows-1252
 274.850 +
 274.851 +OS Locale (lcid: 814, name: nn-NO): Norwegian (Nynorsk) (Norway) - 1252
 274.852 +default locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 274.853 +display locale: ID: en_US, Name: English (United States)
 274.854 +format locale: ID: no_NO_NY, Name: Norwegian (Norway,Nynorsk)
 274.855 +default charset: windows-1252
 274.856 +
 274.857 +OS Locale (lcid: 816, name: pt-PT): Portuguese (Portugal) - 1252
 274.858 +default locale: ID: pt_PT, Name: Portuguese (Portugal)
 274.859 +display locale: ID: en_US, Name: English (United States)
 274.860 +format locale: ID: pt_PT, Name: Portuguese (Portugal)
 274.861 +default charset: windows-1252
 274.862 +
 274.863 +OS Locale (lcid: 81a, name: sr-Latn-CS): Serbian (Latin) (Serbia and Montenegro (Former)) - 1250
 274.864 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
 274.865 +display locale: ID: en_US, Name: English (United States)
 274.866 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
 274.867 +default charset: windows-1250
 274.868 +
 274.869 +OS Locale (lcid: 81d, name: sv-FI): Swedish (Finland) - 1252
 274.870 +default locale: ID: sv_FI, Name: Swedish (Finland)
 274.871 +display locale: ID: en_US, Name: English (United States)
 274.872 +format locale: ID: sv_FI, Name: Swedish (Finland)
 274.873 +default charset: windows-1252
 274.874 +
 274.875 +OS Locale (lcid: 82c, name: az-Cyrl-AZ): Azeri (Cyrillic) (Azerbaijan) - 1251
 274.876 +default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 274.877 +display locale: ID: en_US, Name: English (United States)
 274.878 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 274.879 +default charset: windows-1251
 274.880 +
 274.881 +OS Locale (lcid: 82c, name: az-Cyrl): Azeri (Cyrillic) (Azerbaijan) - 1251
 274.882 +default locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 274.883 +display locale: ID: en_US, Name: English (United States)
 274.884 +format locale: ID: az_AZ, Name: Azerbaijani (Azerbaijan)
 274.885 +default charset: windows-1251
 274.886 +
 274.887 +OS Locale (lcid: 82e, name: dsb): Lower Sorbian (Germany) - 1252
 274.888 +default locale: ID: en_US, Name: English (United States)
 274.889 +display locale: ID: en_US, Name: English (United States)
 274.890 +format locale: ID: en_US, Name: English (United States)
 274.891 +default charset: windows-1252
 274.892 +
 274.893 +OS Locale (lcid: 82e, name: dsb-DE): Lower Sorbian (Germany) - 1252
 274.894 +default locale: ID: en_US, Name: English (United States)
 274.895 +display locale: ID: en_US, Name: English (United States)
 274.896 +format locale: ID: en_US, Name: English (United States)
 274.897 +default charset: windows-1252
 274.898 +
 274.899 +OS Locale (lcid: 83b, name: se-SE): Sami (Northern) (Sweden) - 1252
 274.900 +default locale: ID: se_SE, Name: Northern Sami (Sweden)
 274.901 +display locale: ID: en_US, Name: English (United States)
 274.902 +format locale: ID: se_SE, Name: Northern Sami (Sweden)
 274.903 +default charset: windows-1252
 274.904 +
 274.905 +OS Locale (lcid: 83c, name: ga-IE): Irish (Ireland) - 1252
 274.906 +default locale: ID: ga_IE, Name: Irish (Ireland)
 274.907 +display locale: ID: en_US, Name: English (United States)
 274.908 +format locale: ID: ga_IE, Name: Irish (Ireland)
 274.909 +default charset: windows-1252
 274.910 +
 274.911 +OS Locale (lcid: 83e, name: ms-BN): Malay (Brunei Darussalam) - 1252
 274.912 +default locale: ID: ms_BN, Name: Malay (Brunei)
 274.913 +display locale: ID: en_US, Name: English (United States)
 274.914 +format locale: ID: ms_BN, Name: Malay (Brunei)
 274.915 +default charset: windows-1252
 274.916 +
 274.917 +OS Locale (lcid: 843, name: uz-Cyrl-UZ): Uzbek (Cyrillic) (Uzbekistan) - 1251
 274.918 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 274.919 +display locale: ID: en_US, Name: English (United States)
 274.920 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 274.921 +default charset: windows-1251
 274.922 +
 274.923 +OS Locale (lcid: 843, name: uz-Cyrl): Uzbek (Cyrillic) (Uzbekistan) - 1251
 274.924 +default locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 274.925 +display locale: ID: en_US, Name: English (United States)
 274.926 +format locale: ID: uz_UZ, Name: Uzbek (Uzbekistan)
 274.927 +default charset: windows-1251
 274.928 +
 274.929 +OS Locale (lcid: 845, name: bn-BD): Bengali (Bangladesh) - 0
 274.930 +default locale: ID: bn_BD, Name: Bengali (Bangladesh)
 274.931 +display locale: ID: en_US, Name: English (United States)
 274.932 +format locale: ID: bn_BD, Name: Bengali (Bangladesh)
 274.933 +default charset: UTF-8
 274.934 +
 274.935 +OS Locale (lcid: 850, name: mn-Mong-CN): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 274.936 +default locale: ID: mn_CN, Name: Mongolian (China)
 274.937 +display locale: ID: en_US, Name: English (United States)
 274.938 +format locale: ID: mn_CN, Name: Mongolian (China)
 274.939 +default charset: UTF-8
 274.940 +
 274.941 +OS Locale (lcid: 850, name: mn-Mong): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 274.942 +default locale: ID: mn_CN, Name: Mongolian (China)
 274.943 +display locale: ID: en_US, Name: English (United States)
 274.944 +format locale: ID: mn_CN, Name: Mongolian (China)
 274.945 +default charset: UTF-8
 274.946 +
 274.947 +OS Locale (lcid: 85d, name: iu-Latn): Inuktitut (Latin) (Canada) - 1252
 274.948 +default locale: ID: iu_CA, Name: Inuktitut (Canada)
 274.949 +display locale: ID: en_US, Name: English (United States)
 274.950 +format locale: ID: iu_CA, Name: Inuktitut (Canada)
 274.951 +default charset: windows-1252
 274.952 +
 274.953 +OS Locale (lcid: 85d, name: iu-Latn-CA): Inuktitut (Latin) (Canada) - 1252
 274.954 +default locale: ID: iu_CA, Name: Inuktitut (Canada)
 274.955 +display locale: ID: en_US, Name: English (United States)
 274.956 +format locale: ID: iu_CA, Name: Inuktitut (Canada)
 274.957 +default charset: windows-1252
 274.958 +
 274.959 +OS Locale (lcid: 85f, name: tzm): Tamazight (Latin) (Algeria) - 1252
 274.960 +default locale: ID: en_US, Name: English (United States)
 274.961 +display locale: ID: en_US, Name: English (United States)
 274.962 +format locale: ID: en_US, Name: English (United States)
 274.963 +default charset: windows-1252
 274.964 +
 274.965 +OS Locale (lcid: 85f, name: tzm-Latn-DZ): Tamazight (Latin) (Algeria) - 1252
 274.966 +default locale: ID: en_US, Name: English (United States)
 274.967 +display locale: ID: en_US, Name: English (United States)
 274.968 +format locale: ID: en_US, Name: English (United States)
 274.969 +default charset: windows-1252
 274.970 +
 274.971 +OS Locale (lcid: 85f, name: tzm-Latn): Tamazight (Latin) (Algeria) - 1252
 274.972 +default locale: ID: en_US, Name: English (United States)
 274.973 +display locale: ID: en_US, Name: English (United States)
 274.974 +format locale: ID: en_US, Name: English (United States)
 274.975 +default charset: windows-1252
 274.976 +
 274.977 +OS Locale (lcid: 86b, name: quz-EC): Quechua (Ecuador) - 1252
 274.978 +default locale: ID: en_US, Name: English (United States)
 274.979 +display locale: ID: en_US, Name: English (United States)
 274.980 +format locale: ID: en_US, Name: English (United States)
 274.981 +default charset: windows-1252
 274.982 +
 274.983 +OS Locale (lcid: c01, name: ar-EG): Arabic (Egypt) - 1256
 274.984 +default locale: ID: ar_EG, Name: Arabic (Egypt)
 274.985 +display locale: ID: en_US, Name: English (United States)
 274.986 +format locale: ID: ar_EG, Name: Arabic (Egypt)
 274.987 +default charset: windows-1256
 274.988 +
 274.989 +OS Locale (lcid: c04, name: zh-HK): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 274.990 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
 274.991 +display locale: ID: en_US, Name: English (United States)
 274.992 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 274.993 +default charset: x-MS950-HKSCS
 274.994 +
 274.995 +OS Locale (lcid: c04, name: zh-Hant): Chinese (Traditional) (Hong Kong S.A.R.) - 950
 274.996 +default locale: ID: zh_HK, Name: Chinese (Hong Kong)
 274.997 +display locale: ID: en_US, Name: English (United States)
 274.998 +format locale: ID: zh_HK, Name: Chinese (Hong Kong)
 274.999 +default charset: x-windows-950
274.1000 +
274.1001 +OS Locale (lcid: c07, name: de-AT): German (Austria) - 1252
274.1002 +default locale: ID: de_AT, Name: German (Austria)
274.1003 +display locale: ID: en_US, Name: English (United States)
274.1004 +format locale: ID: de_AT, Name: German (Austria)
274.1005 +default charset: windows-1252
274.1006 +
274.1007 +OS Locale (lcid: c09, name: en-AU): English (Australia) - 1252
274.1008 +default locale: ID: en_AU, Name: English (Australia)
274.1009 +display locale: ID: en_AU, Name: English (Australia)
274.1010 +format locale: ID: en_AU, Name: English (Australia)
274.1011 +default charset: windows-1252
274.1012 +
274.1013 +OS Locale (lcid: c0a, name: es-ES): Spanish (Spain) - 1252
274.1014 +default locale: ID: es_ES, Name: Spanish (Spain)
274.1015 +display locale: ID: en_US, Name: English (United States)
274.1016 +format locale: ID: es_ES, Name: Spanish (Spain)
274.1017 +default charset: windows-1252
274.1018 +
274.1019 +OS Locale (lcid: c0c, name: fr-CA): French (Canada) - 1252
274.1020 +default locale: ID: fr_CA, Name: French (Canada)
274.1021 +display locale: ID: en_US, Name: English (United States)
274.1022 +format locale: ID: fr_CA, Name: French (Canada)
274.1023 +default charset: windows-1252
274.1024 +
274.1025 +OS Locale (lcid: c1a, name: sr-Cyrl-CS): Serbian (Cyrillic) (Serbia and Montenegro (Former)) - 1251
274.1026 +default locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
274.1027 +display locale: ID: en_US, Name: English (United States)
274.1028 +format locale: ID: sr_CS, Name: Serbian (Serbia and Montenegro)
274.1029 +default charset: windows-1251
274.1030 +
274.1031 +OS Locale (lcid: c3b, name: se-FI): Sami (Northern) (Finland) - 1252
274.1032 +default locale: ID: se_FI, Name: Northern Sami (Finland)
274.1033 +display locale: ID: en_US, Name: English (United States)
274.1034 +format locale: ID: se_FI, Name: Northern Sami (Finland)
274.1035 +default charset: windows-1252
274.1036 +
274.1037 +OS Locale (lcid: c6b, name: quz-PE): Quechua (Peru) - 1252
274.1038 +default locale: ID: en_US, Name: English (United States)
274.1039 +display locale: ID: en_US, Name: English (United States)
274.1040 +format locale: ID: en_US, Name: English (United States)
274.1041 +default charset: windows-1252
274.1042 +
274.1043 +OS Locale (lcid: 1001, name: ar-LY): Arabic (Libya) - 1256
274.1044 +default locale: ID: ar_LY, Name: Arabic (Libya)
274.1045 +display locale: ID: en_US, Name: English (United States)
274.1046 +format locale: ID: ar_LY, Name: Arabic (Libya)
274.1047 +default charset: windows-1256
274.1048 +
274.1049 +OS Locale (lcid: 1004, name: zh-SG): Chinese (Simplified) (Singapore) - 936
274.1050 +default locale: ID: zh_SG, Name: Chinese (Singapore)
274.1051 +display locale: ID: en_US, Name: English (United States)
274.1052 +format locale: ID: zh_SG, Name: Chinese (Singapore)
274.1053 +default charset: GBK
274.1054 +
274.1055 +OS Locale (lcid: 1007, name: de-LU): German (Luxembourg) - 1252
274.1056 +default locale: ID: de_LU, Name: German (Luxembourg)
274.1057 +display locale: ID: en_US, Name: English (United States)
274.1058 +format locale: ID: de_LU, Name: German (Luxembourg)
274.1059 +default charset: windows-1252
274.1060 +
274.1061 +OS Locale (lcid: 1009, name: en-CA): English (Canada) - 1252
274.1062 +default locale: ID: en_CA, Name: English (Canada)
274.1063 +display locale: ID: en_CA, Name: English (Canada)
274.1064 +format locale: ID: en_CA, Name: English (Canada)
274.1065 +default charset: windows-1252
274.1066 +
274.1067 +OS Locale (lcid: 100a, name: es-GT): Spanish (Guatemala) - 1252
274.1068 +default locale: ID: es_GT, Name: Spanish (Guatemala)
274.1069 +display locale: ID: en_US, Name: English (United States)
274.1070 +format locale: ID: es_GT, Name: Spanish (Guatemala)
274.1071 +default charset: windows-1252
274.1072 +
274.1073 +OS Locale (lcid: 100c, name: fr-CH): French (Switzerland) - 1252
274.1074 +default locale: ID: fr_CH, Name: French (Switzerland)
274.1075 +display locale: ID: en_US, Name: English (United States)
274.1076 +format locale: ID: fr_CH, Name: French (Switzerland)
274.1077 +default charset: windows-1252
274.1078 +
274.1079 +OS Locale (lcid: 101a, name: hr-BA): Croatian (Latin) (Bosnia and Herzegovina) - 1250
274.1080 +default locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
274.1081 +display locale: ID: en_US, Name: English (United States)
274.1082 +format locale: ID: hr_BA, Name: Croatian (Bosnia and Herzegovina)
274.1083 +default charset: windows-1250
274.1084 +
274.1085 +OS Locale (lcid: 103b, name: smj-NO): Sami (Lule) (Norway) - 1252
274.1086 +default locale: ID: en_US, Name: English (United States)
274.1087 +display locale: ID: en_US, Name: English (United States)
274.1088 +format locale: ID: en_US, Name: English (United States)
274.1089 +default charset: windows-1252
274.1090 +
274.1091 +OS Locale (lcid: 1401, name: ar-DZ): Arabic (Algeria) - 1256
274.1092 +default locale: ID: ar_DZ, Name: Arabic (Algeria)
274.1093 +display locale: ID: en_US, Name: English (United States)
274.1094 +format locale: ID: ar_DZ, Name: Arabic (Algeria)
274.1095 +default charset: windows-1256
274.1096 +
274.1097 +OS Locale (lcid: 1404, name: zh-MO): Chinese (Traditional) (Macao S.A.R.) - 950
274.1098 +default locale: ID: zh_MO, Name: Chinese (Macao)
274.1099 +display locale: ID: en_US, Name: English (United States)
274.1100 +format locale: ID: zh_MO, Name: Chinese (Macao)
274.1101 +default charset: x-windows-950
274.1102 +
274.1103 +OS Locale (lcid: 1407, name: de-LI): German (Liechtenstein) - 1252
274.1104 +default locale: ID: de_LI, Name: German (Liechtenstein)
274.1105 +display locale: ID: en_US, Name: English (United States)
274.1106 +format locale: ID: de_LI, Name: German (Liechtenstein)
274.1107 +default charset: windows-1252
274.1108 +
274.1109 +OS Locale (lcid: 1409, name: en-NZ): English (New Zealand) - 1252
274.1110 +default locale: ID: en_NZ, Name: English (New Zealand)
274.1111 +display locale: ID: en_NZ, Name: English (New Zealand)
274.1112 +format locale: ID: en_NZ, Name: English (New Zealand)
274.1113 +default charset: windows-1252
274.1114 +
274.1115 +OS Locale (lcid: 140a, name: es-CR): Spanish (Costa Rica) - 1252
274.1116 +default locale: ID: es_CR, Name: Spanish (Costa Rica)
274.1117 +display locale: ID: en_US, Name: English (United States)
274.1118 +format locale: ID: es_CR, Name: Spanish (Costa Rica)
274.1119 +default charset: windows-1252
274.1120 +
274.1121 +OS Locale (lcid: 140c, name: fr-LU): French (Luxembourg) - 1252
274.1122 +default locale: ID: fr_LU, Name: French (Luxembourg)
274.1123 +display locale: ID: en_US, Name: English (United States)
274.1124 +format locale: ID: fr_LU, Name: French (Luxembourg)
274.1125 +default charset: windows-1252
274.1126 +
274.1127 +OS Locale (lcid: 141a, name: bs-Latn): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
274.1128 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
274.1129 +display locale: ID: en_US, Name: English (United States)
274.1130 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
274.1131 +default charset: windows-1250
274.1132 +
274.1133 +OS Locale (lcid: 141a, name: bs-Latn-BA): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
274.1134 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
274.1135 +display locale: ID: en_US, Name: English (United States)
274.1136 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
274.1137 +default charset: windows-1250
274.1138 +
274.1139 +OS Locale (lcid: 143b, name: smj-SE): Sami (Lule) (Sweden) - 1252
274.1140 +default locale: ID: en_US, Name: English (United States)
274.1141 +display locale: ID: en_US, Name: English (United States)
274.1142 +format locale: ID: en_US, Name: English (United States)
274.1143 +default charset: windows-1252
274.1144 +
274.1145 +OS Locale (lcid: 143b, name: smj): Sami (Lule) (Sweden) - 1252
274.1146 +default locale: ID: en_US, Name: English (United States)
274.1147 +display locale: ID: en_US, Name: English (United States)
274.1148 +format locale: ID: en_US, Name: English (United States)
274.1149 +default charset: windows-1252
274.1150 +
274.1151 +OS Locale (lcid: 1801, name: ar-MA): Arabic (Morocco) - 1256
274.1152 +default locale: ID: ar_MA, Name: Arabic (Morocco)
274.1153 +display locale: ID: en_US, Name: English (United States)
274.1154 +format locale: ID: ar_MA, Name: Arabic (Morocco)
274.1155 +default charset: windows-1256
274.1156 +
274.1157 +OS Locale (lcid: 1809, name: en-IE): English (Ireland) - 1252
274.1158 +default locale: ID: en_IE, Name: English (Ireland)
274.1159 +display locale: ID: en_IE, Name: English (Ireland)
274.1160 +format locale: ID: en_IE, Name: English (Ireland)
274.1161 +default charset: windows-1252
274.1162 +
274.1163 +OS Locale (lcid: 180a, name: es-PA): Spanish (Panama) - 1252
274.1164 +default locale: ID: es_PA, Name: Spanish (Panama)
274.1165 +display locale: ID: en_US, Name: English (United States)
274.1166 +format locale: ID: es_PA, Name: Spanish (Panama)
274.1167 +default charset: windows-1252
274.1168 +
274.1169 +OS Locale (lcid: 180c, name: fr-MC): French (Principality of Monaco) - 1252
274.1170 +default locale: ID: fr_MC, Name: French (Monaco)
274.1171 +display locale: ID: en_US, Name: English (United States)
274.1172 +format locale: ID: fr_MC, Name: French (Monaco)
274.1173 +default charset: windows-1252
274.1174 +
274.1175 +OS Locale (lcid: 181a, name: sr-Latn-BA): Serbian (Latin) (Bosnia and Herzegovina) - 1250
274.1176 +default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
274.1177 +display locale: ID: en_US, Name: English (United States)
274.1178 +format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
274.1179 +default charset: windows-1250
274.1180 +
274.1181 +OS Locale (lcid: 183b, name: sma-NO): Sami (Southern) (Norway) - 1252
274.1182 +default locale: ID: en_US, Name: English (United States)
274.1183 +display locale: ID: en_US, Name: English (United States)
274.1184 +format locale: ID: en_US, Name: English (United States)
274.1185 +default charset: windows-1252
274.1186 +
274.1187 +OS Locale (lcid: 1c01, name: ar-TN): Arabic (Tunisia) - 1256
274.1188 +default locale: ID: ar_TN, Name: Arabic (Tunisia)
274.1189 +display locale: ID: en_US, Name: English (United States)
274.1190 +format locale: ID: ar_TN, Name: Arabic (Tunisia)
274.1191 +default charset: windows-1256
274.1192 +
274.1193 +OS Locale (lcid: 1c09, name: en-ZA): English (South Africa) - 1252
274.1194 +default locale: ID: en_ZA, Name: English (South Africa)
274.1195 +display locale: ID: en_ZA, Name: English (South Africa)
274.1196 +format locale: ID: en_ZA, Name: English (South Africa)
274.1197 +default charset: windows-1252
274.1198 +
274.1199 +OS Locale (lcid: 1c0a, name: es-DO): Spanish (Dominican Republic) - 1252
274.1200 +default locale: ID: es_DO, Name: Spanish (Dominican Republic)
274.1201 +display locale: ID: en_US, Name: English (United States)
274.1202 +format locale: ID: es_DO, Name: Spanish (Dominican Republic)
274.1203 +default charset: windows-1252
274.1204 +
274.1205 +OS Locale (lcid: 1c1a, name: sr-Cyrl-BA): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
274.1206 +default locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
274.1207 +display locale: ID: en_US, Name: English (United States)
274.1208 +format locale: ID: sr_BA, Name: Serbian (Bosnia and Herzegovina)
274.1209 +default charset: windows-1251
274.1210 +
274.1211 +OS Locale (lcid: 1c3b, name: sma): Sami (Southern) (Sweden) - 1252
274.1212 +default locale: ID: en_US, Name: English (United States)
274.1213 +display locale: ID: en_US, Name: English (United States)
274.1214 +format locale: ID: en_US, Name: English (United States)
274.1215 +default charset: windows-1252
274.1216 +
274.1217 +OS Locale (lcid: 1c3b, name: sma-SE): Sami (Southern) (Sweden) - 1252
274.1218 +default locale: ID: en_US, Name: English (United States)
274.1219 +display locale: ID: en_US, Name: English (United States)
274.1220 +format locale: ID: en_US, Name: English (United States)
274.1221 +default charset: windows-1252
274.1222 +
274.1223 +OS Locale (lcid: 2001, name: ar-OM): Arabic (Oman) - 1256
274.1224 +default locale: ID: ar_OM, Name: Arabic (Oman)
274.1225 +display locale: ID: en_US, Name: English (United States)
274.1226 +format locale: ID: ar_OM, Name: Arabic (Oman)
274.1227 +default charset: windows-1256
274.1228 +
274.1229 +OS Locale (lcid: 2009, name: en-JM): English (Jamaica) - 1252
274.1230 +default locale: ID: en_JM, Name: English (Jamaica)
274.1231 +display locale: ID: en_JM, Name: English (Jamaica)
274.1232 +format locale: ID: en_JM, Name: English (Jamaica)
274.1233 +default charset: windows-1252
274.1234 +
274.1235 +OS Locale (lcid: 200a, name: es-VE): Spanish (Bolivarian Republic of Venezuela) - 1252
274.1236 +default locale: ID: es_VE, Name: Spanish (Venezuela)
274.1237 +display locale: ID: en_US, Name: English (United States)
274.1238 +format locale: ID: es_VE, Name: Spanish (Venezuela)
274.1239 +default charset: windows-1252
274.1240 +
274.1241 +OS Locale (lcid: 201a, name: bs-Cyrl-BA): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
274.1242 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
274.1243 +display locale: ID: en_US, Name: English (United States)
274.1244 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
274.1245 +default charset: windows-1251
274.1246 +
274.1247 +OS Locale (lcid: 201a, name: bs-Cyrl): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
274.1248 +default locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
274.1249 +display locale: ID: en_US, Name: English (United States)
274.1250 +format locale: ID: bs_BA, Name: Bosnian (Bosnia and Herzegovina)
274.1251 +default charset: windows-1251
274.1252 +
274.1253 +OS Locale (lcid: 203b, name: sms-FI): Sami (Skolt) (Finland) - 1252
274.1254 +default locale: ID: en_US, Name: English (United States)
274.1255 +display locale: ID: en_US, Name: English (United States)
274.1256 +format locale: ID: en_US, Name: English (United States)
274.1257 +default charset: windows-1252
274.1258 +
274.1259 +OS Locale (lcid: 203b, name: sms): Sami (Skolt) (Finland) - 1252
274.1260 +default locale: ID: en_US, Name: English (United States)
274.1261 +display locale: ID: en_US, Name: English (United States)
274.1262 +format locale: ID: en_US, Name: English (United States)
274.1263 +default charset: windows-1252
274.1264 +
274.1265 +OS Locale (lcid: 2401, name: ar-YE): Arabic (Yemen) - 1256
274.1266 +default locale: ID: ar_YE, Name: Arabic (Yemen)
274.1267 +display locale: ID: en_US, Name: English (United States)
274.1268 +format locale: ID: ar_YE, Name: Arabic (Yemen)
274.1269 +default charset: windows-1256
274.1270 +
274.1271 +OS Locale (lcid: 2409, name: en-029): English (Caribbean) - 1252
274.1272 +default locale: ID: en, Name: English
274.1273 +display locale: ID: en, Name: English
274.1274 +format locale: ID: en, Name: English
274.1275 +default charset: windows-1252
274.1276 +
274.1277 +OS Locale (lcid: 240a, name: es-CO): Spanish (Colombia) - 1252
274.1278 +default locale: ID: es_CO, Name: Spanish (Colombia)
274.1279 +display locale: ID: en_US, Name: English (United States)
274.1280 +format locale: ID: es_CO, Name: Spanish (Colombia)
274.1281 +default charset: windows-1252
274.1282 +
274.1283 +OS Locale (lcid: 241a, name: sr-Latn-RS): Serbian (Latin) (Serbia) - 1250
274.1284 +default locale: ID: sr_RS, Name: Serbian (Serbia)
274.1285 +display locale: ID: en_US, Name: English (United States)
274.1286 +format locale: ID: sr_RS, Name: Serbian (Serbia)
274.1287 +default charset: windows-1250
274.1288 +
274.1289 +OS Locale (lcid: 241a, name: sr-Latn): Serbian (Latin) (Serbia) - 1250
274.1290 +default locale: ID: sr_RS, Name: Serbian (Serbia)
274.1291 +display locale: ID: en_US, Name: English (United States)
274.1292 +format locale: ID: sr_RS, Name: Serbian (Serbia)
274.1293 +default charset: windows-1250
274.1294 +
274.1295 +OS Locale (lcid: 243b, name: smn): Sami (Inari) (Finland) - 1252
274.1296 +default locale: ID: en_US, Name: English (United States)
274.1297 +display locale: ID: en_US, Name: English (United States)
274.1298 +format locale: ID: en_US, Name: English (United States)
274.1299 +default charset: windows-1252
274.1300 +
274.1301 +OS Locale (lcid: 243b, name: smn-FI): Sami (Inari) (Finland) - 1252
274.1302 +default locale: ID: en_US, Name: English (United States)
274.1303 +display locale: ID: en_US, Name: English (United States)
274.1304 +format locale: ID: en_US, Name: English (United States)
274.1305 +default charset: windows-1252
274.1306 +
274.1307 +OS Locale (lcid: 2801, name: ar-SY): Arabic (Syria) - 1256
274.1308 +default locale: ID: ar_SY, Name: Arabic (Syria)
274.1309 +display locale: ID: en_US, Name: English (United States)
274.1310 +format locale: ID: ar_SY, Name: Arabic (Syria)
274.1311 +default charset: windows-1256
274.1312 +
274.1313 +OS Locale (lcid: 2809, name: en-BZ): English (Belize) - 1252
274.1314 +default locale: ID: en_BZ, Name: English (Belize)
274.1315 +display locale: ID: en_BZ, Name: English (Belize)
274.1316 +format locale: ID: en_BZ, Name: English (Belize)
274.1317 +default charset: windows-1252
274.1318 +
274.1319 +OS Locale (lcid: 280a, name: es-PE): Spanish (Peru) - 1252
274.1320 +default locale: ID: es_PE, Name: Spanish (Peru)
274.1321 +display locale: ID: en_US, Name: English (United States)
274.1322 +format locale: ID: es_PE, Name: Spanish (Peru)
274.1323 +default charset: windows-1252
274.1324 +
274.1325 +OS Locale (lcid: 281a, name: sr-Cyrl-RS): Serbian (Cyrillic) (Serbia) - 1251
274.1326 +default locale: ID: sr_RS, Name: Serbian (Serbia)
274.1327 +display locale: ID: en_US, Name: English (United States)
274.1328 +format locale: ID: sr_RS, Name: Serbian (Serbia)
274.1329 +default charset: windows-1251
274.1330 +
274.1331 +OS Locale (lcid: 281a, name: sr-Cyrl): Serbian (Cyrillic) (Serbia) - 1251
274.1332 +default locale: ID: sr_RS, Name: Serbian (Serbia)
274.1333 +display locale: ID: en_US, Name: English (United States)
274.1334 +format locale: ID: sr_RS, Name: Serbian (Serbia)
274.1335 +default charset: windows-1251
274.1336 +
274.1337 +OS Locale (lcid: 2c01, name: ar-JO): Arabic (Jordan) - 1256
274.1338 +default locale: ID: ar_JO, Name: Arabic (Jordan)
274.1339 +display locale: ID: en_US, Name: English (United States)
274.1340 +format locale: ID: ar_JO, Name: Arabic (Jordan)
274.1341 +default charset: windows-1256
274.1342 +
274.1343 +OS Locale (lcid: 2c09, name: en-TT): English (Trinidad and Tobago) - 1252
274.1344 +default locale: ID: en_TT, Name: English (Trinidad and Tobago)
274.1345 +display locale: ID: en_TT, Name: English (Trinidad and Tobago)
274.1346 +format locale: ID: en_TT, Name: English (Trinidad and Tobago)
274.1347 +default charset: windows-1252
274.1348 +
274.1349 +OS Locale (lcid: 2c0a, name: es-AR): Spanish (Argentina) - 1252
274.1350 +default locale: ID: es_AR, Name: Spanish (Argentina)
274.1351 +display locale: ID: en_US, Name: English (United States)
274.1352 +format locale: ID: es_AR, Name: Spanish (Argentina)
274.1353 +default charset: windows-1252
274.1354 +
274.1355 +OS Locale (lcid: 2c1a, name: sr-Latn-ME): Serbian (Latin) (Montenegro) - 1250
274.1356 +default locale: ID: sr_ME, Name: Serbian (Montenegro)
274.1357 +display locale: ID: en_US, Name: English (United States)
274.1358 +format locale: ID: sr_ME, Name: Serbian (Montenegro)
274.1359 +default charset: windows-1250
274.1360 +
274.1361 +OS Locale (lcid: 3001, name: ar-LB): Arabic (Lebanon) - 1256
274.1362 +default locale: ID: ar_LB, Name: Arabic (Lebanon)
274.1363 +display locale: ID: en_US, Name: English (United States)
274.1364 +format locale: ID: ar_LB, Name: Arabic (Lebanon)
274.1365 +default charset: windows-1256
274.1366 +
274.1367 +OS Locale (lcid: 3009, name: en-ZW): English (Zimbabwe) - 1252
274.1368 +default locale: ID: en_ZW, Name: English (Zimbabwe)
274.1369 +display locale: ID: en_ZW, Name: English (Zimbabwe)
274.1370 +format locale: ID: en_ZW, Name: English (Zimbabwe)
274.1371 +default charset: windows-1252
274.1372 +
274.1373 +OS Locale (lcid: 300a, name: es-EC): Spanish (Ecuador) - 1252
274.1374 +default locale: ID: es_EC, Name: Spanish (Ecuador)
274.1375 +display locale: ID: en_US, Name: English (United States)
274.1376 +format locale: ID: es_EC, Name: Spanish (Ecuador)
274.1377 +default charset: windows-1252
274.1378 +
274.1379 +OS Locale (lcid: 301a, name: sr-Cyrl-ME): Serbian (Cyrillic) (Montenegro) - 1251
274.1380 +default locale: ID: sr_ME, Name: Serbian (Montenegro)
274.1381 +display locale: ID: en_US, Name: English (United States)
274.1382 +format locale: ID: sr_ME, Name: Serbian (Montenegro)
274.1383 +default charset: windows-1251
274.1384 +
274.1385 +OS Locale (lcid: 3401, name: ar-KW): Arabic (Kuwait) - 1256
274.1386 +default locale: ID: ar_KW, Name: Arabic (Kuwait)
274.1387 +display locale: ID: en_US, Name: English (United States)
274.1388 +format locale: ID: ar_KW, Name: Arabic (Kuwait)
274.1389 +default charset: windows-1256
274.1390 +
274.1391 +OS Locale (lcid: 3409, name: en-PH): English (Republic of the Philippines) - 1252
274.1392 +default locale: ID: en_PH, Name: English (Philippines)
274.1393 +display locale: ID: en_PH, Name: English (Philippines)
274.1394 +format locale: ID: en_PH, Name: English (Philippines)
274.1395 +default charset: windows-1252
274.1396 +
274.1397 +OS Locale (lcid: 340a, name: es-CL): Spanish (Chile) - 1252
274.1398 +default locale: ID: es_CL, Name: Spanish (Chile)
274.1399 +display locale: ID: en_US, Name: English (United States)
274.1400 +format locale: ID: es_CL, Name: Spanish (Chile)
274.1401 +default charset: windows-1252
274.1402 +
274.1403 +OS Locale (lcid: 3801, name: ar-AE): Arabic (U.A.E.) - 1256
274.1404 +default locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
274.1405 +display locale: ID: en_US, Name: English (United States)
274.1406 +format locale: ID: ar_AE, Name: Arabic (United Arab Emirates)
274.1407 +default charset: windows-1256
274.1408 +
274.1409 +OS Locale (lcid: 380a, name: es-UY): Spanish (Uruguay) - 1252
274.1410 +default locale: ID: es_UY, Name: Spanish (Uruguay)
274.1411 +display locale: ID: en_US, Name: English (United States)
274.1412 +format locale: ID: es_UY, Name: Spanish (Uruguay)
274.1413 +default charset: windows-1252
274.1414 +
274.1415 +OS Locale (lcid: 3c01, name: ar-BH): Arabic (Bahrain) - 1256
274.1416 +default locale: ID: ar_BH, Name: Arabic (Bahrain)
274.1417 +display locale: ID: en_US, Name: English (United States)
274.1418 +format locale: ID: ar_BH, Name: Arabic (Bahrain)
274.1419 +default charset: windows-1256
274.1420 +
274.1421 +OS Locale (lcid: 3c0a, name: es-PY): Spanish (Paraguay) - 1252
274.1422 +default locale: ID: es_PY, Name: Spanish (Paraguay)
274.1423 +display locale: ID: en_US, Name: English (United States)
274.1424 +format locale: ID: es_PY, Name: Spanish (Paraguay)
274.1425 +default charset: windows-1252
274.1426 +
274.1427 +OS Locale (lcid: 4001, name: ar-QA): Arabic (Qatar) - 1256
274.1428 +default locale: ID: ar_QA, Name: Arabic (Qatar)
274.1429 +display locale: ID: en_US, Name: English (United States)
274.1430 +format locale: ID: ar_QA, Name: Arabic (Qatar)
274.1431 +default charset: windows-1256
274.1432 +
274.1433 +OS Locale (lcid: 4009, name: en-IN): English (India) - 1252
274.1434 +default locale: ID: en_IN, Name: English (India)
274.1435 +display locale: ID: en_IN, Name: English (India)
274.1436 +format locale: ID: en_IN, Name: English (India)
274.1437 +default charset: windows-1252
274.1438 +
274.1439 +OS Locale (lcid: 400a, name: es-BO): Spanish (Bolivia) - 1252
274.1440 +default locale: ID: es_BO, Name: Spanish (Bolivia)
274.1441 +display locale: ID: en_US, Name: English (United States)
274.1442 +format locale: ID: es_BO, Name: Spanish (Bolivia)
274.1443 +default charset: windows-1252
274.1444 +
274.1445 +OS Locale (lcid: 4409, name: en-MY): English (Malaysia) - 1252
274.1446 +default locale: ID: en_MY, Name: English (Malaysia)
274.1447 +display locale: ID: en_MY, Name: English (Malaysia)
274.1448 +format locale: ID: en_MY, Name: English (Malaysia)
274.1449 +default charset: windows-1252
274.1450 +
274.1451 +OS Locale (lcid: 440a, name: es-SV): Spanish (El Salvador) - 1252
274.1452 +default locale: ID: es_SV, Name: Spanish (El Salvador)
274.1453 +display locale: ID: en_US, Name: English (United States)
274.1454 +format locale: ID: es_SV, Name: Spanish (El Salvador)
274.1455 +default charset: windows-1252
274.1456 +
274.1457 +OS Locale (lcid: 4809, name: en-SG): English (Singapore) - 1252
274.1458 +default locale: ID: en_SG, Name: English (Singapore)
274.1459 +display locale: ID: en_SG, Name: English (Singapore)
274.1460 +format locale: ID: en_SG, Name: English (Singapore)
274.1461 +default charset: windows-1252
274.1462 +
274.1463 +OS Locale (lcid: 480a, name: es-HN): Spanish (Honduras) - 1252
274.1464 +default locale: ID: es_HN, Name: Spanish (Honduras)
274.1465 +display locale: ID: en_US, Name: English (United States)
274.1466 +format locale: ID: es_HN, Name: Spanish (Honduras)
274.1467 +default charset: windows-1252
274.1468 +
274.1469 +OS Locale (lcid: 4c0a, name: es-NI): Spanish (Nicaragua) - 1252
274.1470 +default locale: ID: es_NI, Name: Spanish (Nicaragua)
274.1471 +display locale: ID: en_US, Name: English (United States)
274.1472 +format locale: ID: es_NI, Name: Spanish (Nicaragua)
274.1473 +default charset: windows-1252
274.1474 +
274.1475 +OS Locale (lcid: 500a, name: es-PR): Spanish (Puerto Rico) - 1252
274.1476 +default locale: ID: es_PR, Name: Spanish (Puerto Rico)
274.1477 +display locale: ID: en_US, Name: English (United States)
274.1478 +format locale: ID: es_PR, Name: Spanish (Puerto Rico)
274.1479 +default charset: windows-1252
274.1480 +
274.1481 +OS Locale (lcid: 540a, name: es-US): Spanish (United States) - 1252
274.1482 +default locale: ID: es_US, Name: Spanish (United States)
274.1483 +display locale: ID: en, Name: English
274.1484 +format locale: ID: es_US, Name: Spanish (United States)
274.1485 +default charset: windows-1252
274.1486 +
274.1487 +OS UI Language (name: en-US)
274.1488 +default locale: ID: en_US, Name: English (United States)
274.1489 +display locale: ID: en_US, Name: English (United States)
274.1490 +format locale: ID: en_US, Name: English (United States)
274.1491 +default charset: windows-1252
274.1492 +
274.1493 +OS UI Language (name: ja-JP)
274.1494 +default locale: ID: en_US, Name: English (United States)
274.1495 +display locale: ID: ja_JP, Name: Japanese (Japan)
274.1496 +format locale: ID: en_US, Name: English (United States)
274.1497 +default charset: windows-1252
   275.1 --- a/test/java/util/Locale/data/deflocale.winvista	Thu Sep 23 17:33:40 2010 -0700
   275.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   275.3 @@ -1,1031 +0,0 @@
   275.4 -# OSVersionInfo
   275.5 -# MajorVersion: 6
   275.6 -# MinorVersion: 0
   275.7 -# BuildNumber: 5456
   275.8 -# CSDVersion: Service Pack 0 v. 
   275.9 -
  275.10 -
  275.11 -OS Locale (lcid: 401): Arabic (Saudi Arabia) - 1256
  275.12 -ar_SA
  275.13 -Arabic (Saudi Arabia)
  275.14 -windows-1256
  275.15 -
  275.16 -OS Locale (lcid: 402): Bulgarian (Bulgaria) - 1251
  275.17 -bg_BG
  275.18 -Bulgarian (Bulgaria)
  275.19 -windows-1251
  275.20 -
  275.21 -OS Locale (lcid: 403): Catalan (Spain) - 1252
  275.22 -ca_ES
  275.23 -Catalan (Spain)
  275.24 -windows-1252
  275.25 -
  275.26 -OS Locale (lcid: 404): Chinese (Taiwan) - 950
  275.27 -zh_TW
  275.28 -Chinese (Taiwan)
  275.29 -x-windows-950
  275.30 -
  275.31 -OS Locale (lcid: 405): Czech (Czech Republic) - 1250
  275.32 -cs_CZ
  275.33 -Czech (Czech Republic)
  275.34 -windows-1250
  275.35 -
  275.36 -OS Locale (lcid: 406): Danish (Denmark) - 1252
  275.37 -da_DK
  275.38 -Danish (Denmark)
  275.39 -windows-1252
  275.40 -
  275.41 -OS Locale (lcid: 407): German (Germany) - 1252
  275.42 -de_DE
  275.43 -German (Germany)
  275.44 -windows-1252
  275.45 -
  275.46 -OS Locale (lcid: 408): Greek (Greece) - 1253
  275.47 -el_GR
  275.48 -Greek (Greece)
  275.49 -windows-1253
  275.50 -
  275.51 -OS Locale (lcid: 409): English (United States) - 1252
  275.52 -en_US
  275.53 -English (United States)
  275.54 -windows-1252
  275.55 -
  275.56 -OS Locale (lcid: 40b): Finnish (Finland) - 1252
  275.57 -fi_FI
  275.58 -Finnish (Finland)
  275.59 -windows-1252
  275.60 -
  275.61 -OS Locale (lcid: 40c): French (France) - 1252
  275.62 -fr_FR
  275.63 -French (France)
  275.64 -windows-1252
  275.65 -
  275.66 -OS Locale (lcid: 40d): Hebrew (Israel) - 1255
  275.67 -iw_IL
  275.68 -Hebrew (Israel)
  275.69 -windows-1255
  275.70 -
  275.71 -OS Locale (lcid: 40e): Hungarian (Hungary) - 1250
  275.72 -hu_HU
  275.73 -Hungarian (Hungary)
  275.74 -windows-1250
  275.75 -
  275.76 -OS Locale (lcid: 40f): Icelandic (Iceland) - 1252
  275.77 -is_IS
  275.78 -Icelandic (Iceland)
  275.79 -windows-1252
  275.80 -
  275.81 -OS Locale (lcid: 410): Italian (Italy) - 1252
  275.82 -it_IT
  275.83 -Italian (Italy)
  275.84 -windows-1252
  275.85 -
  275.86 -OS Locale (lcid: 411): Japanese (Japan) - 932
  275.87 -ja_JP
  275.88 -Japanese (Japan)
  275.89 -windows-31j
  275.90 -
  275.91 -OS Locale (lcid: 412): Korean (Korea) - 949
  275.92 -ko_KR
  275.93 -Korean (South Korea)
  275.94 -x-windows-949
  275.95 -
  275.96 -OS Locale (lcid: 413): Dutch (Netherlands) - 1252
  275.97 -nl_NL
  275.98 -Dutch (Netherlands)
  275.99 -windows-1252
 275.100 -
 275.101 -OS Locale (lcid: 414): Norwegian (Bokmål) (Norway) - 1252
 275.102 -no_NO
 275.103 -Norwegian (Norway)
 275.104 -windows-1252
 275.105 -
 275.106 -OS Locale (lcid: 415): Polish (Poland) - 1250
 275.107 -pl_PL
 275.108 -Polish (Poland)
 275.109 -windows-1250
 275.110 -
 275.111 -OS Locale (lcid: 416): Portuguese (Brazil) - 1252
 275.112 -pt_BR
 275.113 -Portuguese (Brazil)
 275.114 -windows-1252
 275.115 -
 275.116 -OS Locale (lcid: 417): Romansh (Switzerland) - 1252
 275.117 -rm_CH
 275.118 -Raeto-Romance (Switzerland)
 275.119 -windows-1252
 275.120 -
 275.121 -OS Locale (lcid: 418): Romanian (Romania) - 1250
 275.122 -ro_RO
 275.123 -Romanian (Romania)
 275.124 -windows-1250
 275.125 -
 275.126 -OS Locale (lcid: 419): Russian (Russia) - 1251
 275.127 -ru_RU
 275.128 -Russian (Russia)
 275.129 -windows-1251
 275.130 -
 275.131 -OS Locale (lcid: 41a): Croatian (Croatia) - 1250
 275.132 -hr_HR
 275.133 -Croatian (Croatia)
 275.134 -windows-1250
 275.135 -
 275.136 -OS Locale (lcid: 41b): Slovak (Slovakia) - 1250
 275.137 -sk_SK
 275.138 -Slovak (Slovakia)
 275.139 -windows-1250
 275.140 -
 275.141 -OS Locale (lcid: 41c): Albanian (Albania) - 1250
 275.142 -sq_AL
 275.143 -Albanian (Albania)
 275.144 -windows-1250
 275.145 -
 275.146 -OS Locale (lcid: 41d): Swedish (Sweden) - 1252
 275.147 -sv_SE
 275.148 -Swedish (Sweden)
 275.149 -windows-1252
 275.150 -
 275.151 -OS Locale (lcid: 41e): Thai (Thailand) - 874
 275.152 -th_TH
 275.153 -Thai (Thailand)
 275.154 -x-windows-874
 275.155 -
 275.156 -OS Locale (lcid: 41f): Turkish (Turkey) - 1254
 275.157 -tr_TR
 275.158 -Turkish (Turkey)
 275.159 -windows-1254
 275.160 -
 275.161 -OS Locale (lcid: 420): Urdu (Islamic Republic of Pakistan) - 0
 275.162 -ur_PK
 275.163 -Urdu (Pakistan)
 275.164 -windows-1256
 275.165 -
 275.166 -OS Locale (lcid: 421): Indonesian (Indonesia) - 1252
 275.167 -in_ID
 275.168 -Indonesian (Indonesia)
 275.169 -windows-1252
 275.170 -
 275.171 -OS Locale (lcid: 422): Ukrainian (Ukraine) - 1251
 275.172 -uk_UA
 275.173 -Ukrainian (Ukraine)
 275.174 -windows-1251
 275.175 -
 275.176 -OS Locale (lcid: 423): Belarusian (Belarus) - 1251
 275.177 -be_BY
 275.178 -Belarusian (Belarus)
 275.179 -windows-1251
 275.180 -
 275.181 -OS Locale (lcid: 424): Slovenian (Slovenia) - 1250
 275.182 -sl_SI
 275.183 -Slovenian (Slovenia)
 275.184 -windows-1250
 275.185 -
 275.186 -OS Locale (lcid: 425): Estonian (Estonia) - 1257
 275.187 -et_EE
 275.188 -Estonian (Estonia)
 275.189 -windows-1257
 275.190 -
 275.191 -OS Locale (lcid: 426): Latvian (Latvia) - 1257
 275.192 -lv_LV
 275.193 -Latvian (Latvia)
 275.194 -windows-1257
 275.195 -
 275.196 -OS Locale (lcid: 427): Lithuanian (Lithuania) - 1257
 275.197 -lt_LT
 275.198 -Lithuanian (Lithuania)
 275.199 -windows-1257
 275.200 -
 275.201 -OS Locale (lcid: 428): Tajik (Cyrillic) (Tajikistan) - 1251
 275.202 -tg_TJ
 275.203 -Tajik (Tajikistan)
 275.204 -windows-1251
 275.205 -
 275.206 -OS Locale (lcid: 429): Persian (Iran) - 1256
 275.207 -fa_IR
 275.208 -Persian (Iran)
 275.209 -windows-1256
 275.210 -
 275.211 -OS Locale (lcid: 42a): Vietnamese (Vietnam) - 1258
 275.212 -vi_VN
 275.213 -Vietnamese (Vietnam)
 275.214 -windows-1258
 275.215 -
 275.216 -OS Locale (lcid: 42b): Armenian (Armenia) - 0
 275.217 -hy_AM
 275.218 -Armenian (Armenia)
 275.219 -UTF-8
 275.220 -
 275.221 -OS Locale (lcid: 42c): Azeri (Latin) (Azerbaijan) - 1254
 275.222 -az_AZ
 275.223 -Azerbaijani (Azerbaijan)
 275.224 -windows-1254
 275.225 -
 275.226 -OS Locale (lcid: 42d): Basque (Spain) - 1252
 275.227 -eu_ES
 275.228 -Basque (Spain)
 275.229 -windows-1252
 275.230 -
 275.231 -OS Locale (lcid: 42e): Upper Sorbian (Germany) - 1252
 275.232 -en_US
 275.233 -English (United States)
 275.234 -windows-1252
 275.235 -
 275.236 -OS Locale (lcid: 42f): Macedonian (FYROM) (Macedonia (FYROM)) - 1251
 275.237 -mk_MK
 275.238 -Macedonian (Macedonia)
 275.239 -windows-1251
 275.240 -
 275.241 -OS Locale (lcid: 432): Setswana (South Africa) - 1252
 275.242 -tn_ZA
 275.243 -Tswana (South Africa)
 275.244 -windows-1252
 275.245 -
 275.246 -OS Locale (lcid: 434): isiXhosa (South Africa) - 1252
 275.247 -xh_ZA
 275.248 -Xhosa (South Africa)
 275.249 -windows-1252
 275.250 -
 275.251 -OS Locale (lcid: 435): isiZulu (South Africa) - 1252
 275.252 -zu_ZA
 275.253 -Zulu (South Africa)
 275.254 -windows-1252
 275.255 -
 275.256 -OS Locale (lcid: 436): Afrikaans (South Africa) - 1252
 275.257 -af_ZA
 275.258 -Afrikaans (South Africa)
 275.259 -windows-1252
 275.260 -
 275.261 -OS Locale (lcid: 437): Georgian (Georgia) - 0
 275.262 -ka_GE
 275.263 -Georgian (Georgia)
 275.264 -UTF-8
 275.265 -
 275.266 -OS Locale (lcid: 438): Faroese (Faroe Islands) - 1252
 275.267 -fo_FO
 275.268 -Faroese (Faroe Islands)
 275.269 -windows-1252
 275.270 -
 275.271 -OS Locale (lcid: 439): Hindi (India) - 0
 275.272 -hi_IN
 275.273 -Hindi (India)
 275.274 -UTF-8
 275.275 -
 275.276 -OS Locale (lcid: 43a): Maltese (Malta) - 0
 275.277 -mt_MT
 275.278 -Maltese (Malta)
 275.279 -UTF-8
 275.280 -
 275.281 -OS Locale (lcid: 43b): Sami (Northern) (Norway) - 1252
 275.282 -se_NO
 275.283 -Northern Sami (Norway)
 275.284 -windows-1252
 275.285 -
 275.286 -OS Locale (lcid: 43e): Malay (Malaysia) - 1252
 275.287 -ms_MY
 275.288 -Malay (Malaysia)
 275.289 -windows-1252
 275.290 -
 275.291 -OS Locale (lcid: 43f): Kazakh (Kazakhstan) - 0
 275.292 -kk_KZ
 275.293 -Kazakh (Kazakhstan)
 275.294 -windows-1251
 275.295 -
 275.296 -OS Locale (lcid: 440): Kyrgyz (Kyrgyzstan) - 1251
 275.297 -ky_KG
 275.298 -Kirghiz (Kyrgyzstan)
 275.299 -windows-1251
 275.300 -
 275.301 -OS Locale (lcid: 441): Kiswahili (Kenya) - 1252
 275.302 -sw_KE
 275.303 -Swahili (Kenya)
 275.304 -windows-1252
 275.305 -
 275.306 -OS Locale (lcid: 442): Turkmen (Turkmenistan) - 1250
 275.307 -tk_TM
 275.308 -Turkmen (Turkmenistan)
 275.309 -windows-1250
 275.310 -
 275.311 -OS Locale (lcid: 443): Uzbek (Latin) (Uzbekistan) - 1254
 275.312 -uz_UZ
 275.313 -Uzbek (Uzbekistan)
 275.314 -windows-1254
 275.315 -
 275.316 -OS Locale (lcid: 444): Tatar (Russia) - 1251
 275.317 -tt_RU
 275.318 -Tatar (Russia)
 275.319 -windows-1251
 275.320 -
 275.321 -OS Locale (lcid: 445): Bengali (India) - 0
 275.322 -bn_IN
 275.323 -Bengali (India)
 275.324 -UTF-8
 275.325 -
 275.326 -OS Locale (lcid: 446): Punjabi (India) - 0
 275.327 -pa_IN
 275.328 -Panjabi (India)
 275.329 -UTF-8
 275.330 -
 275.331 -OS Locale (lcid: 447): Gujarati (India) - 0
 275.332 -gu_IN
 275.333 -Gujarati (India)
 275.334 -UTF-8
 275.335 -
 275.336 -OS Locale (lcid: 448): Oriya (India) - 0
 275.337 -or_IN
 275.338 -Oriya (India)
 275.339 -UTF-8
 275.340 -
 275.341 -OS Locale (lcid: 449): Tamil (India) - 0
 275.342 -ta_IN
 275.343 -Tamil (India)
 275.344 -UTF-8
 275.345 -
 275.346 -OS Locale (lcid: 44a): Telugu (India) - 0
 275.347 -te_IN
 275.348 -Telugu (India)
 275.349 -UTF-8
 275.350 -
 275.351 -OS Locale (lcid: 44b): Kannada (India) - 0
 275.352 -kn_IN
 275.353 -Kannada (India)
 275.354 -UTF-8
 275.355 -
 275.356 -OS Locale (lcid: 44c): Malayalam (India) - 0
 275.357 -ml_IN
 275.358 -Malayalam (India)
 275.359 -UTF-8
 275.360 -
 275.361 -OS Locale (lcid: 44d): Assamese (India) - 0
 275.362 -as_IN
 275.363 -Assamese (India)
 275.364 -UTF-8
 275.365 -
 275.366 -OS Locale (lcid: 44e): Marathi (India) - 0
 275.367 -mr_IN
 275.368 -Marathi (India)
 275.369 -UTF-8
 275.370 -
 275.371 -OS Locale (lcid: 44f): Sanskrit (India) - 0
 275.372 -sa_IN
 275.373 -Sanskrit (India)
 275.374 -UTF-8
 275.375 -
 275.376 -OS Locale (lcid: 450): Mongolian (Cyrillic) (Mongolia) - 1251
 275.377 -mn_MN
 275.378 -Mongolian (Mongolia)
 275.379 -windows-1251
 275.380 -
 275.381 -OS Locale (lcid: 451): Tibetan (People's Republic of China) - 0
 275.382 -bo_CN
 275.383 -Tibetan (China)
 275.384 -UTF-8
 275.385 -
 275.386 -OS Locale (lcid: 452): Welsh (United Kingdom) - 1252
 275.387 -cy_GB
 275.388 -Welsh (United Kingdom)
 275.389 -windows-1252
 275.390 -
 275.391 -OS Locale (lcid: 453): Khmer (Cambodia) - 0
 275.392 -km_KH
 275.393 -Khmer (Cambodia)
 275.394 -UTF-8
 275.395 -
 275.396 -OS Locale (lcid: 454): Lao (Lao P.D.R.) - 0
 275.397 -lo_LA
 275.398 -Lao (Laos)
 275.399 -UTF-8
 275.400 -
 275.401 -OS Locale (lcid: 456): Galician (Spain) - 1252
 275.402 -gl_ES
 275.403 -Gallegan (Spain)
 275.404 -windows-1252
 275.405 -
 275.406 -OS Locale (lcid: 457): Konkani (India) - 0
 275.407 -en_US
 275.408 -English (United States)
 275.409 -windows-1252
 275.410 -
 275.411 -OS Locale (lcid: 45a): Syriac (Syria) - 0
 275.412 -en_US
 275.413 -English (United States)
 275.414 -windows-1252
 275.415 -
 275.416 -OS Locale (lcid: 45b): Sinhala (Sri Lanka) - 0
 275.417 -si_LK
 275.418 -Sinhalese (Sri Lanka)
 275.419 -UTF-8
 275.420 -
 275.421 -OS Locale (lcid: 45d): Inuktitut (Canada) - 0
 275.422 -iu_CA
 275.423 -Inuktitut (Canada)
 275.424 -UTF-8
 275.425 -
 275.426 -OS Locale (lcid: 45e): Amharic (Ethiopia) - 0
 275.427 -am_ET
 275.428 -Amharic (Ethiopia)
 275.429 -UTF-8
 275.430 -
 275.431 -OS Locale (lcid: 461): Nepali (Nepal) - 0
 275.432 -ne_NP
 275.433 -Nepali (Nepal)
 275.434 -UTF-8
 275.435 -
 275.436 -OS Locale (lcid: 462): Frisian (Netherlands) - 1252
 275.437 -fy_NL
 275.438 -Frisian (Netherlands)
 275.439 -windows-1252
 275.440 -
 275.441 -OS Locale (lcid: 463): Pashto (Afghanistan) - 0
 275.442 -ps_AF
 275.443 -Pushto (Afghanistan)
 275.444 -windows-1256
 275.445 -
 275.446 -OS Locale (lcid: 464): Filipino (Philippines) - 1252
 275.447 -en_US
 275.448 -English (United States)
 275.449 -windows-1252
 275.450 -
 275.451 -OS Locale (lcid: 465): Divehi (Maldives) - 0
 275.452 -dv_MV
 275.453 -Divehi (Maldives)
 275.454 -UTF-8
 275.455 -
 275.456 -OS Locale (lcid: 468): Hausa (Latin) (Nigeria) - 1252
 275.457 -ha_NG
 275.458 -Hausa (Nigeria)
 275.459 -windows-1252
 275.460 -
 275.461 -OS Locale (lcid: 46a): Yoruba (Nigeria) - 1252
 275.462 -yo_NG
 275.463 -Yoruba (Nigeria)
 275.464 -windows-1252
 275.465 -
 275.466 -OS Locale (lcid: 46b): Quechua (Bolivia) - 1252
 275.467 -qu_BO
 275.468 -Quechua (Bolivia)
 275.469 -windows-1252
 275.470 -
 275.471 -OS Locale (lcid: 46c): Sesotho sa Leboa (South Africa) - 1252
 275.472 -en_US
 275.473 -English (United States)
 275.474 -windows-1252
 275.475 -
 275.476 -OS Locale (lcid: 46d): Bashkir (Russia) - 1251
 275.477 -ba_RU
 275.478 -Bashkir (Russia)
 275.479 -windows-1251
 275.480 -
 275.481 -OS Locale (lcid: 46e): Luxembourgish (Luxembourg) - 1252
 275.482 -lb_LU
 275.483 -Luxembourgish (Luxembourg)
 275.484 -windows-1252
 275.485 -
 275.486 -OS Locale (lcid: 46f): Greenlandic (Greenland) - 1252
 275.487 -kl_GL
 275.488 -Greenlandic (Greenland)
 275.489 -windows-1252
 275.490 -
 275.491 -OS Locale (lcid: 470): Igbo (Nigeria) - 1252
 275.492 -ig_NG
 275.493 -Igbo (Nigeria)
 275.494 -windows-1252
 275.495 -
 275.496 -OS Locale (lcid: 478): Yi (People's Republic of China) - 0
 275.497 -en_US
 275.498 -English (United States)
 275.499 -windows-1252
 275.500 -
 275.501 -OS Locale (lcid: 47a): Mapudungun (Chile) - 1252
 275.502 -en_US
 275.503 -English (United States)
 275.504 -windows-1252
 275.505 -
 275.506 -OS Locale (lcid: 47c): Mohawk (Canada) - 1252
 275.507 -en_US
 275.508 -English (United States)
 275.509 -windows-1252
 275.510 -
 275.511 -OS Locale (lcid: 47e): Breton (France) - 1252
 275.512 -br_FR
 275.513 -Breton (France)
 275.514 -windows-1252
 275.515 -
 275.516 -OS Locale (lcid: 480): Uighur (People's Republic of China) - 1256
 275.517 -ug_CN
 275.518 -Uighur (China)
 275.519 -windows-1256
 275.520 -
 275.521 -OS Locale (lcid: 481): Maori (New Zealand) - 0
 275.522 -mi_NZ
 275.523 -Maori (New Zealand)
 275.524 -UTF-8
 275.525 -
 275.526 -OS Locale (lcid: 482): Occitan (France) - 1252
 275.527 -oc_FR
 275.528 -Occitan (France)
 275.529 -windows-1252
 275.530 -
 275.531 -OS Locale (lcid: 483): Corsican (France) - 1252
 275.532 -co_FR
 275.533 -Corsican (France)
 275.534 -windows-1252
 275.535 -
 275.536 -OS Locale (lcid: 484): Alsatian (France) - 1252
 275.537 -en_US
 275.538 -English (United States)
 275.539 -windows-1252
 275.540 -
 275.541 -OS Locale (lcid: 485): Yakut (Russia) - 1251
 275.542 -en_US
 275.543 -English (United States)
 275.544 -windows-1252
 275.545 -
 275.546 -OS Locale (lcid: 486): K'iche (Guatemala) - 1252
 275.547 -en_US
 275.548 -English (United States)
 275.549 -windows-1252
 275.550 -
 275.551 -OS Locale (lcid: 487): Kinyarwanda (Rwanda) - 1252
 275.552 -rw_RW
 275.553 -Kinyarwanda (Rwanda)
 275.554 -windows-1252
 275.555 -
 275.556 -OS Locale (lcid: 488): Wolof (Senegal) - 1252
 275.557 -wo_SN
 275.558 -Wolof (Senegal)
 275.559 -windows-1252
 275.560 -
 275.561 -OS Locale (lcid: 48c): Dari (Afghanistan) - 1256
 275.562 -en_US
 275.563 -English (United States)
 275.564 -windows-1252
 275.565 -
 275.566 -OS Locale (lcid: 801): Arabic (Iraq) - 1256
 275.567 -ar_IQ
 275.568 -Arabic (Iraq)
 275.569 -windows-1256
 275.570 -
 275.571 -OS Locale (lcid: 804): Chinese (People's Republic of China) - 936
 275.572 -zh_CN
 275.573 -Chinese (China)
 275.574 -GBK
 275.575 -
 275.576 -OS Locale (lcid: 807): German (Switzerland) - 1252
 275.577 -de_CH
 275.578 -German (Switzerland)
 275.579 -windows-1252
 275.580 -
 275.581 -OS Locale (lcid: 809): English (United Kingdom) - 1252
 275.582 -en_GB
 275.583 -English (United Kingdom)
 275.584 -windows-1252
 275.585 -
 275.586 -OS Locale (lcid: 80a): Spanish (Mexico) - 1252
 275.587 -es_MX
 275.588 -Spanish (Mexico)
 275.589 -windows-1252
 275.590 -
 275.591 -OS Locale (lcid: 80c): French (Belgium) - 1252
 275.592 -fr_BE
 275.593 -French (Belgium)
 275.594 -windows-1252
 275.595 -
 275.596 -OS Locale (lcid: 810): Italian (Switzerland) - 1252
 275.597 -it_CH
 275.598 -Italian (Switzerland)
 275.599 -windows-1252
 275.600 -
 275.601 -OS Locale (lcid: 813): Dutch (Belgium) - 1252
 275.602 -nl_BE
 275.603 -Dutch (Belgium)
 275.604 -windows-1252
 275.605 -
 275.606 -OS Locale (lcid: 814): Norwegian (Nynorsk) (Norway) - 1252
 275.607 -no_NO_NY
 275.608 -Norwegian (Norway,Nynorsk)
 275.609 -windows-1252
 275.610 -
 275.611 -OS Locale (lcid: 816): Portuguese (Portugal) - 1252
 275.612 -pt_PT
 275.613 -Portuguese (Portugal)
 275.614 -windows-1252
 275.615 -
 275.616 -OS Locale (lcid: 81a): Serbian (Latin) (Serbia and Montenegro) - 1250
 275.617 -sr_CS
 275.618 -Serbian (Serbia and Montenegro)
 275.619 -windows-1250
 275.620 -
 275.621 -OS Locale (lcid: 81d): Swedish (Finland) - 1252
 275.622 -sv_FI
 275.623 -Swedish (Finland)
 275.624 -windows-1252
 275.625 -
 275.626 -OS Locale (lcid: 82c): Azeri (Cyrillic) (Azerbaijan) - 1251
 275.627 -az_AZ
 275.628 -Azerbaijani (Azerbaijan)
 275.629 -windows-1251
 275.630 -
 275.631 -OS Locale (lcid: 82e): Lower Sorbian (Germany) - 1252
 275.632 -en_US
 275.633 -English (United States)
 275.634 -windows-1252
 275.635 -
 275.636 -OS Locale (lcid: 83b): Sami (Northern) (Sweden) - 1252
 275.637 -se_SE
 275.638 -Northern Sami (Sweden)
 275.639 -windows-1252
 275.640 -
 275.641 -OS Locale (lcid: 83c): Irish (Ireland) - 1252
 275.642 -ga_IE
 275.643 -Irish (Ireland)
 275.644 -windows-1252
 275.645 -
 275.646 -OS Locale (lcid: 83e): Malay (Brunei Darussalam) - 1252
 275.647 -ms_BN
 275.648 -Malay (Brunei)
 275.649 -windows-1252
 275.650 -
 275.651 -OS Locale (lcid: 843): Uzbek (Cyrillic) (Uzbekistan) - 1251
 275.652 -uz_UZ
 275.653 -Uzbek (Uzbekistan)
 275.654 -windows-1251
 275.655 -
 275.656 -OS Locale (lcid: 845): Bengali (Bangladesh) - 0
 275.657 -bn_BD
 275.658 -Bengali (Bangladesh)
 275.659 -UTF-8
 275.660 -
 275.661 -OS Locale (lcid: 850): Mongolian (Traditional Mongolian) (People's Republic of China) - 0
 275.662 -mn_CN
 275.663 -Mongolian (China)
 275.664 -UTF-8
 275.665 -
 275.666 -OS Locale (lcid: 85d): Inuktitut (Latin) (Canada) - 1252
 275.667 -iu_CA
 275.668 -Inuktitut (Canada)
 275.669 -windows-1252
 275.670 -
 275.671 -OS Locale (lcid: 85f): Tamazight (Latin) (Algeria) - 1252
 275.672 -en_US
 275.673 -English (United States)
 275.674 -windows-1252
 275.675 -
 275.676 -OS Locale (lcid: 86b): Quechua (Ecuador) - 1252
 275.677 -qu_EC
 275.678 -Quechua (Ecuador)
 275.679 -windows-1252
 275.680 -
 275.681 -OS Locale (lcid: c01): Arabic (Egypt) - 1256
 275.682 -ar_EG
 275.683 -Arabic (Egypt)
 275.684 -windows-1256
 275.685 -
 275.686 -OS Locale (lcid: c04): Chinese (Hong Kong S.A.R.) - 950
 275.687 -zh_HK
 275.688 -Chinese (Hong Kong)
 275.689 -x-windows-950
 275.690 -
 275.691 -OS Locale (lcid: c07): German (Austria) - 1252
 275.692 -de_AT
 275.693 -German (Austria)
 275.694 -windows-1252
 275.695 -
 275.696 -OS Locale (lcid: c09): English (Australia) - 1252
 275.697 -en_AU
 275.698 -English (Australia)
 275.699 -windows-1252
 275.700 -
 275.701 -OS Locale (lcid: c0a): Spanish (Spain) - 1252
 275.702 -es_ES
 275.703 -Spanish (Spain)
 275.704 -windows-1252
 275.705 -
 275.706 -OS Locale (lcid: c0c): French (Canada) - 1252
 275.707 -fr_CA
 275.708 -French (Canada)
 275.709 -windows-1252
 275.710 -
 275.711 -OS Locale (lcid: c1a): Serbian (Cyrillic) (Serbia and Montenegro) - 1251
 275.712 -sr_CS
 275.713 -Serbian (Serbia and Montenegro)
 275.714 -windows-1251
 275.715 -
 275.716 -OS Locale (lcid: c3b): Sami (Northern) (Finland) - 1252
 275.717 -se_FI
 275.718 -Northern Sami (Finland)
 275.719 -windows-1252
 275.720 -
 275.721 -OS Locale (lcid: c6b): Quechua (Peru) - 1252
 275.722 -qu_PE
 275.723 -Quechua (Peru)
 275.724 -windows-1252
 275.725 -
 275.726 -OS Locale (lcid: 1001): Arabic (Libya) - 1256
 275.727 -ar_LY
 275.728 -Arabic (Libya)
 275.729 -windows-1256
 275.730 -
 275.731 -OS Locale (lcid: 1004): Chinese (Singapore) - 936
 275.732 -zh_SG
 275.733 -Chinese (Singapore)
 275.734 -GBK
 275.735 -
 275.736 -OS Locale (lcid: 1007): German (Luxembourg) - 1252
 275.737 -de_LU
 275.738 -German (Luxembourg)
 275.739 -windows-1252
 275.740 -
 275.741 -OS Locale (lcid: 1009): English (Canada) - 1252
 275.742 -en_CA
 275.743 -English (Canada)
 275.744 -windows-1252
 275.745 -
 275.746 -OS Locale (lcid: 100a): Spanish (Guatemala) - 1252
 275.747 -es_GT
 275.748 -Spanish (Guatemala)
 275.749 -windows-1252
 275.750 -
 275.751 -OS Locale (lcid: 100c): French (Switzerland) - 1252
 275.752 -fr_CH
 275.753 -French (Switzerland)
 275.754 -windows-1252
 275.755 -
 275.756 -OS Locale (lcid: 101a): Croatian (Latin) (Bosnia and Herzegovina) - 1250
 275.757 -hr_BA
 275.758 -Croatian (Bosnia and Herzegovina)
 275.759 -windows-1250
 275.760 -
 275.761 -OS Locale (lcid: 103b): Sami (Lule) (Norway) - 1252
 275.762 -se
 275.763 -Northern Sami
 275.764 -windows-1252
 275.765 -
 275.766 -OS Locale (lcid: 1401): Arabic (Algeria) - 1256
 275.767 -ar_DZ
 275.768 -Arabic (Algeria)
 275.769 -windows-1256
 275.770 -
 275.771 -OS Locale (lcid: 1404): Chinese (Macao S.A.R.) - 950
 275.772 -zh_MO
 275.773 -Chinese (Macao)
 275.774 -x-windows-950
 275.775 -
 275.776 -OS Locale (lcid: 1407): German (Liechtenstein) - 1252
 275.777 -de_LI
 275.778 -German (Liechtenstein)
 275.779 -windows-1252
 275.780 -
 275.781 -OS Locale (lcid: 1409): English (New Zealand) - 1252
 275.782 -en_NZ
 275.783 -English (New Zealand)
 275.784 -windows-1252
 275.785 -
 275.786 -OS Locale (lcid: 140a): Spanish (Costa Rica) - 1252
 275.787 -es_CR
 275.788 -Spanish (Costa Rica)
 275.789 -windows-1252
 275.790 -
 275.791 -OS Locale (lcid: 140c): French (Luxembourg) - 1252
 275.792 -fr_LU
 275.793 -French (Luxembourg)
 275.794 -windows-1252
 275.795 -
 275.796 -OS Locale (lcid: 141a): Bosnian (Latin) (Bosnia and Herzegovina) - 1250
 275.797 -bs_BA
 275.798 -Bosnian (Bosnia and Herzegovina)
 275.799 -windows-1250
 275.800 -
 275.801 -OS Locale (lcid: 143b): Sami (Lule) (Sweden) - 1252
 275.802 -se
 275.803 -Northern Sami
 275.804 -windows-1252
 275.805 -
 275.806 -OS Locale (lcid: 1801): Arabic (Morocco) - 1256
 275.807 -ar_MA
 275.808 -Arabic (Morocco)
 275.809 -windows-1256
 275.810 -
 275.811 -OS Locale (lcid: 1809): English (Ireland) - 1252
 275.812 -en_IE
 275.813 -English (Ireland)
 275.814 -windows-1252
 275.815 -
 275.816 -OS Locale (lcid: 180a): Spanish (Panama) - 1252
 275.817 -es_PA
 275.818 -Spanish (Panama)
 275.819 -windows-1252
 275.820 -
 275.821 -OS Locale (lcid: 180c): French (Principality of Monaco) - 1252
 275.822 -fr_MC
 275.823 -French (Monaco)
 275.824 -windows-1252
 275.825 -
 275.826 -OS Locale (lcid: 181a): Serbian (Latin) (Bosnia and Herzegovina) - 1250
 275.827 -sr_BA
 275.828 -Serbian (Bosnia and Herzegovina)
 275.829 -windows-1250
 275.830 -
 275.831 -OS Locale (lcid: 183b): Sami (Southern) (Norway) - 1252
 275.832 -se
 275.833 -Northern Sami
 275.834 -windows-1252
 275.835 -
 275.836 -OS Locale (lcid: 1c01): Arabic (Tunisia) - 1256
 275.837 -ar_TN
 275.838 -Arabic (Tunisia)
 275.839 -windows-1256
 275.840 -
 275.841 -OS Locale (lcid: 1c09): English (South Africa) - 1252
 275.842 -en_ZA
 275.843 -English (South Africa)
 275.844 -windows-1252
 275.845 -
 275.846 -OS Locale (lcid: 1c0a): Spanish (Dominican Republic) - 1252
 275.847 -es_DO
 275.848 -Spanish (Dominican Republic)
 275.849 -windows-1252
 275.850 -
 275.851 -OS Locale (lcid: 1c1a): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
 275.852 -sr_BA
 275.853 -Serbian (Bosnia and Herzegovina)
 275.854 -windows-1251
 275.855 -
 275.856 -OS Locale (lcid: 1c3b): Sami (Southern) (Sweden) - 1252
 275.857 -se
 275.858 -Northern Sami
 275.859 -windows-1252
 275.860 -
 275.861 -OS Locale (lcid: 2001): Arabic (Oman) - 1256
 275.862 -ar_OM
 275.863 -Arabic (Oman)
 275.864 -windows-1256
 275.865 -
 275.866 -OS Locale (lcid: 2009): English (Jamaica) - 1252
 275.867 -en_JM
 275.868 -English (Jamaica)
 275.869 -windows-1252
 275.870 -
 275.871 -OS Locale (lcid: 200a): Spanish (Venezuela) - 1252
 275.872 -es_VE
 275.873 -Spanish (Venezuela)
 275.874 -windows-1252
 275.875 -
 275.876 -OS Locale (lcid: 201a): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1251
 275.877 -bs_BA
 275.878 -Bosnian (Bosnia and Herzegovina)
 275.879 -windows-1250
 275.880 -
 275.881 -OS Locale (lcid: 203b): Sami (Skolt) (Finland) - 1252
 275.882 -se
 275.883 -Northern Sami
 275.884 -windows-1252
 275.885 -
 275.886 -OS Locale (lcid: 2401): Arabic (Yemen) - 1256
 275.887 -ar_YE
 275.888 -Arabic (Yemen)
 275.889 -windows-1256
 275.890 -
 275.891 -OS Locale (lcid: 2409): English (Caribbean) - 1252
 275.892 -en
 275.893 -English
 275.894 -windows-1252
 275.895 -
 275.896 -OS Locale (lcid: 240a): Spanish (Colombia) - 1252
 275.897 -es_CO
 275.898 -Spanish (Colombia)
 275.899 -windows-1252
 275.900 -
 275.901 -OS Locale (lcid: 243b): Sami (Inari) (Finland) - 1252
 275.902 -se
 275.903 -Northern Sami
 275.904 -windows-1252
 275.905 -
 275.906 -OS Locale (lcid: 2801): Arabic (Syria) - 1256
 275.907 -ar_SY
 275.908 -Arabic (Syria)
 275.909 -windows-1256
 275.910 -
 275.911 -OS Locale (lcid: 2809): English (Belize) - 1252
 275.912 -en_BZ
 275.913 -English (Belize)
 275.914 -windows-1252
 275.915 -
 275.916 -OS Locale (lcid: 280a): Spanish (Peru) - 1252
 275.917 -es_PE
 275.918 -Spanish (Peru)
 275.919 -windows-1252
 275.920 -
 275.921 -OS Locale (lcid: 2c01): Arabic (Jordan) - 1256
 275.922 -ar_JO
 275.923 -Arabic (Jordan)
 275.924 -windows-1256
 275.925 -
 275.926 -OS Locale (lcid: 2c09): English (Trinidad and Tobago) - 1252
 275.927 -en_TT
 275.928 -English (Trinidad and Tobago)
 275.929 -windows-1252
 275.930 -
 275.931 -OS Locale (lcid: 2c0a): Spanish (Argentina) - 1252
 275.932 -es_AR
 275.933 -Spanish (Argentina)
 275.934 -windows-1252
 275.935 -
 275.936 -OS Locale (lcid: 3001): Arabic (Lebanon) - 1256
 275.937 -ar_LB
 275.938 -Arabic (Lebanon)
 275.939 -windows-1256
 275.940 -
 275.941 -OS Locale (lcid: 3009): English (Zimbabwe) - 1252
 275.942 -en_ZW
 275.943 -English (Zimbabwe)
 275.944 -windows-1252
 275.945 -
 275.946 -OS Locale (lcid: 300a): Spanish (Ecuador) - 1252
 275.947 -es_EC
 275.948 -Spanish (Ecuador)
 275.949 -windows-1252
 275.950 -
 275.951 -OS Locale (lcid: 3401): Arabic (Kuwait) - 1256
 275.952 -ar_KW
 275.953 -Arabic (Kuwait)
 275.954 -windows-1256
 275.955 -
 275.956 -OS Locale (lcid: 3409): English (Republic of the Philippines) - 1252
 275.957 -en_PH
 275.958 -English (Philippines)
 275.959 -windows-1252
 275.960 -
 275.961 -OS Locale (lcid: 340a): Spanish (Chile) - 1252
 275.962 -es_CL
 275.963 -Spanish (Chile)
 275.964 -windows-1252
 275.965 -
 275.966 -OS Locale (lcid: 3801): Arabic (U.A.E.) - 1256
 275.967 -ar_AE
 275.968 -Arabic (United Arab Emirates)
 275.969 -windows-1256
 275.970 -
 275.971 -OS Locale (lcid: 380a): Spanish (Uruguay) - 1252
 275.972 -es_UY
 275.973 -Spanish (Uruguay)
 275.974 -windows-1252
 275.975 -
 275.976 -OS Locale (lcid: 3c01): Arabic (Bahrain) - 1256
 275.977 -ar_BH
 275.978 -Arabic (Bahrain)
 275.979 -windows-1256
 275.980 -
 275.981 -OS Locale (lcid: 3c0a): Spanish (Paraguay) - 1252
 275.982 -es_PY
 275.983 -Spanish (Paraguay)
 275.984 -windows-1252
 275.985 -
 275.986 -OS Locale (lcid: 4001): Arabic (Qatar) - 1256
 275.987 -ar_QA
 275.988 -Arabic (Qatar)
 275.989 -windows-1256
 275.990 -
 275.991 -OS Locale (lcid: 4009): English (India) - 1252
 275.992 -en_IN
 275.993 -English (India)
 275.994 -windows-1252
 275.995 -
 275.996 -OS Locale (lcid: 400a): Spanish (Bolivia) - 1252
 275.997 -es_BO
 275.998 -Spanish (Bolivia)
 275.999 -windows-1252
275.1000 -
275.1001 -OS Locale (lcid: 4409): English (Malaysia) - 1252
275.1002 -en_MY
275.1003 -English (Malaysia)
275.1004 -windows-1252
275.1005 -
275.1006 -OS Locale (lcid: 440a): Spanish (El Salvador) - 1252
275.1007 -es_SV
275.1008 -Spanish (El Salvador)
275.1009 -windows-1252
275.1010 -
275.1011 -OS Locale (lcid: 4809): English (Singapore) - 1252
275.1012 -en_SG
275.1013 -English (Singapore)
275.1014 -windows-1252
275.1015 -
275.1016 -OS Locale (lcid: 480a): Spanish (Honduras) - 1252
275.1017 -es_HN
275.1018 -Spanish (Honduras)
275.1019 -windows-1252
275.1020 -
275.1021 -OS Locale (lcid: 4c0a): Spanish (Nicaragua) - 1252
275.1022 -es_NI
275.1023 -Spanish (Nicaragua)
275.1024 -windows-1252
275.1025 -
275.1026 -OS Locale (lcid: 500a): Spanish (Puerto Rico) - 1252
275.1027 -es_PR
275.1028 -Spanish (Puerto Rico)
275.1029 -windows-1252
275.1030 -
275.1031 -OS Locale (lcid: 540a): Spanish (United States) - 1252
275.1032 -es_US
275.1033 -Spanish (United States)
275.1034 -windows-1252
   276.1 --- a/test/java/util/Locale/data/deflocale.winxp	Thu Sep 23 17:33:40 2010 -0700
   276.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   276.3 @@ -1,861 +0,0 @@
   276.4 -# OSVersionInfo
   276.5 -# MajorVersion: 5
   276.6 -# MinorVersion: 1
   276.7 -# BuildNumber: 2600
   276.8 -# CSDVersion: Service Pack 2
   276.9 -
  276.10 -
  276.11 -OS Locale (lcid: 401): Arabic (Saudi Arabia) - 1256
  276.12 -ar_SA
  276.13 -Arabic (Saudi Arabia)
  276.14 -windows-1256
  276.15 -
  276.16 -OS Locale (lcid: 402): Bulgarian (Bulgaria) - 1251
  276.17 -bg_BG
  276.18 -Bulgarian (Bulgaria)
  276.19 -windows-1251
  276.20 -
  276.21 -OS Locale (lcid: 403): Catalan (Spain) - 1252
  276.22 -ca_ES
  276.23 -Catalan (Spain)
  276.24 -windows-1252
  276.25 -
  276.26 -OS Locale (lcid: 404): Chinese (Taiwan) - 950
  276.27 -zh_TW
  276.28 -Chinese (Taiwan)
  276.29 -x-windows-950
  276.30 -
  276.31 -OS Locale (lcid: 405): Czech (Czech Republic) - 1250
  276.32 -cs_CZ
  276.33 -Czech (Czech Republic)
  276.34 -windows-1250
  276.35 -
  276.36 -OS Locale (lcid: 406): Danish (Denmark) - 1252
  276.37 -da_DK
  276.38 -Danish (Denmark)
  276.39 -windows-1252
  276.40 -
  276.41 -OS Locale (lcid: 407): German (Germany) - 1252
  276.42 -de_DE
  276.43 -German (Germany)
  276.44 -windows-1252
  276.45 -
  276.46 -OS Locale (lcid: 408): Greek (Greece) - 1253
  276.47 -el_GR
  276.48 -Greek (Greece)
  276.49 -windows-1253
  276.50 -
  276.51 -OS Locale (lcid: 409): English (United States) - 1252
  276.52 -en_US
  276.53 -English (United States)
  276.54 -windows-1252
  276.55 -
  276.56 -OS Locale (lcid: 40a): Spanish (Spain) - 1252
  276.57 -es_ES
  276.58 -Spanish (Spain)
  276.59 -windows-1252
  276.60 -
  276.61 -OS Locale (lcid: 40b): Finnish (Finland) - 1252
  276.62 -fi_FI
  276.63 -Finnish (Finland)
  276.64 -windows-1252
  276.65 -
  276.66 -OS Locale (lcid: 40c): French (France) - 1252
  276.67 -fr_FR
  276.68 -French (France)
  276.69 -windows-1252
  276.70 -
  276.71 -OS Locale (lcid: 40d): Hebrew (Israel) - 1255
  276.72 -iw_IL
  276.73 -Hebrew (Israel)
  276.74 -windows-1255
  276.75 -
  276.76 -OS Locale (lcid: 40e): Hungarian (Hungary) - 1250
  276.77 -hu_HU
  276.78 -Hungarian (Hungary)
  276.79 -windows-1250
  276.80 -
  276.81 -OS Locale (lcid: 40f): Icelandic (Iceland) - 1252
  276.82 -is_IS
  276.83 -Icelandic (Iceland)
  276.84 -windows-1252
  276.85 -
  276.86 -OS Locale (lcid: 410): Italian (Italy) - 1252
  276.87 -it_IT
  276.88 -Italian (Italy)
  276.89 -windows-1252
  276.90 -
  276.91 -OS Locale (lcid: 411): Japanese (Japan) - 932
  276.92 -ja_JP
  276.93 -Japanese (Japan)
  276.94 -windows-31j
  276.95 -
  276.96 -OS Locale (lcid: 412): Korean (Korea) - 949
  276.97 -ko_KR
  276.98 -Korean (South Korea)
  276.99 -x-windows-949
 276.100 -
 276.101 -OS Locale (lcid: 413): Dutch (Netherlands) - 1252
 276.102 -nl_NL
 276.103 -Dutch (Netherlands)
 276.104 -windows-1252
 276.105 -
 276.106 -OS Locale (lcid: 414): Norwegian (Bokmål) (Norway) - 1252
 276.107 -no_NO
 276.108 -Norwegian (Norway)
 276.109 -windows-1252
 276.110 -
 276.111 -OS Locale (lcid: 415): Polish (Poland) - 1250
 276.112 -pl_PL
 276.113 -Polish (Poland)
 276.114 -windows-1250
 276.115 -
 276.116 -OS Locale (lcid: 416): Portuguese (Brazil) - 1252
 276.117 -pt_BR
 276.118 -Portuguese (Brazil)
 276.119 -windows-1252
 276.120 -
 276.121 -OS Locale (lcid: 417): Romansh (Switzerland) - 1252
 276.122 -rm_CH
 276.123 -Raeto-Romance (Switzerland)
 276.124 -windows-1252
 276.125 -
 276.126 -OS Locale (lcid: 418): Romanian (Romania) - 1250
 276.127 -ro_RO
 276.128 -Romanian (Romania)
 276.129 -windows-1250
 276.130 -
 276.131 -OS Locale (lcid: 419): Russian (Russia) - 1251
 276.132 -ru_RU
 276.133 -Russian (Russia)
 276.134 -windows-1251
 276.135 -
 276.136 -OS Locale (lcid: 41a): Croatian (Croatia) - 1250
 276.137 -hr_HR
 276.138 -Croatian (Croatia)
 276.139 -windows-1250
 276.140 -
 276.141 -OS Locale (lcid: 41b): Slovak (Slovakia) - 1250
 276.142 -sk_SK
 276.143 -Slovak (Slovakia)
 276.144 -windows-1250
 276.145 -
 276.146 -OS Locale (lcid: 41c): Albanian (Albania) - 1250
 276.147 -sq_AL
 276.148 -Albanian (Albania)
 276.149 -windows-1250
 276.150 -
 276.151 -OS Locale (lcid: 41d): Swedish (Sweden) - 1252
 276.152 -sv_SE
 276.153 -Swedish (Sweden)
 276.154 -windows-1252
 276.155 -
 276.156 -OS Locale (lcid: 41e): Thai (Thailand) - 874
 276.157 -th_TH
 276.158 -Thai (Thailand)
 276.159 -x-windows-874
 276.160 -
 276.161 -OS Locale (lcid: 41f): Turkish (Turkey) - 1254
 276.162 -tr_TR
 276.163 -Turkish (Turkey)
 276.164 -windows-1254
 276.165 -
 276.166 -OS Locale (lcid: 420): Urdu (Islamic Republic of Pakistan) - 1256
 276.167 -ur_PK
 276.168 -Urdu (Pakistan)
 276.169 -windows-1256
 276.170 -
 276.171 -OS Locale (lcid: 421): Indonesian (Indonesia) - 1252
 276.172 -in_ID
 276.173 -Indonesian (Indonesia)
 276.174 -windows-1252
 276.175 -
 276.176 -OS Locale (lcid: 422): Ukrainian (Ukraine) - 1251
 276.177 -uk_UA
 276.178 -Ukrainian (Ukraine)
 276.179 -windows-1251
 276.180 -
 276.181 -OS Locale (lcid: 423): Belarusian (Belarus) - 1251
 276.182 -be_BY
 276.183 -Belarusian (Belarus)
 276.184 -windows-1251
 276.185 -
 276.186 -OS Locale (lcid: 424): Slovenian (Slovenia) - 1250
 276.187 -sl_SI
 276.188 -Slovenian (Slovenia)
 276.189 -windows-1250
 276.190 -
 276.191 -OS Locale (lcid: 425): Estonian (Estonia) - 1257
 276.192 -et_EE
 276.193 -Estonian (Estonia)
 276.194 -windows-1257
 276.195 -
 276.196 -OS Locale (lcid: 426): Latvian (Latvia) - 1257
 276.197 -lv_LV
 276.198 -Latvian (Latvia)
 276.199 -windows-1257
 276.200 -
 276.201 -OS Locale (lcid: 427): Lithuanian (Lithuania) - 1257
 276.202 -lt_LT
 276.203 -Lithuanian (Lithuania)
 276.204 -windows-1257
 276.205 -
 276.206 -OS Locale (lcid: 429): Farsi (Iran) - 1256
 276.207 -fa_IR
 276.208 -Persian (Iran)
 276.209 -windows-1256
 276.210 -
 276.211 -OS Locale (lcid: 42a): Vietnamese (Viet Nam) - 1258
 276.212 -vi_VN
 276.213 -Vietnamese (Vietnam)
 276.214 -windows-1258
 276.215 -
 276.216 -OS Locale (lcid: 42b): Armenian (Armenia) - 0
 276.217 -hy_AM
 276.218 -Armenian (Armenia)
 276.219 -UTF-8
 276.220 -
 276.221 -OS Locale (lcid: 42c): Azeri (Latin) (Azerbaijan) - 1254
 276.222 -az_AZ
 276.223 -Azerbaijani (Azerbaijan)
 276.224 -windows-1254
 276.225 -
 276.226 -OS Locale (lcid: 42d): Basque (Spain) - 1252
 276.227 -eu_ES
 276.228 -Basque (Spain)
 276.229 -windows-1252
 276.230 -
 276.231 -OS Locale (lcid: 42f): FYRO Macedonian (Former Yugoslav Republic of Macedonia) - 1251
 276.232 -mk_MK
 276.233 -Macedonian (Macedonia)
 276.234 -windows-1251
 276.235 -
 276.236 -OS Locale (lcid: 432): Tswana (South Africa) - 1252
 276.237 -tn_ZA
 276.238 -Tswana (South Africa)
 276.239 -windows-1252
 276.240 -
 276.241 -OS Locale (lcid: 434): Xhosa (South Africa) - 1252
 276.242 -xh_ZA
 276.243 -Xhosa (South Africa)
 276.244 -windows-1252
 276.245 -
 276.246 -OS Locale (lcid: 435): Zulu (South Africa) - 1252
 276.247 -zu_ZA
 276.248 -Zulu (South Africa)
 276.249 -windows-1252
 276.250 -
 276.251 -OS Locale (lcid: 436): Afrikaans (South Africa) - 1252
 276.252 -af_ZA
 276.253 -Afrikaans (South Africa)
 276.254 -windows-1252
 276.255 -
 276.256 -OS Locale (lcid: 437): Georgian (Georgia) - 0
 276.257 -ka_GE
 276.258 -Georgian (Georgia)
 276.259 -UTF-8
 276.260 -
 276.261 -OS Locale (lcid: 438): Faroese (Faroe Islands) - 1252
 276.262 -fo_FO
 276.263 -Faroese (Faroe Islands)
 276.264 -windows-1252
 276.265 -
 276.266 -OS Locale (lcid: 439): Hindi (India) - 0
 276.267 -hi_IN
 276.268 -Hindi (India)
 276.269 -UTF-8
 276.270 -
 276.271 -OS Locale (lcid: 43a): Maltese (Malta) - 0
 276.272 -mt_MT
 276.273 -Maltese (Malta)
 276.274 -UTF-8
 276.275 -
 276.276 -OS Locale (lcid: 43b): Sami (Northern) (Norway) - 1252
 276.277 -se_NO
 276.278 -Northern Sami (Norway)
 276.279 -windows-1252
 276.280 -
 276.281 -OS Locale (lcid: 43e): Malay (Malaysia) - 1252
 276.282 -ms_MY
 276.283 -Malay (Malaysia)
 276.284 -windows-1252
 276.285 -
 276.286 -OS Locale (lcid: 43f): Kazakh (Kazakhstan) - 1251
 276.287 -kk_KZ
 276.288 -Kazakh (Kazakhstan)
 276.289 -windows-1251
 276.290 -
 276.291 -OS Locale (lcid: 440): Kyrgyz (Kyrgyzstan) - 1251
 276.292 -ky_KG
 276.293 -Kirghiz (Kyrgyzstan)
 276.294 -windows-1251
 276.295 -
 276.296 -OS Locale (lcid: 441): Swahili (Kenya) - 1252
 276.297 -sw_KE
 276.298 -Swahili (Kenya)
 276.299 -windows-1252
 276.300 -
 276.301 -OS Locale (lcid: 443): Uzbek (Latin) (Uzbekistan) - 1254
 276.302 -uz_UZ
 276.303 -Uzbek (Uzbekistan)
 276.304 -windows-1254
 276.305 -
 276.306 -OS Locale (lcid: 444): Tatar (Russia) - 1251
 276.307 -tt_RU
 276.308 -Tatar (Russia)
 276.309 -windows-1251
 276.310 -
 276.311 -OS Locale (lcid: 445): Bengali (India) - 0
 276.312 -bn_IN
 276.313 -Bengali (India)
 276.314 -UTF-8
 276.315 -
 276.316 -OS Locale (lcid: 446): Punjabi (India) - 0
 276.317 -pa_IN
 276.318 -Panjabi (India)
 276.319 -UTF-8
 276.320 -
 276.321 -OS Locale (lcid: 447): Gujarati (India) - 0
 276.322 -gu_IN
 276.323 -Gujarati (India)
 276.324 -UTF-8
 276.325 -
 276.326 -OS Locale (lcid: 449): Tamil (India) - 0
 276.327 -ta_IN
 276.328 -Tamil (India)
 276.329 -UTF-8
 276.330 -
 276.331 -OS Locale (lcid: 44a): Telugu (India) - 0
 276.332 -te_IN
 276.333 -Telugu (India)
 276.334 -UTF-8
 276.335 -
 276.336 -OS Locale (lcid: 44b): Kannada (India) - 0
 276.337 -kn_IN
 276.338 -Kannada (India)
 276.339 -UTF-8
 276.340 -
 276.341 -OS Locale (lcid: 44c): Malayalam (India) - 0
 276.342 -ml_IN
 276.343 -Malayalam (India)
 276.344 -UTF-8
 276.345 -
 276.346 -OS Locale (lcid: 44e): Marathi (India) - 0
 276.347 -mr_IN
 276.348 -Marathi (India)
 276.349 -UTF-8
 276.350 -
 276.351 -OS Locale (lcid: 44f): Sanskrit (India) - 0
 276.352 -sa_IN
 276.353 -Sanskrit (India)
 276.354 -UTF-8
 276.355 -
 276.356 -OS Locale (lcid: 450): Mongolian (Mongolia) - 1251
 276.357 -mn_MN
 276.358 -Mongolian (Mongolia)
 276.359 -windows-1251
 276.360 -
 276.361 -OS Locale (lcid: 452): Welsh (United Kingdom) - 1252
 276.362 -cy_GB
 276.363 -Welsh (United Kingdom)
 276.364 -windows-1252
 276.365 -
 276.366 -OS Locale (lcid: 456): Galician (Spain) - 1252
 276.367 -gl_ES
 276.368 -Gallegan (Spain)
 276.369 -windows-1252
 276.370 -
 276.371 -OS Locale (lcid: 457): Konkani (India) - 0
 276.372 -en_US
 276.373 -English (United States)
 276.374 -windows-1252
 276.375 -
 276.376 -OS Locale (lcid: 45a): Syriac (Syria) - 0
 276.377 -en_US
 276.378 -English (United States)
 276.379 -windows-1252
 276.380 -
 276.381 -OS Locale (lcid: 461): Nepali (Nepal) - 0
 276.382 -ne_NP
 276.383 -Nepali (Nepal)
 276.384 -UTF-8
 276.385 -
 276.386 -OS Locale (lcid: 462): Frisian (Netherlands) - 1252
 276.387 -fy_NL
 276.388 -Frisian (Netherlands)
 276.389 -windows-1252
 276.390 -
 276.391 -OS Locale (lcid: 463): Pashto (Afghanistan) - 1256
 276.392 -ps_AF
 276.393 -Pushto (Afghanistan)
 276.394 -windows-1256
 276.395 -
 276.396 -OS Locale (lcid: 464): Filipino (Philippines) - 1252
 276.397 -en_US
 276.398 -English (United States)
 276.399 -windows-1252
 276.400 -
 276.401 -OS Locale (lcid: 465): Divehi (Maldives) - 0
 276.402 -dv_MV
 276.403 -Divehi (Maldives)
 276.404 -UTF-8
 276.405 -
 276.406 -OS Locale (lcid: 46b): Quechua (Bolivia) - 1252
 276.407 -qu_BO
 276.408 -Quechua (Bolivia)
 276.409 -windows-1252
 276.410 -
 276.411 -OS Locale (lcid: 46c): Northern Sotho (South Africa) - 1252
 276.412 -en_US
 276.413 -English (United States)
 276.414 -windows-1252
 276.415 -
 276.416 -OS Locale (lcid: 46e): Luxembourgish (Luxembourg) - 1252
 276.417 -lb_LU
 276.418 -Luxembourgish (Luxembourg)
 276.419 -windows-1252
 276.420 -
 276.421 -OS Locale (lcid: 47a): Mapudungun (Chile) - 1252
 276.422 -en_US
 276.423 -English (United States)
 276.424 -windows-1252
 276.425 -
 276.426 -OS Locale (lcid: 47c): Mohawk (Canada) - 1252
 276.427 -en_US
 276.428 -English (United States)
 276.429 -windows-1252
 276.430 -
 276.431 -OS Locale (lcid: 481): Maori (New Zealand) - 0
 276.432 -mi_NZ
 276.433 -Maori (New Zealand)
 276.434 -UTF-8
 276.435 -
 276.436 -OS Locale (lcid: 801): Arabic (Iraq) - 1256
 276.437 -ar_IQ
 276.438 -Arabic (Iraq)
 276.439 -windows-1256
 276.440 -
 276.441 -OS Locale (lcid: 804): Chinese (People's Republic of China) - 936
 276.442 -zh_CN
 276.443 -Chinese (China)
 276.444 -GBK
 276.445 -
 276.446 -OS Locale (lcid: 807): German (Switzerland) - 1252
 276.447 -de_CH
 276.448 -German (Switzerland)
 276.449 -windows-1252
 276.450 -
 276.451 -OS Locale (lcid: 809): English (United Kingdom) - 1252
 276.452 -en_GB
 276.453 -English (United Kingdom)
 276.454 -windows-1252
 276.455 -
 276.456 -OS Locale (lcid: 80a): Spanish (Mexico) - 1252
 276.457 -es_MX
 276.458 -Spanish (Mexico)
 276.459 -windows-1252
 276.460 -
 276.461 -OS Locale (lcid: 80c): French (Belgium) - 1252
 276.462 -fr_BE
 276.463 -French (Belgium)
 276.464 -windows-1252
 276.465 -
 276.466 -OS Locale (lcid: 810): Italian (Switzerland) - 1252
 276.467 -it_CH
 276.468 -Italian (Switzerland)
 276.469 -windows-1252
 276.470 -
 276.471 -OS Locale (lcid: 813): Dutch (Belgium) - 1252
 276.472 -nl_BE
 276.473 -Dutch (Belgium)
 276.474 -windows-1252
 276.475 -
 276.476 -OS Locale (lcid: 814): Norwegian (Nynorsk) (Norway) - 1252
 276.477 -no_NO_NY
 276.478 -Norwegian (Norway,Nynorsk)
 276.479 -windows-1252
 276.480 -
 276.481 -OS Locale (lcid: 816): Portuguese (Portugal) - 1252
 276.482 -pt_PT
 276.483 -Portuguese (Portugal)
 276.484 -windows-1252
 276.485 -
 276.486 -OS Locale (lcid: 81a): Serbian (Latin) (Serbia and Montenegro) - 1250
 276.487 -sr_CS
 276.488 -Serbian (Serbia and Montenegro)
 276.489 -windows-1250
 276.490 -
 276.491 -OS Locale (lcid: 81d): Swedish (Finland) - 1252
 276.492 -sv_FI
 276.493 -Swedish (Finland)
 276.494 -windows-1252
 276.495 -
 276.496 -OS Locale (lcid: 82c): Azeri (Cyrillic) (Azerbaijan) - 1251
 276.497 -az_AZ
 276.498 -Azerbaijani (Azerbaijan)
 276.499 -windows-1251
 276.500 -
 276.501 -OS Locale (lcid: 83b): Sami (Northern) (Sweden) - 1252
 276.502 -se_SE
 276.503 -Northern Sami (Sweden)
 276.504 -windows-1252
 276.505 -
 276.506 -OS Locale (lcid: 83c): Irish (Ireland) - 1252
 276.507 -ga_IE
 276.508 -Irish (Ireland)
 276.509 -windows-1252
 276.510 -
 276.511 -OS Locale (lcid: 83e): Malay (Brunei Darussalam) - 1252
 276.512 -ms_BN
 276.513 -Malay (Brunei)
 276.514 -windows-1252
 276.515 -
 276.516 -OS Locale (lcid: 843): Uzbek (Cyrillic) (Uzbekistan) - 1251
 276.517 -uz_UZ
 276.518 -Uzbek (Uzbekistan)
 276.519 -windows-1251
 276.520 -
 276.521 -OS Locale (lcid: 85d): Inuktitut (Latin) (Canada) - 1252
 276.522 -iu_CA
 276.523 -Inuktitut (Canada)
 276.524 -windows-1252
 276.525 -
 276.526 -OS Locale (lcid: 86b): Quechua (Ecuador) - 1252
 276.527 -qu_EC
 276.528 -Quechua (Ecuador)
 276.529 -windows-1252
 276.530 -
 276.531 -OS Locale (lcid: c01): Arabic (Egypt) - 1256
 276.532 -ar_EG
 276.533 -Arabic (Egypt)
 276.534 -windows-1256
 276.535 -
 276.536 -OS Locale (lcid: c04): Chinese (Hong Kong S.A.R.) - 950
 276.537 -zh_HK
 276.538 -Chinese (Hong Kong)
 276.539 -x-windows-950
 276.540 -
 276.541 -OS Locale (lcid: c07): German (Austria) - 1252
 276.542 -de_AT
 276.543 -German (Austria)
 276.544 -windows-1252
 276.545 -
 276.546 -OS Locale (lcid: c09): English (Australia) - 1252
 276.547 -en_AU
 276.548 -English (Australia)
 276.549 -windows-1252
 276.550 -
 276.551 -OS Locale (lcid: c0a): Spanish (Spain) - 1252
 276.552 -es_ES
 276.553 -Spanish (Spain)
 276.554 -windows-1252
 276.555 -
 276.556 -OS Locale (lcid: c0c): French (Canada) - 1252
 276.557 -fr_CA
 276.558 -French (Canada)
 276.559 -windows-1252
 276.560 -
 276.561 -OS Locale (lcid: c1a): Serbian (Cyrillic) (Serbia and Montenegro) - 1251
 276.562 -sr_CS
 276.563 -Serbian (Serbia and Montenegro)
 276.564 -windows-1251
 276.565 -
 276.566 -OS Locale (lcid: c3b): Sami (Northern) (Finland) - 1252
 276.567 -se_FI
 276.568 -Northern Sami (Finland)
 276.569 -windows-1252
 276.570 -
 276.571 -OS Locale (lcid: c6b): Quechua (Peru) - 1252
 276.572 -qu_PE
 276.573 -Quechua (Peru)
 276.574 -windows-1252
 276.575 -
 276.576 -OS Locale (lcid: 1001): Arabic (Libya) - 1256
 276.577 -ar_LY
 276.578 -Arabic (Libya)
 276.579 -windows-1256
 276.580 -
 276.581 -OS Locale (lcid: 1004): Chinese (Singapore) - 936
 276.582 -zh_SG
 276.583 -Chinese (Singapore)
 276.584 -GBK
 276.585 -
 276.586 -OS Locale (lcid: 1007): German (Luxembourg) - 1252
 276.587 -de_LU
 276.588 -German (Luxembourg)
 276.589 -windows-1252
 276.590 -
 276.591 -OS Locale (lcid: 1009): English (Canada) - 1252
 276.592 -en_CA
 276.593 -English (Canada)
 276.594 -windows-1252
 276.595 -
 276.596 -OS Locale (lcid: 100a): Spanish (Guatemala) - 1252
 276.597 -es_GT
 276.598 -Spanish (Guatemala)
 276.599 -windows-1252
 276.600 -
 276.601 -OS Locale (lcid: 100c): French (Switzerland) - 1252
 276.602 -fr_CH
 276.603 -French (Switzerland)
 276.604 -windows-1252
 276.605 -
 276.606 -OS Locale (lcid: 101a): Croatian (Bosnia and Herzegovina) - 1250
 276.607 -hr_BA
 276.608 -Croatian (Bosnia and Herzegovina)
 276.609 -windows-1250
 276.610 -
 276.611 -OS Locale (lcid: 103b): Sami (Lule) (Norway) - 1252
 276.612 -se
 276.613 -Northern Sami
 276.614 -windows-1252
 276.615 -
 276.616 -OS Locale (lcid: 1401): Arabic (Algeria) - 1256
 276.617 -ar_DZ
 276.618 -Arabic (Algeria)
 276.619 -windows-1256
 276.620 -
 276.621 -OS Locale (lcid: 1404): Chinese (Macau S.A.R.) - 950
 276.622 -zh_MO
 276.623 -Chinese (Macao)
 276.624 -x-windows-950
 276.625 -
 276.626 -OS Locale (lcid: 1407): German (Liechtenstein) - 1252
 276.627 -de_LI
 276.628 -German (Liechtenstein)
 276.629 -windows-1252
 276.630 -
 276.631 -OS Locale (lcid: 1409): English (New Zealand) - 1252
 276.632 -en_NZ
 276.633 -English (New Zealand)
 276.634 -windows-1252
 276.635 -
 276.636 -OS Locale (lcid: 140a): Spanish (Costa Rica) - 1252
 276.637 -es_CR
 276.638 -Spanish (Costa Rica)
 276.639 -windows-1252
 276.640 -
 276.641 -OS Locale (lcid: 140c): French (Luxembourg) - 1252
 276.642 -fr_LU
 276.643 -French (Luxembourg)
 276.644 -windows-1252
 276.645 -
 276.646 -OS Locale (lcid: 141a): Bosnian (Bosnia and Herzegovina) - 1250
 276.647 -bs_BA
 276.648 -Bosnian (Bosnia and Herzegovina)
 276.649 -windows-1250
 276.650 -
 276.651 -OS Locale (lcid: 143b): Sami (Lule) (Sweden) - 1252
 276.652 -se
 276.653 -Northern Sami
 276.654 -windows-1252
 276.655 -
 276.656 -OS Locale (lcid: 1801): Arabic (Morocco) - 1256
 276.657 -ar_MA
 276.658 -Arabic (Morocco)
 276.659 -windows-1256
 276.660 -
 276.661 -OS Locale (lcid: 1809): English (Ireland) - 1252
 276.662 -en_IE
 276.663 -English (Ireland)
 276.664 -windows-1252
 276.665 -
 276.666 -OS Locale (lcid: 180a): Spanish (Panama) - 1252
 276.667 -es_PA
 276.668 -Spanish (Panama)
 276.669 -windows-1252
 276.670 -
 276.671 -OS Locale (lcid: 180c): French (Principality of Monaco) - 1252
 276.672 -fr_MC
 276.673 -French (Monaco)
 276.674 -windows-1252
 276.675 -
 276.676 -OS Locale (lcid: 181a): Serbian (Latin) (Bosnia and Herzegovina) - 1250
 276.677 -sr_BA
 276.678 -Serbian (Bosnia and Herzegovina)
 276.679 -windows-1250
 276.680 -
 276.681 -OS Locale (lcid: 183b): Sami (Southern) (Norway) - 1252
 276.682 -se
 276.683 -Northern Sami
 276.684 -windows-1252
 276.685 -
 276.686 -OS Locale (lcid: 1c01): Arabic (Tunisia) - 1256
 276.687 -ar_TN
 276.688 -Arabic (Tunisia)
 276.689 -windows-1256
 276.690 -
 276.691 -OS Locale (lcid: 1c09): English (South Africa) - 1252
 276.692 -en_ZA
 276.693 -English (South Africa)
 276.694 -windows-1252
 276.695 -
 276.696 -OS Locale (lcid: 1c0a): Spanish (Dominican Republic) - 1252
 276.697 -es_DO
 276.698 -Spanish (Dominican Republic)
 276.699 -windows-1252
 276.700 -
 276.701 -OS Locale (lcid: 1c1a): Serbian (Cyrillic) (Bosnia and Herzegovina) - 1251
 276.702 -sr_BA
 276.703 -Serbian (Bosnia and Herzegovina)
 276.704 -windows-1251
 276.705 -
 276.706 -OS Locale (lcid: 1c3b): Sami (Southern) (Sweden) - 1252
 276.707 -se
 276.708 -Northern Sami
 276.709 -windows-1252
 276.710 -
 276.711 -OS Locale (lcid: 2001): Arabic (Oman) - 1256
 276.712 -ar_OM
 276.713 -Arabic (Oman)
 276.714 -windows-1256
 276.715 -
 276.716 -OS Locale (lcid: 2009): English (Jamaica) - 1252
 276.717 -en_JM
 276.718 -English (Jamaica)
 276.719 -windows-1252
 276.720 -
 276.721 -OS Locale (lcid: 200a): Spanish (Venezuela) - 1252
 276.722 -es_VE
 276.723 -Spanish (Venezuela)
 276.724 -windows-1252
 276.725 -
 276.726 -OS Locale (lcid: 201a): Bosnian (Cyrillic) (Bosnia and Herzegovina) - 1250
 276.727 -bs_BA
 276.728 -Bosnian (Bosnia and Herzegovina)
 276.729 -windows-1250
 276.730 -
 276.731 -OS Locale (lcid: 203b): Sami (Skolt) (Finland) - 1252
 276.732 -se
 276.733 -Northern Sami
 276.734 -windows-1252
 276.735 -
 276.736 -OS Locale (lcid: 2401): Arabic (Yemen) - 1256
 276.737 -ar_YE
 276.738 -Arabic (Yemen)
 276.739 -windows-1256
 276.740 -
 276.741 -OS Locale (lcid: 2409): English (Caribbean) - 1252
 276.742 -en
 276.743 -English
 276.744 -windows-1252
 276.745 -
 276.746 -OS Locale (lcid: 240a): Spanish (Colombia) - 1252
 276.747 -es_CO
 276.748 -Spanish (Colombia)
 276.749 -windows-1252
 276.750 -
 276.751 -OS Locale (lcid: 243b): Sami (Inari) (Finland) - 1252
 276.752 -se
 276.753 -Northern Sami
 276.754 -windows-1252
 276.755 -
 276.756 -OS Locale (lcid: 2801): Arabic (Syria) - 1256
 276.757 -ar_SY
 276.758 -Arabic (Syria)
 276.759 -windows-1256
 276.760 -
 276.761 -OS Locale (lcid: 2809): English (Belize) - 1252
 276.762 -en_BZ
 276.763 -English (Belize)
 276.764 -windows-1252
 276.765 -
 276.766 -OS Locale (lcid: 280a): Spanish (Peru) - 1252
 276.767 -es_PE
 276.768 -Spanish (Peru)
 276.769 -windows-1252
 276.770 -
 276.771 -OS Locale (lcid: 2c01): Arabic (Jordan) - 1256
 276.772 -ar_JO
 276.773 -Arabic (Jordan)
 276.774 -windows-1256
 276.775 -
 276.776 -OS Locale (lcid: 2c09): English (Trinidad and Tobago) - 1252
 276.777 -en_TT
 276.778 -English (Trinidad and Tobago)
 276.779 -windows-1252
 276.780 -
 276.781 -OS Locale (lcid: 2c0a): Spanish (Argentina) - 1252
 276.782 -es_AR
 276.783 -Spanish (Argentina)
 276.784 -windows-1252
 276.785 -
 276.786 -OS Locale (lcid: 3001): Arabic (Lebanon) - 1256
 276.787 -ar_LB
 276.788 -Arabic (Lebanon)
 276.789 -windows-1256
 276.790 -
 276.791 -OS Locale (lcid: 3009): English (Zimbabwe) - 1252
 276.792 -en_ZW
 276.793 -English (Zimbabwe)
 276.794 -windows-1252
 276.795 -
 276.796 -OS Locale (lcid: 300a): Spanish (Ecuador) - 1252
 276.797 -es_EC
 276.798 -Spanish (Ecuador)
 276.799 -windows-1252
 276.800 -
 276.801 -OS Locale (lcid: 3401): Arabic (Kuwait) - 1256
 276.802 -ar_KW
 276.803 -Arabic (Kuwait)
 276.804 -windows-1256
 276.805 -
 276.806 -OS Locale (lcid: 3409): English (Republic of the Philippines) - 1252
 276.807 -en_PH
 276.808 -English (Philippines)
 276.809 -windows-1252
 276.810 -
 276.811 -OS Locale (lcid: 340a): Spanish (Chile) - 1252
 276.812 -es_CL
 276.813 -Spanish (Chile)
 276.814 -windows-1252
 276.815 -
 276.816 -OS Locale (lcid: 3801): Arabic (U.A.E.) - 1256
 276.817 -ar_AE
 276.818 -Arabic (United Arab Emirates)
 276.819 -windows-1256
 276.820 -
 276.821 -OS Locale (lcid: 380a): Spanish (Uruguay) - 1252
 276.822 -es_UY
 276.823 -Spanish (Uruguay)
 276.824 -windows-1252
 276.825 -
 276.826 -OS Locale (lcid: 3c01): Arabic (Bahrain) - 1256
 276.827 -ar_BH
 276.828 -Arabic (Bahrain)
 276.829 -windows-1256
 276.830 -
 276.831 -OS Locale (lcid: 3c0a): Spanish (Paraguay) - 1252
 276.832 -es_PY
 276.833 -Spanish (Paraguay)
 276.834 -windows-1252
 276.835 -
 276.836 -OS Locale (lcid: 4001): Arabic (Qatar) - 1256
 276.837 -ar_QA
 276.838 -Arabic (Qatar)
 276.839 -windows-1256
 276.840 -
 276.841 -OS Locale (lcid: 400a): Spanish (Bolivia) - 1252
 276.842 -es_BO
 276.843 -Spanish (Bolivia)
 276.844 -windows-1252
 276.845 -
 276.846 -OS Locale (lcid: 440a): Spanish (El Salvador) - 1252
 276.847 -es_SV
 276.848 -Spanish (El Salvador)
 276.849 -windows-1252
 276.850 -
 276.851 -OS Locale (lcid: 480a): Spanish (Honduras) - 1252
 276.852 -es_HN
 276.853 -Spanish (Honduras)
 276.854 -windows-1252
 276.855 -
 276.856 -OS Locale (lcid: 4c0a): Spanish (Nicaragua) - 1252
 276.857 -es_NI
 276.858 -Spanish (Nicaragua)
 276.859 -windows-1252
 276.860 -
 276.861 -OS Locale (lcid: 500a): Spanish (Puerto Rico) - 1252
 276.862 -es_PR
 276.863 -Spanish (Puerto Rico)
 276.864 -windows-1252
   277.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   277.2 +++ b/test/java/util/Locale/icuLocales.txt	Fri Sep 24 16:41:32 2010 -0700
   277.3 @@ -0,0 +1,292 @@
   277.4 +af
   277.5 +af-NA
   277.6 +af-ZA
   277.7 +am
   277.8 +am-ET
   277.9 +ar
  277.10 +ar-AE
  277.11 +ar-BH
  277.12 +ar-DZ
  277.13 +ar-EG
  277.14 +ar-IQ
  277.15 +ar-JO
  277.16 +ar-KW
  277.17 +ar-LB
  277.18 +ar-LY
  277.19 +ar-MA
  277.20 +ar-OM
  277.21 +ar-QA
  277.22 +ar-SA
  277.23 +ar-SD
  277.24 +ar-SY
  277.25 +ar-TN
  277.26 +ar-YE
  277.27 +as
  277.28 +as-IN
  277.29 +az
  277.30 +az-Cyrl
  277.31 +az-Cyrl-AZ
  277.32 +az-Latn
  277.33 +az-Latn-AZ
  277.34 +be
  277.35 +be-BY
  277.36 +bg
  277.37 +bg-BG
  277.38 +bn
  277.39 +bn-BD
  277.40 +bn-IN
  277.41 +bo
  277.42 +bo-CN
  277.43 +bo-IN
  277.44 +ca
  277.45 +ca-ES
  277.46 +cs
  277.47 +cs-CZ
  277.48 +cy
  277.49 +cy-GB
  277.50 +da
  277.51 +da-DK
  277.52 +de
  277.53 +de-AT
  277.54 +de-BE
  277.55 +de-CH
  277.56 +de-DE
  277.57 +de-LI
  277.58 +de-LU
  277.59 +el
  277.60 +el-CY
  277.61 +el-GR
  277.62 +en
  277.63 +en-AU
  277.64 +en-BE
  277.65 +en-BW
  277.66 +en-BZ
  277.67 +en-CA
  277.68 +en-GB
  277.69 +en-HK
  277.70 +en-IE
  277.71 +en-IN
  277.72 +en-JM
  277.73 +en-MH
  277.74 +en-MT
  277.75 +en-NA
  277.76 +en-NZ
  277.77 +en-PH
  277.78 +en-PK
  277.79 +en-SG
  277.80 +en-TT
  277.81 +en-US
  277.82 +en-US-posix
  277.83 +en-VI
  277.84 +en-ZA
  277.85 +en-ZW
  277.86 +eo
  277.87 +es
  277.88 +es-AR
  277.89 +es-BO
  277.90 +es-CL
  277.91 +es-CO
  277.92 +es-CR
  277.93 +es-DO
  277.94 +es-EC
  277.95 +es-ES
  277.96 +es-GT
  277.97 +es-HN
  277.98 +es-MX
  277.99 +es-NI
 277.100 +es-PA
 277.101 +es-PE
 277.102 +es-PR
 277.103 +es-PY
 277.104 +es-SV
 277.105 +es-US
 277.106 +es-UY
 277.107 +es-VE
 277.108 +et
 277.109 +et-EE
 277.110 +eu
 277.111 +eu-ES
 277.112 +fa
 277.113 +fa-AF
 277.114 +fa-IR
 277.115 +fi
 277.116 +fi-FI
 277.117 +fo
 277.118 +fo-FO
 277.119 +fr
 277.120 +fr-BE
 277.121 +fr-CA
 277.122 +fr-CH
 277.123 +fr-FR
 277.124 +fr-LU
 277.125 +fr-MC
 277.126 +fr-SN
 277.127 +ga
 277.128 +ga-IE
 277.129 +gl
 277.130 +gl-ES
 277.131 +gsw
 277.132 +gsw-CH
 277.133 +gu
 277.134 +gu-IN
 277.135 +gv
 277.136 +gv-GB
 277.137 +ha
 277.138 +ha-Latn
 277.139 +ha-Latn-GH
 277.140 +ha-Latn-NE
 277.141 +ha-Latn-NG
 277.142 +haw
 277.143 +haw-US
 277.144 +he
 277.145 +he-IL
 277.146 +hi
 277.147 +hi-IN
 277.148 +hr
 277.149 +hr-HR
 277.150 +hu
 277.151 +hu-HU
 277.152 +hy
 277.153 +hy-AM
 277.154 +hy-AM-revised
 277.155 +id
 277.156 +id-ID
 277.157 +ii
 277.158 +ii-CN
 277.159 +is
 277.160 +is-IS
 277.161 +it
 277.162 +it-CH
 277.163 +it-IT
 277.164 +ja
 277.165 +ja-JP
 277.166 +ka
 277.167 +ka-GE
 277.168 +kk
 277.169 +kk-Cyrl
 277.170 +kk-Cyrl-KZ
 277.171 +kl
 277.172 +kl-GL
 277.173 +km
 277.174 +km-KH
 277.175 +kn
 277.176 +kn-IN
 277.177 +ko
 277.178 +ko-KR
 277.179 +kok
 277.180 +kok-IN
 277.181 +kw
 277.182 +kw-GB
 277.183 +lt
 277.184 +lt-LT
 277.185 +lv
 277.186 +lv-LV
 277.187 +mk
 277.188 +mk-MK
 277.189 +ml
 277.190 +ml-IN
 277.191 +mr
 277.192 +mr-IN
 277.193 +ms
 277.194 +ms-BN
 277.195 +ms-MY
 277.196 +mt
 277.197 +mt-MT
 277.198 +nb
 277.199 +nb-NO
 277.200 +ne
 277.201 +ne-IN
 277.202 +ne-NP
 277.203 +nl
 277.204 +nl-BE
 277.205 +nl-NL
 277.206 +nn
 277.207 +nn-NO
 277.208 +om
 277.209 +om-ET
 277.210 +om-KE
 277.211 +or
 277.212 +or-IN
 277.213 +pa
 277.214 +pa-Arab
 277.215 +pa-Arab-PK
 277.216 +pa-Guru
 277.217 +pa-Guru-IN
 277.218 +pl
 277.219 +pl-PL
 277.220 +ps
 277.221 +ps-AF
 277.222 +pt
 277.223 +pt-BR
 277.224 +pt-PT
 277.225 +ro
 277.226 +ro-MD
 277.227 +ro-RO
 277.228 +ru
 277.229 +ru-RU
 277.230 +ru-UA
 277.231 +si
 277.232 +si-LK
 277.233 +sk
 277.234 +sk-SK
 277.235 +sl
 277.236 +sl-SI
 277.237 +so
 277.238 +so-DJ
 277.239 +so-ET
 277.240 +so-KE
 277.241 +so-SO
 277.242 +sq
 277.243 +sq-AL
 277.244 +sr
 277.245 +sr-Cyrl
 277.246 +sr-Cyrl-BA
 277.247 +sr-Cyrl-ME
 277.248 +sr-Cyrl-RS
 277.249 +sr-Latn
 277.250 +sr-Latn-BA
 277.251 +sr-Latn-ME
 277.252 +sr-Latn-RS
 277.253 +sv
 277.254 +sv-FI
 277.255 +sv-SE
 277.256 +sw
 277.257 +sw-KE
 277.258 +sw-TZ
 277.259 +ta
 277.260 +ta-IN
 277.261 +te
 277.262 +te-IN
 277.263 +th
 277.264 +th-TH
 277.265 +ti
 277.266 +ti-ER
 277.267 +ti-ET
 277.268 +tr
 277.269 +tr-TR
 277.270 +uk
 277.271 +uk-UA
 277.272 +ur
 277.273 +ur-IN
 277.274 +ur-PK
 277.275 +uz
 277.276 +uz-Arab
 277.277 +uz-Arab-AF
 277.278 +uz-Cyrl
 277.279 +uz-Cyrl-UZ
 277.280 +uz-Latn
 277.281 +uz-Latn-UZ
 277.282 +vi
 277.283 +vi-VN
 277.284 +zh
 277.285 +zh-Hans
 277.286 +zh-Hans-CN
 277.287 +zh-Hans-HK
 277.288 +zh-Hans-MO
 277.289 +zh-Hans-SG
 277.290 +zh-Hant
 277.291 +zh-Hant-HK
 277.292 +zh-Hant-MO
 277.293 +zh-Hant-TW
 277.294 +zu
 277.295 +zu-ZA
   278.1 Binary file test/java/util/Locale/serialized/java6locale_ROOT has changed
   279.1 Binary file test/java/util/Locale/serialized/java6locale__US has changed
   280.1 Binary file test/java/util/Locale/serialized/java6locale___Java has changed
   281.1 Binary file test/java/util/Locale/serialized/java6locale_en has changed
   282.1 Binary file test/java/util/Locale/serialized/java6locale_en_US has changed
   283.1 Binary file test/java/util/Locale/serialized/java6locale_en_US_Java has changed
   284.1 Binary file test/java/util/Locale/serialized/java6locale_iw_IL has changed
   285.1 Binary file test/java/util/Locale/serialized/java6locale_ja_JP_JP has changed
   286.1 Binary file test/java/util/Locale/serialized/java6locale_no_NO_NY has changed
   287.1 Binary file test/java/util/Locale/serialized/java6locale_th_TH_TH has changed
   288.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   288.2 +++ b/test/java/util/TimeZone/Bug6912560.java	Fri Sep 24 16:41:32 2010 -0700
   288.3 @@ -0,0 +1,51 @@
   288.4 +/*
   288.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   288.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   288.7 + *
   288.8 + * This code is free software; you can redistribute it and/or modify it
   288.9 + * under the terms of the GNU General Public License version 2 only, as
  288.10 + * published by the Free Software Foundation.  Oracle designates this
  288.11 + * particular file as subject to the "Classpath" exception as provided
  288.12 + * by Oracle in the LICENSE file that accompanied this code.
  288.13 + *
  288.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  288.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  288.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  288.17 + * version 2 for more details (a copy is included in the LICENSE file that
  288.18 + * accompanied this code).
  288.19 + *
  288.20 + * You should have received a copy of the GNU General Public License version
  288.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  288.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  288.23 + *
  288.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  288.25 + * or visit www.oracle.com if you need additional information or have any
  288.26 + * questions.
  288.27 + */
  288.28 +
  288.29 +/*
  288.30 + * @test
  288.31 + * @bug 6912560
  288.32 + * @run main/othervm Bug6912560
  288.33 + * @summary Make sure that file path canonicalization in
  288.34 + * sun.util.calendar.ZoneInfoFile works with the default security
  288.35 + * manager.
  288.36 + */
  288.37 +
  288.38 +import java.io.File;
  288.39 +import java.util.*;
  288.40 +
  288.41 +public class Bug6912560 {
  288.42 +    public static void main(String[] args) {
  288.43 +        // set the user.timezone property
  288.44 +        String tzname = "Asia/Tokyo";
  288.45 +        System.setProperty("user.timezone", tzname);
  288.46 +
  288.47 +        System.setSecurityManager(new SecurityManager());
  288.48 +        TimeZone tz = TimeZone.getDefault();
  288.49 +        if (!tzname.equals(tz.getID())) {
  288.50 +            throw new RuntimeException("got " + tz.getID()
  288.51 +                                       + ", expected " + tzname);
  288.52 +        }
  288.53 +    }
  288.54 +}
   289.1 --- a/test/java/util/concurrent/forkjoin/Integrate.java	Thu Sep 23 17:33:40 2010 -0700
   289.2 +++ b/test/java/util/concurrent/forkjoin/Integrate.java	Fri Sep 24 16:41:32 2010 -0700
   289.3 @@ -206,7 +206,7 @@
   289.4              q.fork();
   289.5              ar = recEval(c, r, fc, fr, ar);
   289.6              if (!q.tryUnfork()) {
   289.7 -                q.quietlyHelpJoin();
   289.8 +                q.quietlyJoin();
   289.9                  return ar + q.area;
  289.10              }
  289.11              return ar + recEval(l, c, fl, fc, al);
  289.12 @@ -254,7 +254,7 @@
  289.13                  (q = new DQuad(l, c, al)).fork();
  289.14              ar = recEval(c, r, fc, fr, ar);
  289.15              if (q != null && !q.tryUnfork()) {
  289.16 -                q.quietlyHelpJoin();
  289.17 +                q.quietlyJoin();
  289.18                  return ar + q.area;
  289.19              }
  289.20              return ar + recEval(l, c, fl, fc, al);
   290.1 --- a/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java	Thu Sep 23 17:33:40 2010 -0700
   290.2 +++ b/test/javax/imageio/CachePremissionsTest/CachePermissionsTest.java	Fri Sep 24 16:41:32 2010 -0700
   290.3 @@ -50,9 +50,9 @@
   290.4   *           -Djava.security.debug=access can be used to verify file permissions.
   290.5   *
   290.6   * @run     main CachePermissionsTest true
   290.7 - * @run     main/othervm/policy=w.policy CachePermissionsTest false
   290.8 - * @run     main/othervm/policy=rw.policy CachePermissionsTest false
   290.9 - * @run     main/othervm/policy=rwd.policy CachePermissionsTest true
  290.10 + * @run     main/othervm CachePermissionsTest false w.policy
  290.11 + * @run     main/othervm CachePermissionsTest false rw.policy
  290.12 + * @run     main/othervm CachePermissionsTest true rwd.policy
  290.13   */
  290.14  
  290.15  import java.io.File;
  290.16 @@ -73,6 +73,17 @@
  290.17  
  290.18          System.out.println("java.io.tmpdir is " + System.getProperty("java.io.tmpdir"));
  290.19  
  290.20 +        if (args.length > 1) {
  290.21 +            String testsrc = System.getProperty("test.src", ".");
  290.22 +            String policy = testsrc + File.separator + args[1];
  290.23 +
  290.24 +            System.out.println("Policy file: " + policy);
  290.25 +            System.setProperty("java.security.policy", policy);
  290.26 +
  290.27 +            System.out.println("Install security manager...");
  290.28 +            System.setSecurityManager(new SecurityManager());
  290.29 +        }
  290.30 +
  290.31          ByteArrayOutputStream baos = new ByteArrayOutputStream();
  290.32  
  290.33          try {
   291.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   291.2 +++ b/test/javax/sound/midi/Gervill/AudioFloatFormatConverter/SkipTest.java	Fri Sep 24 16:41:32 2010 -0700
   291.3 @@ -0,0 +1,63 @@
   291.4 +/*
   291.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   291.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   291.7 + *
   291.8 + * This code is free software; you can redistribute it and/or modify it
   291.9 + * under the terms of the GNU General Public License version 2 only, as
  291.10 + * published by the Free Software Foundation.  Oracle designates this
  291.11 + * particular file as subject to the "Classpath" exception as provided
  291.12 + * by Oracle in the LICENSE file that accompanied this code.
  291.13 + *
  291.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  291.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  291.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  291.17 + * version 2 for more details (a copy is included in the LICENSE file that
  291.18 + * accompanied this code).
  291.19 + *
  291.20 + * You should have received a copy of the GNU General Public License version
  291.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  291.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  291.23 + *
  291.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  291.25 + * or visit www.oracle.com if you need additional information or have any
  291.26 + * questions.
  291.27 + */
  291.28 +
  291.29 +/* @test
  291.30 + @summary Test skip method returned from AudioFloatFormatConverter.getAudioInputStream */
  291.31 +
  291.32 +import java.io.ByteArrayInputStream;
  291.33 +
  291.34 +import javax.sound.sampled.AudioFormat;
  291.35 +import javax.sound.sampled.AudioInputStream;
  291.36 +
  291.37 +import com.sun.media.sound.AudioFloatFormatConverter;
  291.38 +
  291.39 +public class SkipTest {
  291.40 +
  291.41 +    public static void main(String[] args) throws Exception {
  291.42 +        AudioFloatFormatConverter converter = new AudioFloatFormatConverter();
  291.43 +        byte[] data = { 10, 20, 30, 40, 30, 20, 10 };
  291.44 +        AudioFormat format = new AudioFormat(8000, 8, 1, true, false);
  291.45 +        AudioFormat format2 = new AudioFormat(16000, 8, 1, true, false);
  291.46 +        AudioInputStream ais = new AudioInputStream(new ByteArrayInputStream(
  291.47 +                data), format, data.length);
  291.48 +        AudioInputStream ais2 = converter.getAudioInputStream(format2, ais);
  291.49 +        byte[] data2 = new byte[30];
  291.50 +        int ret = ais2.read(data2, 0, data2.length);
  291.51 +        ais.reset();
  291.52 +        AudioInputStream ais3 = converter.getAudioInputStream(format2, ais);
  291.53 +        byte[] data3 = new byte[100];
  291.54 +        ais3.skip(7);
  291.55 +        int ret2 = ais3.read(data3, 7, data3.length);
  291.56 +        if (ret2 != ret - 7)
  291.57 +            throw new Exception("Skip doesn't work correctly (" + ret2 + " != "
  291.58 +                    + (ret - 7) + ")");
  291.59 +        for (int i = 7; i < ret2 + 7; i++) {
  291.60 +            if (data3[i] != data2[i])
  291.61 +                throw new Exception("Skip doesn't work correctly (" + data3[i]
  291.62 +                        + " != " + data2[i] + ")");
  291.63 +        }
  291.64 +    }
  291.65 +
  291.66 +}
   292.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   292.2 +++ b/test/javax/sound/midi/Gervill/ModelByteBufferWavetable/OpenStream.java	Fri Sep 24 16:41:32 2010 -0700
   292.3 @@ -0,0 +1,142 @@
   292.4 +/*
   292.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   292.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   292.7 + *
   292.8 + * This code is free software; you can redistribute it and/or modify it
   292.9 + * under the terms of the GNU General Public License version 2 only, as
  292.10 + * published by the Free Software Foundation.  Oracle designates this
  292.11 + * particular file as subject to the "Classpath" exception as provided
  292.12 + * by Oracle in the LICENSE file that accompanied this code.
  292.13 + *
  292.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  292.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  292.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  292.17 + * version 2 for more details (a copy is included in the LICENSE file that
  292.18 + * accompanied this code).
  292.19 + *
  292.20 + * You should have received a copy of the GNU General Public License version
  292.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  292.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  292.23 + *
  292.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  292.25 + * or visit www.oracle.com if you need additional information or have any
  292.26 + * questions.
  292.27 + */
  292.28 +
  292.29 +/* @test
  292.30 + @summary Test AudioFloatInputStream.getFrameLength() returned from
  292.31 + ModelByteBufferWavetable openStream method */
  292.32 +
  292.33 +import java.io.ByteArrayOutputStream;
  292.34 +import java.io.File;
  292.35 +import java.io.FileOutputStream;
  292.36 +
  292.37 +import javax.sound.sampled.*;
  292.38 +
  292.39 +import com.sun.media.sound.*;
  292.40 +
  292.41 +public class OpenStream {
  292.42 +
  292.43 +    static float[] testarray;
  292.44 +
  292.45 +    static byte[] test_byte_array;
  292.46 +
  292.47 +    static byte[] test_byte_array_8ext;
  292.48 +
  292.49 +    static AudioFormat format = new AudioFormat(44100, 16, 1, true, false);
  292.50 +
  292.51 +    static AudioFormat format24 = new AudioFormat(44100, 24, 1, true, false);
  292.52 +
  292.53 +    static ModelByteBuffer buffer;
  292.54 +
  292.55 +    static ModelByteBuffer buffer_wave;
  292.56 +
  292.57 +    static ModelByteBuffer buffer8;
  292.58 +
  292.59 +    static ModelByteBuffer buffer16_8;
  292.60 +
  292.61 +    static ModelByteBuffer buffer24;
  292.62 +
  292.63 +    static File test_file;
  292.64 +
  292.65 +    static ModelByteBuffer buffer_wave_ondisk;
  292.66 +
  292.67 +    static void setUp() throws Exception {
  292.68 +        testarray = new float[1024];
  292.69 +        for (int i = 0; i < 1024; i++) {
  292.70 +            double ii = i / 1024.0;
  292.71 +            ii = ii * ii;
  292.72 +            testarray[i] = (float) Math.sin(10 * ii * 2 * Math.PI);
  292.73 +            testarray[i] += (float) Math.sin(1.731 + 2 * ii * 2 * Math.PI);
  292.74 +            testarray[i] += (float) Math.sin(0.231 + 6.3 * ii * 2 * Math.PI);
  292.75 +            testarray[i] *= 0.3;
  292.76 +        }
  292.77 +        test_byte_array = new byte[testarray.length * 2];
  292.78 +        AudioFloatConverter.getConverter(format).toByteArray(testarray,
  292.79 +                test_byte_array);
  292.80 +        buffer = new ModelByteBuffer(test_byte_array);
  292.81 +
  292.82 +        byte[] test_byte_array2 = new byte[testarray.length * 3];
  292.83 +        buffer24 = new ModelByteBuffer(test_byte_array2);
  292.84 +        test_byte_array_8ext = new byte[testarray.length];
  292.85 +        byte[] test_byte_array_8_16 = new byte[testarray.length * 2];
  292.86 +        AudioFloatConverter.getConverter(format24).toByteArray(testarray,
  292.87 +                test_byte_array2);
  292.88 +        int ix = 0;
  292.89 +        int x = 0;
  292.90 +        for (int i = 0; i < test_byte_array_8ext.length; i++) {
  292.91 +            test_byte_array_8ext[i] = test_byte_array2[ix++];
  292.92 +            test_byte_array_8_16[x++] = test_byte_array2[ix++];
  292.93 +            test_byte_array_8_16[x++] = test_byte_array2[ix++];
  292.94 +        }
  292.95 +        buffer16_8 = new ModelByteBuffer(test_byte_array_8_16);
  292.96 +        buffer8 = new ModelByteBuffer(test_byte_array_8ext);
  292.97 +
  292.98 +        AudioInputStream ais = new AudioInputStream(buffer.getInputStream(),
  292.99 +                format, testarray.length);
 292.100 +        ByteArrayOutputStream baos = new ByteArrayOutputStream();
 292.101 +        AudioSystem.write(ais, AudioFileFormat.Type.WAVE, baos);
 292.102 +        buffer_wave = new ModelByteBuffer(baos.toByteArray());
 292.103 +
 292.104 +        test_file = File.createTempFile("test", ".raw");
 292.105 +        FileOutputStream fos = new FileOutputStream(test_file);
 292.106 +        fos.write(baos.toByteArray());
 292.107 +        fos.close();
 292.108 +        buffer_wave_ondisk = new ModelByteBuffer(test_file);
 292.109 +
 292.110 +    }
 292.111 +
 292.112 +    static void tearDown() throws Exception {
 292.113 +        if (!test_file.delete())
 292.114 +            test_file.deleteOnExit();
 292.115 +    }
 292.116 +
 292.117 +    public static void testOpenStream(ModelByteBufferWavetable wavetable)
 292.118 +            throws Exception {
 292.119 +        AudioFloatInputStream ais = wavetable.openStream();
 292.120 +        long frames = wavetable.getBuffer().capacity()
 292.121 +                / wavetable.getFormat().getFrameSize();
 292.122 +        long framelength = ais.getFrameLength();
 292.123 +        ais.close();
 292.124 +        if (frames != framelength) {
 292.125 +            throw new Exception("Incorrect framelength returned (" + frames
 292.126 +                    + " != " + framelength + ")");
 292.127 +        }
 292.128 +    }
 292.129 +
 292.130 +    public static void main(String[] args) throws Exception {
 292.131 +
 292.132 +        setUp();
 292.133 +
 292.134 +        try {
 292.135 +            testOpenStream(new ModelByteBufferWavetable(buffer, format));
 292.136 +            testOpenStream(new ModelByteBufferWavetable(buffer_wave, format));
 292.137 +            testOpenStream(new ModelByteBufferWavetable(buffer_wave_ondisk,
 292.138 +                    format));
 292.139 +        } finally {
 292.140 +            tearDown();
 292.141 +        }
 292.142 +
 292.143 +    }
 292.144 +
 292.145 +}
   293.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   293.2 +++ b/test/javax/sound/midi/Gervill/ModelStandardIndexedDirector/ModelStandardIndexedDirectorTest.java	Fri Sep 24 16:41:32 2010 -0700
   293.3 @@ -0,0 +1,188 @@
   293.4 +/*
   293.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   293.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   293.7 + *
   293.8 + * This code is free software; you can redistribute it and/or modify it
   293.9 + * under the terms of the GNU General Public License version 2 only, as
  293.10 + * published by the Free Software Foundation.  Oracle designates this
  293.11 + * particular file as subject to the "Classpath" exception as provided
  293.12 + * by Oracle in the LICENSE file that accompanied this code.
  293.13 + *
  293.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  293.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  293.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  293.17 + * version 2 for more details (a copy is included in the LICENSE file that
  293.18 + * accompanied this code).
  293.19 + *
  293.20 + * You should have received a copy of the GNU General Public License version
  293.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  293.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  293.23 + *
  293.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  293.25 + * or visit www.oracle.com if you need additional information or have any
  293.26 + * questions.
  293.27 + */
  293.28 +
  293.29 +/* @test
  293.30 +   @summary Test ModelStandardIndexedDirector class */
  293.31 +
  293.32 +import java.util.ArrayList;
  293.33 +import java.util.List;
  293.34 +import java.util.TreeSet;
  293.35 +
  293.36 +import com.sun.media.sound.ModelConnectionBlock;
  293.37 +import com.sun.media.sound.ModelDirectedPlayer;
  293.38 +import com.sun.media.sound.ModelPerformer;
  293.39 +import com.sun.media.sound.ModelStandardDirector;
  293.40 +import com.sun.media.sound.ModelStandardIndexedDirector;
  293.41 +
  293.42 +public class ModelStandardIndexedDirectorTest {
  293.43 +
  293.44 +    private static String treeToString(TreeSet<Integer> set)
  293.45 +    {
  293.46 +        StringBuffer buff = new StringBuffer();
  293.47 +        boolean first = true;
  293.48 +        for(Integer s : set)
  293.49 +        {
  293.50 +            if(!first)
  293.51 +                buff.append(";");
  293.52 +            buff.append(s);
  293.53 +            first = false;
  293.54 +        }
  293.55 +        return buff.toString();
  293.56 +    }
  293.57 +
  293.58 +    private static void testDirector(ModelPerformer[] performers) throws Exception
  293.59 +    {
  293.60 +        final TreeSet<Integer> played = new TreeSet<Integer>();
  293.61 +        ModelDirectedPlayer player = new ModelDirectedPlayer()
  293.62 +        {
  293.63 +            public void play(int performerIndex,
  293.64 +                    ModelConnectionBlock[] connectionBlocks) {
  293.65 +                played.add(performerIndex);
  293.66 +            }
  293.67 +        };
  293.68 +        ModelStandardIndexedDirector idirector =
  293.69 +            new ModelStandardIndexedDirector(performers, player);
  293.70 +        ModelStandardDirector director =
  293.71 +            new ModelStandardDirector(performers, player);
  293.72 +
  293.73 +        for (int n = 0; n < 128; n++)
  293.74 +        {
  293.75 +            for (int v = 0; v < 128; v++)
  293.76 +            {
  293.77 +                director.noteOn(n, v);
  293.78 +                String p1 = treeToString(played);
  293.79 +                played.clear();
  293.80 +                idirector.noteOn(n, v);
  293.81 +                String p2 = treeToString(played);
  293.82 +                played.clear();
  293.83 +                if(!p1.equals(p2))
  293.84 +                    throw new Exception(
  293.85 +                            "Note = " + n + ", Vel = " + v + " failed");
  293.86 +            }
  293.87 +        }
  293.88 +    }
  293.89 +
  293.90 +    private static void testDirectorCombinations(
  293.91 +            ModelPerformer[] performers) throws Exception
  293.92 +    {
  293.93 +        for (int i = 0; i < performers.length; i++) {
  293.94 +            ModelPerformer[] performers2 = new ModelPerformer[i];
  293.95 +            for (int j = 0; j < performers2.length; j++) {
  293.96 +                performers2[j] = performers[i];
  293.97 +            }
  293.98 +            testDirector(performers2);
  293.99 +        }
 293.100 +    }
 293.101 +
 293.102 +    private static void addPerformer(
 293.103 +            List<ModelPerformer> performers,
 293.104 +            int keyfrom,
 293.105 +            int keyto,
 293.106 +            int velfrom,
 293.107 +            int velto)
 293.108 +    {
 293.109 +        ModelPerformer performer = new ModelPerformer();
 293.110 +        performer.setKeyFrom(keyfrom);
 293.111 +        performer.setKeyTo(keyto);
 293.112 +        performer.setVelFrom(velfrom);
 293.113 +        performer.setVelTo(velto);
 293.114 +        performers.add(performer);
 293.115 +    }
 293.116 +
 293.117 +    public static void main(String[] args) throws Exception
 293.118 +    {
 293.119 +        // Test collection of normal values
 293.120 +        List<ModelPerformer> performers = new ArrayList<ModelPerformer>();
 293.121 +        addPerformer(performers, 0, 0, 0, 127);
 293.122 +        addPerformer(performers, 0, 50, 0, 127);
 293.123 +        addPerformer(performers, 0, 127, 0, 127);
 293.124 +        addPerformer(performers, 21, 21, 0, 127);
 293.125 +        addPerformer(performers, 21, 60, 0, 127);
 293.126 +        addPerformer(performers, 21, 127, 0, 127);
 293.127 +        addPerformer(performers, 50, 50, 0, 127);
 293.128 +        addPerformer(performers, 50, 60, 0, 127);
 293.129 +        addPerformer(performers, 50, 127, 0, 127);
 293.130 +        addPerformer(performers, 73, 73, 0, 127);
 293.131 +        addPerformer(performers, 73, 80, 0, 127);
 293.132 +        addPerformer(performers, 73, 127, 0, 127);
 293.133 +        addPerformer(performers, 127, 127, 0, 127);
 293.134 +        addPerformer(performers, 0, 0, 60, 127);
 293.135 +        addPerformer(performers, 0, 50, 60, 127);
 293.136 +        addPerformer(performers, 0, 127, 60, 127);
 293.137 +        addPerformer(performers, 21, 21, 60, 127);
 293.138 +        addPerformer(performers, 21, 60, 60, 127);
 293.139 +        addPerformer(performers, 21, 127, 60, 127);
 293.140 +        addPerformer(performers, 50, 50, 60, 127);
 293.141 +        addPerformer(performers, 50, 60, 60, 127);
 293.142 +        addPerformer(performers, 50, 127, 60, 127);
 293.143 +        addPerformer(performers, 73, 73, 60, 127);
 293.144 +        addPerformer(performers, 73, 80, 60, 127);
 293.145 +        addPerformer(performers, 73, 127, 60, 127);
 293.146 +        addPerformer(performers, 127, 127, 60, 127);
 293.147 +        addPerformer(performers, 0, 0, 80, 83);
 293.148 +        addPerformer(performers, 0, 50, 80, 83);
 293.149 +        addPerformer(performers, 0, 127, 80, 83);
 293.150 +        addPerformer(performers, 21, 21, 80, 83);
 293.151 +        addPerformer(performers, 21, 60, 80, 83);
 293.152 +        addPerformer(performers, 21, 127, 80, 83);
 293.153 +        addPerformer(performers, 50, 50, 80, 83);
 293.154 +        addPerformer(performers, 50, 60, 80, 83);
 293.155 +        addPerformer(performers, 50, 127, 80, 83);
 293.156 +        addPerformer(performers, 73, 73, 80, 83);
 293.157 +        addPerformer(performers, 73, 80, 80, 83);
 293.158 +        addPerformer(performers, 73, 127, 80, 83);
 293.159 +        addPerformer(performers, 127, 127, 80, 83);
 293.160 +
 293.161 +
 293.162 +        testDirectorCombinations(
 293.163 +                performers.toArray(
 293.164 +                        new ModelPerformer[performers.size()])
 293.165 +                );
 293.166 +
 293.167 +        // Test reversed values
 293.168 +        performers.clear();
 293.169 +        addPerformer(performers, 50, 30, 80, 83);
 293.170 +        addPerformer(performers, 30, 30, 50, 30);
 293.171 +        addPerformer(performers, 37, 30, 50, 30);
 293.172 +        testDirector(
 293.173 +                performers.toArray(
 293.174 +                        new ModelPerformer[performers.size()])
 293.175 +                );
 293.176 +
 293.177 +        // Test out-of-range values
 293.178 +        performers.clear();
 293.179 +        addPerformer(performers, -20, 6, 0, 127);
 293.180 +        addPerformer(performers, 0, 300, 0, 300);
 293.181 +        addPerformer(performers, -2, -8, -5, -9);
 293.182 +
 293.183 +        testDirector(
 293.184 +                performers.toArray(
 293.185 +                        new ModelPerformer[performers.size()])
 293.186 +                );
 293.187 +
 293.188 +    }
 293.189 +}
 293.190 +
 293.191 +
   294.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   294.2 +++ b/test/javax/sound/midi/Gervill/SoftChannel/ProgramAndBankChange.java	Fri Sep 24 16:41:32 2010 -0700
   294.3 @@ -0,0 +1,158 @@
   294.4 +/*
   294.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   294.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   294.7 + *
   294.8 + * This code is free software; you can redistribute it and/or modify it
   294.9 + * under the terms of the GNU General Public License version 2 only, as
  294.10 + * published by the Free Software Foundation.  Oracle designates this
  294.11 + * particular file as subject to the "Classpath" exception as provided
  294.12 + * by Oracle in the LICENSE file that accompanied this code.
  294.13 + *
  294.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  294.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  294.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  294.17 + * version 2 for more details (a copy is included in the LICENSE file that
  294.18 + * accompanied this code).
  294.19 + *
  294.20 + * You should have received a copy of the GNU General Public License version
  294.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  294.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  294.23 + *
  294.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  294.25 + * or visit www.oracle.com if you need additional information or have any
  294.26 + * questions.
  294.27 + */
  294.28 +
  294.29 +/* @test
  294.30 +   @summary Test SoftChannel program and bank change */
  294.31 +
  294.32 +import java.io.IOException;
  294.33 +
  294.34 +import javax.sound.midi.*;
  294.35 +import javax.sound.sampled.*;
  294.36 +
  294.37 +import com.sun.media.sound.*;
  294.38 +
  294.39 +public class ProgramAndBankChange {
  294.40 +
  294.41 +    private static SimpleInstrument generateTestInstrument(Patch patch) {
  294.42 +        ModelOscillator osc = new ModelOscillator() {
  294.43 +            public float getAttenuation() {
  294.44 +                return 0;
  294.45 +            }
  294.46 +
  294.47 +            public int getChannels() {
  294.48 +                return 1;
  294.49 +            }
  294.50 +
  294.51 +            public ModelOscillatorStream open(float samplerate) {
  294.52 +                return new ModelOscillatorStream() {
  294.53 +                    public void close() throws IOException {
  294.54 +                    }
  294.55 +
  294.56 +                    public void noteOff(int velocity) {
  294.57 +                    }
  294.58 +
  294.59 +                    public void noteOn(MidiChannel channel, VoiceStatus voice,
  294.60 +                            int noteNumber, int velocity) {
  294.61 +                    }
  294.62 +
  294.63 +                    public int read(float[][] buffer, int offset, int len)
  294.64 +                            throws IOException {
  294.65 +                        return len;
  294.66 +                    }
  294.67 +
  294.68 +                    public void setPitch(float ipitch) {
  294.69 +                    }
  294.70 +                };
  294.71 +            }
  294.72 +        };
  294.73 +        ModelPerformer performer = new ModelPerformer();
  294.74 +        performer.getOscillators().add(osc);
  294.75 +        SimpleInstrument testinstrument = new SimpleInstrument();
  294.76 +        testinstrument.setPatch(patch);
  294.77 +        testinstrument.add(performer);
  294.78 +        return testinstrument;
  294.79 +    }
  294.80 +
  294.81 +    private static void assertTrue(boolean value) throws Exception {
  294.82 +        if (!value)
  294.83 +            throw new RuntimeException("assertTrue fails!");
  294.84 +    }
  294.85 +
  294.86 +    private static void testProgramAndBank(SoftSynthesizer soft,
  294.87 +            AudioInputStream stream, Patch patch) throws Exception {
  294.88 +
  294.89 +        int program = patch.getProgram();
  294.90 +        int bank = patch.getBank();
  294.91 +
  294.92 +        MidiChannel channel = soft.getChannels()[0];
  294.93 +        byte[] buff = new byte[2048];
  294.94 +
  294.95 +        channel.programChange(bank, program);
  294.96 +        channel.noteOn(64, 64);
  294.97 +        stream.read(buff, 0, buff.length);
  294.98 +
  294.99 +        int foundprogram = -1;
 294.100 +        int foundbank = -1;
 294.101 +        VoiceStatus[] vstatus = soft.getVoiceStatus();
 294.102 +        for (int i = 0; i < vstatus.length; i++) {
 294.103 +            if (vstatus[i].active) {
 294.104 +                foundprogram = vstatus[i].program;
 294.105 +                foundbank = vstatus[i].bank;
 294.106 +                break;
 294.107 +            }
 294.108 +        }
 294.109 +
 294.110 +        assertTrue(foundprogram == program);
 294.111 +        assertTrue(foundbank == bank);
 294.112 +
 294.113 +        channel.noteOn(64, 0);
 294.114 +        stream.read(buff, 0, buff.length);
 294.115 +
 294.116 +        channel = soft.getChannels()[1];
 294.117 +        // Send MSB Bank
 294.118 +        channel.controlChange(0x00, bank / 128);
 294.119 +        // Send LSB Bank
 294.120 +        channel.controlChange(0x20, bank % 128);
 294.121 +        // Send Program Change
 294.122 +        channel.programChange(program);
 294.123 +        channel.noteOn(64, 64);
 294.124 +        stream.read(buff, 0, buff.length);
 294.125 +
 294.126 +        foundprogram = -1;
 294.127 +        foundbank = -1;
 294.128 +        vstatus = soft.getVoiceStatus();
 294.129 +        for (int i = 0; i < vstatus.length; i++) {
 294.130 +            if (vstatus[i].active) {
 294.131 +                foundprogram = vstatus[i].program;
 294.132 +                foundbank = vstatus[i].bank;
 294.133 +                break;
 294.134 +            }
 294.135 +        }
 294.136 +        assertTrue(foundprogram == program);
 294.137 +        assertTrue(foundbank == bank);
 294.138 +        channel.noteOn(64, 0);
 294.139 +        stream.read(buff, 0, buff.length);
 294.140 +    }
 294.141 +
 294.142 +    public static void main(String[] args) throws Exception {
 294.143 +        SoftSynthesizer soft = new SoftSynthesizer();
 294.144 +        AudioInputStream stream = soft.openStream(null, null);
 294.145 +        soft.unloadAllInstruments(soft.getDefaultSoundbank());
 294.146 +
 294.147 +        soft.loadInstrument(generateTestInstrument(new Patch(0, 0)));
 294.148 +        soft.loadInstrument(generateTestInstrument(new Patch(7, 0)));
 294.149 +        soft.loadInstrument(generateTestInstrument(new Patch(20, 10)));
 294.150 +        soft.loadInstrument(generateTestInstrument(new Patch(3678, 15)));
 294.151 +        soft.loadInstrument(generateTestInstrument(new Patch(4678, 15)));
 294.152 +
 294.153 +        testProgramAndBank(soft, stream, new Patch(0, 0));
 294.154 +        testProgramAndBank(soft, stream, new Patch(7, 0));
 294.155 +        testProgramAndBank(soft, stream, new Patch(20, 10));
 294.156 +        testProgramAndBank(soft, stream, new Patch(3678, 15));
 294.157 +        testProgramAndBank(soft, stream, new Patch(4678, 15));
 294.158 +
 294.159 +        soft.close();
 294.160 +    }
 294.161 +}
   295.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   295.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/GetAvailableInstruments2.java	Fri Sep 24 16:41:32 2010 -0700
   295.3 @@ -0,0 +1,62 @@
   295.4 +/*
   295.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   295.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   295.7 + *
   295.8 + * This code is free software; you can redistribute it and/or modify it
   295.9 + * under the terms of the GNU General Public License version 2 only, as
  295.10 + * published by the Free Software Foundation.  Oracle designates this
  295.11 + * particular file as subject to the "Classpath" exception as provided
  295.12 + * by Oracle in the LICENSE file that accompanied this code.
  295.13 + *
  295.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  295.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  295.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  295.17 + * version 2 for more details (a copy is included in the LICENSE file that
  295.18 + * accompanied this code).
  295.19 + *
  295.20 + * You should have received a copy of the GNU General Public License version
  295.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  295.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  295.23 + *
  295.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  295.25 + * or visit www.oracle.com if you need additional information or have any
  295.26 + * questions.
  295.27 + */
  295.28 +
  295.29 +/* @test
  295.30 + @summary Test SoftSynthesizer getAvailableInstruments method */
  295.31 +
  295.32 +import javax.sound.midi.MidiDevice;
  295.33 +import javax.sound.midi.MidiUnavailableException;
  295.34 +import javax.sound.midi.Patch;
  295.35 +import javax.sound.midi.Soundbank;
  295.36 +import javax.sound.sampled.*;
  295.37 +import javax.sound.midi.MidiDevice.Info;
  295.38 +
  295.39 +import com.sun.media.sound.*;
  295.40 +
  295.41 +public class GetAvailableInstruments2 {
  295.42 +
  295.43 +    private static void assertEquals(Object a, Object b) throws Exception {
  295.44 +        if (!a.equals(b))
  295.45 +            throw new RuntimeException("assertEquals fails!");
  295.46 +    }
  295.47 +
  295.48 +    private static void assertTrue(boolean value) throws Exception {
  295.49 +        if (!value)
  295.50 +            throw new RuntimeException("assertTrue fails!");
  295.51 +    }
  295.52 +
  295.53 +    public static void main(String[] args) throws Exception {
  295.54 +        AudioSynthesizer synth = new SoftSynthesizer();
  295.55 +        synth.openStream(null, null);
  295.56 +        Soundbank defsbk = synth.getDefaultSoundbank();
  295.57 +        if (defsbk != null) {
  295.58 +            synth.unloadAllInstruments(defsbk);
  295.59 +            assertTrue(defsbk.getInstruments().length == synth
  295.60 +                    .getAvailableInstruments().length);
  295.61 +        }
  295.62 +        synth.close();
  295.63 +
  295.64 +    }
  295.65 +}
   296.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   296.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/GetLoadedInstruments2.java	Fri Sep 24 16:41:32 2010 -0700
   296.3 @@ -0,0 +1,61 @@
   296.4 +/*
   296.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   296.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   296.7 + *
   296.8 + * This code is free software; you can redistribute it and/or modify it
   296.9 + * under the terms of the GNU General Public License version 2 only, as
  296.10 + * published by the Free Software Foundation.  Oracle designates this
  296.11 + * particular file as subject to the "Classpath" exception as provided
  296.12 + * by Oracle in the LICENSE file that accompanied this code.
  296.13 + *
  296.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  296.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  296.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  296.17 + * version 2 for more details (a copy is included in the LICENSE file that
  296.18 + * accompanied this code).
  296.19 + *
  296.20 + * You should have received a copy of the GNU General Public License version
  296.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  296.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  296.23 + *
  296.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  296.25 + * or visit www.oracle.com if you need additional information or have any
  296.26 + * questions.
  296.27 + */
  296.28 +
  296.29 +/* @test
  296.30 + @summary Test SoftSynthesizer getLoadedInstruments method */
  296.31 +
  296.32 +import javax.sound.midi.MidiDevice;
  296.33 +import javax.sound.midi.MidiUnavailableException;
  296.34 +import javax.sound.midi.Patch;
  296.35 +import javax.sound.midi.Soundbank;
  296.36 +import javax.sound.sampled.*;
  296.37 +import javax.sound.midi.MidiDevice.Info;
  296.38 +
  296.39 +import com.sun.media.sound.*;
  296.40 +
  296.41 +public class GetLoadedInstruments2 {
  296.42 +
  296.43 +    private static void assertEquals(Object a, Object b) throws Exception {
  296.44 +        if (!a.equals(b))
  296.45 +            throw new RuntimeException("assertEquals fails!");
  296.46 +    }
  296.47 +
  296.48 +    private static void assertTrue(boolean value) throws Exception {
  296.49 +        if (!value)
  296.50 +            throw new RuntimeException("assertTrue fails!");
  296.51 +    }
  296.52 +
  296.53 +    public static void main(String[] args) throws Exception {
  296.54 +        AudioSynthesizer synth = new SoftSynthesizer();
  296.55 +        synth.openStream(null, null);
  296.56 +        Soundbank defsbk = synth.getDefaultSoundbank();
  296.57 +        if (defsbk != null) {
  296.58 +            assertTrue(defsbk.getInstruments().length == synth
  296.59 +                    .getLoadedInstruments().length);
  296.60 +        }
  296.61 +        synth.close();
  296.62 +
  296.63 +    }
  296.64 +}
   297.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   297.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/GetPropertyInfo.java	Fri Sep 24 16:41:32 2010 -0700
   297.3 @@ -0,0 +1,103 @@
   297.4 +/*
   297.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   297.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   297.7 + *
   297.8 + * This code is free software; you can redistribute it and/or modify it
   297.9 + * under the terms of the GNU General Public License version 2 only, as
  297.10 + * published by the Free Software Foundation.  Oracle designates this
  297.11 + * particular file as subject to the "Classpath" exception as provided
  297.12 + * by Oracle in the LICENSE file that accompanied this code.
  297.13 + *
  297.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  297.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  297.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  297.17 + * version 2 for more details (a copy is included in the LICENSE file that
  297.18 + * accompanied this code).
  297.19 + *
  297.20 + * You should have received a copy of the GNU General Public License version
  297.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  297.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  297.23 + *
  297.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  297.25 + * or visit www.oracle.com if you need additional information or have any
  297.26 + * questions.
  297.27 + */
  297.28 +
  297.29 +/* @test
  297.30 + @summary Test SoftSynthesizer getPropertyInfo method */
  297.31 +
  297.32 +import java.util.HashMap;
  297.33 +import java.util.Map;
  297.34 +
  297.35 +import javax.sound.midi.MidiDevice;
  297.36 +import javax.sound.midi.MidiUnavailableException;
  297.37 +import javax.sound.midi.Patch;
  297.38 +import javax.sound.midi.Soundbank;
  297.39 +import javax.sound.sampled.*;
  297.40 +import javax.sound.sampled.AudioFormat.Encoding;
  297.41 +import javax.sound.midi.MidiDevice.Info;
  297.42 +
  297.43 +import com.sun.media.sound.*;
  297.44 +
  297.45 +public class GetPropertyInfo {
  297.46 +
  297.47 +    private static void assertTrue(boolean value) throws Exception {
  297.48 +        if (!value)
  297.49 +            throw new RuntimeException("assertTrue fails!");
  297.50 +    }
  297.51 +
  297.52 +    public static void main(String[] args) throws Exception {
  297.53 +        SoftSynthesizer synth = new SoftSynthesizer();
  297.54 +        Map<String, Object> p = new HashMap<String, Object>();
  297.55 +        p.put("format", "8000 HZ 24 BIT MONO UNSIGNED BIG-ENDIAN");
  297.56 +        p.put("control rate", 125);
  297.57 +        p.put("reverb", false);
  297.58 +        p.put("auto gain control", "false");
  297.59 +        AudioSynthesizerPropertyInfo[] ap = synth.getPropertyInfo(p);
  297.60 +        for (int i = 0; i < ap.length; i++) {
  297.61 +            if (ap[i].name.equals("control rate"))
  297.62 +                assertTrue(Math.abs((Float) ap[i].value - 125.0) < 0.001);
  297.63 +            if (ap[i].name.equals("reverb"))
  297.64 +                assertTrue((Boolean) ap[i].value == false);
  297.65 +            if (ap[i].name.equals("auto gain control"))
  297.66 +                assertTrue((Boolean) ap[i].value == false);
  297.67 +            if (ap[i].name.equals("format")) {
  297.68 +                AudioFormat format = (AudioFormat) ap[i].value;
  297.69 +                assertTrue(format.getChannels() == 1);
  297.70 +                assertTrue(format.getSampleSizeInBits() == 24);
  297.71 +                assertTrue(format.isBigEndian());
  297.72 +                assertTrue(Math.abs(format.getSampleRate() - 8000) < 0.001);
  297.73 +                assertTrue(format.getEncoding() == Encoding.PCM_UNSIGNED);
  297.74 +            }
  297.75 +        }
  297.76 +        p = new HashMap<String, Object>();
  297.77 +        p.put("format", "9000 Hz, 8 bit, 4 channels");
  297.78 +        ap = synth.getPropertyInfo(p);
  297.79 +        for (int i = 0; i < ap.length; i++) {
  297.80 +            if (ap[i].name.equals("format")) {
  297.81 +                AudioFormat format = (AudioFormat) ap[i].value;
  297.82 +                assertTrue(format.getChannels() == 4);
  297.83 +                assertTrue(format.getSampleSizeInBits() == 8);
  297.84 +                assertTrue(!format.isBigEndian());
  297.85 +                assertTrue(Math.abs(format.getSampleRate() - 9000) < 0.001);
  297.86 +                assertTrue(format.getEncoding() == Encoding.PCM_SIGNED);
  297.87 +            }
  297.88 +        }
  297.89 +
  297.90 +        p = new HashMap<String, Object>();
  297.91 +        p.put("format", "PCM_UNSIGNED 44100.0 Hz, 16 bit, 3 channels, 6 bytes/frame, big-endian");
  297.92 +        ap = synth.getPropertyInfo(p);
  297.93 +        for (int i = 0; i < ap.length; i++) {
  297.94 +            if (ap[i].name.equals("format")) {
  297.95 +                AudioFormat format = (AudioFormat) ap[i].value;
  297.96 +                assertTrue(format.getChannels() == 3);
  297.97 +                assertTrue(format.getSampleSizeInBits() == 16);
  297.98 +                assertTrue(format.isBigEndian());
  297.99 +                assertTrue(Math.abs(format.getSampleRate() - 44100) < 0.001);
 297.100 +                assertTrue(format.getEncoding() == Encoding.PCM_UNSIGNED);
 297.101 +            }
 297.102 +        }
 297.103 +
 297.104 +
 297.105 +    }
 297.106 +}
   298.1 --- a/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadAllInstruments.java	Thu Sep 23 17:33:40 2010 -0700
   298.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadAllInstruments.java	Fri Sep 24 16:41:32 2010 -0700
   298.3 @@ -55,7 +55,6 @@
   298.4          Soundbank defsbk = synth.getDefaultSoundbank();
   298.5          if(defsbk != null)
   298.6          {
   298.7 -            assertTrue(synth.getLoadedInstruments().length == 0);
   298.8              synth.unloadAllInstruments(defsbk);
   298.9              SimpleSoundbank sbk = new SimpleSoundbank();
  298.10              SimpleInstrument ins = new SimpleInstrument();
   299.1 --- a/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstrument.java	Thu Sep 23 17:33:40 2010 -0700
   299.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstrument.java	Fri Sep 24 16:41:32 2010 -0700
   299.3 @@ -55,7 +55,6 @@
   299.4          Soundbank defsbk = synth.getDefaultSoundbank();
   299.5          if(defsbk != null)
   299.6          {
   299.7 -            assertTrue(synth.getLoadedInstruments().length == 0);
   299.8              synth.unloadAllInstruments(defsbk);
   299.9              SimpleSoundbank sbk = new SimpleSoundbank();
  299.10              SimpleInstrument ins = new SimpleInstrument();
   300.1 --- a/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstruments.java	Thu Sep 23 17:33:40 2010 -0700
   300.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/LoadInstruments.java	Fri Sep 24 16:41:32 2010 -0700
   300.3 @@ -55,7 +55,6 @@
   300.4          Soundbank defsbk = synth.getDefaultSoundbank();
   300.5          if(defsbk != null)
   300.6          {
   300.7 -            assertTrue(synth.getLoadedInstruments().length == 0);
   300.8              synth.unloadAllInstruments(defsbk);
   300.9              SimpleSoundbank sbk = new SimpleSoundbank();
  300.10              SimpleInstrument ins = new SimpleInstrument();
   301.1 --- a/test/javax/sound/midi/Gervill/SoftSynthesizer/RemapInstrument.java	Thu Sep 23 17:33:40 2010 -0700
   301.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/RemapInstrument.java	Fri Sep 24 16:41:32 2010 -0700
   301.3 @@ -56,15 +56,15 @@
   301.4          Soundbank defsbk = synth.getDefaultSoundbank();
   301.5          if(defsbk != null)
   301.6          {
   301.7 -            Instrument ins0 = defsbk.getInstrument(new Patch(0,0));
   301.8 +            Instrument ins3 = defsbk.getInstrument(new Patch(0,3));
   301.9              Instrument ins10 = defsbk.getInstrument(new Patch(0,10));
  301.10 -            assertTrue(synth.remapInstrument(ins0, ins10));
  301.11 +            assertTrue(synth.remapInstrument(ins3, ins10));
  301.12              Instrument[] loaded = synth.getLoadedInstruments();
  301.13              for (int i = 0; i < loaded.length; i++) {
  301.14 -                if(loaded[i].getPatch().getBank() == 0)
  301.15 -                if(loaded[i].getPatch().getProgram() == 10)
  301.16 +                if(loaded[i].getPatch().getBank() == ins3.getPatch().getBank())
  301.17 +                if(loaded[i].getPatch().getProgram() == ins3.getPatch().getProgram())
  301.18                  {
  301.19 -                    assertEquals(loaded[i].getName(), ins0.getName());
  301.20 +                    assertEquals(loaded[i].getName(), ins10.getName());
  301.21                      break;
  301.22                  }
  301.23              }
   302.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   302.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/TestDisableLoadDefaultSoundbank.java	Fri Sep 24 16:41:32 2010 -0700
   302.3 @@ -0,0 +1,71 @@
   302.4 +/*
   302.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   302.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   302.7 + *
   302.8 + * This code is free software; you can redistribute it and/or modify it
   302.9 + * under the terms of the GNU General Public License version 2 only, as
  302.10 + * published by the Free Software Foundation.  Oracle designates this
  302.11 + * particular file as subject to the "Classpath" exception as provided
  302.12 + * by Oracle in the LICENSE file that accompanied this code.
  302.13 + *
  302.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  302.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  302.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  302.17 + * version 2 for more details (a copy is included in the LICENSE file that
  302.18 + * accompanied this code).
  302.19 + *
  302.20 + * You should have received a copy of the GNU General Public License version
  302.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  302.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  302.23 + *
  302.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  302.25 + * or visit www.oracle.com if you need additional information or have any
  302.26 + * questions.
  302.27 + */
  302.28 +
  302.29 +/* @test
  302.30 + @summary Test Disable/enable loading default soundbank in SoftSynthesizer */
  302.31 +
  302.32 +import java.util.HashMap;
  302.33 +import java.util.Map;
  302.34 +
  302.35 +import javax.sound.midi.MidiDevice;
  302.36 +import javax.sound.midi.MidiUnavailableException;
  302.37 +import javax.sound.midi.Patch;
  302.38 +import javax.sound.midi.Soundbank;
  302.39 +import javax.sound.sampled.*;
  302.40 +import javax.sound.midi.MidiDevice.Info;
  302.41 +
  302.42 +import com.sun.media.sound.*;
  302.43 +
  302.44 +public class TestDisableLoadDefaultSoundbank {
  302.45 +
  302.46 +    private static void assertEquals(Object a, Object b) throws Exception {
  302.47 +        if (!a.equals(b))
  302.48 +            throw new RuntimeException("assertEquals fails!");
  302.49 +    }
  302.50 +
  302.51 +    private static void assertTrue(boolean value) throws Exception {
  302.52 +        if (!value)
  302.53 +            throw new RuntimeException("assertTrue fails!");
  302.54 +    }
  302.55 +
  302.56 +    public static void main(String[] args) throws Exception {
  302.57 +        AudioSynthesizer synth = new SoftSynthesizer();
  302.58 +        synth.openStream(null, null);
  302.59 +        Soundbank defsbk = synth.getDefaultSoundbank();
  302.60 +        if (defsbk != null) {
  302.61 +            assertTrue(defsbk.getInstruments().length == synth
  302.62 +                    .getLoadedInstruments().length);
  302.63 +        }
  302.64 +        synth.close();
  302.65 +        Map<String, Object> p = new HashMap<String, Object>();
  302.66 +        p.put("load default soundbank", false);
  302.67 +        synth.openStream(null, p);
  302.68 +        if (defsbk != null) {
  302.69 +            assertTrue(synth.getLoadedInstruments().length == 0);
  302.70 +        }
  302.71 +        synth.close();
  302.72 +
  302.73 +    }
  302.74 +}
   303.1 --- a/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadAllInstruments.java	Thu Sep 23 17:33:40 2010 -0700
   303.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadAllInstruments.java	Fri Sep 24 16:41:32 2010 -0700
   303.3 @@ -55,9 +55,8 @@
   303.4          Soundbank defsbk = synth.getDefaultSoundbank();
   303.5          if(defsbk != null)
   303.6          {
   303.7 +            synth.unloadAllInstruments(defsbk);
   303.8              assertTrue(synth.getLoadedInstruments().length == 0);
   303.9 -            synth.unloadAllInstruments(defsbk);
  303.10 -            assertTrue(synth.getAvailableInstruments().length == 0);
  303.11              synth.loadAllInstruments(defsbk);
  303.12              assertTrue(synth.getLoadedInstruments().length != 0);
  303.13              synth.unloadAllInstruments(defsbk);
   304.1 --- a/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstrument.java	Thu Sep 23 17:33:40 2010 -0700
   304.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstrument.java	Fri Sep 24 16:41:32 2010 -0700
   304.3 @@ -55,7 +55,6 @@
   304.4          Soundbank defsbk = synth.getDefaultSoundbank();
   304.5          if(defsbk != null)
   304.6          {
   304.7 -            assertTrue(synth.getLoadedInstruments().length == 0);
   304.8              synth.unloadAllInstruments(defsbk);
   304.9              SimpleSoundbank sbk = new SimpleSoundbank();
  304.10              SimpleInstrument ins = new SimpleInstrument();
   305.1 --- a/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstruments.java	Thu Sep 23 17:33:40 2010 -0700
   305.2 +++ b/test/javax/sound/midi/Gervill/SoftSynthesizer/UnloadInstruments.java	Fri Sep 24 16:41:32 2010 -0700
   305.3 @@ -55,7 +55,6 @@
   305.4          Soundbank defsbk = synth.getDefaultSoundbank();
   305.5          if(defsbk != null)
   305.6          {
   305.7 -            assertTrue(synth.getLoadedInstruments().length == 0);
   305.8              synth.unloadAllInstruments(defsbk);
   305.9              SimpleSoundbank sbk = new SimpleSoundbank();
  305.10              SimpleInstrument ins = new SimpleInstrument();
   306.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   306.2 +++ b/test/javax/sound/midi/Gervill/SoftTuning/RealTimeTuning.java	Fri Sep 24 16:41:32 2010 -0700
   306.3 @@ -0,0 +1,250 @@
   306.4 +/*
   306.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   306.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   306.7 + *
   306.8 + * This code is free software; you can redistribute it and/or modify it
   306.9 + * under the terms of the GNU General Public License version 2 only, as
  306.10 + * published by the Free Software Foundation.  Oracle designates this
  306.11 + * particular file as subject to the "Classpath" exception as provided
  306.12 + * by Oracle in the LICENSE file that accompanied this code.
  306.13 + *
  306.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  306.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  306.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  306.17 + * version 2 for more details (a copy is included in the LICENSE file that
  306.18 + * accompanied this code).
  306.19 + *
  306.20 + * You should have received a copy of the GNU General Public License version
  306.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  306.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  306.23 + *
  306.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  306.25 + * or visit www.oracle.com if you need additional information or have any
  306.26 + * questions.
  306.27 + */
  306.28 +
  306.29 +/* @test
  306.30 + @summary Test RealTime-tunings using SoftReciver.send method */
  306.31 +
  306.32 +import java.io.IOException;
  306.33 +
  306.34 +import javax.sound.midi.*;
  306.35 +import javax.sound.sampled.*;
  306.36 +
  306.37 +import com.sun.media.sound.*;
  306.38 +
  306.39 +public class RealTimeTuning {
  306.40 +
  306.41 +    private static class PitchSpy {
  306.42 +        public float pitch = 0;
  306.43 +
  306.44 +        public Soundbank getSoundBank() {
  306.45 +            ModelOscillator osc = new ModelOscillator() {
  306.46 +                public float getAttenuation() {
  306.47 +                    return 0;
  306.48 +                }
  306.49 +
  306.50 +                public int getChannels() {
  306.51 +                    return 0;
  306.52 +                }
  306.53 +
  306.54 +                public ModelOscillatorStream open(float samplerate) {
  306.55 +                    return new ModelOscillatorStream() {
  306.56 +                        public void close() throws IOException {
  306.57 +                            pitch = 0;
  306.58 +                        }
  306.59 +
  306.60 +                        public void noteOff(int velocity) {
  306.61 +                            pitch = 0;
  306.62 +                        }
  306.63 +
  306.64 +                        public void noteOn(MidiChannel channel,
  306.65 +                                VoiceStatus voice, int noteNumber, int velocity) {
  306.66 +                            pitch = noteNumber * 100;
  306.67 +                        }
  306.68 +
  306.69 +                        public int read(float[][] buffer, int offset, int len)
  306.70 +                                throws IOException {
  306.71 +                            return len;
  306.72 +                        }
  306.73 +
  306.74 +                        public void setPitch(float ipitch) {
  306.75 +                            pitch = ipitch;
  306.76 +                        }
  306.77 +                    };
  306.78 +                }
  306.79 +            };
  306.80 +            ModelPerformer performer = new ModelPerformer();
  306.81 +            performer.getOscillators().add(osc);
  306.82 +            SimpleInstrument testinstrument = new SimpleInstrument();
  306.83 +            testinstrument.setPatch(new Patch(0, 0));
  306.84 +            testinstrument.add(performer);
  306.85 +            SimpleSoundbank testsoundbank = new SimpleSoundbank();
  306.86 +            testsoundbank.addInstrument(testinstrument);
  306.87 +            return testsoundbank;
  306.88 +        }
  306.89 +    }
  306.90 +
  306.91 +    public static void sendTuningChange(Receiver recv, int channel,
  306.92 +            int tuningpreset, int tuningbank) throws InvalidMidiDataException {
  306.93 +        // Data Entry
  306.94 +        ShortMessage sm1 = new ShortMessage();
  306.95 +        sm1.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 04);
  306.96 +        ShortMessage sm2 = new ShortMessage();
  306.97 +        sm2.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);
  306.98 +
  306.99 +        // Tuning Bank
 306.100 +        ShortMessage sm3 = new ShortMessage();
 306.101 +        sm3.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06, tuningbank);
 306.102 +        // Data Increment
 306.103 +        ShortMessage sm4 = new ShortMessage();
 306.104 +        sm4.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);
 306.105 +        // Data Decrement
 306.106 +        ShortMessage sm5 = new ShortMessage();
 306.107 +        sm5.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);
 306.108 +
 306.109 +        // Data Entry
 306.110 +        ShortMessage sm6 = new ShortMessage();
 306.111 +        sm6.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x64, 03);
 306.112 +        ShortMessage sm7 = new ShortMessage();
 306.113 +        sm7.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x65, 00);
 306.114 +
 306.115 +        // Tuning program
 306.116 +        ShortMessage sm8 = new ShortMessage();
 306.117 +        sm8
 306.118 +                .setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x06,
 306.119 +                        tuningpreset);
 306.120 +        // Data Increment
 306.121 +        ShortMessage sm9 = new ShortMessage();
 306.122 +        sm9.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x60, 0x7F);
 306.123 +        // Data Decrement
 306.124 +        ShortMessage sm10 = new ShortMessage();
 306.125 +        sm10.setMessage(ShortMessage.CONTROL_CHANGE, channel, 0x61, 0x7F);
 306.126 +
 306.127 +        recv.send(sm1, -1);
 306.128 +        recv.send(sm2, -1);
 306.129 +        recv.send(sm3, -1);
 306.130 +        recv.send(sm4, -1);
 306.131 +        recv.send(sm5, -1);
 306.132 +        recv.send(sm6, -1);
 306.133 +        recv.send(sm7, -1);
 306.134 +        recv.send(sm8, -1);
 306.135 +        recv.send(sm9, -1);
 306.136 +        recv.send(sm10, -1);
 306.137 +
 306.138 +    }
 306.139 +
 306.140 +    private static void assertTrue(boolean value) throws Exception {
 306.141 +        if (!value)
 306.142 +            throw new RuntimeException("assertTrue fails!");
 306.143 +    }
 306.144 +
 306.145 +    public static void testTunings(int[] msg, int tuningProgram,
 306.146 +            int tuningBank, int targetNote, float targetPitch, boolean realtime)
 306.147 +            throws Exception {
 306.148 +        AudioSynthesizer synth = new SoftSynthesizer();
 306.149 +        AudioInputStream stream = synth.openStream(null, null);
 306.150 +        Receiver recv = synth.getReceiver();
 306.151 +        MidiChannel channel = synth.getChannels()[0];
 306.152 +        byte[] buff = new byte[2048];
 306.153 +
 306.154 +        // Create test instrument which we can use to monitor pitch changes
 306.155 +        PitchSpy pitchspy = new PitchSpy();
 306.156 +
 306.157 +        synth.unloadAllInstruments(synth.getDefaultSoundbank());
 306.158 +        synth.loadAllInstruments(pitchspy.getSoundBank());
 306.159 +
 306.160 +        SysexMessage sysex = null;
 306.161 +
 306.162 +        // Send tuning changes
 306.163 +        if (msg != null) {
 306.164 +            byte[] bmsg = new byte[msg.length];
 306.165 +            for (int i = 0; i < bmsg.length; i++)
 306.166 +                bmsg[i] = (byte) msg[i];
 306.167 +            sysex = new SysexMessage();
 306.168 +            sysex.setMessage(bmsg, bmsg.length);
 306.169 +            if (targetPitch == 0) {
 306.170 +                targetPitch = (float) new SoftTuning(bmsg)
 306.171 +                        .getTuning(targetNote);
 306.172 +                // Check if targetPitch != targetNote * 100
 306.173 +                assertTrue(Math.abs(targetPitch - targetNote * 100.0) > 0.001);
 306.174 +            }
 306.175 +        }
 306.176 +
 306.177 +        if (tuningProgram != -1)
 306.178 +            sendTuningChange(recv, 0, tuningProgram, tuningBank);
 306.179 +
 306.180 +        // First test without tunings
 306.181 +        channel.noteOn(targetNote, 64);
 306.182 +        stream.read(buff, 0, buff.length);
 306.183 +        assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);
 306.184 +
 306.185 +        // Test if realtime/non-realtime works
 306.186 +        if (sysex != null)
 306.187 +            recv.send(sysex, -1);
 306.188 +        stream.read(buff, 0, buff.length);
 306.189 +        if (realtime)
 306.190 +            assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);
 306.191 +        else
 306.192 +            assertTrue(Math.abs(pitchspy.pitch - (targetNote * 100.0)) < 0.001);
 306.193 +
 306.194 +        // Test if tunings works
 306.195 +        channel.noteOn(targetNote, 0);
 306.196 +        stream.read(buff, 0, buff.length);
 306.197 +        assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);
 306.198 +
 306.199 +        channel.noteOn(targetNote, 64);
 306.200 +        stream.read(buff, 0, buff.length);
 306.201 +        assertTrue(Math.abs(pitchspy.pitch - targetPitch) < 0.001);
 306.202 +
 306.203 +        channel.noteOn(targetNote, 0);
 306.204 +        stream.read(buff, 0, buff.length);
 306.205 +        assertTrue(Math.abs(pitchspy.pitch - 0.0) < 0.001);
 306.206 +
 306.207 +        stream.close();
 306.208 +    }
 306.209 +
 306.210 +    public static void main(String[] args) throws Exception {
 306.211 +        // Test with no-tunings
 306.212 +        testTunings(null, -1, -1, 60, 6000, false);
 306.213 +
 306.214 +        int[] msg;
 306.215 +        // 0x02 SINGLE NOTE TUNING CHANGE (REAL-TIME)
 306.216 +        msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x02, 0x10, 0x02, 36, 36, 64,
 306.217 +                0, 60, 70, 0, 0, 0xf7 };
 306.218 +        testTunings(msg, 0x10, 0, 60, 7000, true);
 306.219 +
 306.220 +        // 0x07 SINGLE NOTE TUNING CHANGE (NON REAL-TIME) (BANK)
 306.221 +        msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,
 306.222 +                36, 64, 0, 60, 80, 0, 0, 0xf7 };
 306.223 +        testTunings(msg, 0x07, 0x05, 60, 8000, false);
 306.224 +
 306.225 +        // 0x07 SINGLE NOTE TUNING CHANGE (REAL-TIME) (BANK)
 306.226 +        msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x07, 0x05, 0x07, 0x02, 36,
 306.227 +                36, 64, 0, 60, 80, 0, 0, 0xf7 };
 306.228 +        testTunings(msg, 0x07, 0x05, 60, 8000, true);
 306.229 +
 306.230 +        // 0x08 scale/octave tuning 1-byte form (Non Real-Time)
 306.231 +        msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,
 306.232 +                10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };
 306.233 +        testTunings(msg, -1, -1, 60, 0, false);
 306.234 +
 306.235 +        // 0x08 scale/octave tuning 1-byte form (REAL-TIME)
 306.236 +        msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x08, 0x03, 0x7f, 0x7f, 5,
 306.237 +                10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 0xf7 };
 306.238 +        testTunings(msg, -1, -1, 60, 0, true);
 306.239 +
 306.240 +        // 0x09 scale/octave tuning 2-byte form (Non Real-Time)
 306.241 +        msg = new int[] { 0xf0, 0x7e, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,
 306.242 +                10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,
 306.243 +                30, 35, 40, 45, 50, 51, 52, 0xf7 };
 306.244 +        testTunings(msg, -1, -1, 60, 0, false);
 306.245 +
 306.246 +        // 0x09 scale/octave tuning 2-byte form (REAL-TIME)
 306.247 +        msg = new int[] { 0xf0, 0x7f, 0x7f, 0x08, 0x09, 0x03, 0x7f, 0x7f, 5,
 306.248 +                10, 15, 20, 25, 30, 35, 40, 45, 50, 51, 52, 5, 10, 15, 20, 25,
 306.249 +                30, 35, 40, 45, 50, 51, 52, 0xf7 };
 306.250 +        testTunings(msg, -1, -1, 60, 0, true);
 306.251 +
 306.252 +    }
 306.253 +}
   307.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   307.2 +++ b/test/javax/sound/midi/MidiDeviceConnectors/TestAllDevices.java	Fri Sep 24 16:41:32 2010 -0700
   307.3 @@ -0,0 +1,143 @@
   307.4 +/*
   307.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   307.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   307.7 + *
   307.8 + * This code is free software; you can redistribute it and/or modify it
   307.9 + * under the terms of the GNU General Public License version 2 only, as
  307.10 + * published by the Free Software Foundation.  Oracle designates this
  307.11 + * particular file as subject to the "Classpath" exception as provided
  307.12 + * by Oracle in the LICENSE file that accompanied this code.
  307.13 + *
  307.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  307.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  307.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  307.17 + * version 2 for more details (a copy is included in the LICENSE file that
  307.18 + * accompanied this code).
  307.19 + *
  307.20 + * You should have received a copy of the GNU General Public License version
  307.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  307.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  307.23 + *
  307.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  307.25 + * or visit www.oracle.com if you need additional information or have any
  307.26 + * questions.
  307.27 + */
  307.28 +
  307.29 +/**
  307.30 + * @test
  307.31 + * @bug 4933700
  307.32 + * @summary Tests that default devices return MidiDeviceTransmitter/Receiver and returned objects return correct MidiDevice
  307.33 + * @compile -source 1.7 TestAllDevices.java
  307.34 + * @run main TestAllDevices
  307.35 + * @author Alex Menkov
  307.36 + */
  307.37 +
  307.38 +import javax.sound.midi.MidiDevice;
  307.39 +import javax.sound.midi.MidiDeviceReceiver;
  307.40 +import javax.sound.midi.MidiDeviceTransmitter;
  307.41 +import javax.sound.midi.MidiSystem;
  307.42 +import javax.sound.midi.MidiUnavailableException;
  307.43 +import javax.sound.midi.Receiver;
  307.44 +import javax.sound.midi.Transmitter;
  307.45 +
  307.46 +
  307.47 +public class TestAllDevices {
  307.48 +
  307.49 +    static boolean failed = false;
  307.50 +
  307.51 +    public static void main(String[] args) throws Exception {
  307.52 +        out("default receiver:");
  307.53 +        try {
  307.54 +            Receiver recv = MidiSystem.getReceiver();
  307.55 +            out("  receiver: " + recv);
  307.56 +            if (recv instanceof MidiDeviceReceiver) {
  307.57 +                out("    OK");
  307.58 +            } else {
  307.59 +                out("    ERROR: not an instance of MidiDeviceReceiver");
  307.60 +                failed = true;
  307.61 +            }
  307.62 +        } catch (MidiUnavailableException ex) {
  307.63 +            // this is not an error
  307.64 +            out("  receiver: MidiUnavailableException (test NOT failed)");
  307.65 +        }
  307.66 +
  307.67 +        out("default transmitter:");
  307.68 +        try {
  307.69 +            Transmitter tran = MidiSystem.getTransmitter();
  307.70 +            out("  transmitter: " + tran);
  307.71 +            if (tran instanceof MidiDeviceTransmitter) {
  307.72 +                out("    OK");
  307.73 +            } else {
  307.74 +                out("    ERROR: not an instance of MidiDeviceTransmitter");
  307.75 +                failed = true;
  307.76 +            }
  307.77 +        } catch (MidiUnavailableException ex) {
  307.78 +            // this is not an error
  307.79 +            out("  transmitter: MidiUnavailableException (test NOT failed)");
  307.80 +        }
  307.81 +
  307.82 +        MidiDevice.Info[] infos = MidiSystem .getMidiDeviceInfo();
  307.83 +        for (MidiDevice.Info info: infos) {
  307.84 +            out(info.toString() + ":");
  307.85 +            try {
  307.86 +                MidiDevice dev = MidiSystem.getMidiDevice(info);
  307.87 +                dev.open();
  307.88 +
  307.89 +                try {
  307.90 +                    Receiver recv = dev.getReceiver();
  307.91 +                    out("  receiver: " + recv);
  307.92 +                    if (recv instanceof MidiDeviceReceiver) {
  307.93 +                        MidiDeviceReceiver devRecv = (MidiDeviceReceiver)recv;
  307.94 +                        MidiDevice retDev = devRecv.getMidiDevice();
  307.95 +                        if (retDev == dev) {
  307.96 +                            out("    OK");
  307.97 +                        } else {
  307.98 +                            out("    ERROR: getMidiDevice returned incorrect device: " + retDev);
  307.99 +                            failed = true;
 307.100 +                        }
 307.101 +                    } else {
 307.102 +                        out("    ERROR: not an instance of MidiDeviceReceiver");
 307.103 +                        failed = true;
 307.104 +                    }
 307.105 +                } catch (MidiUnavailableException ex) {
 307.106 +                    // this is not an error
 307.107 +                    out("  receiver: MidiUnavailableException (test NOT failed)");
 307.108 +                }
 307.109 +
 307.110 +                try {
 307.111 +                    Transmitter tran = dev.getTransmitter();
 307.112 +                    out("  transmitter: " + tran);
 307.113 +                    if (tran instanceof MidiDeviceTransmitter) {
 307.114 +                        MidiDeviceTransmitter devTran = (MidiDeviceTransmitter)tran;
 307.115 +                        MidiDevice retDev = devTran.getMidiDevice();
 307.116 +                        if (retDev == dev) {
 307.117 +                            out("    OK");
 307.118 +                        } else {
 307.119 +                            out("    ERROR: getMidiDevice retur4ned incorrect device: " + retDev);
 307.120 +                            failed = true;
 307.121 +                        }
 307.122 +                    } else {
 307.123 +                        out("    ERROR: not an instance of MidiDeviceTransmitter");
 307.124 +                        failed = true;
 307.125 +                    }
 307.126 +                } catch (MidiUnavailableException ex) {
 307.127 +                    // this is not an error
 307.128 +                    out("  transmitter: MidiUnavailableException (test NOT failed)");
 307.129 +                }
 307.130 +
 307.131 +                dev.close();
 307.132 +            } catch (MidiUnavailableException ex) {
 307.133 +                out("  device: MidiUnavailableException (test NOT failed)");
 307.134 +            }
 307.135 +        }
 307.136 +
 307.137 +        if (failed) {
 307.138 +            throw new Exception("Test failed.");
 307.139 +        }
 307.140 +    }
 307.141 +
 307.142 +    static void out(String s) {
 307.143 +        System.out.println(s);
 307.144 +    }
 307.145 +
 307.146 +}
   308.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   308.2 +++ b/test/javax/sound/sampled/AudioFormat/Matches_NOT_SPECIFIED.java	Fri Sep 24 16:41:32 2010 -0700
   308.3 @@ -0,0 +1,102 @@
   308.4 +/*
   308.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   308.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   308.7 + *
   308.8 + * This code is free software; you can redistribute it and/or modify it
   308.9 + * under the terms of the GNU General Public License version 2 only, as
  308.10 + * published by the Free Software Foundation.  Oracle designates this
  308.11 + * particular file as subject to the "Classpath" exception as provided
  308.12 + * by Oracle in the LICENSE file that accompanied this code.
  308.13 + *
  308.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  308.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  308.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  308.17 + * version 2 for more details (a copy is included in the LICENSE file that
  308.18 + * accompanied this code).
  308.19 + *
  308.20 + * You should have received a copy of the GNU General Public License version
  308.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  308.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  308.23 + *
  308.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  308.25 + * or visit www.oracle.com if you need additional information or have any
  308.26 + * questions.
  308.27 + */
  308.28 +
  308.29 +/**
  308.30 + * @test
  308.31 + * @bug 4937708
  308.32 + * @summary Tests that AudioFormat.matches handle NOT_SPECIFIED value in all fields
  308.33 + * @run main Matches_NOT_SPECIFIED
  308.34 + * @author Alex Menkov
  308.35 + *
  308.36 + */
  308.37 +
  308.38 +import javax.sound.sampled.AudioFormat;
  308.39 +import javax.sound.sampled.AudioFormat.Encoding;
  308.40 +import javax.sound.sampled.AudioSystem;
  308.41 +
  308.42 +
  308.43 +public class Matches_NOT_SPECIFIED {
  308.44 +
  308.45 +    static boolean success = true;
  308.46 +    static AudioFormat f1;
  308.47 +    static AudioFormat f2;
  308.48 +
  308.49 +    public static void main(String[] args) throws Exception {
  308.50 +        AudioFormat f3;
  308.51 +        f1 = new AudioFormat(44100, 16, 2, true, false);
  308.52 +        f2 = new AudioFormat(Encoding.PCM_SIGNED,
  308.53 +                AudioSystem.NOT_SPECIFIED,
  308.54 +                AudioSystem.NOT_SPECIFIED,
  308.55 +                AudioSystem.NOT_SPECIFIED,
  308.56 +                AudioSystem.NOT_SPECIFIED,
  308.57 +                AudioSystem.NOT_SPECIFIED, false);
  308.58 +        test(true);
  308.59 +
  308.60 +//        f1 = new AudioFormat(44100, 8, 16, true, false);
  308.61 +        f2 = new AudioFormat(Encoding.PCM_SIGNED,
  308.62 +                AudioSystem.NOT_SPECIFIED,
  308.63 +                AudioSystem.NOT_SPECIFIED,
  308.64 +                AudioSystem.NOT_SPECIFIED,
  308.65 +                AudioSystem.NOT_SPECIFIED,
  308.66 +                AudioSystem.NOT_SPECIFIED, true);
  308.67 +        test(false);
  308.68 +
  308.69 +        f1 = new AudioFormat(44100, 8, 8, true, false);
  308.70 +        test(true);
  308.71 +
  308.72 +        if (success) {
  308.73 +            out("The test PASSED.");
  308.74 +        } else {
  308.75 +            out("The test FAILED.");
  308.76 +            throw new Exception("The test FAILED");
  308.77 +        }
  308.78 +    }
  308.79 +
  308.80 +    static void test(boolean shouldMatch) {
  308.81 +        out("testing:");
  308.82 +        out("  - " + f1.toString());
  308.83 +        out("  - " + f2.toString());
  308.84 +        if (f1.matches(f2)) {
  308.85 +            if (shouldMatch) {
  308.86 +                out("  (OK) MATCHES");
  308.87 +            } else {
  308.88 +                out("  (ERROR) MATCHES");
  308.89 +                success = false;
  308.90 +            }
  308.91 +        } else {
  308.92 +            if (shouldMatch) {
  308.93 +                out("  (ERROR) DOESNT MATCH!");
  308.94 +                success = false;
  308.95 +            } else {
  308.96 +                out("  (OK) DOESNT MATCH!");
  308.97 +            }
  308.98 +        }
  308.99 +    }
 308.100 +
 308.101 +    static void out(String s) {
 308.102 +        System.out.println(s);
 308.103 +    }
 308.104 +
 308.105 +}
   309.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   309.2 +++ b/test/javax/sound/sampled/AudioFormat/PCM_FLOAT_support.java	Fri Sep 24 16:41:32 2010 -0700
   309.3 @@ -0,0 +1,86 @@
   309.4 +/*
   309.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   309.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   309.7 + *
   309.8 + * This code is free software; you can redistribute it and/or modify it
   309.9 + * under the terms of the GNU General Public License version 2 only, as
  309.10 + * published by the Free Software Foundation.  Oracle designates this
  309.11 + * particular file as subject to the "Classpath" exception as provided
  309.12 + * by Oracle in the LICENSE file that accompanied this code.
  309.13 + *
  309.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  309.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  309.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  309.17 + * version 2 for more details (a copy is included in the LICENSE file that
  309.18 + * accompanied this code).
  309.19 + *
  309.20 + * You should have received a copy of the GNU General Public License version
  309.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  309.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  309.23 + *
  309.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  309.25 + * or visit www.oracle.com if you need additional information or have any
  309.26 + * questions.
  309.27 + */
  309.28 +
  309.29 +/**
  309.30 + * @test
  309.31 + * @bug 6944033
  309.32 + * @summary Tests that PCM_FLOAT encoding is supported
  309.33 + * @compile -source 1.7 PCM_FLOAT_support.java
  309.34 + * @run main PCM_FLOAT_support
  309.35 + * @author Alex Menkov
  309.36 + *
  309.37 + */
  309.38 +
  309.39 +import javax.sound.sampled.AudioFormat.Encoding;
  309.40 +import javax.sound.sampled.AudioSystem;
  309.41 +
  309.42 +
  309.43 +public class PCM_FLOAT_support {
  309.44 +
  309.45 +    static Encoding pcmFloatEnc;
  309.46 +
  309.47 +    static boolean testFailed = false;
  309.48 +
  309.49 +    public static void main(String[] args) throws Exception {
  309.50 +        // 1st checks Encoding.PCM_FLOAT is available
  309.51 +        pcmFloatEnc = Encoding.PCM_FLOAT;
  309.52 +
  309.53 +        Encoding[] encodings = AudioSystem.getTargetEncodings(pcmFloatEnc);
  309.54 +        out("conversion from PCM_FLOAT to " + encodings.length + " encodings:");
  309.55 +        for (Encoding e: encodings) {
  309.56 +            out("  - " + e);
  309.57 +        }
  309.58 +        if (encodings.length == 0) {
  309.59 +            testFailed = true;
  309.60 +        }
  309.61 +
  309.62 +        test(Encoding.PCM_SIGNED);
  309.63 +        test(Encoding.PCM_UNSIGNED);
  309.64 +
  309.65 +        if (testFailed) {
  309.66 +            throw new Exception("test failed");
  309.67 +        }
  309.68 +        out("test passed.");
  309.69 +    }
  309.70 +
  309.71 +    static void out(String s) {
  309.72 +        System.out.println(s);
  309.73 +    }
  309.74 +
  309.75 +    static boolean test(Encoding enc) {
  309.76 +        out("conversion " + enc + " -> PCM_FLOAT:");
  309.77 +        Encoding[] encodings = AudioSystem.getTargetEncodings(enc);
  309.78 +        for (Encoding e: encodings) {
  309.79 +            if (e.equals(pcmFloatEnc)) {
  309.80 +                out("  - OK");
  309.81 +                return true;
  309.82 +            }
  309.83 +        }
  309.84 +        out("  - FAILED (not supported)");
  309.85 +        testFailed = true;
  309.86 +        return false;
  309.87 +    }
  309.88 +
  309.89 +}
   310.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   310.2 +++ b/test/javax/swing/JColorChooser/Test6977726.html	Fri Sep 24 16:41:32 2010 -0700
   310.3 @@ -0,0 +1,8 @@
   310.4 +<html>
   310.5 +<body>
   310.6 +If you don't see the preview panel, then test failed, otherwise it passed.
   310.7 +
   310.8 +<applet width="500" height="400" code="Test6977726.class">
   310.9 +</applet>
  310.10 +</body>
  310.11 +</html>
   311.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   311.2 +++ b/test/javax/swing/JColorChooser/Test6977726.java	Fri Sep 24 16:41:32 2010 -0700
   311.3 @@ -0,0 +1,42 @@
   311.4 +/*
   311.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   311.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   311.7 + *
   311.8 + * This code is free software; you can redistribute it and/or modify it
   311.9 + * under the terms of the GNU General Public License version 2 only, as
  311.10 + * published by the Free Software Foundation.
  311.11 + *
  311.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  311.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  311.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  311.15 + * version 2 for more details (a copy is included in the LICENSE file that
  311.16 + * accompanied this code).
  311.17 + *
  311.18 + * You should have received a copy of the GNU General Public License version
  311.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  311.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  311.21 + *
  311.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  311.23 + * or visit www.oracle.com if you need additional information or have any
  311.24 + * questions.
  311.25 + */
  311.26 +
  311.27 +/*
  311.28 + * @test
  311.29 + * @bug 6977726
  311.30 + * @summary Checks if JColorChooser.setPreviewPanel removes the old one
  311.31 + * @author Sergey Malenkov
  311.32 + * @run applet/manual=yesno Test6977726.html
  311.33 + */
  311.34 +
  311.35 +import javax.swing.JApplet;
  311.36 +import javax.swing.JColorChooser;
  311.37 +import javax.swing.JLabel;
  311.38 +
  311.39 +public class Test6977726 extends JApplet {
  311.40 +    public void init() {
  311.41 +        JColorChooser chooser = new JColorChooser();
  311.42 +        chooser.setPreviewPanel(new JLabel("Text Preview Panel"));
  311.43 +        getContentPane().add(chooser);
  311.44 +    }
  311.45 +}
   312.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   312.2 +++ b/test/javax/swing/border/Test6978482.java	Fri Sep 24 16:41:32 2010 -0700
   312.3 @@ -0,0 +1,197 @@
   312.4 +/*
   312.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   312.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   312.7 + *
   312.8 + * This code is free software; you can redistribute it and/or modify it
   312.9 + * under the terms of the GNU General Public License version 2 only, as
  312.10 + * published by the Free Software Foundation.
  312.11 + *
  312.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  312.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  312.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  312.15 + * version 2 for more details (a copy is included in the LICENSE file that
  312.16 + * accompanied this code).
  312.17 + *
  312.18 + * You should have received a copy of the GNU General Public License version
  312.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  312.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  312.21 + *
  312.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  312.23 + * or visit www.oracle.com if you need additional information or have any
  312.24 + * questions.
  312.25 + */
  312.26 +
  312.27 +/*
  312.28 + * @test
  312.29 + * @bug 6978482
  312.30 + * @summary Tests unchecked casts
  312.31 + * @author Sergey Malenkov
  312.32 + */
  312.33 +
  312.34 +import com.sun.java.swing.plaf.motif.MotifBorders;
  312.35 +import com.sun.java.swing.plaf.windows.WindowsBorders;
  312.36 +
  312.37 +import java.awt.Color;
  312.38 +import java.awt.Component;
  312.39 +import java.awt.Font;
  312.40 +import java.awt.Graphics;
  312.41 +import java.awt.image.BufferedImage;
  312.42 +
  312.43 +import javax.swing.ActionMap;
  312.44 +import javax.swing.JFileChooser;
  312.45 +import javax.swing.JLabel;
  312.46 +import javax.swing.JToggleButton;
  312.47 +import javax.swing.JToolBar;
  312.48 +import javax.swing.border.BevelBorder;
  312.49 +import javax.swing.border.Border;
  312.50 +import javax.swing.border.CompoundBorder;
  312.51 +import javax.swing.border.EmptyBorder;
  312.52 +import javax.swing.border.EtchedBorder;
  312.53 +import javax.swing.border.LineBorder;
  312.54 +import javax.swing.border.MatteBorder;
  312.55 +import javax.swing.border.SoftBevelBorder;
  312.56 +import javax.swing.border.TitledBorder;
  312.57 +import javax.swing.plaf.ActionMapUIResource;
  312.58 +import javax.swing.plaf.BorderUIResource;
  312.59 +import javax.swing.plaf.synth.SynthLookAndFeel;
  312.60 +import javax.swing.plaf.basic.BasicBorders;
  312.61 +import javax.swing.plaf.basic.BasicToolBarUI;
  312.62 +import javax.swing.plaf.metal.MetalBorders;
  312.63 +import javax.swing.plaf.metal.MetalComboBoxEditor;
  312.64 +
  312.65 +import sun.swing.plaf.synth.SynthFileChooserUI;
  312.66 +
  312.67 +public class Test6978482 {
  312.68 +    private static final JLabel LABEL = new JLabel();
  312.69 +    private static final JToolBar TOOLBAR = new JToolBar(); // init non-rollover border
  312.70 +
  312.71 +    private static final Border[] BORDERS = {
  312.72 +            new MotifBorders.BevelBorder(true, Color.BLACK, Color.WHITE),
  312.73 +            new MotifBorders.ButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
  312.74 +            new MotifBorders.FocusBorder(Color.BLACK, Color.WHITE),
  312.75 +            new MotifBorders.FrameBorder(LABEL),
  312.76 +            new MotifBorders.MenuBarBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
  312.77 +            new MotifBorders.MotifPopupMenuBorder(new Font(null, Font.PLAIN, 10), Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
  312.78 +            new MotifBorders.ToggleButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
  312.79 +
  312.80 +            new WindowsBorders.ProgressBarBorder(Color.BLACK, Color.WHITE),
  312.81 +            new WindowsBorders.ToolBarBorder(Color.BLACK, Color.WHITE),
  312.82 +            //- WindowsInternalFrameUI.XPBorder is not accessible: check it visually
  312.83 +            //? WindowsTableHeaderUI.IconBorder is not accessible: check it visually
  312.84 +            //- XPStyle.XPEmptyBorder is not accessible: check it visually
  312.85 +            //- XPStyle.XPFillBorder is not accessible: check it visually
  312.86 +            //- XPStyle.XPImageBorder is not accessible: check it visually
  312.87 +
  312.88 +            new BevelBorder(BevelBorder.RAISED),
  312.89 +            new CompoundBorder(),
  312.90 +            new EmptyBorder(1, 2, 3, 4),
  312.91 +            new EtchedBorder(),
  312.92 +            new LineBorder(Color.BLACK, 2, true),
  312.93 +            new MatteBorder(1, 2, 3, 4, Color.BLACK),
  312.94 +            new SoftBevelBorder(BevelBorder.LOWERED),
  312.95 +            new TitledBorder("4856008"),
  312.96 +
  312.97 +            new BorderUIResource(new EmptyBorder(1, 2, 3, 4)),
  312.98 +
  312.99 +            new BasicBorders.ButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
 312.100 +            new BasicBorders.FieldBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
 312.101 +            new BasicBorders.MarginBorder(),
 312.102 +            new BasicBorders.MenuBarBorder(Color.BLACK, Color.WHITE),
 312.103 +            new BasicBorders.RadioButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
 312.104 +            //+ BasicBorders.RolloverMarginBorder:
 312.105 +            new ToolBar().getRolloverMarginBorder(),
 312.106 +            new BasicBorders.SplitPaneBorder(Color.BLACK, Color.WHITE),
 312.107 +            //+ BasicBorders.SplitPaneDividerBorder:
 312.108 +            BasicBorders.getSplitPaneDividerBorder(),
 312.109 +            new BasicBorders.ToggleButtonBorder(Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.BLACK),
 312.110 +
 312.111 +            new MetalBorders.ButtonBorder(),
 312.112 +            //- MetalBorders.DialogBorder is not accessible: check it visually
 312.113 +            new MetalBorders.Flush3DBorder(),
 312.114 +            //- MetalBorders.FrameBorder is not accessible: check it visually
 312.115 +            new MetalBorders.InternalFrameBorder(),
 312.116 +            new MetalBorders.MenuBarBorder(),
 312.117 +            new MetalBorders.MenuItemBorder(),
 312.118 +            new MetalBorders.OptionDialogBorder(),
 312.119 +            new MetalBorders.PaletteBorder(),
 312.120 +            new MetalBorders.PopupMenuBorder(),
 312.121 +            //- MetalBorders.RolloverMarginBorder is not accessible: check it visually
 312.122 +            new MetalBorders.ScrollPaneBorder(),
 312.123 +            new MetalBorders.TableHeaderBorder(),
 312.124 +            new MetalBorders.ToolBarBorder(),
 312.125 +            //+ MetalComboBoxEditor.EditorBorder:
 312.126 +            new MetalEditor().getEditorBorder(),
 312.127 +
 312.128 +            //- SynthBorder is not accessible: check it visually
 312.129 +            //- SynthScrollPaneUI.ViewportBorder is not accessible: check it visually
 312.130 +
 312.131 +            //? CSSBorder is not accessible: check it visually
 312.132 +            //? CommentView.CommentBorder is not accessible: check it visually
 312.133 +            //- HiddenTagView.EndTagBorder is not accessible: check it visually
 312.134 +            //- HiddenTagView.StartTagBorder is not accessible: check it visually
 312.135 +
 312.136 +            //+ SynthFileChooserUI.UIBorder:
 312.137 +            new SynthFileChooser().getUIBorder(),
 312.138 +    };
 312.139 +
 312.140 +    public static void main(String[] args) {
 312.141 +        Component c = new Component() {};
 312.142 +        c.setBackground(Color.WHITE);
 312.143 +        c.setForeground(Color.BLACK);
 312.144 +        Graphics g = new BufferedImage(1024, 768, BufferedImage.TYPE_INT_RGB).getGraphics();
 312.145 +        g.setClip(0, 0, 1024, 768);
 312.146 +        for (Border border : BORDERS) {
 312.147 +            System.out.println(border.getClass());
 312.148 +            border.getBorderInsets(c);
 312.149 +            border.paintBorder(c, g, 0, 0, 1024, 768);
 312.150 +        }
 312.151 +    }
 312.152 +
 312.153 +    // This class is used to get the instance of BasicBorders.RolloverMarginBorder
 312.154 +    private static class ToolBar extends BasicToolBarUI {
 312.155 +        private Border getRolloverMarginBorder() {
 312.156 +            JToggleButton button = new JToggleButton();
 312.157 +            CompoundBorder border = (CompoundBorder) getNonRolloverBorder(button);
 312.158 +            return border.getInsideBorder();
 312.159 +        }
 312.160 +    }
 312.161 +
 312.162 +    // This class is used to get the instance of MetalComboBoxEditor.EditorBorder
 312.163 +    private static class MetalEditor extends MetalComboBoxEditor {
 312.164 +        private Border getEditorBorder() {
 312.165 +            return editor.getBorder();
 312.166 +        }
 312.167 +    }
 312.168 +
 312.169 +    // This class is used to get the instance of SynthFileChooserUI.UIBorder
 312.170 +    private static class SynthFileChooser extends SynthFileChooserUI {
 312.171 +        private static final JFileChooser CHOOSER = new JFileChooser();
 312.172 +        private String name;
 312.173 +
 312.174 +        private SynthFileChooser() {
 312.175 +            super(CHOOSER);
 312.176 +        }
 312.177 +
 312.178 +        private Border getUIBorder() {
 312.179 +            new SynthLookAndFeel().initialize();
 312.180 +            CHOOSER.setBorder(null);
 312.181 +            installDefaults(CHOOSER);
 312.182 +            return CHOOSER.getBorder();
 312.183 +        }
 312.184 +
 312.185 +        @Override
 312.186 +        protected ActionMap createActionMap() {
 312.187 +            return new ActionMapUIResource();
 312.188 +        }
 312.189 +
 312.190 +        @Override
 312.191 +        public String getFileName() {
 312.192 +            return this.name;
 312.193 +        }
 312.194 +
 312.195 +        @Override
 312.196 +        public void setFileName(String name) {
 312.197 +            this.name = name;
 312.198 +        }
 312.199 +    }
 312.200 +}
   313.1 --- a/test/sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java	Thu Sep 23 17:33:40 2010 -0700
   313.2 +++ b/test/sun/java2d/DirectX/OnScreenRenderingResizeTest/OnScreenRenderingResizeTest.java	Fri Sep 24 16:41:32 2010 -0700
   313.3 @@ -157,7 +157,7 @@
   313.4              if (cnt == 90 && robot != null) {
   313.5                  // area where we blitted to should be either white or green
   313.6                  Point p = frame.getLocationOnScreen();
   313.7 -                p.move(in.left+10, in.top+10);
   313.8 +                p.translate(in.left+10, in.top+10);
   313.9                  BufferedImage bi =
  313.10                      robot.createScreenCapture(
  313.11                          new Rectangle(p.x, p.y, IMAGE_W/2, IMAGE_H/2));
  313.12 @@ -166,7 +166,7 @@
  313.13  
  313.14                  // the are where we didn't render should stay white
  313.15                  p = frame.getLocationOnScreen();
  313.16 -                p.move(in.left, in.top+IMAGE_H+5);
  313.17 +                p.translate(in.left, in.top+IMAGE_H+5);
  313.18                  bi = robot.createScreenCapture(
  313.19                      new Rectangle(p.x, p.y,
  313.20                                    frame.getWidth()-in.left-in.right,
   314.1 --- a/test/sun/net/sdp/ProbeIB.java	Thu Sep 23 17:33:40 2010 -0700
   314.2 +++ b/test/sun/net/sdp/ProbeIB.java	Fri Sep 24 16:41:32 2010 -0700
   314.3 @@ -34,21 +34,16 @@
   314.4  
   314.5  public class ProbeIB {
   314.6      public static void main(String[] args) throws IOException {
   314.7 -        Scanner s = new Scanner(new File("/etc/path_to_inst"));
   314.8 +        Scanner s = new Scanner(new File(args[0]));
   314.9          try {
  314.10              while (s.hasNextLine()) {
  314.11 -                String line = s.nextLine();
  314.12 -                if (line.startsWith("#"))
  314.13 -                    continue;
  314.14 -                String[] fields = line.split("\\s+");
  314.15 -                if (!fields[2].equals("\"ibd\""))
  314.16 -                    continue;
  314.17 -                String name = fields[2].substring(1, fields[2].length()-1) + fields[1];
  314.18 -                NetworkInterface ni = NetworkInterface.getByName(name);
  314.19 +                String link = s.nextLine();
  314.20 +                NetworkInterface ni = NetworkInterface.getByName(link);
  314.21                  if (ni != null) {
  314.22                      Enumeration<InetAddress> addrs = ni.getInetAddresses();
  314.23                      while (addrs.hasMoreElements()) {
  314.24 -                        System.out.println(addrs.nextElement().getHostAddress());
  314.25 +                        InetAddress addr = addrs.nextElement();
  314.26 +                        System.out.println(addr.getHostAddress());
  314.27                      }
  314.28                  }
  314.29              }
   315.1 --- a/test/sun/net/sdp/sanity.sh	Thu Sep 23 17:33:40 2010 -0700
   315.2 +++ b/test/sun/net/sdp/sanity.sh	Fri Sep 24 16:41:32 2010 -0700
   315.3 @@ -33,14 +33,15 @@
   315.4      echo "This is a Solaris-only test"
   315.5      exit 0
   315.6  fi
   315.7 -SDPADM=/usr/sbin/sdpadm
   315.8 -if [ ! -f ${SDPADM} ]; then
   315.9 -    echo "SDP not available"
  315.10 -    exit 0
  315.11 -fi
  315.12 -${SDPADM} status|grep Enabled
  315.13 -if [ $? != 0 ]; then 
  315.14 -    echo "SDP not enabled"
  315.15 +
  315.16 +IB_LINKS=ib.links
  315.17 +IB_ADDRS=ib.addrs
  315.18 +
  315.19 +# Display IB partition link information
  315.20 +# (requires Solaris 11, will fail on Solaris 10)
  315.21 +/usr/sbin/dladm show-part -o LINK -p > ${IB_LINKS}
  315.22 +if [ $? != 0 ]; then
  315.23 +    echo "Unable to get IB parition link information"
  315.24      exit 0
  315.25  fi
  315.26  
  315.27 @@ -56,13 +57,13 @@
  315.28  export CLASSPATH
  315.29  
  315.30  # Probe for IP addresses plumbed to IB interfaces
  315.31 -$JAVA -Djava.net.preferIPv4Stack=true ProbeIB > ib_addrs
  315.32 +$JAVA -Djava.net.preferIPv4Stack=true ProbeIB ${IB_LINKS} > ${IB_ADDRS}
  315.33  
  315.34  # Create sdp.conf
  315.35  SDPCONF=sdp.conf
  315.36  rm ${SDPCONF}
  315.37  touch ${SDPCONF}
  315.38 -cat ib_addrs | while read ADDR
  315.39 +cat ${IB_ADDRS} | while read ADDR
  315.40  do
  315.41     echo "bind ${ADDR} *" > ${SDPCONF}
  315.42     echo "connect ${ADDR} *" >> ${SDPCONF}
   316.1 --- a/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java	Thu Sep 23 17:33:40 2010 -0700
   316.2 +++ b/test/sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java	Fri Sep 24 16:41:32 2010 -0700
   316.3 @@ -38,7 +38,7 @@
   316.4  
   316.5  public class ChunkedEncodingTest{
   316.6      private static MessageDigest serverDigest, clientDigest;
   316.7 -    private static byte[] serverMac, clientMac;
   316.8 +    private static volatile byte[] serverMac, clientMac;
   316.9  
  316.10      static void client(String u) throws Exception {
  316.11          URL url = new URL(u);
  316.12 @@ -106,7 +106,7 @@
  316.13              while (is.read() != -1);
  316.14              is.close();
  316.15  
  316.16 -            t.sendResponseHeaders (200, MESSAGE_LENGTH);
  316.17 +            t.sendResponseHeaders (200, 0);
  316.18              OutputStream os = t.getResponseBody();
  316.19              DigestOutputStream dos = new DigestOutputStream(os, serverDigest);
  316.20  
   317.1 --- a/test/sun/security/tools/jarsigner/emptymanifest.sh	Thu Sep 23 17:33:40 2010 -0700
   317.2 +++ b/test/sun/security/tools/jarsigner/emptymanifest.sh	Fri Sep 24 16:41:32 2010 -0700
   317.3 @@ -1,5 +1,5 @@
   317.4  #
   317.5 -# Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   317.6 +# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
   317.7  # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   317.8  #
   317.9  # This code is free software; you can redistribute it and/or modify it
  317.10 @@ -49,13 +49,23 @@
  317.11  
  317.12  KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
  317.13  JAR=$TESTJAVA${FS}bin${FS}jar
  317.14 +JAVA=$TESTJAVA${FS}bin${FS}java
  317.15 +JAVAC=$TESTJAVA${FS}bin${FS}javac
  317.16  JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
  317.17  
  317.18  rm $KS $JFILE
  317.19  echo A > A
  317.20  echo B > B
  317.21  mkdir META-INF
  317.22 -printf "\r\n" > META-INF${FS}MANIFEST.MF
  317.23 +cat <<EOF > CrLf.java
  317.24 +class CrLf {
  317.25 +  public static void main(String[] args) throws Exception {
  317.26 +    System.out.write(new byte[] {'\r', '\n'});
  317.27 +  }
  317.28 +}
  317.29 +EOF
  317.30 +$JAVAC CrLf.java
  317.31 +$JAVA CrLf > META-INF${FS}MANIFEST.MF
  317.32  zip $JFILE META-INF${FS}MANIFEST.MF A B
  317.33  
  317.34  $KT -alias a -dname CN=a -keyalg rsa -genkey -validity 300
   318.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   318.2 +++ b/test/tools/launcher/MiscTests.java	Fri Sep 24 16:41:32 2010 -0700
   318.3 @@ -0,0 +1,90 @@
   318.4 +/*
   318.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   318.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   318.7 + *
   318.8 + * This code is free software; you can redistribute it and/or modify it
   318.9 + * under the terms of the GNU General Public License version 2 only, as
  318.10 + * published by the Free Software Foundation.
  318.11 + *
  318.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
  318.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  318.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  318.15 + * version 2 for more details (a copy is included in the LICENSE file that
  318.16 + * accompanied this code).
  318.17 + *
  318.18 + * You should have received a copy of the GNU General Public License version
  318.19 + * 2 along with this work; if not, write to the Free Software Foundation,
  318.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  318.21 + *
  318.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  318.23 + * or visit www.oracle.com if you need additional information or have any
  318.24 + * questions.
  318.25 + */
  318.26 +
  318.27 +/*
  318.28 + * @test
  318.29 + * @bug 6856415 6981001
  318.30 + * @summary Miscellaneous tests, Exceptions, EnsureJRE etc.
  318.31 + * @compile -XDignore.symbol.file MiscTests.java TestHelper.java
  318.32 + * @run main MiscTests
  318.33 + */
  318.34 +
  318.35 +
  318.36 +import java.io.File;
  318.37 +import java.io.FileNotFoundException;
  318.38 +import java.util.HashMap;
  318.39 +import java.util.Map;
  318.40 +
  318.41 +
  318.42 +public class MiscTests {
  318.43 +
  318.44 +    // 6856415: Checks to ensure that proper exceptions are thrown by java
  318.45 +    static void test6856415() {
  318.46 +        // No pkcs library on win-x64, so we bail out.
  318.47 +        if (TestHelper.is64Bit && TestHelper.isWindows) {
  318.48 +            return;
  318.49 +        }
  318.50 +        StringBuilder sb = new StringBuilder();
  318.51 +        sb.append("public static void main(String... args) {\n");
  318.52 +        sb.append("java.security.Provider p = new sun.security.pkcs11.SunPKCS11(args[0]);\n");
  318.53 +        sb.append("java.security.Security.insertProviderAt(p, 1);\n");
  318.54 +        sb.append("}");
  318.55 +        File testJar = new File("Foo.jar");
  318.56 +        testJar.delete();
  318.57 +        try {
  318.58 +            TestHelper.createJar(testJar, sb.toString());
  318.59 +        } catch (FileNotFoundException fnfe) {
  318.60 +            throw new RuntimeException(fnfe);
  318.61 +        }
  318.62 +        TestHelper.TestResult tr = TestHelper.doExec(TestHelper.javaCmd,
  318.63 +                "-Djava.security.manager", "-jar", testJar.getName(), "foo.bak");
  318.64 +        for (String s : tr.testOutput) {
  318.65 +            System.out.println(s);
  318.66 +    }
  318.67 +        if (!tr.contains("java.security.AccessControlException:" +
  318.68 +                " access denied (\"java.lang.RuntimePermission\"" +
  318.69 +                " \"accessClassInPackage.sun.security.pkcs11\")")) {
  318.70 +            System.out.println(tr.status);
  318.71 +        }
  318.72 +    }
  318.73 +    // 6981001 : Check EnsureJreInstallation is ok, note we cannot
  318.74 +    // thoroughly test this function, we simply do our best.
  318.75 +    static void test6981001() {
  318.76 +        if (TestHelper.is64Bit || !TestHelper.isWindows) {
  318.77 +            return;
  318.78 +        }
  318.79 +        Map<String, String> env = new HashMap<String, String>();
  318.80 +        env.put("_JAVA_LAUNCHER_DEBUG", "true");
  318.81 +        TestHelper.TestResult tr = TestHelper.doExec(env, TestHelper.javaCmd);
  318.82 +        if (!tr.contains(TestHelper.JAVAHOME + "\\lib\\bundles")) {
  318.83 +            System.out.println(tr.status);
  318.84 +        }
  318.85 +    }
  318.86 +    public static void main(String... args) {
  318.87 +        test6856415();
  318.88 +        test6981001();
  318.89 +        if (TestHelper.testExitValue != 0) {
  318.90 +            throw new Error(TestHelper.testExitValue + " tests failed");
  318.91 +    }
  318.92 +}
  318.93 +}
   319.1 --- a/test/tools/launcher/VerifyExceptions.java	Thu Sep 23 17:33:40 2010 -0700
   319.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   319.3 @@ -1,65 +0,0 @@
   319.4 -/*
   319.5 - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
   319.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   319.7 - *
   319.8 - * This code is free software; you can redistribute it and/or modify it
   319.9 - * under the terms of the GNU General Public License version 2 only, as
  319.10 - * published by the Free Software Foundation.
  319.11 - *
  319.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
  319.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  319.14 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  319.15 - * version 2 for more details (a copy is included in the LICENSE file that
  319.16 - * accompanied this code).
  319.17 - *
  319.18 - * You should have received a copy of the GNU General Public License version
  319.19 - * 2 along with this work; if not, write to the Free Software Foundation,
  319.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  319.21 - *
  319.22 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  319.23 - * or visit www.oracle.com if you need additional information or have any
  319.24 - * questions.
  319.25 - */
  319.26 -
  319.27 -/*
  319.28 - * @test
  319.29 - * @bug 6856415
  319.30 - * @summary Checks to ensure that proper exceptions are thrown by java
  319.31 - * @compile -XDignore.symbol.file VerifyExceptions.java TestHelper.java
  319.32 - * @run main VerifyExceptions
  319.33 - */
  319.34 -
  319.35 -
  319.36 -import java.io.File;
  319.37 -import java.io.FileNotFoundException;
  319.38 -
  319.39 -
  319.40 -public class VerifyExceptions {
  319.41 -
  319.42 -    static void test6856415() {
  319.43 -        // No pkcs library on win-x64, so we bail out.
  319.44 -        if (TestHelper.is64Bit && TestHelper.isWindows) {
  319.45 -            return;
  319.46 -        }
  319.47 -        StringBuilder sb = new StringBuilder();
  319.48 -        sb.append("public static void main(String... args) {\n");
  319.49 -        sb.append("java.security.Provider p = new sun.security.pkcs11.SunPKCS11(args[0]);\n");
  319.50 -        sb.append("java.security.Security.insertProviderAt(p, 1);\n");
  319.51 -        sb.append("}");
  319.52 -        File testJar = new File("Foo.jar");
  319.53 -        testJar.delete();
  319.54 -        try {
  319.55 -            TestHelper.createJar(testJar, sb.toString());
  319.56 -        } catch (FileNotFoundException fnfe) {
  319.57 -            throw new RuntimeException(fnfe);
  319.58 -        }
  319.59 -        TestHelper.TestResult tr = TestHelper.doExec(TestHelper.javacCmd,
  319.60 -                "-Djava.security.manager", "-jar", testJar.getName(), "foo.bak");
  319.61 -        tr.checkNegative();
  319.62 -        tr.contains("Exception in thread \"main\" java.security.AccessControlException: access denied (\"java.lang.RuntimePermission\" \"accessClassInPackage.sun.security.pkcs11\")\")");
  319.63 -    }
  319.64 -
  319.65 -    public static void main(String... args) {
  319.66 -        test6856415();
  319.67 -    }
  319.68 -}