提交 39bc336a 编写于 作者: B bae

7043064: sun/java2d/cmm/ tests failed against RI b141 & b138-nightly

Reviewed-by: prr, vadim
上级 79da3b81
...@@ -28,9 +28,8 @@ ...@@ -28,9 +28,8 @@
SUNWprivate_1.1 { SUNWprivate_1.1 {
global: global:
Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative;
Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative;
Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative;
Java_sun_java2d_cmm_lcms_LCMS_getProfileData;
Java_sun_java2d_cmm_lcms_LCMS_getTagNative; Java_sun_java2d_cmm_lcms_LCMS_getTagNative;
Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative;
Java_sun_java2d_cmm_lcms_LCMS_colorConvert; Java_sun_java2d_cmm_lcms_LCMS_colorConvert;
......
...@@ -28,9 +28,8 @@ ...@@ -28,9 +28,8 @@
SUNWprivate_1.1 { SUNWprivate_1.1 {
global: global:
Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative;
Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative;
Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative;
Java_sun_java2d_cmm_lcms_LCMS_getProfileData;
Java_sun_java2d_cmm_lcms_LCMS_getTagNative; Java_sun_java2d_cmm_lcms_LCMS_getTagNative;
Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative;
Java_sun_java2d_cmm_lcms_LCMS_colorConvert; Java_sun_java2d_cmm_lcms_LCMS_colorConvert;
......
...@@ -37,6 +37,7 @@ package java.awt.color; ...@@ -37,6 +37,7 @@ package java.awt.color;
import sun.java2d.cmm.PCMM; import sun.java2d.cmm.PCMM;
import sun.java2d.cmm.CMSManager; import sun.java2d.cmm.CMSManager;
import sun.java2d.cmm.Profile;
import sun.java2d.cmm.ProfileDataVerifier; import sun.java2d.cmm.ProfileDataVerifier;
import sun.java2d.cmm.ProfileDeferralMgr; import sun.java2d.cmm.ProfileDeferralMgr;
import sun.java2d.cmm.ProfileDeferralInfo; import sun.java2d.cmm.ProfileDeferralInfo;
...@@ -94,7 +95,7 @@ public class ICC_Profile implements Serializable { ...@@ -94,7 +95,7 @@ public class ICC_Profile implements Serializable {
private static final long serialVersionUID = -3938515861990936766L; private static final long serialVersionUID = -3938515861990936766L;
transient long ID; private transient Profile cmmProfile;
private transient ProfileDeferralInfo deferralInfo; private transient ProfileDeferralInfo deferralInfo;
private transient ProfileActivator profileActivator; private transient ProfileActivator profileActivator;
...@@ -727,8 +728,8 @@ public class ICC_Profile implements Serializable { ...@@ -727,8 +728,8 @@ public class ICC_Profile implements Serializable {
/** /**
* Constructs an ICC_Profile object with a given ID. * Constructs an ICC_Profile object with a given ID.
*/ */
ICC_Profile(long ID) { ICC_Profile(Profile p) {
this.ID = ID; this.cmmProfile = p;
} }
...@@ -751,8 +752,8 @@ public class ICC_Profile implements Serializable { ...@@ -751,8 +752,8 @@ public class ICC_Profile implements Serializable {
* Frees the resources associated with an ICC_Profile object. * Frees the resources associated with an ICC_Profile object.
*/ */
protected void finalize () { protected void finalize () {
if (ID != 0) { if (cmmProfile != null) {
CMSManager.getModule().freeProfile(ID); CMSManager.getModule().freeProfile(cmmProfile);
} else if (profileActivator != null) { } else if (profileActivator != null) {
ProfileDeferralMgr.unregisterDeferral(profileActivator); ProfileDeferralMgr.unregisterDeferral(profileActivator);
} }
...@@ -770,7 +771,7 @@ public class ICC_Profile implements Serializable { ...@@ -770,7 +771,7 @@ public class ICC_Profile implements Serializable {
public static ICC_Profile getInstance(byte[] data) { public static ICC_Profile getInstance(byte[] data) {
ICC_Profile thisProfile; ICC_Profile thisProfile;
long theID; Profile p = null;
if (ProfileDeferralMgr.deferring) { if (ProfileDeferralMgr.deferring) {
ProfileDeferralMgr.activateProfiles(); ProfileDeferralMgr.activateProfiles();
...@@ -779,32 +780,32 @@ public class ICC_Profile implements Serializable { ...@@ -779,32 +780,32 @@ public class ICC_Profile implements Serializable {
ProfileDataVerifier.verify(data); ProfileDataVerifier.verify(data);
try { try {
theID = CMSManager.getModule().loadProfile(data); p = CMSManager.getModule().loadProfile(data);
} catch (CMMException c) { } catch (CMMException c) {
throw new IllegalArgumentException("Invalid ICC Profile Data"); throw new IllegalArgumentException("Invalid ICC Profile Data");
} }
try { try {
if ((getColorSpaceType (theID) == ColorSpace.TYPE_GRAY) && if ((getColorSpaceType (p) == ColorSpace.TYPE_GRAY) &&
(getData (theID, icSigMediaWhitePointTag) != null) && (getData (p, icSigMediaWhitePointTag) != null) &&
(getData (theID, icSigGrayTRCTag) != null)) { (getData (p, icSigGrayTRCTag) != null)) {
thisProfile = new ICC_ProfileGray (theID); thisProfile = new ICC_ProfileGray (p);
} }
else if ((getColorSpaceType (theID) == ColorSpace.TYPE_RGB) && else if ((getColorSpaceType (p) == ColorSpace.TYPE_RGB) &&
(getData (theID, icSigMediaWhitePointTag) != null) && (getData (p, icSigMediaWhitePointTag) != null) &&
(getData (theID, icSigRedColorantTag) != null) && (getData (p, icSigRedColorantTag) != null) &&
(getData (theID, icSigGreenColorantTag) != null) && (getData (p, icSigGreenColorantTag) != null) &&
(getData (theID, icSigBlueColorantTag) != null) && (getData (p, icSigBlueColorantTag) != null) &&
(getData (theID, icSigRedTRCTag) != null) && (getData (p, icSigRedTRCTag) != null) &&
(getData (theID, icSigGreenTRCTag) != null) && (getData (p, icSigGreenTRCTag) != null) &&
(getData (theID, icSigBlueTRCTag) != null)) { (getData (p, icSigBlueTRCTag) != null)) {
thisProfile = new ICC_ProfileRGB (theID); thisProfile = new ICC_ProfileRGB (p);
} }
else { else {
thisProfile = new ICC_Profile (theID); thisProfile = new ICC_Profile (p);
} }
} catch (CMMException c) { } catch (CMMException c) {
thisProfile = new ICC_Profile (theID); thisProfile = new ICC_Profile (p);
} }
return thisProfile; return thisProfile;
} }
...@@ -1119,7 +1120,7 @@ public class ICC_Profile implements Serializable { ...@@ -1119,7 +1120,7 @@ public class ICC_Profile implements Serializable {
fileName); fileName);
} }
try { try {
ID = CMSManager.getModule().loadProfile(profileData); cmmProfile = CMSManager.getModule().loadProfile(profileData);
} catch (CMMException c) { } catch (CMMException c) {
ProfileDataException pde = new ProfileDataException pde = new
ProfileDataException("Invalid ICC Profile Data" + fileName); ProfileDataException("Invalid ICC Profile Data" + fileName);
...@@ -1229,14 +1230,14 @@ public class ICC_Profile implements Serializable { ...@@ -1229,14 +1230,14 @@ public class ICC_Profile implements Serializable {
causing a deferred profile causing a deferred profile
to be loaded */ to be loaded */
} }
return getColorSpaceType(ID); return getColorSpaceType(cmmProfile);
} }
static int getColorSpaceType(long profileID) { static int getColorSpaceType(Profile p) {
byte[] theHeader; byte[] theHeader;
int theColorSpaceSig, theColorSpace; int theColorSpaceSig, theColorSpace;
theHeader = getData(profileID, icSigHead); theHeader = getData(p, icSigHead);
theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace); theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
theColorSpace = iccCStoJCS (theColorSpaceSig); theColorSpace = iccCStoJCS (theColorSpaceSig);
return theColorSpace; return theColorSpace;
...@@ -1258,15 +1259,15 @@ public class ICC_Profile implements Serializable { ...@@ -1258,15 +1259,15 @@ public class ICC_Profile implements Serializable {
if (ProfileDeferralMgr.deferring) { if (ProfileDeferralMgr.deferring) {
ProfileDeferralMgr.activateProfiles(); ProfileDeferralMgr.activateProfiles();
} }
return getPCSType(ID); return getPCSType(cmmProfile);
} }
static int getPCSType(long profileID) { static int getPCSType(Profile p) {
byte[] theHeader; byte[] theHeader;
int thePCSSig, thePCS; int thePCSSig, thePCS;
theHeader = getData(profileID, icSigHead); theHeader = getData(p, icSigHead);
thePCSSig = intFromBigEndian(theHeader, icHdrPcs); thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
thePCS = iccCStoJCS(thePCSSig); thePCS = iccCStoJCS(thePCSSig);
return thePCS; return thePCS;
...@@ -1326,12 +1327,12 @@ public class ICC_Profile implements Serializable { ...@@ -1326,12 +1327,12 @@ public class ICC_Profile implements Serializable {
PCMM mdl = CMSManager.getModule(); PCMM mdl = CMSManager.getModule();
/* get the number of bytes needed for this profile */ /* get the number of bytes needed for this profile */
profileSize = mdl.getProfileSize(ID); profileSize = mdl.getProfileSize(cmmProfile);
profileData = new byte [profileSize]; profileData = new byte [profileSize];
/* get the data for the profile */ /* get the data for the profile */
mdl.getProfileData(ID, profileData); mdl.getProfileData(cmmProfile, profileData);
return profileData; return profileData;
} }
...@@ -1358,11 +1359,11 @@ public class ICC_Profile implements Serializable { ...@@ -1358,11 +1359,11 @@ public class ICC_Profile implements Serializable {
ProfileDeferralMgr.activateProfiles(); ProfileDeferralMgr.activateProfiles();
} }
return getData(ID, tagSignature); return getData(cmmProfile, tagSignature);
} }
static byte[] getData(long profileID, int tagSignature) { static byte[] getData(Profile p, int tagSignature) {
int tagSize; int tagSize;
byte[] tagData; byte[] tagData;
...@@ -1370,12 +1371,12 @@ public class ICC_Profile implements Serializable { ...@@ -1370,12 +1371,12 @@ public class ICC_Profile implements Serializable {
PCMM mdl = CMSManager.getModule(); PCMM mdl = CMSManager.getModule();
/* get the number of bytes needed for this tag */ /* get the number of bytes needed for this tag */
tagSize = mdl.getTagSize(profileID, tagSignature); tagSize = mdl.getTagSize(p, tagSignature);
tagData = new byte[tagSize]; /* get an array for the tag */ tagData = new byte[tagSize]; /* get an array for the tag */
/* get the tag's data */ /* get the tag's data */
mdl.getTagData(profileID, tagSignature, tagData); mdl.getTagData(p, tagSignature, tagData);
} catch(CMMException c) { } catch(CMMException c) {
tagData = null; tagData = null;
} }
...@@ -1406,7 +1407,7 @@ public class ICC_Profile implements Serializable { ...@@ -1406,7 +1407,7 @@ public class ICC_Profile implements Serializable {
ProfileDeferralMgr.activateProfiles(); ProfileDeferralMgr.activateProfiles();
} }
CMSManager.getModule().setTagData(ID, tagSignature, tagData); CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData);
} }
/** /**
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
package java.awt.color; package java.awt.color;
import java.awt.image.LookupTable; import sun.java2d.cmm.Profile;
import sun.java2d.cmm.ProfileDeferralInfo; import sun.java2d.cmm.ProfileDeferralInfo;
/** /**
...@@ -76,8 +76,8 @@ extends ICC_Profile { ...@@ -76,8 +76,8 @@ extends ICC_Profile {
/** /**
* Constructs a new ICC_ProfileGray from a CMM ID. * Constructs a new ICC_ProfileGray from a CMM ID.
*/ */
ICC_ProfileGray(long ID) { ICC_ProfileGray(Profile p) {
super(ID); super(p);
} }
/** /**
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
package java.awt.color; package java.awt.color;
import java.awt.image.LookupTable; import sun.java2d.cmm.Profile;
import sun.java2d.cmm.ProfileDeferralInfo; import sun.java2d.cmm.ProfileDeferralInfo;
/** /**
...@@ -114,8 +114,8 @@ extends ICC_Profile { ...@@ -114,8 +114,8 @@ extends ICC_Profile {
* @param ID The CMM ID for the profile. * @param ID The CMM ID for the profile.
* *
*/ */
ICC_ProfileRGB(long ID) { ICC_ProfileRGB(Profile p) {
super(ID); super(p);
} }
/** /**
......
...@@ -104,53 +104,53 @@ public class CMSManager { ...@@ -104,53 +104,53 @@ public class CMSManager {
cName = tcmm.getClass().getName(); cName = tcmm.getClass().getName();
} }
public long loadProfile(byte[] data) { public Profile loadProfile(byte[] data) {
System.err.print(cName + ".loadProfile"); System.err.print(cName + ".loadProfile");
long profileID = tcmm.loadProfile(data); Profile p = tcmm.loadProfile(data);
System.err.printf("(ID=%x)\n", profileID); System.err.printf("(ID=%s)\n", p.toString());
return profileID; return p;
} }
public void freeProfile(long profileID) { public void freeProfile(Profile p) {
System.err.printf(cName + ".freeProfile(ID=%x)\n", profileID); System.err.printf(cName + ".freeProfile(ID=%s)\n", p.toString());
tcmm.freeProfile(profileID); tcmm.freeProfile(p);
} }
public int getProfileSize(long profileID) { public int getProfileSize(Profile p) {
System.err.print(cName + ".getProfileSize(ID=" + profileID + ")"); System.err.print(cName + ".getProfileSize(ID=" + p + ")");
int size = tcmm.getProfileSize(profileID); int size = tcmm.getProfileSize(p);
System.err.println("=" + size); System.err.println("=" + size);
return size; return size;
} }
public void getProfileData(long profileID, byte[] data) { public void getProfileData(Profile p, byte[] data) {
System.err.print(cName + ".getProfileData(ID=" + profileID + ") "); System.err.print(cName + ".getProfileData(ID=" + p + ") ");
System.err.println("requested " + data.length + " byte(s)"); System.err.println("requested " + data.length + " byte(s)");
tcmm.getProfileData(profileID, data); tcmm.getProfileData(p, data);
} }
public int getTagSize(long profileID, int tagSignature) { public int getTagSize(Profile p, int tagSignature) {
System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)", System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)",
profileID, signatureToString(tagSignature)); p, signatureToString(tagSignature));
int size = tcmm.getTagSize(profileID, tagSignature); int size = tcmm.getTagSize(p, tagSignature);
System.err.println("=" + size); System.err.println("=" + size);
return size; return size;
} }
public void getTagData(long profileID, int tagSignature, public void getTagData(Profile p, int tagSignature,
byte[] data) { byte[] data) {
System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)", System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)",
profileID, signatureToString(tagSignature)); p, signatureToString(tagSignature));
System.err.println(" requested " + data.length + " byte(s)"); System.err.println(" requested " + data.length + " byte(s)");
tcmm.getTagData(profileID, tagSignature, data); tcmm.getTagData(p, tagSignature, data);
} }
public void setTagData(long profileID, int tagSignature, public void setTagData(Profile p, int tagSignature,
byte[] data) { byte[] data) {
System.err.print(cName + ".setTagData(ID=" + profileID + System.err.print(cName + ".setTagData(ID=" + p +
", TagSig=" + tagSignature + ")"); ", TagSig=" + tagSignature + ")");
System.err.println(" sending " + data.length + " byte(s)"); System.err.println(" sending " + data.length + " byte(s)");
tcmm.setTagData(profileID, tagSignature, data); tcmm.setTagData(p, tagSignature, data);
} }
/* methods for creating ColorTransforms */ /* methods for creating ColorTransforms */
......
...@@ -32,13 +32,13 @@ import java.awt.color.ICC_Profile; ...@@ -32,13 +32,13 @@ import java.awt.color.ICC_Profile;
public interface PCMM { public interface PCMM {
/* methods invoked from ICC_Profile */ /* methods invoked from ICC_Profile */
public long loadProfile(byte[] data); public Profile loadProfile(byte[] data);
public void freeProfile(long profileID); public void freeProfile(Profile p);
public int getProfileSize(long profileID); public int getProfileSize(Profile p);
public void getProfileData(long profileID, byte[] data); public void getProfileData(Profile p, byte[] data);
public void getTagData(long profileID, int tagSignature, byte[] data); public void getTagData(Profile p, int tagSignature, byte[] data);
public int getTagSize(long profileID, int tagSignature); public int getTagSize(Profile p, int tagSignature);
public void setTagData(long profileID, int tagSignature, byte[] data); public void setTagData(Profile p, int tagSignature, byte[] data);
/* methods for creating ColorTransforms */ /* methods for creating ColorTransforms */
public ColorTransform createTransform(ICC_Profile profile, int renderType, public ColorTransform createTransform(ICC_Profile profile, int renderType,
......
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.java2d.cmm;
import java.awt.color.CMMException;
public class Profile {
private final long nativePtr;
protected Profile(long ptr) {
nativePtr = ptr;
}
protected final long getNativePtr() {
if (nativePtr == 0L) {
throw new CMMException("Invalid profile: ptr is null");
}
return nativePtr;
}
}
...@@ -25,96 +25,139 @@ ...@@ -25,96 +25,139 @@
package sun.java2d.cmm.lcms; package sun.java2d.cmm.lcms;
import java.awt.color.CMMException;
import java.awt.color.ICC_Profile; import java.awt.color.ICC_Profile;
import java.util.Arrays;
import java.util.HashMap;
import sun.java2d.cmm.ColorTransform; import sun.java2d.cmm.ColorTransform;
import sun.java2d.cmm.PCMM; import sun.java2d.cmm.PCMM;
import sun.java2d.cmm.Profile;
import sun.java2d.cmm.lcms.LCMSProfile.TagData;
public class LCMS implements PCMM { public class LCMS implements PCMM {
/* methods invoked from ICC_Profile */ /* methods invoked from ICC_Profile */
@Override @Override
public long loadProfile(byte[] data) { public Profile loadProfile(byte[] data) {
long id = loadProfileNative(data); final Object disposerRef = new Object();
if (id != 0L) { final long ptr = loadProfileNative(data, disposerRef);
if (profiles == null) {
profiles = new HashMap<>(); if (ptr != 0L) {
return new LCMSProfile(ptr, disposerRef);
} }
profiles.put(id, new TagCache(id)); return null;
} }
return id;
private native long loadProfileNative(byte[] data, Object ref);
private LCMSProfile getLcmsProfile(Profile p) {
if (p instanceof LCMSProfile) {
return (LCMSProfile)p;
}
throw new CMMException("Invalid profile: " + p);
} }
private native long loadProfileNative(byte[] data);
@Override @Override
public void freeProfile(long profileID) { public void freeProfile(Profile p) {
TagCache c = profiles.remove(profileID); // we use disposer, so this method does nothing
if (c != null) {
c.clear();
} }
if (profiles.isEmpty()) {
profiles = null; @Override
public int getProfileSize(final Profile p) {
synchronized (p) {
return getProfileSizeNative(getLcmsProfile(p).getLcmsPtr());
} }
freeProfileNative(profileID);
} }
private native void freeProfileNative(long profileID); private native int getProfileSizeNative(long ptr);
public native synchronized int getProfileSize(long profileID); @Override
public void getProfileData(final Profile p, byte[] data) {
synchronized (p) {
getProfileDataNative(getLcmsProfile(p).getLcmsPtr(), data);
}
}
public native synchronized void getProfileData(long profileID, byte[] data); private native void getProfileDataNative(long ptr, byte[] data);
@Override @Override
public synchronized int getTagSize(long profileID, int tagSignature) { public int getTagSize(Profile p, int tagSignature) {
TagCache cache = profiles.get(profileID); final LCMSProfile profile = getLcmsProfile(p);
if (cache == null) { synchronized (profile) {
cache = new TagCache(profileID); TagData t = profile.getTag(tagSignature);
profiles.put(profileID, cache);
}
TagData t = cache.getTag(tagSignature);
return t == null ? 0 : t.getSize(); return t == null ? 0 : t.getSize();
} }
}
private static native byte[] getTagNative(long profileID, int signature); static native byte[] getTagNative(long profileID, int signature);
@Override @Override
public synchronized void getTagData(long profileID, int tagSignature, public void getTagData(Profile p, int tagSignature, byte[] data)
byte[] data)
{ {
TagCache cache = profiles.get(profileID); final LCMSProfile profile = getLcmsProfile(p);
if (cache == null) { synchronized (profile) {
cache = new TagCache(profileID); TagData t = profile.getTag(tagSignature);
profiles.put(profileID, cache);
}
TagData t = cache.getTag(tagSignature);
if (t != null) { if (t != null) {
t.copyDataTo(data); t.copyDataTo(data);
} }
} }
}
@Override @Override
public synchronized void setTagData(long profileID, int tagSignature, byte[] data) { public synchronized void setTagData(Profile p, int tagSignature, byte[] data) {
TagCache cache = profiles.get(profileID); final LCMSProfile profile = getLcmsProfile(p);
if (cache != null) { synchronized (profile) {
cache.clear(); profile.clearTagCache();
// Now we are going to update the profile with new tag data
// In some cases, we may change the pointer to the native
// profile.
//
// If we fail to write tag data for any reason, the old pointer
// should be used.
setTagDataNative(profile.getLcmsPtr(),
tagSignature, data);
} }
setTagDataNative(profileID, tagSignature, data);
} }
private native synchronized void setTagDataNative(long profileID, int tagSignature, /**
* Writes supplied data as a tag into the profile.
* Destroys old profile, if new one was successfully
* created.
*
* Returns valid pointer to new profile.
*
* Throws CMMException if operation fails, preserve old profile from
* destruction.
*/
private native void setTagDataNative(long ptr, int tagSignature,
byte[] data); byte[] data);
public static native long getProfileID(ICC_Profile profile); public synchronized static native LCMSProfile getProfileID(ICC_Profile profile);
/* Helper method used from LCMSColorTransfrom */
static long createTransform(
LCMSProfile[] profiles, int renderType,
int inFormatter, boolean isInIntPacked,
int outFormatter, boolean isOutIntPacked,
Object disposerRef)
{
long[] ptrs = new long[profiles.length];
for (int i = 0; i < profiles.length; i++) {
if (profiles[i] == null) throw new CMMException("Unknown profile ID");
ptrs[i] = profiles[i].getLcmsPtr();
}
return createNativeTransform(ptrs, renderType, inFormatter,
isInIntPacked, outFormatter, isOutIntPacked, disposerRef);
}
public static native long createNativeTransform( private static native long createNativeTransform(
long[] profileIDs, int renderType, long[] profileIDs, int renderType,
int inFormatter, boolean isInIntPacked, int inFormatter, boolean isInIntPacked,
int outFormatter, boolean isOutIntPacked, int outFormatter, boolean isOutIntPacked,
...@@ -175,59 +218,4 @@ public class LCMS implements PCMM { ...@@ -175,59 +218,4 @@ public class LCMS implements PCMM {
return theLcms; return theLcms;
} }
private static class TagData {
private int signature;
private byte[] data;
TagData(int sig, byte[] data) {
this.signature = sig;
this.data = data;
}
int getSize() {
return data.length;
}
byte[] getData() {
return Arrays.copyOf(data, data.length);
}
void copyDataTo(byte[] dst) {
System.arraycopy(data, 0, dst, 0, data.length);
}
int getSignature() {
return signature;
}
}
private static class TagCache {
private long profileID;
private HashMap<Integer, TagData> tags;
TagCache(long id) {
profileID = id;
tags = new HashMap<>();
}
TagData getTag(int sig) {
TagData t = tags.get(sig);
if (t == null) {
byte[] tagData = getTagNative(profileID, sig);
if (tagData != null) {
t = new TagData(sig, tagData);
tags.put(sig, t);
}
}
return t;
}
void clear() {
tags.clear();
}
}
private static HashMap<Long, TagCache> profiles;
} }
/*
* Copyright (c) 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.java2d.cmm.lcms;
import java.awt.color.CMMException;
import java.util.Arrays;
import java.util.HashMap;
import sun.java2d.cmm.Profile;
final class LCMSProfile extends Profile {
private final TagCache tagCache;
private final Object disposerReferent;
LCMSProfile(long ptr, Object ref) {
super(ptr);
disposerReferent = ref;
tagCache = new TagCache(this);
}
final long getLcmsPtr() {
return this.getNativePtr();
}
TagData getTag(int sig) {
return tagCache.getTag(sig);
}
void clearTagCache() {
tagCache.clear();
}
static class TagCache {
final LCMSProfile profile;
private HashMap<Integer, TagData> tags;
TagCache(LCMSProfile p) {
profile = p;
tags = new HashMap<>();
}
TagData getTag(int sig) {
TagData t = tags.get(sig);
if (t == null) {
byte[] tagData = LCMS.getTagNative(profile.getNativePtr(), sig);
if (tagData != null) {
t = new TagData(sig, tagData);
tags.put(sig, t);
}
}
return t;
}
void clear() {
tags.clear();
}
}
static class TagData {
private int signature;
private byte[] data;
TagData(int sig, byte[] data) {
this.signature = sig;
this.data = data;
}
int getSize() {
return data.length;
}
byte[] getData() {
return Arrays.copyOf(data, data.length);
}
void copyDataTo(byte[] dst) {
System.arraycopy(data, 0, dst, 0, data.length);
}
int getSignature() {
return signature;
}
}
}
...@@ -62,7 +62,7 @@ public class LCMSTransform implements ColorTransform { ...@@ -62,7 +62,7 @@ public class LCMSTransform implements ColorTransform {
private boolean isOutIntPacked = false; private boolean isOutIntPacked = false;
ICC_Profile[] profiles; ICC_Profile[] profiles;
long [] profileIDs; LCMSProfile[] lcmsProfiles;
int renderType; int renderType;
int transformType; int transformType;
...@@ -84,8 +84,8 @@ public class LCMSTransform implements ColorTransform { ...@@ -84,8 +84,8 @@ public class LCMSTransform implements ColorTransform {
/* Actually, it is not a complete transform but just part of it */ /* Actually, it is not a complete transform but just part of it */
profiles = new ICC_Profile[1]; profiles = new ICC_Profile[1];
profiles[0] = profile; profiles[0] = profile;
profileIDs = new long[1]; lcmsProfiles = new LCMSProfile[1];
profileIDs[0] = LCMS.getProfileID(profile); lcmsProfiles[0] = LCMS.getProfileID(profile);
this.renderType = (renderType == ColorTransform.Any)? this.renderType = (renderType == ColorTransform.Any)?
ICC_Profile.icPerceptual : renderType; ICC_Profile.icPerceptual : renderType;
this.transformType = transformType; this.transformType = transformType;
...@@ -105,14 +105,14 @@ public class LCMSTransform implements ColorTransform { ...@@ -105,14 +105,14 @@ public class LCMSTransform implements ColorTransform {
size+=((LCMSTransform)transforms[i]).profiles.length; size+=((LCMSTransform)transforms[i]).profiles.length;
} }
profiles = new ICC_Profile[size]; profiles = new ICC_Profile[size];
profileIDs = new long[size]; lcmsProfiles = new LCMSProfile[size];
int j = 0; int j = 0;
for (int i=0; i < transforms.length; i++) { for (int i=0; i < transforms.length; i++) {
LCMSTransform curTrans = (LCMSTransform)transforms[i]; LCMSTransform curTrans = (LCMSTransform)transforms[i];
System.arraycopy(curTrans.profiles, 0, profiles, j, System.arraycopy(curTrans.profiles, 0, profiles, j,
curTrans.profiles.length); curTrans.profiles.length);
System.arraycopy(curTrans.profileIDs, 0, profileIDs, j, System.arraycopy(curTrans.lcmsProfiles, 0, lcmsProfiles, j,
curTrans.profileIDs.length); curTrans.lcmsProfiles.length);
j += curTrans.profiles.length; j += curTrans.profiles.length;
} }
renderType = ((LCMSTransform)transforms[0]).renderType; renderType = ((LCMSTransform)transforms[0]).renderType;
...@@ -152,7 +152,7 @@ public class LCMSTransform implements ColorTransform { ...@@ -152,7 +152,7 @@ public class LCMSTransform implements ColorTransform {
outFormatter = out.pixelType; outFormatter = out.pixelType;
isOutIntPacked = out.isIntPacked; isOutIntPacked = out.isIntPacked;
ID = LCMS.createNativeTransform(profileIDs, renderType, ID = LCMS.createTransform(lcmsProfiles, renderType,
inFormatter, isInIntPacked, inFormatter, isInIntPacked,
outFormatter, isOutIntPacked, outFormatter, isOutIntPacked,
disposerReferent); disposerReferent);
......
...@@ -94,8 +94,12 @@ cmsInt32Number TransportValue32(cmsInt32Number Value) ...@@ -94,8 +94,12 @@ cmsInt32Number TransportValue32(cmsInt32Number Value)
# endif # endif
#endif #endif
typedef union storeID_s { /* store SProfile stuff in a Java Long */ typedef struct lcmsProfile_s {
cmsHPROFILE pf; cmsHPROFILE pf;
} lcmsProfile_t, *lcmsProfile_p;
typedef union storeID_s { /* store SProfile stuff in a Java Long */
lcmsProfile_p lcmsPf;
cmsHTRANSFORM xf; cmsHTRANSFORM xf;
jobject jobj; jobject jobj;
jlong j; jlong j;
...@@ -106,7 +110,6 @@ typedef union { ...@@ -106,7 +110,6 @@ typedef union {
jint j; jint j;
} TagSignature_t, *TagSignature_p; } TagSignature_t, *TagSignature_p;
static jfieldID Trans_profileIDs_fID;
static jfieldID Trans_renderType_fID; static jfieldID Trans_renderType_fID;
static jfieldID Trans_ID_fID; static jfieldID Trans_ID_fID;
static jfieldID IL_isIntPacked_fID; static jfieldID IL_isIntPacked_fID;
...@@ -118,7 +121,6 @@ static jfieldID IL_nextRowOffset_fID; ...@@ -118,7 +121,6 @@ static jfieldID IL_nextRowOffset_fID;
static jfieldID IL_width_fID; static jfieldID IL_width_fID;
static jfieldID IL_height_fID; static jfieldID IL_height_fID;
static jfieldID IL_imageAtOnce_fID; static jfieldID IL_imageAtOnce_fID;
static jfieldID PF_ID_fID;
JavaVM *javaVM; JavaVM *javaVM;
...@@ -145,6 +147,18 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { ...@@ -145,6 +147,18 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
return JNI_VERSION_1_6; return JNI_VERSION_1_6;
} }
void LCMS_freeProfile(JNIEnv *env, jlong ptr) {
storeID_t sProfile;
sProfile.j = ptr;
if (sProfile.lcmsPf != NULL) {
if (sProfile.lcmsPf->pf != NULL) {
cmsCloseProfile(sProfile.lcmsPf->pf);
}
free(sProfile.lcmsPf);
}
}
void LCMS_freeTransform(JNIEnv *env, jlong ID) void LCMS_freeTransform(JNIEnv *env, jlong ID)
{ {
storeID_t sTrans; storeID_t sTrans;
...@@ -170,7 +184,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform ...@@ -170,7 +184,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
jlong* ids; jlong* ids;
size = (*env)->GetArrayLength (env, profileIDs); size = (*env)->GetArrayLength (env, profileIDs);
ids = (*env)->GetPrimitiveArrayCritical(env, profileIDs, 0); ids = (*env)->GetLongArrayElements(env, profileIDs, 0);
#ifdef _LITTLE_ENDIAN #ifdef _LITTLE_ENDIAN
/* Reversing data packed into int for LE archs */ /* Reversing data packed into int for LE archs */
...@@ -186,6 +200,8 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform ...@@ -186,6 +200,8 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
iccArray = (cmsHPROFILE*) malloc( iccArray = (cmsHPROFILE*) malloc(
size*2*sizeof(cmsHPROFILE)); size*2*sizeof(cmsHPROFILE));
if (iccArray == NULL) { if (iccArray == NULL) {
(*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);
J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL"); J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL");
return 0L; return 0L;
} }
...@@ -197,7 +213,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform ...@@ -197,7 +213,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
cmsColorSpaceSignature cs; cmsColorSpaceSignature cs;
sTrans.j = ids[i]; sTrans.j = ids[i];
icc = sTrans.pf; icc = sTrans.lcmsPf->pf;
iccArray[j++] = icc; iccArray[j++] = icc;
/* Middle non-abstract profiles should be doubled before passing to /* Middle non-abstract profiles should be doubled before passing to
...@@ -215,13 +231,15 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform ...@@ -215,13 +231,15 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
sTrans.xf = cmsCreateMultiprofileTransform(iccArray, j, sTrans.xf = cmsCreateMultiprofileTransform(iccArray, j,
inFormatter, outFormatter, renderType, 0); inFormatter, outFormatter, renderType, 0);
(*env)->ReleasePrimitiveArrayCritical(env, profileIDs, ids, 0); (*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);
if (sTrans.xf == NULL) { if (sTrans.xf == NULL) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_createNativeTransform: " J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_createNativeTransform: "
"sTrans.xf == NULL"); "sTrans.xf == NULL");
if ((*env)->ExceptionOccurred(env) == NULL) {
JNU_ThrowByName(env, "java/awt/color/CMMException", JNU_ThrowByName(env, "java/awt/color/CMMException",
"Cannot get color transform"); "Cannot get color transform");
}
} else { } else {
Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j); Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j);
} }
...@@ -236,20 +254,23 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform ...@@ -236,20 +254,23 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
/* /*
* Class: sun_java2d_cmm_lcms_LCMS * Class: sun_java2d_cmm_lcms_LCMS
* Method: loadProfile * Method: loadProfile
* Signature: ([B)J * Signature: ([B,Lsun/java2d/cmm/lcms/LCMSProfile;)V
*/ */
JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative
(JNIEnv *env, jobject obj, jbyteArray data) (JNIEnv *env, jobject obj, jbyteArray data, jobject disposerRef)
{ {
jbyte* dataArray; jbyte* dataArray;
jint dataSize; jint dataSize;
storeID_t sProf; storeID_t sProf;
cmsHPROFILE pf;
if (JNU_IsNull(env, data)) { if (JNU_IsNull(env, data)) {
JNU_ThrowIllegalArgumentException(env, "Invalid profile data"); JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
return 0L; return 0L;
} }
sProf.j = 0L;
dataArray = (*env)->GetByteArrayElements (env, data, 0); dataArray = (*env)->GetByteArrayElements (env, data, 0);
dataSize = (*env)->GetArrayLength (env, data); dataSize = (*env)->GetArrayLength (env, data);
...@@ -258,61 +279,56 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative ...@@ -258,61 +279,56 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative
return 0L; return 0L;
} }
sProf.pf = cmsOpenProfileFromMem((const void *)dataArray, pf = cmsOpenProfileFromMem((const void *)dataArray,
(cmsUInt32Number) dataSize); (cmsUInt32Number) dataSize);
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
if (sProf.pf == NULL) { if (pf == NULL) {
JNU_ThrowIllegalArgumentException(env, "Invalid profile data"); JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
} else { } else {
/* Sanity check: try to save the profile in order /* Sanity check: try to save the profile in order
* to force basic validation. * to force basic validation.
*/ */
cmsUInt32Number pfSize = 0; cmsUInt32Number pfSize = 0;
if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize) || if (!cmsSaveProfileToMem(pf, NULL, &pfSize) ||
pfSize < sizeof(cmsICCHeader)) pfSize < sizeof(cmsICCHeader))
{ {
JNU_ThrowIllegalArgumentException(env, "Invalid profile data"); JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
cmsCloseProfile(pf);
pf = NULL;
} }
} }
return sProf.j; if (pf != NULL) {
} // create profile holder
sProf.lcmsPf = (lcmsProfile_p)malloc(sizeof(lcmsProfile_t));
/* if (sProf.lcmsPf != NULL) {
* Class: sun_java2d_cmm_lcms_LCMS // register the disposer record
* Method: freeProfile sProf.lcmsPf->pf = pf;
* Signature: (J)V Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sProf.j);
*/ } else {
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative cmsCloseProfile(pf);
(JNIEnv *env, jobject obj, jlong id) }
{
storeID_t sProf;
sProf.j = id;
if (cmsCloseProfile(sProf.pf) == 0) {
J2dRlsTraceLn1(J2D_TRACE_ERROR, "LCMS_freeProfile: cmsCloseProfile(%d)"
"== 0", id);
JNU_ThrowByName(env, "java/awt/color/CMMException",
"Cannot close profile");
} }
return sProf.j;
} }
/* /*
* Class: sun_java2d_cmm_lcms_LCMS * Class: sun_java2d_cmm_lcms_LCMS
* Method: getProfileSize * Method: getProfileSizeNative
* Signature: (J)I * Signature: (J)I
*/ */
JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSize JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative
(JNIEnv *env, jobject obj, jlong id) (JNIEnv *env, jobject obj, jlong id)
{ {
storeID_t sProf; storeID_t sProf;
cmsUInt32Number pfSize = 0; cmsUInt32Number pfSize = 0;
sProf.j = id; sProf.j = id;
if (cmsSaveProfileToMem(sProf.pf, NULL, &pfSize) && ((jint)pfSize > 0)) { if (cmsSaveProfileToMem(sProf.lcmsPf->pf, NULL, &pfSize) && ((jint)pfSize > 0)) {
return (jint)pfSize; return (jint)pfSize;
} else { } else {
JNU_ThrowByName(env, "java/awt/color/CMMException", JNU_ThrowByName(env, "java/awt/color/CMMException",
...@@ -323,10 +339,10 @@ JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSize ...@@ -323,10 +339,10 @@ JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSize
/* /*
* Class: sun_java2d_cmm_lcms_LCMS * Class: sun_java2d_cmm_lcms_LCMS
* Method: getProfileData * Method: getProfileDataNative
* Signature: (J[B)V * Signature: (J[B)V
*/ */
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative
(JNIEnv *env, jobject obj, jlong id, jbyteArray data) (JNIEnv *env, jobject obj, jlong id, jbyteArray data)
{ {
storeID_t sProf; storeID_t sProf;
...@@ -338,7 +354,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData ...@@ -338,7 +354,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
sProf.j = id; sProf.j = id;
// determine actual profile size // determine actual profile size
if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize)) { if (!cmsSaveProfileToMem(sProf.lcmsPf->pf, NULL, &pfSize)) {
JNU_ThrowByName(env, "java/awt/color/CMMException", JNU_ThrowByName(env, "java/awt/color/CMMException",
"Can not access specified profile."); "Can not access specified profile.");
return; return;
...@@ -354,7 +370,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData ...@@ -354,7 +370,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
dataArray = (*env)->GetByteArrayElements (env, data, 0); dataArray = (*env)->GetByteArrayElements (env, data, 0);
status = cmsSaveProfileToMem(sProf.pf, dataArray, &pfSize); status = cmsSaveProfileToMem(sProf.lcmsPf->pf, dataArray, &pfSize);
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
...@@ -368,7 +384,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData ...@@ -368,7 +384,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
/* Get profile header info */ /* Get profile header info */
static cmsBool _getHeaderInfo(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 _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size); static cmsHPROFILE _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size);
/* /*
...@@ -412,7 +428,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative ...@@ -412,7 +428,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative
return NULL; return NULL;
} }
status = _getHeaderInfo(sProf.pf, dataArray, bufSize); status = _getHeaderInfo(sProf.lcmsPf->pf, dataArray, bufSize);
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
...@@ -425,8 +441,8 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative ...@@ -425,8 +441,8 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative
return data; return data;
} }
if (cmsIsTag(sProf.pf, sig.cms)) { if (cmsIsTag(sProf.lcmsPf->pf, sig.cms)) {
tagSize = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0); tagSize = cmsReadRawTag(sProf.lcmsPf->pf, sig.cms, NULL, 0);
} else { } else {
JNU_ThrowByName(env, "java/awt/color/CMMException", JNU_ThrowByName(env, "java/awt/color/CMMException",
"ICC profile tag not found"); "ICC profile tag not found");
...@@ -449,7 +465,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative ...@@ -449,7 +465,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative
return NULL; return NULL;
} }
bufSize = cmsReadRawTag(sProf.pf, sig.cms, dataArray, tagSize); bufSize = cmsReadRawTag(sProf.lcmsPf->pf, sig.cms, dataArray, tagSize);
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
...@@ -470,8 +486,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative ...@@ -470,8 +486,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative
(JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
{ {
storeID_t sProf; storeID_t sProf;
cmsHPROFILE pfReplace = NULL;
TagSignature_t sig; TagSignature_t sig;
cmsBool status; cmsBool status = FALSE;
jbyte* dataArray; jbyte* dataArray;
int tagSize; int tagSize;
...@@ -493,15 +511,24 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative ...@@ -493,15 +511,24 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative
} }
if (tagSig == SigHead) { if (tagSig == SigHead) {
status = _setHeaderInfo(sProf.pf, dataArray, tagSize); status = _setHeaderInfo(sProf.lcmsPf->pf, dataArray, tagSize);
} else { } else {
status = _writeCookedTag(sProf.pf, sig.cms, dataArray, tagSize); /*
* New strategy for generic tags: create a place holder,
* dump all existing tags there, dump externally supplied
* tag, and return the new profile to the java.
*/
pfReplace = _writeCookedTag(sProf.lcmsPf->pf, sig.cms, dataArray, tagSize);
status = (pfReplace != NULL);
} }
(*env)->ReleaseByteArrayElements(env, data, dataArray, 0); (*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
if (!status) { if (!status) {
JNU_ThrowIllegalArgumentException(env, "Can not write tag data."); JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
} else if (pfReplace != NULL) {
cmsCloseProfile(sProf.lcmsPf->pf);
sProf.lcmsPf->pf = pfReplace;
} }
} }
...@@ -624,12 +651,27 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert ...@@ -624,12 +651,27 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert
/* /*
* Class: sun_java2d_cmm_lcms_LCMS * Class: sun_java2d_cmm_lcms_LCMS
* Method: getProfileID * Method: getProfileID
* Signature: (Ljava/awt/color/ICC_Profile;)J * Signature: (Ljava/awt/color/ICC_Profile;)Lsun/java2d/cmm/lcms/LCMSProfile
*/ */
JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileID JNIEXPORT jobject JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileID
(JNIEnv *env, jclass cls, jobject pf) (JNIEnv *env, jclass cls, jobject pf)
{ {
return (*env)->GetLongField (env, pf, PF_ID_fID); jfieldID fid = (*env)->GetFieldID (env,
(*env)->GetObjectClass(env, pf),
"cmmProfile", "Lsun/java2d/cmm/Profile;");
jclass clsLcmsProfile = (*env)->FindClass(env,
"sun/java2d/cmm/lcms/LCMSProfile");
jobject cmmProfile = (*env)->GetObjectField (env, pf, fid);
if (JNU_IsNull(env, cmmProfile)) {
return NULL;
}
if ((*env)->IsInstanceOf(env, cmmProfile, clsLcmsProfile)) {
return cmmProfile;
}
return NULL;
} }
/* /*
...@@ -644,7 +686,6 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS ...@@ -644,7 +686,6 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS
* corresponding classes to avoid problems with invalidating ids by class * corresponding classes to avoid problems with invalidating ids by class
* unloading * unloading
*/ */
Trans_profileIDs_fID = (*env)->GetFieldID (env, Trans, "profileIDs", "[J");
Trans_renderType_fID = (*env)->GetFieldID (env, Trans, "renderType", "I"); Trans_renderType_fID = (*env)->GetFieldID (env, Trans, "renderType", "I");
Trans_ID_fID = (*env)->GetFieldID (env, Trans, "ID", "J"); Trans_ID_fID = (*env)->GetFieldID (env, Trans, "ID", "J");
...@@ -658,8 +699,6 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS ...@@ -658,8 +699,6 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS
IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I"); IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I");
IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z"); IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z");
IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I"); IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I");
PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
} }
static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize) static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
...@@ -714,19 +753,27 @@ static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize) ...@@ -714,19 +753,27 @@ static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
return TRUE; return TRUE;
} }
static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, /* Returns new profile handler, if it was created successfully,
cmsTagSignature sig, NULL otherwise.
*/
static cmsHPROFILE _writeCookedTag(const cmsHPROFILE pfTarget,
const cmsTagSignature sig,
jbyte *pData, jint size) jbyte *pData, jint size)
{ {
cmsBool status;
cmsUInt32Number pfSize = 0; cmsUInt32Number pfSize = 0;
cmsUInt8Number* pfBuffer = NULL; const cmsInt32Number tagCount = cmsGetTagCount(pfTarget);
cmsInt32Number i;
cmsHPROFILE pfSanity = NULL;
cmsHPROFILE p = cmsCreateProfilePlaceholder(NULL);
if (NULL != p) {
cmsICCHeader hdr = { 0 }; cmsICCHeader hdr = { 0 };
/* Populate the placeholder's header according to target profile */ cmsHPROFILE p = cmsCreateProfilePlaceholder(NULL);
if (NULL == p) {
return NULL;
}
// Populate the placeholder's header according to target profile
hdr.flags = cmsGetHeaderFlags(pfTarget); hdr.flags = cmsGetHeaderFlags(pfTarget);
hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget); hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget);
hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget); hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget);
...@@ -749,41 +796,71 @@ static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, ...@@ -749,41 +796,71 @@ static cmsBool _writeCookedTag(cmsHPROFILE pfTarget,
cmsSetDeviceClass(p, hdr.deviceClass); cmsSetDeviceClass(p, hdr.deviceClass);
cmsSetEncodedICCversion(p, hdr.version); cmsSetEncodedICCversion(p, hdr.version);
// now write the user supplied tag
if (size <= 0 || !cmsWriteRawTag(p, sig, pData, size)) {
cmsCloseProfile(p);
return NULL;
}
if (cmsWriteRawTag(p, sig, pData, size)) { // copy tags from the original profile
if (cmsSaveProfileToMem(p, NULL, &pfSize)) { for (i = 0; i < tagCount; i++) {
pfBuffer = malloc(pfSize); cmsBool isTagReady = FALSE;
if (pfBuffer != NULL) { const cmsTagSignature s = cmsGetTagSignature(pfTarget, i);
/* load raw profile data into the buffer */ const cmsInt32Number tagSize = cmsReadRawTag(pfTarget, s, NULL, 0);
if (!cmsSaveProfileToMem(p, pfBuffer, &pfSize)) {
free(pfBuffer); if (s == sig) {
pfBuffer = NULL; // skip the user supplied tag
continue;
} }
// read raw tag from the original profile
if (tagSize > 0) {
cmsUInt8Number* buf = (cmsUInt8Number*)malloc(tagSize);
if (buf != NULL) {
if (tagSize == cmsReadRawTag(pfTarget, s, buf, tagSize)) {
// now we are ready to write the tag
isTagReady = cmsWriteRawTag(p, s, buf, tagSize);
} }
free(buf);
} }
} }
if (!isTagReady) {
cmsCloseProfile(p); cmsCloseProfile(p);
return NULL;
} }
if (pfBuffer == NULL) {
return FALSE;
} }
/* re-open the placeholder profile */ // now we have all tags moved to the new profile.
p = cmsOpenProfileFromMem(pfBuffer, pfSize); // do some sanity checks: write it to a memory buffer and read again.
free(pfBuffer); if (cmsSaveProfileToMem(p, NULL, &pfSize)) {
status = FALSE; void* buf = malloc(pfSize);
if (buf != NULL) {
if (p != NULL) { // load raw profile data into the buffer
/* Note that pCookedTag points to internal structures of the placeholder, if (cmsSaveProfileToMem(p, buf, &pfSize)) {
* so this data is valid only while the placeholder is open. pfSanity = cmsOpenProfileFromMem(buf, pfSize);
*/ }
void *pCookedTag = cmsReadTag(p, sig); free(buf);
if (pCookedTag != NULL) { }
status = cmsWriteTag(pfTarget, sig, pCookedTag);
} }
pCookedTag = NULL;
if (pfSanity == NULL) {
// for some reason, we failed to save and read the updated profile
// It likely indicates that the profile is not correct, so we report
// a failure here.
cmsCloseProfile(p); cmsCloseProfile(p);
p = NULL;
} else {
// do final check whether we can read and handle the the target tag.
const void* pTag = cmsReadTag(pfSanity, sig);
if (pTag == NULL) {
// the tag can not be cooked
cmsCloseProfile(p);
p = NULL;
} }
return status; cmsCloseProfile(pfSanity);
pfSanity = NULL;
}
return p;
} }
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/** /**
* @test * @test
* @bug 6476665 6523403 6733501 7042594 * @bug 6476665 6523403 6733501 7042594 7043064
* @summary Verifies reading and writing profiles and tags of the standard color * @summary Verifies reading and writing profiles and tags of the standard color
* spaces * spaces
* @run main ReadWriteProfileTest * @run main ReadWriteProfileTest
...@@ -82,6 +82,7 @@ public class ReadWriteProfileTest implements Runnable { ...@@ -82,6 +82,7 @@ public class ReadWriteProfileTest implements Runnable {
public void run() { public void run() {
for (int i = 0; i < cspaces.length; i++) { for (int i = 0; i < cspaces.length; i++) {
System.out.println("Profile: " + csNames[i]);
ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]); ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
byte [] data = pf.getData(); byte [] data = pf.getData();
pf = ICC_Profile.getInstance(data); pf = ICC_Profile.getInstance(data);
...@@ -92,6 +93,10 @@ public class ReadWriteProfileTest implements Runnable { ...@@ -92,6 +93,10 @@ public class ReadWriteProfileTest implements Runnable {
} }
for (int tagSig : tags[i].keySet()) { for (int tagSig : tags[i].keySet()) {
String signature = SigToString(tagSig);
System.out.printf("Tag: %s\n", signature);
System.out.flush();
byte [] tagData = pf.getData(tagSig); byte [] tagData = pf.getData(tagSig);
byte [] empty = new byte[tagData.length]; byte [] empty = new byte[tagData.length];
boolean emptyDataRejected = false; boolean emptyDataRejected = false;
...@@ -104,15 +109,23 @@ public class ReadWriteProfileTest implements Runnable { ...@@ -104,15 +109,23 @@ public class ReadWriteProfileTest implements Runnable {
throw new throw new
RuntimeException("Test failed: empty tag data was not rejected."); RuntimeException("Test failed: empty tag data was not rejected.");
} }
try {
pf.setData(tagSig, tagData); pf.setData(tagSig, tagData);
} catch (IllegalArgumentException e) {
// let's ignore this exception for Kodak proprietary tags
if (isKodakExtention(signature)) {
System.out.println("Ignore Kodak tag: " + signature);
} else {
throw new RuntimeException("Test failed!", e);
}
}
byte [] tagData1 = pf.getData(tagSig); byte [] tagData1 = pf.getData(tagSig);
if (!Arrays.equals(tagData1, tags[i].get(tagSig))) if (!Arrays.equals(tagData1, tags[i].get(tagSig)))
{ {
System.err.println("Incorrect result of getData(int) with" + System.err.println("Incorrect result of getData(int) with" +
" tag " + " tag " +
Integer.toHexString(tagSig) + SigToString(tagSig) +
" of " + csNames[i] + " profile"); " of " + csNames[i] + " profile");
throw new RuntimeException("Incorrect result of " + throw new RuntimeException("Incorrect result of " +
...@@ -122,6 +135,19 @@ public class ReadWriteProfileTest implements Runnable { ...@@ -122,6 +135,19 @@ public class ReadWriteProfileTest implements Runnable {
} }
} }
private static boolean isKodakExtention(String signature) {
return signature.matches("K\\d\\d\\d");
}
private static String SigToString(int tagSig ) {
return String.format("%c%c%c%c",
(char)(0xff & (tagSig >> 24)),
(char)(0xff & (tagSig >> 16)),
(char)(0xff & (tagSig >> 8)),
(char)(0xff & (tagSig)));
}
public static void main(String [] args) { public static void main(String [] args) {
ReadWriteProfileTest test = new ReadWriteProfileTest(); ReadWriteProfileTest test = new ReadWriteProfileTest();
test.run(); test.run();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册