7043064: sun/java2d/cmm/ tests failed against RI b141 & b138-nightly
Reviewed-by: prr, vadim
This commit is contained in:
parent
24f306c761
commit
256894796f
@ -28,9 +28,8 @@
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getProfileSize;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getProfileData;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getTagNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_colorConvert;
|
||||
|
@ -28,9 +28,8 @@
|
||||
SUNWprivate_1.1 {
|
||||
global:
|
||||
Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getProfileSize;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getProfileData;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_getTagNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative;
|
||||
Java_sun_java2d_cmm_lcms_LCMS_colorConvert;
|
||||
|
@ -37,6 +37,7 @@ package java.awt.color;
|
||||
|
||||
import sun.java2d.cmm.PCMM;
|
||||
import sun.java2d.cmm.CMSManager;
|
||||
import sun.java2d.cmm.Profile;
|
||||
import sun.java2d.cmm.ProfileDataVerifier;
|
||||
import sun.java2d.cmm.ProfileDeferralMgr;
|
||||
import sun.java2d.cmm.ProfileDeferralInfo;
|
||||
@ -94,7 +95,7 @@ public class ICC_Profile implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3938515861990936766L;
|
||||
|
||||
transient long ID;
|
||||
private transient Profile cmmProfile;
|
||||
|
||||
private transient ProfileDeferralInfo deferralInfo;
|
||||
private transient ProfileActivator profileActivator;
|
||||
@ -727,8 +728,8 @@ public class ICC_Profile implements Serializable {
|
||||
/**
|
||||
* Constructs an ICC_Profile object with a given ID.
|
||||
*/
|
||||
ICC_Profile(long ID) {
|
||||
this.ID = ID;
|
||||
ICC_Profile(Profile p) {
|
||||
this.cmmProfile = p;
|
||||
}
|
||||
|
||||
|
||||
@ -751,8 +752,8 @@ public class ICC_Profile implements Serializable {
|
||||
* Frees the resources associated with an ICC_Profile object.
|
||||
*/
|
||||
protected void finalize () {
|
||||
if (ID != 0) {
|
||||
CMSManager.getModule().freeProfile(ID);
|
||||
if (cmmProfile != null) {
|
||||
CMSManager.getModule().freeProfile(cmmProfile);
|
||||
} else if (profileActivator != null) {
|
||||
ProfileDeferralMgr.unregisterDeferral(profileActivator);
|
||||
}
|
||||
@ -770,7 +771,7 @@ public class ICC_Profile implements Serializable {
|
||||
public static ICC_Profile getInstance(byte[] data) {
|
||||
ICC_Profile thisProfile;
|
||||
|
||||
long theID;
|
||||
Profile p = null;
|
||||
|
||||
if (ProfileDeferralMgr.deferring) {
|
||||
ProfileDeferralMgr.activateProfiles();
|
||||
@ -779,32 +780,32 @@ public class ICC_Profile implements Serializable {
|
||||
ProfileDataVerifier.verify(data);
|
||||
|
||||
try {
|
||||
theID = CMSManager.getModule().loadProfile(data);
|
||||
p = 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);
|
||||
if ((getColorSpaceType (p) == ColorSpace.TYPE_GRAY) &&
|
||||
(getData (p, icSigMediaWhitePointTag) != null) &&
|
||||
(getData (p, icSigGrayTRCTag) != null)) {
|
||||
thisProfile = new ICC_ProfileGray (p);
|
||||
}
|
||||
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 if ((getColorSpaceType (p) == ColorSpace.TYPE_RGB) &&
|
||||
(getData (p, icSigMediaWhitePointTag) != null) &&
|
||||
(getData (p, icSigRedColorantTag) != null) &&
|
||||
(getData (p, icSigGreenColorantTag) != null) &&
|
||||
(getData (p, icSigBlueColorantTag) != null) &&
|
||||
(getData (p, icSigRedTRCTag) != null) &&
|
||||
(getData (p, icSigGreenTRCTag) != null) &&
|
||||
(getData (p, icSigBlueTRCTag) != null)) {
|
||||
thisProfile = new ICC_ProfileRGB (p);
|
||||
}
|
||||
else {
|
||||
thisProfile = new ICC_Profile (theID);
|
||||
thisProfile = new ICC_Profile (p);
|
||||
}
|
||||
} catch (CMMException c) {
|
||||
thisProfile = new ICC_Profile (theID);
|
||||
thisProfile = new ICC_Profile (p);
|
||||
}
|
||||
return thisProfile;
|
||||
}
|
||||
@ -1119,7 +1120,7 @@ public class ICC_Profile implements Serializable {
|
||||
fileName);
|
||||
}
|
||||
try {
|
||||
ID = CMSManager.getModule().loadProfile(profileData);
|
||||
cmmProfile = CMSManager.getModule().loadProfile(profileData);
|
||||
} catch (CMMException c) {
|
||||
ProfileDataException pde = new
|
||||
ProfileDataException("Invalid ICC Profile Data" + fileName);
|
||||
@ -1229,14 +1230,14 @@ public class ICC_Profile implements Serializable {
|
||||
causing a deferred profile
|
||||
to be loaded */
|
||||
}
|
||||
return getColorSpaceType(ID);
|
||||
return getColorSpaceType(cmmProfile);
|
||||
}
|
||||
|
||||
static int getColorSpaceType(long profileID) {
|
||||
static int getColorSpaceType(Profile p) {
|
||||
byte[] theHeader;
|
||||
int theColorSpaceSig, theColorSpace;
|
||||
|
||||
theHeader = getData(profileID, icSigHead);
|
||||
theHeader = getData(p, icSigHead);
|
||||
theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
|
||||
theColorSpace = iccCStoJCS (theColorSpaceSig);
|
||||
return theColorSpace;
|
||||
@ -1258,15 +1259,15 @@ public class ICC_Profile implements Serializable {
|
||||
if (ProfileDeferralMgr.deferring) {
|
||||
ProfileDeferralMgr.activateProfiles();
|
||||
}
|
||||
return getPCSType(ID);
|
||||
return getPCSType(cmmProfile);
|
||||
}
|
||||
|
||||
|
||||
static int getPCSType(long profileID) {
|
||||
static int getPCSType(Profile p) {
|
||||
byte[] theHeader;
|
||||
int thePCSSig, thePCS;
|
||||
|
||||
theHeader = getData(profileID, icSigHead);
|
||||
theHeader = getData(p, icSigHead);
|
||||
thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
|
||||
thePCS = iccCStoJCS(thePCSSig);
|
||||
return thePCS;
|
||||
@ -1326,12 +1327,12 @@ public class ICC_Profile implements Serializable {
|
||||
PCMM mdl = CMSManager.getModule();
|
||||
|
||||
/* get the number of bytes needed for this profile */
|
||||
profileSize = mdl.getProfileSize(ID);
|
||||
profileSize = mdl.getProfileSize(cmmProfile);
|
||||
|
||||
profileData = new byte [profileSize];
|
||||
|
||||
/* get the data for the profile */
|
||||
mdl.getProfileData(ID, profileData);
|
||||
mdl.getProfileData(cmmProfile, profileData);
|
||||
|
||||
return profileData;
|
||||
}
|
||||
@ -1358,11 +1359,11 @@ public class ICC_Profile implements Serializable {
|
||||
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;
|
||||
byte[] tagData;
|
||||
|
||||
@ -1370,12 +1371,12 @@ public class ICC_Profile implements Serializable {
|
||||
PCMM mdl = CMSManager.getModule();
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* get the tag's data */
|
||||
mdl.getTagData(profileID, tagSignature, tagData);
|
||||
mdl.getTagData(p, tagSignature, tagData);
|
||||
} catch(CMMException c) {
|
||||
tagData = null;
|
||||
}
|
||||
@ -1406,7 +1407,7 @@ public class ICC_Profile implements Serializable {
|
||||
ProfileDeferralMgr.activateProfiles();
|
||||
}
|
||||
|
||||
CMSManager.getModule().setTagData(ID, tagSignature, tagData);
|
||||
CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
package java.awt.color;
|
||||
|
||||
import java.awt.image.LookupTable;
|
||||
import sun.java2d.cmm.Profile;
|
||||
import sun.java2d.cmm.ProfileDeferralInfo;
|
||||
|
||||
/**
|
||||
@ -76,8 +76,8 @@ extends ICC_Profile {
|
||||
/**
|
||||
* Constructs a new ICC_ProfileGray from a CMM ID.
|
||||
*/
|
||||
ICC_ProfileGray(long ID) {
|
||||
super(ID);
|
||||
ICC_ProfileGray(Profile p) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
package java.awt.color;
|
||||
|
||||
import java.awt.image.LookupTable;
|
||||
import sun.java2d.cmm.Profile;
|
||||
import sun.java2d.cmm.ProfileDeferralInfo;
|
||||
|
||||
/**
|
||||
@ -114,8 +114,8 @@ extends ICC_Profile {
|
||||
* @param ID The CMM ID for the profile.
|
||||
*
|
||||
*/
|
||||
ICC_ProfileRGB(long ID) {
|
||||
super(ID);
|
||||
ICC_ProfileRGB(Profile p) {
|
||||
super(p);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,53 +104,53 @@ public class CMSManager {
|
||||
cName = tcmm.getClass().getName();
|
||||
}
|
||||
|
||||
public long loadProfile(byte[] data) {
|
||||
public Profile loadProfile(byte[] data) {
|
||||
System.err.print(cName + ".loadProfile");
|
||||
long profileID = tcmm.loadProfile(data);
|
||||
System.err.printf("(ID=%x)\n", profileID);
|
||||
return profileID;
|
||||
Profile p = tcmm.loadProfile(data);
|
||||
System.err.printf("(ID=%s)\n", p.toString());
|
||||
return p;
|
||||
}
|
||||
|
||||
public void freeProfile(long profileID) {
|
||||
System.err.printf(cName + ".freeProfile(ID=%x)\n", profileID);
|
||||
tcmm.freeProfile(profileID);
|
||||
public void freeProfile(Profile p) {
|
||||
System.err.printf(cName + ".freeProfile(ID=%s)\n", p.toString());
|
||||
tcmm.freeProfile(p);
|
||||
}
|
||||
|
||||
public int getProfileSize(long profileID) {
|
||||
System.err.print(cName + ".getProfileSize(ID=" + profileID + ")");
|
||||
int size = tcmm.getProfileSize(profileID);
|
||||
public int getProfileSize(Profile p) {
|
||||
System.err.print(cName + ".getProfileSize(ID=" + p + ")");
|
||||
int size = tcmm.getProfileSize(p);
|
||||
System.err.println("=" + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
public void getProfileData(long profileID, byte[] data) {
|
||||
System.err.print(cName + ".getProfileData(ID=" + profileID + ") ");
|
||||
public void getProfileData(Profile p, byte[] data) {
|
||||
System.err.print(cName + ".getProfileData(ID=" + p + ") ");
|
||||
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)",
|
||||
profileID, signatureToString(tagSignature));
|
||||
int size = tcmm.getTagSize(profileID, tagSignature);
|
||||
p, signatureToString(tagSignature));
|
||||
int size = tcmm.getTagSize(p, tagSignature);
|
||||
System.err.println("=" + size);
|
||||
return size;
|
||||
}
|
||||
|
||||
public void getTagData(long profileID, int tagSignature,
|
||||
public void getTagData(Profile p, int tagSignature,
|
||||
byte[] data) {
|
||||
System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)",
|
||||
profileID, signatureToString(tagSignature));
|
||||
p, signatureToString(tagSignature));
|
||||
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) {
|
||||
System.err.print(cName + ".setTagData(ID=" + profileID +
|
||||
System.err.print(cName + ".setTagData(ID=" + p +
|
||||
", TagSig=" + tagSignature + ")");
|
||||
System.err.println(" sending " + data.length + " byte(s)");
|
||||
tcmm.setTagData(profileID, tagSignature, data);
|
||||
tcmm.setTagData(p, tagSignature, data);
|
||||
}
|
||||
|
||||
/* methods for creating ColorTransforms */
|
||||
|
@ -32,13 +32,13 @@ import java.awt.color.ICC_Profile;
|
||||
public interface PCMM {
|
||||
|
||||
/* methods invoked from ICC_Profile */
|
||||
public long loadProfile(byte[] data);
|
||||
public void freeProfile(long profileID);
|
||||
public int getProfileSize(long profileID);
|
||||
public void getProfileData(long profileID, byte[] data);
|
||||
public void getTagData(long profileID, int tagSignature, byte[] data);
|
||||
public int getTagSize(long profileID, int tagSignature);
|
||||
public void setTagData(long profileID, int tagSignature, byte[] data);
|
||||
public Profile loadProfile(byte[] data);
|
||||
public void freeProfile(Profile p);
|
||||
public int getProfileSize(Profile p);
|
||||
public void getProfileData(Profile p, byte[] data);
|
||||
public void getTagData(Profile p, int tagSignature, byte[] data);
|
||||
public int getTagSize(Profile p, int tagSignature);
|
||||
public void setTagData(Profile p, int tagSignature, byte[] data);
|
||||
|
||||
/* methods for creating ColorTransforms */
|
||||
public ColorTransform createTransform(ICC_Profile profile, int renderType,
|
||||
|
43
jdk/src/share/classes/sun/java2d/cmm/Profile.java
Normal file
43
jdk/src/share/classes/sun/java2d/cmm/Profile.java
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 @@
|
||||
|
||||
package sun.java2d.cmm.lcms;
|
||||
|
||||
import java.awt.color.CMMException;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import sun.java2d.cmm.ColorTransform;
|
||||
import sun.java2d.cmm.PCMM;
|
||||
import sun.java2d.cmm.Profile;
|
||||
import sun.java2d.cmm.lcms.LCMSProfile.TagData;
|
||||
|
||||
public class LCMS implements PCMM {
|
||||
|
||||
/* methods invoked from ICC_Profile */
|
||||
@Override
|
||||
public long loadProfile(byte[] data) {
|
||||
long id = loadProfileNative(data);
|
||||
public Profile loadProfile(byte[] data) {
|
||||
final Object disposerRef = new Object();
|
||||
|
||||
if (id != 0L) {
|
||||
if (profiles == null) {
|
||||
profiles = new HashMap<>();
|
||||
}
|
||||
profiles.put(id, new TagCache(id));
|
||||
final long ptr = loadProfileNative(data, disposerRef);
|
||||
|
||||
if (ptr != 0L) {
|
||||
return new LCMSProfile(ptr, disposerRef);
|
||||
}
|
||||
return id;
|
||||
return null;
|
||||
}
|
||||
|
||||
private native long loadProfileNative(byte[] data);
|
||||
private native long loadProfileNative(byte[] data, Object ref);
|
||||
|
||||
@Override
|
||||
public void freeProfile(long profileID) {
|
||||
TagCache c = profiles.remove(profileID);
|
||||
if (c != null) {
|
||||
c.clear();
|
||||
private LCMSProfile getLcmsProfile(Profile p) {
|
||||
if (p instanceof LCMSProfile) {
|
||||
return (LCMSProfile)p;
|
||||
}
|
||||
if (profiles.isEmpty()) {
|
||||
profiles = null;
|
||||
}
|
||||
freeProfileNative(profileID);
|
||||
throw new CMMException("Invalid profile: " + p);
|
||||
}
|
||||
|
||||
private native void freeProfileNative(long profileID);
|
||||
|
||||
public native synchronized int getProfileSize(long profileID);
|
||||
|
||||
public native synchronized void getProfileData(long profileID, byte[] data);
|
||||
|
||||
@Override
|
||||
public synchronized int getTagSize(long profileID, int tagSignature) {
|
||||
TagCache cache = profiles.get(profileID);
|
||||
|
||||
if (cache == null) {
|
||||
cache = new TagCache(profileID);
|
||||
profiles.put(profileID, cache);
|
||||
}
|
||||
|
||||
TagData t = cache.getTag(tagSignature);
|
||||
return t == null ? 0 : t.getSize();
|
||||
public void freeProfile(Profile p) {
|
||||
// we use disposer, so this method does nothing
|
||||
}
|
||||
|
||||
private static native byte[] getTagNative(long profileID, int signature);
|
||||
@Override
|
||||
public int getProfileSize(final Profile p) {
|
||||
synchronized (p) {
|
||||
return getProfileSizeNative(getLcmsProfile(p).getLcmsPtr());
|
||||
}
|
||||
}
|
||||
|
||||
private native int getProfileSizeNative(long ptr);
|
||||
|
||||
@Override
|
||||
public synchronized void getTagData(long profileID, int tagSignature,
|
||||
byte[] data)
|
||||
public void getProfileData(final Profile p, byte[] data) {
|
||||
synchronized (p) {
|
||||
getProfileDataNative(getLcmsProfile(p).getLcmsPtr(), data);
|
||||
}
|
||||
}
|
||||
|
||||
private native void getProfileDataNative(long ptr, byte[] data);
|
||||
|
||||
@Override
|
||||
public int getTagSize(Profile p, int tagSignature) {
|
||||
final LCMSProfile profile = getLcmsProfile(p);
|
||||
|
||||
synchronized (profile) {
|
||||
TagData t = profile.getTag(tagSignature);
|
||||
return t == null ? 0 : t.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
static native byte[] getTagNative(long profileID, int signature);
|
||||
|
||||
@Override
|
||||
public void getTagData(Profile p, int tagSignature, byte[] data)
|
||||
{
|
||||
TagCache cache = profiles.get(profileID);
|
||||
final LCMSProfile profile = getLcmsProfile(p);
|
||||
|
||||
if (cache == null) {
|
||||
cache = new TagCache(profileID);
|
||||
profiles.put(profileID, cache);
|
||||
}
|
||||
|
||||
TagData t = cache.getTag(tagSignature);
|
||||
if (t != null) {
|
||||
t.copyDataTo(data);
|
||||
synchronized (profile) {
|
||||
TagData t = profile.getTag(tagSignature);
|
||||
if (t != null) {
|
||||
t.copyDataTo(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setTagData(long profileID, int tagSignature, byte[] data) {
|
||||
TagCache cache = profiles.get(profileID);
|
||||
public synchronized void setTagData(Profile p, int tagSignature, byte[] data) {
|
||||
final LCMSProfile profile = getLcmsProfile(p);
|
||||
|
||||
if (cache != null) {
|
||||
cache.clear();
|
||||
synchronized (profile) {
|
||||
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);
|
||||
|
||||
public static native long getProfileID(ICC_Profile profile);
|
||||
public synchronized static native LCMSProfile getProfileID(ICC_Profile profile);
|
||||
|
||||
public static native long createNativeTransform(
|
||||
/* 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);
|
||||
}
|
||||
|
||||
private static native long createNativeTransform(
|
||||
long[] profileIDs, int renderType,
|
||||
int inFormatter, boolean isInIntPacked,
|
||||
int outFormatter, boolean isOutIntPacked,
|
||||
@ -175,59 +218,4 @@ public class LCMS implements PCMM {
|
||||
|
||||
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;
|
||||
}
|
||||
|
109
jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSProfile.java
Normal file
109
jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSProfile.java
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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 {
|
||||
private boolean isOutIntPacked = false;
|
||||
|
||||
ICC_Profile[] profiles;
|
||||
long [] profileIDs;
|
||||
LCMSProfile[] lcmsProfiles;
|
||||
int renderType;
|
||||
int transformType;
|
||||
|
||||
@ -84,8 +84,8 @@ public class LCMSTransform implements ColorTransform {
|
||||
/* Actually, it is not a complete transform but just part of it */
|
||||
profiles = new ICC_Profile[1];
|
||||
profiles[0] = profile;
|
||||
profileIDs = new long[1];
|
||||
profileIDs[0] = LCMS.getProfileID(profile);
|
||||
lcmsProfiles = new LCMSProfile[1];
|
||||
lcmsProfiles[0] = LCMS.getProfileID(profile);
|
||||
this.renderType = (renderType == ColorTransform.Any)?
|
||||
ICC_Profile.icPerceptual : renderType;
|
||||
this.transformType = transformType;
|
||||
@ -105,14 +105,14 @@ public class LCMSTransform implements ColorTransform {
|
||||
size+=((LCMSTransform)transforms[i]).profiles.length;
|
||||
}
|
||||
profiles = new ICC_Profile[size];
|
||||
profileIDs = new long[size];
|
||||
lcmsProfiles = new LCMSProfile[size];
|
||||
int j = 0;
|
||||
for (int i=0; i < transforms.length; i++) {
|
||||
LCMSTransform curTrans = (LCMSTransform)transforms[i];
|
||||
System.arraycopy(curTrans.profiles, 0, profiles, j,
|
||||
curTrans.profiles.length);
|
||||
System.arraycopy(curTrans.profileIDs, 0, profileIDs, j,
|
||||
curTrans.profileIDs.length);
|
||||
System.arraycopy(curTrans.lcmsProfiles, 0, lcmsProfiles, j,
|
||||
curTrans.lcmsProfiles.length);
|
||||
j += curTrans.profiles.length;
|
||||
}
|
||||
renderType = ((LCMSTransform)transforms[0]).renderType;
|
||||
@ -152,7 +152,7 @@ public class LCMSTransform implements ColorTransform {
|
||||
outFormatter = out.pixelType;
|
||||
isOutIntPacked = out.isIntPacked;
|
||||
|
||||
ID = LCMS.createNativeTransform(profileIDs, renderType,
|
||||
ID = LCMS.createTransform(lcmsProfiles, renderType,
|
||||
inFormatter, isInIntPacked,
|
||||
outFormatter, isOutIntPacked,
|
||||
disposerReferent);
|
||||
|
@ -94,8 +94,12 @@ cmsInt32Number TransportValue32(cmsInt32Number Value)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef union storeID_s { /* store SProfile stuff in a Java Long */
|
||||
typedef struct lcmsProfile_s {
|
||||
cmsHPROFILE pf;
|
||||
} lcmsProfile_t, *lcmsProfile_p;
|
||||
|
||||
typedef union storeID_s { /* store SProfile stuff in a Java Long */
|
||||
lcmsProfile_p lcmsPf;
|
||||
cmsHTRANSFORM xf;
|
||||
jobject jobj;
|
||||
jlong j;
|
||||
@ -106,7 +110,6 @@ typedef union {
|
||||
jint j;
|
||||
} TagSignature_t, *TagSignature_p;
|
||||
|
||||
static jfieldID Trans_profileIDs_fID;
|
||||
static jfieldID Trans_renderType_fID;
|
||||
static jfieldID Trans_ID_fID;
|
||||
static jfieldID IL_isIntPacked_fID;
|
||||
@ -118,7 +121,6 @@ static jfieldID IL_nextRowOffset_fID;
|
||||
static jfieldID IL_width_fID;
|
||||
static jfieldID IL_height_fID;
|
||||
static jfieldID IL_imageAtOnce_fID;
|
||||
static jfieldID PF_ID_fID;
|
||||
|
||||
JavaVM *javaVM;
|
||||
|
||||
@ -145,6 +147,18 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
||||
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)
|
||||
{
|
||||
storeID_t sTrans;
|
||||
@ -170,7 +184,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
|
||||
jlong* ids;
|
||||
|
||||
size = (*env)->GetArrayLength (env, profileIDs);
|
||||
ids = (*env)->GetPrimitiveArrayCritical(env, profileIDs, 0);
|
||||
ids = (*env)->GetLongArrayElements(env, profileIDs, 0);
|
||||
|
||||
#ifdef _LITTLE_ENDIAN
|
||||
/* Reversing data packed into int for LE archs */
|
||||
@ -186,6 +200,8 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
|
||||
iccArray = (cmsHPROFILE*) malloc(
|
||||
size*2*sizeof(cmsHPROFILE));
|
||||
if (iccArray == NULL) {
|
||||
(*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);
|
||||
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL");
|
||||
return 0L;
|
||||
}
|
||||
@ -197,7 +213,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
|
||||
cmsColorSpaceSignature cs;
|
||||
|
||||
sTrans.j = ids[i];
|
||||
icc = sTrans.pf;
|
||||
icc = sTrans.lcmsPf->pf;
|
||||
iccArray[j++] = icc;
|
||||
|
||||
/* Middle non-abstract profiles should be doubled before passing to
|
||||
@ -215,13 +231,15 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
|
||||
sTrans.xf = cmsCreateMultiprofileTransform(iccArray, j,
|
||||
inFormatter, outFormatter, renderType, 0);
|
||||
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, profileIDs, ids, 0);
|
||||
(*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);
|
||||
|
||||
if (sTrans.xf == NULL) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_createNativeTransform: "
|
||||
"sTrans.xf == NULL");
|
||||
JNU_ThrowByName(env, "java/awt/color/CMMException",
|
||||
"Cannot get color transform");
|
||||
if ((*env)->ExceptionOccurred(env) == NULL) {
|
||||
JNU_ThrowByName(env, "java/awt/color/CMMException",
|
||||
"Cannot get color transform");
|
||||
}
|
||||
} else {
|
||||
Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j);
|
||||
}
|
||||
@ -236,20 +254,23 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
|
||||
/*
|
||||
* Class: sun_java2d_cmm_lcms_LCMS
|
||||
* Method: loadProfile
|
||||
* Signature: ([B)J
|
||||
* Signature: ([B,Lsun/java2d/cmm/lcms/LCMSProfile;)V
|
||||
*/
|
||||
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;
|
||||
jint dataSize;
|
||||
storeID_t sProf;
|
||||
cmsHPROFILE pf;
|
||||
|
||||
if (JNU_IsNull(env, data)) {
|
||||
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
|
||||
return 0L;
|
||||
}
|
||||
|
||||
sProf.j = 0L;
|
||||
|
||||
dataArray = (*env)->GetByteArrayElements (env, data, 0);
|
||||
dataSize = (*env)->GetArrayLength (env, data);
|
||||
|
||||
@ -258,22 +279,37 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative
|
||||
return 0L;
|
||||
}
|
||||
|
||||
sProf.pf = cmsOpenProfileFromMem((const void *)dataArray,
|
||||
pf = cmsOpenProfileFromMem((const void *)dataArray,
|
||||
(cmsUInt32Number) dataSize);
|
||||
|
||||
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
|
||||
|
||||
if (sProf.pf == NULL) {
|
||||
if (pf == NULL) {
|
||||
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
|
||||
} else {
|
||||
/* Sanity check: try to save the profile in order
|
||||
* to force basic validation.
|
||||
*/
|
||||
cmsUInt32Number pfSize = 0;
|
||||
if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize) ||
|
||||
if (!cmsSaveProfileToMem(pf, NULL, &pfSize) ||
|
||||
pfSize < sizeof(cmsICCHeader))
|
||||
{
|
||||
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
|
||||
|
||||
cmsCloseProfile(pf);
|
||||
pf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pf != NULL) {
|
||||
// create profile holder
|
||||
sProf.lcmsPf = (lcmsProfile_p)malloc(sizeof(lcmsProfile_t));
|
||||
if (sProf.lcmsPf != NULL) {
|
||||
// register the disposer record
|
||||
sProf.lcmsPf->pf = pf;
|
||||
Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sProf.j);
|
||||
} else {
|
||||
cmsCloseProfile(pf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,37 +318,17 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative
|
||||
|
||||
/*
|
||||
* Class: sun_java2d_cmm_lcms_LCMS
|
||||
* Method: freeProfile
|
||||
* Signature: (J)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative
|
||||
(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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_java2d_cmm_lcms_LCMS
|
||||
* Method: getProfileSize
|
||||
* Method: getProfileSizeNative
|
||||
* 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)
|
||||
{
|
||||
storeID_t sProf;
|
||||
cmsUInt32Number pfSize = 0;
|
||||
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;
|
||||
} else {
|
||||
JNU_ThrowByName(env, "java/awt/color/CMMException",
|
||||
@ -323,10 +339,10 @@ JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSize
|
||||
|
||||
/*
|
||||
* Class: sun_java2d_cmm_lcms_LCMS
|
||||
* Method: getProfileData
|
||||
* Method: getProfileDataNative
|
||||
* 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)
|
||||
{
|
||||
storeID_t sProf;
|
||||
@ -338,7 +354,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
|
||||
sProf.j = id;
|
||||
|
||||
// determine actual profile size
|
||||
if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize)) {
|
||||
if (!cmsSaveProfileToMem(sProf.lcmsPf->pf, NULL, &pfSize)) {
|
||||
JNU_ThrowByName(env, "java/awt/color/CMMException",
|
||||
"Can not access specified profile.");
|
||||
return;
|
||||
@ -354,7 +370,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
|
||||
|
||||
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);
|
||||
|
||||
@ -368,7 +384,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
|
||||
/* Get profile header info */
|
||||
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);
|
||||
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
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = _getHeaderInfo(sProf.pf, dataArray, bufSize);
|
||||
status = _getHeaderInfo(sProf.lcmsPf->pf, dataArray, bufSize);
|
||||
|
||||
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
|
||||
|
||||
@ -425,8 +441,8 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative
|
||||
return data;
|
||||
}
|
||||
|
||||
if (cmsIsTag(sProf.pf, sig.cms)) {
|
||||
tagSize = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0);
|
||||
if (cmsIsTag(sProf.lcmsPf->pf, sig.cms)) {
|
||||
tagSize = cmsReadRawTag(sProf.lcmsPf->pf, sig.cms, NULL, 0);
|
||||
} else {
|
||||
JNU_ThrowByName(env, "java/awt/color/CMMException",
|
||||
"ICC profile tag not found");
|
||||
@ -449,7 +465,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative
|
||||
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);
|
||||
|
||||
@ -470,8 +486,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative
|
||||
(JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
|
||||
{
|
||||
storeID_t sProf;
|
||||
cmsHPROFILE pfReplace = NULL;
|
||||
|
||||
TagSignature_t sig;
|
||||
cmsBool status;
|
||||
cmsBool status = FALSE;
|
||||
jbyte* dataArray;
|
||||
int tagSize;
|
||||
|
||||
@ -493,15 +511,24 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative
|
||||
}
|
||||
|
||||
if (tagSig == SigHead) {
|
||||
status = _setHeaderInfo(sProf.pf, dataArray, tagSize);
|
||||
status = _setHeaderInfo(sProf.lcmsPf->pf, dataArray, tagSize);
|
||||
} 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);
|
||||
|
||||
if (!status) {
|
||||
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
|
||||
/*
|
||||
* Class: sun_java2d_cmm_lcms_LCMS
|
||||
* 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)
|
||||
{
|
||||
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
|
||||
* corresponding classes to avoid problems with invalidating ids by class
|
||||
* unloading
|
||||
*/
|
||||
Trans_profileIDs_fID = (*env)->GetFieldID (env, Trans, "profileIDs", "[J");
|
||||
Trans_renderType_fID = (*env)->GetFieldID (env, Trans, "renderType", "I");
|
||||
Trans_ID_fID = (*env)->GetFieldID (env, Trans, "ID", "J");
|
||||
|
||||
@ -658,8 +699,6 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS
|
||||
IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I");
|
||||
IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z");
|
||||
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)
|
||||
@ -714,76 +753,114 @@ static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cmsBool _writeCookedTag(cmsHPROFILE pfTarget,
|
||||
cmsTagSignature sig,
|
||||
/* Returns new profile handler, if it was created successfully,
|
||||
NULL otherwise.
|
||||
*/
|
||||
static cmsHPROFILE _writeCookedTag(const cmsHPROFILE pfTarget,
|
||||
const cmsTagSignature sig,
|
||||
jbyte *pData, jint size)
|
||||
{
|
||||
cmsBool status;
|
||||
cmsUInt32Number pfSize = 0;
|
||||
cmsUInt8Number* pfBuffer = NULL;
|
||||
const cmsInt32Number tagCount = cmsGetTagCount(pfTarget);
|
||||
cmsInt32Number i;
|
||||
cmsHPROFILE pfSanity = NULL;
|
||||
|
||||
cmsICCHeader hdr = { 0 };
|
||||
|
||||
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);
|
||||
if (NULL == p) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
// 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;
|
||||
}
|
||||
// now write the user supplied tag
|
||||
if (size <= 0 || !cmsWriteRawTag(p, sig, pData, size)) {
|
||||
cmsCloseProfile(p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// copy tags from the original profile
|
||||
for (i = 0; i < tagCount; i++) {
|
||||
cmsBool isTagReady = FALSE;
|
||||
const cmsTagSignature s = cmsGetTagSignature(pfTarget, i);
|
||||
const cmsInt32Number tagSize = cmsReadRawTag(pfTarget, s, NULL, 0);
|
||||
|
||||
if (s == sig) {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (!isTagReady) {
|
||||
cmsCloseProfile(p);
|
||||
return NULL;
|
||||
}
|
||||
pCookedTag = NULL;
|
||||
cmsCloseProfile(p);
|
||||
}
|
||||
return status;
|
||||
|
||||
// now we have all tags moved to the new profile.
|
||||
// do some sanity checks: write it to a memory buffer and read again.
|
||||
if (cmsSaveProfileToMem(p, NULL, &pfSize)) {
|
||||
void* buf = malloc(pfSize);
|
||||
if (buf != NULL) {
|
||||
// load raw profile data into the buffer
|
||||
if (cmsSaveProfileToMem(p, buf, &pfSize)) {
|
||||
pfSanity = cmsOpenProfileFromMem(buf, pfSize);
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
cmsCloseProfile(pfSanity);
|
||||
pfSanity = NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6476665 6523403 6733501 7042594
|
||||
* @bug 6476665 6523403 6733501 7042594 7043064
|
||||
* @summary Verifies reading and writing profiles and tags of the standard color
|
||||
* spaces
|
||||
* @run main ReadWriteProfileTest
|
||||
@ -82,6 +82,7 @@ public class ReadWriteProfileTest implements Runnable {
|
||||
|
||||
public void run() {
|
||||
for (int i = 0; i < cspaces.length; i++) {
|
||||
System.out.println("Profile: " + csNames[i]);
|
||||
ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
|
||||
byte [] data = pf.getData();
|
||||
pf = ICC_Profile.getInstance(data);
|
||||
@ -92,6 +93,10 @@ public class ReadWriteProfileTest implements Runnable {
|
||||
}
|
||||
|
||||
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 [] empty = new byte[tagData.length];
|
||||
boolean emptyDataRejected = false;
|
||||
@ -104,15 +109,23 @@ public class ReadWriteProfileTest implements Runnable {
|
||||
throw new
|
||||
RuntimeException("Test failed: empty tag data was not rejected.");
|
||||
}
|
||||
pf.setData(tagSig, tagData);
|
||||
|
||||
try {
|
||||
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);
|
||||
|
||||
if (!Arrays.equals(tagData1, tags[i].get(tagSig)))
|
||||
{
|
||||
System.err.println("Incorrect result of getData(int) with" +
|
||||
" tag " +
|
||||
Integer.toHexString(tagSig) +
|
||||
SigToString(tagSig) +
|
||||
" of " + csNames[i] + " profile");
|
||||
|
||||
throw new RuntimeException("Incorrect result of " +
|
||||
@ -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) {
|
||||
ReadWriteProfileTest test = new ReadWriteProfileTest();
|
||||
test.run();
|
||||
|
Loading…
Reference in New Issue
Block a user