Merge
authorksrini
Fri Jun 06 08:29:25 2008 -0700 (17 months ago)
changeset 326d8ec2bf4ff08
parent 2925ec71cb4dde0
parent 32502e4c5348592
child 3513761bcf2d59e
Merge
src/solaris/classes/sun/java2d/SurfaceManagerFactory.java
src/windows/classes/sun/java2d/SurfaceManagerFactory.java
--- a/make/common/internal/BinaryPlugs.gmk Tue May 27 10:05:51 2008 -0700
+++ b/make/common/internal/BinaryPlugs.gmk Fri Jun 06 08:29:25 2008 -0700
@@ -126,44 +126,10 @@ com/sun/media/sound/SimpleInputDevicePro
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
@@ -184,11 +150,6 @@ endef # plug-create-clist-jargs
$(PLUG_TEMPDIR)/sound.clist:
@$(prep-target)
@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)
@@ -198,8 +159,6 @@ endef # plug-create-clist-jargs
$(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 @@ import-binary-plug-jmf-classes: $(PLUG_I
$(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-plugs: \
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
--- a/make/common/shared/Defs-utils.gmk Tue May 27 10:05:51 2008 -0700
+++ b/make/common/shared/Defs-utils.gmk Fri Jun 06 08:29:25 2008 -0700
@@ -148,13 +148,15 @@ ifeq ($(PLATFORM),windows)
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
--- a/make/java/awt/Makefile Tue May 27 10:05:51 2008 -0700
+++ b/make/java/awt/Makefile Fri Jun 06 08:29:25 2008 -0700
@@ -28,23 +28,11 @@ PRODUCT = sun
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
--- a/make/java/java/Makefile Tue May 27 10:05:51 2008 -0700
+++ b/make/java/java/Makefile Fri Jun 06 08:29:25 2008 -0700
@@ -394,7 +394,7 @@ LOCALES_GEN_SH = localelist.sh
$(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
--- a/make/java/nio/Makefile Tue May 27 10:05:51 2008 -0700
+++ b/make/java/nio/Makefile Fri Jun 06 08:29:25 2008 -0700
@@ -191,7 +191,7 @@ sources: $(SPP) $(FILES_genout)
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_BUFFER_CMD = SPP="$(SPP_CMD)" NAWK=$
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_CODER_CMD = SPP="$(SPP_CMD)" SED=$(S
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 = $(BUILDTOOLJARDIR)/hash
$(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)
--- a/make/sun/cmm/Makefile Tue May 27 10:05:51 2008 -0700
+++ b/make/sun/cmm/Makefile Fri Jun 06 08:29:25 2008 -0700
@@ -41,12 +41,8 @@ ICCPROFILE_DEST_DIR = $(LIBDIR)/cmm
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
--- a/make/sun/font/FILES_c.gmk Tue May 27 10:05:51 2008 -0700
+++ b/make/sun/font/FILES_c.gmk Fri Jun 06 08:29:25 2008 -0700
@@ -113,7 +113,9 @@ FILES_cpp_shared = \
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 \
--- a/make/sun/font/Makefile Tue May 27 10:05:51 2008 -0700
+++ b/make/sun/font/Makefile Fri Jun 06 08:29:25 2008 -0700
@@ -63,6 +63,7 @@ FILES_export = \
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 \
--- a/src/share/classes/java/awt/Font.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/java/awt/Font.java Fri Jun 06 08:29:25 2008 -0700
@@ -711,7 +711,7 @@ public class Font implements java.io.Ser
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 @@ public class Font implements java.io.Ser
* 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 @@ public class Font implements java.io.Ser
aa = frc.getAntiAliasingHint();
fm = frc.getFractionalMetricsHint();
}
- return getFont2D().getItalicAngle(this, at, aa, fm);
+ return getFont2D().getItalicAngle(this, identityTx, aa, fm);
}
/**
--- a/src/share/classes/java/awt/font/OpenType.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/java/awt/font/OpenType.java Fri Jun 06 08:29:25 2008 -0700
@@ -31,9 +31,9 @@ package java.awt.font;
* <i>sfnt</i> tables from the font. A particular
* <code>Font</code> object can implement this interface.
* <p>
- * For more information on TrueType fonts, see the
- * Apple TrueType Reference Manual
- * ( <a href="http://fonts.apple.com/TTRefMan/index.html">http://fonts.apple.com/TTRefMan/index.html</a> ).
+ * For more information on TrueType and OpenType fonts, see the
+ * OpenType specification.
+ * ( <a href=http://www.microsoft.com/typography/otspec/">http://www.microsoft.com/typography/otspec/l</a> ).
*/
public interface OpenType {
--- a/src/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/javax/print/attribute/standard/ReferenceUriSchemesSupported.java Fri Jun 06 08:29:25 2008 -0700
@@ -44,7 +44,7 @@ import javax.print.attribute.Attribute;
* print request's, print job's, or print service's attribute set.
* <P>
* The Internet Assigned Numbers Authority maintains the
- * <A HREF="http://www.isi.edu/in-notes/iana/assignments/url-schemes">official
+ * <A HREF="http://www.iana.org/assignments/uri-schemes.html">official
* list of URI schemes</A>.
* <p>
* Class ReferenceUriSchemesSupported defines enumeration values for widely
--- a/src/share/classes/sun/awt/image/SunVolatileImage.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/awt/image/SunVolatileImage.java Fri Jun 06 08:29:25 2008 -0700
@@ -165,7 +165,8 @@ public class SunVolatileImage extends Vo
{
return new BufImgVolatileSurfaceManager(this, context);
}
- return SurfaceManagerFactory.createVolatileManager(this, context);
+ SurfaceManagerFactory smf = SurfaceManagerFactory.getInstance();
+ return smf.createVolatileManager(this, context);
}
private Color getForeground() {
--- a/src/share/classes/sun/font/AttributeValues.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/font/AttributeValues.java Fri Jun 06 08:29:25 2008 -0700
@@ -887,10 +887,10 @@ public final class AttributeValues imple
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);
--- a/src/share/classes/sun/font/FileFontStrike.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/font/FileFontStrike.java Fri Jun 06 08:29:25 2008 -0700
@@ -27,6 +27,7 @@ package sun.font;
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 @@ public class FileFontStrike extends Phys
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 @@ public class FileFontStrike extends Phys
* 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 @@ public class FileFontStrike extends Phys
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 @@ public class FileFontStrike extends Phys
}
}
}
-
+ 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 @@ public class FileFontStrike extends Phys
* "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 @@ public class FileFontStrike extends Phys
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<nativeStrikes.length;i++) {
@@ -271,13 +359,19 @@ public class FileFontStrike extends Phys
if (glyphCode >= 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 @@ public class FileFontStrike extends Phys
} 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 @@ public class FileFontStrike extends Phys
} 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 @@ public class FileFontStrike extends Phys
}
}
+ 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.
- */
- float getGlyphAdvance(int glyphCode) {
+ * This is in user space coordinates unless getUserAdv == false.
+ * Device space advance should not be propagated out of this class.
+ */
+ private float getGlyphAdvance(int glyphCode, boolean getUserAdv) {
float advance;
if (glyphCode >= INVISIBLE_GLYPHS) {
@@ -480,11 +580,11 @@ public class FileFontStrike extends Phys
}
}
- 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 @@ public class FileFontStrike extends Phys
}
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 @@ public class FileFontStrike extends Phys
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 @@ public class FileFontStrike extends Phys
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 @@ public class FileFontStrike extends Phys
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);
--- a/src/share/classes/sun/font/Font2D.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/font/Font2D.java Fri Jun 06 08:29:25 2008 -0700
@@ -241,6 +241,13 @@ public abstract class Font2D {
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 @@ public abstract class Font2D {
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());
--- a/src/share/classes/sun/font/FontManager.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/font/FontManager.java Fri Jun 06 08:29:25 2008 -0700
@@ -93,7 +93,6 @@ public final class FontManager {
*/
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 @@ public final class FontManager {
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,35 +284,51 @@ public final class FontManager {
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<CHANNELPOOLSIZE; i++) {
- if (fontFileCache[i] == null) {
- fontFileCache[i] = font;
- poolSize++;
- added = true;
- break;
- }
- }
- assert added;
+ for (int i=0;i<CHANNELPOOLSIZE;i++) {
+ if (fontFileCache[i] == font) {
+ return;
+ }
+ if (fontFileCache[i] == null && freeSlot < 0) {
+ freeSlot = i;
+ }
+ }
+ if (freeSlot >= 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.
*/
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 @@ public final class FontManager {
for (int i=0; i<CHANNELPOOLSIZE; i++) {
if (fontFileCache[i] == font) {
fontFileCache[i] = null;
- poolSize--;
}
}
}
--- a/src/share/classes/sun/font/GlyphLayout.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/font/GlyphLayout.java Fri Jun 06 08:29:25 2008 -0700
@@ -85,7 +85,7 @@ public final class GlyphLayout {
private GVData _gvdata;
// cached glyph layout data for reuse
- private static GlyphLayout cache; // reusable
+ private static volatile GlyphLayout cache; // reusable
private LayoutEngineFactory _lef; // set when get is called, unset when done is called
private TextRecord _textRecord; // the text we're working on, used by iterators
--- a/src/share/classes/sun/font/TrueTypeFont.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/font/TrueTypeFont.java Fri Jun 06 08:29:25 2008 -0700
@@ -893,6 +893,31 @@ public class TrueTypeFont extends FileFo
return null;
}
+ /* Used to determine if this size has embedded bitmaps, which
+ * for CJK fonts should be used in preference to LCD glyphs.
+ */
+ boolean useEmbeddedBitmapsForSize(int ptSize) {
+ if (!supportsCJK) {
+ return false;
+ }
+ if (getDirectoryEntry(EBLCTag) == null) {
+ return false;
+ }
+ ByteBuffer eblcTable = getTableBuffer(EBLCTag);
+ int numSizes = eblcTable.getInt(4);
+ /* The bitmapSizeTable's start at offset of 8.
+ * Each bitmapSizeTable entry is 48 bytes.
+ * The offset of ppemY in the entry is 45.
+ */
+ for (int i=0;i<numSizes;i++) {
+ int ppemY = eblcTable.get(8+(i*48)+45) &0xff;
+ if (ppemY == ptSize) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public String getFullName() {
return fullName;
}
--- a/src/share/classes/sun/font/Type1Font.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/font/Type1Font.java Fri Jun 06 08:29:25 2008 -0700
@@ -589,7 +589,7 @@ public class Type1Font extends FileFont
protected synchronized FontScaler getScaler() {
if (scaler == null) {
- return FontManager.getScaler(this, 0, false, fileSize);
+ scaler = FontManager.getScaler(this, 0, false, fileSize);
}
return scaler;
--- a/src/share/classes/sun/java2d/SunGraphics2D.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/java2d/SunGraphics2D.java Fri Jun 06 08:29:25 2008 -0700
@@ -2805,6 +2805,9 @@ public final class SunGraphics2D
}
if (font.hasLayoutAttributes()) {
+ if (str.length() == 0) {
+ return;
+ }
new TextLayout(str, font, getFontRenderContext()).draw(this, x, y);
return;
}
@@ -2831,6 +2834,9 @@ public final class SunGraphics2D
}
if (font.hasLayoutAttributes()) {
+ if (str.length() == 0) {
+ return;
+ }
new TextLayout(str, font, getFontRenderContext()).draw(this, x, y);
return;
}
@@ -2856,6 +2862,9 @@ public final class SunGraphics2D
if (iterator == null) {
throw new NullPointerException("AttributedCharacterIterator is null");
}
+ if (iterator.getBeginIndex() == iterator.getEndIndex()) {
+ return; /* nothing to draw */
+ }
TextLayout tl = new TextLayout(iterator, getFontRenderContext());
tl.draw(this, (float) x, (float) y);
}
@@ -2864,6 +2873,9 @@ public final class SunGraphics2D
float x, float y) {
if (iterator == null) {
throw new NullPointerException("AttributedCharacterIterator is null");
+ }
+ if (iterator.getBeginIndex() == iterator.getEndIndex()) {
+ return; /* nothing to draw */
}
TextLayout tl = new TextLayout(iterator, getFontRenderContext());
tl.draw(this, x, y);
@@ -2900,6 +2912,9 @@ public final class SunGraphics2D
throw new ArrayIndexOutOfBoundsException("bad offset/length");
}
if (font.hasLayoutAttributes()) {
+ if (data.length == 0) {
+ return;
+ }
new TextLayout(new String(data, offset, length),
font, getFontRenderContext()).draw(this, x, y);
return;
@@ -2934,6 +2949,9 @@ public final class SunGraphics2D
chData[i] = (char)(data[i+offset] & 0xff);
}
if (font.hasLayoutAttributes()) {
+ if (data.length == 0) {
+ return;
+ }
new TextLayout(new String(chData),
font, getFontRenderContext()).draw(this, x, y);
return;
--- a/src/share/classes/sun/print/PSPathGraphics.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/print/PSPathGraphics.java Fri Jun 06 08:29:25 2008 -0700
@@ -344,8 +344,15 @@ class PSPathGraphics extends PathGraphic
double devScaleX = devResX / DEFAULT_USER_RES;
double devScaleY = devResY / DEFAULT_USER_RES;
- if (scaleX > 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.
--- a/src/share/classes/sun/print/ServiceDialog.java Tue May 27 10:05:51 2008 -0700
+++ b/src/share/classes/sun/print/ServiceDialog.java Fri Jun 06 08:29:25 2008 -0700
@@ -2149,48 +2149,55 @@ public class ServiceDialog extends JDial
}
}
}
- }
- 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;
- }
- 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 == null) {
+ or = OrientationRequested.PORTRAIT;
+ }
+ 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);
+ }
+ } else {
+ rbPortrait.setEnabled(pSupported);
+ rbLandscape.setEnabled(lSupported);
+ rbRevPortrait.setEnabled(rpSupported);
+ rbRevLandscape.setEnabled(rlSupported);
+
}
}
}
Binary file src/share/lib/cmm/lcms/GRAY.pf has changed
--- a/src/share/native/sun/font/freetypeScaler.c Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/font/freetypeScaler.c Fri Jun 06 08:29:25 2008 -0700
@@ -368,7 +368,7 @@ Java_sun_font_FreetypeFontScaler_createS
//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 @@ Java_sun_font_FreetypeFontScaler_getGlyp
}
if (context->fmType == TEXT_FM_ON) {
- glyphInfo->advanceX = FT26Dot6ToFloat(ftglyph->advance.x);
- glyphInfo->advanceY = FT26Dot6ToFloat(-ftglyph->advance.y);
+ double advh = FTFixedToFloat(ftglyph->linearHoriAdvance);
+ glyphInfo->advanceX =
+ (float) (advh * FTFixedToFloat(context->transform.xx));
+ glyphInfo->advanceY =
+ (float) (advh * FTFixedToFloat(context->transform.xy));
} else {
- glyphInfo->advanceX =
- (float) ROUND(FT26Dot6ToFloat(ftglyph->advance.x));
- glyphInfo->advanceY =
- (float) ROUND(FT26Dot6ToFloat(-ftglyph->advance.y));
+ 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 @@ static FT_Outline* getFTOutline(JNIEnv*
FT_Outline_Translate(&ftglyph->outline,
FloatToF26Dot6(xpos),
- FloatToF26Dot6(ypos));
+ -FloatToF26Dot6(ypos));
return &ftglyph->outline;
}
--- a/src/share/native/sun/java2d/loops/AlphaMacros.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/AlphaMacros.h Fri Jun 06 08:29:25 2008 -0700
@@ -416,7 +416,8 @@ void NAME_SRCOVER_MASKBLIT(SRC, DST) \
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 @@ void NAME_SRCOVER_MASKBLIT(SRC, DST) \
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 @@ void NAME_SRCOVER_MASKFILL(TYPE) \
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 @@ void NAME_SRCOVER_MASKFILL(TYPE) \
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); \
--- a/src/share/native/sun/java2d/loops/ByteGray.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/ByteGray.h Fri Jun 06 08:29:25 2008 -0700
@@ -35,6 +35,8 @@
typedef jubyte ByteGrayPixelType;
typedef jubyte ByteGrayDataType;
+
+#define ByteGrayIsOpaque 1
#define ByteGrayPixelStride 1
#define ByteGrayBitsPerPixel 8
--- a/src/share/native/sun/java2d/loops/FourByteAbgr.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/FourByteAbgr.h Fri Jun 06 08:29:25 2008 -0700
@@ -33,6 +33,8 @@
typedef jint FourByteAbgrPixelType;
typedef jubyte FourByteAbgrDataType;
+
+#define FourByteAbgrIsOpaque 0
#define FourByteAbgrPixelStride 4
--- a/src/share/native/sun/java2d/loops/FourByteAbgrPre.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/FourByteAbgrPre.h Fri Jun 06 08:29:25 2008 -0700
@@ -33,6 +33,8 @@
typedef jint FourByteAbgrPrePixelType;
typedef jubyte FourByteAbgrPreDataType;
+
+#define FourByteAbgrPreIsOpaque 0
#define FourByteAbgrPrePixelStride 4
--- a/src/share/native/sun/java2d/loops/Index12Gray.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/Index12Gray.h Fri Jun 06 08:29:25 2008 -0700
@@ -36,6 +36,8 @@
typedef jushort Index12GrayPixelType;
typedef jushort Index12GrayDataType;
+
+#define Index12GrayIsOpaque 1
#define Index12GrayPixelStride 2
#define Index12GrayBitsPerPixel 12
--- a/src/share/native/sun/java2d/loops/Index8Gray.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/Index8Gray.h Fri Jun 06 08:29:25 2008 -0700
@@ -36,6 +36,8 @@
typedef jubyte Index8GrayPixelType;
typedef jubyte Index8GrayDataType;
+
+#define Index8GrayIsOpaque 1
#define Index8GrayPixelStride 1
#define Index8GrayBitsPerPixel 8
--- a/src/share/native/sun/java2d/loops/IntArgb.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/IntArgb.h Fri Jun 06 08:29:25 2008 -0700
@@ -37,6 +37,8 @@
typedef jint IntArgbPixelType;
typedef jint IntArgbDataType;
+
+#define IntArgbIsOpaque 0
#define IntArgbPixelStride 4
--- a/src/share/native/sun/java2d/loops/IntArgbBm.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/IntArgbBm.h Fri Jun 06 08:29:25 2008 -0700
@@ -37,6 +37,8 @@
typedef jint IntArgbBmPixelType;
typedef jint IntArgbBmDataType;
+
+#define IntArgbBmIsOpaque 0
#define IntArgbBmPixelStride 4
--- a/src/share/native/sun/java2d/loops/IntArgbPre.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/IntArgbPre.h Fri Jun 06 08:29:25 2008 -0700
@@ -35,6 +35,8 @@
typedef jint IntArgbPrePixelType;
typedef jint IntArgbPreDataType;
+
+#define IntArgbPreIsOpaque 0
#define IntArgbPrePixelStride 4
--- a/src/share/native/sun/java2d/loops/IntBgr.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/IntBgr.h Fri Jun 06 08:29:25 2008 -0700
@@ -38,6 +38,8 @@ typedef jint IntBgrPixelType;
typedef jint IntBgrPixelType;
typedef jint IntBgrDataType;
+#define IntBgrIsOpaque 1
+
#define IntBgrPixelStride 4
#define DeclareIntBgrLoadVars(PREFIX)
--- a/src/share/native/sun/java2d/loops/IntRgb.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/IntRgb.h Fri Jun 06 08:29:25 2008 -0700
@@ -37,6 +37,8 @@
typedef jint IntRgbPixelType;
typedef jint IntRgbDataType;
+
+#define IntRgbIsOpaque 1
#define IntRgbPixelStride 4
--- a/src/share/native/sun/java2d/loops/IntRgbx.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/IntRgbx.h Fri Jun 06 08:29:25 2008 -0700
@@ -36,6 +36,8 @@ typedef jint IntRgbxPixelType;
typedef jint IntRgbxPixelType;
typedef jint IntRgbxDataType;
+#define IntRgbxIsOpaque 1
+
#define IntRgbxPixelStride 4
#define DeclareIntRgbxLoadVars(PREFIX)
--- a/src/share/native/sun/java2d/loops/LoopMacros.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/LoopMacros.h Fri Jun 06 08:29:25 2008 -0700
@@ -1610,8 +1610,12 @@ void NAME_SOLID_DRAWGLYPHLIST(DST)(Surfa
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 @@ void NAME_SOLID_DRAWGLYPHLISTAA(DST)(Sur
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); \
--- a/src/share/native/sun/java2d/loops/ThreeByteBgr.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/ThreeByteBgr.h Fri Jun 06 08:29:25 2008 -0700
@@ -33,6 +33,8 @@
typedef jint ThreeByteBgrPixelType;
typedef jubyte ThreeByteBgrDataType;
+
+#define ThreeByteBgrIsOpaque 1
#define ThreeByteBgrPixelStride 3
--- a/src/share/native/sun/java2d/loops/Ushort4444Argb.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/Ushort4444Argb.h Fri Jun 06 08:29:25 2008 -0700
@@ -33,6 +33,8 @@
typedef jushort Ushort4444ArgbPixelType;
typedef jushort Ushort4444ArgbDataType;
+
+#define Ushort4444ArgbIsOpaque 0
#define Ushort4444ArgbPixelStride 2
--- a/src/share/native/sun/java2d/loops/Ushort555Rgb.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/Ushort555Rgb.h Fri Jun 06 08:29:25 2008 -0700
@@ -34,6 +34,8 @@ typedef jushort Ushort555RgbPixelType;
typedef jushort Ushort555RgbPixelType;
typedef jushort Ushort555RgbDataType;
+#define Ushort555RgbIsOpaque 1
+
#define Ushort555RgbPixelStride 2
#define DeclareUshort555RgbLoadVars(PREFIX)
--- a/src/share/native/sun/java2d/loops/Ushort555Rgbx.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/Ushort555Rgbx.h Fri Jun 06 08:29:25 2008 -0700
@@ -34,6 +34,8 @@ typedef jushort Ushort555RgbxPixelType;
typedef jushort Ushort555RgbxPixelType;
typedef jushort Ushort555RgbxDataType;
+#define Ushort555RgbxIsOpaque 1
+
#define Ushort555RgbxPixelStride 2
#define DeclareUshort555RgbxLoadVars(PREFIX)
--- a/src/share/native/sun/java2d/loops/Ushort565Rgb.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/Ushort565Rgb.h Fri Jun 06 08:29:25 2008 -0700
@@ -34,6 +34,8 @@ typedef jushort Ushort565RgbPixelType;
typedef jushort Ushort565RgbPixelType;
typedef jushort Ushort565RgbDataType;
+#define Ushort565RgbIsOpaque 1
+
#define Ushort565RgbPixelStride 2
#define DeclareUshort565RgbLoadVars(PREFIX)
--- a/src/share/native/sun/java2d/loops/UshortGray.h Tue May 27 10:05:51 2008 -0700
+++ b/src/share/native/sun/java2d/loops/UshortGray.h Fri Jun 06 08:29:25 2008 -0700
@@ -35,6 +35,8 @@
typedef jushort UshortGrayPixelType;
typedef jushort UshortGrayDataType;
+
+#define UshortGrayIsOpaque 1
#define UshortGrayPixelStride 2
#define UshortGrayBitsPerPixel 16
--- a/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java Fri Jun 06 08:29:25 2008 -0700
@@ -48,6 +48,8 @@ import sun.font.FontManager;
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 @@ public class X11GraphicsEnvironment
return null;
}
});
+
+ // Install the correct surface manager factory.
+ SurfaceManagerFactory.setInstance(new UnixSurfaceManagerFactory());
+
}
private static boolean glxAvailable;
--- a/src/solaris/classes/sun/print/AttributeClass.java Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/classes/sun/print/AttributeClass.java Fri Jun 06 08:29:25 2008 -0700
@@ -32,6 +32,7 @@ public class AttributeClass {
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;
--- a/src/solaris/classes/sun/print/CUPSPrinter.java Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/classes/sun/print/CUPSPrinter.java Fri Jun 06 08:29:25 2008 -0700
@@ -333,7 +333,7 @@ public class CUPSPrinter {
AttributeClass.ATTRIBUTES_NATURAL_LANGUAGE,
new AttributeClass("requested-attributes",
AttributeClass.TAG_KEYWORD,
- "printer-name")
+ "printer-uri-supported")
};
if (IPPPrintService.writeIPPRequest(os,
@@ -354,7 +354,7 @@ public class CUPSPrinter {
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();
--- a/src/solaris/classes/sun/print/IPPPrintService.java Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/classes/sun/print/IPPPrintService.java Fri Jun 06 08:29:25 2008 -0700
@@ -335,6 +335,38 @@ public class IPPPrintService implements
}
+ 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 @@ public class IPPPrintService implements
return;
} catch (Exception e) {
IPPPrintService.debug_println(debugPrefix+
- " error creating CUPSPrinter");
+ " error creating CUPSPrinter e="+e);
}
}
@@ -621,17 +653,8 @@ public class IPPPrintService implements
}
}
} 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 @@ public class IPPPrintService implements
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<orientArray.length; i++) {
switch (orientArray[i]) {
@@ -657,11 +680,32 @@ public class IPPPrintService implements
case 6:
orientSup[i] =
OrientationRequested.REVERSE_PORTRAIT;
+ revPort = true;
break;
}
}
- return orientSup;
- }
+ }
+ }
+ if (flavor == null ||
+ flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
+ flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
+
+ if (revPort && flavor == null) {
+ OrientationRequested []orSup = new OrientationRequested[4];
+ orSup[0] = OrientationRequested.PORTRAIT;
+ orSup[1] = OrientationRequested.LANDSCAPE;
+ orSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
+ orSup[3] = OrientationRequested.REVERSE_PORTRAIT;
+ return orSup;
+ } else {
+ OrientationRequested []orSup = new OrientationRequested[3];
+ orSup[0] = OrientationRequested.PORTRAIT;
+ orSup[1] = OrientationRequested.LANDSCAPE;
+ orSup[2] = OrientationRequested.REVERSE_LANDSCAPE;
+ return orSup;
+ }
+ } else {
+ return orientSup;
}
} else if (category == PageRanges.class) {
if (flavor == null ||
@@ -795,6 +839,18 @@ public class IPPPrintService implements
docList.addAll(Arrays.asList(flavors));
+ if (isCupsPrinter) {
+ /*
+ Always add Pageable and Printable for CUPS
+ since it uses Filters to convert from Postscript
+ to device printer language.
+ */
+ docList.add(
+ DocFlavor.SERVICE_FORMATTED.PAGEABLE);
+ docList.add(
+ DocFlavor.SERVICE_FORMATTED.PRINTABLE);
+ }
+
if (mimeType.equals("text/plain") &&
addHostEncoding) {
docList.add(Arrays.asList(textPlainHost));
@@ -808,11 +864,6 @@ public class IPPPrintService implements
} else if (mimeType.equals("image/jpeg")) {
jpgImagesAdded = true;
} else if (mimeType.indexOf("postscript") != -1) {
- docList.add(
- DocFlavor.SERVICE_FORMATTED.PAGEABLE);
- docList.add(
- DocFlavor.SERVICE_FORMATTED.PRINTABLE);
-
psSupported = true;
}
break;
@@ -829,7 +880,7 @@ public class IPPPrintService implements
}
// check if we need to add image DocFlavors
- if (psSupported) {
+ if (psSupported || isCupsPrinter) {
if (!jpgImagesAdded) {
docList.addAll(Arrays.asList(imageJPG));
}
@@ -989,6 +1040,14 @@ public class IPPPrintService implements
if (supportedCats == null) {
getSupportedAttributeCategories();
+ }
+
+ // It is safe to assume that Orientation is always supported
+ // and even if CUPS or an IPP device reports it as not,
+ // our renderer can do portrait, landscape and
+ // reverse landscape.
+ if (category == OrientationRequested.class) {
+ return true;
}
for (int i=0;i<supportedCats.length;i++) {
@@ -1520,10 +1579,7 @@ public class IPPPrintService implements
if (isCupsPrinter) {
try {
urlConnection = getIPPConnection(
- new URL("http://"+
- CUPSPrinter.getServer()+":"+
- CUPSPrinter.getPort()+
- "/printers/"+printer+".ppd"));
+ new URL(myURL+".ppd"));
InputStream is = urlConnection.getInputStream();
if (is != null) {
@@ -1539,6 +1595,11 @@ public class IPPPrintService implements
}
}
} catch (java.io.IOException e) {
+ debug_println(" isPostscript, e= "+e);
+ /* if PPD is not found, this may be a raw printer
+ and in this case it is assumed that it is a
+ Postscript printer */
+ // do nothing
}
}
}
@@ -1602,7 +1663,13 @@ public class IPPPrintService implements
public static boolean writeIPPRequest(OutputStream os,
String operCode,
AttributeClass[] attCl) {
- OutputStreamWriter osw = new OutputStreamWriter(os);
+ OutputStreamWriter osw;
+ try {
+ osw = new OutputStreamWriter(os, "UTF-8");
+ } catch (java.io.UnsupportedEncodingException exc) {
+ debug_println("UTF-8 not supported? Exception: "+exc);
+ return false;
+ }
char[] opCode = new char[2];
opCode[0] = (char)Byte.parseByte(operCode.substring(0,2), 16);
opCode[1] = (char)Byte.parseByte(operCode.substring(2,4), 16);
@@ -1690,7 +1757,7 @@ public class IPPPrintService implements
// read value tag
response[0] = ois.readByte();
- while (response[0] >= 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 @@ public class IPPPrintService implements
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
--- a/src/solaris/classes/sun/print/UnixPrintServiceLookup.java Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/classes/sun/print/UnixPrintServiceLookup.java Fri Jun 06 08:29:25 2008 -0700
@@ -196,11 +196,20 @@ public class UnixPrintServiceLookup exte
// 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<printerURIs.length; i++) {
+ int lastIndex = printerURIs[i].lastIndexOf("/");
+ printers[i] = printerURIs[i].substring(lastIndex+1);
+ }
+ }
} else {
if (isSysV()) {
printers = getAllPrinterNamesSysV();
@@ -236,12 +245,9 @@ public class UnixPrintServiceLookup exte
if (CUPSPrinter.isCupsRunning()) {
try {
- URL serviceURL =
- new URL("http://"+
- CUPSPrinter.getServer()+":"+
- CUPSPrinter.getPort()+"/"+printers[p]);
- printerList.add(new IPPPrintService( printers[p],
- serviceURL));
+ printerList.add(new IPPPrintService(printers[p],
+ printerURIs[p],
+ true));
} catch (Exception e) {
IPPPrintService.debug_println(debugPrefix+
" getAllPrinters Exception "+
@@ -265,12 +271,10 @@ public class UnixPrintServiceLookup exte
if (j == printServices.length) { // not found?
if (CUPSPrinter.isCupsRunning()) {
try {
- URL serviceURL =
- new URL("http://"+
- CUPSPrinter.getServer()+":"+
- CUPSPrinter.getPort()+"/"+printers[p]);
- printerList.add(new IPPPrintService( printers[p],
- serviceURL));
+ printerList.add(new IPPPrintService(
+ printers[p],
+ printerURIs[p],
+ true));
} catch (Exception e) {
IPPPrintService.debug_println(debugPrefix+
" getAllPrinters Exception "+
--- a/src/solaris/native/sun/awt/awt_GraphicsEnv.c Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/native/sun/awt/awt_GraphicsEnv.c Fri Jun 06 08:29:25 2008 -0700
@@ -650,7 +650,7 @@ static void xinerama_init_linux()
if (XineramaQueryScreens != NULL) {
DTRACE_PRINTLN("calling XineramaQueryScreens func on Linux");
xinInfo = (*XineramaQueryScreens)(awt_display, &locNumScr);
- if (xinInfo != NULL) {
+ if (xinInfo != NULL && locNumScr > XScreenCount(awt_display)) {
int32_t idx;
DTRACE_PRINTLN("Enabling Xinerama support");
usingXinerama = True;
@@ -701,7 +701,8 @@ static void xinerama_init_solaris()
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 @@ Java_sun_awt_X11GraphicsEnvironment_getX
#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 @@ typedef Status
short rate,
Time timestamp);
+static XRRQueryVersionType awt_XRRQueryVersion;
static XRRGetScreenInfoType awt_XRRGetScreenInfo;
static XRRFreeScreenConfigInfoType awt_XRRFreeScreenConfigInfo;
static XRRConfigRatesType awt_XRRConfigRates;
@@ -1672,11 +1676,48 @@ static jboolean
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,
"X11GD_InitXrandrFuncs: Could not open libXrandr.so.2");
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);
@@ -1814,15 +1855,6 @@ Java_sun_awt_X11GraphicsDevice_initXrand
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);
--- a/src/solaris/native/sun/java2d/loops/vis_FourByteAbgr.c Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/native/sun/java2d/loops/vis_FourByteAbgr.c Fri Jun 06 08:29:25 2008 -0700
@@ -1936,6 +1936,7 @@ void ADD_SUFF(FourByteAbgrDrawGlyphListA
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,7 +1944,13 @@ void ADD_SUFF(FourByteAbgrDrawGlyphListA
} 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++;
@@ -1984,8 +1991,13 @@ void ADD_SUFF(FourByteAbgrDrawGlyphListA
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);
--- a/src/solaris/native/sun/java2d/loops/vis_FourByteAbgrPre.c Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/native/sun/java2d/loops/vis_FourByteAbgrPre.c Fri Jun 06 08:29:25 2008 -0700
@@ -181,6 +181,7 @@ void ADD_SUFF(FourByteAbgrPreDrawGlyphLi
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 @@ void ADD_SUFF(FourByteAbgrPreDrawGlyphLi
mlib_u8 *src = (void*)pixels;
mlib_s32 *dst, *dst_end;
mlib_u8 *dst8;
-
- ADD_SUFF(FourByteAbgrPreToIntArgbConvert)(dstBase, pbuff, width, 1,
+ mlib_u8* dst_start = dstBase;
+
+ /*
+ * 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 @@ void ADD_SUFF(FourByteAbgrPreDrawGlyphLi
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;
--- a/src/solaris/native/sun/java2d/loops/vis_IntArgb.c Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/native/sun/java2d/loops/vis_IntArgb.c Fri Jun 06 08:29:25 2008 -0700
@@ -428,6 +428,11 @@ void ADD_SUFF(IntArgbDrawGlyphListAA)(GL
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 @@ void ADD_SUFF(IntArgbDrawGlyphListAA)(GL
dst++;
}
+ ADD_SUFF(IntArgbPreToIntArgbConvert)(dstBase, dstBase, width, 1,
+ pRasInfo, pRasInfo,
+ pPrim, pCompInfo);
PTR_ADD(dstBase, scan);
pixels += rowBytes;
}
--- a/src/solaris/native/sun/java2d/loops/vis_IntArgbPre.c Tue May 27 10:05:51 2008 -0700
+++ b/src/solaris/native/sun/java2d/loops/vis_IntArgbPre.c Fri Jun 06 08:29:25 2008 -0700
@@ -1193,10 +1193,6 @@ void ADD_SUFF(IntArgbPreDrawGlyphListAA)
dst++;
}
- ADD_SUFF(IntArgbToIntArgbPreConvert)(dstBase, dstBase, width, 1,
- pRasInfo, pRasInfo,
- pPrim, pCompInfo);
-
PTR_ADD(dstBase, scan);
pixels += rowBytes;
}
--- a/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java Tue May 27 10:05:51 2008 -0700
+++ b/src/windows/classes/sun/awt/Win32GraphicsEnvironment.java Fri Jun 06 08:29:25 2008 -0700
@@ -42,6 +42,8 @@ import sun.awt.windows.WToolkit;
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 @@ public class Win32GraphicsEnvironment
WindowsFlags.initFlags();
initDisplayWrapper();
eudcFontFileName = getEUDCFontFile();
+
+ // Install correct surface manager factory.
+ SurfaceManagerFactory.setInstance(new WindowsSurfaceManagerFactory());
}
/**
@@ -260,6 +265,7 @@ public class Win32GraphicsEnvironment
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 @@ public class Win32GraphicsEnvironment
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 class Win32GraphicsEnvironment
}
public static void registerJREFontsForPrinting() {
- String pathName = null;
+ final String pathName;
synchronized (Win32GraphicsEnvironment.class) {
GraphicsEnvironment.getLocalGraphicsEnvironment();
if (fontsForPrinting == null) {
@@ -305,15 +311,21 @@ public class Win32GraphicsEnvironment
pathName = fontsForPrinting;
fontsForPrinting = null;
}
- File f1 = new File(pathName);
- String[] ls = f1.list(new TTFilter());
- if (ls == null) {
- return;
- }
- for (int i=0; i <ls.length; i++ ) {
- File fontFile = new File(f1, ls[i]);
- registerFontWithPlatform(fontFile.getAbsolutePath());
- }
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Object run() {
+ File f1 = new File(pathName);
+ String[] ls = f1.list(new TTFilter());
+ if (ls == null) {
+ return null;
+ }
+ for (int i=0; i <ls.length; i++ ) {
+ File fontFile = new File(f1, ls[i]);
+ registerFontWithPlatform(fontFile.getAbsolutePath());
+ }
+ return null;
+ }
+ });
}
protected static native void registerFontWithPlatform(String fontName);
--- a/src/windows/classes/sun/awt/windows/WPathGraphics.java Tue May 27 10:05:51 2008 -0700
+++ b/src/windows/classes/sun/awt/windows/WPathGraphics.java Fri Jun 06 08:29:25 2008 -0700
@@ -943,8 +943,16 @@ class WPathGraphics extends PathGraphics
double devResY = wPrinterJob.getYRes();
double devScaleX = devResX / DEFAULT_USER_RES;
double devScaleY = devResY / DEFAULT_USER_RES;
- if (scaleX > 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.
--- a/test/sun/java2d/cmm/ProfileOp/ReadProfileTest.java Tue May 27 10:05:51 2008 -0700
+++ b/test/sun/java2d/cmm/ProfileOp/ReadProfileTest.java Fri Jun 06 08:29:25 2008 -0700
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6476665
+ * @bug 6476665 6523403
* @summary Verifies reading profiles of the standard color spaces
* @run main ReadProfileTest
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/awt/color/CMMException.java Fri Jun 06 08:29:25 2008 -0700
@@ -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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/awt/color/ColorSpace.java Fri Jun 06 08:29:25 2008 -0700
@@ -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.
+ * <p>
+ * 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.
+ * <p>
+ * 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 <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
+ * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
+ * </A>.
+ * <p>
+ * 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.
+ * <p>
+ * The CS_CIEXYZ space used by the toCIEXYZ/fromCIEXYZ methods can be
+ * described as follows:
+<pre>
+
+&nbsp; CIEXYZ
+&nbsp; viewing illuminance: 200 lux
+&nbsp; viewing white point: CIE D50
+&nbsp; media white point: "that of a perfectly reflecting diffuser" -- D50
+&nbsp; media black point: 0 lux or 0 Reflectance
+&nbsp; flare: 1 percent
+&nbsp; surround: 20percent of the media white point
+&nbsp; media description: reflection print (i.e., RLAB, Hunt viewing media)
+&nbsp; note: For developers creating an ICC profile for this conversion
+&nbsp; space, the following is applicable. Use a simple Von Kries
+&nbsp; white point adaptation folded into the 3X3 matrix parameters
+&nbsp; and fold the flare and surround effects into the three
+&nbsp; one-dimensional lookup tables (assuming one uses the minimal
+&nbsp; model for monitors).
+
+</pre>
+ *
+ * <p>
+ * @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
+ * <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
+ * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
+ * </A>.
+ */
+ 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 <CODE>ColorSpace</CODE> 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 <CODE>ColorSpace</CODE> 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 <CODE>true</CODE> if this is a <CODE>CS_sRGB</CODE> color
+ * space, <code>false</code> 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.
+ * <p>
+ * 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 <code>toCIEXYZ</code>
+ * method of this color space to first convert from the input
+ * color space to the CS_CIEXYZ color space, and then use the
+ * <code>fromCIEXYZ</code> 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.
+ * <p>
+ * @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.
+ * <p>
+ * 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 <code>toCIEXYZ</code>
+ * 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
+ * <code>fromCIEXYZ</code> 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.
+ * <p>
+ * @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.
+ * <p>
+ * 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
+ * <code>ICC_ColorSpace</code> for further information.
+ * <p>
+ * @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.
+ * <p>
+ * 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
+ * <code>ICC_ColorSpace</code> for further information.
+ * <p>
+ * @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
+ * <CODE>ColorSpace</CODE>
+ */
+ public int getType() {
+ return type;
+ }
+
+ /**
+ * Returns the number of components of this ColorSpace.
+ * @return The number of components in this <CODE>ColorSpace</CODE>.
+ */
+ 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 <code>idx</code> 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/awt/color/ICC_ColorSpace.java Fri Jun 06 08:29:25 2008 -0700
@@ -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 <A href="http://www.color.org">http://www.color.org</A>).
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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().
+ * <p>
+ * @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.
+ * <p>
+ * 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 <code>toCIEXYZ</code>
+ * method of this color space to first convert from the input
+ * color space to the CS_CIEXYZ color space, and then use the
+ * <code>fromCIEXYZ</code> 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.
+ * <p>
+ * @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.
+ * <p>
+ * 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 <code>toCIEXYZ</code>
+ * 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
+ * <code>fromCIEXYZ</code> 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.
+ * <p>
+ * @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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <pre>
+ *
+ * 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)
+ *
+ * </pre>
+ * <p>
+ * Conversion from the PCS to the device would be done by inverting these
+ * equations:
+ * <pre>
+ *
+ * Xd = Xp * (Xdw / Xd50)
+ * Yd = Yp * (Ydw / Yd50)
+ * Zd = Zp * (Zdw / Zd50)
+ *
+ * </pre>
+ * <p>
+ * 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.
+ * <p>
+ * @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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <pre>
+ *
+ * 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)
+ *
+ * </pre>
+ * <p>
+ * Conversion from the PCS to the device would be done by inverting these
+ * equations:
+ * <pre>
+ *
+ * Xd = Xp * (Xdw / Xd50)
+ * Yd = Yp * (Ydw / Yd50)
+ * Zd = Zp * (Zdw / Zd50)
+ *
+ * </pre>
+ * <p>
+ * 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.
+ * <p>
+ * <p>
+ * @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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/awt/color/ICC_Profile.java Fri Jun 06 08:29:25 2008 -0700
@@ -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 <A href="http://www.color.org"> http://www.color.org</A>).
+ * <p>
+ * 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).
+ * <p>
+ * 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.
+ * <p>
+ * @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 <code>ICC_Profile</code> object corresponding to
+ * the data in the specified <code>data</code> 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 <CODE>ColorSpace</CODE> class.
+ *
+ * @return an <code>ICC_Profile</code> object corresponding to
+ * the specified <code>ColorSpace</code> type.
+ * @exception IllegalArgumentException If <CODE>cspace</CODE> 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 <code>ICC_Profile</code> 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 <CODE>ICC_Profile</CODE> object corresponding to the
+ * data in the specified <code>InputStream</code>.
+ *
+ * @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
+ * <CODE>ColorSpace</CODE> 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
+ * <CODE>ColorSpace</CODE> 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
+ * <code>null</code> 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&nbsp;<code>1</code> corresponds to Java&nbsp;2
+ * Platform,&nbsp;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 <code>ObjectInputStream</code>.
+ * @serialData
+ * The <code>String</code> is the name of one of
+ * <code>CS_<var>*</var></code> constants defined in the
+ * {@link ColorSpace} class if the profile object is a profile
+ * for a predefined color space (for example
+ * <code>"CS_sRGB"</code>). The string is <code>null</code>
+ * otherwise.
+ * <p>
+ * The <code>byte[]</code> array is the profile data for the
+ * profile. For predefined color spaces <code>null</code> 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 <code>ObjectInputStream</code>.
+ * @throws ClassNotFoundException
+ * thrown by <code>ObjectInputStream</code>.
+ * @serialData
+ * The <code>String</code> is the name of one of
+ * <code>CS_<var>*</var></code> constants defined in the
+ * {@link ColorSpace} class if the profile object is a profile
+ * for a predefined color space (for example
+ * <code>"CS_sRGB"</code>). The string is <code>null</code>
+ * otherwise.
+ * <p>
+ * The <code>byte[]</code> array is the profile data for the
+ * profile. It will usually be <code>null</code> for the
+ * predefined profiles.
+ * <p>
+ * If the string is recognized as a constant name for
+ * predefined color space the object will be resolved into
+ * profile obtained with
+ * <code>getInstance(int&nbsp;cspace)</code> and the profile
+ * data are ignored. Otherwise the object will be resolved
+ * into profile obtained with
+ * <code>getInstance(byte[]&nbsp;data)</code>.
+ * @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;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/awt/color/ICC_ProfileGray.java Fri Jun 06 08:29:25 2008 -0700
@@ -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.
+ * <p>
+ * 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.
+<pre>
+
+&nbsp; PCSY = grayTRC[deviceGray]
+
+</pre>
+ * The inverse transform is done by converting the PCS Y components to
+ * device Gray via the inverse of the grayTRC.
+ * <p>
+ */
+
+
+
+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:
+<pre>
+
+&nbsp; gamma
+&nbsp; PCSY = deviceGray
+
+</pre>
+ * @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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/awt/color/ICC_ProfileRGB.java Fri Jun 06 08:29:25 2008 -0700
@@ -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:
+ * <ul>
+ * <li>The profile's color space type is RGB.</li>
+ * <li>The profile includes the <code>redColorantTag</code>,
+ * <code>greenColorantTag</code>, <code>blueColorantTag</code>,
+ * <code>redTRCTag</code>, <code>greenTRCTag</code>,
+ * <code>blueTRCTag</code>, and <code>mediaWhitePointTag</code> tags.</li>
+ * </ul>
+ * The <code>ICC_Profile</code> <code>getInstance</code> method will
+ * return an <code>ICC_ProfileRGB</code> object when these conditions are met.
+ * Three-component, matrix-based input profiles and RGB display profiles are
+ * examples of this type of profile.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <pre>
+ *
+ * &nbsp; linearR = redTRC[deviceR]
+ *
+ * &nbsp; linearG = greenTRC[deviceG]
+ *
+ * &nbsp; linearB = blueTRC[deviceB]
+ *
+ * &nbsp; _ _ _ _ _ _
+ * &nbsp;[ PCSX ] [ redColorantX greenColorantX blueColorantX ] [ linearR ]
+ * &nbsp;[ ] [ ] [ ]
+ * &nbsp;[ PCSY ] = [ redColorantY greenColorantY blueColorantY ] [ linearG ]
+ * &nbsp;[ ] [ ] [ ]
+ * &nbsp;[_ PCSZ _] [_ redColorantZ greenColorantZ blueColorantZ _] [_ linearB _]
+ *
+ * </pre>
+ * 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.
+ * <p>
+ */
+
+
+
+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 <code>ICC_ProfileRGB</code> from a CMM ID.
+ *
+ * @param ID The CMM ID for the profile.
+ *
+ */
+ ICC_ProfileRGB(long ID) {
+ super(ID);
+ }
+
+ /**
+ * Constructs a new <code>ICC_ProfileRGB</code> from a
+ * ProfileDeferralInfo object.
+ *
+ * @param pdi
+ */
+ ICC_ProfileRGB(ProfileDeferralInfo pdi) {
+ super(pdi);
+ }
+
+
+ /**
+ * Returns an array that contains the components of the profile's
+ * <CODE>mediaWhitePointTag</CODE>.
+ *
+ * @return A 3-element <CODE>float</CODE> array containing the x, y,
+ * and z components of the profile's <CODE>mediaWhitePointTag</CODE>.
+ */
+ public float[] getMediaWhitePoint() {
+ return super.getMediaWhitePoint();
+ }
+
+
+ /**
+ * Returns a 3x3 <CODE>float</CODE> matrix constructed from the
+ * X, Y, and Z components of the profile's <CODE>redColorantTag</CODE>,
+ * <CODE>greenColorantTag</CODE>, and <CODE>blueColorantTag</CODE>.
+ * <p>
+ * 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 <CODE>float</CODE> array that contains the x, y, and z
+ * components of the profile's <CODE>redColorantTag</CODE>,
+ * <CODE>greenColorantTag</CODE>, and <CODE>blueColorantTag</CODE>.
+ */
+ 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.
+ * <p>
+ * 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:
+ * <pre>
+ *
+ * &nbsp; gamma
+ * &nbsp; linearComponent = deviceComponent
+ *
+ *</pre>
+ * @param component The <CODE>ICC_ProfileRGB</CODE> 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 <code>REDCOMPONENT</code>,
+ * <code>GREENCOMPONENT</code>, or <code>BLUECOMPONENT</code>.
+ * 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
+ * <code>short</code> values even though they are returned in a
+ * <code>short</code> 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 <CODE>ICC_ProfileRGB</CODE> constant that
+ * represents the component whose TRC you want to retrieve:
+ * <CODE>REDCOMPONENT</CODE>, <CODE>GREENCOMPONENT</CODE>, or
+ * <CODE>BLUECOMPONENT</CODE>.
+ *
+ * @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;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/awt/image/BandedSampleModel.java Fri Jun 06 08:29:25 2008 -0700
@@ -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 <code>dataType</code> 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 <code>dataType</code> 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 <code>BandedSampleModel</code>
+ * @param h the height of the resulting <code>BandedSampleModel</code>
+ * @return a new <code>BandedSampleModel</code> with the specified
+ * width and height.
+ * @throws IllegalArgumentException if <code>w</code> or
+ * <code>h</code> equals either
+ * <code>Integer.MAX_VALUE</code> or
+ * <code>Integer.MIN_VALUE</code>
+ * @throws IllegalArgumentException if <code>dataType</code> 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 <code>dataType</code> 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; i<bands.length; i++) {
+ newBankIndices[i] = bankIndices[bands[i]];
+ newBandOffsets[i] = bandOffsets[bands[i]];
+ }
+
+ return new BandedSampleModel(this.dataType, width, height,
+ this.scanlineStride,
+ newBankIndices, newBandOffsets);
+ }
+
+ /**
+ * Creates a DataBuffer that corresponds to this BandedSampleModel,
+ * The DataBuffer's data type, number of banks, and size
+ * will be consistent with this BandedSampleModel.
+ * @throws IllegalArgumentException if <code>dataType</code> 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.
+ * <p>
+ * The following code illustrates transferring data for one pixel from
+ * DataBuffer <code>db1</code>, whose storage layout is described by
+ * BandedSampleModel <code>bsm1</code>, to DataBuffer <code>db2</code>,
+ * whose storage layout is described by
+ * BandedSampleModel <code>bsm2</code>.
+ * The transfer will generally be more efficient than using
+ * getPixel/setPixel.
+ * <pre>
+ * BandedSampleModel bsm1, bsm2;
+ * DataBufferInt db1, db2;
+ * bsm2.setDataElements(x, y, bsm1.getDataElements(x, y, null, db1),
+ * db2);
+ * </pre>
+ * 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.
+ * <p>
+ * 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<numDataElems; i++) {
+ bdata[i] = (byte)data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)bdata;
+ break;
+
+ case DataBuffer.TYPE_USHORT:
+ case DataBuffer.TYPE_SHORT:
+
+ short[] sdata;
+
+ if (obj == null) {
+ sdata = new short[numDataElems];
+ } else {
+ sdata = (short[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ sdata[i] = (short)data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)sdata;
+ break;
+
+ case DataBuffer.TYPE_INT:
+
+ int[] idata;
+
+ if (obj == null) {
+ idata = new int[numDataElems];
+ } else {
+ idata = (int[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ idata[i] = data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)idata;
+ break;
+
+ case DataBuffer.TYPE_FLOAT:
+
+ float[] fdata;
+
+ if (obj == null) {
+ fdata = new float[numDataElems];
+ } else {
+ fdata = (float[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ fdata[i] = data.getElemFloat(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)fdata;
+ break;
+
+ case DataBuffer.TYPE_DOUBLE:
+
+ double[] ddata;
+
+ if (obj == null) {
+ ddata = new double[numDataElems];
+ } else {
+ ddata = (double[])obj;
+ }
+
+ for (int i=0; i<numDataElems; i++) {
+ ddata[i] = data.getElemDouble(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+
+ obj = (Object)ddata;
+ break;
+ }
+
+ return obj;
+ }
+
+ /**
+ * Returns all samples 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 the 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 = iArray;
+ } else {
+ pixels = new int [numBands];
+ }
+
+ int pixelOffset = y*scanlineStride + x;
+ for (int i=0; i<numBands; i++) {
+ pixels[i] = data.getElem(bankIndices[i],
+ pixelOffset + bandOffsets[i]);
+ }
+ return pixels;
+ }
+
+ /**
+ * Returns all samples 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 iArray If non-null, returns the samples in this array
+ * @param data The DataBuffer containing the image data
+ * @return the samples for 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];
+ }
+
+ 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!");
+ }