--- a/jdk/src/share/classes/java/awt/color/ICC_Profile.java Fri Jun 03 20:13:50 2011 -0700
+++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java Sat Jun 04 17:30:58 2011 -0700
@@ -1382,13 +1382,19 @@
/**
* 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.
+ * a byte array. The array should contain data in a format, corresponded
+ * to the {@code tagSignature} as defined in the ICC specification, section 10.
+ * 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
+ * @throws IllegalArgumentException if {@code tagSignature} is not a signature
+ * as defined in the ICC specification.
+ * @throws IllegalArgumentException if a content of the {@code tagData}
+ * array can not be interpreted as valid tag data, corresponding
+ * to the {@code tagSignature}.
* @see #getData
*/
public void setData(int tagSignature, byte[] tagData) {
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c Fri Jun 03 20:13:50 2011 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c Sat Jun 04 17:30:58 2011 -0700
@@ -233,9 +233,19 @@
jint dataSize;
storeID_t sProf;
+ if (JNU_IsNull(env, data)) {
+ JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
+ return 0L;
+ }
+
dataArray = (*env)->GetByteArrayElements (env, data, 0);
dataSize = (*env)->GetArrayLength (env, data);
+ if (dataArray == NULL) {
+ JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
+ return 0L;
+ }
+
sProf.pf = cmsOpenProfileFromMem((const void *)dataArray,
(cmsUInt32Number) dataSize);
@@ -334,8 +344,9 @@
}
/* Get profile header info */
-cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
-cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
+static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
+static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
+static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size);
/*
* Class: sun_java2d_cmm_lcms_LCMS
@@ -356,7 +367,7 @@
result = sizeof(cmsICCHeader);
} else {
if (cmsIsTag(sProf.pf, sig.cms)) {
- result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0);
+ result = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0);
} else {
JNU_ThrowByName(env, "java/awt/color/CMMException",
"ICC profile tag not found");
@@ -468,22 +479,30 @@
sProf.j = id;
sig.j = tagSig;
+ if (JNU_IsNull(env, data)) {
+ JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
+ return;
+ }
tagSize =(*env)->GetArrayLength(env, data);
dataArray = (*env)->GetByteArrayElements(env, data, 0);
+ if (dataArray == NULL) {
+ JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
+ return;
+ }
+
if (tagSig == SigHead) {
status = _setHeaderInfo(sProf.pf, dataArray, tagSize);
} else {
- status = cmsWriteRawTag(sProf.pf, sig.cms, dataArray, tagSize);
+ status = _writeCookedTag(sProf.pf, sig.cms, dataArray, tagSize);
}
(*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
if (!status) {
- JNU_ThrowByName(env, "java/awt/color/CMMException",
- "Can not write tag data.");
+ JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
}
}
@@ -645,7 +664,7 @@
PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
}
-cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
+static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
{
cmsUInt32Number pfSize = 0;
cmsUInt8Number* pfBuffer = NULL;
@@ -672,7 +691,7 @@
return status;
}
-cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
+static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
{
cmsICCHeader pfHeader = { 0 };
@@ -696,3 +715,77 @@
return TRUE;
}
+
+static cmsBool _writeCookedTag(cmsHPROFILE pfTarget,
+ cmsTagSignature sig,
+ jbyte *pData, jint size)
+{
+ cmsBool status;
+ cmsUInt32Number pfSize = 0;
+ cmsUInt8Number* pfBuffer = NULL;
+
+ cmsHPROFILE p = cmsCreateProfilePlaceholder(NULL);
+ if (NULL != p) {
+ cmsICCHeader hdr = { 0 };
+
+ /* Populate the placeholder's header according to target profile */
+ hdr.flags = cmsGetHeaderFlags(pfTarget);
+ hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget);
+ hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget);
+ hdr.model = cmsGetHeaderModel(pfTarget);
+ hdr.pcs = cmsGetPCS(pfTarget);
+ hdr.colorSpace = cmsGetColorSpace(pfTarget);
+ hdr.deviceClass = cmsGetDeviceClass(pfTarget);
+ hdr.version = cmsGetEncodedICCversion(pfTarget);
+ cmsGetHeaderAttributes(pfTarget, &hdr.attributes);
+ cmsGetHeaderProfileID(pfTarget, (cmsUInt8Number*)&hdr.profileID);
+
+ cmsSetHeaderFlags(p, hdr.flags);
+ cmsSetHeaderManufacturer(p, hdr.manufacturer);
+ cmsSetHeaderModel(p, hdr.model);
+ cmsSetHeaderAttributes(p, hdr.attributes);
+ cmsSetHeaderProfileID(p, (cmsUInt8Number*)&(hdr.profileID));
+ cmsSetHeaderRenderingIntent(p, hdr.renderingIntent);
+ cmsSetPCS(p, hdr.pcs);
+ cmsSetColorSpace(p, hdr.colorSpace);
+ cmsSetDeviceClass(p, hdr.deviceClass);
+ cmsSetEncodedICCversion(p, hdr.version);
+
+
+ if (cmsWriteRawTag(p, sig, pData, size)) {
+ if (cmsSaveProfileToMem(p, NULL, &pfSize)) {
+ pfBuffer = malloc(pfSize);
+ if (pfBuffer != NULL) {
+ /* load raw profile data into the buffer */
+ if (!cmsSaveProfileToMem(p, pfBuffer, &pfSize)) {
+ free(pfBuffer);
+ pfBuffer = NULL;
+ }
+ }
+ }
+ }
+ cmsCloseProfile(p);
+ }
+
+ if (pfBuffer == NULL) {
+ return FALSE;
+ }
+
+ /* re-open the placeholder profile */
+ p = cmsOpenProfileFromMem(pfBuffer, pfSize);
+ free(pfBuffer);
+ status = FALSE;
+
+ if (p != NULL) {
+ /* Note that pCookedTag points to internal structures of the placeholder,
+ * so this data is valid only while the placeholder is open.
+ */
+ void *pCookedTag = cmsReadTag(p, sig);
+ if (pCookedTag != NULL) {
+ status = cmsWriteTag(pfTarget, sig, pCookedTag);
+ }
+ pCookedTag = NULL;
+ cmsCloseProfile(p);
+ }
+ return status;
+}
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c Fri Jun 03 20:13:50 2011 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c Sat Jun 04 17:30:58 2011 -0700
@@ -1636,6 +1636,11 @@
TagDescriptor = _cmsGetTagDescriptor(sig);
// Serialize
+ if (!_cmsWriteTypeBase(MemIO, TypeHandler ->Signature)) {
+ cmsCloseIOhandler(MemIO);
+ return 0;
+ }
+
if (!TypeHandler ->WritePtr(TypeHandler, MemIO, Object, TagDescriptor ->ElemCount)) return 0;
// Get Size and close
--- a/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java Fri Jun 03 20:13:50 2011 -0700
+++ b/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java Sat Jun 04 17:30:58 2011 -0700
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 6476665 6523403 6733501
+ * @bug 6476665 6523403 6733501 7042594
* @summary Verifies reading and writing profiles and tags of the standard color
* spaces
* @run main ReadWriteProfileTest
@@ -94,7 +94,16 @@
for (int tagSig : tags[i].keySet()) {
byte [] tagData = pf.getData(tagSig);
byte [] empty = new byte[tagData.length];
- pf.setData(tagSig, empty);
+ boolean emptyDataRejected = false;
+ try {
+ pf.setData(tagSig, empty);
+ } catch (IllegalArgumentException e) {
+ emptyDataRejected = true;
+ }
+ if (!emptyDataRejected) {
+ throw new
+ RuntimeException("Test failed: empty tag data was not rejected.");
+ }
pf.setData(tagSig, tagData);
byte [] tagData1 = pf.getData(tagSig);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/cmm/ProfileOp/SetDataTest.java Sat Jun 04 17:30:58 2011 -0700
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 7042594
+ * @summary Test verifies that ICC_Profile.setData() conforms the spec.
+ *
+ * @run main SetDataTest
+ */
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.awt.color.ICC_Profile;
+import static java.awt.color.ICC_ColorSpace.CS_GRAY;
+import static java.awt.color.ICC_Profile.icSigGrayTRCTag;
+import static java.awt.color.ICC_Profile.icSigRedTRCTag;
+import static java.awt.color.ICC_Profile.icSigGreenTRCTag;
+
+public class SetDataTest {
+
+ static class TestCase {
+
+ static ICC_Profile profile;
+ static byte[] validTRCdata;
+ static byte[] invalidTRCData;
+
+ static {
+ profile = ICC_Profile.getInstance(CS_GRAY);
+ validTRCdata = profile.getData(icSigGrayTRCTag);
+ invalidTRCData = new byte[]{0x42, 0x42, 0x42, 0x42, 1, 3, 4, 6,};
+ }
+ String desciption;
+ int signature;
+ boolean useValidData;
+ Throwable err;
+ boolean isIAEexpected;
+
+ public TestCase(String descr, int sig,
+ boolean useValidData,
+ boolean isIAEexpected) {
+ this.desciption = descr;
+ this.signature = sig;
+
+ this.useValidData = useValidData;
+ this.isIAEexpected = isIAEexpected;
+
+ }
+
+ public void doTest() {
+ System.out.println(desciption);
+ byte[] data = useValidData
+ ? validTRCdata : invalidTRCData;
+ err = null;
+ try {
+ profile.setData(signature, data);
+ } catch (Throwable e) {
+ err = e;
+ System.out.println("Got exception: " +
+ e.getClass().getName() + ": " +
+ e.getMessage());
+ }
+
+ if (isIAEexpected) {
+ if (err == null) {
+ throw new RuntimeException(
+ "Test failed: expected exception was not thrown");
+ }
+ if (!(err instanceof IllegalArgumentException)) {
+ throw new RuntimeException(
+ "Unexpected exception was thrown: " +
+ err.getMessage(), err);
+ }
+ } else {
+ if (err != null) {
+ throw new RuntimeException(
+ "Unexpected exception was thrown: " +
+ err.getMessage(), err);
+ }
+ }
+ System.out.println("Testcase PASSED");
+ }
+ }
+
+ public static void main(String[] args) {
+ List<TestCase> tests = new ArrayList<TestCase>();
+
+ TestCase selfupdate = new TestCase(
+ "Selfupdate: update grayTRC with the same data.",
+ icSigGrayTRCTag, true, false);
+ tests.add(selfupdate);
+
+ TestCase newValdTag = new TestCase(
+ "Insert new valid tag",
+ icSigRedTRCTag,
+ true, false);
+ tests.add(newValdTag);
+
+ TestCase newInvalidTag = new TestCase(
+ "Insert new tag with invalid contet",
+ icSigGreenTRCTag,
+ false, true);
+ tests.add(newInvalidTag);
+
+ TestCase newUnknowInvalidTag = new TestCase(
+ "Insert new tag with invalid data and unknown signature",
+ 0x41414141,
+ false, true);
+ tests.add(newUnknowInvalidTag);
+
+ TestCase newUnknownValidTag = new TestCase(
+ "Insert new tag with valid data and unknown signatiure",
+ 0x41414141,
+ true, true);
+ tests.add(newUnknownValidTag);
+
+ for (TestCase t: tests) {
+ t.doTest();
+ }
+ System.out.println("Test passed!.");
+ }
+}