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<Path> stream = dir.newDirectoryStream();
81.32 - * try {
81.33 + * try (DirectoryStream<Path> 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<Path> listSourceFiles(Path dir) throws IOException {
81.104 + * List<Path> result = new ArrayList<Path>();
81.105 + * try (DirectoryStream<Path> 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<String,Class<?>> 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<String,Class<?>> = new HashMap<String,Class<?>>();
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— 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— 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— 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> </th><th>modern replacement</th></tr>
116.1482 + * <tr><td>art-lojban</td><td> </td><td>jbo</td></tr>
116.1483 + * <tr><td>i-ami</td><td> </td><td>ami</td></tr>
116.1484 + * <tr><td>i-bnn</td><td> </td><td>bnn</td></tr>
116.1485 + * <tr><td>i-hak</td><td> </td><td>hak</td></tr>
116.1486 + * <tr><td>i-klingon</td><td> </td><td>tlh</td></tr>
116.1487 + * <tr><td>i-lux</td><td> </td><td>lb</td></tr>
116.1488 + * <tr><td>i-navajo</td><td> </td><td>nv</td></tr>
116.1489 + * <tr><td>i-pwn</td><td> </td><td>pwn</td></tr>
116.1490 + * <tr><td>i-tao</td><td> </td><td>tao</td></tr>
116.1491 + * <tr><td>i-tay</td><td> </td><td>tay</td></tr>
116.1492 + * <tr><td>i-tsu</td><td> </td><td>tsu</td></tr>
116.1493 + * <tr><td>no-bok</td><td> </td><td>nb</td></tr>
116.1494 + * <tr><td>no-nyn</td><td> </td><td>nn</td></tr>
116.1495 + * <tr><td>sgn-BE-FR</td><td> </td><td>sfb</td></tr>
116.1496 + * <tr><td>sgn-BE-NL</td><td> </td><td>vgt</td></tr>
116.1497 + * <tr><td>sgn-CH-DE</td><td> </td><td>sgg</td></tr>
116.1498 + * <tr><td>zh-guoyu</td><td> </td><td>cmn</td></tr>
116.1499 + * <tr><td>zh-hakka</td><td> </td><td>hak</td></tr>
116.1500 + * <tr><td>zh-min-nan</td><td> </td><td>nan</td></tr>
116.1501 + * <tr><td>zh-xiang</td><td> </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> </th><th>converts to</th></tr>
116.1511 + * <tr><td>cel-gaulish</td><td> </td><td>xtg-x-cel-gaulish</td></tr>
116.1512 + * <tr><td>en-GB-oed</td><td> </td><td>en-GB-x-oed</td></tr>
116.1513 + * <tr><td>i-default</td><td> </td><td>en-x-i-default</td></tr>
116.1514 + * <tr><td>i-enochian</td><td> </td><td>und-x-i-enochian</td></tr>
116.1515 + * <tr><td>i-mingo</td><td> </td><td>see-x-i-mingo</td></tr>
116.1516 + * <tr><td>zh-min</td><td> </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å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>™</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(×tamp, 1, sizeof(icDateTimeNumber), Icc) != sizeof(icDateTimeNumber))
187.2468 - return FALSE;
187.2469 -
187.2470 - DecodeDateTimeNumber(×tamp, 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, ×tamp, sizeof(cmsDateTimeNumber), 1) != 1) return NULL;
200.1296 +
200.1297 + _cmsDecodeDateTimeNumber(×tamp, 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(×tamp, DateTime);
200.1313 + if (!io ->Write(io, sizeof(cmsDateTimeNumber), ×tamp)) 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 -}