# HG changeset patch # User duke # Date 1499265434 -7200 # Node ID 0be478749d097a2205cd250eafb09cfb71fd2b3b # Parent 9b4457aa27c8a5fd6465527327040aaf94e8751c# Parent 6c92b29dca748c470e42aad23ff4d6180d66fdac Merge diff -r 9b4457aa27c8 -r 0be478749d09 .hgtags-top-repo --- a/.hgtags-top-repo Thu May 22 09:37:44 2008 -0700 +++ b/.hgtags-top-repo Wed Jul 05 16:37:14 2017 +0200 @@ -1,3 +1,4 @@ cfeea66a3fa8ca3686a7cfa2d0ce8ab0169f168d jdk7-b24 cbc8ad9dd0e085a607427ea35411990982f19a36 jdk7-b25 9410f77cc30c604d1caf7c9fe3a57fa19e1acbe8 jdk7-b26 +11b4dc9f2be3523ef989a0db8459eb56b3045c3a jdk7-b27 diff -r 9b4457aa27c8 -r 0be478749d09 corba/.hgtags --- a/corba/.hgtags Thu May 22 09:37:44 2008 -0700 +++ b/corba/.hgtags Wed Jul 05 16:37:14 2017 +0200 @@ -1,3 +1,4 @@ 55540e827aef970ecc010b7e06b912d991c8e3ce jdk7-b24 5e61d5df62586474414d1058e9186441aa908f51 jdk7-b25 0043eb3d4e628f049ff80a8c223b5657136085e7 jdk7-b26 +e84e9018bebbf3e5bafc5706e7882a15cb1c7d99 jdk7-b27 diff -r 9b4457aa27c8 -r 0be478749d09 hotspot/.hgtags --- a/hotspot/.hgtags Thu May 22 09:37:44 2008 -0700 +++ b/hotspot/.hgtags Wed Jul 05 16:37:14 2017 +0200 @@ -1,3 +1,4 @@ a61af66fc99eb5ec9d50c05b0c599757b1289ceb jdk7-b24 7836be3e92d0a4f9ee7566f602c91f5609534e66 jdk7-b25 ad0b851458ff9d1d490ed2d79bb84f75a9fdb753 jdk7-b26 +e3d2692f8442e2d951166dc9bd9a330684754438 jdk7-b27 diff -r 9b4457aa27c8 -r 0be478749d09 jdk/.hgtags --- a/jdk/.hgtags Thu May 22 09:37:44 2008 -0700 +++ b/jdk/.hgtags Wed Jul 05 16:37:14 2017 +0200 @@ -1,3 +1,4 @@ 37a05a11f281b4d238e2f9e7ebb67c63f64d0e77 jdk7-b24 75fca0b0ab83ab1392e615910cea020f66535390 jdk7-b25 fb57027902e04ecafceae31a605e69b436c23d57 jdk7-b26 +3e599d98875ddf919c8ea11cff9b3a99ba631a9b jdk7-b27 diff -r 9b4457aa27c8 -r 0be478749d09 jdk/make/common/internal/BinaryPlugs.gmk --- a/jdk/make/common/internal/BinaryPlugs.gmk Thu May 22 09:37:44 2008 -0700 +++ b/jdk/make/common/internal/BinaryPlugs.gmk Wed Jul 05 16:37:14 2017 +0200 @@ -126,44 +126,10 @@ com/sun/media/sound/SimpleInputDeviceProvider\$$InputDeviceInfo.class \ com/sun/media/sound/SimpleInputDeviceProvider.class -PLUG_AWT_CLASS_NAMES = \ -java/awt/color/CMMException.class \ -java/awt/color/ColorSpace.class \ -java/awt/color/ICC_ColorSpace.class \ -java/awt/color/ICC_Profile\$$1.class \ -java/awt/color/ICC_Profile\$$2.class \ -java/awt/color/ICC_Profile\$$3.class \ -java/awt/color/ICC_Profile.class \ -java/awt/color/ICC_ProfileGray.class \ -java/awt/color/ICC_ProfileRGB.class \ -java/awt/image/BandedSampleModel.class \ -java/awt/image/ColorConvertOp.class \ -java/awt/image/ComponentSampleModel.class \ -java/awt/image/DataBuffer\$$1.class \ -java/awt/image/DataBuffer.class \ -java/awt/image/DataBufferByte.class \ -java/awt/image/DataBufferInt.class \ -java/awt/image/DataBufferShort.class \ -java/awt/image/DataBufferUShort.class \ -java/awt/image/MultiPixelPackedSampleModel.class \ -java/awt/image/Raster.class \ -java/awt/image/RenderedImage.class \ -java/awt/image/SampleModel.class \ -java/awt/image/SinglePixelPackedSampleModel.class \ -java/awt/image/WritableRaster.class \ -java/awt/image/WritableRenderedImage.class \ -java/awt/image/renderable/ContextualRenderedImageFactory.class \ -java/awt/image/renderable/ParameterBlock.class \ -java/awt/image/renderable/RenderContext.class \ -java/awt/image/renderable/RenderableImage.class \ -java/awt/image/renderable/RenderableImageOp.class \ -java/awt/image/renderable/RenderableImageProducer.class \ -java/awt/image/renderable/RenderedImageFactory.class - # Class list temp files (used by both import and export of plugs) PLUG_TEMPDIR=$(ABS_TEMPDIR)/plugs -PLUG_CLASS_AREAS = jmf sound awt +PLUG_CLASS_AREAS = jmf sound PLUG_CLISTS = $(PLUG_CLASS_AREAS:%=$(PLUG_TEMPDIR)/%.clist) # Create jargs file command @@ -186,11 +152,6 @@ @for i in $(PLUG_SOUND_CLASS_NAMES) ; do \ $(ECHO) "$$i" >> $@ ; \ done -$(PLUG_TEMPDIR)/awt.clist: - @$(prep-target) - @for i in $(PLUG_AWT_CLASS_NAMES) ; do \ - $(ECHO) "$$i" >> $@ ; \ - done $(PLUG_TEMPDIR)/all.clist: $(PLUG_CLISTS) @$(prep-target) $(CAT) $(PLUG_CLISTS) > $@ @@ -198,8 +159,6 @@ $(plug-create-jargs) $(PLUG_TEMPDIR)/sound.jargs: $(PLUG_TEMPDIR)/sound.clist $(plug-create-jargs) -$(PLUG_TEMPDIR)/awt.jargs: $(PLUG_TEMPDIR)/awt.clist - $(plug-create-jargs) $(PLUG_TEMPDIR)/all.jargs: $(PLUG_TEMPDIR)/all.clist $(plug-create-jargs) @@ -235,15 +194,12 @@ $(call import-binary-plug-classes,$(PLUG_TEMPDIR)/jmf.clist) import-binary-plug-sound-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/sound.clist $(call import-binary-plug-classes,$(PLUG_TEMPDIR)/sound.clist) -import-binary-plug-awt-classes: $(PLUG_IMPORT_JARFILE) $(PLUG_TEMPDIR)/awt.clist - $(call import-binary-plug-classes,$(PLUG_TEMPDIR)/awt.clist) # Import all classes from the jar file import-binary-plug-jar: \ import-binary-plug-jmf-classes \ - import-binary-plug-sound-classes \ - import-binary-plug-awt-classes + import-binary-plug-sound-classes # Import native libraries @@ -286,7 +242,6 @@ import-binary-plug-jar \ import-binary-plug-jmf-classes \ import-binary-plug-sound-classes \ - import-binary-plug-awt-classes \ import-binary-plug-jsound-library else # !OPENJDK diff -r 9b4457aa27c8 -r 0be478749d09 jdk/make/common/shared/Defs-utils.gmk --- a/jdk/make/common/shared/Defs-utils.gmk Thu May 22 09:37:44 2008 -0700 +++ b/jdk/make/common/shared/Defs-utils.gmk Wed Jul 05 16:37:14 2017 +0200 @@ -148,13 +148,15 @@ ECHO = $(UNIXCOMMAND_PATH)echo -e ZIPEXE = $(UNIXCOMMAND_PATH)zip UNZIP = $(UNIXCOMMAND_PATH)unzip + # Some CYGWIN nawk versions require BINMODE=w for proper '\r' interpretation + NAWK = $(UNIXCOMMAND_PATH)awk -v BINMODE=w else ZIPEXE = $(UTILS_DEVTOOL_PATH)zip UNZIP = $(UTILS_DEVTOOL_PATH)unzip + NAWK = $(UNIXCOMMAND_PATH)awk endif # Re-define some utilities LEX =# override GNU Make intrinsic: no lex on windows - NAWK = $(UNIXCOMMAND_PATH)awk endif # Linux specific diff -r 9b4457aa27c8 -r 0be478749d09 jdk/make/java/awt/Makefile --- a/jdk/make/java/awt/Makefile Thu May 22 09:37:44 2008 -0700 +++ b/jdk/make/java/awt/Makefile Wed Jul 05 16:37:14 2017 +0200 @@ -28,24 +28,12 @@ PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk -# WARNING: Make sure the OPENJDK plugs are up-to-date, see make/common/internal/BinaryPlugs.gmk # # Files # AUTO_FILES_JAVA_DIRS = java/awt sun/awt/geom -# -# Specific to OPENJDK -# -ifdef OPENJDK - -build: import-binary-plug-awt-classes - -include $(BUILDDIR)/common/internal/BinaryPlugs.gmk - -endif - build: properties cursors # diff -r 9b4457aa27c8 -r 0be478749d09 jdk/make/java/java/Makefile --- a/jdk/make/java/java/Makefile Thu May 22 09:37:44 2008 -0700 +++ b/jdk/make/java/java/Makefile Wed Jul 05 16:37:14 2017 +0200 @@ -394,7 +394,7 @@ $(GENSRCDIR)/sun/util/CoreResourceBundleControl.java: \ $(SHARE_SRC)/classes/sun/util/CoreResourceBundleControl-XLocales.java $(LOCALES_GEN_SH) @$(prep-target) - NAWK=$(NAWK) SED=$(SED) $(SH) $(LOCALES_GEN_SH) "$(JRE_NONEXIST_LOCALES)" \ + NAWK="$(NAWK)" SED="$(SED)" $(SH) $(LOCALES_GEN_SH) "$(JRE_NONEXIST_LOCALES)" \ $< $@ clean:: $(RM) $(GENSRCDIR)/sun/util/CoreResourceBundleControl.java diff -r 9b4457aa27c8 -r 0be478749d09 jdk/make/java/nio/Makefile --- a/jdk/make/java/nio/Makefile Thu May 22 09:37:44 2008 -0700 +++ b/jdk/make/java/nio/Makefile Wed Jul 05 16:37:14 2017 +0200 @@ -191,7 +191,7 @@ GEN_BUFFER_SH = genBuffer.sh -GEN_BUFFER_CMD = SPP="$(SPP_CMD)" NAWK=$(NAWK) SED=$(SED) SH=$(SH) \ +GEN_BUFFER_CMD = SPP="$(SPP_CMD)" NAWK="$(NAWK)" SED="$(SED)" SH="$(SH)" \ $(SH) $(GEN_BUFFER_SH) # Public abstract buffer classes @@ -582,7 +582,7 @@ GEN_CODER_SH = genCoder.sh -GEN_CODER_CMD = SPP="$(SPP_CMD)" SED=$(SED) NAWK=$(NAWK) SH=$(SH) $(SH) $(GEN_CODER_SH) +GEN_CODER_CMD = SPP="$(SPP_CMD)" SED="$(SED)" NAWK="$(NAWK)" SH="$(SH)" $(SH) $(GEN_CODER_SH) $(CS_GEN)/CharsetDecoder.java: $(CS_SRC)/Charset-X-Coder.java $(GEN_CODER_SH) $(prep-target) @@ -602,7 +602,7 @@ GEN_EX_SH = genExceptions.sh -GEN_EX_CMD = NAWK=$(NAWK) SH=$(SH) $(SH) $(GEN_EX_SH) +GEN_EX_CMD = NAWK="$(NAWK)" SH="$(SH)" $(SH) $(GEN_EX_SH) $(CH_GEN)/%Exception.java: genExceptions.sh $(CH_SRC)/exceptions $(prep-target) @@ -635,7 +635,7 @@ $(HASHER_JARFILE) $(SCS_SRC)/standard-charsets $(prep-target) @$(RM) $@.temp - NAWK=$(NAWK) TEMPDIR=$(TEMPDIR) SH=$(SH) \ + NAWK="$(NAWK)" TEMPDIR="$(TEMPDIR)" SH="$(SH)" \ HASHER="$(BOOT_JAVA_CMD) -jar $(HASHER_JARFILE)" \ $(SH) -e genCharsetProvider.sh $(SCS_SRC)/standard-charsets $(SCS_GEN) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/make/sun/cmm/Makefile --- a/jdk/make/sun/cmm/Makefile Thu May 22 09:37:44 2008 -0700 +++ b/jdk/make/sun/cmm/Makefile Wed Jul 05 16:37:14 2017 +0200 @@ -41,12 +41,8 @@ ICCPROFILE_DEST_DIR = $(LIBDIR)/cmm iccprofiles: $(ICCPROFILE_DEST_DIR)/sRGB.pf $(ICCPROFILE_DEST_DIR)/GRAY.pf \ - $(ICCPROFILE_DEST_DIR)/CIEXYZ.pf - -ifndef OPENJDK -iccprofiles: $(ICCPROFILE_DEST_DIR)/PYCC.pf \ - $(ICCPROFILE_DEST_DIR)/LINEAR_RGB.pf -endif + $(ICCPROFILE_DEST_DIR)/CIEXYZ.pf $(ICCPROFILE_DEST_DIR)/PYCC.pf \ + $(ICCPROFILE_DEST_DIR)/LINEAR_RGB.pf $(ICCPROFILE_DEST_DIR)/sRGB.pf: $(ICCPROFILE_SRC_DIR)/sRGB.pf $(RM) $(ICCPROFILE_DEST_DIR)/sRGB.pf diff -r 9b4457aa27c8 -r 0be478749d09 jdk/make/sun/font/FILES_c.gmk --- a/jdk/make/sun/font/FILES_c.gmk Thu May 22 09:37:44 2008 -0700 +++ b/jdk/make/sun/font/FILES_c.gmk Wed Jul 05 16:37:14 2017 +0200 @@ -113,7 +113,9 @@ ifeq ($(PLATFORM),windows) -FILES_c_platform = fontpath.c +FILES_c_platform = fontpath.c \ + lcdglyph.c + FILES_cpp_platform = D3DTextRenderer.cpp else FILES_c_platform = X11FontScaler.c \ diff -r 9b4457aa27c8 -r 0be478749d09 jdk/make/sun/font/Makefile --- a/jdk/make/sun/font/Makefile Thu May 22 09:37:44 2008 -0700 +++ b/jdk/make/sun/font/Makefile Wed Jul 05 16:37:14 2017 +0200 @@ -63,6 +63,7 @@ java/awt/Font.java \ java/text/Bidi.java \ sun/font/FileFont.java \ + sun/font/FileFontStrike.java \ sun/font/FontManager.java \ sun/font/GlyphList.java \ sun/font/NativeFont.java \ diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java --- a/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Wed Jul 05 16:37:14 2017 +0200 @@ -233,7 +233,6 @@ MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException { - ObjectName logicalName = name; Class theClass; if (className == null) { @@ -519,8 +518,7 @@ QueryExp query) { // Query the MBeans on the repository // - Set list = null; - list = repository.query(name, query); + Set list = repository.query(name, query); if (queryByRepo) { // The repository performs the filtering @@ -576,8 +574,7 @@ private Set queryNamesImpl(ObjectName name, QueryExp query) { // Query the MBeans on the repository // - Set list = null; - list = repository.query(name, query); + Set list = repository.query(name, query); if (queryByRepo) { // The repository performs the filtering @@ -1042,7 +1039,7 @@ if (registerFailed && moi instanceof DynamicMBean2) ((DynamicMBean2) moi).registerFailed(); try { - moi.postRegister(new Boolean(registrationDone)); + moi.postRegister(registrationDone); } catch (RuntimeException e) { throw new RuntimeMBeanException(e, "RuntimeException thrown in postRegister method"); @@ -1094,8 +1091,7 @@ IllegalArgumentException("Object name cannot be null"), "Exception occurred trying to get an MBean"); } - DynamicMBean obj = null; - obj = repository.retrieve(name); + DynamicMBean obj = repository.retrieve(name); if (obj == null) { if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) { MBEANSERVER_LOGGER.logp(Level.FINER, @@ -1568,7 +1564,6 @@ query.setMBeanServer(server); try { for (NamedObject no : list) { - final DynamicMBean obj = no.getObject(); boolean res; try { res = query.apply(no.getName()); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Jul 05 16:37:14 2017 +0200 @@ -205,7 +205,7 @@ */ public Object instantiate(Class theClass) throws ReflectionException, MBeanException { - Object moi = null; + Object moi; // ------------------------------ @@ -265,7 +265,7 @@ // ------------------------------ // ------------------------------ final Class[] tab; - Object moi= null; + Object moi; try { // Build the signature of the method // @@ -283,8 +283,7 @@ } // Query the metadata service to get the right constructor - Constructor cons = null; - cons = findConstructor(theClass, tab); + Constructor cons = findConstructor(theClass, tab); if (cons == null) { throw new ReflectionException(new @@ -408,7 +407,7 @@ throw new RuntimeOperationsException(new IllegalArgumentException(), "Null className passed in parameter"); } - Class theClass = null; + Class theClass; if (loaderName == null) { // Load the class using the agent class loader theClass = findClass(className, loader); @@ -621,7 +620,7 @@ static Class loadClass(String className, ClassLoader loader) throws ReflectionException { - Class theClass = null; + Class theClass; if (className == null) { throw new RuntimeOperationsException(new IllegalArgumentException("The class name cannot be null"), diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/com/sun/jmx/mbeanserver/Repository.java --- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Wed Jul 05 16:37:14 2017 +0200 @@ -89,7 +89,6 @@ /* This class is used to match an ObjectName against a pattern. */ private final static class ObjectNamePattern { - private final char[] domain; private final String[] keys; private final String[] values; private final String properties; @@ -106,8 +105,7 @@ * @param pattern The ObjectName pattern under examination. **/ public ObjectNamePattern(ObjectName pattern) { - this(pattern.getDomain(), - pattern.isPropertyListPattern(), + this(pattern.isPropertyListPattern(), pattern.isPropertyValuePattern(), pattern.getCanonicalKeyPropertyListString(), pattern.getKeyPropertyList(), @@ -124,13 +122,11 @@ * @param keyPropertyList pattern.getKeyPropertyList(). * @param pattern The ObjectName pattern under examination. **/ - ObjectNamePattern(String domain, - boolean propertyListPattern, + ObjectNamePattern(boolean propertyListPattern, boolean propertyValuePattern, String canonicalProps, Map keyPropertyList, ObjectName pattern) { - this.domain = domain.toCharArray(); this.isPropertyListPattern = propertyListPattern; this.isPropertyValuePattern = propertyValuePattern; this.properties = canonicalProps; @@ -538,7 +534,7 @@ // "domain:*", "domain:[key=value],*" : names in the specified domain // Surely one of the most frequent case ... query on the whole world - ObjectName name = null; + ObjectName name; if (pattern == null || pattern.getCanonicalName().length() == 0 || pattern.equals(ObjectName.WILDCARD)) @@ -660,7 +656,7 @@ * @return Number of MBeans. */ public Integer getCount() { - return new Integer(nbElements); + return nbElements; } /** @@ -669,7 +665,7 @@ * * @return A string giving the name of the default domain name. */ - public String getDefaultDomain() { + public String getDefaultDomain() { return domain; } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java --- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ClientNotifForwarder.java Wed Jul 05 16:37:14 2017 +0200 @@ -435,7 +435,6 @@ clientSequenceNumber = nr.getNextSequenceNumber(); - final int size = infoList.size(); listeners = new HashMap(); for (int i = 0 ; i < len ; i++) { @@ -792,9 +791,6 @@ private Thread currentFetchThread; - // admin stuff - private boolean inited = false; - // state /** * This state means that a thread is being created for fetching and forwarding notifications. diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java --- a/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Wed Jul 05 16:37:14 2017 +0200 @@ -269,7 +269,7 @@ ", the maxNotifications is " + maxNotifications); } - NotificationResult nr = null; + NotificationResult nr; final long t = Math.min(connectionTimeout, timeout); try { nr = notifBuffer.fetchNotifications(bufferFilter, @@ -322,7 +322,7 @@ private Integer getListenerID() { synchronized(listenerCounterLock) { - return new Integer(listenerCounter++); + return listenerCounter++; } } @@ -336,7 +336,7 @@ SecurityManager sm = System.getSecurityManager(); if (sm != null) { AccessControlContext acc = AccessController.getContext(); - ObjectInstance oi = null; + ObjectInstance oi; try { oi = AccessController.doPrivileged( new PrivilegedExceptionAction() { diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java --- a/jdk/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/remote/security/FileLoginModule.java Wed Jul 05 16:37:14 2017 +0200 @@ -437,7 +437,7 @@ // get the username and password getUsernamePassword(usePasswdFromSharedState); - String localPassword = null; + String localPassword; // userCredentials is initialized in login() if (((localPassword = userCredentials.getProperty(username)) == null) || @@ -487,10 +487,14 @@ throw ace; } } - BufferedInputStream bis = new BufferedInputStream(fis); - userCredentials = new Properties(); - userCredentials.load(bis); - bis.close(); + try { + BufferedInputStream bis = new BufferedInputStream(fis); + userCredentials = new Properties(); + userCredentials.load(bis); + bis.close(); + } finally { + fis.close(); + } } /** diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java --- a/jdk/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/remote/security/JMXPluggableAuthenticator.java Wed Jul 05 16:37:14 2017 +0200 @@ -295,7 +295,7 @@ private static class FileLoginConfig extends Configuration { // The JAAS configuration for file-based authentication - private static AppConfigurationEntry[] entries; + private AppConfigurationEntry[] entries; // The classname of the login module for file-based authentication private static final String FILE_LOGIN_MODULE = diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java --- a/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/com/sun/jmx/remote/security/MBeanServerFileAccessController.java Wed Jul 05 16:37:14 2017 +0200 @@ -231,10 +231,13 @@ private static Properties propertiesFromFile(String fname) throws IOException { FileInputStream fin = new FileInputStream(fname); - Properties p = new Properties(); - p.load(fin); - fin.close(); - return p; + try { + Properties p = new Properties(); + p.load(fin); + return p; + } finally { + fin.close(); + } } private void checkAccessLevel(String accessLevel) { diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/Font.java --- a/jdk/src/share/classes/java/awt/Font.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/java/awt/Font.java Wed Jul 05 16:37:14 2017 +0200 @@ -711,7 +711,7 @@ EBIDI_EMBEDDING, EJUSTIFICATION, EINPUT_METHOD_HIGHLIGHT, EINPUT_METHOD_UNDERLINE, ESWAP_COLORS, ENUMERIC_SHAPING, EKERNING, - ELIGATURES, ETRACKING); + ELIGATURES, ETRACKING, ESUPERSCRIPT); private static final int EXTRA_MASK = AttributeValues.getMask(ETRANSFORM, ESUPERSCRIPT, EWIDTH); @@ -1970,7 +1970,6 @@ * in the JDK - and the only likely caller - is in this same class. */ private float getItalicAngle(FontRenderContext frc) { - AffineTransform at = (isTransformed()) ? getTransform() : identityTx; Object aa, fm; if (frc == null) { aa = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF; @@ -1979,7 +1978,7 @@ aa = frc.getAntiAliasingHint(); fm = frc.getFractionalMetricsHint(); } - return getFont2D().getItalicAngle(this, at, aa, fm); + return getFont2D().getItalicAngle(this, identityTx, aa, fm); } /** diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/color/CMMException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/color/CMMException.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,57 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + Created by gbp, October 25, 1997 + + * + */ +/********************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + + +package java.awt.color; + + +/** + * This exception is thrown if the native CMM returns an error. + */ + +public class CMMException extends java.lang.RuntimeException { + + /** + * Constructs a CMMException with the specified detail message. + * @param s the specified detail message + */ + public CMMException (String s) { + super (s); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/color/ColorSpace.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/color/ColorSpace.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,611 @@ +/* + * Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/********************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.color; + +import sun.java2d.cmm.PCMM; +import sun.java2d.cmm.CMSManager; + + +/** + * This abstract class is used to serve as a color space tag to identify the + * specific color space of a Color object or, via a ColorModel object, + * of an Image, a BufferedImage, or a GraphicsDevice. It contains + * methods that transform colors in a specific color space to/from sRGB + * and to/from a well-defined CIEXYZ color space. + *

+ * For purposes of the methods in this class, colors are represented as + * arrays of color components represented as floats in a normalized range + * defined by each ColorSpace. For many ColorSpaces (e.g. sRGB), this + * range is 0.0 to 1.0. However, some ColorSpaces have components whose + * values have a different range. Methods are provided to inquire per + * component minimum and maximum normalized values. + *

+ * Several variables are defined for purposes of referring to color + * space types (e.g. TYPE_RGB, TYPE_XYZ, etc.) and to refer to specific + * color spaces (e.g. CS_sRGB and CS_CIEXYZ). + * sRGB is a proposed standard RGB color space. For more information, + * see + * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html + * . + *

+ * The purpose of the methods to transform to/from the well-defined + * CIEXYZ color space is to support conversions between any two color + * spaces at a reasonably high degree of accuracy. It is expected that + * particular implementations of subclasses of ColorSpace (e.g. + * ICC_ColorSpace) will support high performance conversion based on + * underlying platform color management systems. + *

+ * The CS_CIEXYZ space used by the toCIEXYZ/fromCIEXYZ methods can be + * described as follows: +

+
+      CIEXYZ
+      viewing illuminance: 200 lux
+      viewing white point: CIE D50
+      media white point: "that of a perfectly reflecting diffuser" -- D50
+      media black point: 0 lux or 0 Reflectance
+      flare: 1 percent
+      surround: 20percent of the media white point
+      media description: reflection print (i.e., RLAB, Hunt viewing media)
+      note: For developers creating an ICC profile for this conversion
+            space, the following is applicable.  Use a simple Von Kries
+            white point adaptation folded into the 3X3 matrix parameters
+            and fold the flare and surround effects into the three
+            one-dimensional lookup tables (assuming one uses the minimal
+            model for monitors).
+
+
+ * + *

+ * @see ICC_ColorSpace + */ + + + +public abstract class ColorSpace implements java.io.Serializable { + + static final long serialVersionUID = -409452704308689724L; + + private int type; + private int numComponents; + private transient String [] compName = null; + + // Cache of singletons for the predefined color spaces. + private static ColorSpace sRGBspace; + private static ColorSpace XYZspace; + private static ColorSpace PYCCspace; + private static ColorSpace GRAYspace; + private static ColorSpace LINEAR_RGBspace; + + /** + * Any of the family of XYZ color spaces. + */ + public static final int TYPE_XYZ = 0; + + /** + * Any of the family of Lab color spaces. + */ + public static final int TYPE_Lab = 1; + + /** + * Any of the family of Luv color spaces. + */ + public static final int TYPE_Luv = 2; + + /** + * Any of the family of YCbCr color spaces. + */ + public static final int TYPE_YCbCr = 3; + + /** + * Any of the family of Yxy color spaces. + */ + public static final int TYPE_Yxy = 4; + + /** + * Any of the family of RGB color spaces. + */ + public static final int TYPE_RGB = 5; + + /** + * Any of the family of GRAY color spaces. + */ + public static final int TYPE_GRAY = 6; + + /** + * Any of the family of HSV color spaces. + */ + public static final int TYPE_HSV = 7; + + /** + * Any of the family of HLS color spaces. + */ + public static final int TYPE_HLS = 8; + + /** + * Any of the family of CMYK color spaces. + */ + public static final int TYPE_CMYK = 9; + + /** + * Any of the family of CMY color spaces. + */ + public static final int TYPE_CMY = 11; + + /** + * Generic 2 component color spaces. + */ + public static final int TYPE_2CLR = 12; + + /** + * Generic 3 component color spaces. + */ + public static final int TYPE_3CLR = 13; + + /** + * Generic 4 component color spaces. + */ + public static final int TYPE_4CLR = 14; + + /** + * Generic 5 component color spaces. + */ + public static final int TYPE_5CLR = 15; + + /** + * Generic 6 component color spaces. + */ + public static final int TYPE_6CLR = 16; + + /** + * Generic 7 component color spaces. + */ + public static final int TYPE_7CLR = 17; + + /** + * Generic 8 component color spaces. + */ + public static final int TYPE_8CLR = 18; + + /** + * Generic 9 component color spaces. + */ + public static final int TYPE_9CLR = 19; + + /** + * Generic 10 component color spaces. + */ + public static final int TYPE_ACLR = 20; + + /** + * Generic 11 component color spaces. + */ + public static final int TYPE_BCLR = 21; + + /** + * Generic 12 component color spaces. + */ + public static final int TYPE_CCLR = 22; + + /** + * Generic 13 component color spaces. + */ + public static final int TYPE_DCLR = 23; + + /** + * Generic 14 component color spaces. + */ + public static final int TYPE_ECLR = 24; + + /** + * Generic 15 component color spaces. + */ + public static final int TYPE_FCLR = 25; + + /** + * The sRGB color space defined at + * + * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html + * . + */ + public static final int CS_sRGB = 1000; + + /** + * A built-in linear RGB color space. This space is based on the + * same RGB primaries as CS_sRGB, but has a linear tone reproduction curve. + */ + public static final int CS_LINEAR_RGB = 1004; + + /** + * The CIEXYZ conversion color space defined above. + */ + public static final int CS_CIEXYZ = 1001; + + /** + * The Photo YCC conversion color space. + */ + public static final int CS_PYCC = 1002; + + /** + * The built-in linear gray scale color space. + */ + public static final int CS_GRAY = 1003; + + + /** + * Constructs a ColorSpace object given a color space type + * and the number of components. + * @param type one of the ColorSpace type constants + * @param numcomponents the number of components in the color space + */ + protected ColorSpace (int type, int numcomponents) { + this.type = type; + this.numComponents = numcomponents; + } + + + /** + * Returns a ColorSpace representing one of the specific + * predefined color spaces. + * @param colorspace a specific color space identified by one of + * the predefined class constants (e.g. CS_sRGB, CS_LINEAR_RGB, + * CS_CIEXYZ, CS_GRAY, or CS_PYCC) + * @return the requested ColorSpace object + */ + // NOTE: This method may be called by privileged threads. + // DO NOT INVOKE CLIENT CODE ON THIS THREAD! + public static ColorSpace getInstance (int colorspace) + { + ColorSpace theColorSpace; + + switch (colorspace) { + case CS_sRGB: + synchronized(ColorSpace.class) { + if (sRGBspace == null) { + ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB); + sRGBspace = new ICC_ColorSpace (theProfile); + } + + theColorSpace = sRGBspace; + } + break; + + case CS_CIEXYZ: + synchronized(ColorSpace.class) { + if (XYZspace == null) { + ICC_Profile theProfile = + ICC_Profile.getInstance (CS_CIEXYZ); + XYZspace = new ICC_ColorSpace (theProfile); + } + + theColorSpace = XYZspace; + } + break; + + case CS_PYCC: + synchronized(ColorSpace.class) { + if (PYCCspace == null) { + ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC); + PYCCspace = new ICC_ColorSpace (theProfile); + } + + theColorSpace = PYCCspace; + } + break; + + + case CS_GRAY: + synchronized(ColorSpace.class) { + if (GRAYspace == null) { + ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY); + GRAYspace = new ICC_ColorSpace (theProfile); + /* to allow access from java.awt.ColorModel */ + CMSManager.GRAYspace = GRAYspace; + } + + theColorSpace = GRAYspace; + } + break; + + + case CS_LINEAR_RGB: + synchronized(ColorSpace.class) { + if (LINEAR_RGBspace == null) { + ICC_Profile theProfile = + ICC_Profile.getInstance(CS_LINEAR_RGB); + LINEAR_RGBspace = new ICC_ColorSpace (theProfile); + /* to allow access from java.awt.ColorModel */ + CMSManager.LINEAR_RGBspace = LINEAR_RGBspace; + } + + theColorSpace = LINEAR_RGBspace; + } + break; + + + default: + throw new IllegalArgumentException ("Unknown color space"); + } + + return theColorSpace; + } + + + /** + * Returns true if the ColorSpace is CS_sRGB. + * @return true if this is a CS_sRGB color + * space, false if it is not + */ + public boolean isCS_sRGB () { + /* REMIND - make sure we know sRGBspace exists already */ + return (this == sRGBspace); + } + + /** + * Transforms a color value assumed to be in this ColorSpace + * into a value in the default CS_sRGB color space. + *

+ * This method transforms color values using algorithms designed + * to produce the best perceptual match between input and output + * colors. In order to do colorimetric conversion of color values, + * you should use the toCIEXYZ + * method of this color space to first convert from the input + * color space to the CS_CIEXYZ color space, and then use the + * fromCIEXYZ method of the CS_sRGB color space to + * convert from CS_CIEXYZ to the output color space. + * See {@link #toCIEXYZ(float[]) toCIEXYZ} and + * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. + *

+ * @param colorvalue a float array with length of at least the number + * of components in this ColorSpace + * @return a float array of length 3 + * @throws ArrayIndexOutOfBoundsException if array length is not + * at least the number of components in this ColorSpace + */ + public abstract float[] toRGB(float[] colorvalue); + + + /** + * Transforms a color value assumed to be in the default CS_sRGB + * color space into this ColorSpace. + *

+ * This method transforms color values using algorithms designed + * to produce the best perceptual match between input and output + * colors. In order to do colorimetric conversion of color values, + * you should use the toCIEXYZ + * method of the CS_sRGB color space to first convert from the input + * color space to the CS_CIEXYZ color space, and then use the + * fromCIEXYZ method of this color space to + * convert from CS_CIEXYZ to the output color space. + * See {@link #toCIEXYZ(float[]) toCIEXYZ} and + * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. + *

+ * @param rgbvalue a float array with length of at least 3 + * @return a float array with length equal to the number of + * components in this ColorSpace + * @throws ArrayIndexOutOfBoundsException if array length is not + * at least 3 + */ + public abstract float[] fromRGB(float[] rgbvalue); + + + /** + * Transforms a color value assumed to be in this ColorSpace + * into the CS_CIEXYZ conversion color space. + *

+ * This method transforms color values using relative colorimetry, + * as defined by the International Color Consortium standard. This + * means that the XYZ values returned by this method are represented + * relative to the D50 white point of the CS_CIEXYZ color space. + * This representation is useful in a two-step color conversion + * process in which colors are transformed from an input color + * space to CS_CIEXYZ and then to an output color space. This + * representation is not the same as the XYZ values that would + * be measured from the given color value by a colorimeter. + * A further transformation is necessary to compute the XYZ values + * that would be measured using current CIE recommended practices. + * See the {@link ICC_ColorSpace#toCIEXYZ(float[]) toCIEXYZ} method of + * ICC_ColorSpace for further information. + *

+ * @param colorvalue a float array with length of at least the number + * of components in this ColorSpace + * @return a float array of length 3 + * @throws ArrayIndexOutOfBoundsException if array length is not + * at least the number of components in this ColorSpace. + */ + public abstract float[] toCIEXYZ(float[] colorvalue); + + + /** + * Transforms a color value assumed to be in the CS_CIEXYZ conversion + * color space into this ColorSpace. + *

+ * This method transforms color values using relative colorimetry, + * as defined by the International Color Consortium standard. This + * means that the XYZ argument values taken by this method are represented + * relative to the D50 white point of the CS_CIEXYZ color space. + * This representation is useful in a two-step color conversion + * process in which colors are transformed from an input color + * space to CS_CIEXYZ and then to an output color space. The color + * values returned by this method are not those that would produce + * the XYZ value passed to the method when measured by a colorimeter. + * If you have XYZ values corresponding to measurements made using + * current CIE recommended practices, they must be converted to D50 + * relative values before being passed to this method. + * See the {@link ICC_ColorSpace#fromCIEXYZ(float[]) fromCIEXYZ} method of + * ICC_ColorSpace for further information. + *

+ * @param colorvalue a float array with length of at least 3 + * @return a float array with length equal to the number of + * components in this ColorSpace + * @throws ArrayIndexOutOfBoundsException if array length is not + * at least 3 + */ + public abstract float[] fromCIEXYZ(float[] colorvalue); + + /** + * Returns the color space type of this ColorSpace (for example + * TYPE_RGB, TYPE_XYZ, ...). The type defines the + * number of components of the color space and the interpretation, + * e.g. TYPE_RGB identifies a color space with three components - red, + * green, and blue. It does not define the particular color + * characteristics of the space, e.g. the chromaticities of the + * primaries. + * + * @return the type constant that represents the type of this + * ColorSpace + */ + public int getType() { + return type; + } + + /** + * Returns the number of components of this ColorSpace. + * @return The number of components in this ColorSpace. + */ + public int getNumComponents() { + return numComponents; + } + + /** + * Returns the name of the component given the component index. + * + * @param idx the component index + * @return the name of the component at the specified index + * @throws IllegalArgumentException if idx is + * less than 0 or greater than numComponents - 1 + */ + public String getName (int idx) { + /* REMIND - handle common cases here */ + if ((idx < 0) || (idx > numComponents - 1)) { + throw new IllegalArgumentException( + "Component index out of range: " + idx); + } + + if (compName == null) { + switch (type) { + case ColorSpace.TYPE_XYZ: + compName = new String[] {"X", "Y", "Z"}; + break; + case ColorSpace.TYPE_Lab: + compName = new String[] {"L", "a", "b"}; + break; + case ColorSpace.TYPE_Luv: + compName = new String[] {"L", "u", "v"}; + break; + case ColorSpace.TYPE_YCbCr: + compName = new String[] {"Y", "Cb", "Cr"}; + break; + case ColorSpace.TYPE_Yxy: + compName = new String[] {"Y", "x", "y"}; + break; + case ColorSpace.TYPE_RGB: + compName = new String[] {"Red", "Green", "Blue"}; + break; + case ColorSpace.TYPE_GRAY: + compName = new String[] {"Gray"}; + break; + case ColorSpace.TYPE_HSV: + compName = new String[] {"Hue", "Saturation", "Value"}; + break; + case ColorSpace.TYPE_HLS: + compName = new String[] {"Hue", "Lightness", + "Saturation"}; + break; + case ColorSpace.TYPE_CMYK: + compName = new String[] {"Cyan", "Magenta", "Yellow", + "Black"}; + break; + case ColorSpace.TYPE_CMY: + compName = new String[] {"Cyan", "Magenta", "Yellow"}; + break; + default: + String [] tmp = new String[numComponents]; + for (int i = 0; i < tmp.length; i++) { + tmp[i] = "Unnamed color component(" + i + ")"; + } + compName = tmp; + } + } + return compName[idx]; + } + + /** + * Returns the minimum normalized color component value for the + * specified component. The default implementation in this abstract + * class returns 0.0 for all components. Subclasses should override + * this method if necessary. + * + * @param component the component index + * @return the minimum normalized component value + * @throws IllegalArgumentException if component is less than 0 or + * greater than numComponents - 1 + * @since 1.4 + */ + public float getMinValue(int component) { + if ((component < 0) || (component > numComponents - 1)) { + throw new IllegalArgumentException( + "Component index out of range: " + component); + } + return 0.0f; + } + + /** + * Returns the maximum normalized color component value for the + * specified component. The default implementation in this abstract + * class returns 1.0 for all components. Subclasses should override + * this method if necessary. + * + * @param component the component index + * @return the maximum normalized component value + * @throws IllegalArgumentException if component is less than 0 or + * greater than numComponents - 1 + * @since 1.4 + */ + public float getMaxValue(int component) { + if ((component < 0) || (component > numComponents - 1)) { + throw new IllegalArgumentException( + "Component index out of range: " + component); + } + return 1.0f; + } + + /* Returns true if cspace is the XYZspace. + */ + static boolean isCS_CIEXYZ(ColorSpace cspace) { + return (cspace == XYZspace); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/color/ICC_ColorSpace.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/color/ICC_ColorSpace.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,616 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/********************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.color; + +import sun.java2d.cmm.ColorTransform; +import sun.java2d.cmm.CMSManager; +import sun.java2d.cmm.PCMM; + + +/** + * + * The ICC_ColorSpace class is an implementation of the abstract + * ColorSpace class. This representation of + * device independent and device dependent color spaces is based on the + * International Color Consortium Specification ICC.1:2001-12, File Format for + * Color Profiles (see http://www.color.org). + *

+ * Typically, a Color or ColorModel would be associated with an ICC + * Profile which is either an input, display, or output profile (see + * the ICC specification). There are other types of ICC Profiles, e.g. + * abstract profiles, device link profiles, and named color profiles, + * which do not contain information appropriate for representing the color + * space of a color, image, or device (see ICC_Profile). + * Attempting to create an ICC_ColorSpace object from an inappropriate ICC + * Profile is an error. + *

+ * ICC Profiles represent transformations from the color space of + * the profile (e.g. a monitor) to a Profile Connection Space (PCS). + * Profiles of interest for tagging images or colors have a + * PCS which is one of the device independent + * spaces (one CIEXYZ space and two CIELab spaces) defined in the + * ICC Profile Format Specification. Most profiles of interest + * either have invertible transformations or explicitly specify + * transformations going both directions. Should an ICC_ColorSpace + * object be used in a way requiring a conversion from PCS to + * the profile's native space and there is inadequate data to + * correctly perform the conversion, the ICC_ColorSpace object will + * produce output in the specified type of color space (e.g. TYPE_RGB, + * TYPE_CMYK, etc.), but the specific color values of the output data + * will be undefined. + *

+ * The details of this class are not important for simple applets, + * which draw in a default color space or manipulate and display + * imported images with a known color space. At most, such applets + * would need to get one of the default color spaces via + * ColorSpace.getInstance(). + *

+ * @see ColorSpace + * @see ICC_Profile + */ + + + +public class ICC_ColorSpace extends ColorSpace { + + static final long serialVersionUID = 3455889114070431483L; + + private ICC_Profile thisProfile; + private float[] minVal; + private float[] maxVal; + private float[] diffMinMax; + private float[] invDiffMinMax; + private boolean needScaleInit = true; + + // {to,from}{RGB,CIEXYZ} methods create and cache these when needed + private transient ColorTransform this2srgb; + private transient ColorTransform srgb2this; + private transient ColorTransform this2xyz; + private transient ColorTransform xyz2this; + + + /** + * Constructs a new ICC_ColorSpace from an ICC_Profile object. + * @param profile the specified ICC_Profile object + * @exception IllegalArgumentException if profile is inappropriate for + * representing a ColorSpace. + */ + public ICC_ColorSpace (ICC_Profile profile) { + super (profile.getColorSpaceType(), profile.getNumComponents()); + + int profileClass = profile.getProfileClass(); + + /* REMIND - is NAMEDCOLOR OK? */ + if ((profileClass != ICC_Profile.CLASS_INPUT) && + (profileClass != ICC_Profile.CLASS_DISPLAY) && + (profileClass != ICC_Profile.CLASS_OUTPUT) && + (profileClass != ICC_Profile.CLASS_COLORSPACECONVERSION) && + (profileClass != ICC_Profile.CLASS_NAMEDCOLOR) && + (profileClass != ICC_Profile.CLASS_ABSTRACT)) { + throw new IllegalArgumentException("Invalid profile type"); + } + + thisProfile = profile; + setMinMax(); + } + + /** + * Returns the ICC_Profile for this ICC_ColorSpace. + * @return the ICC_Profile for this ICC_ColorSpace. + */ + public ICC_Profile getProfile() { + return thisProfile; + } + + /** + * Transforms a color value assumed to be in this ColorSpace + * into a value in the default CS_sRGB color space. + *

+ * This method transforms color values using algorithms designed + * to produce the best perceptual match between input and output + * colors. In order to do colorimetric conversion of color values, + * you should use the toCIEXYZ + * method of this color space to first convert from the input + * color space to the CS_CIEXYZ color space, and then use the + * fromCIEXYZ method of the CS_sRGB color space to + * convert from CS_CIEXYZ to the output color space. + * See {@link #toCIEXYZ(float[]) toCIEXYZ} and + * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. + *

+ * @param colorvalue a float array with length of at least the number + * of components in this ColorSpace. + * @return a float array of length 3. + * @throws ArrayIndexOutOfBoundsException if array length is not + * at least the number of components in this ColorSpace. + */ + public float[] toRGB (float[] colorvalue) { + + if (this2srgb == null) { + ColorTransform[] transformList = new ColorTransform [2]; + ICC_ColorSpace srgbCS = + (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB); + PCMM mdl = CMSManager.getModule(); + transformList[0] = mdl.createTransform( + thisProfile, ColorTransform.Any, ColorTransform.In); + transformList[1] = mdl.createTransform( + srgbCS.getProfile(), ColorTransform.Any, ColorTransform.Out); + this2srgb = mdl.createTransform(transformList); + if (needScaleInit) { + setComponentScaling(); + } + } + + int nc = this.getNumComponents(); + short tmp[] = new short[nc]; + for (int i = 0; i < nc; i++) { + tmp[i] = (short) + ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f); + } + tmp = this2srgb.colorConvert(tmp, null); + float[] result = new float [3]; + for (int i = 0; i < 3; i++) { + result[i] = ((float) (tmp[i] & 0xffff)) / 65535.0f; + } + return result; + } + + /** + * Transforms a color value assumed to be in the default CS_sRGB + * color space into this ColorSpace. + *

+ * This method transforms color values using algorithms designed + * to produce the best perceptual match between input and output + * colors. In order to do colorimetric conversion of color values, + * you should use the toCIEXYZ + * method of the CS_sRGB color space to first convert from the input + * color space to the CS_CIEXYZ color space, and then use the + * fromCIEXYZ method of this color space to + * convert from CS_CIEXYZ to the output color space. + * See {@link #toCIEXYZ(float[]) toCIEXYZ} and + * {@link #fromCIEXYZ(float[]) fromCIEXYZ} for further information. + *

+ * @param rgbvalue a float array with length of at least 3. + * @return a float array with length equal to the number of + * components in this ColorSpace. + * @throws ArrayIndexOutOfBoundsException if array length is not + * at least 3. + */ + public float[] fromRGB(float[] rgbvalue) { + + if (srgb2this == null) { + ColorTransform[] transformList = new ColorTransform [2]; + ICC_ColorSpace srgbCS = + (ICC_ColorSpace) ColorSpace.getInstance (CS_sRGB); + PCMM mdl = CMSManager.getModule(); + transformList[0] = mdl.createTransform( + srgbCS.getProfile(), ColorTransform.Any, ColorTransform.In); + transformList[1] = mdl.createTransform( + thisProfile, ColorTransform.Any, ColorTransform.Out); + srgb2this = mdl.createTransform(transformList); + if (needScaleInit) { + setComponentScaling(); + } + } + + short tmp[] = new short[3]; + for (int i = 0; i < 3; i++) { + tmp[i] = (short) ((rgbvalue[i] * 65535.0f) + 0.5f); + } + tmp = srgb2this.colorConvert(tmp, null); + int nc = this.getNumComponents(); + float[] result = new float [nc]; + for (int i = 0; i < nc; i++) { + result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * + diffMinMax[i] + minVal[i]; + } + return result; + } + + + /** + * Transforms a color value assumed to be in this ColorSpace + * into the CS_CIEXYZ conversion color space. + *

+ * This method transforms color values using relative colorimetry, + * as defined by the ICC Specification. This + * means that the XYZ values returned by this method are represented + * relative to the D50 white point of the CS_CIEXYZ color space. + * This representation is useful in a two-step color conversion + * process in which colors are transformed from an input color + * space to CS_CIEXYZ and then to an output color space. This + * representation is not the same as the XYZ values that would + * be measured from the given color value by a colorimeter. + * A further transformation is necessary to compute the XYZ values + * that would be measured using current CIE recommended practices. + * The paragraphs below explain this in more detail. + *

+ * The ICC standard uses a device independent color space (DICS) as the + * mechanism for converting color from one device to another device. In + * this architecture, colors are converted from the source device's color + * space to the ICC DICS and then from the ICC DICS to the destination + * device's color space. The ICC standard defines device profiles which + * contain transforms which will convert between a device's color space + * and the ICC DICS. The overall conversion of colors from a source + * device to colors of a destination device is done by connecting the + * device-to-DICS transform of the profile for the source device to the + * DICS-to-device transform of the profile for the destination device. + * For this reason, the ICC DICS is commonly referred to as the profile + * connection space (PCS). The color space used in the methods + * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC + * Specification. This is also the color space represented by + * ColorSpace.CS_CIEXYZ. + *

+ * The XYZ values of a color are often represented as relative to some + * white point, so the actual meaning of the XYZ values cannot be known + * without knowing the white point of those values. This is known as + * relative colorimetry. The PCS uses a white point of D50, so the XYZ + * values of the PCS are relative to D50. For example, white in the PCS + * will have the XYZ values of D50, which is defined to be X=.9642, + * Y=1.000, and Z=0.8249. This white point is commonly used for graphic + * arts applications, but others are often used in other applications. + *

+ * To quantify the color characteristics of a device such as a printer + * or monitor, measurements of XYZ values for particular device colors + * are typically made. For purposes of this discussion, the term + * device XYZ values is used to mean the XYZ values that would be + * measured from device colors using current CIE recommended practices. + *

+ * Converting between device XYZ values and the PCS XYZ values returned + * by this method corresponds to converting between the device's color + * space, as represented by CIE colorimetric values, and the PCS. There + * are many factors involved in this process, some of which are quite + * subtle. The most important, however, is the adjustment made to account + * for differences between the device's white point and the white point of + * the PCS. There are many techniques for doing this and it is the + * subject of much current research and controversy. Some commonly used + * methods are XYZ scaling, the von Kries transform, and the Bradford + * transform. The proper method to use depends upon each particular + * application. + *

+ * The simplest method is XYZ scaling. In this method each device XYZ + * value is converted to a PCS XYZ value by multiplying it by the ratio + * of the PCS white point (D50) to the device white point. + *

+     *
+     * Xd, Yd, Zd are the device XYZ values
+     * Xdw, Ydw, Zdw are the device XYZ white point values
+     * Xp, Yp, Zp are the PCS XYZ values
+     * Xd50, Yd50, Zd50 are the PCS XYZ white point values
+     *
+     * Xp = Xd * (Xd50 / Xdw)
+     * Yp = Yd * (Yd50 / Ydw)
+     * Zp = Zd * (Zd50 / Zdw)
+     *
+     * 
+ *

+ * Conversion from the PCS to the device would be done by inverting these + * equations: + *

+     *
+     * Xd = Xp * (Xdw / Xd50)
+     * Yd = Yp * (Ydw / Yd50)
+     * Zd = Zp * (Zdw / Zd50)
+     *
+     * 
+ *

+ * Note that the media white point tag in an ICC profile is not the same + * as the device white point. The media white point tag is expressed in + * PCS values and is used to represent the difference between the XYZ of + * device illuminant and the XYZ of the device media when measured under + * that illuminant. The device white point is expressed as the device + * XYZ values corresponding to white displayed on the device. For + * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device + * will result in a measured device XYZ value of D65. This will not + * be the same as the media white point tag XYZ value in the ICC + * profile for an sRGB device. + *

+ * @param colorvalue a float array with length of at least the number + * of components in this ColorSpace. + * @return a float array of length 3. + * @throws ArrayIndexOutOfBoundsException if array length is not + * at least the number of components in this ColorSpace. + */ + public float[] toCIEXYZ(float[] colorvalue) { + + if (this2xyz == null) { + ColorTransform[] transformList = new ColorTransform [2]; + ICC_ColorSpace xyzCS = + (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ); + PCMM mdl = CMSManager.getModule(); + try { + transformList[0] = mdl.createTransform( + thisProfile, ICC_Profile.icRelativeColorimetric, + ColorTransform.In); + } catch (CMMException e) { + transformList[0] = mdl.createTransform( + thisProfile, ColorTransform.Any, ColorTransform.In); + } + transformList[1] = mdl.createTransform( + xyzCS.getProfile(), ColorTransform.Any, ColorTransform.Out); + this2xyz = mdl.createTransform (transformList); + if (needScaleInit) { + setComponentScaling(); + } + } + + int nc = this.getNumComponents(); + short tmp[] = new short[nc]; + for (int i = 0; i < nc; i++) { + tmp[i] = (short) + ((colorvalue[i] - minVal[i]) * invDiffMinMax[i] + 0.5f); + } + tmp = this2xyz.colorConvert(tmp, null); + float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f); + // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components + float[] result = new float [3]; + for (int i = 0; i < 3; i++) { + result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * ALMOST_TWO; + } + return result; + } + + + /** + * Transforms a color value assumed to be in the CS_CIEXYZ conversion + * color space into this ColorSpace. + *

+ * This method transforms color values using relative colorimetry, + * as defined by the ICC Specification. This + * means that the XYZ argument values taken by this method are represented + * relative to the D50 white point of the CS_CIEXYZ color space. + * This representation is useful in a two-step color conversion + * process in which colors are transformed from an input color + * space to CS_CIEXYZ and then to an output color space. The color + * values returned by this method are not those that would produce + * the XYZ value passed to the method when measured by a colorimeter. + * If you have XYZ values corresponding to measurements made using + * current CIE recommended practices, they must be converted to D50 + * relative values before being passed to this method. + * The paragraphs below explain this in more detail. + *

+ * The ICC standard uses a device independent color space (DICS) as the + * mechanism for converting color from one device to another device. In + * this architecture, colors are converted from the source device's color + * space to the ICC DICS and then from the ICC DICS to the destination + * device's color space. The ICC standard defines device profiles which + * contain transforms which will convert between a device's color space + * and the ICC DICS. The overall conversion of colors from a source + * device to colors of a destination device is done by connecting the + * device-to-DICS transform of the profile for the source device to the + * DICS-to-device transform of the profile for the destination device. + * For this reason, the ICC DICS is commonly referred to as the profile + * connection space (PCS). The color space used in the methods + * toCIEXYZ and fromCIEXYZ is the CIEXYZ PCS defined by the ICC + * Specification. This is also the color space represented by + * ColorSpace.CS_CIEXYZ. + *

+ * The XYZ values of a color are often represented as relative to some + * white point, so the actual meaning of the XYZ values cannot be known + * without knowing the white point of those values. This is known as + * relative colorimetry. The PCS uses a white point of D50, so the XYZ + * values of the PCS are relative to D50. For example, white in the PCS + * will have the XYZ values of D50, which is defined to be X=.9642, + * Y=1.000, and Z=0.8249. This white point is commonly used for graphic + * arts applications, but others are often used in other applications. + *

+ * To quantify the color characteristics of a device such as a printer + * or monitor, measurements of XYZ values for particular device colors + * are typically made. For purposes of this discussion, the term + * device XYZ values is used to mean the XYZ values that would be + * measured from device colors using current CIE recommended practices. + *

+ * Converting between device XYZ values and the PCS XYZ values taken as + * arguments by this method corresponds to converting between the device's + * color space, as represented by CIE colorimetric values, and the PCS. + * There are many factors involved in this process, some of which are quite + * subtle. The most important, however, is the adjustment made to account + * for differences between the device's white point and the white point of + * the PCS. There are many techniques for doing this and it is the + * subject of much current research and controversy. Some commonly used + * methods are XYZ scaling, the von Kries transform, and the Bradford + * transform. The proper method to use depends upon each particular + * application. + *

+ * The simplest method is XYZ scaling. In this method each device XYZ + * value is converted to a PCS XYZ value by multiplying it by the ratio + * of the PCS white point (D50) to the device white point. + *

+     *
+     * Xd, Yd, Zd are the device XYZ values
+     * Xdw, Ydw, Zdw are the device XYZ white point values
+     * Xp, Yp, Zp are the PCS XYZ values
+     * Xd50, Yd50, Zd50 are the PCS XYZ white point values
+     *
+     * Xp = Xd * (Xd50 / Xdw)
+     * Yp = Yd * (Yd50 / Ydw)
+     * Zp = Zd * (Zd50 / Zdw)
+     *
+     * 
+ *

+ * Conversion from the PCS to the device would be done by inverting these + * equations: + *

+     *
+     * Xd = Xp * (Xdw / Xd50)
+     * Yd = Yp * (Ydw / Yd50)
+     * Zd = Zp * (Zdw / Zd50)
+     *
+     * 
+ *

+ * Note that the media white point tag in an ICC profile is not the same + * as the device white point. The media white point tag is expressed in + * PCS values and is used to represent the difference between the XYZ of + * device illuminant and the XYZ of the device media when measured under + * that illuminant. The device white point is expressed as the device + * XYZ values corresponding to white displayed on the device. For + * example, displaying the RGB color (1.0, 1.0, 1.0) on an sRGB device + * will result in a measured device XYZ value of D65. This will not + * be the same as the media white point tag XYZ value in the ICC + * profile for an sRGB device. + *

+ *

+ * @param colorvalue a float array with length of at least 3. + * @return a float array with length equal to the number of + * components in this ColorSpace. + * @throws ArrayIndexOutOfBoundsException if array length is not + * at least 3. + */ + public float[] fromCIEXYZ(float[] colorvalue) { + + if (xyz2this == null) { + ColorTransform[] transformList = new ColorTransform [2]; + ICC_ColorSpace xyzCS = + (ICC_ColorSpace) ColorSpace.getInstance (CS_CIEXYZ); + PCMM mdl = CMSManager.getModule(); + transformList[0] = mdl.createTransform ( + xyzCS.getProfile(), ColorTransform.Any, ColorTransform.In); + try { + transformList[1] = mdl.createTransform( + thisProfile, ICC_Profile.icRelativeColorimetric, + ColorTransform.Out); + } catch (CMMException e) { + transformList[1] = CMSManager.getModule().createTransform( + thisProfile, ColorTransform.Any, ColorTransform.Out); + } + xyz2this = mdl.createTransform(transformList); + if (needScaleInit) { + setComponentScaling(); + } + } + + short tmp[] = new short[3]; + float ALMOST_TWO = 1.0f + (32767.0f / 32768.0f); + float factor = 65535.0f / ALMOST_TWO; + // For CIEXYZ, min = 0.0, max = ALMOST_TWO for all components + for (int i = 0; i < 3; i++) { + tmp[i] = (short) ((colorvalue[i] * factor) + 0.5f); + } + tmp = xyz2this.colorConvert(tmp, null); + int nc = this.getNumComponents(); + float[] result = new float [nc]; + for (int i = 0; i < nc; i++) { + result[i] = (((float) (tmp[i] & 0xffff)) / 65535.0f) * + diffMinMax[i] + minVal[i]; + } + return result; + } + + /** + * Returns the minimum normalized color component value for the + * specified component. For TYPE_XYZ spaces, this method returns + * minimum values of 0.0 for all components. For TYPE_Lab spaces, + * this method returns 0.0 for L and -128.0 for a and b components. + * This is consistent with the encoding of the XYZ and Lab Profile + * Connection Spaces in the ICC specification. For all other types, this + * method returns 0.0 for all components. When using an ICC_ColorSpace + * with a profile that requires different minimum component values, + * it is necessary to subclass this class and override this method. + * @param component The component index. + * @return The minimum normalized component value. + * @throws IllegalArgumentException if component is less than 0 or + * greater than numComponents - 1. + * @since 1.4 + */ + public float getMinValue(int component) { + if ((component < 0) || (component > this.getNumComponents() - 1)) { + throw new IllegalArgumentException( + "Component index out of range: + component"); + } + return minVal[component]; + } + + /** + * Returns the maximum normalized color component value for the + * specified component. For TYPE_XYZ spaces, this method returns + * maximum values of 1.0 + (32767.0 / 32768.0) for all components. + * For TYPE_Lab spaces, + * this method returns 100.0 for L and 127.0 for a and b components. + * This is consistent with the encoding of the XYZ and Lab Profile + * Connection Spaces in the ICC specification. For all other types, this + * method returns 1.0 for all components. When using an ICC_ColorSpace + * with a profile that requires different maximum component values, + * it is necessary to subclass this class and override this method. + * @param component The component index. + * @return The maximum normalized component value. + * @throws IllegalArgumentException if component is less than 0 or + * greater than numComponents - 1. + * @since 1.4 + */ + public float getMaxValue(int component) { + if ((component < 0) || (component > this.getNumComponents() - 1)) { + throw new IllegalArgumentException( + "Component index out of range: + component"); + } + return maxVal[component]; + } + + private void setMinMax() { + int nc = this.getNumComponents(); + int type = this.getType(); + minVal = new float[nc]; + maxVal = new float[nc]; + if (type == ColorSpace.TYPE_Lab) { + minVal[0] = 0.0f; // L + maxVal[0] = 100.0f; + minVal[1] = -128.0f; // a + maxVal[1] = 127.0f; + minVal[2] = -128.0f; // b + maxVal[2] = 127.0f; + } else if (type == ColorSpace.TYPE_XYZ) { + minVal[0] = minVal[1] = minVal[2] = 0.0f; // X, Y, Z + maxVal[0] = maxVal[1] = maxVal[2] = 1.0f + (32767.0f/ 32768.0f); + } else { + for (int i = 0; i < nc; i++) { + minVal[i] = 0.0f; + maxVal[i] = 1.0f; + } + } + } + + private void setComponentScaling() { + int nc = this.getNumComponents(); + diffMinMax = new float[nc]; + invDiffMinMax = new float[nc]; + for (int i = 0; i < nc; i++) { + minVal[i] = this.getMinValue(i); // in case getMinVal is overridden + maxVal[i] = this.getMaxValue(i); // in case getMaxVal is overridden + diffMinMax[i] = maxVal[i] - minVal[i]; + invDiffMinMax[i] = 65535.0f / diffMinMax[i]; + } + needScaleInit = false; + } + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/color/ICC_Profile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,2003 @@ +/* + * Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/********************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.color; + +import sun.java2d.cmm.PCMM; +import sun.java2d.cmm.CMSManager; +import sun.java2d.cmm.ProfileDeferralMgr; +import sun.java2d.cmm.ProfileDeferralInfo; +import sun.java2d.cmm.ProfileActivator; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamException; +import java.io.OutputStream; +import java.io.Serializable; + +import java.util.StringTokenizer; + +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * A representation of color profile data for device independent and + * device dependent color spaces based on the International Color + * Consortium Specification ICC.1:2001-12, File Format for Color Profiles, + * (see http://www.color.org). + *

+ * An ICC_ColorSpace object can be constructed from an appropriate + * ICC_Profile. + * Typically, an ICC_ColorSpace would be associated with an ICC + * Profile which is either an input, display, or output profile (see + * the ICC specification). There are also device link, abstract, + * color space conversion, and named color profiles. These are less + * useful for tagging a color or image, but are useful for other + * purposes (in particular device link profiles can provide improved + * performance for converting from one device's color space to + * another's). + *

+ * ICC Profiles represent transformations from the color space of + * the profile (e.g. a monitor) to a Profile Connection Space (PCS). + * Profiles of interest for tagging images or colors have a PCS + * which is one of the two specific device independent + * spaces (one CIEXYZ space and one CIELab space) defined in the + * ICC Profile Format Specification. Most profiles of interest + * either have invertible transformations or explicitly specify + * transformations going both directions. + *

+ * @see ICC_ColorSpace + */ + + +public class ICC_Profile implements Serializable { + + private static final long serialVersionUID = -3938515861990936766L; + + transient long ID; + + private transient ProfileDeferralInfo deferralInfo; + private transient ProfileActivator profileActivator; + + // Registry of singleton profile objects for specific color spaces + // defined in the ColorSpace class (e.g. CS_sRGB), see + // getInstance(int cspace) factory method. + private static ICC_Profile sRGBprofile; + private static ICC_Profile XYZprofile; + private static ICC_Profile PYCCprofile; + private static ICC_Profile GRAYprofile; + private static ICC_Profile LINEAR_RGBprofile; + + + /** + * Profile class is input. + */ + public static final int CLASS_INPUT = 0; + + /** + * Profile class is display. + */ + public static final int CLASS_DISPLAY = 1; + + /** + * Profile class is output. + */ + public static final int CLASS_OUTPUT = 2; + + /** + * Profile class is device link. + */ + public static final int CLASS_DEVICELINK = 3; + + /** + * Profile class is color space conversion. + */ + public static final int CLASS_COLORSPACECONVERSION = 4; + + /** + * Profile class is abstract. + */ + public static final int CLASS_ABSTRACT = 5; + + /** + * Profile class is named color. + */ + public static final int CLASS_NAMEDCOLOR = 6; + + + /** + * ICC Profile Color Space Type Signature: 'XYZ '. + */ + public static final int icSigXYZData = 0x58595A20; /* 'XYZ ' */ + + /** + * ICC Profile Color Space Type Signature: 'Lab '. + */ + public static final int icSigLabData = 0x4C616220; /* 'Lab ' */ + + /** + * ICC Profile Color Space Type Signature: 'Luv '. + */ + public static final int icSigLuvData = 0x4C757620; /* 'Luv ' */ + + /** + * ICC Profile Color Space Type Signature: 'YCbr'. + */ + public static final int icSigYCbCrData = 0x59436272; /* 'YCbr' */ + + /** + * ICC Profile Color Space Type Signature: 'Yxy '. + */ + public static final int icSigYxyData = 0x59787920; /* 'Yxy ' */ + + /** + * ICC Profile Color Space Type Signature: 'RGB '. + */ + public static final int icSigRgbData = 0x52474220; /* 'RGB ' */ + + /** + * ICC Profile Color Space Type Signature: 'GRAY'. + */ + public static final int icSigGrayData = 0x47524159; /* 'GRAY' */ + + /** + * ICC Profile Color Space Type Signature: 'HSV'. + */ + public static final int icSigHsvData = 0x48535620; /* 'HSV ' */ + + /** + * ICC Profile Color Space Type Signature: 'HLS'. + */ + public static final int icSigHlsData = 0x484C5320; /* 'HLS ' */ + + /** + * ICC Profile Color Space Type Signature: 'CMYK'. + */ + public static final int icSigCmykData = 0x434D594B; /* 'CMYK' */ + + /** + * ICC Profile Color Space Type Signature: 'CMY '. + */ + public static final int icSigCmyData = 0x434D5920; /* 'CMY ' */ + + /** + * ICC Profile Color Space Type Signature: '2CLR'. + */ + public static final int icSigSpace2CLR = 0x32434C52; /* '2CLR' */ + + /** + * ICC Profile Color Space Type Signature: '3CLR'. + */ + public static final int icSigSpace3CLR = 0x33434C52; /* '3CLR' */ + + /** + * ICC Profile Color Space Type Signature: '4CLR'. + */ + public static final int icSigSpace4CLR = 0x34434C52; /* '4CLR' */ + + /** + * ICC Profile Color Space Type Signature: '5CLR'. + */ + public static final int icSigSpace5CLR = 0x35434C52; /* '5CLR' */ + + /** + * ICC Profile Color Space Type Signature: '6CLR'. + */ + public static final int icSigSpace6CLR = 0x36434C52; /* '6CLR' */ + + /** + * ICC Profile Color Space Type Signature: '7CLR'. + */ + public static final int icSigSpace7CLR = 0x37434C52; /* '7CLR' */ + + /** + * ICC Profile Color Space Type Signature: '8CLR'. + */ + public static final int icSigSpace8CLR = 0x38434C52; /* '8CLR' */ + + /** + * ICC Profile Color Space Type Signature: '9CLR'. + */ + public static final int icSigSpace9CLR = 0x39434C52; /* '9CLR' */ + + /** + * ICC Profile Color Space Type Signature: 'ACLR'. + */ + public static final int icSigSpaceACLR = 0x41434C52; /* 'ACLR' */ + + /** + * ICC Profile Color Space Type Signature: 'BCLR'. + */ + public static final int icSigSpaceBCLR = 0x42434C52; /* 'BCLR' */ + + /** + * ICC Profile Color Space Type Signature: 'CCLR'. + */ + public static final int icSigSpaceCCLR = 0x43434C52; /* 'CCLR' */ + + /** + * ICC Profile Color Space Type Signature: 'DCLR'. + */ + public static final int icSigSpaceDCLR = 0x44434C52; /* 'DCLR' */ + + /** + * ICC Profile Color Space Type Signature: 'ECLR'. + */ + public static final int icSigSpaceECLR = 0x45434C52; /* 'ECLR' */ + + /** + * ICC Profile Color Space Type Signature: 'FCLR'. + */ + public static final int icSigSpaceFCLR = 0x46434C52; /* 'FCLR' */ + + + /** + * ICC Profile Class Signature: 'scnr'. + */ + public static final int icSigInputClass = 0x73636E72; /* 'scnr' */ + + /** + * ICC Profile Class Signature: 'mntr'. + */ + public static final int icSigDisplayClass = 0x6D6E7472; /* 'mntr' */ + + /** + * ICC Profile Class Signature: 'prtr'. + */ + public static final int icSigOutputClass = 0x70727472; /* 'prtr' */ + + /** + * ICC Profile Class Signature: 'link'. + */ + public static final int icSigLinkClass = 0x6C696E6B; /* 'link' */ + + /** + * ICC Profile Class Signature: 'abst'. + */ + public static final int icSigAbstractClass = 0x61627374; /* 'abst' */ + + /** + * ICC Profile Class Signature: 'spac'. + */ + public static final int icSigColorSpaceClass = 0x73706163; /* 'spac' */ + + /** + * ICC Profile Class Signature: 'nmcl'. + */ + public static final int icSigNamedColorClass = 0x6e6d636c; /* 'nmcl' */ + + + /** + * ICC Profile Rendering Intent: Perceptual. + */ + public static final int icPerceptual = 0; + + /** + * ICC Profile Rendering Intent: RelativeColorimetric. + */ + public static final int icRelativeColorimetric = 1; + + /** + * ICC Profile Rendering Intent: Media-RelativeColorimetric. + * @since 1.5 + */ + public static final int icMediaRelativeColorimetric = 1; + + /** + * ICC Profile Rendering Intent: Saturation. + */ + public static final int icSaturation = 2; + + /** + * ICC Profile Rendering Intent: AbsoluteColorimetric. + */ + public static final int icAbsoluteColorimetric = 3; + + /** + * ICC Profile Rendering Intent: ICC-AbsoluteColorimetric. + * @since 1.5 + */ + public static final int icICCAbsoluteColorimetric = 3; + + + /** + * ICC Profile Tag Signature: 'head' - special. + */ + public static final int icSigHead = 0x68656164; /* 'head' - special */ + + /** + * ICC Profile Tag Signature: 'A2B0'. + */ + public static final int icSigAToB0Tag = 0x41324230; /* 'A2B0' */ + + /** + * ICC Profile Tag Signature: 'A2B1'. + */ + public static final int icSigAToB1Tag = 0x41324231; /* 'A2B1' */ + + /** + * ICC Profile Tag Signature: 'A2B2'. + */ + public static final int icSigAToB2Tag = 0x41324232; /* 'A2B2' */ + + /** + * ICC Profile Tag Signature: 'bXYZ'. + */ + public static final int icSigBlueColorantTag = 0x6258595A; /* 'bXYZ' */ + + /** + * ICC Profile Tag Signature: 'bXYZ'. + * @since 1.5 + */ + public static final int icSigBlueMatrixColumnTag = 0x6258595A; /* 'bXYZ' */ + + /** + * ICC Profile Tag Signature: 'bTRC'. + */ + public static final int icSigBlueTRCTag = 0x62545243; /* 'bTRC' */ + + /** + * ICC Profile Tag Signature: 'B2A0'. + */ + public static final int icSigBToA0Tag = 0x42324130; /* 'B2A0' */ + + /** + * ICC Profile Tag Signature: 'B2A1'. + */ + public static final int icSigBToA1Tag = 0x42324131; /* 'B2A1' */ + + /** + * ICC Profile Tag Signature: 'B2A2'. + */ + public static final int icSigBToA2Tag = 0x42324132; /* 'B2A2' */ + + /** + * ICC Profile Tag Signature: 'calt'. + */ + public static final int icSigCalibrationDateTimeTag = 0x63616C74; + /* 'calt' */ + + /** + * ICC Profile Tag Signature: 'targ'. + */ + public static final int icSigCharTargetTag = 0x74617267; /* 'targ' */ + + /** + * ICC Profile Tag Signature: 'cprt'. + */ + public static final int icSigCopyrightTag = 0x63707274; /* 'cprt' */ + + /** + * ICC Profile Tag Signature: 'crdi'. + */ + public static final int icSigCrdInfoTag = 0x63726469; /* 'crdi' */ + + /** + * ICC Profile Tag Signature: 'dmnd'. + */ + public static final int icSigDeviceMfgDescTag = 0x646D6E64; /* 'dmnd' */ + + /** + * ICC Profile Tag Signature: 'dmdd'. + */ + public static final int icSigDeviceModelDescTag = 0x646D6464; /* 'dmdd' */ + + /** + * ICC Profile Tag Signature: 'devs'. + */ + public static final int icSigDeviceSettingsTag = 0x64657673; /* 'devs' */ + + /** + * ICC Profile Tag Signature: 'gamt'. + */ + public static final int icSigGamutTag = 0x67616D74; /* 'gamt' */ + + /** + * ICC Profile Tag Signature: 'kTRC'. + */ + public static final int icSigGrayTRCTag = 0x6b545243; /* 'kTRC' */ + + /** + * ICC Profile Tag Signature: 'gXYZ'. + */ + public static final int icSigGreenColorantTag = 0x6758595A; /* 'gXYZ' */ + + /** + * ICC Profile Tag Signature: 'gXYZ'. + * @since 1.5 + */ + public static final int icSigGreenMatrixColumnTag = 0x6758595A;/* 'gXYZ' */ + + /** + * ICC Profile Tag Signature: 'gTRC'. + */ + public static final int icSigGreenTRCTag = 0x67545243; /* 'gTRC' */ + + /** + * ICC Profile Tag Signature: 'lumi'. + */ + public static final int icSigLuminanceTag = 0x6C756d69; /* 'lumi' */ + + /** + * ICC Profile Tag Signature: 'meas'. + */ + public static final int icSigMeasurementTag = 0x6D656173; /* 'meas' */ + + /** + * ICC Profile Tag Signature: 'bkpt'. + */ + public static final int icSigMediaBlackPointTag = 0x626B7074; /* 'bkpt' */ + + /** + * ICC Profile Tag Signature: 'wtpt'. + */ + public static final int icSigMediaWhitePointTag = 0x77747074; /* 'wtpt' */ + + /** + * ICC Profile Tag Signature: 'ncl2'. + */ + public static final int icSigNamedColor2Tag = 0x6E636C32; /* 'ncl2' */ + + /** + * ICC Profile Tag Signature: 'resp'. + */ + public static final int icSigOutputResponseTag = 0x72657370; /* 'resp' */ + + /** + * ICC Profile Tag Signature: 'pre0'. + */ + public static final int icSigPreview0Tag = 0x70726530; /* 'pre0' */ + + /** + * ICC Profile Tag Signature: 'pre1'. + */ + public static final int icSigPreview1Tag = 0x70726531; /* 'pre1' */ + + /** + * ICC Profile Tag Signature: 'pre2'. + */ + public static final int icSigPreview2Tag = 0x70726532; /* 'pre2' */ + + /** + * ICC Profile Tag Signature: 'desc'. + */ + public static final int icSigProfileDescriptionTag = 0x64657363; + /* 'desc' */ + + /** + * ICC Profile Tag Signature: 'pseq'. + */ + public static final int icSigProfileSequenceDescTag = 0x70736571; + /* 'pseq' */ + + /** + * ICC Profile Tag Signature: 'psd0'. + */ + public static final int icSigPs2CRD0Tag = 0x70736430; /* 'psd0' */ + + /** + * ICC Profile Tag Signature: 'psd1'. + */ + public static final int icSigPs2CRD1Tag = 0x70736431; /* 'psd1' */ + + /** + * ICC Profile Tag Signature: 'psd2'. + */ + public static final int icSigPs2CRD2Tag = 0x70736432; /* 'psd2' */ + + /** + * ICC Profile Tag Signature: 'psd3'. + */ + public static final int icSigPs2CRD3Tag = 0x70736433; /* 'psd3' */ + + /** + * ICC Profile Tag Signature: 'ps2s'. + */ + public static final int icSigPs2CSATag = 0x70733273; /* 'ps2s' */ + + /** + * ICC Profile Tag Signature: 'ps2i'. + */ + public static final int icSigPs2RenderingIntentTag = 0x70733269; + /* 'ps2i' */ + + /** + * ICC Profile Tag Signature: 'rXYZ'. + */ + public static final int icSigRedColorantTag = 0x7258595A; /* 'rXYZ' */ + + /** + * ICC Profile Tag Signature: 'rXYZ'. + * @since 1.5 + */ + public static final int icSigRedMatrixColumnTag = 0x7258595A; /* 'rXYZ' */ + + /** + * ICC Profile Tag Signature: 'rTRC'. + */ + public static final int icSigRedTRCTag = 0x72545243; /* 'rTRC' */ + + /** + * ICC Profile Tag Signature: 'scrd'. + */ + public static final int icSigScreeningDescTag = 0x73637264; /* 'scrd' */ + + /** + * ICC Profile Tag Signature: 'scrn'. + */ + public static final int icSigScreeningTag = 0x7363726E; /* 'scrn' */ + + /** + * ICC Profile Tag Signature: 'tech'. + */ + public static final int icSigTechnologyTag = 0x74656368; /* 'tech' */ + + /** + * ICC Profile Tag Signature: 'bfd '. + */ + public static final int icSigUcrBgTag = 0x62666420; /* 'bfd ' */ + + /** + * ICC Profile Tag Signature: 'vued'. + */ + public static final int icSigViewingCondDescTag = 0x76756564; /* 'vued' */ + + /** + * ICC Profile Tag Signature: 'view'. + */ + public static final int icSigViewingConditionsTag = 0x76696577;/* 'view' */ + + /** + * ICC Profile Tag Signature: 'chrm'. + */ + public static final int icSigChromaticityTag = 0x6368726d; /* 'chrm' */ + + /** + * ICC Profile Tag Signature: 'chad'. + * @since 1.5 + */ + public static final int icSigChromaticAdaptationTag = 0x63686164;/* 'chad' */ + + /** + * ICC Profile Tag Signature: 'clro'. + * @since 1.5 + */ + public static final int icSigColorantOrderTag = 0x636C726F; /* 'clro' */ + + /** + * ICC Profile Tag Signature: 'clrt'. + * @since 1.5 + */ + public static final int icSigColorantTableTag = 0x636C7274; /* 'clrt' */ + + + /** + * ICC Profile Header Location: profile size in bytes. + */ + public static final int icHdrSize = 0; /* Profile size in bytes */ + + /** + * ICC Profile Header Location: CMM for this profile. + */ + public static final int icHdrCmmId = 4; /* CMM for this profile */ + + /** + * ICC Profile Header Location: format version number. + */ + public static final int icHdrVersion = 8; /* Format version number */ + + /** + * ICC Profile Header Location: type of profile. + */ + public static final int icHdrDeviceClass = 12; /* Type of profile */ + + /** + * ICC Profile Header Location: color space of data. + */ + public static final int icHdrColorSpace = 16; /* Color space of data */ + + /** + * ICC Profile Header Location: PCS - XYZ or Lab only. + */ + public static final int icHdrPcs = 20; /* PCS - XYZ or Lab only */ + + /** + * ICC Profile Header Location: date profile was created. + */ + public static final int icHdrDate = 24; /* Date profile was created */ + + /** + * ICC Profile Header Location: icMagicNumber. + */ + public static final int icHdrMagic = 36; /* icMagicNumber */ + + /** + * ICC Profile Header Location: primary platform. + */ + public static final int icHdrPlatform = 40; /* Primary Platform */ + + /** + * ICC Profile Header Location: various bit settings. + */ + public static final int icHdrFlags = 44; /* Various bit settings */ + + /** + * ICC Profile Header Location: device manufacturer. + */ + public static final int icHdrManufacturer = 48; /* Device manufacturer */ + + /** + * ICC Profile Header Location: device model number. + */ + public static final int icHdrModel = 52; /* Device model number */ + + /** + * ICC Profile Header Location: device attributes. + */ + public static final int icHdrAttributes = 56; /* Device attributes */ + + /** + * ICC Profile Header Location: rendering intent. + */ + public static final int icHdrRenderingIntent = 64; /* Rendering intent */ + + /** + * ICC Profile Header Location: profile illuminant. + */ + public static final int icHdrIlluminant = 68; /* Profile illuminant */ + + /** + * ICC Profile Header Location: profile creator. + */ + public static final int icHdrCreator = 80; /* Profile creator */ + + /** + * ICC Profile Header Location: profile's ID. + * @since 1.5 + */ + public static final int icHdrProfileID = 84; /* Profile's ID */ + + + /** + * ICC Profile Constant: tag type signaturE. + */ + public static final int icTagType = 0; /* tag type signature */ + + /** + * ICC Profile Constant: reserved. + */ + public static final int icTagReserved = 4; /* reserved */ + + /** + * ICC Profile Constant: curveType count. + */ + public static final int icCurveCount = 8; /* curveType count */ + + /** + * ICC Profile Constant: curveType data. + */ + public static final int icCurveData = 12; /* curveType data */ + + /** + * ICC Profile Constant: XYZNumber X. + */ + public static final int icXYZNumberX = 8; /* XYZNumber X */ + + + /** + * Constructs an ICC_Profile object with a given ID. + */ + ICC_Profile(long ID) { + this.ID = ID; + } + + + /** + * Constructs an ICC_Profile object whose loading will be deferred. + * The ID will be 0 until the profile is loaded. + */ + ICC_Profile(ProfileDeferralInfo pdi) { + this.deferralInfo = pdi; + this.profileActivator = new ProfileActivator() { + public void activate() { + activateDeferredProfile(); + } + }; + ProfileDeferralMgr.registerDeferral(this.profileActivator); + } + + + /** + * Frees the resources associated with an ICC_Profile object. + */ + protected void finalize () { + if (ID != 0) { + CMSManager.getModule().freeProfile(ID); + } else if (profileActivator != null) { + ProfileDeferralMgr.unregisterDeferral(profileActivator); + } + } + + + /** + * Constructs an ICC_Profile object corresponding to the data in + * a byte array. Throws an IllegalArgumentException if the data + * does not correspond to a valid ICC Profile. + * @param data the specified ICC Profile data + * @return an ICC_Profile object corresponding to + * the data in the specified data array. + */ + public static ICC_Profile getInstance(byte[] data) { + ICC_Profile thisProfile; + + long theID; + + if (ProfileDeferralMgr.deferring) { + ProfileDeferralMgr.activateProfiles(); + } + + try { + theID = CMSManager.getModule().loadProfile(data); + } catch (CMMException c) { + throw new IllegalArgumentException("Invalid ICC Profile Data"); + } + + try { + if ((getColorSpaceType (theID) == ColorSpace.TYPE_GRAY) && + (getData (theID, icSigMediaWhitePointTag) != null) && + (getData (theID, icSigGrayTRCTag) != null)) { + thisProfile = new ICC_ProfileGray (theID); + } + else if ((getColorSpaceType (theID) == ColorSpace.TYPE_RGB) && + (getData (theID, icSigMediaWhitePointTag) != null) && + (getData (theID, icSigRedColorantTag) != null) && + (getData (theID, icSigGreenColorantTag) != null) && + (getData (theID, icSigBlueColorantTag) != null) && + (getData (theID, icSigRedTRCTag) != null) && + (getData (theID, icSigGreenTRCTag) != null) && + (getData (theID, icSigBlueTRCTag) != null)) { + thisProfile = new ICC_ProfileRGB (theID); + } + else { + thisProfile = new ICC_Profile (theID); + } + } catch (CMMException c) { + thisProfile = new ICC_Profile (theID); + } + return thisProfile; + } + + + + /** + * Constructs an ICC_Profile corresponding to one of the specific color + * spaces defined by the ColorSpace class (for example CS_sRGB). + * Throws an IllegalArgumentException if cspace is not one of the + * defined color spaces. + * + * @param cspace the type of color space to create a profile for. + * The specified type is one of the color + * space constants defined in the ColorSpace class. + * + * @return an ICC_Profile object corresponding to + * the specified ColorSpace type. + * @exception IllegalArgumentException If cspace is not + * one of the predefined color space types. + */ + public static ICC_Profile getInstance (int cspace) { + ICC_Profile thisProfile = null; + String fileName; + + switch (cspace) { + case ColorSpace.CS_sRGB: + synchronized(ICC_Profile.class) { + if (sRGBprofile == null) { + try { + /* + * Deferral is only used for standard profiles. + * Enabling the appropriate access privileges is handled + * at a lower level. + */ + sRGBprofile = getDeferredInstance( + new ProfileDeferralInfo("sRGB.pf", + ColorSpace.TYPE_RGB, + 3, CLASS_DISPLAY)); + } catch (IOException e) { + throw new IllegalArgumentException( + "Can't load standard profile: sRGB.pf"); + } + } + thisProfile = sRGBprofile; + } + + break; + + case ColorSpace.CS_CIEXYZ: + synchronized(ICC_Profile.class) { + if (XYZprofile == null) { + XYZprofile = getStandardProfile("CIEXYZ.pf"); + } + thisProfile = XYZprofile; + } + + break; + + case ColorSpace.CS_PYCC: + synchronized(ICC_Profile.class) { + if (PYCCprofile == null) { + PYCCprofile = getStandardProfile("PYCC.pf"); + } + thisProfile = PYCCprofile; + } + + break; + + case ColorSpace.CS_GRAY: + synchronized(ICC_Profile.class) { + if (GRAYprofile == null) { + GRAYprofile = getStandardProfile("GRAY.pf"); + } + thisProfile = GRAYprofile; + } + + break; + + case ColorSpace.CS_LINEAR_RGB: + synchronized(ICC_Profile.class) { + if (LINEAR_RGBprofile == null) { + LINEAR_RGBprofile = getStandardProfile("LINEAR_RGB.pf"); + } + thisProfile = LINEAR_RGBprofile; + } + + break; + + default: + throw new IllegalArgumentException("Unknown color space"); + } + + return thisProfile; + } + + /* This asserts system privileges, so is used only for the + * standard profiles. + */ + private static ICC_Profile getStandardProfile(final String name) { + + return (ICC_Profile) AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + ICC_Profile p = null; + try { + p = getInstance (name); + } catch (IOException ex) { + throw new IllegalArgumentException( + "Can't load standard profile: " + name); + } + return p; + } + }); + } + + /** + * Constructs an ICC_Profile corresponding to the data in a file. + * fileName may be an absolute or a relative file specification. + * Relative file names are looked for in several places: first, relative + * to any directories specified by the java.iccprofile.path property; + * second, relative to any directories specified by the java.class.path + * property; finally, in a directory used to store profiles always + * available, such as the profile for sRGB. Built-in profiles use .pf as + * the file name extension for profiles, e.g. sRGB.pf. + * This method throws an IOException if the specified file cannot be + * opened or if an I/O error occurs while reading the file. It throws + * an IllegalArgumentException if the file does not contain valid ICC + * Profile data. + * @param fileName The file that contains the data for the profile. + * + * @return an ICC_Profile object corresponding to + * the data in the specified file. + * @exception IOException If the specified file cannot be opened or + * an I/O error occurs while reading the file. + * + * @exception IllegalArgumentException If the file does not + * contain valid ICC Profile data. + * + * @exception SecurityException If a security manager is installed + * and it does not permit read access to the given file. + */ + public static ICC_Profile getInstance(String fileName) throws IOException { + ICC_Profile thisProfile; + FileInputStream fis; + + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkRead(fileName); + } + + if ((fis = openProfile(fileName)) == null) { + throw new IOException("Cannot open file " + fileName); + } + + thisProfile = getInstance(fis); + + fis.close(); /* close the file */ + + return thisProfile; + } + + + /** + * Constructs an ICC_Profile corresponding to the data in an InputStream. + * This method throws an IllegalArgumentException if the stream does not + * contain valid ICC Profile data. It throws an IOException if an I/O + * error occurs while reading the stream. + * @param s The input stream from which to read the profile data. + * + * @return an ICC_Profile object corresponding to the + * data in the specified InputStream. + * + * @exception IOException If an I/O error occurs while reading the stream. + * + * @exception IllegalArgumentException If the stream does not + * contain valid ICC Profile data. + */ + public static ICC_Profile getInstance(InputStream s) throws IOException { + byte profileData[]; + + if (s instanceof ProfileDeferralInfo) { + /* hack to detect profiles whose loading can be deferred */ + return getDeferredInstance((ProfileDeferralInfo) s); + } + + if ((profileData = getProfileDataFromStream(s)) == null) { + throw new IllegalArgumentException("Invalid ICC Profile Data"); + } + + return getInstance(profileData); + } + + + static byte[] getProfileDataFromStream(InputStream s) throws IOException { + byte profileData[]; + int profileSize; + + byte header[] = new byte[128]; + int bytestoread = 128; + int bytesread = 0; + int n; + + while (bytestoread != 0) { + if ((n = s.read(header, bytesread, bytestoread)) < 0) { + return null; + } + bytesread += n; + bytestoread -= n; + } + if (header[36] != 0x61 || header[37] != 0x63 || + header[38] != 0x73 || header[39] != 0x70) { + return null; /* not a valid profile */ + } + profileSize = ((header[0] & 0xff) << 24) | + ((header[1] & 0xff) << 16) | + ((header[2] & 0xff) << 8) | + (header[3] & 0xff); + profileData = new byte[profileSize]; + System.arraycopy(header, 0, profileData, 0, 128); + bytestoread = profileSize - 128; + bytesread = 128; + while (bytestoread != 0) { + if ((n = s.read(profileData, bytesread, bytestoread)) < 0) { + return null; + } + bytesread += n; + bytestoread -= n; + } + + return profileData; + } + + + /** + * Constructs an ICC_Profile for which the actual loading of the + * profile data from a file and the initialization of the CMM should + * be deferred as long as possible. + * Deferral is only used for standard profiles. + * If deferring is disabled, then getStandardProfile() ensures + * that all of the appropriate access privileges are granted + * when loading this profile. + * If deferring is enabled, then the deferred activation + * code will take care of access privileges. + * @see activateDeferredProfile() + */ + static ICC_Profile getDeferredInstance(ProfileDeferralInfo pdi) + throws IOException { + + if (!ProfileDeferralMgr.deferring) { + return getStandardProfile(pdi.filename); + } + if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) { + return new ICC_ProfileRGB(pdi); + } else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) { + return new ICC_ProfileGray(pdi); + } else { + return new ICC_Profile(pdi); + } + } + + + void activateDeferredProfile() { + byte profileData[]; + FileInputStream fis; + String fileName = deferralInfo.filename; + + profileActivator = null; + deferralInfo = null; + if ((fis = openProfile(fileName)) == null) { + throw new IllegalArgumentException("Cannot open file " + fileName); + } + try { + profileData = getProfileDataFromStream(fis); + fis.close(); /* close the file */ + } + catch (IOException e) { + throw new IllegalArgumentException("Invalid ICC Profile Data" + + fileName); + } + if (profileData == null) { + throw new IllegalArgumentException("Invalid ICC Profile Data" + + fileName); + } + try { + ID = CMSManager.getModule().loadProfile(profileData); + } catch (CMMException c) { + throw new IllegalArgumentException("Invalid ICC Profile Data" + + fileName); + } + } + + + /** + * Returns profile major version. + * @return The major version of the profile. + */ + public int getMajorVersion() { + byte[] theHeader; + + theHeader = getData(icSigHead); /* getData will activate deferred + profiles if necessary */ + + return (int) theHeader[8]; + } + + /** + * Returns profile minor version. + * @return The minor version of the profile. + */ + public int getMinorVersion() { + byte[] theHeader; + + theHeader = getData(icSigHead); /* getData will activate deferred + profiles if necessary */ + + return (int) theHeader[9]; + } + + /** + * Returns the profile class. + * @return One of the predefined profile class constants. + */ + public int getProfileClass() { + byte[] theHeader; + int theClassSig, theClass; + + if (deferralInfo != null) { + return deferralInfo.profileClass; /* Need to have this info for + ICC_ColorSpace without + causing a deferred profile + to be loaded */ + } + + theHeader = getData(icSigHead); + + theClassSig = intFromBigEndian (theHeader, icHdrDeviceClass); + + switch (theClassSig) { + case icSigInputClass: + theClass = CLASS_INPUT; + break; + + case icSigDisplayClass: + theClass = CLASS_DISPLAY; + break; + + case icSigOutputClass: + theClass = CLASS_OUTPUT; + break; + + case icSigLinkClass: + theClass = CLASS_DEVICELINK; + break; + + case icSigColorSpaceClass: + theClass = CLASS_COLORSPACECONVERSION; + break; + + case icSigAbstractClass: + theClass = CLASS_ABSTRACT; + break; + + case icSigNamedColorClass: + theClass = CLASS_NAMEDCOLOR; + break; + + default: + throw new IllegalArgumentException("Unknown profile class"); + } + + return theClass; + } + + /** + * Returns the color space type. Returns one of the color space type + * constants defined by the ColorSpace class. This is the + * "input" color space of the profile. The type defines the + * number of components of the color space and the interpretation, + * e.g. TYPE_RGB identifies a color space with three components - red, + * green, and blue. It does not define the particular color + * characteristics of the space, e.g. the chromaticities of the + * primaries. + * @return One of the color space type constants defined in the + * ColorSpace class. + */ + public int getColorSpaceType() { + if (deferralInfo != null) { + return deferralInfo.colorSpaceType; /* Need to have this info for + ICC_ColorSpace without + causing a deferred profile + to be loaded */ + } + return getColorSpaceType(ID); + } + + static int getColorSpaceType(long profileID) { + byte[] theHeader; + int theColorSpaceSig, theColorSpace; + + theHeader = getData(profileID, icSigHead); + theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace); + theColorSpace = iccCStoJCS (theColorSpaceSig); + return theColorSpace; + } + + /** + * Returns the color space type of the Profile Connection Space (PCS). + * Returns one of the color space type constants defined by the + * ColorSpace class. This is the "output" color space of the + * profile. For an input, display, or output profile useful + * for tagging colors or images, this will be either TYPE_XYZ or + * TYPE_Lab and should be interpreted as the corresponding specific + * color space defined in the ICC specification. For a device + * link profile, this could be any of the color space type constants. + * @return One of the color space type constants defined in the + * ColorSpace class. + */ + public int getPCSType() { + if (ProfileDeferralMgr.deferring) { + ProfileDeferralMgr.activateProfiles(); + } + return getPCSType(ID); + } + + + static int getPCSType(long profileID) { + byte[] theHeader; + int thePCSSig, thePCS; + + theHeader = getData(profileID, icSigHead); + thePCSSig = intFromBigEndian(theHeader, icHdrPcs); + thePCS = iccCStoJCS(thePCSSig); + return thePCS; + } + + + /** + * Write this ICC_Profile to a file. + * + * @param fileName The file to write the profile data to. + * + * @exception IOException If the file cannot be opened for writing + * or an I/O error occurs while writing to the file. + */ + public void write(String fileName) throws IOException { + FileOutputStream outputFile; + byte profileData[]; + + profileData = getData(); /* this will activate deferred + profiles if necessary */ + outputFile = new FileOutputStream(fileName); + outputFile.write(profileData); + outputFile.close (); + } + + + /** + * Write this ICC_Profile to an OutputStream. + * + * @param s The stream to write the profile data to. + * + * @exception IOException If an I/O error occurs while writing to the + * stream. + */ + public void write(OutputStream s) throws IOException { + byte profileData[]; + + profileData = getData(); /* this will activate deferred + profiles if necessary */ + s.write(profileData); + } + + + /** + * Returns a byte array corresponding to the data of this ICC_Profile. + * @return A byte array that contains the profile data. + * @see #setData(int, byte[]) + */ + public byte[] getData() { + int profileSize; + byte[] profileData; + + if (ProfileDeferralMgr.deferring) { + ProfileDeferralMgr.activateProfiles(); + } + + PCMM mdl = CMSManager.getModule(); + + /* get the number of bytes needed for this profile */ + profileSize = mdl.getProfileSize(ID); + + profileData = new byte [profileSize]; + + /* get the data for the profile */ + mdl.getProfileData(ID, profileData); + + return profileData; + } + + + /** + * Returns a particular tagged data element from the profile as + * a byte array. Elements are identified by signatures + * as defined in the ICC specification. The signature + * icSigHead can be used to get the header. This method is useful + * for advanced applets or applications which need to access + * profile data directly. + * + * @param tagSignature The ICC tag signature for the data element you + * want to get. + * + * @return A byte array that contains the tagged data element. Returns + * null if the specified tag doesn't exist. + * @see #setData(int, byte[]) + */ + public byte[] getData(int tagSignature) { + + if (ProfileDeferralMgr.deferring) { + ProfileDeferralMgr.activateProfiles(); + } + + return getData(ID, tagSignature); + } + + + static byte[] getData(long profileID, int tagSignature) { + int tagSize; + byte[] tagData; + + try { + PCMM mdl = CMSManager.getModule(); + + /* get the number of bytes needed for this tag */ + tagSize = mdl.getTagSize(profileID, tagSignature); + + tagData = new byte[tagSize]; /* get an array for the tag */ + + /* get the tag's data */ + mdl.getTagData(profileID, tagSignature, tagData); + } catch(CMMException c) { + tagData = null; + } + + return tagData; + } + + /** + * Sets a particular tagged data element in the profile from + * a byte array. This method is useful + * for advanced applets or applications which need to access + * profile data directly. + * + * @param tagSignature The ICC tag signature for the data element + * you want to set. + * @param tagData the data to set for the specified tag signature + * @see #getData + */ + public void setData(int tagSignature, byte[] tagData) { + + if (ProfileDeferralMgr.deferring) { + ProfileDeferralMgr.activateProfiles(); + } + + CMSManager.getModule().setTagData(ID, tagSignature, tagData); + } + + /** + * Sets the rendering intent of the profile. + * This is used to select the proper transform from a profile that + * has multiple transforms. + */ + void setRenderingIntent(int renderingIntent) { + byte[] theHeader = getData(icSigHead);/* getData will activate deferred + profiles if necessary */ + intToBigEndian (renderingIntent, theHeader, icHdrRenderingIntent); + /* set the rendering intent */ + setData (icSigHead, theHeader); + } + + + /** + * Returns the rendering intent of the profile. + * This is used to select the proper transform from a profile that + * has multiple transforms. It is typically set in a source profile + * to select a transform from an output profile. + */ + int getRenderingIntent() { + byte[] theHeader = getData(icSigHead);/* getData will activate deferred + profiles if necessary */ + + int renderingIntent = intFromBigEndian(theHeader, icHdrRenderingIntent); + /* set the rendering intent */ + return renderingIntent; + } + + + /** + * Returns the number of color components in the "input" color + * space of this profile. For example if the color space type + * of this profile is TYPE_RGB, then this method will return 3. + * + * @return The number of color components in the profile's input + * color space. + * + * @throws ProfileDataException if color space is in the profile + * is invalid + */ + public int getNumComponents() { + byte[] theHeader; + int theColorSpaceSig, theNumComponents; + + if (deferralInfo != null) { + return deferralInfo.numComponents; /* Need to have this info for + ICC_ColorSpace without + causing a deferred profile + to be loaded */ + } + theHeader = getData(icSigHead); + + theColorSpaceSig = intFromBigEndian (theHeader, icHdrColorSpace); + + switch (theColorSpaceSig) { + case icSigGrayData: + theNumComponents = 1; + break; + + case icSigSpace2CLR: + theNumComponents = 2; + break; + + case icSigXYZData: + case icSigLabData: + case icSigLuvData: + case icSigYCbCrData: + case icSigYxyData: + case icSigRgbData: + case icSigHsvData: + case icSigHlsData: + case icSigCmyData: + case icSigSpace3CLR: + theNumComponents = 3; + break; + + case icSigCmykData: + case icSigSpace4CLR: + theNumComponents = 4; + break; + + case icSigSpace5CLR: + theNumComponents = 5; + break; + + case icSigSpace6CLR: + theNumComponents = 6; + break; + + case icSigSpace7CLR: + theNumComponents = 7; + break; + + case icSigSpace8CLR: + theNumComponents = 8; + break; + + case icSigSpace9CLR: + theNumComponents = 9; + break; + + case icSigSpaceACLR: + theNumComponents = 10; + break; + + case icSigSpaceBCLR: + theNumComponents = 11; + break; + + case icSigSpaceCCLR: + theNumComponents = 12; + break; + + case icSigSpaceDCLR: + theNumComponents = 13; + break; + + case icSigSpaceECLR: + theNumComponents = 14; + break; + + case icSigSpaceFCLR: + theNumComponents = 15; + break; + + default: + throw new ProfileDataException ("invalid ICC color space"); + } + + return theNumComponents; + } + + + /** + * Returns a float array of length 3 containing the X, Y, and Z + * components of the mediaWhitePointTag in the ICC profile. + */ + float[] getMediaWhitePoint() { + return getXYZTag(icSigMediaWhitePointTag); + /* get the media white point tag */ + } + + + /** + * Returns a float array of length 3 containing the X, Y, and Z + * components encoded in an XYZType tag. + */ + float[] getXYZTag(int theTagSignature) { + byte[] theData; + float[] theXYZNumber; + int i1, i2, theS15Fixed16; + + theData = getData(theTagSignature); /* get the tag data */ + /* getData will activate deferred + profiles if necessary */ + + theXYZNumber = new float [3]; /* array to return */ + + /* convert s15Fixed16Number to float */ + for (i1 = 0, i2 = icXYZNumberX; i1 < 3; i1++, i2 += 4) { + theS15Fixed16 = intFromBigEndian(theData, i2); + theXYZNumber [i1] = ((float) theS15Fixed16) / 65536.0f; + } + return theXYZNumber; + } + + + /** + * Returns a gamma value representing a tone reproduction + * curve (TRC). If the profile represents the TRC as a table rather + * than a single gamma value, then an exception is thrown. In this + * case the actual table can be obtained via getTRC(). + * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag, + * icSigGreenTRCTag, or icSigBlueTRCTag. + * @return the gamma value as a float. + * @exception ProfileDataException if the profile does not specify + * the TRC as a single gamma value. + */ + float getGamma(int theTagSignature) { + byte[] theTRCData; + float theGamma; + int theU8Fixed8; + + theTRCData = getData(theTagSignature); /* get the TRC */ + /* getData will activate deferred + profiles if necessary */ + + if (intFromBigEndian (theTRCData, icCurveCount) != 1) { + throw new ProfileDataException ("TRC is not a gamma"); + } + + /* convert u8Fixed8 to float */ + theU8Fixed8 = (shortFromBigEndian(theTRCData, icCurveData)) & 0xffff; + + theGamma = ((float) theU8Fixed8) / 256.0f; + + return theGamma; + } + + + /** + * Returns the TRC as an array of shorts. If the profile has + * specified the TRC as linear (gamma = 1.0) or as a simple gamma + * value, this method throws an exception, and the getGamma() method + * should be used to get the gamma value. Otherwise the short array + * returned here represents a lookup table where the input Gray value + * is conceptually in the range [0.0, 1.0]. Value 0.0 maps + * to array index 0 and value 1.0 maps to array index length-1. + * Interpolation may be used to generate output values for + * input values which do not map exactly to an index in the + * array. Output values also map linearly to the range [0.0, 1.0]. + * Value 0.0 is represented by an array value of 0x0000 and + * value 1.0 by 0xFFFF, i.e. the values are really unsigned + * short values, although they are returned in a short array. + * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag, + * icSigGreenTRCTag, or icSigBlueTRCTag. + * @return a short array representing the TRC. + * @exception ProfileDataException if the profile does not specify + * the TRC as a table. + */ + short[] getTRC(int theTagSignature) { + byte[] theTRCData; + short[] theTRC; + int i1, i2, nElements, theU8Fixed8; + + theTRCData = getData(theTagSignature); /* get the TRC */ + /* getData will activate deferred + profiles if necessary */ + + nElements = intFromBigEndian(theTRCData, icCurveCount); + + if (nElements == 1) { + throw new ProfileDataException("TRC is not a table"); + } + + /* make the short array */ + theTRC = new short [nElements]; + + for (i1 = 0, i2 = icCurveData; i1 < nElements; i1++, i2 += 2) { + theTRC[i1] = shortFromBigEndian(theTRCData, i2); + } + + return theTRC; + } + + + /* convert an ICC color space signature into a Java color space type */ + static int iccCStoJCS(int theColorSpaceSig) { + int theColorSpace; + + switch (theColorSpaceSig) { + case icSigXYZData: + theColorSpace = ColorSpace.TYPE_XYZ; + break; + + case icSigLabData: + theColorSpace = ColorSpace.TYPE_Lab; + break; + + case icSigLuvData: + theColorSpace = ColorSpace.TYPE_Luv; + break; + + case icSigYCbCrData: + theColorSpace = ColorSpace.TYPE_YCbCr; + break; + + case icSigYxyData: + theColorSpace = ColorSpace.TYPE_Yxy; + break; + + case icSigRgbData: + theColorSpace = ColorSpace.TYPE_RGB; + break; + + case icSigGrayData: + theColorSpace = ColorSpace.TYPE_GRAY; + break; + + case icSigHsvData: + theColorSpace = ColorSpace.TYPE_HSV; + break; + + case icSigHlsData: + theColorSpace = ColorSpace.TYPE_HLS; + break; + + case icSigCmykData: + theColorSpace = ColorSpace.TYPE_CMYK; + break; + + case icSigCmyData: + theColorSpace = ColorSpace.TYPE_CMY; + break; + + case icSigSpace2CLR: + theColorSpace = ColorSpace.TYPE_2CLR; + break; + + case icSigSpace3CLR: + theColorSpace = ColorSpace.TYPE_3CLR; + break; + + case icSigSpace4CLR: + theColorSpace = ColorSpace.TYPE_4CLR; + break; + + case icSigSpace5CLR: + theColorSpace = ColorSpace.TYPE_5CLR; + break; + + case icSigSpace6CLR: + theColorSpace = ColorSpace.TYPE_6CLR; + break; + + case icSigSpace7CLR: + theColorSpace = ColorSpace.TYPE_7CLR; + break; + + case icSigSpace8CLR: + theColorSpace = ColorSpace.TYPE_8CLR; + break; + + case icSigSpace9CLR: + theColorSpace = ColorSpace.TYPE_9CLR; + break; + + case icSigSpaceACLR: + theColorSpace = ColorSpace.TYPE_ACLR; + break; + + case icSigSpaceBCLR: + theColorSpace = ColorSpace.TYPE_BCLR; + break; + + case icSigSpaceCCLR: + theColorSpace = ColorSpace.TYPE_CCLR; + break; + + case icSigSpaceDCLR: + theColorSpace = ColorSpace.TYPE_DCLR; + break; + + case icSigSpaceECLR: + theColorSpace = ColorSpace.TYPE_ECLR; + break; + + case icSigSpaceFCLR: + theColorSpace = ColorSpace.TYPE_FCLR; + break; + + default: + throw new IllegalArgumentException ("Unknown color space"); + } + + return theColorSpace; + } + + + static int intFromBigEndian(byte[] array, int index) { + return (((array[index] & 0xff) << 24) | + ((array[index+1] & 0xff) << 16) | + ((array[index+2] & 0xff) << 8) | + (array[index+3] & 0xff)); + } + + + static void intToBigEndian(int value, byte[] array, int index) { + array[index] = (byte) (value >> 24); + array[index+1] = (byte) (value >> 16); + array[index+2] = (byte) (value >> 8); + array[index+3] = (byte) (value); + } + + + static short shortFromBigEndian(byte[] array, int index) { + return (short) (((array[index] & 0xff) << 8) | + (array[index+1] & 0xff)); + } + + + static void shortToBigEndian(short value, byte[] array, int index) { + array[index] = (byte) (value >> 8); + array[index+1] = (byte) (value); + } + + + /* + * fileName may be an absolute or a relative file specification. + * Relative file names are looked for in several places: first, relative + * to any directories specified by the java.iccprofile.path property; + * second, relative to any directories specified by the java.class.path + * property; finally, in a directory used to store profiles always + * available, such as a profile for sRGB. Built-in profiles use .pf as + * the file name extension for profiles, e.g. sRGB.pf. + */ + private static FileInputStream openProfile(final String fileName) { + return (FileInputStream)java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Object run() { + return privilegedOpenProfile(fileName); + } + }); + } + + /* + * this version is called from doPrivileged in privilegedOpenProfile. + * the whole method is privileged! + */ + private static FileInputStream privilegedOpenProfile(String fileName) { + FileInputStream fis = null; + String path, dir, fullPath; + + File f = new File(fileName); /* try absolute file name */ + + if ((!f.isFile()) && + ((path = System.getProperty("java.iccprofile.path")) != null)){ + /* try relative to java.iccprofile.path */ + StringTokenizer st = + new StringTokenizer(path, File.pathSeparator); + while (st.hasMoreTokens() && (!f.isFile())) { + dir = st.nextToken(); + fullPath = dir + File.separatorChar + fileName; + f = new File(fullPath); + } + } + + if ((!f.isFile()) && + ((path = System.getProperty("java.class.path")) != null)) { + /* try relative to java.class.path */ + StringTokenizer st = + new StringTokenizer(path, File.pathSeparator); + while (st.hasMoreTokens() && (!f.isFile())) { + dir = st.nextToken(); + fullPath = dir + File.separatorChar + fileName; + f = new File(fullPath); + } + } + + if (!f.isFile()) { /* try the directory of built-in profiles */ + dir = System.getProperty("java.home") + + File.separatorChar + "lib" + File.separatorChar + "cmm"; + fullPath = dir + File.separatorChar + fileName; + f = new File(fullPath); + } + + if (f.isFile()) { + try { + fis = new FileInputStream(f); + } catch (FileNotFoundException e) { + } + } + return fis; + } + + + /* + * Serialization support. + * + * Directly deserialized profiles are useless since they are not + * registered with CMM. We don't allow constructor to be called + * directly and instead have clients to call one of getInstance + * factory methods that will register the profile with CMM. For + * deserialization we implement readResolve method that will + * resolve the bogus deserialized profile object with one obtained + * with getInstance as well. + * + * There're two primary factory methods for construction of ICC + * profiles: getInstance(int cspace) and getInstance(byte[] data). + * This implementation of ICC_Profile uses the former to return a + * cached singleton profile object, other implementations will + * likely use this technique too. To preserve the singleton + * pattern across serialization we serialize cached singleton + * profiles in such a way that deserializing VM could call + * getInstance(int cspace) method that will resolve deserialized + * object into the corresponding singleton as well. + * + * Since the singletons are private to ICC_Profile the readResolve + * method have to be `protected' instead of `private' so that + * singletons that are instances of subclasses of ICC_Profile + * could be correctly deserialized. + */ + + + /** + * Version of the format of additional serialized data in the + * stream. Version 1 corresponds to Java 2 + * Platform, v1.3. + * @since 1.3 + * @serial + */ + private int iccProfileSerializedDataVersion = 1; + + + /** + * Writes default serializable fields to the stream. Writes a + * string and an array of bytes to the stream as additional data. + * + * @param s stream used for serialization. + * @throws IOException + * thrown by ObjectInputStream. + * @serialData + * The String is the name of one of + * CS_* constants defined in the + * {@link ColorSpace} class if the profile object is a profile + * for a predefined color space (for example + * "CS_sRGB"). The string is null + * otherwise. + *

+ * The byte[] array is the profile data for the + * profile. For predefined color spaces null is + * written instead of the profile data. If in the future + * versions of Java API new predefined color spaces will be + * added, future versions of this class may choose to write + * for new predefined color spaces not only the color space + * name, but the profile data as well so that older versions + * could still deserialize the object. + */ + private void writeObject(ObjectOutputStream s) + throws IOException + { + s.defaultWriteObject(); + + String csName = null; + if (this == sRGBprofile) { + csName = "CS_sRGB"; + } else if (this == XYZprofile) { + csName = "CS_CIEXYZ"; + } else if (this == PYCCprofile) { + csName = "CS_PYCC"; + } else if (this == GRAYprofile) { + csName = "CS_GRAY"; + } else if (this == LINEAR_RGBprofile) { + csName = "CS_LINEAR_RGB"; + } + + // Future versions may choose to write profile data for new + // predefined color spaces as well, if any will be introduced, + // so that old versions that don't recognize the new CS name + // may fall back to constructing profile from the data. + byte[] data = null; + if (csName == null) { + // getData will activate deferred profile if necessary + data = getData(); + } + + s.writeObject(csName); + s.writeObject(data); + } + + // Temporary storage used by readObject to store resolved profile + // (obtained with getInstance) for readResolve to return. + private transient ICC_Profile resolvedDeserializedProfile; + + /** + * Reads default serializable fields from the stream. Reads from + * the stream a string and an array of bytes as additional data. + * + * @param s stream used for deserialization. + * @throws IOException + * thrown by ObjectInputStream. + * @throws ClassNotFoundException + * thrown by ObjectInputStream. + * @serialData + * The String is the name of one of + * CS_* constants defined in the + * {@link ColorSpace} class if the profile object is a profile + * for a predefined color space (for example + * "CS_sRGB"). The string is null + * otherwise. + *

+ * The byte[] array is the profile data for the + * profile. It will usually be null for the + * predefined profiles. + *

+ * If the string is recognized as a constant name for + * predefined color space the object will be resolved into + * profile obtained with + * getInstance(int cspace) and the profile + * data are ignored. Otherwise the object will be resolved + * into profile obtained with + * getInstance(byte[] data). + * @see #readResolve() + * @see #getInstance(int) + * @see #getInstance(byte[]) + */ + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException + { + s.defaultReadObject(); + + String csName = (String)s.readObject(); + byte[] data = (byte[])s.readObject(); + + int cspace = 0; // ColorSpace.CS_* constant if known + boolean isKnownPredefinedCS = false; + if (csName != null) { + isKnownPredefinedCS = true; + if (csName.equals("CS_sRGB")) { + cspace = ColorSpace.CS_sRGB; + } else if (csName.equals("CS_CIEXYZ")) { + cspace = ColorSpace.CS_CIEXYZ; + } else if (csName.equals("CS_PYCC")) { + cspace = ColorSpace.CS_PYCC; + } else if (csName.equals("CS_GRAY")) { + cspace = ColorSpace.CS_GRAY; + } else if (csName.equals("CS_LINEAR_RGB")) { + cspace = ColorSpace.CS_LINEAR_RGB; + } else { + isKnownPredefinedCS = false; + } + } + + if (isKnownPredefinedCS) { + resolvedDeserializedProfile = getInstance(cspace); + } else { + resolvedDeserializedProfile = getInstance(data); + } + } + + /** + * Resolves instances being deserialized into instances registered + * with CMM. + * @return ICC_Profile object for profile registered with CMM. + * @throws ObjectStreamException + * never thrown, but mandated by the serialization spec. + * @since 1.3 + */ + protected Object readResolve() throws ObjectStreamException { + return resolvedDeserializedProfile; + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,150 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/********************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.color; + +import java.awt.image.LookupTable; +import sun.java2d.cmm.ProfileDeferralInfo; + +/** + * + * A subclass of the ICC_Profile class which represents profiles + * which meet the following criteria: the color space type of the + * profile is TYPE_GRAY and the profile includes the grayTRCTag and + * mediaWhitePointTag tags. Examples of this kind of profile are + * monochrome input profiles, monochrome display profiles, and + * monochrome output profiles. The getInstance methods in the + * ICC_Profile class will + * return an ICC_ProfileGray object when the above conditions are + * met. The advantage of this class is that it provides a lookup + * table that Java or native methods may be able to use directly to + * optimize color conversion in some cases. + *

+ * To transform from a GRAY device profile color space to the CIEXYZ Profile + * Connection Space, the device gray component is transformed by + * a lookup through the tone reproduction curve (TRC). The result is + * treated as the achromatic component of the PCS. +

+
+                PCSY = grayTRC[deviceGray]
+
+
+ * The inverse transform is done by converting the PCS Y components to + * device Gray via the inverse of the grayTRC. + *

+ */ + + + +public class ICC_ProfileGray +extends ICC_Profile { + + static final long serialVersionUID = -1124721290732002649L; + + /** + * Constructs a new ICC_ProfileGray from a CMM ID. + */ + ICC_ProfileGray(long ID) { + super(ID); + } + + /** + * Constructs a new ICC_ProfileGray from a ProfileDeferralInfo object. + */ + ICC_ProfileGray(ProfileDeferralInfo pdi) { + super(pdi); + } + + + /** + * Returns a float array of length 3 containing the X, Y, and Z + * components of the mediaWhitePointTag in the ICC profile. + * @return an array containing the components of the + * mediaWhitePointTag in the ICC profile. + */ + public float[] getMediaWhitePoint() { + return super.getMediaWhitePoint(); + } + + + /** + * Returns a gamma value representing the tone reproduction + * curve (TRC). If the profile represents the TRC as a table rather + * than a single gamma value, then an exception is thrown. In this + * case the actual table can be obtained via getTRC(). When + * using a gamma value, the PCS Y component is computed as follows: +

+
+                          gamma
+         PCSY = deviceGray
+
+
+ * @return the gamma value as a float. + * @exception ProfileDataException if the profile does not specify + * the TRC as a single gamma value. + */ + public float getGamma() { + float theGamma; + + theGamma = super.getGamma(ICC_Profile.icSigGrayTRCTag); + return theGamma; + } + + /** + * Returns the TRC as an array of shorts. If the profile has + * specified the TRC as linear (gamma = 1.0) or as a simple gamma + * value, this method throws an exception, and the getGamma() method + * should be used to get the gamma value. Otherwise the short array + * returned here represents a lookup table where the input Gray value + * is conceptually in the range [0.0, 1.0]. Value 0.0 maps + * to array index 0 and value 1.0 maps to array index length-1. + * Interpolation may be used to generate output values for + * input values which do not map exactly to an index in the + * array. Output values also map linearly to the range [0.0, 1.0]. + * Value 0.0 is represented by an array value of 0x0000 and + * value 1.0 by 0xFFFF, i.e. the values are really unsigned + * short values, although they are returned in a short array. + * @return a short array representing the TRC. + * @exception ProfileDataException if the profile does not specify + * the TRC as a table. + */ + public short[] getTRC() { + short[] theTRC; + + theTRC = super.getTRC(ICC_Profile.icSigGrayTRCTag); + return theTRC; + } + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,282 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/********************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.color; + +import java.awt.image.LookupTable; +import sun.java2d.cmm.ProfileDeferralInfo; + +/** + * + * The ICC_ProfileRGB class is a subclass of the ICC_Profile class + * that represents profiles which meet the following criteria: + *
    + *
  • The profile's color space type is RGB.
  • + *
  • The profile includes the redColorantTag, + * greenColorantTag, blueColorantTag, + * redTRCTag, greenTRCTag, + * blueTRCTag, and mediaWhitePointTag tags.
  • + *
+ * The ICC_Profile getInstance method will + * return an ICC_ProfileRGB object when these conditions are met. + * Three-component, matrix-based input profiles and RGB display profiles are + * examples of this type of profile. + *

+ * This profile class provides color transform matrices and lookup tables + * that Java or native methods can use directly to + * optimize color conversion in some cases. + *

+ * To transform from a device profile color space to the CIEXYZ Profile + * Connection Space, each device color component is first linearized by + * a lookup through the corresponding tone reproduction curve (TRC). + * The resulting linear RGB components are converted to the CIEXYZ PCS + * using a a 3x3 matrix constructed from the RGB colorants. + *

+ *
+ *                 linearR = redTRC[deviceR]
+ *
+ *                 linearG = greenTRC[deviceG]
+ *
+ *                 linearB = blueTRC[deviceB]
+ *
+ *   _      _       _                                             _   _         _
+ *  [  PCSX  ]     [  redColorantX  greenColorantX  blueColorantX  ] [  linearR  ]
+ *  [        ]     [                                               ] [           ]
+ *  [  PCSY  ]  =  [  redColorantY  greenColorantY  blueColorantY  ] [  linearG  ]
+ *  [        ]     [                                               ] [           ]
+ *  [_ PCSZ _]     [_ redColorantZ  greenColorantZ  blueColorantZ _] [_ linearB _]
+ *
+ * 
+ * The inverse transform is performed by converting PCS XYZ components to linear + * RGB components through the inverse of the above 3x3 matrix, and then converting + * linear RGB to device RGB through inverses of the TRCs. + *

+ */ + + + +public class ICC_ProfileRGB +extends ICC_Profile { + + static final long serialVersionUID = 8505067385152579334L; + + /** + * Used to get a gamma value or TRC for the red component. + */ + public static final int REDCOMPONENT = 0; + + /** + * Used to get a gamma value or TRC for the green component. + */ + public static final int GREENCOMPONENT = 1; + + /** + * Used to get a gamma value or TRC for the blue component. + */ + public static final int BLUECOMPONENT = 2; + + + /** + * Constructs an new ICC_ProfileRGB from a CMM ID. + * + * @param ID The CMM ID for the profile. + * + */ + ICC_ProfileRGB(long ID) { + super(ID); + } + + /** + * Constructs a new ICC_ProfileRGB from a + * ProfileDeferralInfo object. + * + * @param pdi + */ + ICC_ProfileRGB(ProfileDeferralInfo pdi) { + super(pdi); + } + + + /** + * Returns an array that contains the components of the profile's + * mediaWhitePointTag. + * + * @return A 3-element float array containing the x, y, + * and z components of the profile's mediaWhitePointTag. + */ + public float[] getMediaWhitePoint() { + return super.getMediaWhitePoint(); + } + + + /** + * Returns a 3x3 float matrix constructed from the + * X, Y, and Z components of the profile's redColorantTag, + * greenColorantTag, and blueColorantTag. + *

+ * This matrix can be used for color transforms in the forward + * direction of the profile--from the profile color space + * to the CIEXYZ PCS. + * + * @return A 3x3 float array that contains the x, y, and z + * components of the profile's redColorantTag, + * greenColorantTag, and blueColorantTag. + */ + public float[][] getMatrix() { + float[][] theMatrix = new float[3][3]; + float[] tmpMatrix; + + tmpMatrix = getXYZTag(ICC_Profile.icSigRedColorantTag); + theMatrix[0][0] = tmpMatrix[0]; + theMatrix[1][0] = tmpMatrix[1]; + theMatrix[2][0] = tmpMatrix[2]; + tmpMatrix = getXYZTag(ICC_Profile.icSigGreenColorantTag); + theMatrix[0][1] = tmpMatrix[0]; + theMatrix[1][1] = tmpMatrix[1]; + theMatrix[2][1] = tmpMatrix[2]; + tmpMatrix = getXYZTag(ICC_Profile.icSigBlueColorantTag); + theMatrix[0][2] = tmpMatrix[0]; + theMatrix[1][2] = tmpMatrix[1]; + theMatrix[2][2] = tmpMatrix[2]; + return theMatrix; + } + + /** + * Returns a gamma value representing the tone reproduction curve + * (TRC) for a particular component. The component parameter + * must be one of REDCOMPONENT, GREENCOMPONENT, or BLUECOMPONENT. + *

+ * If the profile + * represents the TRC for the corresponding component + * as a table rather than a single gamma value, an + * exception is thrown. In this case the actual table + * can be obtained through the {@link #getTRC(int)} method. + * When using a gamma value, + * the linear component (R, G, or B) is computed as follows: + *

+     *
+     *                                           gamma
+     *          linearComponent = deviceComponent
+     *
+     *
+ * @param component The ICC_ProfileRGB constant that + * represents the component whose TRC you want to retrieve + * @return the gamma value as a float. + * @exception ProfileDataException if the profile does not specify + * the corresponding TRC as a single gamma value. + */ + public float getGamma(int component) { + float theGamma; + int theSignature; + + switch (component) { + case REDCOMPONENT: + theSignature = ICC_Profile.icSigRedTRCTag; + break; + + case GREENCOMPONENT: + theSignature = ICC_Profile.icSigGreenTRCTag; + break; + + case BLUECOMPONENT: + theSignature = ICC_Profile.icSigBlueTRCTag; + break; + + default: + throw new IllegalArgumentException("Must be Red, Green, or Blue"); + } + + theGamma = super.getGamma(theSignature); + + return theGamma; + } + + /** + * Returns the TRC for a particular component as an array. + * Component must be REDCOMPONENT, + * GREENCOMPONENT, or BLUECOMPONENT. + * Otherwise the returned array + * represents a lookup table where the input component value + * is conceptually in the range [0.0, 1.0]. Value 0.0 maps + * to array index 0 and value 1.0 maps to array index length-1. + * Interpolation might be used to generate output values for + * input values that do not map exactly to an index in the + * array. Output values also map linearly to the range [0.0, 1.0]. + * Value 0.0 is represented by an array value of 0x0000 and + * value 1.0 by 0xFFFF. In other words, the values are really unsigned + * short values even though they are returned in a + * short array. + * + * If the profile has specified the corresponding TRC + * as linear (gamma = 1.0) or as a simple gamma value, this method + * throws an exception. In this case, the {@link #getGamma(int)} + * method should be used to get the gamma value. + * + * @param component The ICC_ProfileRGB constant that + * represents the component whose TRC you want to retrieve: + * REDCOMPONENT, GREENCOMPONENT, or + * BLUECOMPONENT. + * + * @return a short array representing the TRC. + * @exception ProfileDataException if the profile does not specify + * the corresponding TRC as a table. + */ + public short[] getTRC(int component) { + short[] theTRC; + int theSignature; + + switch (component) { + case REDCOMPONENT: + theSignature = ICC_Profile.icSigRedTRCTag; + break; + + case GREENCOMPONENT: + theSignature = ICC_Profile.icSigGreenTRCTag; + break; + + case BLUECOMPONENT: + theSignature = ICC_Profile.icSigBlueTRCTag; + break; + + default: + throw new IllegalArgumentException("Must be Red, Green, or Blue"); + } + + theTRC = super.getTRC(theSignature); + + return theTRC; + } + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/font/OpenType.java --- a/jdk/src/share/classes/java/awt/font/OpenType.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/java/awt/font/OpenType.java Wed Jul 05 16:37:14 2017 +0200 @@ -31,9 +31,9 @@ * sfnt tables from the font. A particular * Font object can implement this interface. *

- * For more information on TrueType fonts, see the - * Apple TrueType Reference Manual - * ( http://fonts.apple.com/TTRefMan/index.html ). + * For more information on TrueType and OpenType fonts, see the + * OpenType specification. + * ( http://www.microsoft.com/typography/otspec/l ). */ public interface OpenType { diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/BandedSampleModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/BandedSampleModel.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,839 @@ +/* + * Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +/** + * This class represents image data which is stored in a band interleaved + * fashion and for + * which each sample of a pixel occupies one data element of the DataBuffer. + * It subclasses ComponentSampleModel but provides a more efficent + * implementation for accessing band interleaved image data than is provided + * by ComponentSampleModel. This class should typically be used when working + * with images which store sample data for each band in a different bank of the + * DataBuffer. Accessor methods are provided so that image data can be + * manipulated directly. Pixel stride is the number of + * data array elements between two samples for the same band on the same + * scanline. The pixel stride for a BandedSampleModel is one. + * Scanline stride is the number of data array elements between + * a given sample and the corresponding sample in the same column of the next + * scanline. Band offsets denote the number + * of data array elements from the first data array element of the bank + * of the DataBuffer holding each band to the first sample of the band. + * The bands are numbered from 0 to N-1. + * Bank indices denote the correspondence between a bank of the data buffer + * and a band of image data. This class supports + * {@link DataBuffer#TYPE_BYTE TYPE_BYTE}, + * {@link DataBuffer#TYPE_USHORT TYPE_USHORT}, + * {@link DataBuffer#TYPE_SHORT TYPE_SHORT}, + * {@link DataBuffer#TYPE_INT TYPE_INT}, + * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, and + * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE} datatypes + */ + + +public final class BandedSampleModel extends ComponentSampleModel +{ + + /** + * Constructs a BandedSampleModel with the specified parameters. + * The pixel stride will be one data element. The scanline stride + * will be the same as the width. Each band will be stored in + * a separate bank and all band offsets will be zero. + * @param dataType The data type for storing samples. + * @param w The width (in pixels) of the region of + * image data described. + * @param h The height (in pixels) of the region of image + * data described. + * @param numBands The number of bands for the image data. + * @throws IllegalArgumentException if dataType is not + * one of the supported data types + */ + public BandedSampleModel(int dataType, int w, int h, int numBands) { + super(dataType, w, h, 1, w, + BandedSampleModel.createIndicesArray(numBands), + BandedSampleModel.createOffsetArray(numBands)); + } + + /** + * Constructs a BandedSampleModel with the specified parameters. + * The number of bands will be inferred from the lengths of the + * bandOffsets bankIndices arrays, which must be equal. The pixel + * stride will be one data element. + * @param dataType The data type for storing samples. + * @param w The width (in pixels) of the region of + * image data described. + * @param h The height (in pixels) of the region of + * image data described. + * @param scanlineStride The line stride of the of the image data. + * @param bankIndices The bank index for each band. + * @param bandOffsets The band offset for each band. + * @throws IllegalArgumentException if dataType is not + * one of the supported data types + */ + public BandedSampleModel(int dataType, + int w, int h, + int scanlineStride, + int bankIndices[], + int bandOffsets[]) { + + super(dataType, w, h, 1,scanlineStride, bankIndices, bandOffsets); + } + + /** + * Creates a new BandedSampleModel with the specified + * width and height. The new BandedSampleModel will have the same + * number of bands, storage data type, and bank indices + * as this BandedSampleModel. The band offsets will be compressed + * such that the offset between bands will be w*pixelStride and + * the minimum of all of the band offsets is zero. + * @param w the width of the resulting BandedSampleModel + * @param h the height of the resulting BandedSampleModel + * @return a new BandedSampleModel with the specified + * width and height. + * @throws IllegalArgumentException if w or + * h equals either + * Integer.MAX_VALUE or + * Integer.MIN_VALUE + * @throws IllegalArgumentException if dataType is not + * one of the supported data types + */ + public SampleModel createCompatibleSampleModel(int w, int h) { + int[] bandOffs; + + if (numBanks == 1) { + bandOffs = orderBands(bandOffsets, w*h); + } + else { + bandOffs = new int[bandOffsets.length]; + } + + SampleModel sampleModel = + new BandedSampleModel(dataType, w, h, w, bankIndices, bandOffs); + return sampleModel; + } + + /** + * Creates a new BandedSampleModel with a subset of the bands of this + * BandedSampleModel. The new BandedSampleModel can be + * used with any DataBuffer that the existing BandedSampleModel + * can be used with. The new BandedSampleModel/DataBuffer + * combination will represent an image with a subset of the bands + * of the original BandedSampleModel/DataBuffer combination. + * @throws RasterFormatException if the number of bands is greater than + * the number of banks in this sample model. + * @throws IllegalArgumentException if dataType is not + * one of the supported data types + */ + public SampleModel createSubsetSampleModel(int bands[]) { + if (bands.length > bankIndices.length) + throw new RasterFormatException("There are only " + + bankIndices.length + + " bands"); + int newBankIndices[] = new int[bands.length]; + int newBandOffsets[] = new int[bands.length]; + + for (int i=0; idataType is not + * one of the supported types. + */ + public DataBuffer createDataBuffer() { + DataBuffer dataBuffer = null; + + int size = scanlineStride * height; + switch (dataType) { + case DataBuffer.TYPE_BYTE: + dataBuffer = new DataBufferByte(size, numBanks); + break; + case DataBuffer.TYPE_USHORT: + dataBuffer = new DataBufferUShort(size, numBanks); + break; + case DataBuffer.TYPE_SHORT: + dataBuffer = new DataBufferShort(size, numBanks); + break; + case DataBuffer.TYPE_INT: + dataBuffer = new DataBufferInt(size, numBanks); + break; + case DataBuffer.TYPE_FLOAT: + dataBuffer = new DataBufferFloat(size, numBanks); + break; + case DataBuffer.TYPE_DOUBLE: + dataBuffer = new DataBufferDouble(size, numBanks); + break; + default: + throw new IllegalArgumentException("dataType is not one " + + "of the supported types."); + } + + return dataBuffer; + } + + + /** + * Returns data for a single pixel in a primitive array of type + * TransferType. For a BandedSampleModel, this will be the same + * as the data type, and samples will be returned one per array + * element. Generally, obj + * should be passed in as null, so that the Object will be created + * automatically and will be of the right primitive data type. + *

+ * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is described by + * BandedSampleModel bsm1, to DataBuffer db2, + * whose storage layout is described by + * BandedSampleModel bsm2. + * The transfer will generally be more efficient than using + * getPixel/setPixel. + *

+     *       BandedSampleModel bsm1, bsm2;
+     *       DataBufferInt db1, db2;
+     *       bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
+     *                            db2);
+     * 
+ * Using getDataElements/setDataElements to transfer between two + * DataBuffer/SampleModel pairs is legitimate if the SampleModels have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * If obj is non-null, it should be a primitive array of type TransferType. + * Otherwise, a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if obj is non-null and is not large enough to hold + * the pixel data. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param obj If non-null, a primitive array in which to return + * the pixel data. + * @param data The DataBuffer containing the image data. + * @return the data for the specified pixel. + * @see #setDataElements(int, int, Object, DataBuffer) + */ + public Object getDataElements(int x, int y, Object obj, DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int type = getTransferType(); + int numDataElems = getNumDataElements(); + int pixelOffset = y*scanlineStride + x; + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] bdata; + + if (obj == null) { + bdata = new byte[numDataElems]; + } else { + bdata = (byte[])obj; + } + + for (int i=0; i= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int[] pixels; + + if (iArray != null) { + pixels = iArray; + } else { + pixels = new int [numBands]; + } + + int pixelOffset = y*scanlineStride + x; + for (int i=0; i width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int[] pixels; + + if (iArray != null) { + pixels = iArray; + } else { + pixels = new int[w*h*numBands]; + } + + for (int k = 0; k < numBands; k++) { + int lineOffset = y*scanlineStride + x + bandOffsets[k]; + int srcOffset = k; + int bank = bankIndices[k]; + + for (int i = 0; i < h; i++) { + int pixelOffset = lineOffset; + for (int j = 0; j < w; j++) { + pixels[srcOffset] = data.getElem(bank, pixelOffset++); + srcOffset += numBands; + } + lineOffset += scanlineStride; + } + } + return pixels; + } + + /** + * Returns as int the sample in a specified band for the pixel + * located at (x,y). + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to return + * @param data The DataBuffer containing the image data + * @return the sample in the specified band for the specified pixel. + * @see #setSample(int, int, int, int, DataBuffer) + */ + public int getSample(int x, int y, int b, DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int sample = + data.getElem(bankIndices[b], + y*scanlineStride + x + bandOffsets[b]); + return sample; + } + + /** + * Returns the sample in a specified band + * for the pixel located at (x,y) as a float. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to return + * @param data The DataBuffer containing the image data + * @return a float value that represents the sample in the specified + * band for the specified pixel. + */ + public float getSampleFloat(int x, int y, int b, DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + float sample = data.getElemFloat(bankIndices[b], + y*scanlineStride + x + bandOffsets[b]); + return sample; + } + + /** + * Returns the sample in a specified band + * for a pixel located at (x,y) as a double. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to return + * @param data The DataBuffer containing the image data + * @return a double value that represents the sample in the specified + * band for the specified pixel. + */ + public double getSampleDouble(int x, int y, int b, DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + double sample = data.getElemDouble(bankIndices[b], + y*scanlineStride + x + bandOffsets[b]); + return sample; + } + + /** + * Returns the samples in a specified band for the specified rectangle + * of pixels in an int array, one sample per data array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location + * @param y The Y coordinate of the upper left pixel location + * @param w The width of the pixel rectangle + * @param h The height of the pixel rectangle + * @param b The band to return + * @param iArray If non-null, returns the samples in this array + * @param data The DataBuffer containing the image data + * @return the samples in the specified band for the pixels within + * the specified region. + * @see #setSamples(int, int, int, int, int, int[], DataBuffer) + */ + public int[] getSamples(int x, int y, int w, int h, int b, + int iArray[], DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int samples[]; + if (iArray != null) { + samples = iArray; + } else { + samples = new int [w*h]; + } + + int lineOffset = y*scanlineStride + x + bandOffsets[b]; + int srcOffset = 0; + int bank = bankIndices[b]; + + for (int i = 0; i < h; i++) { + int sampleOffset = lineOffset; + for (int j = 0; j < w; j++) { + samples[srcOffset++] = data.getElem(bank, sampleOffset++); + } + lineOffset += scanlineStride; + } + return samples; + } + + /** + * Sets the data for a single pixel in the specified DataBuffer from a + * primitive array of type TransferType. For a BandedSampleModel, + * this will be the same as the data type, and samples are transferred + * one per array element. + *

+ * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is described by + * BandedSampleModel bsm1, to DataBuffer db2, + * whose storage layout is described by + * BandedSampleModel bsm2. + * The transfer will generally be more efficient than using + * getPixel/setPixel. + *

+     *       BandedSampleModel bsm1, bsm2;
+     *       DataBufferInt db1, db2;
+     *       bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
+     *                            db2);
+     * 
+ * Using getDataElements/setDataElements to transfer between two + * DataBuffer/SampleModel pairs is legitimate if the SampleModels have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * obj must be a primitive array of type TransferType. Otherwise, + * a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if obj is not large enough to hold the pixel data. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param obj If non-null, returns the primitive array in this + * object + * @param data The DataBuffer containing the image data + * @see #getDataElements(int, int, Object, DataBuffer) + */ + public void setDataElements(int x, int y, Object obj, DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int type = getTransferType(); + int numDataElems = getNumDataElements(); + int pixelOffset = y*scanlineStride + x; + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] barray = (byte[])obj; + + for (int i=0; i= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int pixelOffset = y*scanlineStride + x; + for (int i=0; i width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + for (int k = 0; k < numBands; k++) { + int lineOffset = y*scanlineStride + x + bandOffsets[k]; + int srcOffset = k; + int bank = bankIndices[k]; + + for (int i = 0; i < h; i++) { + int pixelOffset = lineOffset; + for (int j = 0; j < w; j++) { + data.setElem(bank, pixelOffset++, iArray[srcOffset]); + srcOffset += numBands; + } + lineOffset += scanlineStride; + } + } + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using an int for input. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to set + * @param s The input sample as an int + * @param data The DataBuffer containing the image data + * @see #getSample(int, int, int, DataBuffer) + */ + public void setSample(int x, int y, int b, int s, + DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + data.setElem(bankIndices[b], + y*scanlineStride + x + bandOffsets[b], s); + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using a float for input. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to set + * @param s The input sample as a float + * @param data The DataBuffer containing the image data + * @see #getSample(int, int, int, DataBuffer) + */ + public void setSample(int x, int y, int b, + float s , + DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + data.setElemFloat(bankIndices[b], + y*scanlineStride + x + bandOffsets[b], s); + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using a double for input. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to set + * @param s The input sample as a double + * @param data The DataBuffer containing the image data + * @see #getSample(int, int, int, DataBuffer) + */ + public void setSample(int x, int y, int b, + double s, + DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + data.setElemDouble(bankIndices[b], + y*scanlineStride + x + bandOffsets[b], s); + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from an int array containing one sample per data array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location + * @param y The Y coordinate of the upper left pixel location + * @param w The width of the pixel rectangle + * @param h The height of the pixel rectangle + * @param b The band to set + * @param iArray The input sample array + * @param data The DataBuffer containing the image data + * @see #getSamples(int, int, int, int, int, int[], DataBuffer) + */ + public void setSamples(int x, int y, int w, int h, int b, + int iArray[], DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int lineOffset = y*scanlineStride + x + bandOffsets[b]; + int srcOffset = 0; + int bank = bankIndices[b]; + + for (int i = 0; i < h; i++) { + int sampleOffset = lineOffset; + for (int j = 0; j < w; j++) { + data.setElem(bank, sampleOffset++, iArray[srcOffset++]); + } + lineOffset += scanlineStride; + } + } + + private static int[] createOffsetArray(int numBands) { + int[] bandOffsets = new int[numBands]; + for (int i=0; i < numBands; i++) { + bandOffsets[i] = 0; + } + return bandOffsets; + } + + private static int[] createIndicesArray(int numBands) { + int[] bankIndices = new int[numBands]; + for (int i=0; i < numBands; i++) { + bankIndices[i] = i; + } + return bankIndices; + } + + // Differentiate hash code from other ComponentSampleModel subclasses + public int hashCode() { + return super.hashCode() ^ 0x2; + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/ColorConvertOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/ColorConvertOp.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,1109 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/********************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.image; + +import java.awt.Point; +import java.awt.Graphics2D; +import java.awt.color.*; +import sun.java2d.cmm.ColorTransform; +import sun.java2d.cmm.CMSManager; +import sun.java2d.cmm.ProfileDeferralMgr; +import sun.java2d.cmm.PCMM; +import java.awt.geom.Rectangle2D; +import java.awt.geom.Point2D; +import java.awt.RenderingHints; + +/** + * This class performs a pixel-by-pixel color conversion of the data in + * the source image. The resulting color values are scaled to the precision + * of the destination image. Color conversion can be specified + * via an array of ColorSpace objects or an array of ICC_Profile objects. + *

+ * If the source is a BufferedImage with premultiplied alpha, the + * color components are divided by the alpha component before color conversion. + * If the destination is a BufferedImage with premultiplied alpha, the + * color components are multiplied by the alpha component after conversion. + * Rasters are treated as having no alpha channel, i.e. all bands are + * color bands. + *

+ * If a RenderingHints object is specified in the constructor, the + * color rendering hint and the dithering hint may be used to control + * color conversion. + *

+ * Note that Source and Destination may be the same object. + *

+ * @see java.awt.RenderingHints#KEY_COLOR_RENDERING + * @see java.awt.RenderingHints#KEY_DITHERING + */ +public class ColorConvertOp implements BufferedImageOp, RasterOp { + ICC_Profile[] profileList; + ColorSpace[] CSList; + ColorTransform thisTransform, thisRasterTransform; + ICC_Profile thisSrcProfile, thisDestProfile; + RenderingHints hints; + boolean gotProfiles; + float[] srcMinVals, srcMaxVals, dstMinVals, dstMaxVals; + + /* the class initializer */ + static { + if (ProfileDeferralMgr.deferring) { + ProfileDeferralMgr.activateProfiles(); + } + } + + /** + * Constructs a new ColorConvertOp which will convert + * from a source color space to a destination color space. + * The RenderingHints argument may be null. + * This Op can be used only with BufferedImages, and will convert + * directly from the ColorSpace of the source image to that of the + * destination. The destination argument of the filter method + * cannot be specified as null. + * @param hints the RenderingHints object used to control + * the color conversion, or null + */ + public ColorConvertOp (RenderingHints hints) + { + profileList = new ICC_Profile [0]; /* 0 length list */ + this.hints = hints; + } + + /** + * Constructs a new ColorConvertOp from a ColorSpace object. + * The RenderingHints argument may be null. This + * Op can be used only with BufferedImages, and is primarily useful + * when the {@link #filter(BufferedImage, BufferedImage) filter} + * method is invoked with a destination argument of null. + * In that case, the ColorSpace defines the destination color space + * for the destination created by the filter method. Otherwise, the + * ColorSpace defines an intermediate space to which the source is + * converted before being converted to the destination space. + * @param cspace defines the destination ColorSpace or an + * intermediate ColorSpace + * @param hints the RenderingHints object used to control + * the color conversion, or null + * @throws NullPointerException if cspace is null + */ + public ColorConvertOp (ColorSpace cspace, RenderingHints hints) + { + if (cspace == null) { + throw new NullPointerException("ColorSpace cannot be null"); + } + if (cspace instanceof ICC_ColorSpace) { + profileList = new ICC_Profile [1]; /* 1 profile in the list */ + + profileList [0] = ((ICC_ColorSpace) cspace).getProfile(); + } + else { + CSList = new ColorSpace[1]; /* non-ICC case: 1 ColorSpace in list */ + CSList[0] = cspace; + } + this.hints = hints; + } + + + /** + * Constructs a new ColorConvertOp from two ColorSpace objects. + * The RenderingHints argument may be null. + * This Op is primarily useful for calling the filter method on + * Rasters, in which case the two ColorSpaces define the operation + * to be performed on the Rasters. In that case, the number of bands + * in the source Raster must match the number of components in + * srcCspace, and the number of bands in the destination Raster + * must match the number of components in dstCspace. For BufferedImages, + * the two ColorSpaces define intermediate spaces through which the + * source is converted before being converted to the destination space. + * @param srcCspace the source ColorSpace + * @param dstCspace the destination ColorSpace + * @param hints the RenderingHints object used to control + * the color conversion, or null + * @throws NullPointerException if either srcCspace or dstCspace is null + */ + public ColorConvertOp(ColorSpace srcCspace, ColorSpace dstCspace, + RenderingHints hints) + { + if ((srcCspace == null) || (dstCspace == null)) { + throw new NullPointerException("ColorSpaces cannot be null"); + } + if ((srcCspace instanceof ICC_ColorSpace) && + (dstCspace instanceof ICC_ColorSpace)) { + profileList = new ICC_Profile [2]; /* 2 profiles in the list */ + + profileList [0] = ((ICC_ColorSpace) srcCspace).getProfile(); + profileList [1] = ((ICC_ColorSpace) dstCspace).getProfile(); + + getMinMaxValsFromColorSpaces(srcCspace, dstCspace); + } else { + /* non-ICC case: 2 ColorSpaces in list */ + CSList = new ColorSpace[2]; + CSList[0] = srcCspace; + CSList[1] = dstCspace; + } + this.hints = hints; + } + + + /** + * Constructs a new ColorConvertOp from an array of ICC_Profiles. + * The RenderingHints argument may be null. + * The sequence of profiles may include profiles that represent color + * spaces, profiles that represent effects, etc. If the whole sequence + * does not represent a well-defined color conversion, an exception is + * thrown. + *

For BufferedImages, if the ColorSpace + * of the source BufferedImage does not match the requirements of the + * first profile in the array, + * the first conversion is to an appropriate ColorSpace. + * If the requirements of the last profile in the array are not met + * by the ColorSpace of the destination BufferedImage, + * the last conversion is to the destination's ColorSpace. + *

For Rasters, the number of bands in the source Raster must match + * the requirements of the first profile in the array, and the + * number of bands in the destination Raster must match the requirements + * of the last profile in the array. The array must have at least two + * elements or calling the filter method for Rasters will throw an + * IllegalArgumentException. + * @param profiles the array of ICC_Profile objects + * @param hints the RenderingHints object used to control + * the color conversion, or null + * @exception IllegalArgumentException when the profile sequence does not + * specify a well-defined color conversion + * @exception NullPointerException if profiles is null + */ + public ColorConvertOp (ICC_Profile[] profiles, RenderingHints hints) + { + if (profiles == null) { + throw new NullPointerException("Profiles cannot be null"); + } + gotProfiles = true; + profileList = new ICC_Profile[profiles.length]; + for (int i1 = 0; i1 < profiles.length; i1++) { + profileList[i1] = profiles[i1]; + } + this.hints = hints; + } + + + /** + * Returns the array of ICC_Profiles used to construct this ColorConvertOp. + * Returns null if the ColorConvertOp was not constructed from such an + * array. + * @return the array of ICC_Profile objects of this + * ColorConvertOp, or null if this + * ColorConvertOp was not constructed with an + * array of ICC_Profile objects. + */ + public final ICC_Profile[] getICC_Profiles() { + if (gotProfiles) { + ICC_Profile[] profiles = new ICC_Profile[profileList.length]; + for (int i1 = 0; i1 < profileList.length; i1++) { + profiles[i1] = profileList[i1]; + } + return profiles; + } + return null; + } + + /** + * ColorConverts the source BufferedImage. + * If the destination image is null, + * a BufferedImage will be created with an appropriate ColorModel. + * @param src the source BufferedImage to be converted + * @param dest the destination BufferedImage, + * or null + * @return dest color converted from src + * or a new, converted BufferedImage + * if dest is null + * @exception IllegalArgumentException if dest is null and this op was + * constructed using the constructor which takes only a + * RenderingHints argument, since the operation is ill defined. + */ + public final BufferedImage filter(BufferedImage src, BufferedImage dest) { + ColorSpace srcColorSpace, destColorSpace; + BufferedImage savdest = null; + + if (src.getColorModel() instanceof IndexColorModel) { + IndexColorModel icm = (IndexColorModel) src.getColorModel(); + src = icm.convertToIntDiscrete(src.getRaster(), true); + } + srcColorSpace = src.getColorModel().getColorSpace(); + if (dest != null) { + if (dest.getColorModel() instanceof IndexColorModel) { + savdest = dest; + dest = null; + destColorSpace = null; + } else { + destColorSpace = dest.getColorModel().getColorSpace(); + } + } else { + destColorSpace = null; + } + + if ((CSList != null) || + (!(srcColorSpace instanceof ICC_ColorSpace)) || + ((dest != null) && + (!(destColorSpace instanceof ICC_ColorSpace)))) { + /* non-ICC case */ + dest = nonICCBIFilter(src, srcColorSpace, dest, destColorSpace); + } else { + dest = ICCBIFilter(src, srcColorSpace, dest, destColorSpace); + } + + if (savdest != null) { + Graphics2D big = savdest.createGraphics(); + try { + big.drawImage(dest, 0, 0, null); + } finally { + big.dispose(); + } + return savdest; + } else { + return dest; + } + } + + private final BufferedImage ICCBIFilter(BufferedImage src, + ColorSpace srcColorSpace, + BufferedImage dest, + ColorSpace destColorSpace) { + int nProfiles = profileList.length; + ICC_Profile srcProfile = null, destProfile = null; + + srcProfile = ((ICC_ColorSpace) srcColorSpace).getProfile(); + + if (dest == null) { /* last profile in the list defines + the output color space */ + if (nProfiles == 0) { + throw new IllegalArgumentException( + "Destination ColorSpace is undefined"); + } + destProfile = profileList [nProfiles - 1]; + dest = createCompatibleDestImage(src, null); + } + else { + if (src.getHeight() != dest.getHeight() || + src.getWidth() != dest.getWidth()) { + throw new IllegalArgumentException( + "Width or height of BufferedImages do not match"); + } + destProfile = ((ICC_ColorSpace) destColorSpace).getProfile(); + } + + /* Checking if all profiles in the transform sequence are the same. + * If so, performing just copying the data. + */ + if (srcProfile == destProfile) { + boolean noTrans = true; + for (int i = 0; i < nProfiles; i++) { + if (srcProfile != profileList[i]) { + noTrans = false; + break; + } + } + if (noTrans) { + Graphics2D g = dest.createGraphics(); + try { + g.drawImage(src, 0, 0, null); + } finally { + g.dispose(); + } + + return dest; + } + } + + /* make a new transform if needed */ + if ((thisTransform == null) || (thisSrcProfile != srcProfile) || + (thisDestProfile != destProfile) ) { + updateBITransform(srcProfile, destProfile); + } + + /* color convert the image */ + thisTransform.colorConvert(src, dest); + + return dest; + } + + private void updateBITransform(ICC_Profile srcProfile, + ICC_Profile destProfile) { + ICC_Profile[] theProfiles; + int i1, nProfiles, nTransforms, whichTrans, renderState; + ColorTransform[] theTransforms; + boolean useSrc = false, useDest = false; + + nProfiles = profileList.length; + nTransforms = nProfiles; + if ((nProfiles == 0) || (srcProfile != profileList[0])) { + nTransforms += 1; + useSrc = true; + } + if ((nProfiles == 0) || (destProfile != profileList[nProfiles - 1]) || + (nTransforms < 2)) { + nTransforms += 1; + useDest = true; + } + + /* make the profile list */ + theProfiles = new ICC_Profile[nTransforms]; /* the list of profiles + for this Op */ + + int idx = 0; + if (useSrc) { + /* insert source as first profile */ + theProfiles[idx++] = srcProfile; + } + + for (i1 = 0; i1 < nProfiles; i1++) { + /* insert profiles defined in this Op */ + theProfiles[idx++] = profileList [i1]; + } + + if (useDest) { + /* insert dest as last profile */ + theProfiles[idx] = destProfile; + } + + /* make the transform list */ + theTransforms = new ColorTransform [nTransforms]; + + /* initialize transform get loop */ + if (theProfiles[0].getProfileClass() == ICC_Profile.CLASS_OUTPUT) { + /* if first profile is a printer + render as colorimetric */ + renderState = ICC_Profile.icRelativeColorimetric; + } + else { + renderState = ICC_Profile.icPerceptual; /* render any other + class perceptually */ + } + + whichTrans = ColorTransform.In; + + PCMM mdl = CMSManager.getModule(); + + /* get the transforms from each profile */ + for (i1 = 0; i1 < nTransforms; i1++) { + if (i1 == nTransforms -1) { /* last profile? */ + whichTrans = ColorTransform.Out; /* get output transform */ + } + else { /* check for abstract profile */ + if ((whichTrans == ColorTransform.Simulation) && + (theProfiles[i1].getProfileClass () == + ICC_Profile.CLASS_ABSTRACT)) { + renderState = ICC_Profile.icPerceptual; + whichTrans = ColorTransform.In; + } + } + + theTransforms[i1] = mdl.createTransform ( + theProfiles[i1], renderState, whichTrans); + + /* get this profile's rendering intent to select transform + from next profile */ + renderState = getRenderingIntent(theProfiles[i1]); + + /* "middle" profiles use simulation transform */ + whichTrans = ColorTransform.Simulation; + } + + /* make the net transform */ + thisTransform = mdl.createTransform(theTransforms); + + /* update corresponding source and dest profiles */ + thisSrcProfile = srcProfile; + thisDestProfile = destProfile; + } + + /** + * ColorConverts the image data in the source Raster. + * If the destination Raster is null, a new Raster will be created. + * The number of bands in the source and destination Rasters must + * meet the requirements explained above. The constructor used to + * create this ColorConvertOp must have provided enough information + * to define both source and destination color spaces. See above. + * Otherwise, an exception is thrown. + * @param src the source Raster to be converted + * @param dest the destination WritableRaster, + * or null + * @return dest color converted from src + * or a new, converted WritableRaster + * if dest is null + * @exception IllegalArgumentException if the number of source or + * destination bands is incorrect, the source or destination + * color spaces are undefined, or this op was constructed + * with one of the constructors that applies only to + * operations on BufferedImages. + */ + public final WritableRaster filter (Raster src, WritableRaster dest) { + + if (CSList != null) { + /* non-ICC case */ + return nonICCRasterFilter(src, dest); + } + int nProfiles = profileList.length; + if (nProfiles < 2) { + throw new IllegalArgumentException( + "Source or Destination ColorSpace is undefined"); + } + if (src.getNumBands() != profileList[0].getNumComponents()) { + throw new IllegalArgumentException( + "Numbers of source Raster bands and source color space " + + "components do not match"); + } + if (dest == null) { + dest = createCompatibleDestRaster(src); + } + else { + if (src.getHeight() != dest.getHeight() || + src.getWidth() != dest.getWidth()) { + throw new IllegalArgumentException( + "Width or height of Rasters do not match"); + } + if (dest.getNumBands() != + profileList[nProfiles-1].getNumComponents()) { + throw new IllegalArgumentException( + "Numbers of destination Raster bands and destination " + + "color space components do not match"); + } + } + + /* make a new transform if needed */ + if (thisRasterTransform == null) { + int i1, whichTrans, renderState; + ColorTransform[] theTransforms; + + /* make the transform list */ + theTransforms = new ColorTransform [nProfiles]; + + /* initialize transform get loop */ + if (profileList[0].getProfileClass() == ICC_Profile.CLASS_OUTPUT) { + /* if first profile is a printer + render as colorimetric */ + renderState = ICC_Profile.icRelativeColorimetric; + } + else { + renderState = ICC_Profile.icPerceptual; /* render any other + class perceptually */ + } + + whichTrans = ColorTransform.In; + + PCMM mdl = CMSManager.getModule(); + + /* get the transforms from each profile */ + for (i1 = 0; i1 < nProfiles; i1++) { + if (i1 == nProfiles -1) { /* last profile? */ + whichTrans = ColorTransform.Out; /* get output transform */ + } + else { /* check for abstract profile */ + if ((whichTrans == ColorTransform.Simulation) && + (profileList[i1].getProfileClass () == + ICC_Profile.CLASS_ABSTRACT)) { + renderState = ICC_Profile.icPerceptual; + whichTrans = ColorTransform.In; + } + } + + theTransforms[i1] = mdl.createTransform ( + profileList[i1], renderState, whichTrans); + + /* get this profile's rendering intent to select transform + from next profile */ + renderState = getRenderingIntent(profileList[i1]); + + /* "middle" profiles use simulation transform */ + whichTrans = ColorTransform.Simulation; + } + + /* make the net transform */ + thisRasterTransform = mdl.createTransform(theTransforms); + } + + int srcTransferType = src.getTransferType(); + int dstTransferType = dest.getTransferType(); + if ((srcTransferType == DataBuffer.TYPE_FLOAT) || + (srcTransferType == DataBuffer.TYPE_DOUBLE) || + (dstTransferType == DataBuffer.TYPE_FLOAT) || + (dstTransferType == DataBuffer.TYPE_DOUBLE)) { + if (srcMinVals == null) { + getMinMaxValsFromProfiles(profileList[0], + profileList[nProfiles-1]); + } + /* color convert the raster */ + thisRasterTransform.colorConvert(src, dest, + srcMinVals, srcMaxVals, + dstMinVals, dstMaxVals); + } else { + /* color convert the raster */ + thisRasterTransform.colorConvert(src, dest); + } + + + return dest; + } + + /** + * Returns the bounding box of the destination, given this source. + * Note that this will be the same as the the bounding box of the + * source. + * @param src the source BufferedImage + * @return a Rectangle2D that is the bounding box + * of the destination, given the specified src + */ + public final Rectangle2D getBounds2D (BufferedImage src) { + return getBounds2D(src.getRaster()); + } + + /** + * Returns the bounding box of the destination, given this source. + * Note that this will be the same as the the bounding box of the + * source. + * @param src the source Raster + * @return a Rectangle2D that is the bounding box + * of the destination, given the specified src + */ + public final Rectangle2D getBounds2D (Raster src) { + /* return new Rectangle (src.getXOffset(), + src.getYOffset(), + src.getWidth(), src.getHeight()); */ + return src.getBounds(); + } + + /** + * Creates a zeroed destination image with the correct size and number of + * bands, given this source. + * @param src Source image for the filter operation. + * @param destCM ColorModel of the destination. If null, an + * appropriate ColorModel will be used. + * @return a BufferedImage with the correct size and + * number of bands from the specified src. + * @throws IllegalArgumentException if destCM is + * null and this ColorConvertOp was + * created without any ICC_Profile or + * ColorSpace defined for the destination + */ + public BufferedImage createCompatibleDestImage (BufferedImage src, + ColorModel destCM) { + ColorSpace cs = null;; + if (destCM == null) { + if (CSList == null) { + /* ICC case */ + int nProfiles = profileList.length; + if (nProfiles == 0) { + throw new IllegalArgumentException( + "Destination ColorSpace is undefined"); + } + ICC_Profile destProfile = profileList[nProfiles - 1]; + cs = new ICC_ColorSpace(destProfile); + } else { + /* non-ICC case */ + int nSpaces = CSList.length; + cs = CSList[nSpaces - 1]; + } + } + return createCompatibleDestImage(src, destCM, cs); + } + + private BufferedImage createCompatibleDestImage(BufferedImage src, + ColorModel destCM, + ColorSpace destCS) { + BufferedImage image; + if (destCM == null) { + ColorModel srcCM = src.getColorModel(); + int nbands = destCS.getNumComponents(); + boolean hasAlpha = srcCM.hasAlpha(); + if (hasAlpha) { + nbands += 1; + } + int[] nbits = new int[nbands]; + for (int i = 0; i < nbands; i++) { + nbits[i] = 8; + } + destCM = new ComponentColorModel(destCS, nbits, hasAlpha, + srcCM.isAlphaPremultiplied(), + srcCM.getTransparency(), + DataBuffer.TYPE_BYTE); + } + int w = src.getWidth(); + int h = src.getHeight(); + image = new BufferedImage(destCM, + destCM.createCompatibleWritableRaster(w, h), + destCM.isAlphaPremultiplied(), null); + return image; + } + + + /** + * Creates a zeroed destination Raster with the correct size and number of + * bands, given this source. + * @param src the specified Raster + * @return a WritableRaster with the correct size and number + * of bands from the specified src + * @throws IllegalArgumentException if this ColorConvertOp + * was created without sufficient information to define the + * dst and src color spaces + */ + public WritableRaster createCompatibleDestRaster (Raster src) { + int ncomponents; + + if (CSList != null) { + /* non-ICC case */ + if (CSList.length != 2) { + throw new IllegalArgumentException( + "Destination ColorSpace is undefined"); + } + ncomponents = CSList[1].getNumComponents(); + } else { + /* ICC case */ + int nProfiles = profileList.length; + if (nProfiles < 2) { + throw new IllegalArgumentException( + "Destination ColorSpace is undefined"); + } + ncomponents = profileList[nProfiles-1].getNumComponents(); + } + + WritableRaster dest = + Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, + src.getWidth(), + src.getHeight(), + ncomponents, + new Point(src.getMinX(), src.getMinY())); + return dest; + } + + /** + * Returns the location of the destination point given a + * point in the source. If dstPt is non-null, + * it will be used to hold the return value. Note that + * for this class, the destination point will be the same + * as the source point. + * @param srcPt the specified source Point2D + * @param dstPt the destination Point2D + * @return dstPt after setting its location to be + * the same as srcPt + */ + public final Point2D getPoint2D (Point2D srcPt, Point2D dstPt) { + if (dstPt == null) { + dstPt = new Point2D.Float(); + } + dstPt.setLocation(srcPt.getX(), srcPt.getY()); + + return dstPt; + } + + + /** + * Returns the RenderingIntent from the specified ICC Profile. + */ + private int getRenderingIntent (ICC_Profile profile) { + byte[] header = profile.getData(ICC_Profile.icSigHead); + int index = ICC_Profile.icHdrRenderingIntent; + return (((header[index] & 0xff) << 24) | + ((header[index+1] & 0xff) << 16) | + ((header[index+2] & 0xff) << 8) | + (header[index+3] & 0xff)); + } + + /** + * Returns the rendering hints used by this op. + * @return the RenderingHints object of this + * ColorConvertOp + */ + public final RenderingHints getRenderingHints() { + return hints; + } + + private final BufferedImage nonICCBIFilter(BufferedImage src, + ColorSpace srcColorSpace, + BufferedImage dst, + ColorSpace dstColorSpace) { + + int w = src.getWidth(); + int h = src.getHeight(); + ICC_ColorSpace ciespace = + (ICC_ColorSpace) ColorSpace.getInstance(ColorSpace.CS_CIEXYZ); + if (dst == null) { + dst = createCompatibleDestImage(src, null); + dstColorSpace = dst.getColorModel().getColorSpace(); + } else { + if ((h != dst.getHeight()) || (w != dst.getWidth())) { + throw new IllegalArgumentException( + "Width or height of BufferedImages do not match"); + } + } + Raster srcRas = src.getRaster(); + WritableRaster dstRas = dst.getRaster(); + ColorModel srcCM = src.getColorModel(); + ColorModel dstCM = dst.getColorModel(); + int srcNumComp = srcCM.getNumColorComponents(); + int dstNumComp = dstCM.getNumColorComponents(); + boolean dstHasAlpha = dstCM.hasAlpha(); + boolean needSrcAlpha = srcCM.hasAlpha() && dstHasAlpha; + ColorSpace[] list; + if ((CSList == null) && (profileList.length != 0)) { + /* possible non-ICC src, some profiles, possible non-ICC dst */ + boolean nonICCSrc, nonICCDst; + ICC_Profile srcProfile, dstProfile; + if (!(srcColorSpace instanceof ICC_ColorSpace)) { + nonICCSrc = true; + srcProfile = ciespace.getProfile(); + } else { + nonICCSrc = false; + srcProfile = ((ICC_ColorSpace) srcColorSpace).getProfile(); + } + if (!(dstColorSpace instanceof ICC_ColorSpace)) { + nonICCDst = true; + dstProfile = ciespace.getProfile(); + } else { + nonICCDst = false; + dstProfile = ((ICC_ColorSpace) dstColorSpace).getProfile(); + } + /* make a new transform if needed */ + if ((thisTransform == null) || (thisSrcProfile != srcProfile) || + (thisDestProfile != dstProfile) ) { + updateBITransform(srcProfile, dstProfile); + } + // process per scanline + float maxNum = 65535.0f; // use 16-bit precision in CMM + ColorSpace cs; + int iccSrcNumComp; + if (nonICCSrc) { + cs = ciespace; + iccSrcNumComp = 3; + } else { + cs = srcColorSpace; + iccSrcNumComp = srcNumComp; + } + float[] srcMinVal = new float[iccSrcNumComp]; + float[] srcInvDiffMinMax = new float[iccSrcNumComp]; + for (int i = 0; i < srcNumComp; i++) { + srcMinVal[i] = cs.getMinValue(i); + srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]); + } + int iccDstNumComp; + if (nonICCDst) { + cs = ciespace; + iccDstNumComp = 3; + } else { + cs = dstColorSpace; + iccDstNumComp = dstNumComp; + } + float[] dstMinVal = new float[iccDstNumComp]; + float[] dstDiffMinMax = new float[iccDstNumComp]; + for (int i = 0; i < dstNumComp; i++) { + dstMinVal[i] = cs.getMinValue(i); + dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum; + } + float[] dstColor; + if (dstHasAlpha) { + int size = ((dstNumComp + 1) > 3) ? (dstNumComp + 1) : 3; + dstColor = new float[size]; + } else { + int size = (dstNumComp > 3) ? dstNumComp : 3; + dstColor = new float[size]; + } + short[] srcLine = new short[w * iccSrcNumComp]; + short[] dstLine = new short[w * iccDstNumComp]; + Object pixel; + float[] color; + float[] alpha = null; + if (needSrcAlpha) { + alpha = new float[w]; + } + int idx; + // process each scanline + for (int y = 0; y < h; y++) { + // convert src scanline + pixel = null; + color = null; + idx = 0; + for (int x = 0; x < w; x++) { + pixel = srcRas.getDataElements(x, y, pixel); + color = srcCM.getNormalizedComponents(pixel, color, 0); + if (needSrcAlpha) { + alpha[x] = color[srcNumComp]; + } + if (nonICCSrc) { + color = srcColorSpace.toCIEXYZ(color); + } + for (int i = 0; i < iccSrcNumComp; i++) { + srcLine[idx++] = (short) + ((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] + + 0.5f); + } + } + // color convert srcLine to dstLine + thisTransform.colorConvert(srcLine, dstLine); + // convert dst scanline + pixel = null; + idx = 0; + for (int x = 0; x < w; x++) { + for (int i = 0; i < iccDstNumComp; i++) { + dstColor[i] = ((float) (dstLine[idx++] & 0xffff)) * + dstDiffMinMax[i] + dstMinVal[i]; + } + if (nonICCDst) { + color = srcColorSpace.fromCIEXYZ(dstColor); + for (int i = 0; i < dstNumComp; i++) { + dstColor[i] = color[i]; + } + } + if (needSrcAlpha) { + dstColor[dstNumComp] = alpha[x]; + } else if (dstHasAlpha) { + dstColor[dstNumComp] = 1.0f; + } + pixel = dstCM.getDataElements(dstColor, 0, pixel); + dstRas.setDataElements(x, y, pixel); + } + } + } else { + /* possible non-ICC src, possible CSList, possible non-ICC dst */ + // process per pixel + int numCS; + if (CSList == null) { + numCS = 0; + } else { + numCS = CSList.length; + } + float[] dstColor; + if (dstHasAlpha) { + dstColor = new float[dstNumComp + 1]; + } else { + dstColor = new float[dstNumComp]; + } + Object spixel = null; + Object dpixel = null; + float[] color = null; + float[] tmpColor; + // process each pixel + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + spixel = srcRas.getDataElements(x, y, spixel); + color = srcCM.getNormalizedComponents(spixel, color, 0); + tmpColor = srcColorSpace.toCIEXYZ(color); + for (int i = 0; i < numCS; i++) { + tmpColor = CSList[i].fromCIEXYZ(tmpColor); + tmpColor = CSList[i].toCIEXYZ(tmpColor); + } + tmpColor = dstColorSpace.fromCIEXYZ(tmpColor); + for (int i = 0; i < dstNumComp; i++) { + dstColor[i] = tmpColor[i]; + } + if (needSrcAlpha) { + dstColor[dstNumComp] = color[srcNumComp]; + } else if (dstHasAlpha) { + dstColor[dstNumComp] = 1.0f; + } + dpixel = dstCM.getDataElements(dstColor, 0, dpixel); + dstRas.setDataElements(x, y, dpixel); + + } + } + } + + return dst; + } + + /* color convert a Raster - handles byte, ushort, int, short, float, + or double transferTypes */ + private final WritableRaster nonICCRasterFilter(Raster src, + WritableRaster dst) { + + if (CSList.length != 2) { + throw new IllegalArgumentException( + "Destination ColorSpace is undefined"); + } + if (src.getNumBands() != CSList[0].getNumComponents()) { + throw new IllegalArgumentException( + "Numbers of source Raster bands and source color space " + + "components do not match"); + } + if (dst == null) { + dst = createCompatibleDestRaster(src); + } else { + if (src.getHeight() != dst.getHeight() || + src.getWidth() != dst.getWidth()) { + throw new IllegalArgumentException( + "Width or height of Rasters do not match"); + } + if (dst.getNumBands() != CSList[1].getNumComponents()) { + throw new IllegalArgumentException( + "Numbers of destination Raster bands and destination " + + "color space components do not match"); + } + } + + if (srcMinVals == null) { + getMinMaxValsFromColorSpaces(CSList[0], CSList[1]); + } + + SampleModel srcSM = src.getSampleModel(); + SampleModel dstSM = dst.getSampleModel(); + boolean srcIsFloat, dstIsFloat; + int srcTransferType = src.getTransferType(); + int dstTransferType = dst.getTransferType(); + if ((srcTransferType == DataBuffer.TYPE_FLOAT) || + (srcTransferType == DataBuffer.TYPE_DOUBLE)) { + srcIsFloat = true; + } else { + srcIsFloat = false; + } + if ((dstTransferType == DataBuffer.TYPE_FLOAT) || + (dstTransferType == DataBuffer.TYPE_DOUBLE)) { + dstIsFloat = true; + } else { + dstIsFloat = false; + } + int w = src.getWidth(); + int h = src.getHeight(); + int srcNumBands = src.getNumBands(); + int dstNumBands = dst.getNumBands(); + float[] srcScaleFactor = null; + float[] dstScaleFactor = null; + if (!srcIsFloat) { + srcScaleFactor = new float[srcNumBands]; + for (int i = 0; i < srcNumBands; i++) { + if (srcTransferType == DataBuffer.TYPE_SHORT) { + srcScaleFactor[i] = (srcMaxVals[i] - srcMinVals[i]) / + 32767.0f; + } else { + srcScaleFactor[i] = (srcMaxVals[i] - srcMinVals[i]) / + ((float) ((1 << srcSM.getSampleSize(i)) - 1)); + } + } + } + if (!dstIsFloat) { + dstScaleFactor = new float[dstNumBands]; + for (int i = 0; i < dstNumBands; i++) { + if (dstTransferType == DataBuffer.TYPE_SHORT) { + dstScaleFactor[i] = 32767.0f / + (dstMaxVals[i] - dstMinVals[i]); + } else { + dstScaleFactor[i] = + ((float) ((1 << dstSM.getSampleSize(i)) - 1)) / + (dstMaxVals[i] - dstMinVals[i]); + } + } + } + int ys = src.getMinY(); + int yd = dst.getMinY(); + int xs, xd; + float sample; + float[] color = new float[srcNumBands]; + float[] tmpColor; + ColorSpace srcColorSpace = CSList[0]; + ColorSpace dstColorSpace = CSList[1]; + // process each pixel + for (int y = 0; y < h; y++, ys++, yd++) { + // get src scanline + xs = src.getMinX(); + xd = dst.getMinX(); + for (int x = 0; x < w; x++, xs++, xd++) { + for (int i = 0; i < srcNumBands; i++) { + sample = src.getSampleFloat(xs, ys, i); + if (!srcIsFloat) { + sample = sample * srcScaleFactor[i] + srcMinVals[i]; + } + color[i] = sample; + } + tmpColor = srcColorSpace.toCIEXYZ(color); + tmpColor = dstColorSpace.fromCIEXYZ(tmpColor); + for (int i = 0; i < dstNumBands; i++) { + sample = tmpColor[i]; + if (!dstIsFloat) { + sample = (sample - dstMinVals[i]) * dstScaleFactor[i]; + } + dst.setSample(xd, yd, i, sample); + } + } + } + return dst; + } + + private void getMinMaxValsFromProfiles(ICC_Profile srcProfile, + ICC_Profile dstProfile) { + int type = srcProfile.getColorSpaceType(); + int nc = srcProfile.getNumComponents(); + srcMinVals = new float[nc]; + srcMaxVals = new float[nc]; + setMinMax(type, nc, srcMinVals, srcMaxVals); + type = dstProfile.getColorSpaceType(); + nc = dstProfile.getNumComponents(); + dstMinVals = new float[nc]; + dstMaxVals = new float[nc]; + setMinMax(type, nc, dstMinVals, dstMaxVals); + } + + private void setMinMax(int type, int nc, float[] minVals, float[] maxVals) { + if (type == ColorSpace.TYPE_Lab) { + minVals[0] = 0.0f; // L + maxVals[0] = 100.0f; + minVals[1] = -128.0f; // a + maxVals[1] = 127.0f; + minVals[2] = -128.0f; // b + maxVals[2] = 127.0f; + } else if (type == ColorSpace.TYPE_XYZ) { + minVals[0] = minVals[1] = minVals[2] = 0.0f; // X, Y, Z + maxVals[0] = maxVals[1] = maxVals[2] = 1.0f + (32767.0f/ 32768.0f); + } else { + for (int i = 0; i < nc; i++) { + minVals[i] = 0.0f; + maxVals[i] = 1.0f; + } + } + } + + private void getMinMaxValsFromColorSpaces(ColorSpace srcCspace, + ColorSpace dstCspace) { + int nc = srcCspace.getNumComponents(); + srcMinVals = new float[nc]; + srcMaxVals = new float[nc]; + for (int i = 0; i < nc; i++) { + srcMinVals[i] = srcCspace.getMinValue(i); + srcMaxVals[i] = srcCspace.getMaxValue(i); + } + nc = dstCspace.getNumComponents(); + dstMinVals = new float[nc]; + dstMaxVals = new float[nc]; + for (int i = 0; i < nc; i++) { + dstMinVals[i] = dstCspace.getMinValue(i); + dstMaxVals[i] = dstCspace.getMaxValue(i); + } + } + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/ComponentSampleModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/ComponentSampleModel.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,1202 @@ +/* + * Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import java.util.Arrays; + +/** + * This class represents image data which is stored such that each sample + * of a pixel occupies one data element of the DataBuffer. It stores the + * N samples which make up a pixel in N separate data array elements. + * Different bands may be in different banks of the DataBuffer. + * Accessor methods are provided so that image data can be manipulated + * directly. This class can support different kinds of interleaving, e.g. + * band interleaving, scanline interleaving, and pixel interleaving. + * Pixel stride is the number of data array elements between two samples + * for the same band on the same scanline. Scanline stride is the number + * of data array elements between a given sample and the corresponding sample + * in the same column of the next scanline. Band offsets denote the number + * of data array elements from the first data array element of the bank + * of the DataBuffer holding each band to the first sample of the band. + * The bands are numbered from 0 to N-1. This class can represent image + * data for which each sample is an unsigned integral number which can be + * stored in 8, 16, or 32 bits (using DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT, + * respectively), data for which each sample is a signed integral number + * which can be stored in 16 bits (using DataBuffer.TYPE_SHORT), + * or data for which each sample is a signed float or double quantity + * (using DataBuffer.TYPE_FLOAT or + * DataBuffer.TYPE_DOUBLE, respectively). + * All samples of a given ComponentSampleModel + * are stored with the same precision. All strides and offsets must be + * non-negative. This class supports + * {@link DataBuffer#TYPE_BYTE TYPE_BYTE}, + * {@link DataBuffer#TYPE_USHORT TYPE_USHORT}, + * {@link DataBuffer#TYPE_SHORT TYPE_SHORT}, + * {@link DataBuffer#TYPE_INT TYPE_INT}, + * {@link DataBuffer#TYPE_FLOAT TYPE_FLOAT}, + * {@link DataBuffer#TYPE_DOUBLE TYPE_DOUBLE}, + * @see java.awt.image.PixelInterleavedSampleModel + * @see java.awt.image.BandedSampleModel + */ + +public class ComponentSampleModel extends SampleModel +{ + /** Offsets for all bands in data array elements. */ + protected int bandOffsets[]; + + /** Index for each bank storing a band of image data. */ + protected int[] bankIndices; + + /** + * The number of bands in this + * ComponentSampleModel. + */ + protected int numBands = 1; + + /** + * The number of banks in this + * ComponentSampleModel. + */ + protected int numBanks = 1; + + /** + * Line stride (in data array elements) of the region of image + * data described by this ComponentSampleModel. + */ + protected int scanlineStride; + + /** Pixel stride (in data array elements) of the region of image + * data described by this ComponentSampleModel. + */ + protected int pixelStride; + + static private native void initIDs(); + static { + ColorModel.loadLibraries(); + initIDs(); + } + + /** + * Constructs a ComponentSampleModel with the specified parameters. + * The number of bands will be given by the length of the bandOffsets array. + * All bands will be stored in the first bank of the DataBuffer. + * @param dataType the data type for storing samples + * @param w the width (in pixels) of the region of + * image data described + * @param h the height (in pixels) of the region of + * image data described + * @param pixelStride the pixel stride of the region of image + * data described + * @param scanlineStride the line stride of the region of image + * data described + * @param bandOffsets the offsets of all bands + * @throws IllegalArgumentException if w or + * h is not greater than 0 + * @throws IllegalArgumentException if pixelStride + * is less than 0 + * @throws IllegalArgumentException if scanlineStride + * is less than 0 + * @throws IllegalArgumentException if numBands + * is less than 1 + * @throws IllegalArgumentException if the product of w + * and h is greater than + * Integer.MAX_VALUE + * @throws IllegalArgumentException if dataType is not + * one of the supported data types + */ + public ComponentSampleModel(int dataType, + int w, int h, + int pixelStride, + int scanlineStride, + int bandOffsets[]) { + super(dataType, w, h, bandOffsets.length); + this.dataType = dataType; + this.pixelStride = pixelStride; + this.scanlineStride = scanlineStride; + this.bandOffsets = (int[])bandOffsets.clone(); + numBands = bandOffsets.length; + if (pixelStride < 0) { + throw new IllegalArgumentException("Pixel stride must be >= 0"); + } + // TODO - bug 4296691 - remove this check + if (scanlineStride < 0) { + throw new IllegalArgumentException("Scanline stride must be >= 0"); + } + if (numBands < 1) { + throw new IllegalArgumentException("Must have at least one band."); + } + if ((dataType < DataBuffer.TYPE_BYTE) || + (dataType > DataBuffer.TYPE_DOUBLE)) { + throw new IllegalArgumentException("Unsupported dataType."); + } + bankIndices = new int[numBands]; + for (int i=0; iw or + * h is not greater than 0 + * @throws IllegalArgumentException if pixelStride + * is less than 0 + * @throws IllegalArgumentException if scanlineStride + * is less than 0 + * @throws IllegalArgumentException if the length of + * bankIndices does not equal the length of + * bankOffsets + * @throws IllegalArgumentException if any of the bank indices + * of bandIndices is less than 0 + * @throws IllegalArgumentException if dataType is not + * one of the supported data types + */ + public ComponentSampleModel(int dataType, + int w, int h, + int pixelStride, + int scanlineStride, + int bankIndices[], + int bandOffsets[]) { + super(dataType, w, h, bandOffsets.length); + this.dataType = dataType; + this.pixelStride = pixelStride; + this.scanlineStride = scanlineStride; + this.bandOffsets = (int[])bandOffsets.clone(); + this.bankIndices = (int[]) bankIndices.clone(); + if (pixelStride < 0) { + throw new IllegalArgumentException("Pixel stride must be >= 0"); + } + // TODO - bug 4296691 - remove this check + if (scanlineStride < 0) { + throw new IllegalArgumentException("Scanline stride must be >= 0"); + } + if ((dataType < DataBuffer.TYPE_BYTE) || + (dataType > DataBuffer.TYPE_DOUBLE)) { + throw new IllegalArgumentException("Unsupported dataType."); + } + int maxBank = bankIndices[0]; + if (maxBank < 0) { + throw new IllegalArgumentException("Index of bank 0 is less than "+ + "0 ("+maxBank+")"); + } + for (int i=1; i < bankIndices.length; i++) { + if (bankIndices[i] > maxBank) { + maxBank = bankIndices[i]; + } + else if (bankIndices[i] < 0) { + throw new IllegalArgumentException("Index of bank "+i+ + " is less than 0 ("+ + maxBank+")"); + } + } + numBanks = maxBank+1; + numBands = bandOffsets.length; + if (bandOffsets.length != bankIndices.length) { + throw new IllegalArgumentException("Length of bandOffsets must "+ + "equal length of bankIndices."); + } + } + + /** + * Returns the size of the data buffer (in data elements) needed + * for a data buffer that matches this ComponentSampleModel. + */ + private long getBufferSize() { + int maxBandOff=bandOffsets[0]; + for (int i=1; i= 0) + size += maxBandOff+1; + if (pixelStride > 0) + size += pixelStride * (width-1); + if (scanlineStride > 0) + size += scanlineStride*(height-1); + return size; + } + + /** + * Preserves band ordering with new step factor... + */ + int []orderBands(int orig[], int step) { + int map[] = new int[orig.length]; + int ret[] = new int[orig.length]; + + for (int i=0; i orig[map[j]]) { + index = j; + } + } + ret[map[index]] = i*step; + map[index] = map[i]; + } + return ret; + } + + /** + * Creates a new ComponentSampleModel with the specified + * width and height. The new SampleModel will have the same + * number of bands, storage data type, interleaving scheme, and + * pixel stride as this SampleModel. + * @param w the width of the resulting SampleModel + * @param h the height of the resulting SampleModel + * @return a new ComponentSampleModel with the specified size + * @throws IllegalArgumentException if w or + * h is not greater than 0 + */ + public SampleModel createCompatibleSampleModel(int w, int h) { + SampleModel ret=null; + long size; + int minBandOff=bandOffsets[0]; + int maxBandOff=bandOffsets[0]; + for (int i=1; i lStride) { + if (pStride > bStride) { + if (lStride > bStride) { // pix > line > band + bandOff = new int[bandOffsets.length]; + for (int i=0; i band > line + bandOff = orderBands(bandOffsets,lStride*h); + pStride = bands*lStride*h; + } + } else { // band > pix > line + pStride = lStride*h; + bandOff = orderBands(bandOffsets,pStride*w); + } + } else { + if (pStride > bStride) { // line > pix > band + bandOff = new int[bandOffsets.length]; + for (int i=0; i bStride) { // line > band > pix + bandOff = orderBands(bandOffsets,pStride*w); + lStride = bands*pStride*w; + } else { // band > line > pix + lStride = pStride*w; + bandOff = orderBands(bandOffsets,lStride*h); + } + } + } + + // make sure we make room for negative offsets... + int base = 0; + if (scanlineStride < 0) { + base += lStride*h; + lStride *= -1; + } + if (pixelStride < 0) { + base += pStride*w; + pStride *= -1; + } + + for (int i=0; iComponentSampleModel + * @return a ComponentSampleModel created with a subset + * of bands from this ComponentSampleModel. + */ + public SampleModel createSubsetSampleModel(int bands[]) { + if (bands.length > bankIndices.length) + throw new RasterFormatException("There are only " + + bankIndices.length + + " bands"); + int newBankIndices[] = new int[bands.length]; + int newBandOffsets[] = new int[bands.length]; + + for (int i=0; iDataBuffer that corresponds to this + * ComponentSampleModel. + * The DataBuffer object's data type, number of banks, + * and size are be consistent with this ComponentSampleModel. + * @return a DataBuffer whose data type, number of banks + * and size are consistent with this + * ComponentSampleModel. + */ + public DataBuffer createDataBuffer() { + DataBuffer dataBuffer = null; + + int size = (int)getBufferSize(); + switch (dataType) { + case DataBuffer.TYPE_BYTE: + dataBuffer = new DataBufferByte(size, numBanks); + break; + case DataBuffer.TYPE_USHORT: + dataBuffer = new DataBufferUShort(size, numBanks); + break; + case DataBuffer.TYPE_SHORT: + dataBuffer = new DataBufferShort(size, numBanks); + break; + case DataBuffer.TYPE_INT: + dataBuffer = new DataBufferInt(size, numBanks); + break; + case DataBuffer.TYPE_FLOAT: + dataBuffer = new DataBufferFloat(size, numBanks); + break; + case DataBuffer.TYPE_DOUBLE: + dataBuffer = new DataBufferDouble(size, numBanks); + break; + } + + return dataBuffer; + } + + + /** Gets the offset for the first band of pixel (x,y). + * A sample of the first band can be retrieved from a + * DataBuffer + * data with a ComponentSampleModel + * csm as + *

+     *        data.getElem(csm.getOffset(x, y));
+     * 
+ * @param x the X location of the pixel + * @param y the Y location of the pixel + * @return the offset for the first band of the specified pixel. + */ + public int getOffset(int x, int y) { + int offset = y*scanlineStride + x*pixelStride + bandOffsets[0]; + return offset; + } + + /** Gets the offset for band b of pixel (x,y). + * A sample of band b can be retrieved from a + * DataBuffer data + * with a ComponentSampleModel csm as + *
+     *       data.getElem(csm.getOffset(x, y, b));
+     * 
+ * @param x the X location of the specified pixel + * @param y the Y location of the specified pixel + * @param b the specified band + * @return the offset for the specified band of the specified pixel. + */ + public int getOffset(int x, int y, int b) { + int offset = y*scanlineStride + x*pixelStride + bandOffsets[b]; + return offset; + } + + /** Returns the number of bits per sample for all bands. + * @return an array containing the number of bits per sample + * for all bands, where each element in the array + * represents a band. + */ + public final int[] getSampleSize() { + int sampleSize[] = new int [numBands]; + int sizeInBits = getSampleSize(0); + + for (int i=0; iComponentSampleModel. + */ + public final int getScanlineStride() { + return scanlineStride; + } + + /** Returns the pixel stride of this ComponentSampleModel. + * @return the pixel stride of this ComponentSampleModel. + */ + public final int getPixelStride() { + return pixelStride; + } + + /** + * Returns the number of data elements needed to transfer a pixel + * with the + * {@link #getDataElements(int, int, Object, DataBuffer) } and + * {@link #setDataElements(int, int, Object, DataBuffer) } + * methods. + * For a ComponentSampleModel, this is identical to the + * number of bands. + * @return the number of data elements needed to transfer a pixel with + * the getDataElements and + * setDataElements methods. + * @see java.awt.image.SampleModel#getNumDataElements + * @see #getNumBands + */ + public final int getNumDataElements() { + return getNumBands(); + } + + /** + * Returns data for a single pixel in a primitive array of type + * TransferType. For a ComponentSampleModel, + * this is the same as the data type, and samples are returned + * one per array element. Generally, obj should + * be passed in as null, so that the Object + * is created automatically and is the right primitive data type. + *

+ * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is + * described by ComponentSampleModel csm1, + * to DataBuffer db2, whose storage layout + * is described by ComponentSampleModel csm2. + * The transfer is usually more efficient than using + * getPixel and setPixel. + *

+     *       ComponentSampleModel csm1, csm2;
+     *       DataBufferInt db1, db2;
+     *       csm2.setDataElements(x, y,
+     *                            csm1.getDataElements(x, y, null, db1), db2);
+     * 
+ * + * Using getDataElements and setDataElements + * to transfer between two DataBuffer/SampleModel + * pairs is legitimate if the SampleModel objects have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * If obj is not null, it should be a + * primitive array of type TransferType. + * Otherwise, a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException might be thrown if the + * coordinates are not in bounds, or if obj is not + * null and is not large enough to hold + * the pixel data. + * + * @param x the X coordinate of the pixel location + * @param y the Y coordinate of the pixel location + * @param obj if non-null, a primitive array + * in which to return the pixel data + * @param data the DataBuffer containing the image data + * @return the data of the specified pixel + * @see #setDataElements(int, int, Object, DataBuffer) + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds, or if obj is too small to hold the ouput. + */ + public Object getDataElements(int x, int y, Object obj, DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int type = getTransferType(); + int numDataElems = getNumDataElements(); + int pixelOffset = y*scanlineStride + x*pixelStride; + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] bdata; + + if (obj == null) + bdata = new byte[numDataElems]; + else + bdata = (byte[])obj; + + for (int i=0; iArrayIndexOutOfBoundsException might be thrown if + * the coordinates are not in bounds. + * @param x the X coordinate of the pixel location + * @param y the Y coordinate of the pixel location + * @param iArray If non-null, returns the samples in this array + * @param data The DataBuffer containing the image data + * @return the samples of the specified pixel. + * @see #setPixel(int, int, int[], DataBuffer) + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds, or if iArray is too small to hold the output. + */ + public int[] getPixel(int x, int y, int iArray[], DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int pixels[]; + if (iArray != null) { + pixels = iArray; + } else { + pixels = new int [numBands]; + } + int pixelOffset = y*scanlineStride + x*pixelStride; + for (int i=0; iArrayIndexOutOfBoundsException might be thrown if + * the coordinates are not in bounds. + * @param x The X coordinate of the upper left pixel location + * @param y The Y coordinate of the upper left pixel location + * @param w The width of the pixel rectangle + * @param h The height of the pixel rectangle + * @param iArray If non-null, returns the samples in this array + * @param data The DataBuffer containing the image data + * @return the samples of the pixels within the specified region. + * @see #setPixels(int, int, int, int, int[], DataBuffer) + */ + public int[] getPixels(int x, int y, int w, int h, + int iArray[], DataBuffer data) { + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int pixels[]; + if (iArray != null) { + pixels = iArray; + } else { + pixels = new int [w*h*numBands]; + } + int lineOffset = y*scanlineStride + x*pixelStride; + int srcOffset = 0; + + for (int i = 0; i < h; i++) { + int pixelOffset = lineOffset; + for (int j = 0; j < w; j++) { + for (int k=0; k < numBands; k++) { + pixels[srcOffset++] = + data.getElem(bankIndices[k], pixelOffset + bandOffsets[k]); + } + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + return pixels; + } + + /** + * Returns as int the sample in a specified band for the pixel + * located at (x,y). + * An ArrayIndexOutOfBoundsException might be thrown if + * the coordinates are not in bounds. + * @param x the X coordinate of the pixel location + * @param y the Y coordinate of the pixel location + * @param b the band to return + * @param data the DataBuffer containing the image data + * @return the sample in a specified band for the specified pixel + * @see #setSample(int, int, int, int, DataBuffer) + */ + public int getSample(int x, int y, int b, DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int sample = data.getElem(bankIndices[b], + y*scanlineStride + x*pixelStride + + bandOffsets[b]); + return sample; + } + + /** + * Returns the sample in a specified band + * for the pixel located at (x,y) as a float. + * An ArrayIndexOutOfBoundsException might be + * thrown if the coordinates are not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to return + * @param data The DataBuffer containing the image data + * @return a float value representing the sample in the specified + * band for the specified pixel. + */ + public float getSampleFloat(int x, int y, int b, DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + float sample = data.getElemFloat(bankIndices[b], + y*scanlineStride + x*pixelStride + + bandOffsets[b]); + return sample; + } + + /** + * Returns the sample in a specified band + * for a pixel located at (x,y) as a double. + * An ArrayIndexOutOfBoundsException might be + * thrown if the coordinates are not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to return + * @param data The DataBuffer containing the image data + * @return a double value representing the sample in the specified + * band for the specified pixel. + */ + public double getSampleDouble(int x, int y, int b, DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + double sample = data.getElemDouble(bankIndices[b], + y*scanlineStride + x*pixelStride + + bandOffsets[b]); + return sample; + } + + /** + * Returns the samples in a specified band for the specified rectangle + * of pixels in an int array, one sample per data array element. + * An ArrayIndexOutOfBoundsException might be thrown if + * the coordinates are not in bounds. + * @param x The X coordinate of the upper left pixel location + * @param y The Y coordinate of the upper left pixel location + * @param w the width of the pixel rectangle + * @param h the height of the pixel rectangle + * @param b the band to return + * @param iArray if non-null, returns the samples + * in this array + * @param data the DataBuffer containing the image data + * @return the samples in the specified band of the specified pixel + * @see #setSamples(int, int, int, int, int, int[], DataBuffer) + */ + public int[] getSamples(int x, int y, int w, int h, int b, + int iArray[], DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int samples[]; + if (iArray != null) { + samples = iArray; + } else { + samples = new int [w*h]; + } + int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b]; + int srcOffset = 0; + + for (int i = 0; i < h; i++) { + int sampleOffset = lineOffset; + for (int j = 0; j < w; j++) { + samples[srcOffset++] = data.getElem(bankIndices[b], + sampleOffset); + sampleOffset += pixelStride; + } + lineOffset += scanlineStride; + } + return samples; + } + + /** + * Sets the data for a single pixel in the specified + * DataBuffer from a primitive array of type + * TransferType. For a ComponentSampleModel, + * this is the same as the data type, and samples are transferred + * one per array element. + *

+ * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is + * described by ComponentSampleModel csm1, + * to DataBuffer db2, whose storage layout + * is described by ComponentSampleModel csm2. + * The transfer is usually more efficient than using + * getPixel and setPixel. + *

+     *       ComponentSampleModel csm1, csm2;
+     *       DataBufferInt db1, db2;
+     *       csm2.setDataElements(x, y, csm1.getDataElements(x, y, null, db1),
+     *                            db2);
+     * 
+ * Using getDataElements and setDataElements + * to transfer between two DataBuffer/SampleModel pairs + * is legitimate if the SampleModel objects have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * A ClassCastException is thrown if obj is not + * a primitive array of type TransferType. + * An ArrayIndexOutOfBoundsException might be thrown if + * the coordinates are not in bounds, or if obj is not large + * enough to hold the pixel data. + * @param x the X coordinate of the pixel location + * @param y the Y coordinate of the pixel location + * @param obj a primitive array containing pixel data + * @param data the DataBuffer containing the image data + * @see #getDataElements(int, int, Object, DataBuffer) + */ + public void setDataElements(int x, int y, Object obj, DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int type = getTransferType(); + int numDataElems = getNumDataElements(); + int pixelOffset = y*scanlineStride + x*pixelStride; + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] barray = (byte[])obj; + + for (int i=0; iDataBuffer using an int array of + * samples for input. An ArrayIndexOutOfBoundsException + * might be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param iArray The input samples in an int array + * @param data The DataBuffer containing the image data + * @see #getPixel(int, int, int[], DataBuffer) + */ + public void setPixel(int x, int y, int iArray[], DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int pixelOffset = y*scanlineStride + x*pixelStride; + for (int i=0; iArrayIndexOutOfBoundsException might be thrown if the + * coordinates are not in bounds. + * @param x The X coordinate of the upper left pixel location + * @param y The Y coordinate of the upper left pixel location + * @param w The width of the pixel rectangle + * @param h The height of the pixel rectangle + * @param iArray The input samples in an int array + * @param data The DataBuffer containing the image data + * @see #getPixels(int, int, int, int, int[], DataBuffer) + */ + public void setPixels(int x, int y, int w, int h, + int iArray[], DataBuffer data) { + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int lineOffset = y*scanlineStride + x*pixelStride; + int srcOffset = 0; + + for (int i = 0; i < h; i++) { + int pixelOffset = lineOffset; + for (int j = 0; j < w; j++) { + for (int k=0; k < numBands; k++) { + data.setElem(bankIndices[k], pixelOffset + bandOffsets[k], + iArray[srcOffset++]); + } + pixelOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using an int for input. + * An ArrayIndexOutOfBoundsException might be thrown if the + * coordinates are not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b the band to set + * @param s the input sample as an int + * @param data the DataBuffer containing the image data + * @see #getSample(int, int, int, DataBuffer) + */ + public void setSample(int x, int y, int b, int s, + DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + data.setElem(bankIndices[b], + y*scanlineStride + x*pixelStride + bandOffsets[b], s); + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using a float for input. + * An ArrayIndexOutOfBoundsException might be thrown if + * the coordinates are not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to set + * @param s The input sample as a float + * @param data The DataBuffer containing the image data + * @see #getSample(int, int, int, DataBuffer) + */ + public void setSample(int x, int y, int b, + float s , + DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + data.setElemFloat(bankIndices[b], + y*scanlineStride + x*pixelStride + bandOffsets[b], + s); + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using a double for input. + * An ArrayIndexOutOfBoundsException might be thrown if + * the coordinates are not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to set + * @param s The input sample as a double + * @param data The DataBuffer containing the image data + * @see #getSample(int, int, int, DataBuffer) + */ + public void setSample(int x, int y, int b, + double s, + DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + data.setElemDouble(bankIndices[b], + y*scanlineStride + x*pixelStride + bandOffsets[b], + s); + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from an int array containing one sample per data array element. + * An ArrayIndexOutOfBoundsException might be thrown if the + * coordinates are not in bounds. + * @param x The X coordinate of the upper left pixel location + * @param y The Y coordinate of the upper left pixel location + * @param w The width of the pixel rectangle + * @param h The height of the pixel rectangle + * @param b The band to set + * @param iArray The input samples in an int array + * @param data The DataBuffer containing the image data + * @see #getSamples(int, int, int, int, int, int[], DataBuffer) + */ + public void setSamples(int x, int y, int w, int h, int b, + int iArray[], DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int lineOffset = y*scanlineStride + x*pixelStride + bandOffsets[b]; + int srcOffset = 0; + + for (int i = 0; i < h; i++) { + int sampleOffset = lineOffset; + for (int j = 0; j < w; j++) { + data.setElem(bankIndices[b], sampleOffset, iArray[srcOffset++]); + sampleOffset += pixelStride; + } + lineOffset += scanlineStride; + } + } + + public boolean equals(Object o) { + if ((o == null) || !(o instanceof ComponentSampleModel)) { + return false; + } + + ComponentSampleModel that = (ComponentSampleModel)o; + return this.width == that.width && + this.height == that.height && + this.numBands == that.numBands && + this.dataType == that.dataType && + Arrays.equals(this.bandOffsets, that.bandOffsets) && + Arrays.equals(this.bankIndices, that.bankIndices) && + this.numBands == that.numBands && + this.numBanks == that.numBanks && + this.scanlineStride == that.scanlineStride && + this.pixelStride == that.pixelStride; + } + + // If we implement equals() we must also implement hashCode + public int hashCode() { + int hash = 0; + hash = width; + hash <<= 8; + hash ^= height; + hash <<= 8; + hash ^= numBands; + hash <<= 8; + hash ^= dataType; + hash <<= 8; + for (int i = 0; i < bandOffsets.length; i++) { + hash ^= bandOffsets[i]; + hash <<= 8; + } + for (int i = 0; i < bankIndices.length; i++) { + hash ^= bankIndices[i]; + hash <<= 8; + } + hash ^= numBands; + hash <<= 8; + hash ^= numBanks; + hash <<= 8; + hash ^= scanlineStride; + hash <<= 8; + hash ^= pixelStride; + return hash; + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/DataBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/DataBuffer.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,535 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import sun.java2d.StateTrackable.State; +import static sun.java2d.StateTrackable.State.*; +import sun.java2d.StateTrackableDelegate; + +import sun.awt.image.SunWritableRaster; + +/** + * This class exists to wrap one or more data arrays. Each data array in + * the DataBuffer is referred to as a bank. Accessor methods for getting + * and setting elements of the DataBuffer's banks exist with and without + * a bank specifier. The methods without a bank specifier use the default 0th + * bank. The DataBuffer can optionally take an offset per bank, so that + * data in an existing array can be used even if the interesting data + * doesn't start at array location zero. Getting or setting the 0th + * element of a bank, uses the (0+offset)th element of the array. The + * size field specifies how much of the data array is available for + * use. Size + offset for a given bank should never be greater + * than the length of the associated data array. The data type of + * a data buffer indicates the type of the data array(s) and may also + * indicate additional semantics, e.g. storing unsigned 8-bit data + * in elements of a byte array. The data type may be TYPE_UNDEFINED + * or one of the types defined below. Other types may be added in + * the future. Generally, an object of class DataBuffer will be cast down + * to one of its data type specific subclasses to access data type specific + * methods for improved performance. Currently, the Java 2D(tm) API + * image classes use TYPE_BYTE, TYPE_USHORT, TYPE_INT, TYPE_SHORT, + * TYPE_FLOAT, and TYPE_DOUBLE DataBuffers to store image data. + * @see java.awt.image.Raster + * @see java.awt.image.SampleModel + */ +public abstract class DataBuffer { + + /** Tag for unsigned byte data. */ + public static final int TYPE_BYTE = 0; + + /** Tag for unsigned short data. */ + public static final int TYPE_USHORT = 1; + + /** Tag for signed short data. Placeholder for future use. */ + public static final int TYPE_SHORT = 2; + + /** Tag for int data. */ + public static final int TYPE_INT = 3; + + /** Tag for float data. Placeholder for future use. */ + public static final int TYPE_FLOAT = 4; + + /** Tag for double data. Placeholder for future use. */ + public static final int TYPE_DOUBLE = 5; + + /** Tag for undefined data. */ + public static final int TYPE_UNDEFINED = 32; + + /** The data type of this DataBuffer. */ + protected int dataType; + + /** The number of banks in this DataBuffer. */ + protected int banks; + + /** Offset into default (first) bank from which to get the first element. */ + protected int offset; + + /** Usable size of all banks. */ + protected int size; + + /** Offsets into all banks. */ + protected int offsets[]; + + /* The current StateTrackable state. */ + StateTrackableDelegate theTrackable; + + /** Size of the data types indexed by DataType tags defined above. */ + private static final int dataTypeSize[] = {8,16,16,32,32,64}; + + /** Returns the size (in bits) of the data type, given a datatype tag. + * @param type the value of one of the defined datatype tags + * @return the size of the data type + * @throws IllegalArgumentException if type is less than + * zero or greater than {@link #TYPE_DOUBLE} + */ + public static int getDataTypeSize(int type) { + if (type < TYPE_BYTE || type > TYPE_DOUBLE) { + throw new IllegalArgumentException("Unknown data type "+type); + } + return dataTypeSize[type]; + } + + /** + * Constructs a DataBuffer containing one bank of the specified + * data type and size. + * + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + */ + protected DataBuffer(int dataType, int size) { + this(UNTRACKABLE, dataType, size); + } + + /** + * Constructs a DataBuffer containing one bank of the specified + * data type and size with the indicated initial {@link State State}. + * + * @param initialState the initial {@link State State} state of the data + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @since 1.7 + */ + DataBuffer(State initialState, + int dataType, int size) + { + this.theTrackable = StateTrackableDelegate.createInstance(initialState); + this.dataType = dataType; + this.banks = 1; + this.size = size; + this.offset = 0; + this.offsets = new int[1]; // init to 0 by new + } + + /** + * Constructs a DataBuffer containing the specified number of + * banks. Each bank has the specified size and an offset of 0. + * + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + */ + protected DataBuffer(int dataType, int size, int numBanks) { + this(UNTRACKABLE, dataType, size, numBanks); + } + + /** + * Constructs a DataBuffer containing the specified number of + * banks with the indicated initial {@link State State}. + * Each bank has the specified size and an offset of 0. + * + * @param initialState the initial {@link State State} state of the data + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @since 1.7 + */ + DataBuffer(State initialState, + int dataType, int size, int numBanks) + { + this.theTrackable = StateTrackableDelegate.createInstance(initialState); + this.dataType = dataType; + this.banks = numBanks; + this.size = size; + this.offset = 0; + this.offsets = new int[banks]; // init to 0 by new + } + + /** + * Constructs a DataBuffer that contains the specified number + * of banks. Each bank has the specified datatype, size and offset. + * + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @param offset the offset for each bank + */ + protected DataBuffer(int dataType, int size, int numBanks, int offset) { + this(UNTRACKABLE, dataType, size, numBanks, offset); + } + + /** + * Constructs a DataBuffer that contains the specified number + * of banks with the indicated initial {@link State State}. + * Each bank has the specified datatype, size and offset. + * + * @param initialState the initial {@link State State} state of the data + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @param offset the offset for each bank + * @since 1.7 + */ + DataBuffer(State initialState, + int dataType, int size, int numBanks, int offset) + { + this.theTrackable = StateTrackableDelegate.createInstance(initialState); + this.dataType = dataType; + this.banks = numBanks; + this.size = size; + this.offset = offset; + this.offsets = new int[numBanks]; + for (int i = 0; i < numBanks; i++) { + this.offsets[i] = offset; + } + } + + /** + * Constructs a DataBuffer which contains the specified number + * of banks. Each bank has the specified datatype and size. The + * offset for each bank is specified by its respective entry in + * the offsets array. + * + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @param offsets an array containing an offset for each bank. + * @throws ArrayIndexOutOfBoundsException if numBanks + * does not equal the length of offsets + */ + protected DataBuffer(int dataType, int size, int numBanks, int offsets[]) { + this(UNTRACKABLE, dataType, size, numBanks, offsets); + } + + /** + * Constructs a DataBuffer which contains the specified number + * of banks with the indicated initial {@link State State}. + * Each bank has the specified datatype and size. The + * offset for each bank is specified by its respective entry in + * the offsets array. + * + * @param initialState the initial {@link State State} state of the data + * @param dataType the data type of this DataBuffer + * @param size the size of the banks + * @param numBanks the number of banks in this + * DataBuffer + * @param offsets an array containing an offset for each bank. + * @throws ArrayIndexOutOfBoundsException if numBanks + * does not equal the length of offsets + * @since 1.7 + */ + DataBuffer(State initialState, + int dataType, int size, int numBanks, int offsets[]) + { + if (numBanks != offsets.length) { + throw new ArrayIndexOutOfBoundsException("Number of banks" + + " does not match number of bank offsets"); + } + this.theTrackable = StateTrackableDelegate.createInstance(initialState); + this.dataType = dataType; + this.banks = numBanks; + this.size = size; + this.offset = offsets[0]; + this.offsets = (int[])offsets.clone(); + } + + /** Returns the data type of this DataBuffer. + * @return the data type of this DataBuffer. + */ + public int getDataType() { + return dataType; + } + + /** Returns the size (in array elements) of all banks. + * @return the size of all banks. + */ + public int getSize() { + return size; + } + + /** Returns the offset of the default bank in array elements. + * @return the offset of the default bank. + */ + public int getOffset() { + return offset; + } + + /** Returns the offsets (in array elements) of all the banks. + * @return the offsets of all banks. + */ + public int[] getOffsets() { + return (int[])offsets.clone(); + } + + /** Returns the number of banks in this DataBuffer. + * @return the number of banks. + */ + public int getNumBanks() { + return banks; + } + + /** + * Returns the requested data array element from the first (default) bank + * as an integer. + * @param i the index of the requested data array element + * @return the data array element at the specified index. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return getElem(0,i); + } + + /** + * Returns the requested data array element from the specified bank + * as an integer. + * @param bank the specified bank + * @param i the index of the requested data array element + * @return the data array element at the specified index from the + * specified bank at the specified index. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public abstract int getElem(int bank, int i); + + /** + * Sets the requested data array element in the first (default) bank + * from the given integer. + * @param i the specified index into the data array + * @param val the data to set the element at the specified index in + * the data array + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + setElem(0,i,val); + } + + /** + * Sets the requested data array element in the specified bank + * from the given integer. + * @param bank the specified bank + * @param i the specified index into the data array + * @param val the data to set the element in the specified bank + * at the specified index in the data array + * @see #getElem(int) + * @see #getElem(int, int) + */ + public abstract void setElem(int bank, int i, int val); + + /** + * Returns the requested data array element from the first (default) bank + * as a float. The implementation in this class is to cast getElem(i) + * to a float. Subclasses may override this method if another + * implementation is needed. + * @param i the index of the requested data array element + * @return a float value representing the data array element at the + * specified index. + * @see #setElemFloat(int, float) + * @see #setElemFloat(int, int, float) + */ + public float getElemFloat(int i) { + return (float)getElem(i); + } + + /** + * Returns the requested data array element from the specified bank + * as a float. The implementation in this class is to cast + * {@link #getElem(int, int)} + * to a float. Subclasses can override this method if another + * implementation is needed. + * @param bank the specified bank + * @param i the index of the requested data array element + * @return a float value representing the data array element from the + * specified bank at the specified index. + * @see #setElemFloat(int, float) + * @see #setElemFloat(int, int, float) + */ + public float getElemFloat(int bank, int i) { + return (float)getElem(bank,i); + } + + /** + * Sets the requested data array element in the first (default) bank + * from the given float. The implementation in this class is to cast + * val to an int and call {@link #setElem(int, int)}. Subclasses + * can override this method if another implementation is needed. + * @param i the specified index + * @param val the value to set the element at the specified index in + * the data array + * @see #getElemFloat(int) + * @see #getElemFloat(int, int) + */ + public void setElemFloat(int i, float val) { + setElem(i,(int)val); + } + + /** + * Sets the requested data array element in the specified bank + * from the given float. The implementation in this class is to cast + * val to an int and call {@link #setElem(int, int)}. Subclasses can + * override this method if another implementation is needed. + * @param bank the specified bank + * @param i the specified index + * @param val the value to set the element in the specified bank at + * the specified index in the data array + * @see #getElemFloat(int) + * @see #getElemFloat(int, int) + */ + public void setElemFloat(int bank, int i, float val) { + setElem(bank,i,(int)val); + } + + /** + * Returns the requested data array element from the first (default) bank + * as a double. The implementation in this class is to cast + * {@link #getElem(int)} + * to a double. Subclasses can override this method if another + * implementation is needed. + * @param i the specified index + * @return a double value representing the element at the specified + * index in the data array. + * @see #setElemDouble(int, double) + * @see #setElemDouble(int, int, double) + */ + public double getElemDouble(int i) { + return (double)getElem(i); + } + + /** + * Returns the requested data array element from the specified bank as + * a double. The implementation in this class is to cast getElem(bank, i) + * to a double. Subclasses may override this method if another + * implementation is needed. + * @param bank the specified bank + * @param i the specified index + * @return a double value representing the element from the specified + * bank at the specified index in the data array. + * @see #setElemDouble(int, double) + * @see #setElemDouble(int, int, double) + */ + public double getElemDouble(int bank, int i) { + return (double)getElem(bank,i); + } + + /** + * Sets the requested data array element in the first (default) bank + * from the given double. The implementation in this class is to cast + * val to an int and call {@link #setElem(int, int)}. Subclasses can + * override this method if another implementation is needed. + * @param i the specified index + * @param val the value to set the element at the specified index + * in the data array + * @see #getElemDouble(int) + * @see #getElemDouble(int, int) + */ + public void setElemDouble(int i, double val) { + setElem(i,(int)val); + } + + /** + * Sets the requested data array element in the specified bank + * from the given double. The implementation in this class is to cast + * val to an int and call {@link #setElem(int, int)}. Subclasses can + * override this method if another implementation is needed. + * @param bank the specified bank + * @param i the specified index + * @param val the value to set the element in the specified bank + * at the specified index of the data array + * @see #getElemDouble(int) + * @see #getElemDouble(int, int) + */ + public void setElemDouble(int bank, int i, double val) { + setElem(bank,i,(int)val); + } + + static int[] toIntArray(Object obj) { + if (obj instanceof int[]) { + return (int[])obj; + } else if (obj == null) { + return null; + } else if (obj instanceof short[]) { + short sdata[] = (short[])obj; + int idata[] = new int[sdata.length]; + for (int i = 0; i < sdata.length; i++) { + idata[i] = (int)sdata[i] & 0xffff; + } + return idata; + } else if (obj instanceof byte[]) { + byte bdata[] = (byte[])obj; + int idata[] = new int[bdata.length]; + for (int i = 0; i < bdata.length; i++) { + idata[i] = 0xff & (int)bdata[i]; + } + return idata; + } + return null; + } + + static { + SunWritableRaster.setDataStealer(new SunWritableRaster.DataStealer() { + public byte[] getData(DataBufferByte dbb, int bank) { + return dbb.bankdata[bank]; + } + + public short[] getData(DataBufferUShort dbus, int bank) { + return dbus.bankdata[bank]; + } + + public int[] getData(DataBufferInt dbi, int bank) { + return dbi.bankdata[bank]; + } + + public StateTrackableDelegate getTrackable(DataBuffer db) { + return db.theTrackable; + } + }); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/DataBufferByte.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/DataBufferByte.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,286 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally as bytes. + * Values stored in the byte array(s) of this DataBuffer are treated as + * unsigned values. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array, as noted below in the + * documentation for those methods. + * + */ +public final class DataBufferByte extends DataBuffer +{ + /** The default data bank. */ + byte data[]; + + /** All data banks */ + byte bankdata[][]; + + /** + * Constructs a byte-based DataBuffer with a single bank and the + * specified size. + * + * @param size The size of the DataBuffer. + */ + public DataBufferByte(int size) { + super(STABLE, TYPE_BYTE, size); + data = new byte[size]; + bankdata = new byte[1][]; + bankdata[0] = data; + } + + /** + * Constructs a byte based DataBuffer with the specified number of + * banks all of which are the specified size. + * + * @param size The size of the banks in the DataBuffer. + * @param numBanks The number of banks in the aDataBuffer. + */ + public DataBufferByte(int size, int numBanks) { + super(STABLE, TYPE_BYTE, size, numBanks); + bankdata = new byte[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new byte[size]; + } + data = bankdata[0]; + } + + /** + * Constructs a byte-based DataBuffer with a single bank using the + * specified array. + * Only the first size elements should be used by accessors of + * this DataBuffer. dataArray must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The byte array for the DataBuffer. + * @param size The size of the DataBuffer bank. + */ + public DataBufferByte(byte dataArray[], int size) { + super(UNTRACKABLE, TYPE_BYTE, size); + data = dataArray; + bankdata = new byte[1][]; + bankdata[0] = data; + } + + /** + * Constructs a byte-based DataBuffer with a single bank using the + * specified array, size, and offset. dataArray must have at least + * offset + size elements. Only elements offset + * through offset + size - 1 + * should be used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The byte array for the DataBuffer. + * @param size The size of the DataBuffer bank. + * @param offset The offset into the dataArray. dataArray + * must have at least offset + size elements. + */ + public DataBufferByte(byte dataArray[], int size, int offset){ + super(UNTRACKABLE, TYPE_BYTE, size, 1, offset); + data = dataArray; + bankdata = new byte[1][]; + bankdata[0] = data; + } + + /** + * Constructs a byte-based DataBuffer with the specified arrays. + * The number of banks is equal to dataArray.length. + * Only the first size elements of each array should be used by + * accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The byte arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + */ + public DataBufferByte(byte dataArray[][], int size) { + super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length); + bankdata = (byte[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs a byte-based DataBuffer with the specified arrays, size, + * and offsets. + * The number of banks is equal to dataArray.length. Each array must + * be at least as large as size + the corresponding offset. + * There must be an entry in the offset array for each dataArray + * entry. For each bank, only elements offset through + * offset + size - 1 should be used by accessors of this + * DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The byte arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + * @param offsets The offsets into each array. + */ + public DataBufferByte(byte dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_BYTE, size, dataArray.length, offsets); + bankdata = (byte[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) byte data array. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return The first byte data array. + */ + public byte[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank The bank whose data array you want to get. + * @return The data array for the specified bank. + */ + public byte[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data arrays for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return All of the data arrays. + */ + public byte[][] getBankData() { + theTrackable.setUntrackable(); + return (byte[][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first (default) bank. + * + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return (int)(data[i+offset]) & 0xff; + } + + /** + * Returns the requested data array element from the specified bank. + * + * @param bank The bank from which you want to get a data array element. + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return (int)(bankdata[bank][i+offsets[bank]]) & 0xff; + } + + /** + * Sets the requested data array element in the first (default) bank + * to the specified value. + * + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + data[i+offset] = (byte)val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * from the given integer. + * @param bank The bank in which you want to set the data array element. + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the specified data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + bankdata[bank][i+offsets[bank]] = (byte)val; + theTrackable.markDirty(); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/DataBufferInt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/DataBufferInt.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,284 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally + * as integers. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array as noted below in the + * documentation for those methods. + * + */ +public final class DataBufferInt extends DataBuffer +{ + /** The default data bank. */ + int data[]; + + /** All data banks */ + int bankdata[][]; + + /** + * Constructs an integer-based DataBuffer with a single bank + * and the specified size. + * + * @param size The size of the DataBuffer. + */ + public DataBufferInt(int size) { + super(STABLE, TYPE_INT, size); + data = new int[size]; + bankdata = new int[1][]; + bankdata[0] = data; + } + + /** + * Constructs an integer-based DataBuffer with the specified number of + * banks, all of which are the specified size. + * + * @param size The size of the banks in the DataBuffer. + * @param numBanks The number of banks in the aDataBuffer. + */ + public DataBufferInt(int size, int numBanks) { + super(STABLE, TYPE_INT, size, numBanks); + bankdata = new int[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new int[size]; + } + data = bankdata[0]; + } + + /** + * Constructs an integer-based DataBuffer with a single bank using the + * specified array. + * Only the first size elements should be used by accessors of + * this DataBuffer. dataArray must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The integer array for the DataBuffer. + * @param size The size of the DataBuffer bank. + */ + public DataBufferInt(int dataArray[], int size) { + super(UNTRACKABLE, TYPE_INT, size); + data = dataArray; + bankdata = new int[1][]; + bankdata[0] = data; + } + + /** + * Constructs an integer-based DataBuffer with a single bank using the + * specified array, size, and offset. dataArray must have at least + * offset + size elements. Only elements offset + * through offset + size - 1 + * should be used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The integer array for the DataBuffer. + * @param size The size of the DataBuffer bank. + * @param offset The offset into the dataArray. + */ + public DataBufferInt(int dataArray[], int size, int offset) { + super(UNTRACKABLE, TYPE_INT, size, 1, offset); + data = dataArray; + bankdata = new int[1][]; + bankdata[0] = data; + } + + /** + * Constructs an integer-based DataBuffer with the specified arrays. + * The number of banks will be equal to dataArray.length. + * Only the first size elements of each array should be used by + * accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The integer arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + */ + public DataBufferInt(int dataArray[][], int size) { + super(UNTRACKABLE, TYPE_INT, size, dataArray.length); + bankdata = (int [][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs an integer-based DataBuffer with the specified arrays, size, + * and offsets. + * The number of banks is equal to dataArray.length. Each array must + * be at least as large as size + the corresponding offset. There must + * be an entry in the offset array for each dataArray entry. For each + * bank, only elements offset through + * offset + size - 1 should be + * used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The integer arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + * @param offsets The offsets into each array. + */ + public DataBufferInt(int dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_INT, size, dataArray.length, offsets); + bankdata = (int [][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) int data array in DataBuffer. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return The first integer data array. + */ + public int[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank The bank whose data array you want to get. + * @return The data array for the specified bank. + */ + public int[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data arrays for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return All of the data arrays. + */ + public int[][] getBankData() { + theTrackable.setUntrackable(); + return (int [][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first (default) bank. + * + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return data[i+offset]; + } + + /** + * Returns the requested data array element from the specified bank. + * + * @param bank The bank from which you want to get a data array element. + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return bankdata[bank][i+offsets[bank]]; + } + + /** + * Sets the requested data array element in the first (default) bank + * to the specified value. + * + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + data[i+offset] = val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * to the integer value i. + * @param bank The bank in which you want to set the data array element. + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the specified data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + bankdata[bank][i+offsets[bank]] = (int)val; + theTrackable.markDirty(); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/DataBufferShort.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/DataBufferShort.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,283 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally as shorts. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array as noted below in the + * documentation for those methods. + * + */ +public final class DataBufferShort extends DataBuffer +{ + /** The default data bank. */ + short data[]; + + /** All data banks */ + short bankdata[][]; + + /** + * Constructs a short-based DataBuffer with a single bank and the + * specified size. + * + * @param size The size of the DataBuffer. + */ + public DataBufferShort(int size) { + super(STABLE, TYPE_SHORT,size); + data = new short[size]; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs a short-based DataBuffer with the specified number of + * banks all of which are the specified size. + * + * @param size The size of the banks in the DataBuffer. + * @param numBanks The number of banks in the aDataBuffer. + */ + public DataBufferShort(int size, int numBanks) { + super(STABLE, TYPE_SHORT,size,numBanks); + bankdata = new short[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new short[size]; + } + data = bankdata[0]; + } + + /** + * Constructs a short-based DataBuffer with a single bank using the + * specified array. + * Only the first size elements should be used by accessors of + * this DataBuffer. dataArray must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The short array for the DataBuffer. + * @param size The size of the DataBuffer bank. + */ + public DataBufferShort(short dataArray[], int size) { + super(UNTRACKABLE, TYPE_SHORT, size); + data = dataArray; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs a short-based DataBuffer with a single bank using the + * specified array, size, and offset. dataArray must have at least + * offset + size elements. Only elements offset + * through offset + size - 1 + * should be used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The short array for the DataBuffer. + * @param size The size of the DataBuffer bank. + * @param offset The offset into the dataArray. + */ + public DataBufferShort(short dataArray[], int size, int offset) { + super(UNTRACKABLE, TYPE_SHORT, size, 1, offset); + data = dataArray; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs a short-based DataBuffer with the specified arrays. + * The number of banks will be equal to dataArray.length. + * Only the first size elements of each array should be used by + * accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The short arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + */ + public DataBufferShort(short dataArray[][], int size) { + super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length); + bankdata = (short[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs a short-based DataBuffer with the specified arrays, size, + * and offsets. + * The number of banks is equal to dataArray.length. Each array must + * be at least as large as size + the corresponding offset. There must + * be an entry in the offset array for each dataArray entry. For each + * bank, only elements offset through + * offset + size - 1 should be + * used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The short arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + * @param offsets The offsets into each array. + */ + public DataBufferShort(short dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_SHORT, size, dataArray.length, offsets); + bankdata = (short[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) byte data array. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return The first short data array. + */ + public short[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank The bank whose data array you want to get. + * @return The data array for the specified bank. + */ + public short[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data arrays for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return All of the data arrays. + */ + public short[][] getBankData() { + theTrackable.setUntrackable(); + return (short[][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first (default) bank. + * + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return (int)(data[i+offset]); + } + + /** + * Returns the requested data array element from the specified bank. + * + * @param bank The bank from which you want to get a data array element. + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return (int)(bankdata[bank][i+offsets[bank]]); + } + + /** + * Sets the requested data array element in the first (default) bank + * to the specified value. + * + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + data[i+offset] = (short)val; + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * from the given integer. + * @param bank The bank in which you want to set the data array element. + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the specified data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + bankdata[bank][i+offsets[bank]] = (short)val; + theTrackable.markDirty(); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/DataBufferUShort.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/DataBufferUShort.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,318 @@ +/* + * Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import static sun.java2d.StateTrackable.State.*; + +/** + * This class extends DataBuffer and stores data internally as + * shorts. Values stored in the short array(s) of this DataBuffer + * are treated as unsigned values. + *

+ * + * Note that some implementations may function more efficiently + * if they can maintain control over how the data for an image is + * stored. + * For example, optimizations such as caching an image in video + * memory require that the implementation track all modifications + * to that data. + * Other implementations may operate better if they can store the + * data in locations other than a Java array. + * To maintain optimum compatibility with various optimizations + * it is best to avoid constructors and methods which expose the + * underlying storage as a Java array as noted below in the + * documentation for those methods. + * + */ +public final class DataBufferUShort extends DataBuffer +{ + /** The default data bank. */ + short data[]; + + /** All data banks */ + short bankdata[][]; + + /** + * Constructs an unsigned-short based DataBuffer with a single bank and the + * specified size. + * + * @param size The size of the DataBuffer. + */ + public DataBufferUShort(int size) { + super(STABLE, TYPE_USHORT, size); + data = new short[size]; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs an unsigned-short based DataBuffer with the specified number of + * banks, all of which are the specified size. + * + * @param size The size of the banks in the DataBuffer. + * @param numBanks The number of banks in the aDataBuffer. + */ + public DataBufferUShort(int size, int numBanks) { + super(STABLE, TYPE_USHORT, size, numBanks); + bankdata = new short[numBanks][]; + for (int i= 0; i < numBanks; i++) { + bankdata[i] = new short[size]; + } + data = bankdata[0]; + } + + /** + * Constructs an unsigned-short based DataBuffer with a single bank + * using the specified array. + * Only the first size elements should be used by accessors of + * this DataBuffer. dataArray must be large enough to + * hold size elements. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The unsigned-short array for the DataBuffer. + * @param size The size of the DataBuffer bank. + */ + public DataBufferUShort(short dataArray[], int size) { + super(UNTRACKABLE, TYPE_USHORT, size); + if (dataArray == null) { + throw new NullPointerException("dataArray is null"); + } + data = dataArray; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs an unsigned-short based DataBuffer with a single bank + * using the specified array, size, and offset. dataArray must have at + * least offset + size elements. Only elements + * offset through offset + size - 1 should + * be used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The unsigned-short array for the DataBuffer. + * @param size The size of the DataBuffer bank. + * @param offset The offset into the dataArray. + */ + public DataBufferUShort(short dataArray[], int size, int offset) { + super(UNTRACKABLE, TYPE_USHORT, size, 1, offset); + if (dataArray == null) { + throw new NullPointerException("dataArray is null"); + } + if ((size+offset) > dataArray.length) { + throw new IllegalArgumentException("Length of dataArray is less "+ + " than size+offset."); + } + data = dataArray; + bankdata = new short[1][]; + bankdata[0] = data; + } + + /** + * Constructs an unsigned-short based DataBuffer with the specified arrays. + * The number of banks will be equal to dataArray.length. + * Only the first size elements of each array should be used by + * accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The unsigned-short arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + */ + public DataBufferUShort(short dataArray[][], int size) { + super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length); + if (dataArray == null) { + throw new NullPointerException("dataArray is null"); + } + for (int i=0; i < dataArray.length; i++) { + if (dataArray[i] == null) { + throw new NullPointerException("dataArray["+i+"] is null"); + } + } + + bankdata = (short[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Constructs an unsigned-short based DataBuffer with specified arrays, + * size, and offsets. + * The number of banks is equal to dataArray.length. Each array must + * be at least as large as size + the corresponding offset. There must + * be an entry in the offset array for each dataArray entry. For each + * bank, only elements offset through + * offset + size - 1 should be + * used by accessors of this DataBuffer. + *

+ * Note that {@code DataBuffer} objects created by this constructor + * may be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param dataArray The unsigned-short arrays for the DataBuffer. + * @param size The size of the banks in the DataBuffer. + * @param offsets The offsets into each array. + */ + public DataBufferUShort(short dataArray[][], int size, int offsets[]) { + super(UNTRACKABLE, TYPE_USHORT, size, dataArray.length, offsets); + if (dataArray == null) { + throw new NullPointerException("dataArray is null"); + } + for (int i=0; i < dataArray.length; i++) { + if (dataArray[i] == null) { + throw new NullPointerException("dataArray["+i+"] is null"); + } + if ((size+offsets[i]) > dataArray[i].length) { + throw new IllegalArgumentException("Length of dataArray["+i+ + "] is less than size+"+ + "offsets["+i+"]."); + } + + } + bankdata = (short[][]) dataArray.clone(); + data = bankdata[0]; + } + + /** + * Returns the default (first) unsigned-short data array. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return The first unsigned-short data array. + */ + public short[] getData() { + theTrackable.setUntrackable(); + return data; + } + + /** + * Returns the data array for the specified bank. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @param bank The bank whose data array you want to get. + * @return The data array for the specified bank. + */ + public short[] getData(int bank) { + theTrackable.setUntrackable(); + return bankdata[bank]; + } + + /** + * Returns the data arrays for all banks. + *

+ * Note that calling this method may cause this {@code DataBuffer} + * object to be incompatible with performance + * optimizations used by some implementations (such as caching + * an associated image in video memory). + * + * @return All of the data arrays. + */ + public short[][] getBankData() { + theTrackable.setUntrackable(); + return (short[][]) bankdata.clone(); + } + + /** + * Returns the requested data array element from the first (default) bank. + * + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int i) { + return (int)(data[i+offset]&0xffff); + } + + /** + * Returns the requested data array element from the specified bank. + * + * @param bank The bank from which you want to get a data array element. + * @param i The data array element you want to get. + * @return The requested data array element as an integer. + * @see #setElem(int, int) + * @see #setElem(int, int, int) + */ + public int getElem(int bank, int i) { + return (int)(bankdata[bank][i+offsets[bank]]&0xffff); + } + + /** + * Sets the requested data array element in the first (default) bank + * to the specified value. + * + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int i, int val) { + data[i+offset] = (short)(val&0xffff); + theTrackable.markDirty(); + } + + /** + * Sets the requested data array element in the specified bank + * from the given integer. + * @param bank The bank in which you want to set the data array element. + * @param i The data array element you want to set. + * @param val The integer value to which you want to set the specified data array element. + * @see #getElem(int) + * @see #getElem(int, int) + */ + public void setElem(int bank, int i, int val) { + bankdata[bank][i+offsets[bank]] = (short)(val&0xffff); + theTrackable.markDirty(); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/MultiPixelPackedSampleModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/MultiPixelPackedSampleModel.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,699 @@ +/* + * Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +/** + * The MultiPixelPackedSampleModel class represents + * one-banded images and can pack multiple one-sample + * pixels into one data element. Pixels are not allowed to span data elements. + * The data type can be DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, + * or DataBuffer.TYPE_INT. Each pixel must be a power of 2 number of bits + * and a power of 2 number of pixels must fit exactly in one data element. + * Pixel bit stride is equal to the number of bits per pixel. Scanline + * stride is in data elements and the last several data elements might be + * padded with unused pixels. Data bit offset is the offset in bits from + * the beginning of the {@link DataBuffer} to the first pixel and must be + * a multiple of pixel bit stride. + *

+ * The following code illustrates extracting the bits for pixel + * x, y from DataBuffer data + * and storing the pixel data in data elements of type + * dataType: + *

+ *      int dataElementSize = DataBuffer.getDataTypeSize(dataType);
+ *      int bitnum = dataBitOffset + x*pixelBitStride;
+ *      int element = data.getElem(y*scanlineStride + bitnum/dataElementSize);
+ *      int shift = dataElementSize - (bitnum & (dataElementSize-1))
+ *                  - pixelBitStride;
+ *      int pixel = (element >> shift) & ((1 << pixelBitStride) - 1);
+ * 
+ */ + +public class MultiPixelPackedSampleModel extends SampleModel +{ + /** The number of bits from one pixel to the next. */ + int pixelBitStride; + + /** Bitmask that extracts the rightmost pixel of a data element. */ + int bitMask; + + /** + * The number of pixels that fit in a data element. Also used + * as the number of bits per pixel. + */ + int pixelsPerDataElement; + + /** The size of a data element in bits. */ + int dataElementSize; + + /** The bit offset into the data array where the first pixel begins. + */ + int dataBitOffset; + + /** ScanlineStride of the data buffer described in data array elements. */ + int scanlineStride; + + /** + * Constructs a MultiPixelPackedSampleModel with the + * specified data type, width, height and number of bits per pixel. + * @param dataType the data type for storing samples + * @param w the width, in pixels, of the region of + * image data described + * @param h the height, in pixels, of the region of + * image data described + * @param numberOfBits the number of bits per pixel + * @throws IllegalArgumentException if dataType is not + * either DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, or + * DataBuffer.TYPE_INT + */ + public MultiPixelPackedSampleModel(int dataType, + int w, + int h, + int numberOfBits) { + this(dataType,w,h, + numberOfBits, + (w*numberOfBits+DataBuffer.getDataTypeSize(dataType)-1)/ + DataBuffer.getDataTypeSize(dataType), + 0); + if (dataType != DataBuffer.TYPE_BYTE && + dataType != DataBuffer.TYPE_USHORT && + dataType != DataBuffer.TYPE_INT) { + throw new IllegalArgumentException("Unsupported data type "+ + dataType); + } + } + + /** + * Constructs a MultiPixelPackedSampleModel with + * specified data type, width, height, number of bits per pixel, + * scanline stride and data bit offset. + * @param dataType the data type for storing samples + * @param w the width, in pixels, of the region of + * image data described + * @param h the height, in pixels, of the region of + * image data described + * @param numberOfBits the number of bits per pixel + * @param scanlineStride the line stride of the image data + * @param dataBitOffset the data bit offset for the region of image + * data described + * @exception RasterFormatException if the number of bits per pixel + * is not a power of 2 or if a power of 2 number of + * pixels do not fit in one data element. + * @throws IllegalArgumentException if w or + * h is not greater than 0 + * @throws IllegalArgumentException if dataType is not + * either DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, or + * DataBuffer.TYPE_INT + */ + public MultiPixelPackedSampleModel(int dataType, int w, int h, + int numberOfBits, + int scanlineStride, + int dataBitOffset) { + super(dataType, w, h, 1); + if (dataType != DataBuffer.TYPE_BYTE && + dataType != DataBuffer.TYPE_USHORT && + dataType != DataBuffer.TYPE_INT) { + throw new IllegalArgumentException("Unsupported data type "+ + dataType); + } + this.dataType = dataType; + this.pixelBitStride = numberOfBits; + this.scanlineStride = scanlineStride; + this.dataBitOffset = dataBitOffset; + this.dataElementSize = DataBuffer.getDataTypeSize(dataType); + this.pixelsPerDataElement = dataElementSize/numberOfBits; + if (pixelsPerDataElement*numberOfBits != dataElementSize) { + throw new RasterFormatException("MultiPixelPackedSampleModel " + + "does not allow pixels to " + + "span data element boundaries"); + } + this.bitMask = (1 << numberOfBits) - 1; + } + + + /** + * Creates a new MultiPixelPackedSampleModel with the + * specified width and height. The new + * MultiPixelPackedSampleModel has the + * same storage data type and number of bits per pixel as this + * MultiPixelPackedSampleModel. + * @param w the specified width + * @param h the specified height + * @return a {@link SampleModel} with the specified width and height + * and with the same storage data type and number of bits per pixel + * as this MultiPixelPackedSampleModel. + * @throws IllegalArgumentException if w or + * h is not greater than 0 + */ + public SampleModel createCompatibleSampleModel(int w, int h) { + SampleModel sampleModel = + new MultiPixelPackedSampleModel(dataType, w, h, pixelBitStride); + return sampleModel; + } + + /** + * Creates a DataBuffer that corresponds to this + * MultiPixelPackedSampleModel. The + * DataBuffer object's data type and size + * is consistent with this MultiPixelPackedSampleModel. + * The DataBuffer has a single bank. + * @return a DataBuffer with the same data type and + * size as this MultiPixelPackedSampleModel. + */ + public DataBuffer createDataBuffer() { + DataBuffer dataBuffer = null; + + int size = (int)scanlineStride*height; + switch (dataType) { + case DataBuffer.TYPE_BYTE: + dataBuffer = new DataBufferByte(size+(dataBitOffset+7)/8); + break; + case DataBuffer.TYPE_USHORT: + dataBuffer = new DataBufferUShort(size+(dataBitOffset+15)/16); + break; + case DataBuffer.TYPE_INT: + dataBuffer = new DataBufferInt(size+(dataBitOffset+31)/32); + break; + } + return dataBuffer; + } + + /** + * Returns the number of data elements needed to transfer one pixel + * via the {@link #getDataElements} and {@link #setDataElements} + * methods. For a MultiPixelPackedSampleModel, this is + * one. + * @return the number of data elements. + */ + public int getNumDataElements() { + return 1; + } + + /** + * Returns the number of bits per sample for all bands. + * @return the number of bits per sample. + */ + public int[] getSampleSize() { + int sampleSize[] = {pixelBitStride}; + return sampleSize; + } + + /** + * Returns the number of bits per sample for the specified band. + * @param band the specified band + * @return the number of bits per sample for the specified band. + */ + public int getSampleSize(int band) { + return pixelBitStride; + } + + /** + * Returns the offset of pixel (x, y) in data array elements. + * @param x the X coordinate of the specified pixel + * @param y the Y coordinate of the specified pixel + * @return the offset of the specified pixel. + */ + public int getOffset(int x, int y) { + int offset = y * scanlineStride; + offset += (x*pixelBitStride+dataBitOffset)/dataElementSize; + return offset; + } + + /** + * Returns the offset, in bits, into the data element in which it is + * stored for the xth pixel of a scanline. + * This offset is the same for all scanlines. + * @param x the specified pixel + * @return the bit offset of the specified pixel. + */ + public int getBitOffset(int x){ + return (x*pixelBitStride+dataBitOffset)%dataElementSize; + } + + /** + * Returns the scanline stride. + * @return the scanline stride of this + * MultiPixelPackedSampleModel. + */ + public int getScanlineStride() { + return scanlineStride; + } + + /** + * Returns the pixel bit stride in bits. This value is the same as + * the number of bits per pixel. + * @return the pixelBitStride of this + * MultiPixelPackedSampleModel. + */ + public int getPixelBitStride() { + return pixelBitStride; + } + + /** + * Returns the data bit offset in bits. + * @return the dataBitOffset of this + * MultiPixelPackedSampleModel. + */ + public int getDataBitOffset() { + return dataBitOffset; + } + + /** + * Returns the TransferType used to transfer pixels by way of the + * getDataElements and setDataElements + * methods. The TransferType might or might not be the same as the + * storage DataType. The TransferType is one of + * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, + * or DataBuffer.TYPE_INT. + * @return the transfertype. + */ + public int getTransferType() { + if (pixelBitStride > 16) + return DataBuffer.TYPE_INT; + else if (pixelBitStride > 8) + return DataBuffer.TYPE_USHORT; + else + return DataBuffer.TYPE_BYTE; + } + + /** + * Creates a new MultiPixelPackedSampleModel with a + * subset of the bands of this + * MultiPixelPackedSampleModel. Since a + * MultiPixelPackedSampleModel only has one band, the + * bands argument must have a length of one and indicate the zeroth + * band. + * @param bands the specified bands + * @return a new SampleModel with a subset of bands of + * this MultiPixelPackedSampleModel. + * @exception RasterFormatException if the number of bands requested + * is not one. + * @throws IllegalArgumentException if w or + * h is not greater than 0 + */ + public SampleModel createSubsetSampleModel(int bands[]) { + if (bands != null) { + if (bands.length != 1) + throw new RasterFormatException("MultiPixelPackedSampleModel has " + + "only one band."); + } + SampleModel sm = createCompatibleSampleModel(width, height); + return sm; + } + + /** + * Returns as int the sample in a specified band for the + * pixel located at (x, y). An + * ArrayIndexOutOfBoundsException is thrown if the + * coordinates are not in bounds. + * @param x the X coordinate of the specified pixel + * @param y the Y coordinate of the specified pixel + * @param b the band to return, which is assumed to be 0 + * @param data the DataBuffer containing the image + * data + * @return the specified band containing the sample of the specified + * pixel. + * @exception ArrayIndexOutOfBoundException if the specified + * coordinates are not in bounds. + * @see #setSample(int, int, int, int, DataBuffer) + */ + public int getSample(int x, int y, int b, DataBuffer data) { + // 'b' must be 0 + if ((x < 0) || (y < 0) || (x >= width) || (y >= height) || + (b != 0)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int bitnum = dataBitOffset + x*pixelBitStride; + int element = data.getElem(y*scanlineStride + bitnum/dataElementSize); + int shift = dataElementSize - (bitnum & (dataElementSize-1)) + - pixelBitStride; + return (element >> shift) & bitMask; + } + + /** + * Sets a sample in the specified band for the pixel located at + * (x, y) in the DataBuffer using an + * int for input. + * An ArrayIndexOutOfBoundsException is thrown if the + * coordinates are not in bounds. + * @param x the X coordinate of the specified pixel + * @param y the Y coordinate of the specified pixel + * @param b the band to return, which is assumed to be 0 + * @param s the input sample as an int + * @param data the DataBuffer where image data is stored + * @exception ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds. + * @see #getSample(int, int, int, DataBuffer) + */ + public void setSample(int x, int y, int b, int s, + DataBuffer data) { + // 'b' must be 0 + if ((x < 0) || (y < 0) || (x >= width) || (y >= height) || + (b != 0)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int bitnum = dataBitOffset + x * pixelBitStride; + int index = y * scanlineStride + (bitnum / dataElementSize); + int shift = dataElementSize - (bitnum & (dataElementSize-1)) + - pixelBitStride; + int element = data.getElem(index); + element &= ~(bitMask << shift); + element |= (s & bitMask) << shift; + data.setElem(index,element); + } + + /** + * Returns data for a single pixel in a primitive array of type + * TransferType. For a MultiPixelPackedSampleModel, + * the array has one element, and the type is the smallest of + * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT + * that can hold a single pixel. Generally, obj + * should be passed in as null, so that the + * Object is created automatically and is the + * correct primitive data type. + *

+ * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is + * described by MultiPixelPackedSampleModel + * mppsm1, to DataBuffer db2, + * whose storage layout is described by + * MultiPixelPackedSampleModel mppsm2. + * The transfer is generally more efficient than using + * getPixel or setPixel. + *

+     *       MultiPixelPackedSampleModel mppsm1, mppsm2;
+     *       DataBufferInt db1, db2;
+     *       mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
+     *                              db1), db2);
+     * 
+ * Using getDataElements or setDataElements + * to transfer between two DataBuffer/SampleModel pairs + * is legitimate if the SampleModels have the same number + * of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * If obj is not null, it should be a + * primitive array of type TransferType. Otherwise, a + * ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException is thrown if the + * coordinates are not in bounds, or if obj is not + * null and is not large enough to hold the pixel data. + * @param x the X coordinate of the specified pixel + * @param y the Y coordinate of the specified pixel + * @param obj a primitive array in which to return the pixel data or + * null. + * @param data the DataBuffer containing the image data. + * @return an Object containing data for the specified + * pixel. + * @exception ClassCastException if obj is not a + * primitive array of type TransferType or is not null + * @exception ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds, or if obj is not null or + * not large enough to hold the pixel data + * @see #setDataElements(int, int, Object, DataBuffer) + */ + public Object getDataElements(int x, int y, Object obj, DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int type = getTransferType(); + int bitnum = dataBitOffset + x*pixelBitStride; + int shift = dataElementSize - (bitnum & (dataElementSize-1)) + - pixelBitStride; + int element = 0; + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] bdata; + + if (obj == null) + bdata = new byte[1]; + else + bdata = (byte[])obj; + + element = data.getElem(y*scanlineStride + + bitnum/dataElementSize); + bdata[0] = (byte)((element >> shift) & bitMask); + + obj = (Object)bdata; + break; + + case DataBuffer.TYPE_USHORT: + + short[] sdata; + + if (obj == null) + sdata = new short[1]; + else + sdata = (short[])obj; + + element = data.getElem(y*scanlineStride + + bitnum/dataElementSize); + sdata[0] = (short)((element >> shift) & bitMask); + + obj = (Object)sdata; + break; + + case DataBuffer.TYPE_INT: + + int[] idata; + + if (obj == null) + idata = new int[1]; + else + idata = (int[])obj; + + element = data.getElem(y*scanlineStride + + bitnum/dataElementSize); + idata[0] = (element >> shift) & bitMask; + + obj = (Object)idata; + break; + } + + return obj; + } + + /** + * Returns the specified single band pixel in the first element + * of an int array. + * ArrayIndexOutOfBoundsException is thrown if the + * coordinates are not in bounds. + * @param x the X coordinate of the specified pixel + * @param y the Y coordinate of the specified pixel + * @param iArray the array containing the pixel to be returned or + * null + * @param data the DataBuffer where image data is stored + * @return an array containing the specified pixel. + * @exception ArrayIndexOutOfBoundsException if the coordinates + * are not in bounds + * @see #setPixel(int, int, int[], DataBuffer) + */ + public int[] getPixel(int x, int y, int iArray[], DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int pixels[]; + if (iArray != null) { + pixels = iArray; + } else { + pixels = new int [numBands]; + } + int bitnum = dataBitOffset + x*pixelBitStride; + int element = data.getElem(y*scanlineStride + bitnum/dataElementSize); + int shift = dataElementSize - (bitnum & (dataElementSize-1)) + - pixelBitStride; + pixels[0] = (element >> shift) & bitMask; + return pixels; + } + + /** + * Sets the data for a single pixel in the specified + * DataBuffer from a primitive array of type + * TransferType. For a MultiPixelPackedSampleModel, + * only the first element of the array holds valid data, + * and the type must be the smallest of + * DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, or DataBuffer.TYPE_INT + * that can hold a single pixel. + *

+ * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is + * described by MultiPixelPackedSampleModel + * mppsm1, to DataBuffer db2, + * whose storage layout is described by + * MultiPixelPackedSampleModel mppsm2. + * The transfer is generally more efficient than using + * getPixel or setPixel. + *

+     *       MultiPixelPackedSampleModel mppsm1, mppsm2;
+     *       DataBufferInt db1, db2;
+     *       mppsm2.setDataElements(x, y, mppsm1.getDataElements(x, y, null,
+     *                              db1), db2);
+     * 
+ * Using getDataElements or setDataElements to + * transfer between two DataBuffer/SampleModel pairs is + * legitimate if the SampleModel objects have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * obj must be a primitive array of type TransferType. + * Otherwise, a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException is thrown if the + * coordinates are not in bounds, or if obj is not large + * enough to hold the pixel data. + * @param x the X coordinate of the pixel location + * @param y the Y coordinate of the pixel location + * @param obj a primitive array containing pixel data + * @param data the DataBuffer containing the image data + * @see #getDataElements(int, int, Object, DataBuffer) + */ + public void setDataElements(int x, int y, Object obj, DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int type = getTransferType(); + int bitnum = dataBitOffset + x * pixelBitStride; + int index = y * scanlineStride + (bitnum / dataElementSize); + int shift = dataElementSize - (bitnum & (dataElementSize-1)) + - pixelBitStride; + int element = data.getElem(index); + element &= ~(bitMask << shift); + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] barray = (byte[])obj; + element |= ( ((int)(barray[0])&0xff) & bitMask) << shift; + data.setElem(index, element); + break; + + case DataBuffer.TYPE_USHORT: + + short[] sarray = (short[])obj; + element |= ( ((int)(sarray[0])&0xffff) & bitMask) << shift; + data.setElem(index, element); + break; + + case DataBuffer.TYPE_INT: + + int[] iarray = (int[])obj; + element |= (iarray[0] & bitMask) << shift; + data.setElem(index, element); + break; + } + } + + /** + * Sets a pixel in the DataBuffer using an + * int array for input. + * ArrayIndexOutOfBoundsException is thrown if + * the coordinates are not in bounds. + * @param x the X coordinate of the pixel location + * @param y the Y coordinate of the pixel location + * @param iArray the input pixel in an int array + * @param data the DataBuffer containing the image data + * @see #getPixel(int, int, int[], DataBuffer) + */ + public void setPixel(int x, int y, int[] iArray, DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int bitnum = dataBitOffset + x * pixelBitStride; + int index = y * scanlineStride + (bitnum / dataElementSize); + int shift = dataElementSize - (bitnum & (dataElementSize-1)) + - pixelBitStride; + int element = data.getElem(index); + element &= ~(bitMask << shift); + element |= (iArray[0] & bitMask) << shift; + data.setElem(index,element); + } + + public boolean equals(Object o) { + if ((o == null) || !(o instanceof MultiPixelPackedSampleModel)) { + return false; + } + + MultiPixelPackedSampleModel that = (MultiPixelPackedSampleModel)o; + return this.width == that.width && + this.height == that.height && + this.numBands == that.numBands && + this.dataType == that.dataType && + this.pixelBitStride == that.pixelBitStride && + this.bitMask == that.bitMask && + this.pixelsPerDataElement == that.pixelsPerDataElement && + this.dataElementSize == that.dataElementSize && + this.dataBitOffset == that.dataBitOffset && + this.scanlineStride == that.scanlineStride; + } + + // If we implement equals() we must also implement hashCode + public int hashCode() { + int hash = 0; + hash = width; + hash <<= 8; + hash ^= height; + hash <<= 8; + hash ^= numBands; + hash <<= 8; + hash ^= dataType; + hash <<= 8; + hash ^= pixelBitStride; + hash <<= 8; + hash ^= bitMask; + hash <<= 8; + hash ^= pixelsPerDataElement; + hash <<= 8; + hash ^= dataElementSize; + hash <<= 8; + hash ^= dataBitOffset; + hash <<= 8; + hash ^= scanlineStride; + return hash; + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/Raster.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/Raster.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,1777 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + + +package java.awt.image; +import java.awt.Rectangle; +import java.awt.Point; + +import sun.awt.image.ByteInterleavedRaster; +import sun.awt.image.ShortInterleavedRaster; +import sun.awt.image.IntegerInterleavedRaster; +import sun.awt.image.ByteBandedRaster; +import sun.awt.image.ShortBandedRaster; +import sun.awt.image.BytePackedRaster; +import sun.awt.image.SunWritableRaster; + +/** + * A class representing a rectangular array of pixels. A Raster + * encapsulates a DataBuffer that stores the sample values and a + * SampleModel that describes how to locate a given sample value in a + * DataBuffer. + *

+ * A Raster defines values for pixels occupying a particular + * rectangular area of the plane, not necessarily including (0, 0). + * The rectangle, known as the Raster's bounding rectangle and + * available by means of the getBounds method, is defined by minX, + * minY, width, and height values. The minX and minY values define + * the coordinate of the upper left corner of the Raster. References + * to pixels outside of the bounding rectangle may result in an + * exception being thrown, or may result in references to unintended + * elements of the Raster's associated DataBuffer. It is the user's + * responsibility to avoid accessing such pixels. + *

+ * A SampleModel describes how samples of a Raster + * are stored in the primitive array elements of a DataBuffer. + * Samples may be stored one per data element, as in a + * PixelInterleavedSampleModel or BandedSampleModel, or packed several to + * an element, as in a SinglePixelPackedSampleModel or + * MultiPixelPackedSampleModel. The SampleModel is also + * controls whether samples are sign extended, allowing unsigned + * data to be stored in signed Java data types such as byte, short, and + * int. + *

+ * Although a Raster may live anywhere in the plane, a SampleModel + * makes use of a simple coordinate system that starts at (0, 0). A + * Raster therefore contains a translation factor that allows pixel + * locations to be mapped between the Raster's coordinate system and + * that of the SampleModel. The translation from the SampleModel + * coordinate system to that of the Raster may be obtained by the + * getSampleModelTranslateX and getSampleModelTranslateY methods. + *

+ * A Raster may share a DataBuffer with another Raster either by + * explicit construction or by the use of the createChild and + * createTranslatedChild methods. Rasters created by these methods + * can return a reference to the Raster they were created from by + * means of the getParent method. For a Raster that was not + * constructed by means of a call to createTranslatedChild or + * createChild, getParent will return null. + *

+ * The createTranslatedChild method returns a new Raster that + * shares all of the data of the current Raster, but occupies a + * bounding rectangle of the same width and height but with a + * different starting point. For example, if the parent Raster + * occupied the region (10, 10) to (100, 100), and the translated + * Raster was defined to start at (50, 50), then pixel (20, 20) of the + * parent and pixel (60, 60) of the child occupy the same location in + * the DataBuffer shared by the two Rasters. In the first case, (-10, + * -10) should be added to a pixel coordinate to obtain the + * corresponding SampleModel coordinate, and in the second case (-50, + * -50) should be added. + *

+ * The translation between a parent and child Raster may be + * determined by subtracting the child's sampleModelTranslateX and + * sampleModelTranslateY values from those of the parent. + *

+ * The createChild method may be used to create a new Raster + * occupying only a subset of its parent's bounding rectangle + * (with the same or a translated coordinate system) or + * with a subset of the bands of its parent. + *

+ * All constructors are protected. The correct way to create a + * Raster is to use one of the static create methods defined in this + * class. These methods create instances of Raster that use the + * standard Interleaved, Banded, and Packed SampleModels and that may + * be processed more efficiently than a Raster created by combining + * an externally generated SampleModel and DataBuffer. + * @see java.awt.image.DataBuffer + * @see java.awt.image.SampleModel + * @see java.awt.image.PixelInterleavedSampleModel + * @see java.awt.image.BandedSampleModel + * @see java.awt.image.SinglePixelPackedSampleModel + * @see java.awt.image.MultiPixelPackedSampleModel + */ +public class Raster { + + /** + * The SampleModel that describes how pixels from this Raster + * are stored in the DataBuffer. + */ + protected SampleModel sampleModel; + + /** The DataBuffer that stores the image data. */ + protected DataBuffer dataBuffer; + + /** The X coordinate of the upper-left pixel of this Raster. */ + protected int minX; + + /** The Y coordinate of the upper-left pixel of this Raster. */ + protected int minY; + + /** The width of this Raster. */ + protected int width; + + /** The height of this Raster. */ + protected int height; + + /** + * The X translation from the coordinate space of the + * Raster's SampleModel to that of the Raster. + */ + protected int sampleModelTranslateX; + + /** + * The Y translation from the coordinate space of the + * Raster's SampleModel to that of the Raster. + */ + protected int sampleModelTranslateY; + + /** The number of bands in the Raster. */ + protected int numBands; + + /** The number of DataBuffer data elements per pixel. */ + protected int numDataElements; + + /** The parent of this Raster, or null. */ + protected Raster parent; + + static private native void initIDs(); + static { + ColorModel.loadLibraries(); + initIDs(); + } + + /** + * Creates a Raster based on a PixelInterleavedSampleModel with the + * specified data type, width, height, and number of bands. + * + *

The upper left corner of the Raster is given by the + * location argument. If location is null, (0, 0) will be used. + * The dataType parameter should be one of the enumerated values + * defined in the DataBuffer class. + * + *

Note that interleaved DataBuffer.TYPE_INT + * Rasters are not supported. To create a 1-band Raster of type + * DataBuffer.TYPE_INT, use + * Raster.createPackedRaster(). + *

The only dataTypes supported currently are TYPE_BYTE + * and TYPE_USHORT. + * @param dataType the data type for storing samples + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param bands the number of bands + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified data type, + * width, height and number of bands. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + */ + public static WritableRaster createInterleavedRaster(int dataType, + int w, int h, + int bands, + Point location) { + int[] bandOffsets = new int[bands]; + for (int i = 0; i < bands; i++) { + bandOffsets[i] = i; + } + return createInterleavedRaster(dataType, w, h, w*bands, bands, + bandOffsets, location); + } + + /** + * Creates a Raster based on a PixelInterleavedSampleModel with the + * specified data type, width, height, scanline stride, pixel + * stride, and band offsets. The number of bands is inferred from + * bandOffsets.length. + * + *

The upper left corner of the Raster is given by the + * location argument. If location is null, (0, 0) will be used. + * The dataType parameter should be one of the enumerated values + * defined in the DataBuffer class. + * + *

Note that interleaved DataBuffer.TYPE_INT + * Rasters are not supported. To create a 1-band Raster of type + * DataBuffer.TYPE_INT, use + * Raster.createPackedRaster(). + *

The only dataTypes supported currently are TYPE_BYTE + * and TYPE_USHORT. + * @param dataType the data type for storing samples + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param scanlineStride the line stride of the image data + * @param pixelStride the pixel stride of the image data + * @param bandOffsets the offsets of all bands + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified data type, + * width, height, scanline stride, pixel stride and band + * offsets. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws IllegalArgumentException if dataType is not + * one of the supported data types, which are + * DataBuffer.TYPE_BYTE, or + * DataBuffer.TYPE_USHORT. + */ + public static WritableRaster createInterleavedRaster(int dataType, + int w, int h, + int scanlineStride, + int pixelStride, + int bandOffsets[], + Point location) { + DataBuffer d; + int bands = bandOffsets.length; + + int maxBandOff = bandOffsets[0]; + for (int i=1; i < bands; i++) { + if (bandOffsets[i] > maxBandOff) { + maxBandOff = bandOffsets[i]; + } + } + int size = maxBandOff + scanlineStride*(h-1) + pixelStride*(w-1) + 1; + switch(dataType) { + case DataBuffer.TYPE_BYTE: + d = new DataBufferByte(size); + break; + + case DataBuffer.TYPE_USHORT: + d = new DataBufferUShort(size); + break; + + default: + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + + return createInterleavedRaster(d, w, h, scanlineStride, + pixelStride, bandOffsets, location); + } + + /** + * Creates a Raster based on a BandedSampleModel with the + * specified data type, width, height, and number of bands. + * + *

The upper left corner of the Raster is given by the + * location argument. If location is null, (0, 0) will be used. + * The dataType parameter should be one of the enumerated values + * defined in the DataBuffer class. + * + *

The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT, + * and TYPE_INT. + * @param dataType the data type for storing samples + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param bands the number of bands + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified data type, + * width, height and number of bands. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws ArrayIndexOutOfBoundsException if bands + * is less than 1 + */ + public static WritableRaster createBandedRaster(int dataType, + int w, int h, + int bands, + Point location) { + if (bands < 1) { + throw new ArrayIndexOutOfBoundsException("Number of bands ("+ + bands+") must"+ + " be greater than 0"); + } + int[] bankIndices = new int[bands]; + int[] bandOffsets = new int[bands]; + for (int i = 0; i < bands; i++) { + bankIndices[i] = i; + bandOffsets[i] = 0; + } + + return createBandedRaster(dataType, w, h, w, + bankIndices, bandOffsets, + location); + } + + /** + * Creates a Raster based on a BandedSampleModel with the + * specified data type, width, height, scanline stride, bank + * indices and band offsets. The number of bands is inferred from + * bankIndices.length and bandOffsets.length, which must be the + * same. + * + *

The upper left corner of the Raster is given by the + * location argument. The dataType parameter should be one of the + * enumerated values defined in the DataBuffer class. + * + *

The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT, + * and TYPE_INT. + * @param dataType the data type for storing samples + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param scanlineStride the line stride of the image data + * @param bankIndices the bank indices for each band + * @param bandOffsets the offsets of all bands + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified data type, + * width, height, scanline stride, bank indices and band + * offsets. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws IllegalArgumentException if dataType is not + * one of the supported data types, which are + * DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT + * or DataBuffer.TYPE_INT + * @throws ArrayIndexOutOfBoundsException if bankIndices + * or bandOffsets is null + */ + public static WritableRaster createBandedRaster(int dataType, + int w, int h, + int scanlineStride, + int bankIndices[], + int bandOffsets[], + Point location) { + DataBuffer d; + int bands = bandOffsets.length; + + if (bankIndices == null) { + throw new + ArrayIndexOutOfBoundsException("Bank indices array is null"); + } + if (bandOffsets == null) { + throw new + ArrayIndexOutOfBoundsException("Band offsets array is null"); + } + + // Figure out the #banks and the largest band offset + int maxBank = bankIndices[0]; + int maxBandOff = bandOffsets[0]; + for (int i = 1; i < bands; i++) { + if (bankIndices[i] > maxBank) { + maxBank = bankIndices[i]; + } + if (bandOffsets[i] > maxBandOff) { + maxBandOff = bandOffsets[i]; + } + } + int banks = maxBank + 1; + int size = maxBandOff + scanlineStride*(h-1) + (w-1) + 1; + + switch(dataType) { + case DataBuffer.TYPE_BYTE: + d = new DataBufferByte(size, banks); + break; + + case DataBuffer.TYPE_USHORT: + d = new DataBufferUShort(size, banks); + break; + + case DataBuffer.TYPE_INT: + d = new DataBufferInt(size, banks); + break; + + default: + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + + return createBandedRaster(d, w, h, scanlineStride, + bankIndices, bandOffsets, location); + } + + /** + * Creates a Raster based on a SinglePixelPackedSampleModel with + * the specified data type, width, height, and band masks. + * The number of bands is inferred from bandMasks.length. + * + *

The upper left corner of the Raster is given by the + * location argument. If location is null, (0, 0) will be used. + * The dataType parameter should be one of the enumerated values + * defined in the DataBuffer class. + * + *

The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT, + * and TYPE_INT. + * @param dataType the data type for storing samples + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param bandMasks an array containing an entry for each band + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified data type, + * width, height, and band masks. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws IllegalArgumentException if dataType is not + * one of the supported data types, which are + * DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT + * or DataBuffer.TYPE_INT + */ + public static WritableRaster createPackedRaster(int dataType, + int w, int h, + int bandMasks[], + Point location) { + DataBuffer d; + + switch(dataType) { + case DataBuffer.TYPE_BYTE: + d = new DataBufferByte(w*h); + break; + + case DataBuffer.TYPE_USHORT: + d = new DataBufferUShort(w*h); + break; + + case DataBuffer.TYPE_INT: + d = new DataBufferInt(w*h); + break; + + default: + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + + return createPackedRaster(d, w, h, w, bandMasks, location); + } + + /** + * Creates a Raster based on a packed SampleModel with the + * specified data type, width, height, number of bands, and bits + * per band. If the number of bands is one, the SampleModel will + * be a MultiPixelPackedSampleModel. + * + *

If the number of bands is more than one, the SampleModel + * will be a SinglePixelPackedSampleModel, with each band having + * bitsPerBand bits. In either case, the requirements on dataType + * and bitsPerBand imposed by the corresponding SampleModel must + * be met. + * + *

The upper left corner of the Raster is given by the + * location argument. If location is null, (0, 0) will be used. + * The dataType parameter should be one of the enumerated values + * defined in the DataBuffer class. + * + *

The only dataTypes supported currently are TYPE_BYTE, TYPE_USHORT, + * and TYPE_INT. + * @param dataType the data type for storing samples + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param bands the number of bands + * @param bitsPerBand the number of bits per band + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified data type, + * width, height, number of bands, and bits per band. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws IllegalArgumentException if the product of + * bitsPerBand and bands is + * greater than the number of bits held by + * dataType + * @throws IllegalArgumentException if bitsPerBand or + * bands is not greater than zero + * @throws IllegalArgumentException if dataType is not + * one of the supported data types, which are + * DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT + * or DataBuffer.TYPE_INT + */ + public static WritableRaster createPackedRaster(int dataType, + int w, int h, + int bands, + int bitsPerBand, + Point location) { + DataBuffer d; + + if (bands <= 0) { + throw new IllegalArgumentException("Number of bands ("+bands+ + ") must be greater than 0"); + } + + if (bitsPerBand <= 0) { + throw new IllegalArgumentException("Bits per band ("+bitsPerBand+ + ") must be greater than 0"); + } + + if (bands != 1) { + int[] masks = new int[bands]; + int mask = (1 << bitsPerBand) - 1; + int shift = (bands-1)*bitsPerBand; + + /* Make sure the total mask size will fit in the data type */ + if (shift+bitsPerBand > DataBuffer.getDataTypeSize(dataType)) { + throw new IllegalArgumentException("bitsPerBand("+ + bitsPerBand+") * bands is "+ + " greater than data type "+ + "size."); + } + switch(dataType) { + case DataBuffer.TYPE_BYTE: + case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_INT: + break; + default: + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + + for (int i = 0; i < bands; i++) { + masks[i] = mask << shift; + shift = shift - bitsPerBand; + } + + return createPackedRaster(dataType, w, h, masks, location); + } + else { + double fw = w; + switch(dataType) { + case DataBuffer.TYPE_BYTE: + d = new DataBufferByte((int)(Math.ceil(fw/(8/bitsPerBand)))*h); + break; + + case DataBuffer.TYPE_USHORT: + d = new DataBufferUShort((int)(Math.ceil(fw/(16/bitsPerBand)))*h); + break; + + case DataBuffer.TYPE_INT: + d = new DataBufferInt((int)(Math.ceil(fw/(32/bitsPerBand)))*h); + break; + + default: + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + + return createPackedRaster(d, w, h, bitsPerBand, location); + } + } + + /** + * Creates a Raster based on a PixelInterleavedSampleModel with the + * specified DataBuffer, width, height, scanline stride, pixel + * stride, and band offsets. The number of bands is inferred from + * bandOffsets.length. The upper left corner of the Raster + * is given by the location argument. If location is null, (0, 0) + * will be used. + *

Note that interleaved DataBuffer.TYPE_INT + * Rasters are not supported. To create a 1-band Raster of type + * DataBuffer.TYPE_INT, use + * Raster.createPackedRaster(). + * @param dataBuffer the DataBuffer that contains the + * image data + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param scanlineStride the line stride of the image data + * @param pixelStride the pixel stride of the image data + * @param bandOffsets the offsets of all bands + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified + * DataBuffer, width, height, scanline stride, + * pixel stride and band offsets. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws IllegalArgumentException if dataType is not + * one of the supported data types, which are + * DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT + * @throws RasterFormatException if dataBuffer has more + * than one bank. + * @throws NullPointerException if dataBuffer is null + */ + public static WritableRaster createInterleavedRaster(DataBuffer dataBuffer, + int w, int h, + int scanlineStride, + int pixelStride, + int bandOffsets[], + Point location) { + if (dataBuffer == null) { + throw new NullPointerException("DataBuffer cannot be null"); + } + if (location == null) { + location = new Point(0, 0); + } + int dataType = dataBuffer.getDataType(); + + PixelInterleavedSampleModel csm = + new PixelInterleavedSampleModel(dataType, w, h, + pixelStride, + scanlineStride, + bandOffsets); + switch(dataType) { + case DataBuffer.TYPE_BYTE: + return new ByteInterleavedRaster(csm, dataBuffer, location); + + case DataBuffer.TYPE_USHORT: + return new ShortInterleavedRaster(csm, dataBuffer, location); + + default: + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + } + + /** + * Creates a Raster based on a BandedSampleModel with the + * specified DataBuffer, width, height, scanline stride, bank + * indices, and band offsets. The number of bands is inferred + * from bankIndices.length and bandOffsets.length, which must be + * the same. The upper left corner of the Raster is given by the + * location argument. If location is null, (0, 0) will be used. + * @param dataBuffer the DataBuffer that contains the + * image data + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param scanlineStride the line stride of the image data + * @param bankIndices the bank indices for each band + * @param bandOffsets the offsets of all bands + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified + * DataBuffer, width, height, scanline stride, + * bank indices and band offsets. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws IllegalArgumentException if dataType is not + * one of the supported data types, which are + * DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT + * or DataBuffer.TYPE_INT + * @throws NullPointerException if dataBuffer is null + */ + public static WritableRaster createBandedRaster(DataBuffer dataBuffer, + int w, int h, + int scanlineStride, + int bankIndices[], + int bandOffsets[], + Point location) { + if (dataBuffer == null) { + throw new NullPointerException("DataBuffer cannot be null"); + } + if (location == null) { + location = new Point(0,0); + } + int dataType = dataBuffer.getDataType(); + + int bands = bankIndices.length; + if (bandOffsets.length != bands) { + throw new IllegalArgumentException( + "bankIndices.length != bandOffsets.length"); + } + + BandedSampleModel bsm = + new BandedSampleModel(dataType, w, h, + scanlineStride, + bankIndices, bandOffsets); + + switch(dataType) { + case DataBuffer.TYPE_BYTE: + return new ByteBandedRaster(bsm, dataBuffer, location); + + case DataBuffer.TYPE_USHORT: + return new ShortBandedRaster(bsm, dataBuffer, location); + + case DataBuffer.TYPE_INT: + return new SunWritableRaster(bsm, dataBuffer, location); + + default: + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + } + + /** + * Creates a Raster based on a SinglePixelPackedSampleModel with + * the specified DataBuffer, width, height, scanline stride, and + * band masks. The number of bands is inferred from bandMasks.length. + * The upper left corner of the Raster is given by + * the location argument. If location is null, (0, 0) will be used. + * @param dataBuffer the DataBuffer that contains the + * image data + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param scanlineStride the line stride of the image data + * @param bandMasks an array containing an entry for each band + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified + * DataBuffer, width, height, scanline stride, + * and band masks. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws IllegalArgumentException if dataType is not + * one of the supported data types, which are + * DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT + * or DataBuffer.TYPE_INT + * @throws RasterFormatException if dataBuffer has more + * than one bank. + * @throws NullPointerException if dataBuffer is null + */ + public static WritableRaster createPackedRaster(DataBuffer dataBuffer, + int w, int h, + int scanlineStride, + int bandMasks[], + Point location) { + if (dataBuffer == null) { + throw new NullPointerException("DataBuffer cannot be null"); + } + if (location == null) { + location = new Point(0,0); + } + int dataType = dataBuffer.getDataType(); + + SinglePixelPackedSampleModel sppsm = + new SinglePixelPackedSampleModel(dataType, w, h, scanlineStride, + bandMasks); + + switch(dataType) { + case DataBuffer.TYPE_BYTE: + return new ByteInterleavedRaster(sppsm, dataBuffer, location); + + case DataBuffer.TYPE_USHORT: + return new ShortInterleavedRaster(sppsm, dataBuffer, location); + + case DataBuffer.TYPE_INT: + return new IntegerInterleavedRaster(sppsm, dataBuffer, location); + + default: + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + } + + /** + * Creates a Raster based on a MultiPixelPackedSampleModel with the + * specified DataBuffer, width, height, and bits per pixel. The upper + * left corner of the Raster is given by the location argument. If + * location is null, (0, 0) will be used. + * @param dataBuffer the DataBuffer that contains the + * image data + * @param w the width in pixels of the image data + * @param h the height in pixels of the image data + * @param bitsPerPixel the number of bits for each pixel + * @param location the upper-left corner of the Raster + * @return a WritableRaster object with the specified + * DataBuffer, width, height, and + * bits per pixel. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * location.x + w or + * location.y + h results in integer + * overflow + * @throws IllegalArgumentException if dataType is not + * one of the supported data types, which are + * DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT + * or DataBuffer.TYPE_INT + * @throws RasterFormatException if dataBuffer has more + * than one bank. + * @throws NullPointerException if dataBuffer is null + */ + public static WritableRaster createPackedRaster(DataBuffer dataBuffer, + int w, int h, + int bitsPerPixel, + Point location) { + if (dataBuffer == null) { + throw new NullPointerException("DataBuffer cannot be null"); + } + if (location == null) { + location = new Point(0,0); + } + int dataType = dataBuffer.getDataType(); + + if (dataType != DataBuffer.TYPE_BYTE && + dataType != DataBuffer.TYPE_USHORT && + dataType != DataBuffer.TYPE_INT) { + throw new IllegalArgumentException("Unsupported data type " + + dataType); + } + + if (dataBuffer.getNumBanks() != 1) { + throw new + RasterFormatException("DataBuffer for packed Rasters"+ + " must only have 1 bank."); + } + + MultiPixelPackedSampleModel mppsm = + new MultiPixelPackedSampleModel(dataType, w, h, bitsPerPixel); + + if (dataType == DataBuffer.TYPE_BYTE && + (bitsPerPixel == 1 || bitsPerPixel == 2 || bitsPerPixel == 4)) { + return new BytePackedRaster(mppsm, dataBuffer, location); + } else { + return new SunWritableRaster(mppsm, dataBuffer, location); + } + } + + + /** + * Creates a Raster with the specified SampleModel and DataBuffer. + * The upper left corner of the Raster is given by the location argument. + * If location is null, (0, 0) will be used. + * @param sm the specified SampleModel + * @param db the specified DataBuffer + * @param location the upper-left corner of the Raster + * @return a Raster with the specified + * SampleModel, DataBuffer, and + * location. + * @throws RasterFormatException if computing either + * location.x + sm.getWidth() or + * location.y + sm.getHeight() results in integer + * overflow + * @throws RasterFormatException if db has more + * than one bank and sm is a + * PixelInterleavedSampleModel, SinglePixelPackedSampleModel, + * or MultiPixelPackedSampleModel. + * @throws NullPointerException if either SampleModel or DataBuffer is + * null + */ + public static Raster createRaster(SampleModel sm, + DataBuffer db, + Point location) { + if ((sm == null) || (db == null)) { + throw new NullPointerException("SampleModel and DataBuffer cannot be null"); + } + + if (location == null) { + location = new Point(0,0); + } + int dataType = sm.getDataType(); + + if (sm instanceof PixelInterleavedSampleModel) { + switch(dataType) { + case DataBuffer.TYPE_BYTE: + return new ByteInterleavedRaster(sm, db, location); + + case DataBuffer.TYPE_USHORT: + return new ShortInterleavedRaster(sm, db, location); + } + } else if (sm instanceof SinglePixelPackedSampleModel) { + switch(dataType) { + case DataBuffer.TYPE_BYTE: + return new ByteInterleavedRaster(sm, db, location); + + case DataBuffer.TYPE_USHORT: + return new ShortInterleavedRaster(sm, db, location); + + case DataBuffer.TYPE_INT: + return new IntegerInterleavedRaster(sm, db, location); + } + } else if (sm instanceof MultiPixelPackedSampleModel && + dataType == DataBuffer.TYPE_BYTE && + sm.getSampleSize(0) < 8) { + return new BytePackedRaster(sm, db, location); + } + + // we couldn't do anything special - do the generic thing + + return new Raster(sm,db,location); + } + + /** + * Creates a WritableRaster with the specified SampleModel. + * The upper left corner of the Raster is given by the location argument. + * If location is null, (0, 0) will be used. + * @param sm the specified SampleModel + * @param location the upper-left corner of the + * WritableRaster + * @return a WritableRaster with the specified + * SampleModel and location. + * @throws RasterFormatException if computing either + * location.x + sm.getWidth() or + * location.y + sm.getHeight() results in integer + * overflow + */ + public static WritableRaster createWritableRaster(SampleModel sm, + Point location) { + if (location == null) { + location = new Point(0,0); + } + + return createWritableRaster(sm, sm.createDataBuffer(), location); + } + + /** + * Creates a WritableRaster with the specified SampleModel and DataBuffer. + * The upper left corner of the Raster is given by the location argument. + * If location is null, (0, 0) will be used. + * @param sm the specified SampleModel + * @param db the specified DataBuffer + * @param location the upper-left corner of the + * WritableRaster + * @return a WritableRaster with the specified + * SampleModel, DataBuffer, and + * location. + * @throws RasterFormatException if computing either + * location.x + sm.getWidth() or + * location.y + sm.getHeight() results in integer + * overflow + * @throws RasterFormatException if db has more + * than one bank and sm is a + * PixelInterleavedSampleModel, SinglePixelPackedSampleModel, + * or MultiPixelPackedSampleModel. + * @throws NullPointerException if either SampleModel or DataBuffer is null + */ + public static WritableRaster createWritableRaster(SampleModel sm, + DataBuffer db, + Point location) { + if ((sm == null) || (db == null)) { + throw new NullPointerException("SampleModel and DataBuffer cannot be null"); + } + if (location == null) { + location = new Point(0,0); + } + + int dataType = sm.getDataType(); + + if (sm instanceof PixelInterleavedSampleModel) { + switch(dataType) { + case DataBuffer.TYPE_BYTE: + return new ByteInterleavedRaster(sm, db, location); + + case DataBuffer.TYPE_USHORT: + return new ShortInterleavedRaster(sm, db, location); + } + } else if (sm instanceof SinglePixelPackedSampleModel) { + switch(dataType) { + case DataBuffer.TYPE_BYTE: + return new ByteInterleavedRaster(sm, db, location); + + case DataBuffer.TYPE_USHORT: + return new ShortInterleavedRaster(sm, db, location); + + case DataBuffer.TYPE_INT: + return new IntegerInterleavedRaster(sm, db, location); + } + } else if (sm instanceof MultiPixelPackedSampleModel && + dataType == DataBuffer.TYPE_BYTE && + sm.getSampleSize(0) < 8) { + return new BytePackedRaster(sm, db, location); + } + + // we couldn't do anything special - do the generic thing + + return new SunWritableRaster(sm,db,location); + } + + /** + * Constructs a Raster with the given SampleModel. The Raster's + * upper left corner is origin and it is the same size as the + * SampleModel. A DataBuffer large enough to describe the + * Raster is automatically created. + * @param sampleModel The SampleModel that specifies the layout + * @param origin The Point that specified the origin + * @throws RasterFormatException if computing either + * origin.x + sampleModel.getWidth() or + * origin.y + sampleModel.getHeight() results in + * integer overflow + * @throws NullPointerException either sampleModel or + * origin is null + */ + protected Raster(SampleModel sampleModel, + Point origin) { + this(sampleModel, + sampleModel.createDataBuffer(), + new Rectangle(origin.x, + origin.y, + sampleModel.getWidth(), + sampleModel.getHeight()), + origin, + null); + } + + /** + * Constructs a Raster with the given SampleModel and DataBuffer. + * The Raster's upper left corner is origin and it is the same size + * as the SampleModel. The DataBuffer is not initialized and must + * be compatible with SampleModel. + * @param sampleModel The SampleModel that specifies the layout + * @param dataBuffer The DataBuffer that contains the image data + * @param origin The Point that specifies the origin + * @throws RasterFormatException if computing either + * origin.x + sampleModel.getWidth() or + * origin.y + sampleModel.getHeight() results in + * integer overflow + * @throws NullPointerException either sampleModel or + * origin is null + */ + protected Raster(SampleModel sampleModel, + DataBuffer dataBuffer, + Point origin) { + this(sampleModel, + dataBuffer, + new Rectangle(origin.x, + origin.y, + sampleModel.getWidth(), + sampleModel.getHeight()), + origin, + null); + } + + /** + * Constructs a Raster with the given SampleModel, DataBuffer, and + * parent. aRegion specifies the bounding rectangle of the new + * Raster. When translated into the base Raster's coordinate + * system, aRegion must be contained by the base Raster. + * (The base Raster is the Raster's ancestor which has no parent.) + * sampleModelTranslate specifies the sampleModelTranslateX and + * sampleModelTranslateY values of the new Raster. + * + * Note that this constructor should generally be called by other + * constructors or create methods, it should not be used directly. + * @param sampleModel The SampleModel that specifies the layout + * @param dataBuffer The DataBuffer that contains the image data + * @param aRegion The Rectangle that specifies the image area + * @param sampleModelTranslate The Point that specifies the translation + * from SampleModel to Raster coordinates + * @param parent The parent (if any) of this raster + * @throws NullPointerException if any of sampleModel, + * dataBuffer, aRegion or + * sampleModelTranslate is null + * @throws RasterFormatException if aRegion has width + * or height less than or equal to zero, or computing either + * aRegion.x + aRegion.width or + * aRegion.y + aRegion.height results in integer + * overflow + */ + protected Raster(SampleModel sampleModel, + DataBuffer dataBuffer, + Rectangle aRegion, + Point sampleModelTranslate, + Raster parent) { + + if ((sampleModel == null) || (dataBuffer == null) || + (aRegion == null) || (sampleModelTranslate == null)) { + throw new NullPointerException("SampleModel, dataBuffer, aRegion and " + + "sampleModelTranslate cannot be null"); + } + this.sampleModel = sampleModel; + this.dataBuffer = dataBuffer; + minX = aRegion.x; + minY = aRegion.y; + width = aRegion.width; + height = aRegion.height; + if (width <= 0 || height <= 0) { + throw new RasterFormatException("negative or zero " + + ((width <= 0) ? "width" : "height")); + } + if ((minX + width) < minX) { + throw new RasterFormatException( + "overflow condition for X coordinates of Raster"); + } + if ((minY + height) < minY) { + throw new RasterFormatException( + "overflow condition for Y coordinates of Raster"); + } + + sampleModelTranslateX = sampleModelTranslate.x; + sampleModelTranslateY = sampleModelTranslate.y; + + numBands = sampleModel.getNumBands(); + numDataElements = sampleModel.getNumDataElements(); + this.parent = parent; + } + + + /** + * Returns the parent Raster (if any) of this Raster or null. + * @return the parent Raster or null. + */ + public Raster getParent() { + return parent; + } + + /** + * Returns the X translation from the coordinate system of the + * SampleModel to that of the Raster. To convert a pixel's X + * coordinate from the Raster coordinate system to the SampleModel + * coordinate system, this value must be subtracted. + * @return the X translation from the coordinate space of the + * Raster's SampleModel to that of the Raster. + */ + final public int getSampleModelTranslateX() { + return sampleModelTranslateX; + } + + /** + * Returns the Y translation from the coordinate system of the + * SampleModel to that of the Raster. To convert a pixel's Y + * coordinate from the Raster coordinate system to the SampleModel + * coordinate system, this value must be subtracted. + * @return the Y translation from the coordinate space of the + * Raster's SampleModel to that of the Raster. + */ + final public int getSampleModelTranslateY() { + return sampleModelTranslateY; + } + + /** + * Create a compatible WritableRaster the same size as this Raster with + * the same SampleModel and a new initialized DataBuffer. + * @return a compatible WritableRaster with the same sample + * model and a new data buffer. + */ + public WritableRaster createCompatibleWritableRaster() { + return new SunWritableRaster(sampleModel, new Point(0,0)); + } + + /** + * Create a compatible WritableRaster with the specified size, a new + * SampleModel, and a new initialized DataBuffer. + * @param w the specified width of the new WritableRaster + * @param h the specified height of the new WritableRaster + * @return a compatible WritableRaster with the specified + * size and a new sample model and data buffer. + * @exception RasterFormatException if the width or height is less than + * or equal to zero. + */ + public WritableRaster createCompatibleWritableRaster(int w, int h) { + if (w <= 0 || h <=0) { + throw new RasterFormatException("negative " + + ((w <= 0) ? "width" : "height")); + } + + SampleModel sm = sampleModel.createCompatibleSampleModel(w,h); + + return new SunWritableRaster(sm, new Point(0,0)); + } + + /** + * Create a compatible WritableRaster with location (minX, minY) + * and size (width, height) specified by rect, a + * new SampleModel, and a new initialized DataBuffer. + * @param rect a Rectangle that specifies the size and + * location of the WritableRaster + * @return a compatible WritableRaster with the specified + * size and location and a new sample model and data buffer. + * @throws RasterFormatException if rect has width + * or height less than or equal to zero, or computing either + * rect.x + rect.width or + * rect.y + rect.height results in integer + * overflow + * @throws NullPointerException if rect is null + */ + public WritableRaster createCompatibleWritableRaster(Rectangle rect) { + if (rect == null) { + throw new NullPointerException("Rect cannot be null"); + } + return createCompatibleWritableRaster(rect.x, rect.y, + rect.width, rect.height); + } + + /** + * Create a compatible WritableRaster with the specified + * location (minX, minY) and size (width, height), a + * new SampleModel, and a new initialized DataBuffer. + * @param x the X coordinate of the upper-left corner of + * the WritableRaster + * @param y the Y coordinate of the upper-left corner of + * the WritableRaster + * @param w the specified width of the WritableRaster + * @param h the specified height of the WritableRaster + * @return a compatible WritableRaster with the specified + * size and location and a new sample model and data buffer. + * @throws RasterFormatException if w or h + * is less than or equal to zero, or computing either + * x + w or + * y + h results in integer + * overflow + */ + public WritableRaster createCompatibleWritableRaster(int x, int y, + int w, int h) { + WritableRaster ret = createCompatibleWritableRaster(w, h); + return ret.createWritableChild(0,0,w,h,x,y,null); + } + + /** + * Create a Raster with the same size, SampleModel and DataBuffer + * as this one, but with a different location. The new Raster + * will possess a reference to the current Raster, accessible + * through its getParent() method. + * + * @param childMinX the X coordinate of the upper-left + * corner of the new Raster + * @param childMinY the Y coordinate of the upper-left + * corner of the new Raster + * @return a new Raster with the same size, SampleModel, + * and DataBuffer as this Raster, but with the + * specified location. + * @throws RasterFormatException if computing either + * childMinX + this.getWidth() or + * childMinY + this.getHeight() results in integer + * overflow + */ + public Raster createTranslatedChild(int childMinX, int childMinY) { + return createChild(minX,minY,width,height, + childMinX,childMinY,null); + } + + /** + * Returns a new Raster which shares all or part of this Raster's + * DataBuffer. The new Raster will possess a reference to the + * current Raster, accessible through its getParent() method. + * + *

The parentX, parentY, width and height parameters + * form a Rectangle in this Raster's coordinate space, + * indicating the area of pixels to be shared. An error will + * be thrown if this Rectangle is not contained with the bounds + * of the current Raster. + * + *

The new Raster may additionally be translated to a + * different coordinate system for the plane than that used by the current + * Raster. The childMinX and childMinY parameters give the new + * (x, y) coordinate of the upper-left pixel of the returned + * Raster; the coordinate (childMinX, childMinY) in the new Raster + * will map to the same pixel as the coordinate (parentX, parentY) + * in the current Raster. + * + *

The new Raster may be defined to contain only a subset of + * the bands of the current Raster, possibly reordered, by means + * of the bandList parameter. If bandList is null, it is taken to + * include all of the bands of the current Raster in their current + * order. + * + *

To create a new Raster that contains a subregion of the current + * Raster, but shares its coordinate system and bands, + * this method should be called with childMinX equal to parentX, + * childMinY equal to parentY, and bandList equal to null. + * + * @param parentX The X coordinate of the upper-left corner + * in this Raster's coordinates + * @param parentY The Y coordinate of the upper-left corner + * in this Raster's coordinates + * @param width Width of the region starting at (parentX, parentY) + * @param height Height of the region starting at (parentX, parentY). + * @param childMinX The X coordinate of the upper-left corner + * of the returned Raster + * @param childMinY The Y coordinate of the upper-left corner + * of the returned Raster + * @param bandList Array of band indices, or null to use all bands + * @return a new Raster. + * @exception RasterFormatException if the specified subregion is outside + * of the raster bounds. + * @throws RasterFormatException if width or + * height + * is less than or equal to zero, or computing any of + * parentX + width, parentY + height, + * childMinX + width, or + * childMinY + height results in integer + * overflow + */ + public Raster createChild(int parentX, int parentY, + int width, int height, + int childMinX, int childMinY, + int bandList[]) { + if (parentX < this.minX) { + throw new RasterFormatException("parentX lies outside raster"); + } + if (parentY < this.minY) { + throw new RasterFormatException("parentY lies outside raster"); + } + if ((parentX + width < parentX) || + (parentX + width > this.width + this.minX)) { + throw new RasterFormatException("(parentX + width) is outside raster"); + } + if ((parentY + height < parentY) || + (parentY + height > this.height + this.minY)) { + throw new RasterFormatException("(parentY + height) is outside raster"); + } + + SampleModel subSampleModel; + // Note: the SampleModel for the child Raster should have the same + // width and height as that for the parent, since it represents + // the physical layout of the pixel data. The child Raster's width + // and height represent a "virtual" view of the pixel data, so + // they may be different than those of the SampleModel. + if (bandList == null) { + subSampleModel = sampleModel; + } else { + subSampleModel = sampleModel.createSubsetSampleModel(bandList); + } + + int deltaX = childMinX - parentX; + int deltaY = childMinY - parentY; + + return new Raster(subSampleModel, getDataBuffer(), + new Rectangle(childMinX, childMinY, width, height), + new Point(sampleModelTranslateX + deltaX, + sampleModelTranslateY + deltaY), this); + } + + /** + * Returns the bounding Rectangle of this Raster. This function returns + * the same information as getMinX/MinY/Width/Height. + * @return the bounding box of this Raster. + */ + public Rectangle getBounds() { + return new Rectangle(minX, minY, width, height); + } + + /** Returns the minimum valid X coordinate of the Raster. + * @return the minimum x coordinate of this Raster. + */ + final public int getMinX() { + return minX; + } + + /** Returns the minimum valid Y coordinate of the Raster. + * @return the minimum y coordinate of this Raster. + */ + final public int getMinY() { + return minY; + } + + /** Returns the width in pixels of the Raster. + * @return the width of this Raster. + */ + final public int getWidth() { + return width; + } + + /** Returns the height in pixels of the Raster. + * @return the height of this Raster. + */ + final public int getHeight() { + return height; + } + + /** Returns the number of bands (samples per pixel) in this Raster. + * @return the number of bands of this Raster. + */ + final public int getNumBands() { + return numBands; + } + + /** + * Returns the number of data elements needed to transfer one pixel + * via the getDataElements and setDataElements methods. When pixels + * are transferred via these methods, they may be transferred in a + * packed or unpacked format, depending on the implementation of the + * underlying SampleModel. Using these methods, pixels are transferred + * as an array of getNumDataElements() elements of a primitive type given + * by getTransferType(). The TransferType may or may not be the same + * as the storage data type of the DataBuffer. + * @return the number of data elements. + */ + final public int getNumDataElements() { + return sampleModel.getNumDataElements(); + } + + /** + * Returns the TransferType used to transfer pixels via the + * getDataElements and setDataElements methods. When pixels + * are transferred via these methods, they may be transferred in a + * packed or unpacked format, depending on the implementation of the + * underlying SampleModel. Using these methods, pixels are transferred + * as an array of getNumDataElements() elements of a primitive type given + * by getTransferType(). The TransferType may or may not be the same + * as the storage data type of the DataBuffer. The TransferType will + * be one of the types defined in DataBuffer. + * @return this transfer type. + */ + final public int getTransferType() { + return sampleModel.getTransferType(); + } + + /** Returns the DataBuffer associated with this Raster. + * @return the DataBuffer of this Raster. + */ + public DataBuffer getDataBuffer() { + return dataBuffer; + } + + /** Returns the SampleModel that describes the layout of the image data. + * @return the SampleModel of this Raster. + */ + public SampleModel getSampleModel() { + return sampleModel; + } + + /** + * Returns data for a single pixel in a primitive array of type + * TransferType. For image data supported by the Java 2D(tm) API, + * this will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, + * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, + * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format, + * thus increasing efficiency for data transfers. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of TransferType. + * @see java.awt.image.SampleModel#getDataElements(int, int, Object, DataBuffer) + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param outData An object reference to an array of type defined by + * getTransferType() and length getNumDataElements(). + * If null, an array of appropriate type and size will be + * allocated + * @return An object reference to an array of type defined by + * getTransferType() with the requested pixel data. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if outData is too small to hold the output. + */ + public Object getDataElements(int x, int y, Object outData) { + return sampleModel.getDataElements(x - sampleModelTranslateX, + y - sampleModelTranslateY, + outData, dataBuffer); + } + + /** + * Returns the pixel data for the specified rectangle of pixels in a + * primitive array of type TransferType. + * For image data supported by the Java 2D API, this + * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, + * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, + * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format, + * thus increasing efficiency for data transfers. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * A ClassCastException will be thrown if the input object is non null + * and references anything other than an array of TransferType. + * @see java.awt.image.SampleModel#getDataElements(int, int, int, int, Object, DataBuffer) + * @param x The X coordinate of the upper-left pixel location + * @param y The Y coordinate of the upper-left pixel location + * @param w Width of the pixel rectangle + * @param h Height of the pixel rectangle + * @param outData An object reference to an array of type defined by + * getTransferType() and length w*h*getNumDataElements(). + * If null, an array of appropriate type and size will be + * allocated. + * @return An object reference to an array of type defined by + * getTransferType() with the requested pixel data. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if outData is too small to hold the output. + */ + public Object getDataElements(int x, int y, int w, int h, Object outData) { + return sampleModel.getDataElements(x - sampleModelTranslateX, + y - sampleModelTranslateY, + w, h, outData, dataBuffer); + } + + /** + * Returns the samples in an array of int for the specified pixel. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param iArray An optionally preallocated int array + * @return the samples for the specified pixel. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if iArray is too small to hold the output. + */ + public int[] getPixel(int x, int y, int iArray[]) { + return sampleModel.getPixel(x - sampleModelTranslateX, + y - sampleModelTranslateY, + iArray, dataBuffer); + } + + /** + * Returns the samples in an array of float for the + * specified pixel. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param fArray An optionally preallocated float array + * @return the samples for the specified pixel. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if fArray is too small to hold the output. + */ + public float[] getPixel(int x, int y, float fArray[]) { + return sampleModel.getPixel(x - sampleModelTranslateX, + y - sampleModelTranslateY, + fArray, dataBuffer); + } + + /** + * Returns the samples in an array of double for the specified pixel. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param dArray An optionally preallocated double array + * @return the samples for the specified pixel. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if dArray is too small to hold the output. + */ + public double[] getPixel(int x, int y, double dArray[]) { + return sampleModel.getPixel(x - sampleModelTranslateX, + y - sampleModelTranslateY, + dArray, dataBuffer); + } + + /** + * Returns an int array containing all samples for a rectangle of pixels, + * one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the upper-left pixel location + * @param y The Y coordinate of the upper-left pixel location + * @param w Width of the pixel rectangle + * @param h Height of the pixel rectangle + * @param iArray An optionally pre-allocated int array + * @return the samples for the specified rectangle of pixels. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if iArray is too small to hold the output. + */ + public int[] getPixels(int x, int y, int w, int h, int iArray[]) { + return sampleModel.getPixels(x - sampleModelTranslateX, + y - sampleModelTranslateY, w, h, + iArray, dataBuffer); + } + + /** + * Returns a float array containing all samples for a rectangle of pixels, + * one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param w Width of the pixel rectangle + * @param h Height of the pixel rectangle + * @param fArray An optionally pre-allocated float array + * @return the samples for the specified rectangle of pixels. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if fArray is too small to hold the output. + */ + public float[] getPixels(int x, int y, int w, int h, + float fArray[]) { + return sampleModel.getPixels(x - sampleModelTranslateX, + y - sampleModelTranslateY, w, h, + fArray, dataBuffer); + } + + /** + * Returns a double array containing all samples for a rectangle of pixels, + * one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the upper-left pixel location + * @param y The Y coordinate of the upper-left pixel location + * @param w Width of the pixel rectangle + * @param h Height of the pixel rectangle + * @param dArray An optionally pre-allocated double array + * @return the samples for the specified rectangle of pixels. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if dArray is too small to hold the output. + */ + public double[] getPixels(int x, int y, int w, int h, + double dArray[]) { + return sampleModel.getPixels(x - sampleModelTranslateX, + y - sampleModelTranslateY, + w, h, dArray, dataBuffer); + } + + + /** + * Returns the sample in a specified band for the pixel located + * at (x,y) as an int. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to return + * @return the sample in the specified band for the pixel at the + * specified coordinate. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds. + */ + public int getSample(int x, int y, int b) { + return sampleModel.getSample(x - sampleModelTranslateX, + y - sampleModelTranslateY, b, + dataBuffer); + } + + /** + * Returns the sample in a specified band + * for the pixel located at (x,y) as a float. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to return + * @return the sample in the specified band for the pixel at the + * specified coordinate. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds. + */ + public float getSampleFloat(int x, int y, int b) { + return sampleModel.getSampleFloat(x - sampleModelTranslateX, + y - sampleModelTranslateY, b, + dataBuffer); + } + + /** + * Returns the sample in a specified band + * for a pixel located at (x,y) as a double. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param b The band to return + * @return the sample in the specified band for the pixel at the + * specified coordinate. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds. + */ + public double getSampleDouble(int x, int y, int b) { + return sampleModel.getSampleDouble(x - sampleModelTranslateX, + y - sampleModelTranslateY, + b, dataBuffer); + } + + /** + * Returns the samples for a specified band for the specified rectangle + * of pixels in an int array, one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the upper-left pixel location + * @param y The Y coordinate of the upper-left pixel location + * @param w Width of the pixel rectangle + * @param h Height of the pixel rectangle + * @param b The band to return + * @param iArray An optionally pre-allocated int array + * @return the samples for the specified band for the specified + * rectangle of pixels. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if iArray is too small to + * hold the output. + */ + public int[] getSamples(int x, int y, int w, int h, int b, + int iArray[]) { + return sampleModel.getSamples(x - sampleModelTranslateX, + y - sampleModelTranslateY, + w, h, b, iArray, + dataBuffer); + } + + /** + * Returns the samples for a specified band for the specified rectangle + * of pixels in a float array, one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the upper-left pixel location + * @param y The Y coordinate of the upper-left pixel location + * @param w Width of the pixel rectangle + * @param h Height of the pixel rectangle + * @param b The band to return + * @param fArray An optionally pre-allocated float array + * @return the samples for the specified band for the specified + * rectangle of pixels. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if fArray is too small to + * hold the output. + */ + public float[] getSamples(int x, int y, int w, int h, int b, + float fArray[]) { + return sampleModel.getSamples(x - sampleModelTranslateX, + y - sampleModelTranslateY, + w, h, b, fArray, dataBuffer); + } + + /** + * Returns the samples for a specified band for a specified rectangle + * of pixels in a double array, one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown + * if the coordinates are not in bounds. However, explicit bounds + * checking is not guaranteed. + * @param x The X coordinate of the upper-left pixel location + * @param y The Y coordinate of the upper-left pixel location + * @param w Width of the pixel rectangle + * @param h Height of the pixel rectangle + * @param b The band to return + * @param dArray An optionally pre-allocated double array + * @return the samples for the specified band for the specified + * rectangle of pixels. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if dArray is too small to + * hold the output. + */ + public double[] getSamples(int x, int y, int w, int h, int b, + double dArray[]) { + return sampleModel.getSamples(x - sampleModelTranslateX, + y - sampleModelTranslateY, + w, h, b, dArray, dataBuffer); + } + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/RenderedImage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/RenderedImage.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,217 @@ +/* + * Portions Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; +import java.awt.Rectangle; +import java.util.Dictionary; +import java.util.Vector; + +/** + * RenderedImage is a common interface for objects which contain + * or can produce image data in the form of Rasters. The image + * data may be stored/produced as a single tile or a regular array + * of tiles. + */ + +public interface RenderedImage { + + /** + * Returns a vector of RenderedImages that are the immediate sources of + * image data for this RenderedImage. This method returns null if + * the RenderedImage object has no information about its immediate + * sources. It returns an empty Vector if the RenderedImage object has + * no immediate sources. + * @return a Vector of RenderedImage objects. + */ + Vector getSources(); + + /** + * Gets a property from the property set of this image. The set of + * properties and whether it is immutable is determined by the + * implementing class. This method returns + * java.awt.Image.UndefinedProperty if the specified property is + * not defined for this RenderedImage. + * @param name the name of the property + * @return the property indicated by the specified name. + * @see java.awt.Image#UndefinedProperty + */ + Object getProperty(String name); + + /** + * Returns an array of names recognized by + * {@link #getProperty(String) getProperty(String)} + * or null, if no property names are recognized. + * @return a String array containing all of the + * property names that getProperty(String) recognizes; + * or null if no property names are recognized. + */ + String[] getPropertyNames(); + + /** + * Returns the ColorModel associated with this image. All Rasters + * returned from this image will have this as their ColorModel. This + * can return null. + * @return the ColorModel of this image. + */ + ColorModel getColorModel(); + + /** + * Returns the SampleModel associated with this image. All Rasters + * returned from this image will have this as their SampleModel. + * @return the SampleModel of this image. + */ + SampleModel getSampleModel(); + + /** + * Returns the width of the RenderedImage. + * @return the width of this RenderedImage. + */ + int getWidth(); + + /** + * Returns the height of the RenderedImage. + * @return the height of this RenderedImage. + */ + int getHeight(); + + /** + * Returns the minimum X coordinate (inclusive) of the RenderedImage. + * @return the X coordinate of this RenderedImage. + */ + int getMinX(); + + /** + * Returns the minimum Y coordinate (inclusive) of the RenderedImage. + * @return the Y coordinate of this RenderedImage. + */ + int getMinY(); + + /** + * Returns the number of tiles in the X direction. + * @return the number of tiles in the X direction. + */ + int getNumXTiles(); + + /** + * Returns the number of tiles in the Y direction. + * @return the number of tiles in the Y direction. + */ + int getNumYTiles(); + + /** + * Returns the minimum tile index in the X direction. + * @return the minimum tile index in the X direction. + */ + int getMinTileX(); + + /** + * Returns the minimum tile index in the Y direction. + * @return the minimum tile index in the X direction. + */ + int getMinTileY(); + + /** + * Returns the tile width in pixels. All tiles must have the same + * width. + * @return the tile width in pixels. + */ + int getTileWidth(); + + /** + * Returns the tile height in pixels. All tiles must have the same + * height. + * @return the tile height in pixels. + */ + int getTileHeight(); + + /** + * Returns the X offset of the tile grid relative to the origin, + * i.e., the X coordinate of the upper-left pixel of tile (0, 0). + * (Note that tile (0, 0) may not actually exist.) + * @return the X offset of the tile grid relative to the origin. + */ + int getTileGridXOffset(); + + /** + * Returns the Y offset of the tile grid relative to the origin, + * i.e., the Y coordinate of the upper-left pixel of tile (0, 0). + * (Note that tile (0, 0) may not actually exist.) + * @return the Y offset of the tile grid relative to the origin. + */ + int getTileGridYOffset(); + + /** + * Returns tile (tileX, tileY). Note that tileX and tileY are indices + * into the tile array, not pixel locations. The Raster that is returned + * is live and will be updated if the image is changed. + * @param tileX the X index of the requested tile in the tile array + * @param tileY the Y index of the requested tile in the tile array + * @return the tile given the specified indices. + */ + Raster getTile(int tileX, int tileY); + + /** + * Returns the image as one large tile (for tile based + * images this will require fetching the whole image + * and copying the image data over). The Raster returned is + * a copy of the image data and will not be updated if the image + * is changed. + * @return the image as one large tile. + */ + Raster getData(); + + /** + * Computes and returns an arbitrary region of the RenderedImage. + * The Raster returned is a copy of the image data and will not + * be updated if the image is changed. + * @param rect the region of the RenderedImage to be returned. + * @return the region of the RenderedImage + * indicated by the specified Rectangle. + */ + Raster getData(Rectangle rect); + + /** + * Computes an arbitrary rectangular region of the RenderedImage + * and copies it into a caller-supplied WritableRaster. The region + * to be computed is determined from the bounds of the supplied + * WritableRaster. The supplied WritableRaster must have a + * SampleModel that is compatible with this image. If raster is null, + * an appropriate WritableRaster is created. + * @param raster a WritableRaster to hold the returned portion of the + * image, or null. + * @return a reference to the supplied or created WritableRaster. + */ + WritableRaster copyData(WritableRaster raster); +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/SampleModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/SampleModel.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,1393 @@ +/* + * Portions Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +/** + * This abstract class defines an interface for extracting samples of pixels + * in an image. All image data is expressed as a collection of pixels. + * Each pixel consists of a number of samples. A sample is a datum + * for one band of an image and a band consists of all samples of a + * particular type in an image. For example, a pixel might contain + * three samples representing its red, green and blue components. + * There are three bands in the image containing this pixel. One band + * consists of all the red samples from all pixels in the + * image. The second band consists of all the green samples and + * the remaining band consists of all of the blue samples. The pixel + * can be stored in various formats. For example, all samples from + * a particular band can be stored contiguously or all samples from a + * single pixel can be stored contiguously. + *

+ * Subclasses of SampleModel specify the types of samples they can + * represent (e.g. unsigned 8-bit byte, signed 16-bit short, etc.) + * and may specify how the samples are organized in memory. + * In the Java 2D(tm) API, built-in image processing operators may + * not operate on all possible sample types, but generally will work + * for unsigned integral samples of 16 bits or less. Some operators + * support a wider variety of sample types. + *

+ * A collection of pixels is represented as a Raster, which consists of + * a DataBuffer and a SampleModel. The SampleModel allows access to + * samples in the DataBuffer and may provide low-level information that + * a programmer can use to directly manipulate samples and pixels in the + * DataBuffer. + *

+ * This class is generally a fall back method for dealing with + * images. More efficient code will cast the SampleModel to the + * appropriate subclass and extract the information needed to directly + * manipulate pixels in the DataBuffer. + * + * @see java.awt.image.DataBuffer + * @see java.awt.image.Raster + * @see java.awt.image.ComponentSampleModel + * @see java.awt.image.PixelInterleavedSampleModel + * @see java.awt.image.BandedSampleModel + * @see java.awt.image.MultiPixelPackedSampleModel + * @see java.awt.image.SinglePixelPackedSampleModel + */ + +public abstract class SampleModel +{ + + /** Width in pixels of the region of image data that this SampleModel + * describes. + */ + protected int width; + + /** Height in pixels of the region of image data that this SampleModel + * describes. + */ + protected int height; + + /** Number of bands of the image data that this SampleModel describes. */ + protected int numBands; + + /** Data type of the DataBuffer storing the pixel data. + * @see java.awt.image.DataBuffer + */ + protected int dataType; + + static private native void initIDs(); + static { + ColorModel.loadLibraries(); + initIDs(); + } + + /** + * Constructs a SampleModel with the specified parameters. + * @param dataType The data type of the DataBuffer storing the pixel data. + * @param w The width (in pixels) of the region of image data. + * @param h The height (in pixels) of the region of image data. + * @param numBands The number of bands of the image data. + * @throws IllegalArgumentException if w or h + * is not greater than 0 + * @throws IllegalArgumentException if the product of w + * and h is greater than + * Integer.MAX_VALUE + * @throws IllegalArgumentException if dataType is not + * one of the supported data types + */ + public SampleModel(int dataType, int w, int h, int numBands) + { + float size = (float)w*h; + if (w <= 0 || h <= 0) { + throw new IllegalArgumentException("Width ("+w+") and height ("+ + h+") must be > 0"); + } + if (size >= Integer.MAX_VALUE) { + throw new IllegalArgumentException("Dimensions (width="+w+ + " height="+h+") are too large"); + } + + if (dataType < DataBuffer.TYPE_BYTE || + (dataType > DataBuffer.TYPE_DOUBLE && + dataType != DataBuffer.TYPE_UNDEFINED)) + { + throw new IllegalArgumentException("Unsupported dataType: "+ + dataType); + } + + if (numBands <= 0) { + throw new IllegalArgumentException("Number of bands must be > 0"); + } + + this.dataType = dataType; + this.width = w; + this.height = h; + this.numBands = numBands; + } + + /** Returns the width in pixels. + * @return the width in pixels of the region of image data + * that this SampleModel describes. + */ + final public int getWidth() { + return width; + } + + /** Returns the height in pixels. + * @return the height in pixels of the region of image data + * that this SampleModel describes. + */ + final public int getHeight() { + return height; + } + + /** Returns the total number of bands of image data. + * @return the number of bands of image data that this + * SampleModel describes. + */ + final public int getNumBands() { + return numBands; + } + + /** Returns the number of data elements needed to transfer a pixel + * via the getDataElements and setDataElements methods. When pixels + * are transferred via these methods, they may be transferred in a + * packed or unpacked format, depending on the implementation of the + * SampleModel. Using these methods, pixels are transferred as an + * array of getNumDataElements() elements of a primitive type given + * by getTransferType(). The TransferType may or may not be the same + * as the storage DataType. + * @return the number of data elements. + * @see #getDataElements(int, int, Object, DataBuffer) + * @see #getDataElements(int, int, int, int, Object, DataBuffer) + * @see #setDataElements(int, int, Object, DataBuffer) + * @see #setDataElements(int, int, int, int, Object, DataBuffer) + * @see #getTransferType + */ + public abstract int getNumDataElements(); + + /** Returns the data type of the DataBuffer storing the pixel data. + * @return the data type. + */ + final public int getDataType() { + return dataType; + } + + /** Returns the TransferType used to transfer pixels via the + * getDataElements and setDataElements methods. When pixels + * are transferred via these methods, they may be transferred in a + * packed or unpacked format, depending on the implementation of the + * SampleModel. Using these methods, pixels are transferred as an + * array of getNumDataElements() elements of a primitive type given + * by getTransferType(). The TransferType may or may not be the same + * as the storage DataType. The TransferType will be one of the types + * defined in DataBuffer. + * @return the transfer type. + * @see #getDataElements(int, int, Object, DataBuffer) + * @see #getDataElements(int, int, int, int, Object, DataBuffer) + * @see #setDataElements(int, int, Object, DataBuffer) + * @see #setDataElements(int, int, int, int, Object, DataBuffer) + * @see #getNumDataElements + * @see java.awt.image.DataBuffer + */ + public int getTransferType() { + return dataType; + } + + /** + * Returns the samples for a specified pixel in an int array, + * one sample per array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location + * @param y The Y coordinate of the pixel location + * @param iArray If non-null, returns the samples in this array + * @param data The DataBuffer containing the image data + * @return the samples for the specified pixel. + * @see #setPixel(int, int, int[], DataBuffer) + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds, or if iArray is too small to hold the output. + */ + public int[] getPixel(int x, int y, int iArray[], DataBuffer data) { + + int pixels[]; + + if (iArray != null) + pixels = iArray; + else + pixels = new int[numBands]; + + for (int i=0; i + * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is described by + * SampleModel sm1, to DataBuffer db2, whose + * storage layout is described by SampleModel sm2. + * The transfer will generally be more efficient than using + * getPixel/setPixel. + *

+     *       SampleModel sm1, sm2;
+     *       DataBuffer db1, db2;
+     *       sm2.setDataElements(x, y, sm1.getDataElements(x, y, null, db1), db2);
+     * 
+ * Using getDataElements/setDataElements to transfer between two + * DataBuffer/SampleModel pairs is legitimate if the SampleModels have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * If obj is non-null, it should be a primitive array of type TransferType. + * Otherwise, a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if obj is non-null and is not large enough to hold + * the pixel data. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param obj If non-null, a primitive array in which to return + * the pixel data. + * @param data The DataBuffer containing the image data. + * @return the data elements for the specified pixel. + * @see #getNumDataElements + * @see #getTransferType + * @see java.awt.image.DataBuffer + * @see #setDataElements(int, int, Object, DataBuffer) + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds, or if obj is too small to hold the output. + */ + public abstract Object getDataElements(int x, int y, + Object obj, DataBuffer data); + + /** + * Returns the pixel data for the specified rectangle of pixels in a + * primitive array of type TransferType. + * For image data supported by the Java 2D API, this + * will be one of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT, + * DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, DataBuffer.TYPE_FLOAT, + * or DataBuffer.TYPE_DOUBLE. Data may be returned in a packed format, + * thus increasing efficiency for data transfers. Generally, obj + * should be passed in as null, so that the Object will be created + * automatically and will be of the right primitive data type. + *

+ * The following code illustrates transferring data for a rectangular + * region of pixels from + * DataBuffer db1, whose storage layout is described by + * SampleModel sm1, to DataBuffer db2, whose + * storage layout is described by SampleModel sm2. + * The transfer will generally be more efficient than using + * getPixels/setPixels. + *

+     *       SampleModel sm1, sm2;
+     *       DataBuffer db1, db2;
+     *       sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w,
+     *                           h, null, db1), db2);
+     * 
+ * Using getDataElements/setDataElements to transfer between two + * DataBuffer/SampleModel pairs is legitimate if the SampleModels have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * If obj is non-null, it should be a primitive array of type TransferType. + * Otherwise, a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if obj is non-null and is not large enough to hold + * the pixel data. + * @param x The minimum X coordinate of the pixel rectangle. + * @param y The minimum Y coordinate of the pixel rectangle. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param obj If non-null, a primitive array in which to return + * the pixel data. + * @param data The DataBuffer containing the image data. + * @return the data elements for the specified region of pixels. + * @see #getNumDataElements + * @see #getTransferType + * @see #setDataElements(int, int, int, int, Object, DataBuffer) + * @see java.awt.image.DataBuffer + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds, or if obj is too small to hold the output. + */ + public Object getDataElements(int x, int y, int w, int h, + Object obj, DataBuffer data) { + + int type = getTransferType(); + int numDataElems = getNumDataElements(); + int cnt = 0; + Object o = null; + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] btemp; + byte[] bdata; + + if (obj == null) + bdata = new byte[numDataElems*w*h]; + else + bdata = (byte[])obj; + + for (int i=y; i + * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is described by + * SampleModel sm1, to DataBuffer db2, whose + * storage layout is described by SampleModel sm2. + * The transfer will generally be more efficient than using + * getPixel/setPixel. + *

+     *       SampleModel sm1, sm2;
+     *       DataBuffer db1, db2;
+     *       sm2.setDataElements(x, y, sm1.getDataElements(x, y, null, db1),
+     *                           db2);
+     * 
+ * Using getDataElements/setDataElements to transfer between two + * DataBuffer/SampleModel pairs is legitimate if the SampleModels have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * obj must be a primitive array of type TransferType. Otherwise, + * a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if obj is not large enough to hold the pixel data. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param obj A primitive array containing pixel data. + * @param data The DataBuffer containing the image data. + * @see #getNumDataElements + * @see #getTransferType + * @see #getDataElements(int, int, Object, DataBuffer) + * @see java.awt.image.DataBuffer + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds, or if obj is too small to hold the input. + */ + public abstract void setDataElements(int x, int y, + Object obj, DataBuffer data); + + /** + * Sets the data for a rectangle of pixels in the specified DataBuffer + * from a primitive array of type TransferType. For image data supported + * by the Java 2D API, this will be one of DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, + * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array + * may be in a packed format, thus increasing efficiency for data + * transfers. + *

+ * The following code illustrates transferring data for a rectangular + * region of pixels from + * DataBuffer db1, whose storage layout is described by + * SampleModel sm1, to DataBuffer db2, whose + * storage layout is described by SampleModel sm2. + * The transfer will generally be more efficient than using + * getPixels/setPixels. + *

+     *       SampleModel sm1, sm2;
+     *       DataBuffer db1, db2;
+     *       sm2.setDataElements(x, y, w, h, sm1.getDataElements(x, y, w, h,
+     *                           null, db1), db2);
+     * 
+ * Using getDataElements/setDataElements to transfer between two + * DataBuffer/SampleModel pairs is legitimate if the SampleModels have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * obj must be a primitive array of type TransferType. Otherwise, + * a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if obj is not large enough to hold the pixel data. + * @param x The minimum X coordinate of the pixel rectangle. + * @param y The minimum Y coordinate of the pixel rectangle. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param obj A primitive array containing pixel data. + * @param data The DataBuffer containing the image data. + * @see #getNumDataElements + * @see #getTransferType + * @see #getDataElements(int, int, int, int, Object, DataBuffer) + * @see java.awt.image.DataBuffer + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are + * not in bounds, or if obj is too small to hold the input. + */ + public void setDataElements(int x, int y, int w, int h, + Object obj, DataBuffer data) { + + int cnt = 0; + Object o = null; + int type = getTransferType(); + int numDataElems = getNumDataElements(); + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] barray = (byte[])obj; + byte[] btemp = new byte[numDataElems]; + + for (int i=y; isetSample(int, int, int, DataBuffer) method using + * that int value. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param b The band to set. + * @param s The input sample as a float. + * @param data The DataBuffer containing the image data. + * @see #getSample(int, int, int, DataBuffer) + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds. + */ + public void setSample(int x, int y, int b, + float s , + DataBuffer data) { + int sample = (int)s; + + setSample(x, y, b, sample, data); + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using a double for input. + * The default implementation of this method casts the input + * double sample to an int and then calls the + * setSample(int, int, int, DataBuffer) method using + * that int value. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param b The band to set. + * @param s The input sample as a double. + * @param data The DataBuffer containing the image data. + * @see #getSample(int, int, int, DataBuffer) + * + * @throws NullPointerException if data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds. + */ + public void setSample(int x, int y, int b, + double s, + DataBuffer data) { + int sample = (int)s; + + setSample(x, y, b, sample, data); + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from an int array containing one sample per array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param b The band to set. + * @param iArray The input samples in an int array. + * @param data The DataBuffer containing the image data. + * @see #getSamples(int, int, int, int, int, int[], DataBuffer) + * + * @throws NullPointerException if iArray or data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if iArray is too small to + * hold the input. + */ + public void setSamples(int x, int y, int w, int h, int b, + int iArray[], DataBuffer data) { + + int Offset=0; + + for (int i=y; i<(y+h); i++) { + for (int j=x; j<(x+w); j++) { + setSample(j, i, b, iArray[Offset++], data); + } + } + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from a float array containing one sample per array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param b The band to set. + * @param fArray The input samples in a float array. + * @param data The DataBuffer containing the image data. + * @see #getSamples(int, int, int, int, int, float[], DataBuffer) + * + * @throws NullPointerException if fArray or data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if fArray is too small to + * hold the input. + */ + public void setSamples(int x, int y, int w, int h, int b, + float fArray[], DataBuffer data) { + int Offset=0; + + for (int i=y; i<(y+h); i++) { + for (int j=x; j<(x+w); j++) { + setSample(j, i, b, fArray[Offset++], data); + } + } + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from a double array containing one sample per array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param b The band to set. + * @param dArray The input samples in a double array. + * @param data The DataBuffer containing the image data. + * @see #getSamples(int, int, int, int, int, double[], DataBuffer) + * + * @throws NullPointerException if dArray or data is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if dArray is too small to + * hold the input. + */ + public void setSamples(int x, int y, int w, int h, int b, + double dArray[], DataBuffer data) { + int Offset=0; + + for (int i=y; i<(y+h); i++) { + for (int j=x; j<(x+w); j++) { + setSample(j, i, b, dArray[Offset++], data); + } + } + } + + /** + * Creates a SampleModel which describes data in this SampleModel's + * format, but with a different width and height. + * @param w the width of the image data + * @param h the height of the image data + * @return a SampleModel describing the same image + * data as this SampleModel, but with a + * different size. + */ + public abstract SampleModel createCompatibleSampleModel(int w, int h); + + /** + * Creates a new SampleModel + * with a subset of the bands of this + * SampleModel. + * @param bands the subset of bands of this SampleModel + * @return a SampleModel with a subset of bands of this + * SampleModel. + */ + public abstract SampleModel createSubsetSampleModel(int bands[]); + + /** + * Creates a DataBuffer that corresponds to this SampleModel. + * The DataBuffer's width and height will match this SampleModel's. + * @return a DataBuffer corresponding to this + * SampleModel. + */ + public abstract DataBuffer createDataBuffer(); + + /** Returns the size in bits of samples for all bands. + * @return the size of samples for all bands. + */ + public abstract int[] getSampleSize(); + + /** Returns the size in bits of samples for the specified band. + * @param band the specified band + * @return the size of the samples of the specified band. + */ + public abstract int getSampleSize(int band); + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/SinglePixelPackedSampleModel.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,805 @@ +/* + * Portions Copyright 1997-2001 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; + +import java.util.Arrays; + +/** + * This class represents pixel data packed such that the N samples which make + * up a single pixel are stored in a single data array element, and each data + * data array element holds samples for only one pixel. + * This class supports + * {@link DataBuffer#TYPE_BYTE TYPE_BYTE}, + * {@link DataBuffer#TYPE_USHORT TYPE_USHORT}, + * {@link DataBuffer#TYPE_INT TYPE_INT} data types. + * All data array elements reside + * in the first bank of a DataBuffer. Accessor methods are provided so + * that the image data can be manipulated directly. Scanline stride is the + * number of data array elements between a given sample and the corresponding + * sample in the same column of the next scanline. Bit masks are the masks + * required to extract the samples representing the bands of the pixel. + * Bit offsets are the offsets in bits into the data array + * element of the samples representing the bands of the pixel. + *

+ * The following code illustrates extracting the bits of the sample + * representing band b for pixel x,y + * from DataBuffer data: + *

+ *      int sample = data.getElem(y * scanlineStride + x);
+ *      sample = (sample & bitMasks[b]) >>> bitOffsets[b];
+ * 
+ */ + +public class SinglePixelPackedSampleModel extends SampleModel +{ + /** Bit masks for all bands of the image data. */ + private int bitMasks[]; + + /** Bit Offsets for all bands of the image data. */ + private int bitOffsets[]; + + /** Bit sizes for all the bands of the image data. */ + private int bitSizes[]; + + /** Maximum bit size. */ + private int maxBitSize; + + /** Line stride of the region of image data described by this + * SinglePixelPackedSampleModel. + */ + private int scanlineStride; + + private static native void initIDs(); + static { + ColorModel.loadLibraries(); + initIDs(); + } + + /** + * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands. + * Each sample is stored in a data array element in the position of + * its corresponding bit mask. Each bit mask must be contiguous and + * masks must not overlap. + * @param dataType The data type for storing samples. + * @param w The width (in pixels) of the region of the + * image data described. + * @param h The height (in pixels) of the region of the + * image data described. + * @param bitMasks The bit masks for all bands. + * @throws IllegalArgumentException if dataType is not + * either DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, or + * DataBuffer.TYPE_INT + */ + public SinglePixelPackedSampleModel(int dataType, int w, int h, + int bitMasks[]) { + this(dataType, w, h, w, bitMasks); + if (dataType != DataBuffer.TYPE_BYTE && + dataType != DataBuffer.TYPE_USHORT && + dataType != DataBuffer.TYPE_INT) { + throw new IllegalArgumentException("Unsupported data type "+ + dataType); + } + } + + /** + * Constructs a SinglePixelPackedSampleModel with bitMasks.length bands + * and a scanline stride equal to scanlineStride data array elements. + * Each sample is stored in a data array element in the position of + * its corresponding bit mask. Each bit mask must be contiguous and + * masks must not overlap. + * @param dataType The data type for storing samples. + * @param w The width (in pixels) of the region of + * image data described. + * @param h The height (in pixels) of the region of + * image data described. + * @param scanlineStride The line stride of the image data. + * @param bitMasks The bit masks for all bands. + * @throws IllegalArgumentException if w or + * h is not greater than 0 + * @throws IllegalArgumentException if any mask in + * bitMask is not contiguous + * @throws IllegalArgumentException if dataType is not + * either DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, or + * DataBuffer.TYPE_INT + */ + public SinglePixelPackedSampleModel(int dataType, int w, int h, + int scanlineStride, int bitMasks[]) { + super(dataType, w, h, bitMasks.length); + if (dataType != DataBuffer.TYPE_BYTE && + dataType != DataBuffer.TYPE_USHORT && + dataType != DataBuffer.TYPE_INT) { + throw new IllegalArgumentException("Unsupported data type "+ + dataType); + } + this.dataType = dataType; + this.bitMasks = (int[]) bitMasks.clone(); + this.scanlineStride = scanlineStride; + + this.bitOffsets = new int[numBands]; + this.bitSizes = new int[numBands]; + + this.maxBitSize = 0; + for (int i=0; i>> 1; + bitOffset++; + } + while ((mask & 1) == 1) { + mask = mask >>> 1; + bitSize++; + } + if (mask != 0) { + throw new IllegalArgumentException("Mask "+bitMasks[i]+ + " must be contiguous"); + } + } + bitOffsets[i] = bitOffset; + bitSizes[i] = bitSize; + if (bitSize > maxBitSize) { + maxBitSize = bitSize; + } + } + } + + /** + * Returns the number of data elements needed to transfer one pixel + * via the getDataElements and setDataElements methods. + * For a SinglePixelPackedSampleModel, this is one. + */ + public int getNumDataElements() { + return 1; + } + + /** + * Returns the size of the buffer (in data array elements) + * needed for a data buffer that matches this + * SinglePixelPackedSampleModel. + */ + private long getBufferSize() { + long size = scanlineStride * (height-1) + width; + return size; + } + + /** + * Creates a new SinglePixelPackedSampleModel with the specified + * width and height. The new SinglePixelPackedSampleModel will have the + * same storage data type and bit masks as this + * SinglePixelPackedSampleModel. + * @param w the width of the resulting SampleModel + * @param h the height of the resulting SampleModel + * @return a SinglePixelPackedSampleModel with the + * specified width and height. + * @throws IllegalArgumentException if w or + * h is not greater than 0 + */ + public SampleModel createCompatibleSampleModel(int w, int h) { + SampleModel sampleModel = new SinglePixelPackedSampleModel(dataType, w, h, + bitMasks); + return sampleModel; + } + + /** + * Creates a DataBuffer that corresponds to this + * SinglePixelPackedSampleModel. The DataBuffer's data type and size + * will be consistent with this SinglePixelPackedSampleModel. The + * DataBuffer will have a single bank. + */ + public DataBuffer createDataBuffer() { + DataBuffer dataBuffer = null; + + int size = (int)getBufferSize(); + switch (dataType) { + case DataBuffer.TYPE_BYTE: + dataBuffer = new DataBufferByte(size); + break; + case DataBuffer.TYPE_USHORT: + dataBuffer = new DataBufferUShort(size); + break; + case DataBuffer.TYPE_INT: + dataBuffer = new DataBufferInt(size); + break; + } + return dataBuffer; + } + + /** Returns the number of bits per sample for all bands. */ + public int[] getSampleSize() { + int mask; + int sampleSize[] = new int [numBands]; + for (int i=0; i>> bitOffsets[i]; + while ((mask & 1) != 0) { + sampleSize[i] ++; + mask = mask >>> 1; + } + } + + return sampleSize; + } + + /** Returns the number of bits per sample for the specified band. */ + public int getSampleSize(int band) { + int sampleSize = 0; + int mask = bitMasks[band] >>> bitOffsets[band]; + while ((mask & 1) != 0) { + sampleSize ++; + mask = mask >>> 1; + } + + return sampleSize; + } + + /** Returns the offset (in data array elements) of pixel (x,y). + * The data element containing pixel x,y + * can be retrieved from a DataBuffer data with a + * SinglePixelPackedSampleModel sppsm as: + *
+     *        data.getElem(sppsm.getOffset(x, y));
+     * 
+ * @param x the X coordinate of the specified pixel + * @param y the Y coordinate of the specified pixel + * @return the offset of the specified pixel. + */ + public int getOffset(int x, int y) { + int offset = y * scanlineStride + x; + return offset; + } + + /** Returns the bit offsets into the data array element representing + * a pixel for all bands. + * @return the bit offsets representing a pixel for all bands. + */ + public int [] getBitOffsets() { + return (int[])bitOffsets.clone(); + } + + /** Returns the bit masks for all bands. + * @return the bit masks for all bands. + */ + public int [] getBitMasks() { + return (int[])bitMasks.clone(); + } + + /** Returns the scanline stride of this SinglePixelPackedSampleModel. + * @return the scanline stride of this + * SinglePixelPackedSampleModel. + */ + public int getScanlineStride() { + return scanlineStride; + } + + /** + * This creates a new SinglePixelPackedSampleModel with a subset of the + * bands of this SinglePixelPackedSampleModel. The new + * SinglePixelPackedSampleModel can be used with any DataBuffer that the + * existing SinglePixelPackedSampleModel can be used with. The new + * SinglePixelPackedSampleModel/DataBuffer combination will represent + * an image with a subset of the bands of the original + * SinglePixelPackedSampleModel/DataBuffer combination. + * @exception RasterFormatException if the length of the bands argument is + * greater than the number of bands in + * the sample model. + */ + public SampleModel createSubsetSampleModel(int bands[]) { + if (bands.length > numBands) + throw new RasterFormatException("There are only " + + numBands + + " bands"); + int newBitMasks[] = new int[bands.length]; + for (int i=0; i + * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is described by + * SinglePixelPackedSampleModel sppsm1, to + * DataBuffer db2, whose storage layout is described by + * SinglePixelPackedSampleModel sppsm2. + * The transfer will generally be more efficient than using + * getPixel/setPixel. + *
+     *       SinglePixelPackedSampleModel sppsm1, sppsm2;
+     *       DataBufferInt db1, db2;
+     *       sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
+     *                              db1), db2);
+     * 
+ * Using getDataElements/setDataElements to transfer between two + * DataBuffer/SampleModel pairs is legitimate if the SampleModels have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * If obj is non-null, it should be a primitive array of type TransferType. + * Otherwise, a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if obj is non-null and is not large enough to hold + * the pixel data. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param obj If non-null, a primitive array in which to return + * the pixel data. + * @param data The DataBuffer containing the image data. + * @return the data for the specified pixel. + * @see #setDataElements(int, int, Object, DataBuffer) + */ + public Object getDataElements(int x, int y, Object obj, DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int type = getTransferType(); + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] bdata; + + if (obj == null) + bdata = new byte[1]; + else + bdata = (byte[])obj; + + bdata[0] = (byte)data.getElem(y * scanlineStride + x); + + obj = (Object)bdata; + break; + + case DataBuffer.TYPE_USHORT: + + short[] sdata; + + if (obj == null) + sdata = new short[1]; + else + sdata = (short[])obj; + + sdata[0] = (short)data.getElem(y * scanlineStride + x); + + obj = (Object)sdata; + break; + + case DataBuffer.TYPE_INT: + + int[] idata; + + if (obj == null) + idata = new int[1]; + else + idata = (int[])obj; + + idata[0] = data.getElem(y * scanlineStride + x); + + obj = (Object)idata; + break; + } + + return obj; + } + + /** + * Returns all samples in for the specified pixel in an int array. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param iArray If non-null, returns the samples in this array + * @param data The DataBuffer containing the image data. + * @return all samples for the specified pixel. + * @see #setPixel(int, int, int[], DataBuffer) + */ + public int [] getPixel(int x, int y, int iArray[], DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int pixels[]; + if (iArray == null) { + pixels = new int [numBands]; + } else { + pixels = iArray; + } + + int value = data.getElem(y * scanlineStride + x); + for (int i=0; i>> bitOffsets[i]; + } + return pixels; + } + + /** + * Returns all samples for the specified rectangle of pixels in + * an int array, one sample per array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param iArray If non-null, returns the samples in this array. + * @param data The DataBuffer containing the image data. + * @return all samples for the specified region of pixels. + * @see #setPixels(int, int, int, int, int[], DataBuffer) + */ + public int[] getPixels(int x, int y, int w, int h, + int iArray[], DataBuffer data) { + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int pixels[]; + if (iArray != null) { + pixels = iArray; + } else { + pixels = new int [w*h*numBands]; + } + int lineOffset = y*scanlineStride + x; + int dstOffset = 0; + + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + int value = data.getElem(lineOffset+j); + for (int k=0; k < numBands; k++) { + pixels[dstOffset++] = + ((value & bitMasks[k]) >>> bitOffsets[k]); + } + } + lineOffset += scanlineStride; + } + return pixels; + } + + /** + * Returns as int the sample in a specified band for the pixel + * located at (x,y). + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param b The band to return. + * @param data The DataBuffer containing the image data. + * @return the sample in a specified band for the specified + * pixel. + * @see #setSample(int, int, int, int, DataBuffer) + */ + public int getSample(int x, int y, int b, DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int sample = data.getElem(y * scanlineStride + x); + return ((sample & bitMasks[b]) >>> bitOffsets[b]); + } + + /** + * Returns the samples for a specified band for the specified rectangle + * of pixels in an int array, one sample per array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param b The band to return. + * @param iArray If non-null, returns the samples in this array. + * @param data The DataBuffer containing the image data. + * @return the samples for the specified band for the specified + * region of pixels. + * @see #setSamples(int, int, int, int, int, int[], DataBuffer) + */ + public int[] getSamples(int x, int y, int w, int h, int b, + int iArray[], DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int samples[]; + if (iArray != null) { + samples = iArray; + } else { + samples = new int [w*h]; + } + int lineOffset = y*scanlineStride + x; + int dstOffset = 0; + + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + int value = data.getElem(lineOffset+j); + samples[dstOffset++] = + ((value & bitMasks[b]) >>> bitOffsets[b]); + } + lineOffset += scanlineStride; + } + return samples; + } + + /** + * Sets the data for a single pixel in the specified DataBuffer from a + * primitive array of type TransferType. For a + * SinglePixelPackedSampleModel, only the first element of the array + * will hold valid data, and the type of the array must be the same as + * the storage data type of the SinglePixelPackedSampleModel. + *

+ * The following code illustrates transferring data for one pixel from + * DataBuffer db1, whose storage layout is described by + * SinglePixelPackedSampleModel sppsm1, + * to DataBuffer db2, whose storage layout is described by + * SinglePixelPackedSampleModel sppsm2. + * The transfer will generally be more efficient than using + * getPixel/setPixel. + *

+     *       SinglePixelPackedSampleModel sppsm1, sppsm2;
+     *       DataBufferInt db1, db2;
+     *       sppsm2.setDataElements(x, y, sppsm1.getDataElements(x, y, null,
+     *                              db1), db2);
+     * 
+ * Using getDataElements/setDataElements to transfer between two + * DataBuffer/SampleModel pairs is legitimate if the SampleModels have + * the same number of bands, corresponding bands have the same number of + * bits per sample, and the TransferTypes are the same. + *

+ * obj must be a primitive array of type TransferType. Otherwise, + * a ClassCastException is thrown. An + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if obj is not large enough to hold the pixel data. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param obj A primitive array containing pixel data. + * @param data The DataBuffer containing the image data. + * @see #getDataElements(int, int, Object, DataBuffer) + */ + public void setDataElements(int x, int y, Object obj, DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int type = getTransferType(); + + switch(type) { + + case DataBuffer.TYPE_BYTE: + + byte[] barray = (byte[])obj; + data.setElem(y*scanlineStride+x, ((int)barray[0])&0xff); + break; + + case DataBuffer.TYPE_USHORT: + + short[] sarray = (short[])obj; + data.setElem(y*scanlineStride+x, ((int)sarray[0])&0xffff); + break; + + case DataBuffer.TYPE_INT: + + int[] iarray = (int[])obj; + data.setElem(y*scanlineStride+x, iarray[0]); + break; + } + } + + /** + * Sets a pixel in the DataBuffer using an int array of samples for input. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param iArray The input samples in an int array. + * @param data The DataBuffer containing the image data. + * @see #getPixel(int, int, int[], DataBuffer) + */ + public void setPixel(int x, int y, + int iArray[], + DataBuffer data) { + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int lineOffset = y * scanlineStride + x; + int value = data.getElem(lineOffset); + for (int i=0; i < numBands; i++) { + value &= ~bitMasks[i]; + value |= ((iArray[i] << bitOffsets[i]) & bitMasks[i]); + } + data.setElem(lineOffset, value); + } + + /** + * Sets all samples for a rectangle of pixels from an int array containing + * one sample per array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param iArray The input samples in an int array. + * @param data The DataBuffer containing the image data. + * @see #getPixels(int, int, int, int, int[], DataBuffer) + */ + public void setPixels(int x, int y, int w, int h, + int iArray[], DataBuffer data) { + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int lineOffset = y*scanlineStride + x; + int srcOffset = 0; + + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + int value = data.getElem(lineOffset+j); + for (int k=0; k < numBands; k++) { + value &= ~bitMasks[k]; + int srcValue = iArray[srcOffset++]; + value |= ((srcValue << bitOffsets[k]) + & bitMasks[k]); + } + data.setElem(lineOffset+j, value); + } + lineOffset += scanlineStride; + } + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using an int for input. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param b The band to set. + * @param s The input sample as an int. + * @param data The DataBuffer containing the image data. + * @see #getSample(int, int, int, DataBuffer) + */ + public void setSample(int x, int y, int b, int s, + DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int value = data.getElem(y*scanlineStride + x); + value &= ~bitMasks[b]; + value |= (s << bitOffsets[b]) & bitMasks[b]; + data.setElem(y*scanlineStride + x,value); + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from an int array containing one sample per array element. + * ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w The width of the pixel rectangle. + * @param h The height of the pixel rectangle. + * @param b The band to set. + * @param iArray The input samples in an int array. + * @param data The DataBuffer containing the image data. + * @see #getSamples(int, int, int, int, int, int[], DataBuffer) + */ + public void setSamples(int x, int y, int w, int h, int b, + int iArray[], DataBuffer data) { + // Bounds check for 'b' will be performed automatically + if ((x < 0) || (y < 0) || (x + w > width) || (y + h > height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + int lineOffset = y*scanlineStride + x; + int srcOffset = 0; + + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + int value = data.getElem(lineOffset+j); + value &= ~bitMasks[b]; + int sample = iArray[srcOffset++]; + value |= ((int)sample << bitOffsets[b]) & bitMasks[b]; + data.setElem(lineOffset+j,value); + } + lineOffset += scanlineStride; + } + } + + public boolean equals(Object o) { + if ((o == null) || !(o instanceof SinglePixelPackedSampleModel)) { + return false; + } + + SinglePixelPackedSampleModel that = (SinglePixelPackedSampleModel)o; + return this.width == that.width && + this.height == that.height && + this.numBands == that.numBands && + this.dataType == that.dataType && + Arrays.equals(this.bitMasks, that.bitMasks) && + Arrays.equals(this.bitOffsets, that.bitOffsets) && + Arrays.equals(this.bitSizes, that.bitSizes) && + this.maxBitSize == that.maxBitSize && + this.scanlineStride == that.scanlineStride; + } + + // If we implement equals() we must also implement hashCode + public int hashCode() { + int hash = 0; + hash = width; + hash <<= 8; + hash ^= height; + hash <<= 8; + hash ^= numBands; + hash <<= 8; + hash ^= dataType; + hash <<= 8; + for (int i = 0; i < bitMasks.length; i++) { + hash ^= bitMasks[i]; + hash <<= 8; + } + for (int i = 0; i < bitOffsets.length; i++) { + hash ^= bitOffsets[i]; + hash <<= 8; + } + for (int i = 0; i < bitSizes.length; i++) { + hash ^= bitSizes[i]; + hash <<= 8; + } + hash ^= maxBitSize; + hash <<= 8; + hash ^= scanlineStride; + return hash; + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/WritableRaster.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/WritableRaster.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,741 @@ +/* + * Portions Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; +import java.awt.Rectangle; +import java.awt.Point; + +/** + * This class extends Raster to provide pixel writing capabilities. + * Refer to the class comment for Raster for descriptions of how + * a Raster stores pixels. + * + *

The constructors of this class are protected. To instantiate + * a WritableRaster, use one of the createWritableRaster factory methods + * in the Raster class. + */ +public class WritableRaster extends Raster { + + /** + * Constructs a WritableRaster with the given SampleModel. The + * WritableRaster's upper left corner is origin and it is the + * same size as the SampleModel. A DataBuffer large enough to + * describe the WritableRaster is automatically created. + * @param sampleModel The SampleModel that specifies the layout. + * @param origin The Point that specifies the origin. + * @throws RasterFormatException if computing either + * origin.x + sampleModel.getWidth() or + * origin.y + sampleModel.getHeight() results + * in integer overflow + */ + protected WritableRaster(SampleModel sampleModel, + Point origin) { + this(sampleModel, + sampleModel.createDataBuffer(), + new Rectangle(origin.x, + origin.y, + sampleModel.getWidth(), + sampleModel.getHeight()), + origin, + null); + } + + /** + * Constructs a WritableRaster with the given SampleModel and DataBuffer. + * The WritableRaster's upper left corner is origin and it is the same + * size as the SampleModel. The DataBuffer is not initialized and must + * be compatible with SampleModel. + * @param sampleModel The SampleModel that specifies the layout. + * @param dataBuffer The DataBuffer that contains the image data. + * @param origin The Point that specifies the origin. + * @throws RasterFormatException if computing either + * origin.x + sampleModel.getWidth() or + * origin.y + sampleModel.getHeight() results + * in integer overflow + */ + protected WritableRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Point origin) { + this(sampleModel, + dataBuffer, + new Rectangle(origin.x, + origin.y, + sampleModel.getWidth(), + sampleModel.getHeight()), + origin, + null); + } + + /** + * Constructs a WritableRaster with the given SampleModel, DataBuffer, + * and parent. aRegion specifies the bounding rectangle of the new + * Raster. When translated into the base Raster's coordinate + * system, aRegion must be contained by the base Raster. + * (The base Raster is the Raster's ancestor which has no parent.) + * sampleModelTranslate specifies the sampleModelTranslateX and + * sampleModelTranslateY values of the new Raster. + * + * Note that this constructor should generally be called by other + * constructors or create methods, it should not be used directly. + * @param sampleModel The SampleModel that specifies the layout. + * @param dataBuffer The DataBuffer that contains the image data. + * @param aRegion The Rectangle that specifies the image area. + * @param sampleModelTranslate The Point that specifies the translation + * from SampleModel to Raster coordinates. + * @param parent The parent (if any) of this raster. + * @throws RasterFormatException if aRegion has width + * or height less than or equal to zero, or computing either + * aRegion.x + aRegion.width or + * aRegion.y + aRegion.height results in integer + * overflow + */ + protected WritableRaster(SampleModel sampleModel, + DataBuffer dataBuffer, + Rectangle aRegion, + Point sampleModelTranslate, + WritableRaster parent){ + super(sampleModel,dataBuffer,aRegion,sampleModelTranslate,parent); + } + + /** Returns the parent WritableRaster (if any) of this WritableRaster, + * or else null. + * @return the parent of this WritableRaster, or + * null. + */ + public WritableRaster getWritableParent() { + return (WritableRaster)parent; + } + + /** + * Create a WritableRaster with the same size, SampleModel and DataBuffer + * as this one, but with a different location. The new WritableRaster + * will possess a reference to the current WritableRaster, accessible + * through its getParent() and getWritableParent() methods. + * + * @param childMinX X coord of the upper left corner of the new Raster. + * @param childMinY Y coord of the upper left corner of the new Raster. + * @return a WritableRaster the same as this one except + * for the specified location. + * @throws RasterFormatException if computing either + * childMinX + this.getWidth() or + * childMinY + this.getHeight() results in integer + * overflow + */ + public WritableRaster createWritableTranslatedChild(int childMinX, + int childMinY) { + return createWritableChild(minX,minY,width,height, + childMinX,childMinY,null); + } + + /** + * Returns a new WritableRaster which shares all or part of this + * WritableRaster's DataBuffer. The new WritableRaster will + * possess a reference to the current WritableRaster, accessible + * through its getParent() and getWritableParent() methods. + * + *

The parentX, parentY, width and height parameters form a + * Rectangle in this WritableRaster's coordinate space, indicating + * the area of pixels to be shared. An error will be thrown if + * this Rectangle is not contained with the bounds of the current + * WritableRaster. + * + *

The new WritableRaster may additionally be translated to a + * different coordinate system for the plane than that used by the current + * WritableRaster. The childMinX and childMinY parameters give + * the new (x, y) coordinate of the upper-left pixel of the + * returned WritableRaster; the coordinate (childMinX, childMinY) + * in the new WritableRaster will map to the same pixel as the + * coordinate (parentX, parentY) in the current WritableRaster. + * + *

The new WritableRaster may be defined to contain only a + * subset of the bands of the current WritableRaster, possibly + * reordered, by means of the bandList parameter. If bandList is + * null, it is taken to include all of the bands of the current + * WritableRaster in their current order. + * + *

To create a new WritableRaster that contains a subregion of + * the current WritableRaster, but shares its coordinate system + * and bands, this method should be called with childMinX equal to + * parentX, childMinY equal to parentY, and bandList equal to + * null. + * + * @param parentX X coordinate of the upper left corner in this + * WritableRaster's coordinates. + * @param parentY Y coordinate of the upper left corner in this + * WritableRaster's coordinates. + * @param w Width of the region starting at (parentX, parentY). + * @param h Height of the region starting at (parentX, parentY). + * @param childMinX X coordinate of the upper left corner of + * the returned WritableRaster. + * @param childMinY Y coordinate of the upper left corner of + * the returned WritableRaster. + * @param bandList Array of band indices, or null to use all bands. + * @return a WritableRaster sharing all or part of the + * DataBuffer of this WritableRaster. + * @exception RasterFormatException if the subregion is outside of the + * raster bounds. + * @throws RasterFormatException if w or + * h + * is less than or equal to zero, or computing any of + * parentX + w, parentY + h, + * childMinX + w, or + * childMinY + h results in integer + * overflow + */ + public WritableRaster createWritableChild(int parentX, int parentY, + int w, int h, + int childMinX, int childMinY, + int bandList[]) { + if (parentX < this.minX) { + throw new RasterFormatException("parentX lies outside raster"); + } + if (parentY < this.minY) { + throw new RasterFormatException("parentY lies outside raster"); + } + if ((parentX+w < parentX) || (parentX+w > this.width + this.minX)) { + throw new RasterFormatException("(parentX + width) is outside raster"); + } + if ((parentY+h < parentY) || (parentY+h > this.height + this.minY)) { + throw new RasterFormatException("(parentY + height) is outside raster"); + } + + SampleModel sm; + // Note: the SampleModel for the child Raster should have the same + // width and height as that for the parent, since it represents + // the physical layout of the pixel data. The child Raster's width + // and height represent a "virtual" view of the pixel data, so + // they may be different than those of the SampleModel. + if (bandList != null) { + sm = sampleModel.createSubsetSampleModel(bandList); + } + else { + sm = sampleModel; + } + + int deltaX = childMinX - parentX; + int deltaY = childMinY - parentY; + + return new WritableRaster(sm, + getDataBuffer(), + new Rectangle(childMinX,childMinY, + w, h), + new Point(sampleModelTranslateX+deltaX, + sampleModelTranslateY+deltaY), + this); + } + + /** + * Sets the data for a single pixel from a + * primitive array of type TransferType. For image data supported by + * the Java 2D(tm) API, this will be one of DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, + * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array + * may be in a packed format, thus increasing efficiency for data + * transfers. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if inData is not large enough to hold the pixel data. + * However, explicit bounds checking is not guaranteed. + * A ClassCastException will be thrown if the input object is not null + * and references anything other than an array of TransferType. + * @see java.awt.image.SampleModel#setDataElements(int, int, Object, DataBuffer) + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param inData An object reference to an array of type defined by + * getTransferType() and length getNumDataElements() + * containing the pixel data to place at x,y. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if inData is too small to hold the input. + */ + public void setDataElements(int x, int y, Object inData) { + sampleModel.setDataElements(x-sampleModelTranslateX, + y-sampleModelTranslateY, + inData, dataBuffer); + } + + /** + * Sets the data for a rectangle of pixels from an input Raster. + * The input Raster must be compatible with this WritableRaster + * in that they must have the same number of bands, corresponding bands + * must have the same number of bits per sample, the TransferTypes + * and NumDataElements must be the same, and the packing used by + * the getDataElements/setDataElements must be identical. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param inRaster Raster containing data to place at x,y. + * + * @throws NullPointerException if inRaster is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds. + */ + public void setDataElements(int x, int y, Raster inRaster) { + int dstOffX = x+inRaster.getMinX(); + int dstOffY = y+inRaster.getMinY(); + int width = inRaster.getWidth(); + int height = inRaster.getHeight(); + if ((dstOffX < this.minX) || (dstOffY < this.minY) || + (dstOffX + width > this.minX + this.width) || + (dstOffY + height > this.minY + this.height)) { + throw new ArrayIndexOutOfBoundsException + ("Coordinate out of bounds!"); + } + + int srcOffX = inRaster.getMinX(); + int srcOffY = inRaster.getMinY(); + Object tdata = null; + + for (int startY=0; startY < height; startY++) { + tdata = inRaster.getDataElements(srcOffX, srcOffY+startY, + width, 1, tdata); + setDataElements(dstOffX, dstOffY+startY, + width, 1, tdata); + } + } + + /** + * Sets the data for a rectangle of pixels from a + * primitive array of type TransferType. For image data supported by + * the Java 2D API, this will be one of DataBuffer.TYPE_BYTE, + * DataBuffer.TYPE_USHORT, DataBuffer.TYPE_INT, DataBuffer.TYPE_SHORT, + * DataBuffer.TYPE_FLOAT, or DataBuffer.TYPE_DOUBLE. Data in the array + * may be in a packed format, thus increasing efficiency for data + * transfers. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds, or if inData is not large enough to hold the pixel data. + * However, explicit bounds checking is not guaranteed. + * A ClassCastException will be thrown if the input object is not null + * and references anything other than an array of TransferType. + * @see java.awt.image.SampleModel#setDataElements(int, int, int, int, Object, DataBuffer) + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param inData An object reference to an array of type defined by + * getTransferType() and length w*h*getNumDataElements() + * containing the pixel data to place between x,y and + * x+w-1, y+h-1. + * + * @throws NullPointerException if inData is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if inData is too small to hold the input. + */ + public void setDataElements(int x, int y, int w, int h, Object inData) { + sampleModel.setDataElements(x-sampleModelTranslateX, + y-sampleModelTranslateY, + w,h,inData,dataBuffer); + } + + /** + * Copies pixels from Raster srcRaster to this WritableRaster. Each pixel + * in srcRaster is copied to the same x,y address in this raster, unless + * the address falls outside the bounds of this raster. srcRaster + * must have the same number of bands as this WritableRaster. The + * copy is a simple copy of source samples to the corresponding destination + * samples. + *

+ * If all samples of both source and destination Rasters are of + * integral type and less than or equal to 32 bits in size, then calling + * this method is equivalent to executing the following code for all + * x,y addresses valid in both Rasters. + *

+     *       Raster srcRaster;
+     *       WritableRaster dstRaster;
+     *       for (int b = 0; b < srcRaster.getNumBands(); b++) {
+     *           dstRaster.setSample(x, y, b, srcRaster.getSample(x, y, b));
+     *       }
+     * 
+ * Thus, when copying an integral type source to an integral type + * destination, if the source sample size is greater than the destination + * sample size for a particular band, the high order bits of the source + * sample are truncated. If the source sample size is less than the + * destination size for a particular band, the high order bits of the + * destination are zero-extended or sign-extended depending on whether + * srcRaster's SampleModel treats the sample as a signed or unsigned + * quantity. + *

+ * When copying a float or double source to an integral type destination, + * each source sample is cast to the destination type. When copying an + * integral type source to a float or double destination, the source + * is first converted to a 32-bit int (if necessary), using the above + * rules for integral types, and then the int is cast to float or + * double. + *

+ * @param srcRaster The Raster from which to copy pixels. + * + * @throws NullPointerException if srcRaster is null. + */ + public void setRect(Raster srcRaster) { + setRect(0,0,srcRaster); + } + + /** + * Copies pixels from Raster srcRaster to this WritableRaster. + * For each (x, y) address in srcRaster, the corresponding pixel + * is copied to address (x+dx, y+dy) in this WritableRaster, + * unless (x+dx, y+dy) falls outside the bounds of this raster. + * srcRaster must have the same number of bands as this WritableRaster. + * The copy is a simple copy of source samples to the corresponding + * destination samples. For details, see + * {@link WritableRaster#setRect(Raster)}. + * + * @param dx The X translation factor from src space to dst space + * of the copy. + * @param dy The Y translation factor from src space to dst space + * of the copy. + * @param srcRaster The Raster from which to copy pixels. + * + * @throws NullPointerException if srcRaster is null. + */ + public void setRect(int dx, int dy, Raster srcRaster) { + int width = srcRaster.getWidth(); + int height = srcRaster.getHeight(); + int srcOffX = srcRaster.getMinX(); + int srcOffY = srcRaster.getMinY(); + int dstOffX = dx+srcOffX; + int dstOffY = dy+srcOffY; + + // Clip to this raster + if (dstOffX < this.minX) { + int skipX = this.minX - dstOffX; + width -= skipX; + srcOffX += skipX; + dstOffX = this.minX; + } + if (dstOffY < this.minY) { + int skipY = this.minY - dstOffY; + height -= skipY; + srcOffY += skipY; + dstOffY = this.minY; + } + if (dstOffX+width > this.minX+this.width) { + width = this.minX + this.width - dstOffX; + } + if (dstOffY+height > this.minY+this.height) { + height = this.minY + this.height - dstOffY; + } + + if (width <= 0 || height <= 0) { + return; + } + + switch (srcRaster.getSampleModel().getDataType()) { + case DataBuffer.TYPE_BYTE: + case DataBuffer.TYPE_SHORT: + case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_INT: + int[] iData = null; + for (int startY=0; startY < height; startY++) { + // Grab one scanline at a time + iData = + srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1, + iData); + setPixels(dstOffX, dstOffY+startY, width, 1, iData); + } + break; + + case DataBuffer.TYPE_FLOAT: + float[] fData = null; + for (int startY=0; startY < height; startY++) { + fData = + srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1, + fData); + setPixels(dstOffX, dstOffY+startY, width, 1, fData); + } + break; + + case DataBuffer.TYPE_DOUBLE: + double[] dData = null; + for (int startY=0; startY < height; startY++) { + // Grab one scanline at a time + dData = + srcRaster.getPixels(srcOffX, srcOffY+startY, width, 1, + dData); + setPixels(dstOffX, dstOffY+startY, width, 1, dData); + } + break; + } + } + + /** + * Sets a pixel in the DataBuffer using an int array of samples for input. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param iArray The input samples in a int array. + * + * @throws NullPointerException if iArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if iArray is too small to hold the input. + */ + public void setPixel(int x, int y, int iArray[]) { + sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY, + iArray,dataBuffer); + } + + /** + * Sets a pixel in the DataBuffer using a float array of samples for input. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param fArray The input samples in a float array. + * + * @throws NullPointerException if fArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if fArray is too small to hold the input. + */ + public void setPixel(int x, int y, float fArray[]) { + sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY, + fArray,dataBuffer); + } + + /** + * Sets a pixel in the DataBuffer using a double array of samples for input. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param dArray The input samples in a double array. + * + * @throws NullPointerException if dArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if dArray is too small to hold the input. + */ + public void setPixel(int x, int y, double dArray[]) { + sampleModel.setPixel(x-sampleModelTranslateX,y-sampleModelTranslateY, + dArray,dataBuffer); + } + + /** + * Sets all samples for a rectangle of pixels from an int array containing + * one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param iArray The input int pixel array. + * + * @throws NullPointerException if iArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if iArray is too small to hold the input. + */ + public void setPixels(int x, int y, int w, int h, int iArray[]) { + sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY, + w,h,iArray,dataBuffer); + } + + /** + * Sets all samples for a rectangle of pixels from a float array containing + * one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param fArray The input float pixel array. + * + * @throws NullPointerException if fArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if fArray is too small to hold the input. + */ + public void setPixels(int x, int y, int w, int h, float fArray[]) { + sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY, + w,h,fArray,dataBuffer); + } + + /** + * Sets all samples for a rectangle of pixels from a double array containing + * one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param dArray The input double pixel array. + * + * @throws NullPointerException if dArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates are not + * in bounds, or if dArray is too small to hold the input. + */ + public void setPixels(int x, int y, int w, int h, double dArray[]) { + sampleModel.setPixels(x-sampleModelTranslateX,y-sampleModelTranslateY, + w,h,dArray,dataBuffer); + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using an int for input. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param b The band to set. + * @param s The input sample. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds. + */ + public void setSample(int x, int y, int b, int s) { + sampleModel.setSample(x-sampleModelTranslateX, + y-sampleModelTranslateY, b, s, + dataBuffer); + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using a float for input. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param b The band to set. + * @param s The input sample as a float. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds. + */ + public void setSample(int x, int y, int b, float s){ + sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY, + b,s,dataBuffer); + } + + /** + * Sets a sample in the specified band for the pixel located at (x,y) + * in the DataBuffer using a double for input. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the pixel location. + * @param y The Y coordinate of the pixel location. + * @param b The band to set. + * @param s The input sample as a double. + * + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds. + */ + public void setSample(int x, int y, int b, double s){ + sampleModel.setSample(x-sampleModelTranslateX,y-sampleModelTranslateY, + b,s,dataBuffer); + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from an int array containing one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param b The band to set. + * @param iArray The input int sample array. + * + * @throws NullPointerException if iArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if iArray is too small to + * hold the input. + */ + public void setSamples(int x, int y, int w, int h, int b, + int iArray[]) { + sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY, + w,h,b,iArray,dataBuffer); + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from a float array containing one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param b The band to set. + * @param fArray The input float sample array. + * + * @throws NullPointerException if fArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if fArray is too small to + * hold the input. + */ + public void setSamples(int x, int y, int w, int h, int b, + float fArray[]) { + sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY, + w,h,b,fArray,dataBuffer); + } + + /** + * Sets the samples in the specified band for the specified rectangle + * of pixels from a double array containing one sample per array element. + * An ArrayIndexOutOfBoundsException may be thrown if the coordinates are + * not in bounds. + * However, explicit bounds checking is not guaranteed. + * @param x The X coordinate of the upper left pixel location. + * @param y The Y coordinate of the upper left pixel location. + * @param w Width of the pixel rectangle. + * @param h Height of the pixel rectangle. + * @param b The band to set. + * @param dArray The input double sample array. + * + * @throws NullPointerException if dArray is null. + * @throws ArrayIndexOutOfBoundsException if the coordinates or + * the band index are not in bounds, or if dArray is too small to + * hold the input. + */ + public void setSamples(int x, int y, int w, int h, int b, + double dArray[]) { + sampleModel.setSamples(x-sampleModelTranslateX,y-sampleModelTranslateY, + w,h,b,dArray,dataBuffer); + } + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/WritableRenderedImage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/WritableRenderedImage.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,151 @@ +/* + * Portions Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* **************************************************************** + ****************************************************************** + ****************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 + *** As an unpublished work pursuant to Title 17 of the United + *** States Code. All rights reserved. + ****************************************************************** + ****************************************************************** + ******************************************************************/ + +package java.awt.image; +import java.awt.Point; + +/** + * WriteableRenderedImage is a common interface for objects which + * contain or can produce image data in the form of Rasters and + * which can be modified and/or written over. The image + * data may be stored/produced as a single tile or a regular array + * of tiles. + *

+ * WritableRenderedImage provides notification to other interested + * objects when a tile is checked out for writing (via the + * getWritableTile method) and when the last writer of a particular + * tile relinquishes its access (via a call to releaseWritableTile). + * Additionally, it allows any caller to determine whether any tiles + * are currently checked out (via hasTileWriters), and to obtain a + * list of such tiles (via getWritableTileIndices, in the form of a Vector + * of Point objects). + *

+ * Objects wishing to be notified of changes in tile writability must + * implement the TileObserver interface, and are added by a + * call to addTileObserver. Multiple calls to + * addTileObserver for the same object will result in multiple + * notifications. An existing observer may reduce its notifications + * by calling removeTileObserver; if the observer had no + * notifications the operation is a no-op. + *

+ * It is necessary for a WritableRenderedImage to ensure that + * notifications occur only when the first writer acquires a tile and + * the last writer releases it. + * + */ + +public interface WritableRenderedImage extends RenderedImage +{ + + /** + * Adds an observer. If the observer is already present, + * it will receive multiple notifications. + * @param to the specified TileObserver + */ + public void addTileObserver(TileObserver to); + + /** + * Removes an observer. If the observer was not registered, + * nothing happens. If the observer was registered for multiple + * notifications, it will now be registered for one fewer. + * @param to the specified TileObserver + */ + public void removeTileObserver(TileObserver to); + + /** + * Checks out a tile for writing. + * + * The WritableRenderedImage is responsible for notifying all + * of its TileObservers when a tile goes from having + * no writers to having one writer. + * + * @param tileX the X index of the tile. + * @param tileY the Y index of the tile. + * @return a writable tile. + */ + public WritableRaster getWritableTile(int tileX, int tileY); + + /** + * Relinquishes the right to write to a tile. If the caller + * continues to write to the tile, the results are undefined. + * Calls to this method should only appear in matching pairs + * with calls to getWritableTile; any other use will lead + * to undefined results. + * + * The WritableRenderedImage is responsible for notifying all of + * its TileObservers when a tile goes from having one writer + * to having no writers. + * + * @param tileX the X index of the tile. + * @param tileY the Y index of the tile. + */ + public void releaseWritableTile(int tileX, int tileY); + + /** + * Returns whether a tile is currently checked out for writing. + * + * @param tileX the X index of the tile. + * @param tileY the Y index of the tile. + * @return true if specified tile is checked out + * for writing; false otherwise. + */ + public boolean isTileWritable(int tileX, int tileY); + + /** + * Returns an array of Point objects indicating which tiles + * are checked out for writing. Returns null if none are + * checked out. + * @return an array containing the locations of tiles that are + * checked out for writing. + */ + public Point[] getWritableTileIndices(); + + /** + * Returns whether any tile is checked out for writing. + * Semantically equivalent to (getWritableTileIndices() != null). + * @return true if any tiles are checked out for + * writing; false otherwise. + */ + public boolean hasTileWriters(); + + /** + * Sets a rect of the image to the contents of the Raster r, which is + * assumed to be in the same coordinate space as the WritableRenderedImage. + * The operation is clipped to the bounds of the WritableRenderedImage. + * @param r the specified Raster + */ + public void setData(Raster r); + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/renderable/ContextualRenderedImageFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/renderable/ContextualRenderedImageFactory.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,143 @@ +/* + * Portions Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* ******************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.image.renderable; +import java.awt.geom.Rectangle2D; +import java.awt.image.RenderedImage; + +/** + * ContextualRenderedImageFactory provides an interface for the + * functionality that may differ between instances of + * RenderableImageOp. Thus different operations on RenderableImages + * may be performed by a single class such as RenderedImageOp through + * the use of multiple instances of ContextualRenderedImageFactory. + * The name ContextualRenderedImageFactory is commonly shortened to + * "CRIF." + * + *

All operations that are to be used in a rendering-independent + * chain must implement ContextualRenderedImageFactory. + * + *

Classes that implement this interface must provide a + * constructor with no arguments. + */ +public interface ContextualRenderedImageFactory extends RenderedImageFactory { + + /** + * Maps the operation's output RenderContext into a RenderContext + * for each of the operation's sources. This is useful for + * operations that can be expressed in whole or in part simply as + * alterations in the RenderContext, such as an affine mapping, or + * operations that wish to obtain lower quality renderings of + * their sources in order to save processing effort or + * transmission bandwith. Some operations, such as blur, can also + * use this mechanism to avoid obtaining sources of higher quality + * than necessary. + * + * @param i the index of the source image. + * @param renderContext the RenderContext being applied to the operation. + * @param paramBlock a ParameterBlock containing the operation's + * sources and parameters. + * @param image the RenderableImage being rendered. + * @return a RenderContext for + * the source at the specified index of the parameters + * Vector contained in the specified ParameterBlock. + */ + RenderContext mapRenderContext(int i, + RenderContext renderContext, + ParameterBlock paramBlock, + RenderableImage image); + + /** + * Creates a rendering, given a RenderContext and a ParameterBlock + * containing the operation's sources and parameters. The output + * is a RenderedImage that takes the RenderContext into account to + * determine its dimensions and placement on the image plane. + * This method houses the "intelligence" that allows a + * rendering-independent operation to adapt to a specific + * RenderContext. + * + * @param renderContext The RenderContext specifying the rendering + * @param paramBlock a ParameterBlock containing the operation's + * sources and parameters + * @return a RenderedImage from the sources and parameters + * in the specified ParameterBlock and according to the + * rendering instructions in the specified RenderContext. + */ + RenderedImage create(RenderContext renderContext, + ParameterBlock paramBlock); + + /** + * Returns the bounding box for the output of the operation, + * performed on a given set of sources, in rendering-independent + * space. The bounds are returned as a Rectangle2D, that is, an + * axis-aligned rectangle with floating-point corner coordinates. + * + * @param paramBlock a ParameterBlock containing the operation's + * sources and parameters. + * @return a Rectangle2D specifying the rendering-independent + * bounding box of the output. + */ + Rectangle2D getBounds2D(ParameterBlock paramBlock); + + /** + * Gets the appropriate instance of the property specified by the name + * parameter. This method must determine which instance of a property to + * return when there are multiple sources that each specify the property. + * + * @param paramBlock a ParameterBlock containing the operation's + * sources and parameters. + * @param name a String naming the desired property. + * @return an object reference to the value of the property requested. + */ + Object getProperty(ParameterBlock paramBlock, String name); + + /** + * Returns a list of names recognized by getProperty. + * @return the list of property names. + */ + String[] getPropertyNames(); + + /** + * Returns true if successive renderings (that is, calls to + * create(RenderContext, ParameterBlock)) with the same arguments + * may produce different results. This method may be used to + * determine whether an existing rendering may be cached and + * reused. It is always safe to return true. + * @return true if successive renderings with the + * same arguments might produce different results; + * false otherwise. + */ + boolean isDynamic(); +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/renderable/RenderContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/renderable/RenderContext.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,272 @@ +/* + * Portions Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* ******************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.image.renderable; +import java.util.*; +import java.awt.geom.*; +import java.awt.*; +import java.awt.image.*; + +/** + * A RenderContext encapsulates the information needed to produce a + * specific rendering from a RenderableImage. It contains the area to + * be rendered specified in rendering-independent terms, the + * resolution at which the rendering is to be performed, and hints + * used to control the rendering process. + * + *

Users create RenderContexts and pass them to the + * RenderableImage via the createRendering method. Most of the methods of + * RenderContexts are not meant to be used directly by applications, + * but by the RenderableImage and operator classes to which it is + * passed. + * + *

The AffineTransform parameter passed into and out of this class + * are cloned. The RenderingHints and Shape parameters are not + * necessarily cloneable and are therefore only reference copied. + * Altering RenderingHints or Shape instances that are in use by + * instances of RenderContext may have undesired side effects. + */ +public class RenderContext implements Cloneable { + + /** Table of hints. May be null. */ + RenderingHints hints; + + /** Transform to convert user coordinates to device coordinates. */ + AffineTransform usr2dev; + + /** The area of interest. May be null. */ + Shape aoi; + + // Various constructors that allow different levels of + // specificity. If the Shape is missing the whole renderable area + // is assumed. If hints is missing no hints are assumed. + + /** + * Constructs a RenderContext with a given transform. + * The area of interest is supplied as a Shape, + * and the rendering hints are supplied as a RenderingHints object. + * + * @param usr2dev an AffineTransform. + * @param aoi a Shape representing the area of interest. + * @param hints a RenderingHints object containing rendering hints. + */ + public RenderContext(AffineTransform usr2dev, + Shape aoi, + RenderingHints hints) { + this.hints = hints; + this.aoi = aoi; + this.usr2dev = (AffineTransform)usr2dev.clone(); + } + + /** + * Constructs a RenderContext with a given transform. + * The area of interest is taken to be the entire renderable area. + * No rendering hints are used. + * + * @param usr2dev an AffineTransform. + */ + public RenderContext(AffineTransform usr2dev) { + this(usr2dev, null, null); + } + + /** + * Constructs a RenderContext with a given transform and rendering hints. + * The area of interest is taken to be the entire renderable area. + * + * @param usr2dev an AffineTransform. + * @param hints a RenderingHints object containing rendering hints. + */ + public RenderContext(AffineTransform usr2dev, RenderingHints hints) { + this(usr2dev, null, hints); + } + + /** + * Constructs a RenderContext with a given transform and area of interest. + * The area of interest is supplied as a Shape. + * No rendering hints are used. + * + * @param usr2dev an AffineTransform. + * @param aoi a Shape representing the area of interest. + */ + public RenderContext(AffineTransform usr2dev, Shape aoi) { + this(usr2dev, aoi, null); + } + + /** + * Gets the rendering hints of this RenderContext. + * @return a RenderingHints object that represents + * the rendering hints of this RenderContext. + * @see #setRenderingHints(RenderingHints) + */ + public RenderingHints getRenderingHints() { + return hints; + } + + /** + * Sets the rendering hints of this RenderContext. + * @param hints a RenderingHints object that represents + * the rendering hints to assign to this RenderContext. + * @see #getRenderingHints + */ + public void setRenderingHints(RenderingHints hints) { + this.hints = hints; + } + + /** + * Sets the current user-to-device AffineTransform contained + * in the RenderContext to a given transform. + * + * @param newTransform the new AffineTransform. + * @see #getTransform + */ + public void setTransform(AffineTransform newTransform) { + usr2dev = (AffineTransform)newTransform.clone(); + } + + /** + * Modifies the current user-to-device transform by prepending another + * transform. In matrix notation the operation is: + *

+     * [this] = [modTransform] x [this]
+     * 
+ * + * @param modTransform the AffineTransform to prepend to the + * current usr2dev transform. + * @since 1.3 + */ + public void preConcatenateTransform(AffineTransform modTransform) { + this.preConcetenateTransform(modTransform); + } + + /** + * Modifies the current user-to-device transform by prepending another + * transform. In matrix notation the operation is: + *
+     * [this] = [modTransform] x [this]
+     * 
+ * This method does the same thing as the preConcatenateTransform + * method. It is here for backward compatibility with previous releases + * which misspelled the method name. + * + * @param modTransform the AffineTransform to prepend to the + * current usr2dev transform. + * @deprecated replaced by + * preConcatenateTransform(AffineTransform). + */ + @Deprecated + public void preConcetenateTransform(AffineTransform modTransform) { + usr2dev.preConcatenate(modTransform); + } + + /** + * Modifies the current user-to-device transform by appending another + * transform. In matrix notation the operation is: + *
+     * [this] = [this] x [modTransform]
+     * 
+ * + * @param modTransform the AffineTransform to append to the + * current usr2dev transform. + * @since 1.3 + */ + public void concatenateTransform(AffineTransform modTransform) { + this.concetenateTransform(modTransform); + } + + /** + * Modifies the current user-to-device transform by appending another + * transform. In matrix notation the operation is: + *
+     * [this] = [this] x [modTransform]
+     * 
+ * This method does the same thing as the concatenateTransform + * method. It is here for backward compatibility with previous releases + * which misspelled the method name. + * + * @param modTransform the AffineTransform to append to the + * current usr2dev transform. + * @deprecated replaced by + * concatenateTransform(AffineTransform). + */ + @Deprecated + public void concetenateTransform(AffineTransform modTransform) { + usr2dev.concatenate(modTransform); + } + + /** + * Gets the current user-to-device AffineTransform. + * + * @return a reference to the current AffineTransform. + * @see #setTransform(AffineTransform) + */ + public AffineTransform getTransform() { + return (AffineTransform)usr2dev.clone(); + } + + /** + * Sets the current area of interest. The old area is discarded. + * + * @param newAoi The new area of interest. + * @see #getAreaOfInterest + */ + public void setAreaOfInterest(Shape newAoi) { + aoi = newAoi; + } + + /** + * Gets the ares of interest currently contained in the + * RenderContext. + * + * @return a reference to the area of interest of the RenderContext, + * or null if none is specified. + * @see #setAreaOfInterest(Shape) + */ + public Shape getAreaOfInterest() { + return aoi; + } + + /** + * Makes a copy of a RenderContext. The area of interest is copied + * by reference. The usr2dev AffineTransform and hints are cloned, + * while the area of interest is copied by reference. + * + * @return the new cloned RenderContext. + */ + public Object clone() { + RenderContext newRenderContext = new RenderContext(usr2dev, + aoi, hints); + return newRenderContext; + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/renderable/RenderableImage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/renderable/RenderableImage.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,198 @@ +/* + * Portions Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* ******************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.image.renderable; +import java.util.Vector; +import java.awt.RenderingHints; +import java.awt.image.*; + +/** + * A RenderableImage is a common interface for rendering-independent + * images (a notion which subsumes resolution independence). That is, + * images which are described and have operations applied to them + * independent of any specific rendering of the image. For example, a + * RenderableImage can be rotated and cropped in + * resolution-independent terms. Then, it can be rendered for various + * specific contexts, such as a draft preview, a high-quality screen + * display, or a printer, each in an optimal fashion. + * + *

A RenderedImage is returned from a RenderableImage via the + * createRendering() method, which takes a RenderContext. The + * RenderContext specifies how the RenderedImage should be + * constructed. Note that it is not possible to extract pixels + * directly from a RenderableImage. + * + *

The createDefaultRendering() and createScaledRendering() methods are + * convenience methods that construct an appropriate RenderContext + * internally. All of the rendering methods may return a reference to a + * previously produced rendering. + */ +public interface RenderableImage { + + /** + * String constant that can be used to identify a property on + * a RenderedImage obtained via the createRendering or + * createScaledRendering methods. If such a property exists, + * the value of the propoery will be a RenderingHints object + * specifying which hints were observed in creating the rendering. + */ + static final String HINTS_OBSERVED = "HINTS_OBSERVED"; + + /** + * Returns a vector of RenderableImages that are the sources of + * image data for this RenderableImage. Note that this method may + * return an empty vector, to indicate that the image has no sources, + * or null, to indicate that no information is available. + * + * @return a (possibly empty) Vector of RenderableImages, or null. + */ + Vector getSources(); + + /** + * Gets a property from the property set of this image. + * If the property name is not recognized, java.awt.Image.UndefinedProperty + * will be returned. + * + * @param name the name of the property to get, as a String. + * @return a reference to the property Object, or the value + * java.awt.Image.UndefinedProperty. + */ + Object getProperty(String name); + + /** + * Returns a list of names recognized by getProperty. + * @return a list of property names. + */ + String[] getPropertyNames(); + + /** + * Returns true if successive renderings (that is, calls to + * createRendering() or createScaledRendering()) with the same arguments + * may produce different results. This method may be used to + * determine whether an existing rendering may be cached and + * reused. It is always safe to return true. + * @return true if successive renderings with the + * same arguments might produce different results; + * false otherwise. + */ + boolean isDynamic(); + + /** + * Gets the width in user coordinate space. By convention, the + * usual width of a RenderableImage is equal to the image's aspect + * ratio (width divided by height). + * + * @return the width of the image in user coordinates. + */ + float getWidth(); + + /** + * Gets the height in user coordinate space. By convention, the + * usual height of a RenderedImage is equal to 1.0F. + * + * @return the height of the image in user coordinates. + */ + float getHeight(); + + /** + * Gets the minimum X coordinate of the rendering-independent image data. + * @return the minimum X coordinate of the rendering-independent image + * data. + */ + float getMinX(); + + /** + * Gets the minimum Y coordinate of the rendering-independent image data. + * @return the minimum Y coordinate of the rendering-independent image + * data. + */ + float getMinY(); + + /** + * Creates a RenderedImage instance of this image with width w, and + * height h in pixels. The RenderContext is built automatically + * with an appropriate usr2dev transform and an area of interest + * of the full image. All the rendering hints come from hints + * passed in. + * + *

If w == 0, it will be taken to equal + * Math.round(h*(getWidth()/getHeight())). + * Similarly, if h == 0, it will be taken to equal + * Math.round(w*(getHeight()/getWidth())). One of + * w or h must be non-zero or else an IllegalArgumentException + * will be thrown. + * + *

The created RenderedImage may have a property identified + * by the String HINTS_OBSERVED to indicate which RenderingHints + * were used to create the image. In addition any RenderedImages + * that are obtained via the getSources() method on the created + * RenderedImage may have such a property. + * + * @param w the width of rendered image in pixels, or 0. + * @param h the height of rendered image in pixels, or 0. + * @param hints a RenderingHints object containg hints. + * @return a RenderedImage containing the rendered data. + */ + RenderedImage createScaledRendering(int w, int h, RenderingHints hints); + + /** + * Returnd a RenderedImage instance of this image with a default + * width and height in pixels. The RenderContext is built + * automatically with an appropriate usr2dev transform and an area + * of interest of the full image. The rendering hints are + * empty. createDefaultRendering may make use of a stored + * rendering for speed. + * + * @return a RenderedImage containing the rendered data. + */ + RenderedImage createDefaultRendering(); + + /** + * Creates a RenderedImage that represented a rendering of this image + * using a given RenderContext. This is the most general way to obtain a + * rendering of a RenderableImage. + * + *

The created RenderedImage may have a property identified + * by the String HINTS_OBSERVED to indicate which RenderingHints + * (from the RenderContext) were used to create the image. + * In addition any RenderedImages + * that are obtained via the getSources() method on the created + * RenderedImage may have such a property. + * + * @param renderContext the RenderContext to use to produce the rendering. + * @return a RenderedImage containing the rendered data. + */ + RenderedImage createRendering(RenderContext renderContext); +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/renderable/RenderableImageOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/renderable/RenderableImageOp.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,350 @@ +/* + * Portions Copyright 1998-2000 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* ******************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.image.renderable; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.RenderedImage; +import java.awt.RenderingHints; +import java.util.Hashtable; +import java.util.Vector; + +/** + * This class handles the renderable aspects of an operation with help + * from its associated instance of a ContextualRenderedImageFactory. + */ +public class RenderableImageOp implements RenderableImage { + + /** A ParameterBlock containing source and parameters. */ + ParameterBlock paramBlock; + + /** The associated ContextualRenderedImageFactory. */ + ContextualRenderedImageFactory myCRIF; + + /** The bounding box of the results of this RenderableImageOp. */ + Rectangle2D boundingBox; + + + /** + * Constructs a RenderedImageOp given a + * ContextualRenderedImageFactory object, and + * a ParameterBlock containing RenderableImage sources and other + * parameters. Any RenderedImage sources referenced by the + * ParameterBlock will be ignored. + * + * @param CRIF a ContextualRenderedImageFactory object + * @param paramBlock a ParameterBlock containing this operation's source + * images and other parameters necessary for the operation + * to run. + */ + public RenderableImageOp(ContextualRenderedImageFactory CRIF, + ParameterBlock paramBlock) { + this.myCRIF = CRIF; + this.paramBlock = (ParameterBlock) paramBlock.clone(); + } + + /** + * Returns a vector of RenderableImages that are the sources of + * image data for this RenderableImage. Note that this method may + * return an empty vector, to indicate that the image has no sources, + * or null, to indicate that no information is available. + * + * @return a (possibly empty) Vector of RenderableImages, or null. + */ + public Vector getSources() { + return getRenderableSources(); + } + + private Vector getRenderableSources() { + Vector sources = null; + + if (paramBlock.getNumSources() > 0) { + sources = new Vector(); + int i = 0; + while (i < paramBlock.getNumSources()) { + Object o = paramBlock.getSource(i); + if (o instanceof RenderableImage) { + sources.add((RenderableImage)o); + i++; + } else { + break; + } + } + } + return sources; + } + + /** + * Gets a property from the property set of this image. + * If the property name is not recognized, java.awt.Image.UndefinedProperty + * will be returned. + * + * @param name the name of the property to get, as a String. + * @return a reference to the property Object, or the value + * java.awt.Image.UndefinedProperty. + */ + public Object getProperty(String name) { + return myCRIF.getProperty(paramBlock, name); + } + + /** + * Return a list of names recognized by getProperty. + * @return a list of property names. + */ + public String[] getPropertyNames() { + return myCRIF.getPropertyNames(); + } + + /** + * Returns true if successive renderings (that is, calls to + * createRendering() or createScaledRendering()) with the same arguments + * may produce different results. This method may be used to + * determine whether an existing rendering may be cached and + * reused. The CRIF's isDynamic method will be called. + * @return true if successive renderings with the + * same arguments might produce different results; + * false otherwise. + */ + public boolean isDynamic() { + return myCRIF.isDynamic(); + } + + /** + * Gets the width in user coordinate space. By convention, the + * usual width of a RenderableImage is equal to the image's aspect + * ratio (width divided by height). + * + * @return the width of the image in user coordinates. + */ + public float getWidth() { + if (boundingBox == null) { + boundingBox = myCRIF.getBounds2D(paramBlock); + } + return (float)boundingBox.getWidth(); + } + + /** + * Gets the height in user coordinate space. By convention, the + * usual height of a RenderedImage is equal to 1.0F. + * + * @return the height of the image in user coordinates. + */ + public float getHeight() { + if (boundingBox == null) { + boundingBox = myCRIF.getBounds2D(paramBlock); + } + return (float)boundingBox.getHeight(); + } + + /** + * Gets the minimum X coordinate of the rendering-independent image data. + */ + public float getMinX() { + if (boundingBox == null) { + boundingBox = myCRIF.getBounds2D(paramBlock); + } + return (float)boundingBox.getMinX(); + } + + /** + * Gets the minimum Y coordinate of the rendering-independent image data. + */ + public float getMinY() { + if (boundingBox == null) { + boundingBox = myCRIF.getBounds2D(paramBlock); + } + return (float)boundingBox.getMinY(); + } + + /** + * Change the current ParameterBlock of the operation, allowing + * editing of image rendering chains. The effects of such a + * change will be visible when a new rendering is created from + * this RenderableImageOp or any dependent RenderableImageOp. + * + * @param paramBlock the new ParameterBlock. + * @return the old ParameterBlock. + * @see #getParameterBlock + */ + public ParameterBlock setParameterBlock(ParameterBlock paramBlock) { + ParameterBlock oldParamBlock = this.paramBlock; + this.paramBlock = (ParameterBlock)paramBlock.clone(); + return oldParamBlock; + } + + /** + * Returns a reference to the current parameter block. + * @return the ParameterBlock of this + * RenderableImageOp. + * @see #setParameterBlock(ParameterBlock) + */ + public ParameterBlock getParameterBlock() { + return paramBlock; + } + + /** + * Creates a RenderedImage instance of this image with width w, and + * height h in pixels. The RenderContext is built automatically + * with an appropriate usr2dev transform and an area of interest + * of the full image. All the rendering hints come from hints + * passed in. + * + *

If w == 0, it will be taken to equal + * Math.round(h*(getWidth()/getHeight())). + * Similarly, if h == 0, it will be taken to equal + * Math.round(w*(getHeight()/getWidth())). One of + * w or h must be non-zero or else an IllegalArgumentException + * will be thrown. + * + *

The created RenderedImage may have a property identified + * by the String HINTS_OBSERVED to indicate which RenderingHints + * were used to create the image. In addition any RenderedImages + * that are obtained via the getSources() method on the created + * RenderedImage may have such a property. + * + * @param w the width of rendered image in pixels, or 0. + * @param h the height of rendered image in pixels, or 0. + * @param hints a RenderingHints object containg hints. + * @return a RenderedImage containing the rendered data. + */ + public RenderedImage createScaledRendering(int w, int h, + RenderingHints hints) { + // DSR -- code to try to get a unit scale + double sx = (double)w/getWidth(); + double sy = (double)h/getHeight(); + if (Math.abs(sx/sy - 1.0) < 0.01) { + sx = sy; + } + AffineTransform usr2dev = AffineTransform.getScaleInstance(sx, sy); + RenderContext newRC = new RenderContext(usr2dev, hints); + return createRendering(newRC); + } + + /** + * Gets a RenderedImage instance of this image with a default + * width and height in pixels. The RenderContext is built + * automatically with an appropriate usr2dev transform and an area + * of interest of the full image. All the rendering hints come + * from hints passed in. Implementors of this interface must be + * sure that there is a defined default width and height. + * + * @return a RenderedImage containing the rendered data. + */ + public RenderedImage createDefaultRendering() { + AffineTransform usr2dev = new AffineTransform(); // Identity + RenderContext newRC = new RenderContext(usr2dev); + return createRendering(newRC); + } + + /** + * Creates a RenderedImage which represents this + * RenderableImageOp (including its Renderable sources) rendered + * according to the given RenderContext. + * + *

This method supports chaining of either Renderable or + * RenderedImage operations. If sources in + * the ParameterBlock used to construct the RenderableImageOp are + * RenderableImages, then a three step process is followed: + * + *

    + *
  1. mapRenderContext() is called on the associated CRIF for + * each RenderableImage source; + *
  2. createRendering() is called on each of the RenderableImage sources + * using the backwards-mapped RenderContexts obtained in step 1, + * resulting in a rendering of each source; + *
  3. ContextualRenderedImageFactory.create() is called + * with a new ParameterBlock containing the parameters of + * the RenderableImageOp and the RenderedImages that were created by the + * createRendering() calls. + *
+ * + *

If the elements of the source Vector of + * the ParameterBlock used to construct the RenderableImageOp are + * instances of RenderedImage, then the CRIF.create() method is + * called immediately using the original ParameterBlock. + * This provides a basis case for the recursion. + * + *

The created RenderedImage may have a property identified + * by the String HINTS_OBSERVED to indicate which RenderingHints + * (from the RenderContext) were used to create the image. + * In addition any RenderedImages + * that are obtained via the getSources() method on the created + * RenderedImage may have such a property. + * + * @param renderContext The RenderContext to use to perform the rendering. + * @return a RenderedImage containing the desired output image. + */ + public RenderedImage createRendering(RenderContext renderContext) { + RenderedImage image = null; + RenderContext rcOut = null; + + // Clone the original ParameterBlock; if the ParameterBlock + // contains RenderableImage sources, they will be replaced by + // RenderedImages. + ParameterBlock renderedParamBlock = (ParameterBlock)paramBlock.clone(); + Vector sources = getRenderableSources(); + + try { + // This assumes that if there is no renderable source, that there + // is a rendered source in paramBlock + + if (sources != null) { + Vector renderedSources = new Vector(); + for (int i = 0; i < sources.size(); i++) { + rcOut = myCRIF.mapRenderContext(i, renderContext, + paramBlock, this); + RenderedImage rdrdImage = + ((RenderableImage)sources.elementAt(i)).createRendering(rcOut); + if (rdrdImage == null) { + return null; + } + + // Add this rendered image to the ParameterBlock's + // list of RenderedImages. + renderedSources.addElement(rdrdImage); + } + + if (renderedSources.size() > 0) { + renderedParamBlock.setSources(renderedSources); + } + } + + return myCRIF.create(renderContext, renderedParamBlock); + } catch (ArrayIndexOutOfBoundsException e) { + // This should never happen + return null; + } + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/renderable/RenderableImageProducer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/renderable/RenderableImageProducer.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,219 @@ +/* + * Portions Copyright 1998 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* ******************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.image.renderable; +import java.awt.color.ColorSpace; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.DirectColorModel; +import java.awt.image.ImageConsumer; +import java.awt.image.ImageProducer; +import java.awt.image.Raster; +import java.awt.image.RenderedImage; +import java.awt.image.SampleModel; +import java.util.Enumeration; +import java.util.Vector; + +/** + * An adapter class that implements ImageProducer to allow the + * asynchronous production of a RenderableImage. The size of the + * ImageConsumer is determined by the scale factor of the usr2dev + * transform in the RenderContext. If the RenderContext is null, the + * default rendering of the RenderableImage is used. This class + * implements an asynchronous production that produces the image in + * one thread at one resolution. This class may be subclassed to + * implement versions that will render the image using several + * threads. These threads could render either the same image at + * progressively better quality, or different sections of the image at + * a single resolution. + */ +public class RenderableImageProducer implements ImageProducer, Runnable { + + /** The RenderableImage source for the producer. */ + RenderableImage rdblImage; + + /** The RenderContext to use for producing the image. */ + RenderContext rc; + + /** A Vector of image consumers. */ + Vector ics = new Vector(); + + /** + * Constructs a new RenderableImageProducer from a RenderableImage + * and a RenderContext. + * + * @param rdblImage the RenderableImage to be rendered. + * @param rc the RenderContext to use for producing the pixels. + */ + public RenderableImageProducer(RenderableImage rdblImage, + RenderContext rc) { + this.rdblImage = rdblImage; + this.rc = rc; + } + + /** + * Sets a new RenderContext to use for the next startProduction() call. + * + * @param rc the new RenderContext. + */ + public synchronized void setRenderContext(RenderContext rc) { + this.rc = rc; + } + + /** + * Adds an ImageConsumer to the list of consumers interested in + * data for this image. + * + * @param ic an ImageConsumer to be added to the interest list. + */ + public synchronized void addConsumer(ImageConsumer ic) { + if (!ics.contains(ic)) { + ics.addElement(ic); + } + } + + /** + * Determine if an ImageConsumer is on the list of consumers + * currently interested in data for this image. + * + * @param ic the ImageConsumer to be checked. + * @return true if the ImageConsumer is on the list; false otherwise. + */ + public synchronized boolean isConsumer(ImageConsumer ic) { + return ics.contains(ic); + } + + /** + * Remove an ImageConsumer from the list of consumers interested in + * data for this image. + * + * @param ic the ImageConsumer to be removed. + */ + public synchronized void removeConsumer(ImageConsumer ic) { + ics.removeElement(ic); + } + + /** + * Adds an ImageConsumer to the list of consumers interested in + * data for this image, and immediately starts delivery of the + * image data through the ImageConsumer interface. + * + * @param ic the ImageConsumer to be added to the list of consumers. + */ + public synchronized void startProduction(ImageConsumer ic) { + addConsumer(ic); + // Need to build a runnable object for the Thread. + Thread thread = new Thread(this, "RenderableImageProducer Thread"); + thread.start(); + } + + /** + * Requests that a given ImageConsumer have the image data delivered + * one more time in top-down, left-right order. + * + * @param ic the ImageConsumer requesting the resend. + */ + public void requestTopDownLeftRightResend(ImageConsumer ic) { + // So far, all pixels are already sent in TDLR order + } + + /** + * The runnable method for this class. This will produce an image using + * the current RenderableImage and RenderContext and send it to all the + * ImageConsumer currently registered with this class. + */ + public void run() { + // First get the rendered image + RenderedImage rdrdImage; + if (rc != null) { + rdrdImage = rdblImage.createRendering(rc); + } else { + rdrdImage = rdblImage.createDefaultRendering(); + } + + // And its ColorModel + ColorModel colorModel = rdrdImage.getColorModel(); + Raster raster = rdrdImage.getData(); + SampleModel sampleModel = raster.getSampleModel(); + DataBuffer dataBuffer = raster.getDataBuffer(); + + if (colorModel == null) { + colorModel = ColorModel.getRGBdefault(); + } + int minX = raster.getMinX(); + int minY = raster.getMinY(); + int width = raster.getWidth(); + int height = raster.getHeight(); + + Enumeration icList; + ImageConsumer ic; + // Set up the ImageConsumers + icList = ics.elements(); + while (icList.hasMoreElements()) { + ic = (ImageConsumer)icList.nextElement(); + ic.setDimensions(width,height); + ic.setHints(ImageConsumer.TOPDOWNLEFTRIGHT | + ImageConsumer.COMPLETESCANLINES | + ImageConsumer.SINGLEPASS | + ImageConsumer.SINGLEFRAME); + } + + // Get RGB pixels from the raster scanline by scanline and + // send to consumers. + int pix[] = new int[width]; + int i,j; + int numBands = sampleModel.getNumBands(); + int tmpPixel[] = new int[numBands]; + for (j = 0; j < height; j++) { + for(i = 0; i < width; i++) { + sampleModel.getPixel(i, j, tmpPixel, dataBuffer); + pix[i] = colorModel.getDataElement(tmpPixel, 0); + } + // Now send the scanline to the Consumers + icList = ics.elements(); + while (icList.hasMoreElements()) { + ic = (ImageConsumer)icList.nextElement(); + ic.setPixels(0, j, width, 1, colorModel, pix, 0, width); + } + } + + // Now tell the consumers we're done. + icList = ics.elements(); + while (icList.hasMoreElements()) { + ic = (ImageConsumer)icList.nextElement(); + ic.imageComplete(ImageConsumer.STATICIMAGEDONE); + } + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/java/awt/image/renderable/RenderedImageFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/image/renderable/RenderedImageFactory.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,78 @@ +/* + * Portions Copyright 1998 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* ******************************************************************** + ********************************************************************** + ********************************************************************** + *** COPYRIGHT (c) Eastman Kodak Company, 1997 *** + *** As an unpublished work pursuant to Title 17 of the United *** + *** States Code. All rights reserved. *** + ********************************************************************** + ********************************************************************** + **********************************************************************/ + +package java.awt.image.renderable; +import java.awt.image.RenderedImage; +import java.awt.RenderingHints; + +/** + * The RenderedImageFactory interface (often abbreviated RIF) is + * intended to be implemented by classes that wish to act as factories + * to produce different renderings, for example by executing a series + * of BufferedImageOps on a set of sources, depending on a specific + * set of parameters, properties, and rendering hints. + */ +public interface RenderedImageFactory { + + /** + * Creates a RenderedImage representing the results of an imaging + * operation (or chain of operations) for a given ParameterBlock and + * RenderingHints. The RIF may also query any source images + * referenced by the ParameterBlock for their dimensions, + * SampleModels, properties, etc., as necessary. + * + *

The create() method can return null if the + * RenderedImageFactory is not capable of producing output for the + * given set of source images and parameters. For example, if a + * RenderedImageFactory is only capable of performing a 3x3 + * convolution on single-banded image data, and the source image has + * multiple bands or the convolution Kernel is 5x5, null should be + * returned. + * + *

Hints should be taken into account, but can be ignored. + * The created RenderedImage may have a property identified + * by the String HINTS_OBSERVED to indicate which RenderingHints + * were used to create the image. In addition any RenderedImages + * that are obtained via the getSources() method on the created + * RenderedImage may have such a property. + * + * @param paramBlock a ParameterBlock containing sources and parameters + * for the RenderedImage to be created. + * @param hints a RenderingHints object containing hints. + * @return A RenderedImage containing the desired output. + */ + RenderedImage create(ParameterBlock paramBlock, + RenderingHints hints); +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/NumericValueExp.java --- a/jdk/src/share/classes/javax/management/NumericValueExp.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/NumericValueExp.java Wed Jul 05 16:37:14 2017 +0200 @@ -83,7 +83,7 @@ *

The serialVersionUID of this class is -4679739485102359104L. */ private static final ObjectStreamField[] serialPersistentFields; - private Number val = new Double(0); + private Number val = 0.0; private static boolean compat = false; static { @@ -213,11 +213,11 @@ } if (isLong) { - this.val = new Long(longVal); + this.val = longVal; } else { - this.val = new Double(doubleVal); + this.val = doubleVal; } } else diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/ObjectName.java --- a/jdk/src/share/classes/javax/management/ObjectName.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/ObjectName.java Wed Jul 05 16:37:14 2017 +0200 @@ -449,7 +449,7 @@ // parses domain part domain_parsing: while (index < len) { - switch (c = name_chars[index]) { + switch (name_chars[index]) { case ':' : _domain_length = index++; break domain_parsing; @@ -619,7 +619,7 @@ case '\n' : final String ichar = ((c1=='\n')?"\\n":""+c1); throw new MalformedObjectNameException( - "Invalid character '" + c1 + + "Invalid character '" + ichar + "' in value part of property"); default : in_index++; diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/StandardMBean.java --- a/jdk/src/share/classes/javax/management/StandardMBean.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/StandardMBean.java Wed Jul 05 16:37:14 2017 +0200 @@ -750,7 +750,7 @@ * @return the Descriptor for the new MBeanInfo. */ Descriptor getDescriptor(MBeanInfo info, boolean immutableInfo) { - ImmutableDescriptor desc = null; + ImmutableDescriptor desc; if (info == null || info.getDescriptor() == null || info.getDescriptor().getFieldNames().length == 0) { diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/loading/MLet.java --- a/jdk/src/share/classes/javax/management/loading/MLet.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/loading/MLet.java Wed Jul 05 16:37:14 2017 +0200 @@ -591,8 +591,8 @@ // Instantiate the class specified in the // CODE or OBJECT section of the MLet tag // - Object o = null; - ObjectInstance objInst = null; + Object o; + ObjectInstance objInst; if (code != null && serName != null) { final String msg = @@ -1131,11 +1131,17 @@ return null; } finally { // Cleanup ... - if (tmpFile!=null) try { - tmpFile.delete(); - } catch (Exception x) { - MLET_LOGGER.logp(Level.FINEST, MLet.class.getName(), - "getTmpDir", "Failed to delete temporary file", x); + if (tmpFile!=null) { + try { + boolean deleted = tmpFile.delete(); + if (!deleted) { + MLET_LOGGER.logp(Level.FINEST, MLet.class.getName(), + "getTmpDir", "Failed to delete temp file"); + } + } catch (Exception x) { + MLET_LOGGER.logp(Level.FINEST, MLet.class.getName(), + "getTmpDir", "Failed to delete temporary file", x); + } } } } @@ -1178,25 +1184,8 @@ * Removes any white space from a string. This is used to * convert strings such as "Windows NT" to "WindowsNT". */ - private String removeSpace(String s) { - s = s.trim(); - int j = s.indexOf(' '); - if (j == -1) { - return s; - } - String temp = ""; - int k = 0; - while (j != -1) { - s = s.substring(k); - j = s.indexOf(' '); - if (j != -1) { - temp = temp + s.substring(0, j); - } else { - temp = temp + s.substring(0); - } - k = j + 1; - } - return temp; + private static String removeSpace(String s) { + return s.trim().replace(" ", ""); } /** diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/loading/MLetParser.java --- a/jdk/src/share/classes/javax/management/loading/MLetParser.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/loading/MLetParser.java Wed Jul 05 16:37:14 2017 +0200 @@ -240,14 +240,12 @@ MLET_LOGGER.logp(Level.FINER, MLetParser.class.getName(), mth, requiresCodeWarning); - atts = null; throw new IOException(requiresCodeWarning); } if (atts.get("archive") == null) { MLET_LOGGER.logp(Level.FINER, MLetParser.class.getName(), mth, requiresJarsWarning); - atts = null; throw new IOException(requiresJarsWarning); } } @@ -265,7 +263,7 @@ public List parseURL(String urlname) throws IOException { // Parse the document // - URL url = null; + URL url; if (urlname.indexOf(':') <= 1) { String userDir = System.getProperty("user.dir"); String prot; diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java --- a/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/modelmbean/DescriptorSupport.java Wed Jul 05 16:37:14 2017 +0200 @@ -591,8 +591,6 @@ Set returnedSet = descriptorMap.entrySet(); int i = 0; - Object currValue = null; - Map.Entry currElement = null; if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { MODELMBEAN_LOGGER.logp(Level.FINEST, @@ -600,7 +598,7 @@ "getFields()", "Returning " + numberOfEntries + " fields"); } for (Iterator iter = returnedSet.iterator(); iter.hasNext(); i++) { - currElement = (Map.Entry) iter.next(); + Map.Entry currElement = (Map.Entry) iter.next(); if (currElement == null) { if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) { @@ -609,7 +607,7 @@ "getFields()", "Element is null"); } } else { - currValue = currElement.getValue(); + Object currValue = currElement.getValue(); if (currValue == null) { responseFields[i] = currElement.getKey() + "="; } else { @@ -1127,7 +1125,7 @@ final char c = entities[i].charAt(0); final String entity = entities[i].substring(1); charToEntityMap[c] = entity; - entityToCharMap.put(entity, new Character(c)); + entityToCharMap.put(entity, c); } } @@ -1325,13 +1323,11 @@ // utility to convert to int, returns -2 if bogus. private long toNumeric(String inStr) { - long result = -2; try { - result = java.lang.Long.parseLong(inStr); + return java.lang.Long.parseLong(inStr); } catch (Exception e) { return -2; } - return result; } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java Wed Jul 05 16:37:14 2017 +0200 @@ -432,7 +432,7 @@ */ private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { - Descriptor clone = null; + Descriptor clone; if (in == null) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java Wed Jul 05 16:37:14 2017 +0200 @@ -393,7 +393,7 @@ * @exception RuntimeOperationsException if Descriptor is invalid */ private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { - Descriptor clone = null; + Descriptor clone; if (in == null) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java Wed Jul 05 16:37:14 2017 +0200 @@ -944,7 +944,7 @@ * @exception RuntimeOperationsException if Descriptor is invalid */ private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { - Descriptor clone = null; + Descriptor clone; if (in == null) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java Wed Jul 05 16:37:14 2017 +0200 @@ -328,7 +328,7 @@ * @exception RuntimeOperationsException if Descriptor is invalid */ private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { - Descriptor clone = null; + Descriptor clone; if (in == null) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java --- a/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java Wed Jul 05 16:37:14 2017 +0200 @@ -424,7 +424,7 @@ */ private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { - Descriptor clone = null; + Descriptor clone; if (in == null) { clone = new DescriptorSupport(); MODELMBEAN_LOGGER.finer("Null Descriptor, creating new."); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java --- a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java Wed Jul 05 16:37:14 2017 +0200 @@ -1425,9 +1425,7 @@ } /* Check attributeDescriptor for getMethod */ - ModelMBeanAttributeInfo attrInfo=null; - Descriptor attrDescr=null; - Object response = null; + Object response; try { if (modelMBeanInfo == null) @@ -1435,14 +1433,14 @@ "getAttribute failed: ModelMBeanInfo not found for "+ attrName); - attrInfo = modelMBeanInfo.getAttribute(attrName); + ModelMBeanAttributeInfo attrInfo = modelMBeanInfo.getAttribute(attrName); Descriptor mmbDesc = modelMBeanInfo.getMBeanDescriptor(); if (attrInfo == null) throw new AttributeNotFoundException("getAttribute failed:"+ " ModelMBeanAttributeInfo not found for " + attrName); - attrDescr = attrInfo.getDescriptor(); + Descriptor attrDescr = attrInfo.getDescriptor(); if (attrDescr != null) { if (!attrInfo.isReadable()) throw new AttributeNotFoundException( @@ -1684,14 +1682,13 @@ "getAttributes(String[])","Entry"); } - AttributeList responseList = null; if (attrNames == null) throw new RuntimeOperationsException(new IllegalArgumentException("attributeNames must not be null"), "Exception occurred trying to get attributes of a "+ "RequiredModelMBean"); - responseList = new AttributeList(); + AttributeList responseList = new AttributeList(); for (int i = 0; i < attrNames.length; i++) { try { responseList.add(new Attribute(attrNames[i], @@ -1833,8 +1830,6 @@ throw new AttributeNotFoundException("setAttribute failed: " + attrName + " is not writable "); - Object setResponse = null; - String attrSetMethod = (String) (attrDescr.getFieldValue("setMethod")); String attrGetMethod = (String) @@ -1873,9 +1868,9 @@ } updateDescriptor = true; } else { - setResponse = invoke(attrSetMethod, - (new Object[] {attrValue}), - (new String[] {attrType}) ); + invoke(attrSetMethod, + (new Object[] {attrValue}), + (new String[] {attrType}) ); } /* change cached value */ @@ -2023,8 +2018,6 @@ private synchronized void writeToLog(String logFileName, String logEntry) throws Exception { - PrintStream logOut = null; - FileOutputStream fos = null; if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) { MODELMBEAN_LOGGER.logp(Level.FINER, RequiredModelMBean.class.getName(), @@ -2041,9 +2034,9 @@ return; } + FileOutputStream fos = new FileOutputStream(logFileName, true); try { - fos = new FileOutputStream(logFileName, true); - logOut = new PrintStream(fos); + PrintStream logOut = new PrintStream(fos); logOut.println(logEntry); logOut.close(); if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) { @@ -2062,6 +2055,8 @@ logFileName); } throw e; + } finally { + fos.close(); } } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/monitor/CounterMonitor.java --- a/jdk/src/share/classes/javax/management/monitor/CounterMonitor.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/monitor/CounterMonitor.java Wed Jul 05 16:37:14 2017 +0200 @@ -740,16 +740,16 @@ // switch (o.getType()) { case INTEGER: - o.setThreshold(new Integer((int)threshold_value)); + o.setThreshold(Integer.valueOf((int)threshold_value)); break; case BYTE: - o.setThreshold(new Byte((byte)threshold_value)); + o.setThreshold(Byte.valueOf((byte)threshold_value)); break; case SHORT: - o.setThreshold(new Short((short)threshold_value)); + o.setThreshold(Short.valueOf((short)threshold_value)); break; case LONG: - o.setThreshold(new Long(threshold_value)); + o.setThreshold(Long.valueOf(threshold_value)); break; default: // Should never occur... @@ -810,10 +810,10 @@ derived += modulus.longValue(); switch (o.getType()) { - case INTEGER: o.setDerivedGauge(new Integer((int) derived)); break; - case BYTE: o.setDerivedGauge(new Byte((byte) derived)); break; - case SHORT: o.setDerivedGauge(new Short((short) derived)); break; - case LONG: o.setDerivedGauge(new Long(derived)); break; + case INTEGER: o.setDerivedGauge(Integer.valueOf((int) derived)); break; + case BYTE: o.setDerivedGauge(Byte.valueOf((byte) derived)); break; + case SHORT: o.setDerivedGauge(Short.valueOf((short) derived)); break; + case LONG: o.setDerivedGauge(Long.valueOf(derived)); break; default: // Should never occur... MONITOR_LOGGER.logp(Level.FINEST, CounterMonitor.class.getName(), diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/monitor/GaugeMonitor.java --- a/jdk/src/share/classes/javax/management/monitor/GaugeMonitor.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/monitor/GaugeMonitor.java Wed Jul 05 16:37:14 2017 +0200 @@ -636,28 +636,28 @@ Number der; switch (o.getType()) { case INTEGER: - der = new Integer(((Integer)scanGauge).intValue() - - ((Integer)prev).intValue()); + der = Integer.valueOf(((Integer)scanGauge).intValue() - + ((Integer)prev).intValue()); break; case BYTE: - der = new Byte((byte)(((Byte)scanGauge).byteValue() - - ((Byte)prev).byteValue())); + der = Byte.valueOf((byte)(((Byte)scanGauge).byteValue() - + ((Byte)prev).byteValue())); break; case SHORT: - der = new Short((short)(((Short)scanGauge).shortValue() - - ((Short)prev).shortValue())); + der = Short.valueOf((short)(((Short)scanGauge).shortValue() - + ((Short)prev).shortValue())); break; case LONG: - der = new Long(((Long)scanGauge).longValue() - - ((Long)prev).longValue()); + der = Long.valueOf(((Long)scanGauge).longValue() - + ((Long)prev).longValue()); break; case FLOAT: - der = new Float(((Float)scanGauge).floatValue() - - ((Float)prev).floatValue()); + der = Float.valueOf(((Float)scanGauge).floatValue() - + ((Float)prev).floatValue()); break; case DOUBLE: - der = new Double(((Double)scanGauge).doubleValue() - - ((Double)prev).doubleValue()); + der = Double.valueOf(((Double)scanGauge).doubleValue() - + ((Double)prev).doubleValue()); break; default: // Should never occur... diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/monitor/Monitor.java --- a/jdk/src/share/classes/javax/management/monitor/Monitor.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/monitor/Monitor.java Wed Jul 05 16:37:14 2017 +0200 @@ -367,7 +367,7 @@ /** * Constant used to initialize all the numeric values. */ - static final Integer INTEGER_ZERO = new Integer(0); + static final Integer INTEGER_ZERO = 0; /* @@ -1122,12 +1122,12 @@ */ private void monitor(ObservedObject o, int index, int an[]) { - String attribute = null; + String attribute; String notifType = null; String msg = null; Object derGauge = null; Object trigger = null; - ObjectName object = null; + ObjectName object; Comparable value = null; MonitorNotification alarm = null; @@ -1565,7 +1565,7 @@ final ThreadGroup group; final AtomicInteger threadNumber = new AtomicInteger(1); final String namePrefix; - final String nameSuffix = "]"; + static final String nameSuffix = "]"; public DaemonThreadFactory(String poolName) { SecurityManager s = System.getSecurityManager(); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/openmbean/ArrayType.java --- a/jdk/src/share/classes/javax/management/openmbean/ArrayType.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/openmbean/ArrayType.java Wed Jul 05 16:37:14 2017 +0200 @@ -726,7 +726,7 @@ value += dimension; value += elementType.hashCode(); value += Boolean.valueOf(primitiveArray).hashCode(); - myHashCode = new Integer(value); + myHashCode = Integer.valueOf(value); } // return always the same hash code for this instance (immutable) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/openmbean/CompositeType.java --- a/jdk/src/share/classes/javax/management/openmbean/CompositeType.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/openmbean/CompositeType.java Wed Jul 05 16:37:14 2017 +0200 @@ -426,7 +426,7 @@ value += key.hashCode(); value += this.nameToType.get(key).hashCode(); } - myHashCode = new Integer(value); + myHashCode = Integer.valueOf(value); } // return always the same hash code for this instance (immutable) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java --- a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java Wed Jul 05 16:37:14 2017 +0200 @@ -769,7 +769,6 @@ "array with same dimensions"; throw new IllegalArgumentException(msg); } - Class targetComponentClass = targetArrayClass.getComponentType(); OpenType componentOpenType; if (dim == 1) componentOpenType = baseType; diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/openmbean/OpenMBeanConstructorInfoSupport.java --- a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanConstructorInfoSupport.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanConstructorInfoSupport.java Wed Jul 05 16:37:14 2017 +0200 @@ -252,7 +252,7 @@ int value = 0; value += this.getName().hashCode(); value += Arrays.asList(this.getSignature()).hashCode(); - myHashCode = new Integer(value); + myHashCode = Integer.valueOf(value); } // return always the same hash code for this instance (immutable) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/openmbean/OpenMBeanInfoSupport.java --- a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanInfoSupport.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanInfoSupport.java Wed Jul 05 16:37:14 2017 +0200 @@ -347,7 +347,7 @@ value += arraySetHash(this.getConstructors()); value += arraySetHash(this.getOperations()); value += arraySetHash(this.getNotifications()); - myHashCode = new Integer(value); + myHashCode = Integer.valueOf(value); } // return always the same hash code for this instance (immutable) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/openmbean/OpenMBeanOperationInfoSupport.java --- a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanOperationInfoSupport.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanOperationInfoSupport.java Wed Jul 05 16:37:14 2017 +0200 @@ -352,7 +352,7 @@ value += Arrays.asList(this.getSignature()).hashCode(); value += this.getReturnOpenType().hashCode(); value += this.getImpact(); - myHashCode = new Integer(value); + myHashCode = Integer.valueOf(value); } // return always the same hash code for this instance (immutable) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/openmbean/SimpleType.java --- a/jdk/src/share/classes/javax/management/openmbean/SimpleType.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/openmbean/SimpleType.java Wed Jul 05 16:37:14 2017 +0200 @@ -257,7 +257,7 @@ // Calculate the hash code value if it has not yet been done (ie 1st call to hashCode()) // if (myHashCode == null) { - myHashCode = new Integer(this.getClassName().hashCode()); + myHashCode = Integer.valueOf(this.getClassName().hashCode()); } // return always the same hash code for this instance (immutable) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/openmbean/TabularType.java --- a/jdk/src/share/classes/javax/management/openmbean/TabularType.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/openmbean/TabularType.java Wed Jul 05 16:37:14 2017 +0200 @@ -332,7 +332,7 @@ for (Iterator k = indexNames.iterator(); k.hasNext(); ) { value += k.next().hashCode(); } - myHashCode = new Integer(value); + myHashCode = Integer.valueOf(value); } // return always the same hash code for this instance (immutable) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/relation/RelationNotification.java --- a/jdk/src/share/classes/javax/management/relation/RelationNotification.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/relation/RelationNotification.java Wed Jul 05 16:37:14 2017 +0200 @@ -369,7 +369,7 @@ * @return a {@link List} of {@link ObjectName}. */ public List getMBeansToUnregister() { - List result = null; + List result; if (unregisterMBeanList != null) { result = new ArrayList(unregisterMBeanList); } else { @@ -397,7 +397,7 @@ * @return the old value of the updated role. */ public List getOldRoleValue() { - List result = null; + List result; if (oldRoleValue != null) { result = new ArrayList(oldRoleValue); } else { @@ -412,7 +412,7 @@ * @return the new value of the updated role. */ public List getNewRoleValue() { - List result = null; + List result; if (newRoleValue != null) { result = new ArrayList(newRoleValue); } else { diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/relation/RelationService.java --- a/jdk/src/share/classes/javax/management/relation/RelationService.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/relation/RelationService.java Wed Jul 05 16:37:14 2017 +0200 @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import javax.management.Attribute; @@ -122,7 +123,7 @@ // Internal counter to provide sequence numbers for notifications sent by: // - the Relation Service // - a relation handled by the Relation Service - private Long myNtfSeqNbrCounter = new Long(0); + private final AtomicLong atomicSeqNo = new AtomicLong(); // ObjectName used to register the Relation Service in the MBean Server private ObjectName myObjName = null; @@ -256,19 +257,6 @@ return; } - // Returns internal counter to be used for Sequence Numbers of - // notifications to be raised by: - // - a relation handled by this Relation Service (when updated) - // - the Relation Service - private Long getNotificationSequenceNumber() { - Long result = null; - synchronized(myNtfSeqNbrCounter) { - result = new Long(myNtfSeqNbrCounter.longValue() + 1); - myNtfSeqNbrCounter = new Long(result.longValue()); - } - return result; - } - // // Relation type handling // @@ -369,7 +357,7 @@ * @return ArrayList of relation type names (Strings) */ public List getAllRelationTypeNames() { - ArrayList result = null; + ArrayList result; synchronized(myRelType2ObjMap) { result = new ArrayList(myRelType2ObjMap.keySet()); } @@ -684,7 +672,7 @@ // Can throw InstanceNotFoundException (but detected above) // No MBeanException as no exception raised by this method, and no // ReflectionException - String relId = null; + String relId; try { relId = (String)(myMBeanServer.getAttribute(relationObjectName, "RelationId")); @@ -707,7 +695,7 @@ // Can throw InstanceNotFoundException (but detected above) // No MBeanException as no exception raised by this method, no // ReflectionException - ObjectName relServObjName = null; + ObjectName relServObjName; try { relServObjName = (ObjectName) (myMBeanServer.getAttribute(relationObjectName, @@ -737,7 +725,7 @@ // Can throw InstanceNotFoundException (but detected above) // No MBeanException as no exception raised by this method, no // ReflectionException - String relTypeName = null; + String relTypeName; try { relTypeName = (String)(myMBeanServer.getAttribute(relationObjectName, "RelationTypeName")); @@ -758,7 +746,7 @@ // Can throw InstanceNotFoundException (but detected above) // No MBeanException as no exception raised by this method, no // ReflectionException - RoleList roleList = null; + RoleList roleList; try { roleList = (RoleList)(myMBeanServer.invoke(relationObjectName, "retrieveAllRoles", @@ -912,7 +900,7 @@ * @return ArrayList of String */ public List getAllRelationIds() { - List result = null; + List result; synchronized(myRelId2ObjMap) { result = new ArrayList(myRelId2ObjMap.keySet()); } @@ -948,7 +936,7 @@ RELATION_LOGGER.entering(RelationService.class.getName(), "checkRoleReading", new Object[] {roleName, relationTypeName}); - Integer result = null; + Integer result; // Can throw a RelationTypeNotFoundException RelationType relType = getRelationType(relationTypeName); @@ -965,7 +953,7 @@ false); } catch (RoleInfoNotFoundException exc) { - result = new Integer(RoleStatus.NO_ROLE_WITH_NAME); + result = Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); } RELATION_LOGGER.exiting(RelationService.class.getName(), @@ -1021,13 +1009,13 @@ writeChkFlag = false; } - RoleInfo roleInfo = null; + RoleInfo roleInfo; try { roleInfo = relType.getRoleInfo(roleName); } catch (RoleInfoNotFoundException exc) { RELATION_LOGGER.exiting(RelationService.class.getName(), "checkRoleWriting"); - return new Integer(RoleStatus.NO_ROLE_WITH_NAME); + return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); } Integer result = checkRoleInt(2, @@ -1436,7 +1424,7 @@ // Relation id to relation type name map // First retrieves the relation type name - String relTypeName = null; + String relTypeName; synchronized(myRelId2RelTypeMap) { relTypeName = myRelId2RelTypeMap.get(relationId); myRelId2RelTypeMap.remove(relationId); @@ -1641,7 +1629,7 @@ // List of relation ids of interest regarding the selected // relation type - List relIdList = null; + List relIdList; if (relationTypeName == null) { // Considers all relations relIdList = new ArrayList(allRelIdSet); @@ -1655,7 +1643,7 @@ for (String currRelId : allRelIdSet) { // Retrieves its relation type - String currRelTypeName = null; + String currRelTypeName; synchronized(myRelId2RelTypeMap) { currRelTypeName = myRelId2RelTypeMap.get(currRelId); @@ -1952,7 +1940,7 @@ // Can throw a RelationNotFoundException Object relObj = getRelation(relationId); - RoleResult result = null; + RoleResult result; if (relObj instanceof RelationSupport) { // Internal relation @@ -2022,7 +2010,7 @@ // Can throw a RelationNotFoundException Object relObj = getRelation(relationId); - RoleResult result = null; + RoleResult result; if (relObj instanceof RelationSupport) { // Internal relation @@ -2073,7 +2061,7 @@ // Can throw a RelationNotFoundException Object relObj = getRelation(relationId); - Integer result = null; + Integer result; if (relObj instanceof RelationSupport) { // Internal relation @@ -2268,7 +2256,7 @@ // Can throw a RelationNotFoundException Object relObj = getRelation(relationId); - RoleResult result = null; + RoleResult result; if (relObj instanceof RelationSupport) { // Internal relation @@ -2390,7 +2378,7 @@ // Can throw a RelationNotFoundException Object relObj = getRelation(relationId); - String result = null; + String result; if (relObj instanceof RelationSupport) { // Internal relation @@ -2473,7 +2461,7 @@ // Note: do both tests as a relation can be an MBean and be // itself referenced in another relation :) - String relId = null; + String relId; synchronized(myRelMBeanObjName2RelIdMap){ relId = myRelMBeanObjName2RelIdMap.get(mbeanName); } @@ -2511,9 +2499,6 @@ RELATION_LOGGER.entering(RelationService.class.getName(), "getNotificationInfo"); - MBeanNotificationInfo[] ntfInfoArray = - new MBeanNotificationInfo[1]; - String ntfClass = "javax.management.relation.RelationNotification"; String[] ntfTypes = new String[] { @@ -2615,7 +2600,7 @@ "getRelationType", relationTypeName); // No null relation type accepted, so can use get() - RelationType relType = null; + RelationType relType; synchronized(myRelType2ObjMap) { relType = (myRelType2ObjMap.get(relationTypeName)); } @@ -2659,7 +2644,7 @@ "getRelation", relationId); // No null relation accepted, so can use get() - Object rel = null; + Object rel; synchronized(myRelId2ObjMap) { rel = myRelId2ObjMap.get(relationId); } @@ -3077,7 +3062,7 @@ // Retrieves corresponding role info // Can throw a RoleInfoNotFoundException to be converted into a // RoleNotFoundException - RoleInfo roleInfo = null; + RoleInfo roleInfo; try { roleInfo = relType.getRoleInfo(currRoleName); } catch (RoleInfoNotFoundException exc) { @@ -3227,7 +3212,7 @@ if (!(roleName.equals(expName))) { RELATION_LOGGER.exiting(RelationService.class.getName(), "checkRoleInt"); - return new Integer(RoleStatus.NO_ROLE_WITH_NAME); + return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); } // Checks read access if required @@ -3236,7 +3221,7 @@ if (!isReadable) { RELATION_LOGGER.exiting(RelationService.class.getName(), "checkRoleInt"); - return new Integer(RoleStatus.ROLE_NOT_READABLE); + return Integer.valueOf(RoleStatus.ROLE_NOT_READABLE); } else { // End of check :) RELATION_LOGGER.exiting(RelationService.class.getName(), @@ -3572,7 +3557,7 @@ // Relation type name // Note: do not use getRelationTypeName() as if it is a relation MBean // it is already unregistered. - String relTypeName = null; + String relTypeName; synchronized(myRelId2RelTypeMap) { relTypeName = (myRelId2RelTypeMap.get(relationId)); } @@ -3609,7 +3594,7 @@ } // Sequence number - Long seqNbr = getNotificationSequenceNumber(); + Long seqNo = atomicSeqNo.incrementAndGet(); // Timestamp Date currDate = new Date(); @@ -3625,7 +3610,7 @@ // Creation or removal ntf = new RelationNotification(ntfType, this, - seqNbr.longValue(), + seqNo.longValue(), timeStamp, message, relationId, @@ -3640,7 +3625,7 @@ // Update ntf = new RelationNotification(ntfType, this, - seqNbr.longValue(), + seqNo.longValue(), timeStamp, message, relationId, @@ -3732,7 +3717,7 @@ // // Shall not throw RelationTypeNotFoundException or // RoleInfoNotFoundException - RoleInfo currRoleInfo = null; + RoleInfo currRoleInfo; try { currRoleInfo = getRoleInfo(currRelTypeName, currRoleName); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/relation/RelationSupport.java --- a/jdk/src/share/classes/javax/management/relation/RelationSupport.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/relation/RelationSupport.java Wed Jul 05 16:37:14 2017 +0200 @@ -34,6 +34,7 @@ import java.util.Map; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import static com.sun.jmx.defaults.JmxProperties.RELATION_LOGGER; import static com.sun.jmx.mbeanserver.Util.cast; import javax.management.InstanceNotFoundException; @@ -110,7 +111,7 @@ private Map myRoleName2ValueMap = new HashMap(); // Flag to indicate if the object has been added in the Relation Service - private Boolean myInRelServFlg = null; + private final AtomicBoolean myInRelServFlg = new AtomicBoolean(); // // Constructors @@ -403,7 +404,7 @@ "getRoleCardinality", roleName); // Try to retrieve the role - Role role = null; + Role role; synchronized(myRoleName2ValueMap) { // No null Role is allowed, so direct use of get() role = (myRoleName2ValueMap.get(roleName)); @@ -427,7 +428,7 @@ RELATION_LOGGER.exiting(RelationSupport.class.getName(), "getRoleCardinality"); - return new Integer(roleValue.size()); + return roleValue.size(); } /** @@ -701,11 +702,7 @@ * the Relation Service. */ public Boolean isInRelationService() { - Boolean result = null; - synchronized(myInRelServFlg) { - result = Boolean.valueOf(myInRelServFlg.booleanValue()); - } - return result; + return myInRelServFlg.get(); } public void setRelationServiceManagementFlag(Boolean flag) @@ -715,10 +712,7 @@ String excMsg = "Invalid parameter."; throw new IllegalArgumentException(excMsg); } - synchronized(myInRelServFlg) { - myInRelServFlg = Boolean.valueOf(flag.booleanValue()); - } - return; + myInRelServFlg.set(flag); } // @@ -790,7 +784,7 @@ int pbType = 0; - Role role = null; + Role role; synchronized(myRoleName2ValueMap) { // No null Role is allowed, so direct use of get() role = (myRoleName2ValueMap.get(roleName)); @@ -801,7 +795,7 @@ } else { // Checks if the role is readable - Integer status = null; + Integer status; if (relationServCallFlg) { @@ -851,7 +845,7 @@ pbType = status.intValue(); } - Object result = null; + Object result; if (pbType == 0) { // Role can be retrieved @@ -937,7 +931,7 @@ for (int i = 0; i < roleNameArray.length; i++) { String currRoleName = roleNameArray[i]; - Object currResult = null; + Object currResult; // Can throw RelationServiceNotRegisteredException // @@ -1102,13 +1096,13 @@ // handle initialization of role when creating the relation // (roles provided in the RoleList parameter are directly set but // roles automatically initialized are set using setRole()) - Role role = null; + Role role; synchronized(myRoleName2ValueMap) { role = (myRoleName2ValueMap.get(roleName)); } List oldRoleValue; - Boolean initFlg = null; + Boolean initFlg; if (role == null) { initFlg = true; @@ -1122,7 +1116,7 @@ // Checks if the role can be set: is writable (except if // initialization) and correct value try { - Integer status = null; + Integer status; if (relationServCallFlg) { @@ -1314,7 +1308,7 @@ Object[] params = new Object[3]; params[0] = myRelId; params[1] = newRole; - params[2] = ((ArrayList)oldRoleValue); + params[2] = oldRoleValue; String[] signature = new String[3]; signature[0] = "java.lang.String"; signature[1] = "javax.management.relation.Role"; @@ -1598,7 +1592,6 @@ myRelTypeName = relationTypeName; // Can throw InvalidRoleValueException initRoleMap(list); - myInRelServFlg = Boolean.FALSE; RELATION_LOGGER.exiting(RelationSupport.class.getName(), "initMembers"); return; @@ -1710,7 +1703,7 @@ roleName, relationServCallFlg, relationServ}); // Retrieves current role value - Role role = null; + Role role; synchronized(myRoleName2ValueMap) { role = (myRoleName2ValueMap.get(roleName)); } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/remote/JMXConnectorFactory.java --- a/jdk/src/share/classes/javax/management/remote/JMXConnectorFactory.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/remote/JMXConnectorFactory.java Wed Jul 05 16:37:14 2017 +0200 @@ -435,7 +435,7 @@ Iterator providers = getProviderIterator(JMXConnectorProvider.class, loader); - JMXConnector connection = null; + JMXConnector connection; IOException exception = null; while(providers.hasNext()) { try { @@ -450,7 +450,7 @@ "] Service provider exception: " + e); if (!(e instanceof MalformedURLException)) { if (exception == null) { - if (exception instanceof IOException) { + if (e instanceof IOException) { exception = (IOException) e; } else { exception = EnvHelp.initCause( diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/remote/JMXConnectorServerFactory.java --- a/jdk/src/share/classes/javax/management/remote/JMXConnectorServerFactory.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/remote/JMXConnectorServerFactory.java Wed Jul 05 16:37:14 2017 +0200 @@ -215,12 +215,10 @@ JMXConnectorFactory. getProviderIterator(JMXConnectorServerProvider.class, loader); - JMXConnectorServer connection = null; IOException exception = null; while (providers.hasNext()) { try { - connection = providers.next().newJMXConnectorServer(url, map, mbs); - return connection; + return providers.next().newJMXConnectorServer(url, map, mbs); } catch (JMXProviderException e) { throw e; } catch (Exception e) { @@ -230,7 +228,7 @@ "] Service provider exception: " + e); if (!(e instanceof MalformedURLException)) { if (exception == null) { - if (exception instanceof IOException) { + if (e instanceof IOException) { exception = (IOException) e; } else { exception = EnvHelp.initCause( diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/remote/JMXServiceURL.java --- a/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java Wed Jul 05 16:37:14 2017 +0200 @@ -162,8 +162,6 @@ requiredPrefix); } - int[] ptr = new int[1]; - // Parse the protocol name final int protoStart = requiredPrefixLength; final int protoEnd = indexOf(serviceURL, ':', protoStart); @@ -664,11 +662,6 @@ hostNameBitSet.set('.'); } - private static void addCharsToBitSet(BitSet set, String chars) { - for (int i = 0; i < chars.length(); i++) - set.set(chars.charAt(i)); - } - /** * The value returned by {@link #getProtocol()}. */ diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java Wed Jul 05 16:37:14 2017 +0200 @@ -1376,12 +1376,12 @@ protected Integer addListenerForMBeanRemovedNotif() throws IOException, InstanceNotFoundException { - MarshalledObject sFilter = null; NotificationFilterSupport clientFilter = new NotificationFilterSupport(); clientFilter.enableType( MBeanServerNotification.UNREGISTRATION_NOTIFICATION); - sFilter = new MarshalledObject(clientFilter); + MarshalledObject sFilter = + new MarshalledObject(clientFilter); Integer[] listenerIDs; final ObjectName[] names = @@ -1434,7 +1434,7 @@ connectionId, clientNotifCounter++, message, - new Long(number)); + Long.valueOf(number)); sendNotification(n); } } @@ -1593,7 +1593,7 @@ protected void doStart() throws IOException { // Get RMIServer stub from directory or URL encoding if needed. - RMIServer stub = null; + RMIServer stub; try { stub = (rmiServer!=null)?rmiServer: findRMIServer(jmxServiceURL, env); @@ -2532,7 +2532,7 @@ * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to * connect unconnected stubs. **/ - private static WeakReference orb = null; + private static volatile WeakReference orb = null; // TRACES & DEBUG //--------------- diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Wed Jul 05 16:37:14 2017 +0200 @@ -365,7 +365,7 @@ // Access file property specified, create an instance // of the MBeanServerFileAccessController class // - MBeanServerForwarder mbsf = null; + MBeanServerForwarder mbsf; try { mbsf = new MBeanServerFileAccessController(accessFile); } catch (IOException e) { diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/management/timer/Timer.java --- a/jdk/src/share/classes/javax/management/timer/Timer.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/management/timer/Timer.java Wed Jul 05 16:37:14 2017 +0200 @@ -344,13 +344,11 @@ // if (isActive == true) { - TimerAlarmClock alarmClock; - for (Object[] obj : timerTable.values()) { // Stop all the TimerAlarmClock. // - alarmClock = (TimerAlarmClock)obj[ALARM_CLOCK_INDEX]; + TimerAlarmClock alarmClock = (TimerAlarmClock)obj[ALARM_CLOCK_INDEX]; if (alarmClock != null) { // alarmClock.interrupt(); // try { @@ -364,7 +362,6 @@ // // alarmClock.cancel(); - alarmClock = null; } } @@ -458,8 +455,7 @@ // Create and add the timer notification into the timer table. // - Integer notifID = null; - notifID = new Integer(++counterID); + Integer notifID = Integer.valueOf(++counterID); // The sequenceNumber and the timeStamp attributes are updated // when the notification is emitted by the timer. @@ -486,8 +482,8 @@ obj[TIMER_NOTIF_INDEX] = (Object)notif; obj[TIMER_DATE_INDEX] = (Object)d; - obj[TIMER_PERIOD_INDEX] = (Object) new Long(period); - obj[TIMER_NB_OCCUR_INDEX] = (Object) new Long(nbOccurences); + obj[TIMER_PERIOD_INDEX] = (Object) period; + obj[TIMER_NB_OCCUR_INDEX] = (Object) nbOccurences; obj[ALARM_CLOCK_INDEX] = (Object)alarmClock; obj[FIXED_RATE_INDEX] = Boolean.valueOf(fixedRate); @@ -678,7 +674,6 @@ // // Remove the reference on the TimerAlarmClock. // // alarmClock.cancel(); - alarmClock = null; } // Remove the timer notification from the timer table. @@ -755,7 +750,6 @@ // // } alarmClock.cancel(); - alarmClock = null; } // Remove all the timer notifications from the timer table. @@ -906,8 +900,7 @@ Object[] obj = timerTable.get(id); if (obj != null) { - Long period = (Long)obj[TIMER_PERIOD_INDEX]; - return (new Long(period.longValue())); + return (Long)obj[TIMER_PERIOD_INDEX]; } return null; } @@ -924,8 +917,7 @@ Object[] obj = timerTable.get(id); if (obj != null) { - Long nbOccurences = (Long)obj[TIMER_NB_OCCUR_INDEX]; - return (new Long(nbOccurences.longValue())); + return (Long)obj[TIMER_NB_OCCUR_INDEX]; } return null; } @@ -1096,7 +1088,7 @@ if ((nbOccurences.longValue() == 0) || (nbOccurences.longValue() > 1)) { date.setTime(date.getTime() + period.longValue()); - obj[TIMER_NB_OCCUR_INDEX] = new Long(java.lang.Math.max(0L, (nbOccurences.longValue() - 1))); + obj[TIMER_NB_OCCUR_INDEX] = Long.valueOf(java.lang.Math.max(0L, (nbOccurences.longValue() - 1))); nbOccurences = (Long)obj[TIMER_NB_OCCUR_INDEX]; if (isActive == true) { @@ -1146,9 +1138,6 @@ // // Ignore... // } alarmClock.cancel(); - // Remove the reference on the TimerAlarmClock. - // - alarmClock = null; } timerTable.remove(notifID); } @@ -1165,10 +1154,6 @@ // } alarmClock.cancel(); - - // Remove the reference on the TimerAlarmClock. - // - alarmClock = null; } timerTable.remove(notifID); } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java --- a/jdk/src/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java Wed Jul 05 16:37:14 2017 +0200 @@ -44,7 +44,7 @@ * print request's, print job's, or print service's attribute set. *

* The Internet Assigned Numbers Authority maintains the - * official + * official * list of URI schemes. *

* Class ReferenceUriSchemesSupported defines enumeration values for widely diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/sun/awt/image/SunVolatileImage.java --- a/jdk/src/share/classes/sun/awt/image/SunVolatileImage.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/sun/awt/image/SunVolatileImage.java Wed Jul 05 16:37:14 2017 +0200 @@ -165,7 +165,8 @@ { return new BufImgVolatileSurfaceManager(this, context); } - return SurfaceManagerFactory.createVolatileManager(this, context); + SurfaceManagerFactory smf = SurfaceManagerFactory.getInstance(); + return smf.createVolatileManager(this, context); } private Color getForeground() { diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/sun/font/AttributeValues.java --- a/jdk/src/share/classes/sun/font/AttributeValues.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/sun/font/AttributeValues.java Wed Jul 05 16:37:14 2017 +0200 @@ -887,10 +887,10 @@ try { AffineTransform rtxi = rtx.createInverse(); + double dx = tx.getTranslateX(); + double dy = tx.getTranslateY(); tx.preConcatenate(rtxi); if (andTranslation) { - double dx = tx.getTranslateX(); - double dy = tx.getTranslateY(); if (dx != 0 || dy != 0) { tx.setTransform(tx.getScaleX(), tx.getShearY(), tx.getShearX(), tx.getScaleY(), 0, 0); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/sun/font/FileFontStrike.java --- a/jdk/src/share/classes/sun/font/FileFontStrike.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/sun/font/FileFontStrike.java Wed Jul 05 16:37:14 2017 +0200 @@ -27,6 +27,7 @@ import java.lang.ref.SoftReference; import java.awt.Font; +import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; @@ -105,6 +106,19 @@ boolean useNatives; NativeStrike[] nativeStrikes; + /* Used only for communication to native layer */ + private int intPtSize; + + /* Perform global initialisation needed for Windows native rasterizer */ + private static native boolean initNative(); + private static boolean isXPorLater = false; + static { + if (FontManager.isWindows && !FontManager.useT2K && + !GraphicsEnvironment.isHeadless()) { + isXPorLater = initNative(); + } + } + FileFontStrike(FileFont fileFont, FontStrikeDesc desc) { super(fileFont, desc); this.fileFont = fileFont; @@ -165,7 +179,7 @@ * should not segment unless there's another reason to do so. */ float ptSize = (float)matrix[3]; // interpreted only when meaningful. - int iSize = (int)ptSize; + int iSize = intPtSize = (int)ptSize; boolean isSimpleTx = (at.getType() & complexTX) == 0; segmentedCache = (numGlyphs > SEGSIZE << 3) || @@ -189,8 +203,26 @@ FontManager.deRegisterBadFont(fileFont); return; } - - if (fileFont.checkUseNatives() && desc.aaHint==0 && !algoStyle) { + /* First, see if native code should be used to create the glyph. + * GDI will return the integer metrics, not fractional metrics, which + * may be requested for this strike, so we would require here that : + * desc.fmHint != INTVAL_FRACTIONALMETRICS_ON + * except that the advance returned by GDI is always overwritten by + * the JDK rasteriser supplied one (see getGlyphImageFromWindows()). + */ + if (FontManager.isWindows && isXPorLater && + !FontManager.useT2K && + !GraphicsEnvironment.isHeadless() && + !fileFont.useJavaRasterizer && + (desc.aaHint == INTVAL_TEXT_ANTIALIAS_LCD_HRGB || + desc.aaHint == INTVAL_TEXT_ANTIALIAS_LCD_HBGR) && + (matrix[1] == 0.0 && matrix[2] == 0.0 && + matrix[0] == matrix[3] && + matrix[0] >= 3.0 && matrix[0] <= 100.0) && + !((TrueTypeFont)fileFont).useEmbeddedBitmapsForSize(intPtSize)) { + useNatives = true; + } + else if (fileFont.checkUseNatives() && desc.aaHint==0 && !algoStyle) { /* Check its a simple scale of a pt size in the range * where native bitmaps typically exist (6-36 pts) */ if (matrix[1] == 0.0 && matrix[2] == 0.0 && @@ -208,7 +240,16 @@ } } } - + if (FontManager.logging && FontManager.isWindows) { + FontManager.logger.info + ("Strike for " + fileFont + " at size = " + intPtSize + + " use natives = " + useNatives + + " useJavaRasteriser = " + fileFont.useJavaRasterizer + + " AAHint = " + desc.aaHint + + " Has Embedded bitmaps = " + + ((TrueTypeFont)fileFont). + useEmbeddedBitmapsForSize(intPtSize)); + } this.disposer = new FontStrikeDisposer(fileFont, desc, pScalerContext); /* Always get the image and the advance together for smaller sizes @@ -217,7 +258,12 @@ * "maximumSizeForGetImageWithAdvance". * This should be no greater than OutlineTextRender.THRESHOLD. */ - getImageWithAdvance = at.getScaleY() <= 48.0; + double maxSz = 48.0; + getImageWithAdvance = + Math.abs(at.getScaleX()) <= maxSz && + Math.abs(at.getScaleY()) <= maxSz && + Math.abs(at.getShearX()) <= maxSz && + Math.abs(at.getShearY()) <= maxSz; /* Some applications request advance frequently during layout. * If we are not getting and caching the image with the advance, @@ -250,8 +296,50 @@ return fileFont.getNumGlyphs(); } + long getGlyphImageFromNative(int glyphCode) { + if (FontManager.isWindows) { + return getGlyphImageFromWindows(glyphCode); + } else { + return getGlyphImageFromX11(glyphCode); + } + } + + /* There's no global state conflicts, so this method is not + * presently synchronized. + */ + private native long _getGlyphImageFromWindows(String family, + int style, + int size, + int glyphCode, + boolean fracMetrics); + + long getGlyphImageFromWindows(int glyphCode) { + String family = fileFont.getFamilyName(null); + int style = desc.style & Font.BOLD | desc.style & Font.ITALIC + | fileFont.getStyle(); + int size = intPtSize; + long ptr = _getGlyphImageFromWindows + (family, style, size, glyphCode, + desc.fmHint == INTVAL_FRACTIONALMETRICS_ON); + if (ptr != 0) { + /* Get the advance from the JDK rasterizer. This is mostly + * necessary for the fractional metrics case, but there are + * also some very small number (<0.25%) of marginal cases where + * there is some rounding difference between windows and JDK. + * After these are resolved, we can restrict this extra + * work to the FM case. + */ + float advance = getGlyphAdvance(glyphCode, false); + StrikeCache.unsafe.putFloat(ptr + StrikeCache.xAdvanceOffset, + advance); + return ptr; + } else { + return fileFont.getGlyphImage(pScalerContext, glyphCode); + } + } + /* Try the native strikes first, then try the fileFont strike */ - long getGlyphImageFromNative(int glyphCode) { + long getGlyphImageFromX11(int glyphCode) { long glyphPtr; char charCode = fileFont.glyphToCharMap[glyphCode]; for (int i=0;i= INVISIBLE_GLYPHS) { return StrikeCache.invisibleGlyphPtr; } - long glyphPtr; + long glyphPtr = 0L; if ((glyphPtr = getCachedGlyphPtr(glyphCode)) != 0L) { return glyphPtr; } else { if (useNatives) { glyphPtr = getGlyphImageFromNative(glyphCode); - } else { + if (glyphPtr == 0L && FontManager.logging) { + FontManager.logger.info + ("Strike for " + fileFont + + " at size = " + intPtSize + + " couldn't get native glyph for code = " + glyphCode); + } + } if (glyphPtr == 0L) { glyphPtr = fileFont.getGlyphImage(pScalerContext, glyphCode); } @@ -295,10 +389,10 @@ } else if ((images[i] = getCachedGlyphPtr(glyphCode)) != 0L) { continue; } else { - long glyphPtr; + long glyphPtr = 0L; if (useNatives) { glyphPtr = getGlyphImageFromNative(glyphCode); - } else { + } if (glyphPtr == 0L) { glyphPtr = fileFont.getGlyphImage(pScalerContext, glyphCode); } @@ -327,10 +421,11 @@ } else if ((images[i] = getCachedGlyphPtr(glyphCode)) != 0L) { continue; } else { - long glyphPtr; + long glyphPtr = 0L; if (useNatives) { glyphPtr = getGlyphImageFromNative(glyphCode); - } else { + } + if (glyphPtr == 0L) { glyphPtr = fileFont.getGlyphImage(pScalerContext, glyphCode); } @@ -454,11 +549,16 @@ } } + float getGlyphAdvance(int glyphCode) { + return getGlyphAdvance(glyphCode, true); + } + /* Metrics info is always retrieved. If the GlyphInfo address is non-zero * then metrics info there is valid and can just be copied. - * This is in user space coordinates. + * This is in user space coordinates unless getUserAdv == false. + * Device space advance should not be propagated out of this class. */ - float getGlyphAdvance(int glyphCode) { + private float getGlyphAdvance(int glyphCode, boolean getUserAdv) { float advance; if (glyphCode >= INVISIBLE_GLYPHS) { @@ -480,11 +580,11 @@ } } - if (invertDevTx != null) { + if (invertDevTx != null || !getUserAdv) { /* If there is a device transform need x & y advance to * transform back into user space. */ - advance = getGlyphMetrics(glyphCode).x; + advance = getGlyphMetrics(glyphCode, getUserAdv).x; } else { long glyphPtr; if (getImageWithAdvance) { @@ -620,6 +720,10 @@ } Point2D.Float getGlyphMetrics(int glyphCode) { + return getGlyphMetrics(glyphCode, true); + } + + private Point2D.Float getGlyphMetrics(int glyphCode, boolean getUserAdv) { Point2D.Float metrics = new Point2D.Float(); // !!! or do we force sgv user glyphs? @@ -627,7 +731,7 @@ return metrics; } long glyphPtr; - if (getImageWithAdvance) { + if (getImageWithAdvance && getUserAdv) { /* A heuristic optimisation says that for most cases its * worthwhile retrieving the image at the same time as the * metrics. So here we get the image data even if its not @@ -644,9 +748,9 @@ metrics.y = StrikeCache.unsafe.getFloat (glyphPtr + StrikeCache.yAdvanceOffset); /* advance is currently in device space, need to convert back - * into user space. + * into user space, unless getUserAdv == false. * This must not include the translation component. */ - if (invertDevTx != null) { + if (invertDevTx != null && getUserAdv) { invertDevTx.deltaTransform(metrics, metrics); } } else { @@ -675,9 +779,9 @@ if (value == null) { fileFont.getGlyphMetrics(pScalerContext, glyphCode, metrics); /* advance is currently in device space, need to convert back - * into user space. + * into user space, unless getUserAdv == false. */ - if (invertDevTx != null) { + if (invertDevTx != null && getUserAdv) { invertDevTx.deltaTransform(metrics, metrics); } value = new Point2D.Float(metrics.x, metrics.y); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/sun/font/Font2D.java --- a/jdk/src/share/classes/sun/font/Font2D.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/sun/font/Font2D.java Wed Jul 05 16:37:14 2017 +0200 @@ -241,6 +241,13 @@ if (font.isTransformed()) { glyphTx.concatenate(font.getTransform()); } + if (glyphTx.getTranslateX() != 0 || glyphTx.getTranslateY() != 0) { + glyphTx.setTransform(glyphTx.getScaleX(), + glyphTx.getShearY(), + glyphTx.getShearX(), + glyphTx.getScaleY(), + 0.0, 0.0); + } FontStrikeDesc desc = new FontStrikeDesc(devTx, glyphTx, font.getStyle(), aa, fm); return getStrike(desc, false); @@ -266,6 +273,13 @@ at.scale(ptSize, ptSize); if (font.isTransformed()) { at.concatenate(font.getTransform()); + if (at.getTranslateX() != 0 || at.getTranslateY() != 0) { + at.setTransform(at.getScaleX(), + at.getShearY(), + at.getShearX(), + at.getScaleY(), + 0.0, 0.0); + } } int aa = FontStrikeDesc.getAAHintIntVal(this, font, frc); int fm = FontStrikeDesc.getFMHintIntVal(frc.getFractionalMetricsHint()); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/sun/font/FontManager.java --- a/jdk/src/share/classes/sun/font/FontManager.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/sun/font/FontManager.java Wed Jul 05 16:37:14 2017 +0200 @@ -93,7 +93,6 @@ */ private static final int CHANNELPOOLSIZE = 20; private static int lastPoolIndex = 0; - private static int poolSize = 0; private static FileFont fontFileCache[] = new FileFont[CHANNELPOOLSIZE]; /* Need to implement a simple linked list scheme for fast @@ -245,9 +244,11 @@ osName = System.getProperty("os.name", "unknownOS"); isSolaris = osName.startsWith("SunOS"); + String t2kStr = System.getProperty("sun.java2d.font.scaler"); + if (t2kStr != null) { + useT2K = "t2k".equals(t2kStr); + } if (isSolaris) { - String t2kStr= System.getProperty("sun.java2d.font.scaler"); - useT2K = "t2k".equals(t2kStr); String version = System.getProperty("os.version", "unk"); isSolaris8 = version.equals("5.8"); isSolaris9 = version.equals("5.9"); @@ -283,29 +284,32 @@ private static native void initIDs(); public static void addToPool(FileFont font) { - boolean added = false; + + FileFont fontFileToClose = null; + int freeSlot = -1; + synchronized (fontFileCache) { - /* use poolSize to quickly detect if there's any free slots. - * This is a performance tweak based on the assumption that - * if this is executed at all often, its because there are many - * fonts being used and the pool will be full, and we will save - * a fruitless iteration + /* Avoid duplicate entries in the pool, and don't close() it, + * since this method is called only from within open(). + * Seeing a duplicate is most likely to happen if the thread + * was interrupted during a read, forcing perhaps repeated + * close and open calls and it eventually it ends up pointing + * at the same slot. */ - if (poolSize < CHANNELPOOLSIZE) { - for (int i=0; i= 0) { + fontFileCache[freeSlot] = font; + return; } else { - // is it possible for this to be the same font? - assert fontFileCache[lastPoolIndex] != font; - /* replace with new font, poolSize is unchanged. */ - fontFileCache[lastPoolIndex].close(); + /* replace with new font. */ + fontFileToClose = fontFileCache[lastPoolIndex]; fontFileCache[lastPoolIndex] = font; /* lastPoolIndex is updated so that the least recently opened * file will be closed next. @@ -313,6 +317,19 @@ lastPoolIndex = (lastPoolIndex+1) % CHANNELPOOLSIZE; } } + /* Need to close the font file outside of the synchronized block, + * since its possible some other thread is in an open() call on + * this font file, and could be holding its lock and the pool lock. + * Releasing the pool lock allows that thread to continue, so it can + * then release the lock on this font, allowing the close() call + * below to proceed. + * Also, calling close() is safe because any other thread using + * the font we are closing() synchronizes all reading, so we + * will not close the file while its in use. + */ + if (fontFileToClose != null) { + fontFileToClose.close(); + } } /* @@ -334,7 +351,6 @@ for (int i=0; i devScaleX) scaleX = devScaleX; - if (scaleY > devScaleY) scaleY = devScaleY; + /* check if rotated or sheared */ + int transformType = fullTransform.getType(); + boolean clampScale = ((transformType & + (AffineTransform.TYPE_GENERAL_ROTATION | + AffineTransform.TYPE_GENERAL_TRANSFORM)) != 0); + if (clampScale) { + if (scaleX > devScaleX) scaleX = devScaleX; + if (scaleY > devScaleY) scaleY = devScaleY; + } /* We do not need to draw anything if either scaling * factor is zero. diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/classes/sun/print/ServiceDialog.java --- a/jdk/src/share/classes/sun/print/ServiceDialog.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/classes/sun/print/ServiceDialog.java Wed Jul 05 16:37:14 2017 +0200 @@ -2149,48 +2149,55 @@ } } } - } - rbPortrait.setEnabled(pSupported); - rbLandscape.setEnabled(lSupported); - rbRevPortrait.setEnabled(rpSupported); - rbRevLandscape.setEnabled(rlSupported); - - OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory); - if (or == null || - !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) { - - or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory); - // need to validate if default is not supported - if (!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) { - or = null; - Object values = - psCurrent.getSupportedAttributeValues(orCategory, - docFlavor, - asCurrent); - if (values instanceof OrientationRequested[]) { - OrientationRequested[] orValues = + + rbPortrait.setEnabled(pSupported); + rbLandscape.setEnabled(lSupported); + rbRevPortrait.setEnabled(rpSupported); + rbRevLandscape.setEnabled(rlSupported); + + OrientationRequested or = (OrientationRequested)asCurrent.get(orCategory); + if (or == null || + !psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) { + + or = (OrientationRequested)psCurrent.getDefaultAttributeValue(orCategory); + // need to validate if default is not supported + if (!psCurrent.isAttributeValueSupported(or, docFlavor, asCurrent)) { + or = null; + values = + psCurrent.getSupportedAttributeValues(orCategory, + docFlavor, + asCurrent); + if (values instanceof OrientationRequested[]) { + OrientationRequested[] orValues = (OrientationRequested[])values; - if (orValues.length > 1) { - // get the first in the list - or = orValues[0]; + if (orValues.length > 1) { + // get the first in the list + or = orValues[0]; + } } } - } - - if (or == null) { - or = OrientationRequested.PORTRAIT; + + if (or == null) { + or = OrientationRequested.PORTRAIT; + } + asCurrent.add(or); } - asCurrent.add(or); - } - - if (or == OrientationRequested.PORTRAIT) { - rbPortrait.setSelected(true); - } else if (or == OrientationRequested.LANDSCAPE) { - rbLandscape.setSelected(true); - } else if (or == OrientationRequested.REVERSE_PORTRAIT) { - rbRevPortrait.setSelected(true); - } else { // if (or == OrientationRequested.REVERSE_LANDSCAPE) - rbRevLandscape.setSelected(true); + + if (or == OrientationRequested.PORTRAIT) { + rbPortrait.setSelected(true); + } else if (or == OrientationRequested.LANDSCAPE) { + rbLandscape.setSelected(true); + } else if (or == OrientationRequested.REVERSE_PORTRAIT) { + rbRevPortrait.setSelected(true); + } else { // if (or == OrientationRequested.REVERSE_LANDSCAPE) + rbRevLandscape.setSelected(true); + } + } else { + rbPortrait.setEnabled(pSupported); + rbLandscape.setEnabled(lSupported); + rbRevPortrait.setEnabled(rpSupported); + rbRevLandscape.setEnabled(rlSupported); + } } } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/lib/cmm/lcms/GRAY.pf Binary file jdk/src/share/lib/cmm/lcms/GRAY.pf has changed diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/lib/cmm/lcms/LINEAR_RGB.pf Binary file jdk/src/share/lib/cmm/lcms/LINEAR_RGB.pf has changed diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/lib/cmm/lcms/PYCC.pf Binary file jdk/src/share/lib/cmm/lcms/PYCC.pf has changed diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/font/freetypeScaler.c --- a/jdk/src/share/native/sun/font/freetypeScaler.c Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/font/freetypeScaler.c Wed Jul 05 16:37:14 2017 +0200 @@ -368,7 +368,7 @@ //text can not be smaller than 1 point ptsz = 1.0; } - context->ptsz = (((int) ptsz) << 6); + context->ptsz = (int)(ptsz * 64); context->transform.xx = FloatToFTFixed((float)dmat[0]/ptsz); context->transform.yx = -FloatToFTFixed((float)dmat[1]/ptsz); context->transform.xy = -FloatToFTFixed((float)dmat[2]/ptsz); @@ -779,13 +779,24 @@ } if (context->fmType == TEXT_FM_ON) { - glyphInfo->advanceX = FT26Dot6ToFloat(ftglyph->advance.x); - glyphInfo->advanceY = FT26Dot6ToFloat(-ftglyph->advance.y); - } else { + double advh = FTFixedToFloat(ftglyph->linearHoriAdvance); glyphInfo->advanceX = - (float) ROUND(FT26Dot6ToFloat(ftglyph->advance.x)); + (float) (advh * FTFixedToFloat(context->transform.xx)); glyphInfo->advanceY = - (float) ROUND(FT26Dot6ToFloat(-ftglyph->advance.y)); + (float) (advh * FTFixedToFloat(context->transform.xy)); + } else { + if (!ftglyph->advance.y) { + glyphInfo->advanceX = + (float) ROUND(FT26Dot6ToFloat(ftglyph->advance.x)); + glyphInfo->advanceY = 0; + } else if (!ftglyph->advance.x) { + glyphInfo->advanceX = 0; + glyphInfo->advanceY = + (float) ROUND(FT26Dot6ToFloat(-ftglyph->advance.y)); + } else { + glyphInfo->advanceX = FT26Dot6ToFloat(ftglyph->advance.x); + glyphInfo->advanceY = FT26Dot6ToFloat(-ftglyph->advance.y); + } } if (imageSize == 0) { @@ -974,7 +985,7 @@ FT_Outline_Translate(&ftglyph->outline, FloatToF26Dot6(xpos), - FloatToF26Dot6(ypos)); + -FloatToF26Dot6(ypos)); return &ftglyph->outline; } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/AlphaMacros.h --- a/jdk/src/share/native/sun/java2d/loops/AlphaMacros.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/AlphaMacros.h Wed Jul 05 16:37:14 2017 +0200 @@ -416,7 +416,8 @@ MultiplyAndStore ## STRATEGY ## Comps(res, \ srcF, res);\ } \ - if (!(DST ## IsPremultiplied) && resA && \ + if (!(DST ## IsOpaque) && \ + !(DST ## IsPremultiplied) && resA && \ resA < MaxValFor ## STRATEGY) \ { \ DivideAndStore ## STRATEGY ## Comps(res, \ @@ -475,7 +476,8 @@ MultiplyAndStore ## STRATEGY ## Comps(res, \ srcF, res); \ } \ - if (!(DST ## IsPremultiplied) && resA && \ + if (!(DST ## IsOpaque) && \ + !(DST ## IsPremultiplied) && resA && \ resA < MaxValFor ## STRATEGY) \ { \ DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ @@ -797,7 +799,8 @@ Store ## STRATEGY ## CompsUsingOp(res, +=, tmp); \ } \ } \ - if (!(TYPE ## IsPremultiplied) && resA && \ + if (!(TYPE ## IsOpaque) && \ + !(TYPE ## IsPremultiplied) && resA && \ resA < MaxValFor ## STRATEGY) \ { \ DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ @@ -831,7 +834,8 @@ Postload ## STRATEGY ## From ## TYPE(pRas, DstPix, res); \ MultiplyAddAndStore ## STRATEGY ## Comps(res, \ dstF, res, src); \ - if (!(TYPE ## IsPremultiplied) && resA && \ + if (!(TYPE ## IsOpaque) && \ + !(TYPE ## IsPremultiplied) && resA && \ resA < MaxValFor ## STRATEGY) \ { \ DivideAndStore ## STRATEGY ## Comps(res, res, resA); \ diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/ByteGray.h --- a/jdk/src/share/native/sun/java2d/loops/ByteGray.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/ByteGray.h Wed Jul 05 16:37:14 2017 +0200 @@ -36,6 +36,8 @@ typedef jubyte ByteGrayPixelType; typedef jubyte ByteGrayDataType; +#define ByteGrayIsOpaque 1 + #define ByteGrayPixelStride 1 #define ByteGrayBitsPerPixel 8 diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/FourByteAbgr.h --- a/jdk/src/share/native/sun/java2d/loops/FourByteAbgr.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/FourByteAbgr.h Wed Jul 05 16:37:14 2017 +0200 @@ -34,6 +34,8 @@ typedef jint FourByteAbgrPixelType; typedef jubyte FourByteAbgrDataType; +#define FourByteAbgrIsOpaque 0 + #define FourByteAbgrPixelStride 4 #define DeclareFourByteAbgrLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/FourByteAbgrPre.h --- a/jdk/src/share/native/sun/java2d/loops/FourByteAbgrPre.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/FourByteAbgrPre.h Wed Jul 05 16:37:14 2017 +0200 @@ -34,6 +34,8 @@ typedef jint FourByteAbgrPrePixelType; typedef jubyte FourByteAbgrPreDataType; +#define FourByteAbgrPreIsOpaque 0 + #define FourByteAbgrPrePixelStride 4 #define DeclareFourByteAbgrPreLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/Index12Gray.h --- a/jdk/src/share/native/sun/java2d/loops/Index12Gray.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/Index12Gray.h Wed Jul 05 16:37:14 2017 +0200 @@ -37,6 +37,8 @@ typedef jushort Index12GrayPixelType; typedef jushort Index12GrayDataType; +#define Index12GrayIsOpaque 1 + #define Index12GrayPixelStride 2 #define Index12GrayBitsPerPixel 12 diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/Index8Gray.h --- a/jdk/src/share/native/sun/java2d/loops/Index8Gray.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/Index8Gray.h Wed Jul 05 16:37:14 2017 +0200 @@ -37,6 +37,8 @@ typedef jubyte Index8GrayPixelType; typedef jubyte Index8GrayDataType; +#define Index8GrayIsOpaque 1 + #define Index8GrayPixelStride 1 #define Index8GrayBitsPerPixel 8 diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/IntArgb.h --- a/jdk/src/share/native/sun/java2d/loops/IntArgb.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/IntArgb.h Wed Jul 05 16:37:14 2017 +0200 @@ -38,6 +38,8 @@ typedef jint IntArgbPixelType; typedef jint IntArgbDataType; +#define IntArgbIsOpaque 0 + #define IntArgbPixelStride 4 #define DeclareIntArgbLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/IntArgbBm.h --- a/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/IntArgbBm.h Wed Jul 05 16:37:14 2017 +0200 @@ -38,6 +38,8 @@ typedef jint IntArgbBmPixelType; typedef jint IntArgbBmDataType; +#define IntArgbBmIsOpaque 0 + #define IntArgbBmPixelStride 4 #define DeclareIntArgbBmLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/IntArgbPre.h --- a/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/IntArgbPre.h Wed Jul 05 16:37:14 2017 +0200 @@ -36,6 +36,8 @@ typedef jint IntArgbPrePixelType; typedef jint IntArgbPreDataType; +#define IntArgbPreIsOpaque 0 + #define IntArgbPrePixelStride 4 #define DeclareIntArgbPreLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/IntBgr.h --- a/jdk/src/share/native/sun/java2d/loops/IntBgr.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/IntBgr.h Wed Jul 05 16:37:14 2017 +0200 @@ -38,6 +38,8 @@ typedef jint IntBgrPixelType; typedef jint IntBgrDataType; +#define IntBgrIsOpaque 1 + #define IntBgrPixelStride 4 #define DeclareIntBgrLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/IntRgb.h --- a/jdk/src/share/native/sun/java2d/loops/IntRgb.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/IntRgb.h Wed Jul 05 16:37:14 2017 +0200 @@ -38,6 +38,8 @@ typedef jint IntRgbPixelType; typedef jint IntRgbDataType; +#define IntRgbIsOpaque 1 + #define IntRgbPixelStride 4 #define DeclareIntRgbLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/IntRgbx.h --- a/jdk/src/share/native/sun/java2d/loops/IntRgbx.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/IntRgbx.h Wed Jul 05 16:37:14 2017 +0200 @@ -36,6 +36,8 @@ typedef jint IntRgbxPixelType; typedef jint IntRgbxDataType; +#define IntRgbxIsOpaque 1 + #define IntRgbxPixelStride 4 #define DeclareIntRgbxLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/LoopMacros.h --- a/jdk/src/share/native/sun/java2d/loops/LoopMacros.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/LoopMacros.h Wed Jul 05 16:37:14 2017 +0200 @@ -1610,8 +1610,12 @@ MUL8(SRC_PREFIX ## A, mixValSrc); \ MultMultAddAndStore4ByteArgbComps(dst, mixValDst, dst, \ mixValSrc, SRC_PREFIX); \ - Store ## DST ## From4ByteArgb(DST_PTR, pix, PIXEL_INDEX, \ - dstA, dstR, dstG, dstB); \ + if (!(DST ## IsOpaque) && \ + !(DST ## IsPremultiplied) && dstA && dstA < 255) { \ + DivideAndStore4ByteArgbComps(dst, dst, dstA); \ + } \ + Store ## DST ## From4ByteArgbComps(DST_PTR, pix, \ + PIXEL_INDEX, dst); \ } else { \ Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \ FG_PIXEL, PREFIX); \ @@ -1793,8 +1797,12 @@ dstR = gammaLut[dstR]; \ dstG = gammaLut[dstG]; \ dstB = gammaLut[dstB]; \ - Store ## DST ## From4ByteArgb(DST_PTR, pix, PIXEL_INDEX, \ - dstA, dstR, dstG, dstB); \ + if (!(DST ## IsOpaque) && \ + !(DST ## IsPremultiplied) && dstA && dstA < 255) { \ + DivideAndStore4ByteArgbComps(dst, dst, dstA); \ + } \ + Store ## DST ## From4ByteArgbComps(DST_PTR, pix, \ + PIXEL_INDEX, dst); \ } else { \ Store ## DST ## PixelData(DST_PTR, PIXEL_INDEX, \ FG_PIXEL, PREFIX); \ diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/ThreeByteBgr.h --- a/jdk/src/share/native/sun/java2d/loops/ThreeByteBgr.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/ThreeByteBgr.h Wed Jul 05 16:37:14 2017 +0200 @@ -34,6 +34,8 @@ typedef jint ThreeByteBgrPixelType; typedef jubyte ThreeByteBgrDataType; +#define ThreeByteBgrIsOpaque 1 + #define ThreeByteBgrPixelStride 3 #define DeclareThreeByteBgrLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h --- a/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/Ushort4444Argb.h Wed Jul 05 16:37:14 2017 +0200 @@ -34,6 +34,8 @@ typedef jushort Ushort4444ArgbPixelType; typedef jushort Ushort4444ArgbDataType; +#define Ushort4444ArgbIsOpaque 0 + #define Ushort4444ArgbPixelStride 2 #define DeclareUshort4444ArgbLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/Ushort555Rgb.h --- a/jdk/src/share/native/sun/java2d/loops/Ushort555Rgb.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/Ushort555Rgb.h Wed Jul 05 16:37:14 2017 +0200 @@ -34,6 +34,8 @@ typedef jushort Ushort555RgbPixelType; typedef jushort Ushort555RgbDataType; +#define Ushort555RgbIsOpaque 1 + #define Ushort555RgbPixelStride 2 #define DeclareUshort555RgbLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/Ushort555Rgbx.h --- a/jdk/src/share/native/sun/java2d/loops/Ushort555Rgbx.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/Ushort555Rgbx.h Wed Jul 05 16:37:14 2017 +0200 @@ -34,6 +34,8 @@ typedef jushort Ushort555RgbxPixelType; typedef jushort Ushort555RgbxDataType; +#define Ushort555RgbxIsOpaque 1 + #define Ushort555RgbxPixelStride 2 #define DeclareUshort555RgbxLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/Ushort565Rgb.h --- a/jdk/src/share/native/sun/java2d/loops/Ushort565Rgb.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/Ushort565Rgb.h Wed Jul 05 16:37:14 2017 +0200 @@ -34,6 +34,8 @@ typedef jushort Ushort565RgbPixelType; typedef jushort Ushort565RgbDataType; +#define Ushort565RgbIsOpaque 1 + #define Ushort565RgbPixelStride 2 #define DeclareUshort565RgbLoadVars(PREFIX) diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/share/native/sun/java2d/loops/UshortGray.h --- a/jdk/src/share/native/sun/java2d/loops/UshortGray.h Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/share/native/sun/java2d/loops/UshortGray.h Wed Jul 05 16:37:14 2017 +0200 @@ -36,6 +36,8 @@ typedef jushort UshortGrayPixelType; typedef jushort UshortGrayDataType; +#define UshortGrayIsOpaque 1 + #define UshortGrayPixelStride 2 #define UshortGrayBitsPerPixel 16 diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java --- a/jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java Wed Jul 05 16:37:14 2017 +0200 @@ -48,6 +48,8 @@ import sun.font.FontManager; import sun.font.NativeFont; import sun.java2d.SunGraphicsEnvironment; +import sun.java2d.SurfaceManagerFactory; +import sun.java2d.UnixSurfaceManagerFactory; /** * This is an implementation of a GraphicsEnvironment object for the @@ -177,6 +179,10 @@ return null; } }); + + // Install the correct surface manager factory. + SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory()); + } private static boolean glxAvailable; diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/classes/sun/java2d/SurfaceManagerFactory.java --- a/jdk/src/solaris/classes/sun/java2d/SurfaceManagerFactory.java Thu May 22 09:37:44 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package sun.java2d; - -import java.awt.GraphicsConfiguration; -import java.awt.image.BufferedImage; -import sun.awt.X11GraphicsConfig; -import sun.awt.image.SunVolatileImage; -import sun.awt.image.SurfaceManager; -import sun.awt.image.VolatileSurfaceManager; -import sun.java2d.opengl.GLXGraphicsConfig; -import sun.java2d.opengl.GLXVolatileSurfaceManager; -import sun.java2d.x11.X11VolatileSurfaceManager; - -/** - * This is a factory class with static methods for creating a - * platform-specific instance of a particular SurfaceManager. Each platform - * (Windows, Unix, etc.) has its own specialized SurfaceManagerFactory. - */ -public class SurfaceManagerFactory { - /** - * Creates a new instance of a VolatileSurfaceManager given any - * arbitrary SunVolatileImage. An optional context Object can be supplied - * as a way for the caller to pass pipeline-specific context data to - * the VolatileSurfaceManager (such as a backbuffer handle, for example). - * - * For Unix platforms, this method returns either an X11- or a GLX- - * specific VolatileSurfaceManager based on the GraphicsConfiguration - * under which the SunVolatileImage was created. - */ - public static VolatileSurfaceManager - createVolatileManager(SunVolatileImage vImg, - Object context) - { - GraphicsConfiguration gc = vImg.getGraphicsConfig(); - if (gc instanceof GLXGraphicsConfig) { - return new GLXVolatileSurfaceManager(vImg, context); - } else { - return new X11VolatileSurfaceManager(vImg, context); - } - } -} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +package sun.java2d; + +import java.awt.GraphicsConfiguration; + +import sun.awt.image.SunVolatileImage; +import sun.awt.image.VolatileSurfaceManager; +import sun.java2d.opengl.GLXGraphicsConfig; +import sun.java2d.opengl.GLXVolatileSurfaceManager; +import sun.java2d.x11.X11VolatileSurfaceManager; + +/** + * The SurfaceManagerFactory that creates VolatileSurfaceManager + * implementations for the Unix volatile images. + */ +public class UnixSurfaceManagerFactory extends SurfaceManagerFactory { + + /** + * Creates a new instance of a VolatileSurfaceManager given any + * arbitrary SunVolatileImage. An optional context Object can be supplied + * as a way for the caller to pass pipeline-specific context data to + * the VolatileSurfaceManager (such as a backbuffer handle, for example). + * + * For Unix platforms, this method returns either an X11- or a GLX- + * specific VolatileSurfaceManager based on the GraphicsConfiguration + * under which the SunVolatileImage was created. + */ + public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg, + Object context) + { + GraphicsConfiguration gc = vImg.getGraphicsConfig(); + if (gc instanceof GLXGraphicsConfig) { + return new GLXVolatileSurfaceManager(vImg, context); + } else { + return new X11VolatileSurfaceManager(vImg, context); + } + } + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/classes/sun/print/AttributeClass.java --- a/jdk/src/solaris/classes/sun/print/AttributeClass.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/classes/sun/print/AttributeClass.java Wed Jul 05 16:37:14 2017 +0200 @@ -32,6 +32,7 @@ private int nameLen; private Object myValue; + public static final int TAG_UNSUPPORTED_VALUE = 0x10; public static final int TAG_INT = 0x21; public static final int TAG_BOOL = 0x22; public static final int TAG_ENUM = 0x23; diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/classes/sun/print/CUPSPrinter.java --- a/jdk/src/solaris/classes/sun/print/CUPSPrinter.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/classes/sun/print/CUPSPrinter.java Wed Jul 05 16:37:14 2017 +0200 @@ -333,7 +333,7 @@ AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE, new AttributeClass("requested-attributes", AttributeClass.TAG_KEYWORD, - "printer-name") + "printer-uri-supported") }; if (IPPPrintService.writeIPPRequest(os, @@ -354,7 +354,7 @@ ArrayList printerNames = new ArrayList(); for (int i=0; i< responseMap.length; i++) { AttributeClass attribClass = (AttributeClass) - responseMap[i].get("printer-name"); + responseMap[i].get("printer-uri-supported"); if (attribClass != null) { String nameStr = attribClass.getStringValue(); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/classes/sun/print/IPPPrintService.java --- a/jdk/src/solaris/classes/sun/print/IPPPrintService.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/classes/sun/print/IPPPrintService.java Wed Jul 05 16:37:14 2017 +0200 @@ -335,6 +335,38 @@ } + IPPPrintService(String name, String uriStr, boolean isCups) { + if ((name == null) || (uriStr == null)){ + throw new IllegalArgumentException("null uri or printer name"); + } + printer = name; + supportedDocFlavors = null; + supportedCats = null; + mediaSizeNames = null; + customMediaSizeNames = null; + mediaTrays = null; + cps = null; + init = false; + defaultMediaIndex = -1; + try { + myURL = + new URL(uriStr.replaceFirst("ipp", "http")); + } catch (Exception e) { + IPPPrintService.debug_println(debugPrefix+ + " IPPPrintService, myURL="+ + myURL+" Exception= "+ + e); + } + + isCupsPrinter = isCups; + try { + myURI = new URI(uriStr); + debug_println(debugPrefix+"IPPPrintService myURI : "+myURI); + } catch (java.net.URISyntaxException e) { + throw new IllegalArgumentException("invalid uri"); + } + } + /* * Initialize mediaSizeNames, mediaTrays and other attributes. @@ -375,7 +407,7 @@ return; } catch (Exception e) { IPPPrintService.debug_println(debugPrefix+ - " error creating CUPSPrinter"); + " error creating CUPSPrinter e="+e); } } @@ -621,17 +653,8 @@ } } } else if (category == OrientationRequested.class) { - if (flavor == null || - flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || - flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { - // Orientation is emulated in Pageable/Printable flavors - // so we report the 3 orientations as supported. - OrientationRequested []orientSup = new OrientationRequested[3]; - orientSup[0] = OrientationRequested.PORTRAIT; - orientSup[1] = OrientationRequested.LANDSCAPE; - orientSup[2] = OrientationRequested.REVERSE_LANDSCAPE; - return orientSup; - } + boolean revPort = false; + OrientationRequested[] orientSup = null; AttributeClass attribClass = (getAttMap != null) ? (AttributeClass)getAttMap.get("orientation-requested-supported") @@ -639,7 +662,7 @@ if (attribClass != null) { int[] orientArray = attribClass.getArrayOfIntValues(); if ((orientArray != null) && (orientArray.length > 0)) { - OrientationRequested[] orientSup = + orientSup = new OrientationRequested[orientArray.length]; for (int i=0; i= AttributeClass.TAG_INT && + while (response[0] >= AttributeClass.TAG_UNSUPPORTED_VALUE && response[0] <= AttributeClass.TAG_MEMBER_ATTRNAME) { // read name length len = ois.readShort(); @@ -1710,12 +1777,16 @@ respList.add(responseMap); responseMap = new HashMap(); } - AttributeClass ac = - new AttributeClass(attribStr, - valTagByte, - outArray); - responseMap.put(ac.getName(), ac); + // exclude those that are unknown + if (valTagByte >= AttributeClass.TAG_INT) { + AttributeClass ac = + new AttributeClass(attribStr, + valTagByte, + outArray); + + responseMap.put(ac.getName(), ac); + } outObj = new ByteArrayOutputStream(); counter = 0; //reset counter diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java --- a/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/classes/sun/print/UnixPrintServiceLookup.java Wed Jul 05 16:37:14 2017 +0200 @@ -196,11 +196,20 @@ // refreshes "printServices" public synchronized void refreshServices() { - String[] printers; /* excludes the default printer */ + /* excludes the default printer */ + String[] printers = null; // array of printer names + String[] printerURIs = null; //array of printer URIs getDefaultPrintService(); if (CUPSPrinter.isCupsRunning()) { - printers = CUPSPrinter.getAllPrinters(); + printerURIs = CUPSPrinter.getAllPrinters(); + if ((printerURIs != null) && (printerURIs.length > 0)) { + printers = new String[printerURIs.length]; + for (int i=0; i XScreenCount(awt_display)) { int32_t idx; DTRACE_PRINTLN("Enabling Xinerama support"); usingXinerama = True; @@ -701,7 +701,8 @@ if (XineramaSolarisFunc != NULL) { DTRACE_PRINTLN("calling XineramaGetInfo func on Solaris"); if ((*XineramaSolarisFunc)(awt_display, 0, &fbrects[0], - &fbhints[0], &locNumScr) != 0) + &fbhints[0], &locNumScr) != 0 && + locNumScr > XScreenCount(awt_display)) { DTRACE_PRINTLN("Enabling Xinerama support"); usingXinerama = True; @@ -1626,6 +1627,8 @@ #define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI +typedef Status + (*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp); typedef XRRScreenConfiguration* (*XRRGetScreenInfoType)(Display *dpy, Drawable root); typedef void @@ -1650,6 +1653,7 @@ short rate, Time timestamp); +static XRRQueryVersionType awt_XRRQueryVersion; static XRRGetScreenInfoType awt_XRRGetScreenInfo; static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo; static XRRConfigRatesType awt_XRRConfigRates; @@ -1672,6 +1676,8 @@ static jboolean X11GD_InitXrandrFuncs(JNIEnv *env) { + int rr_maj_ver = 0, rr_min_ver = 0; + void *pLibRandR = dlopen("libXrandr.so.2", RTLD_LAZY | RTLD_LOCAL); if (pLibRandR == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -1679,6 +1685,41 @@ return JNI_FALSE; } + LOAD_XRANDR_FUNC(XRRQueryVersion); + + if (!(*awt_XRRQueryVersion)(awt_display, &rr_maj_ver, &rr_min_ver)) { + J2dRlsTraceLn(J2D_TRACE_ERROR, + "X11GD_InitXrandrFuncs: XRRQueryVersion returned an error status"); + dlclose(pLibRandR); + return JNI_FALSE; + } + + if (usingXinerama) { + /* + * We can proceed as long as this is RANDR 1.2 or above. + * As of Xorg server 1.3 onwards the Xinerama backend may actually be + * a fake one provided by RANDR itself. See Java bug 6636469 for info. + */ + if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) { + J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. " + "Xinerama is active and Xrandr version is %d.%d", + rr_maj_ver, rr_min_ver); + dlclose(pLibRandR); + return JNI_FALSE; + } + + /* + * REMIND: Fullscreen mode doesn't work quite right with multi-monitor + * setups and RANDR 1.2. So for now we also require a single screen. + */ + if (awt_numScreens > 1 ) { + J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. " + "Multiple screens in use"); + dlclose(pLibRandR); + return JNI_FALSE; + } + } + LOAD_XRANDR_FUNC(XRRGetScreenInfo); LOAD_XRANDR_FUNC(XRRFreeScreenConfigInfo); LOAD_XRANDR_FUNC(XRRConfigRates); @@ -1814,15 +1855,6 @@ int opcode = 0, firstEvent = 0, firstError = 0; jboolean ret; - if (usingXinerama) { - /* - * REMIND: we'll just punt if Xinerama is enabled; we can remove this - * restriction in the future if we find Xinerama and XRandR playing - * well together... - */ - return JNI_FALSE; - } - AWT_LOCK(); ret = (jboolean)XQueryExtension(awt_display, "RANDR", &opcode, &firstEvent, &firstError); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/native/sun/java2d/loops/vis_FourByteAbgr.c --- a/jdk/src/solaris/native/sun/java2d/loops/vis_FourByteAbgr.c Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/native/sun/java2d/loops/vis_FourByteAbgr.c Wed Jul 05 16:37:14 2017 +0200 @@ -1936,6 +1936,7 @@ for (j = 0; j < height; j++) { mlib_u8 *src = (void*)pixels; mlib_s32 *dst, *dst_end; + mlib_u8 *dst_start; if ((mlib_s32)dstBase & 3) { COPY_NA(dstBase, pbuff, width*sizeof(mlib_s32)); @@ -1943,8 +1944,14 @@ } else { dst = (void*)dstBase; } + dst_start = (void*)dst; dst_end = dst + width; + /* Need to reset the GSR from the values set by the + * convert call near the end of this loop. + */ + vis_write_gsr(7 << 0); + if ((mlib_s32)dst & 7) { pix = *src++; dd = vis_fpadd16(MUL8_VIS(srcG_f, pix), d_half); @@ -1984,8 +1991,13 @@ dst++; } + ADD_SUFF(IntArgbPreToIntArgbConvert)(dst_start, dst_start, + width, 1, + pRasInfo, pRasInfo, + pPrim, pCompInfo); + if ((mlib_s32)dstBase & 3) { - COPY_NA(pbuff, dstBase, width*sizeof(mlib_s32)); + COPY_NA(dst_start, dstBase, width*sizeof(mlib_s32)); } PTR_ADD(dstBase, scan); diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/native/sun/java2d/loops/vis_FourByteAbgrPre.c --- a/jdk/src/solaris/native/sun/java2d/loops/vis_FourByteAbgrPre.c Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/native/sun/java2d/loops/vis_FourByteAbgrPre.c Wed Jul 05 16:37:14 2017 +0200 @@ -181,6 +181,7 @@ d_half = vis_to_double_dup((1 << (16 + 6)) | (1 << 6)); srcG_f = vis_to_float(argbcolor); + ARGB2ABGR_FL(srcG_f); for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { const jubyte *pixels; @@ -238,8 +239,33 @@ mlib_u8 *src = (void*)pixels; mlib_s32 *dst, *dst_end; mlib_u8 *dst8; + mlib_u8* dst_start = dstBase; - ADD_SUFF(FourByteAbgrPreToIntArgbConvert)(dstBase, pbuff, width, 1, + /* + * Typically the inner loop here works on Argb input data, an + * Argb color, and produces ArgbPre output data. To use that + * standard approach we would need a FourByteAbgrPre to IntArgb + * converter for the front end and an IntArgbPre to FourByteAbgrPre + * converter for the back end. The converter exists for the + * front end, but it is a workaround implementation that uses a 2 + * stage conversion and an intermediate buffer that is allocated + * on every call. The converter for the back end doesn't really + * exist, but we could reuse the IntArgb to FourByteAbgr converter + * to do the same work - at the cost of swapping the components as + * we copy the data back. All of this is more work than we really + * need so we use an alternate procedure: + * - Copy the data into an int-aligned temporary buffer (if needed) + * - Convert the data from FourByteAbgrPre to IntAbgr by using the + * IntArgbPre to IntArgb converter in the int-aligned buffer. + * - Swap the color data to Abgr so that the inner loop goes from + * IntAbgr data to IntAbgrPre data + * - Simply copy the IntAbgrPre data back into place. + */ + if (((mlib_s32)dstBase) & 3) { + COPY_NA(dstBase, pbuff, width*sizeof(mlib_s32)); + dst_start = pbuff; + } + ADD_SUFF(IntArgbPreToIntArgbConvert)(dst_start, pbuff, width, 1, pRasInfo, pRasInfo, pPrim, pCompInfo); @@ -283,9 +309,7 @@ dst++; } - ADD_SUFF(IntArgbToFourByteAbgrPreConvert)(pbuff, dstBase, width, 1, - pRasInfo, pRasInfo, - pPrim, pCompInfo); + COPY_NA(pbuff, dstBase, width*sizeof(mlib_s32)); src = (void*)pixels; dst8 = (void*)dstBase; diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/native/sun/java2d/loops/vis_IntArgb.c --- a/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgb.c Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgb.c Wed Jul 05 16:37:14 2017 +0200 @@ -428,6 +428,11 @@ dst = (void*)dstBase; dst_end = dst + width; + /* Clearing the Graphics Status Register is necessary otherwise + * left over scale settings affect the pack instructions. + */ + vis_write_gsr(0 << 3); + if ((mlib_s32)dst & 7) { pix = *src++; dd = vis_fpadd16(MUL8_VIS(srcG_f, pix), d_half); @@ -467,6 +472,9 @@ dst++; } + ADD_SUFF(IntArgbPreToIntArgbConvert)(dstBase, dstBase, width, 1, + pRasInfo, pRasInfo, + pPrim, pCompInfo); PTR_ADD(dstBase, scan); pixels += rowBytes; } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre.c --- a/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre.c Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/solaris/native/sun/java2d/loops/vis_IntArgbPre.c Wed Jul 05 16:37:14 2017 +0200 @@ -1193,10 +1193,6 @@ dst++; } - ADD_SUFF(IntArgbToIntArgbPreConvert)(dstBase, dstBase, width, 1, - pRasInfo, pRasInfo, - pPrim, pCompInfo); - PTR_ADD(dstBase, scan); pixels += rowBytes; } diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java --- a/jdk/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java Wed Jul 05 16:37:14 2017 +0200 @@ -42,6 +42,8 @@ import sun.awt.windows.WToolkit; import sun.font.FontManager; import sun.java2d.SunGraphicsEnvironment; +import sun.java2d.SurfaceManagerFactory; +import sun.java2d.WindowsSurfaceManagerFactory; import sun.java2d.windows.WindowsFlags; /** @@ -64,6 +66,9 @@ WindowsFlags.initFlags(); initDisplayWrapper(); eudcFontFileName = getEUDCFontFile(); + + // Install correct surface manager factory. + SurfaceManagerFactory.setInstance(new WindowsSurfaceManagerFactory()); } /** @@ -260,6 +265,7 @@ try { while (!found && parser.hasMoreTokens()) { String newPath = parser.nextToken(); + boolean ujr = newPath.equals(jreFontDirName); File theFile = new File(newPath, fontFileName); if (theFile.canRead()) { found = true; @@ -267,11 +273,11 @@ if (defer) { FontManager.registerDeferredFont(fontFileName, path, nativeNames, - fontFormat, true, + fontFormat, ujr, fontRank); } else { FontManager.registerFontFile(path, nativeNames, - fontFormat, true, + fontFormat, ujr, fontRank); } break; @@ -296,7 +302,7 @@ } public static void registerJREFontsForPrinting() { - String pathName = null; + final String pathName; synchronized (Win32GraphicsEnvironment.class) { GraphicsEnvironment.getLocalGraphicsEnvironment(); if (fontsForPrinting == null) { @@ -305,15 +311,21 @@ pathName = fontsForPrinting; fontsForPrinting = null; } - File f1 = new File(pathName); - String[] ls = f1.list(new TTFilter()); - if (ls == null) { - return; - } - for (int i=0; i devScaleX) scaleX = devScaleX; - if (scaleY > devScaleY) scaleY = devScaleY; + + /* check if rotated or sheared */ + int transformType = fullTransform.getType(); + boolean clampScale = ((transformType & + (AffineTransform.TYPE_GENERAL_ROTATION | + AffineTransform.TYPE_GENERAL_TRANSFORM)) != 0); + if (clampScale) { + if (scaleX > devScaleX) scaleX = devScaleX; + if (scaleY > devScaleY) scaleY = devScaleY; + } /* We do not need to draw anything if either scaling * factor is zero. diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/windows/classes/sun/java2d/SurfaceManagerFactory.java --- a/jdk/src/windows/classes/sun/java2d/SurfaceManagerFactory.java Thu May 22 09:37:44 2008 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Sun designates this - * particular file as subject to the "Classpath" exception as provided - * by Sun in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. - */ - -package sun.java2d; - -import java.awt.GraphicsConfiguration; -import java.awt.image.BufferedImage; -import sun.awt.image.SunVolatileImage; -import sun.awt.image.SurfaceManager; -import sun.awt.image.VolatileSurfaceManager; -import sun.java2d.opengl.WGLGraphicsConfig; -import sun.java2d.opengl.WGLVolatileSurfaceManager; -import sun.java2d.windows.WindowsFlags; -import sun.java2d.windows.WinVolatileSurfaceManager; - -/** - * This is a factory class with static methods for creating a - * platform-specific instance of a particular SurfaceManager. Each platform - * (Windows, Unix, etc.) has its own specialized SurfaceManagerFactory. - */ -public class SurfaceManagerFactory { - /** - * Creates a new instance of a VolatileSurfaceManager given any - * arbitrary SunVolatileImage. An optional context Object can be supplied - * as a way for the caller to pass pipeline-specific context data to - * the VolatileSurfaceManager (such as a backbuffer handle, for example). - * - * For Windows platforms, this method returns a Windows-specific - * VolatileSurfaceManager. - */ - public static VolatileSurfaceManager - createVolatileManager(SunVolatileImage vImg, - Object context) - { - GraphicsConfiguration gc = vImg.getGraphicsConfig(); - if (gc instanceof WGLGraphicsConfig) { - return new WGLVolatileSurfaceManager(vImg, context); - } else { - return new WinVolatileSurfaceManager(vImg, context); - } - } -} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/windows/classes/sun/java2d/WindowsSurfaceManagerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/windows/classes/sun/java2d/WindowsSurfaceManagerFactory.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d; + +import java.awt.GraphicsConfiguration; +import java.awt.image.BufferedImage; +import sun.awt.image.SunVolatileImage; +import sun.awt.image.SurfaceManager; +import sun.awt.image.VolatileSurfaceManager; +import sun.java2d.opengl.WGLGraphicsConfig; +import sun.java2d.opengl.WGLVolatileSurfaceManager; +import sun.java2d.windows.WindowsFlags; +import sun.java2d.windows.WinVolatileSurfaceManager; + +/** + * The SurfaceManagerFactory that creates VolatileSurfaceManager + * implementations for the Windows volatile images. + */ +public class WindowsSurfaceManagerFactory extends SurfaceManagerFactory { + + /** + * Creates a new instance of a VolatileSurfaceManager given any + * arbitrary SunVolatileImage. An optional context Object can be supplied + * as a way for the caller to pass pipeline-specific context data to + * the VolatileSurfaceManager (such as a backbuffer handle, for example). + * + * For Windows platforms, this method returns a Windows-specific + * VolatileSurfaceManager. + */ + public VolatileSurfaceManager createVolatileManager(SunVolatileImage vImg, + Object context) + { + GraphicsConfiguration gc = vImg.getGraphicsConfig(); + if (gc instanceof WGLGraphicsConfig) { + return new WGLVolatileSurfaceManager(vImg, context); + } else { + return new WinVolatileSurfaceManager(vImg, context); + } + } + +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/src/windows/native/sun/font/lcdglyph.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/windows/native/sun/font/lcdglyph.c Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,481 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * The function here is used to get a GDI rasterized LCD glyph and place it + * into the JDK glyph cache. The benefit is rendering fidelity for the + * most common cases, with no impact on the 2D rendering pipelines. + * + * Requires that the font and graphics are unrotated, and the scale is + * a simple one, and the font is a TT font registered with windows. + * Those conditions are established by the calling code. + * + * This code + * - Receives the family name, style, and size of the font + * and creates a Font object. + * - Create a surface from which we can get a DC : must be 16 bit or more. + * Ideally we'd be able to specify the depth of this, but in practice we + * have to accept it will be the same as the default screen. + * - Selects the GDI font on to the device + * - Uses GetGlyphOutline to estimate the bounds. + * - Creates a DIB on to which to blit the image. + * - Creates a GlyphInfo structure and copies the GDI glyph and offsets + * into the glyph which is returned. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "fontscalerdefs.h" + +/* Some of these are also defined in awtmsg.h but I don't want a dependency + * on that here. They are needed here - and in awtmsg.h - until we + * move up our build to define WIN32_WINNT >= 0x501 (ie XP), since MS + * headers will not define them otherwise. + */ +#ifndef SPI_GETFONTSMOOTHINGTYPE +#define SPI_GETFONTSMOOTHINGTYPE 0x200A +#endif //SPI_GETFONTSMOOTHINGTYPE + +#ifndef SPI_GETFONTSMOOTHINGCONTRAST +#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C +#endif //SPI_GETFONTSMOOTHINGCONTRAST + +#ifndef SPI_GETFONTSMOOTHINGORIENTATION +#define SPI_GETFONTSMOOTHINGORIENTATION 0x2012 +#endif //SPI_GETFONTSMOOTHINGORIENTATION + +#ifndef FE_FONTSMOOTHINGORIENTATIONBGR +#define FE_FONTSMOOTHINGORIENTATIONBGR 0x0000 +#endif //FE_FONTSMOOTHINGORIENTATIONBGR + +#ifndef FE_FONTSMOOTHINGORIENTATIONRGB +#define FE_FONTSMOOTHINGORIENTATIONRGB 0x0001 +#endif //FE_FONTSMOOTHINGORIENTATIONRGB + +#define MIN_GAMMA 100 +#define MAX_GAMMA 220 +#define LCDLUTCOUNT (MAX_GAMMA-MIN_GAMMA+1) + +static unsigned char* igLUTable[LCDLUTCOUNT]; + +static unsigned char* getIGTable(int gamma) { + int i, index; + double ig; + char *igTable; + + if (gamma < MIN_GAMMA) { + gamma = MIN_GAMMA; + } else if (gamma > MAX_GAMMA) { + gamma = MAX_GAMMA; + } + + index = gamma - MIN_GAMMA; + + if (igLUTable[index] != NULL) { + return igLUTable[index]; + } + igTable = (unsigned char*)malloc(256); + if (igTable == NULL) { + return NULL; + } + igTable[0] = 0; + igTable[255] = 255; + ig = ((double)gamma)/100.0; + + for (i=1;i<255;i++) { + igTable[i] = (unsigned char)(pow(((double)i)/255.0, ig)*255); + } + igLUTable[index] = igTable; + return igTable; +} + + +JNIEXPORT jboolean JNICALL + Java_sun_font_FileFontStrike_initNative(JNIEnv *env, jclass unused) { + + DWORD osVersion = GetVersion(); + DWORD majorVersion = (DWORD)(LOBYTE(LOWORD(osVersion))); + DWORD minorVersion = (DWORD)(HIBYTE(LOWORD(osVersion))); + + /* Need at least XP which is 5.1 */ + if (majorVersion < 5 || (majorVersion == 5 && minorVersion < 1)) { + return JNI_FALSE; + } + + memset(igLUTable, 0, LCDLUTCOUNT); + + return JNI_TRUE; +} + +#ifndef CLEARTYPE_QUALITY +#define CLEARTYPE_QUALITY 5 +#endif + +#ifndef CLEARTYPE_NATURAL_QUALITY +#define CLEARTYPE_NATURAL_QUALITY 6 +#endif + +#define FREE_AND_RETURN \ + if (hDesktopDC != 0 && hWnd != 0) { \ + ReleaseDC(hWnd, hDesktopDC); \ + }\ + if (hMemoryDC != 0) { \ + DeleteObject(hMemoryDC); \ + } \ + if (hBitmap != 0) { \ + DeleteObject(hBitmap); \ + } \ + if (dibImage != NULL) { \ + free(dibImage); \ + } \ + if (glyphInfo != NULL) { \ + free(glyphInfo); \ + } \ + return (jlong)0; +/* end define */ + +JNIEXPORT jlong JNICALL +Java_sun_font_FileFontStrike__1getGlyphImageFromWindows +(JNIEnv *env, jobject unused, + jstring fontFamily, jint style, jint size, jint glyphCode, jboolean fm) { + + GLYPHMETRICS glyphMetrics; + LOGFONTW lf; + BITMAPINFO bmi; + TEXTMETRIC textMetric; + RECT rect; + int bytesWidth, dibBytesWidth, extra, imageSize, dibImageSize; + unsigned char* dibImage = NULL, *rowPtr, *pixelPtr, *dibPixPtr, *dibRowPtr; + unsigned char r,g,b; + unsigned char* igTable; + GlyphInfo* glyphInfo = NULL; + int nameLen; + LPWSTR name; + HFONT oldFont, hFont; + MAT2 mat2; + + unsigned short width; + unsigned short height; + short advanceX; + short advanceY; + int topLeftX; + int topLeftY; + int err; + int bmWidth, bmHeight; + int x, y; + HBITMAP hBitmap = NULL, hOrigBM; + int gamma, orient; + + HWND hWnd = NULL; + HDC hDesktopDC = NULL; + HDC hMemoryDC = NULL; + + hWnd = GetDesktopWindow(); + hDesktopDC = GetWindowDC(hWnd); + if (hDesktopDC == NULL) { + return (jlong)0; + } + if (GetDeviceCaps(hDesktopDC, BITSPIXEL) < 15) { + FREE_AND_RETURN; + } + + hMemoryDC = CreateCompatibleDC(hDesktopDC); + if (hMemoryDC == NULL || fontFamily == NULL) { + FREE_AND_RETURN; + } + err = SetMapMode(hMemoryDC, MM_TEXT); + if (err == 0) { + FREE_AND_RETURN; + } + + memset(&lf, 0, sizeof(LOGFONTW)); + lf.lfHeight = -size; + lf.lfWeight = (style & 1) ? FW_BOLD : FW_NORMAL; + lf.lfItalic = (style & 2) ? 0xff : 0; + lf.lfCharSet = DEFAULT_CHARSET; + lf.lfQuality = CLEARTYPE_QUALITY; + lf.lfOutPrecision = OUT_TT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfPitchAndFamily = DEFAULT_PITCH; + + nameLen = (*env)->GetStringLength(env, fontFamily); + name = (LPWSTR)alloca((nameLen+1)*2); + if (name == NULL) { + FREE_AND_RETURN; + } + (*env)->GetStringRegion(env, fontFamily, 0, nameLen, name); + name[nameLen] = '\0'; + + if (nameLen < (sizeof(lf.lfFaceName) / sizeof(lf.lfFaceName[0]))) { + wcscpy(lf.lfFaceName, name); + } else { + FREE_AND_RETURN; + } + + hFont = CreateFontIndirectW(&lf); + if (hFont == NULL) { + FREE_AND_RETURN; + } + oldFont = SelectObject(hMemoryDC, hFont); + + memset(&textMetric, 0, sizeof(TEXTMETRIC)); + err = GetTextMetrics(hMemoryDC, &textMetric); + if (err == 0) { + FREE_AND_RETURN; + } + memset(&glyphMetrics, 0, sizeof(GLYPHMETRICS)); + memset(&mat2, 0, sizeof(MAT2)); + mat2.eM11.value = 1; mat2.eM22.value = 1; + err = GetGlyphOutline(hMemoryDC, glyphCode, + GGO_METRICS|GGO_GLYPH_INDEX, + &glyphMetrics, + 0, NULL, &mat2); + if (err == GDI_ERROR) { + /* Probably no such glyph - ie the font wasn't the one we expected. */ + FREE_AND_RETURN; + } + + width = (unsigned short)glyphMetrics.gmBlackBoxX; + height = (unsigned short)glyphMetrics.gmBlackBoxY; + + /* Don't handle "invisible" glyphs in this code */ + if (width <= 0 || height == 0) { + FREE_AND_RETURN; + } + + advanceX = glyphMetrics.gmCellIncX; + advanceY = glyphMetrics.gmCellIncY; + topLeftX = glyphMetrics.gmptGlyphOrigin.x; + topLeftY = glyphMetrics.gmptGlyphOrigin.y; + + /* GetGlyphOutline pre-dates cleartype and I'm not sure that it will + * account for all pixels touched by the rendering. Need to widen, + * and also adjust by one the x position at which it is rendered. + * The extra pixels of width are used as follows : + * One extra pixel at the left and the right will be needed to absorb + * the pixels that will be touched by filtering by GDI to compensate + * for colour fringing. + * However there seem to be some cases where GDI renders two extra + * pixels to the right, so we add one additional pixel to the right, + * and in the code that copies this to the image cache we test for + * the (rare) cases when this is touched, and if its not reduce the + * stated image width for the blitting loops. + * For fractional metrics : + * One extra pixel at each end to account for sub-pixel positioning used + * when fractional metrics is on in LCD mode. + * The pixel at the left is needed so the blitting loop can index into + * that a byte at a time to more accurately position the glyph. + * The pixel at the right is needed so that when such indexing happens, + * the blitting still can use the same width. + * Consequently the width that is specified for the glyph is one less + * than that of the actual image. + * Note that in the FM case as a consequence we need to adjust the + * position at which GDI renders, and the declared width of the glyph + * See the if (fm) {} cases in the code. + * For the non-FM case, we not only save 3 bytes per row, but this + * prevents apparent glyph overlapping which affects the rendering + * performance of accelerated pipelines since it adds additional + * read-back requirements. + */ + width+=3; + if (fm) { + width+=1; + } + /* DIB scanline must end on a DWORD boundary. We specify 3 bytes per pixel, + * so must round up as needed to a multiple of 4 bytes. + */ + dibBytesWidth = bytesWidth = width*3; + extra = dibBytesWidth % 4; + if (extra != 0) { + dibBytesWidth += (4-extra); + } + /* The glyph cache image must be a multiple of 3 bytes wide. */ + extra = bytesWidth % 3; + if (extra != 0) { + bytesWidth += (3-extra); + } + bmWidth = width; + bmHeight = height; + + /* Must use desktop DC to create a bitmap of that depth */ + hBitmap = CreateCompatibleBitmap(hDesktopDC, bmWidth, bmHeight); + if (hBitmap == NULL) { + FREE_AND_RETURN; + } + hOrigBM = (HBITMAP)SelectObject(hMemoryDC, hBitmap); + + /* Fill in black */ + rect.left = 0; + rect.top = 0; + rect.right = bmWidth; + rect.bottom = bmHeight; + FillRect(hMemoryDC, (LPRECT)&rect, GetStockObject(BLACK_BRUSH)); + + /* Set text color to white, background to black. */ + SetBkColor(hMemoryDC, RGB(0,0,0)); + SetTextColor(hMemoryDC, RGB(255,255,255)); + + /* adjust rendering position */ + x = -topLeftX+1; + if (fm) { + x += 1; + } + y = topLeftY - textMetric.tmAscent; + err = ExtTextOutW(hMemoryDC, x, y, ETO_GLYPH_INDEX|ETO_OPAQUE, + (LPRECT)&rect, (LPCWSTR)&glyphCode, 1, NULL); + if (err == 0) { + FREE_AND_RETURN; + } + + /* Now get the image into a DIB. + * MS docs for GetDIBits says the compatible bitmap must not be + * selected into a DC, so restore the original first. + */ + SelectObject(hMemoryDC, hOrigBM); + SelectObject(hMemoryDC, oldFont); + DeleteObject(hFont); + + memset(&bmi, 0, sizeof(BITMAPINFO)); + bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); + bmi.bmiHeader.biWidth = width; + bmi.bmiHeader.biHeight = -height; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + + dibImageSize = dibBytesWidth*height; + dibImage = malloc(dibImageSize); + if (dibImage == NULL) { + FREE_AND_RETURN; + } + memset(dibImage, 0, dibImageSize); + + err = GetDIBits(hMemoryDC, hBitmap, 0, height, dibImage, + &bmi, DIB_RGB_COLORS); + + if (err == 0) { /* GetDIBits failed. */ + FREE_AND_RETURN; + } + + err = SystemParametersInfo(SPI_GETFONTSMOOTHINGORIENTATION, 0, &orient, 0); + if (err == 0) { + FREE_AND_RETURN; + } + err = SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &gamma, 0); + if (err == 0) { + FREE_AND_RETURN; + } + igTable = getIGTable(gamma/10); + if (igTable == NULL) { + FREE_AND_RETURN; + } + + /* Now copy glyph image into a GlyphInfo structure and return it. + * NB the xadvance calculated here may be overwritten by the caller. + * 1 is subtracted from the bitmap width to get the glyph width, since + * that extra "1" was added as padding, so the sub-pixel positioning of + * fractional metrics could index into it. + */ + imageSize = bytesWidth*height; + glyphInfo = (GlyphInfo*)malloc(sizeof(GlyphInfo)+imageSize); + if (malloc == NULL) { + FREE_AND_RETURN; + } + glyphInfo->cellInfo = NULL; + glyphInfo->rowBytes = bytesWidth; + glyphInfo->width = width; + if (fm) { + glyphInfo->width -= 1; // must subtract 1 + } + glyphInfo->height = height; + glyphInfo->advanceX = advanceX; + glyphInfo->advanceY = advanceY; + glyphInfo->topLeftX = (float)(topLeftX-1); + if (fm) { + glyphInfo->topLeftX -= 1; + } + glyphInfo->topLeftY = (float)-topLeftY; + glyphInfo->image = (unsigned char*)glyphInfo+sizeof(GlyphInfo); + memset(glyphInfo->image, 0, imageSize); + + /* DIB 24bpp data is always stored in BGR order, but we usually + * need this in RGB, so we can't just memcpy and need to swap B and R. + * Also need to apply inverse gamma adjustment here. + * We re-use the variable "extra" to see if the last pixel is touched + * at all. If its not we can reduce the glyph image width. This comes + * into play in some cases where GDI touches more pixels than accounted + * for by increasing width by two pixels over the B&W image. Whilst + * the bytes are in the cache, it doesn't affect rendering performance + * of the hardware pipelines. + */ + extra = 0; + if (fm) { + extra = 1; // always need it. + } + dibRowPtr = dibImage; + rowPtr = glyphInfo->image; + for (y=0;ywidth -= 1; + } + + free(dibImage); + ReleaseDC(hWnd, hDesktopDC); + DeleteObject(hMemoryDC); + DeleteObject(hBitmap); + + return ptr_to_jlong(glyphInfo); +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/test/java/awt/Graphics2D/DrawString/AlphaSurfaceText.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Graphics2D/DrawString/AlphaSurfaceText.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,106 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6679308 + * @summary test drawing to Alpha surfaces + */ + +import java.awt.*; +import java.awt.image.*; + +public class AlphaSurfaceText { + + int wid=400, hgt=200; + + public AlphaSurfaceText(int biType, Color c) { + BufferedImage opaquebi0 = + new BufferedImage(wid, hgt, BufferedImage.TYPE_INT_RGB); + drawText(opaquebi0, c); + + BufferedImage alphabi = new BufferedImage(wid, hgt, biType); + drawText(alphabi, c); + BufferedImage opaquebi1 = + new BufferedImage(wid, hgt, BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = opaquebi1.createGraphics(); + g2d.drawImage(alphabi, 0, 0, null); + compare(opaquebi0, opaquebi1, biType, c); + } + + private void drawText(BufferedImage bi, Color c) { + Graphics2D g = bi.createGraphics(); + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + g.setColor(c); + g.setFont(new Font("sansserif", Font.PLAIN, 70)); + g.drawString("Hello!", 20, 100); + g.setFont(new Font("sansserif", Font.PLAIN, 12)); + g.drawString("Hello!", 20, 130); + g.setFont(new Font("sansserif", Font.PLAIN, 10)); + g.drawString("Hello!", 20, 150); + } + + // Need to allow for minimal rounding error, so allow each component + // to differ by 1. + void compare(BufferedImage bi0, BufferedImage bi1, int biType, Color c) { + for (int x=0; x> 16; + int r1 = (rgb1 & 0xff0000) >> 16; + int rdiff = r0-r1; if (rdiff<0) rdiff = -rdiff; + int g0 = (rgb0 & 0x00ff00) >> 8; + int g1 = (rgb1 & 0x00ff00) >> 8; + int gdiff = g0-g1; if (gdiff<0) gdiff = -gdiff; + int b0 = (rgb0 & 0x0000ff); + int b1 = (rgb1 & 0x0000ff); + int bdiff = b0-b1; if (bdiff<0) bdiff = -bdiff; + if (rdiff > 1 || gdiff > 1 || bdiff > 1) { + throw new RuntimeException( + "Images differ for type "+biType + " col="+c + + " at x=" + x + " y="+ y + " " + + Integer.toHexString(rgb0) + " vs " + + Integer.toHexString(rgb1)); + } + } + } + + } + public static void main(String[] args) { + new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB, Color.white); + new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB, Color.red); + new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB, Color.blue); + new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB_PRE, Color.white); + new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB_PRE, Color.red); + new AlphaSurfaceText(BufferedImage.TYPE_INT_ARGB_PRE, Color.blue); + new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR, Color.white); + new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR, Color.red); + new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR, Color.blue); + new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR_PRE, Color.white); + new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR_PRE, Color.red); + new AlphaSurfaceText(BufferedImage.TYPE_4BYTE_ABGR_PRE, Color.blue); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/test/java/awt/Graphics2D/DrawString/DrawStrSuper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Graphics2D/DrawString/DrawStrSuper.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,151 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6684056 + * @summary Super-scripted text needs to be positioned the same with + * drawString and TextLayout. + */ +import java.awt.*; +import java.awt.event.*; +import java.awt.font.*; +import static java.awt.font.TextAttribute.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.util.HashMap; + + +public class DrawStrSuper extends Component { + + int angle = 0; + static boolean interactive = false; + + int wid=400, hgt=400; + BufferedImage bi = null; + + void paintImage() { + + if (bi == null) { + bi = new BufferedImage(wid, hgt, BufferedImage.TYPE_INT_RGB); + } + Graphics2D g2d = bi.createGraphics(); + g2d.setColor(Color.white); + g2d.fillRect(0, 0, wid, hgt); + g2d.translate(200, 200); + + Font fnt = new Font("Arial", Font.PLAIN, 20); + fnt = fnt.deriveFont(60.0f); + HashMap attrMap = new HashMap(); + AffineTransform aff = + AffineTransform.getRotateInstance(angle * Math.PI/180.0); + attrMap.put(SUPERSCRIPT, SUPERSCRIPT_SUPER); + attrMap.put(TRANSFORM, aff); + fnt = fnt.deriveFont(attrMap); + + g2d.setFont(fnt); + g2d.setColor(Color.yellow); + TextLayout tl = new TextLayout("Text", fnt,g2d.getFontRenderContext()); + g2d.fill(tl.getBounds()); + + g2d.setColor(Color.black); + g2d.drawLine(-3, 0, 3, 0); + g2d.drawLine(0, -3, 0, 3); + + g2d.setColor(Color.blue); + g2d.drawString("Text", 0, 0); + + g2d.setColor(Color.red); + tl.draw(g2d,0f,0f); + + // Test BI: should be no blue + int blue = Color.blue.getRGB(); + for (int px=0;px 0.1) { + throw new + RuntimeException("Ratio of blue to red is too great: " + + (blueCount/(double)redCount)); + } + } + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/test/java/awt/Graphics2D/DrawString/ScaledLCDTextMetrics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/Graphics2D/DrawString/ScaledLCDTextMetrics.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6685312 + * @summary Check advance of LCD text on a scaled graphics. + */ + +import javax.swing.*; +import java.awt.*; +import static java.awt.RenderingHints.*; + +public class ScaledLCDTextMetrics extends Component { + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.add("Center", new ScaledLCDTextMetrics()); + f.pack(); + f.setVisible(true); + } + + public Dimension getPreferredSize() { + return new Dimension(200,100); + } + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D)g; + + Font f = new Font("Tahoma", Font.PLAIN, 11); + g.setFont(f); + g.setColor(Color.white); + g.fillRect(0,0,400,300); + g.setColor(Color.black); + g2.setRenderingHint(KEY_TEXT_ANTIALIASING,VALUE_TEXT_ANTIALIAS_LCD_HRGB); + String text = "ABCDEFGHIJKLI"; + + FontMetrics fm1 = g2.getFontMetrics(); + int adv1 = fm1.stringWidth(text); + g.drawString(text, 5, 20); + + g2.scale(2,2); + + FontMetrics fm2 = g2.getFontMetrics(); + int adv2 = fm2.stringWidth(text); + g.drawString(text, 5, 40); + + double frac = Math.abs(adv1/(double)adv2); + + System.out.println("scalex1: " + adv1); + System.out.println("scalex2: " + adv2); + System.out.println("Fraction : "+ frac); + + // adv1 will not be exactly the same as adv2, but should differ + // only by a fraction. + + if (frac < 0.8 || frac > 1.2) { + throw new RuntimeException("Metrics differ " + + "Adv1="+adv1+" Adv2="+adv2+" Fraction="+frac); + } + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/test/java/awt/font/Rotate/Shear.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/font/Rotate/Shear.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6692979 + * @summary Verify no crashes with extreme shears. + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.font.*; +import java.awt.geom.*; +public class Shear extends Component { + + public static void main(String[] args) { + JFrame f = new JFrame(); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.getContentPane().add("Center", new Shear()); + f.pack(); + f.setVisible(true); + } + + public Dimension getPreferredSize() { + return new Dimension(400,300); + } + + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D)g; + + g.setColor(Color.white); + g.fillRect(0,0,400,300); + g.setColor(Color.black); + Font origFont = new Font(Font.DIALOG, Font.BOLD, 30); + for (int i=0;i<=360;i++) { + double sv = i*180.0/Math.PI; + AffineTransform tx = AffineTransform.getShearInstance(sv, sv); + Font font = origFont.deriveFont(tx); + g.setFont(font); + GlyphVector gv = + font.createGlyphVector(g2.getFontRenderContext(), "JavaFX"); + //System.out.println(gv.getVisualBounds()); + g.drawString("JavaFX", 100, 100); + } + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/test/java/awt/font/Rotate/TranslatedOutlineTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/font/Rotate/TranslatedOutlineTest.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test TranslatedOutlineTest + * @bug 6703377 + * @summary This test verifies that outline is translated in a correct direction + * @run main TranslatedOutlineTest + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.image.BufferedImage; + +public class TranslatedOutlineTest { + public static void main(String a[]) { + /* prepare blank image */ + BufferedImage bi = new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB); + Graphics2D g2 = (Graphics2D) bi.getGraphics(); + g2.setColor(Color.WHITE); + g2.fillRect(0, 0, 50, 50); + + /* draw outline somethere in the middle of the image */ + FontRenderContext frc = new FontRenderContext(null, false, false); + g2.setColor(Color.RED); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + GlyphVector gv = g2.getFont().createGlyphVector(frc, "test"); + g2.fill(gv.getOutline(20, 20)); + + /* Check if anything was drawn. + * If y direction is not correct then image is still blank and + * test will fail. + */ + int bgcolor = Color.WHITE.getRGB(); + for (int i=0; i q = + new ArrayBlockingQueue(100); + NotificationListener qListener = new NotificationListener() { + public void handleNotification(Notification notification, + Object handback) { + q.add(notification); + } + }; + mbs.addNotificationListener(relSvcName, qListener, null, null); + + RoleInfo leftInfo = + new RoleInfo("left", "javax.management.timer.TimerMBean"); + RoleInfo rightInfo = + new RoleInfo("right", "javax.management.timer.Timer"); + relSvc.createRelationType("typeName", new RoleInfo[] {leftInfo, rightInfo}); + ObjectName timer1 = new ObjectName("a:type=timer,number=1"); + ObjectName timer2 = new ObjectName("a:type=timer,number=2"); + mbs.createMBean("javax.management.timer.Timer", timer1); + mbs.createMBean("javax.management.timer.Timer", timer2); + + Role leftRole = + new Role("left", Arrays.asList(new ObjectName[] {timer1})); + Role rightRole = + new Role("right", Arrays.asList(new ObjectName[] {timer2})); + RoleList roles = + new RoleList(Arrays.asList(new Role[] {leftRole, rightRole})); + + final int NREPEAT = 10; + + for (int i = 0; i < NREPEAT; i++) { + relSvc.createRelation("relationName", "typeName", roles); + relSvc.removeRelation("relationName"); + } + + Notification firstNotif = q.remove(); + long seqNo = firstNotif.getSequenceNumber(); + for (int i = 0; i < NREPEAT * 2 - 1; i++) { + Notification n = q.remove(); + long nSeqNo = n.getSequenceNumber(); + if (nSeqNo != seqNo + 1) { + throw new Exception( + "TEST FAILED: expected seqNo " + (seqNo + 1) + "; got " + + nSeqNo); + } + seqNo++; + } + System.out.println("TEST PASSED: got " + (NREPEAT * 2) + " notifications " + + "with contiguous sequence numbers"); + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/test/javax/print/PrintSE/PrintSE.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/print/PrintSE/PrintSE.java Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.awt.*; +import java.awt.print.*; +import javax.print.*; +import javax.print.attribute.*; + +public class PrintSE implements Printable { + + public static void main(String[] args) throws Exception { + GraphicsEnvironment.getLocalGraphicsEnvironment(); + + PrintService service = PrintServiceLookup.lookupDefaultPrintService(); + if (service == null) { + System.out.println("No print service found."); + return; + } + SimpleDoc doc = + new SimpleDoc(new PrintSE(), + DocFlavor.SERVICE_FORMATTED.PRINTABLE, + new HashDocAttributeSet()); + DocPrintJob job = service.createPrintJob(); + job.print(doc, new HashPrintRequestAttributeSet()); + } + + public int print(Graphics g, PageFormat pf, int pg) { + if (pg > 0) return NO_SUCH_PAGE; + g.drawString("Test passes.", 100, 100); + return PAGE_EXISTS; + } +} diff -r 9b4457aa27c8 -r 0be478749d09 jdk/test/javax/print/PrintSE/PrintSE.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/print/PrintSE/PrintSE.sh Wed Jul 05 16:37:14 2017 +0200 @@ -0,0 +1,51 @@ +#!/bin/sh + +# +# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 6662775 +# @summary Tests queuePrintJob is sufficient permission. +# @run clean PrintSE +# @run build PrintSE +# @run compile PrintSE.java +# @run shell/timeout=300 PrintSE.sh + +echo ------------------------------------------------------------- +echo Launching test for `basename $0 .sh` +echo ------------------------------------------------------------- + +createJavaPolicyFile() +{ + cat << EOF > ${TESTCLASSES}/print.policy +grant { + permission java.lang.RuntimePermission "queuePrintJob"; +}; +EOF +} + +createJavaPolicyFile + +${TESTJAVA}/bin/java -Djava.security.manager -Djava.security.policy=${TESTCLASSES}/print.policy -cp ${TESTCLASSES} PrintSE + +exit $? diff -r 9b4457aa27c8 -r 0be478749d09 jdk/test/sun/java2d/cmm/ProfileOp/ReadProfileTest.java --- a/jdk/test/sun/java2d/cmm/ProfileOp/ReadProfileTest.java Thu May 22 09:37:44 2008 -0700 +++ b/jdk/test/sun/java2d/cmm/ProfileOp/ReadProfileTest.java Wed Jul 05 16:37:14 2017 +0200 @@ -23,7 +23,7 @@ /** * @test - * @bug 6476665 + * @bug 6476665 6523403 * @summary Verifies reading profiles of the standard color spaces * @run main ReadProfileTest */