6733501: Apply IcedTea little cms patches
Reviewed-by: bae, prr
This commit is contained in:
parent
8e6208656a
commit
7f2828e070
@ -30,6 +30,41 @@
|
||||
#include "Disposer.h"
|
||||
#include "lcms.h"
|
||||
|
||||
|
||||
#define ALIGNLONG(x) (((x)+3) & ~(3)) // Aligns to DWORD boundary
|
||||
|
||||
#ifdef USE_BIG_ENDIAN
|
||||
#define AdjustEndianess32(a)
|
||||
#else
|
||||
|
||||
static
|
||||
void AdjustEndianess32(LPBYTE pByte)
|
||||
{
|
||||
BYTE temp1;
|
||||
BYTE temp2;
|
||||
|
||||
temp1 = *pByte++;
|
||||
temp2 = *pByte++;
|
||||
*(pByte-1) = *pByte;
|
||||
*pByte++ = temp2;
|
||||
*(pByte-3) = *pByte;
|
||||
*pByte = temp1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Transports to properly encoded values - note that icc profiles does use
|
||||
// big endian notation.
|
||||
|
||||
static
|
||||
icInt32Number TransportValue32(icInt32Number Value)
|
||||
{
|
||||
icInt32Number Temp = Value;
|
||||
|
||||
AdjustEndianess32((LPBYTE) &Temp);
|
||||
return Temp;
|
||||
}
|
||||
|
||||
#define SigMake(a,b,c,d) \
|
||||
( ( ((int) ((unsigned char) (a))) << 24) | \
|
||||
( ((int) ((unsigned char) (b))) << 16) | \
|
||||
@ -182,6 +217,8 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfile
|
||||
|
||||
sProf.pf = cmsOpenProfileFromMem((LPVOID)dataArray, (DWORD) dataSize);
|
||||
|
||||
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
|
||||
|
||||
if (sProf.pf == NULL) {
|
||||
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
|
||||
}
|
||||
@ -345,7 +382,23 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData
|
||||
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagData
|
||||
(JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
|
||||
{
|
||||
fprintf(stderr, "setTagData operation is not implemented");
|
||||
cmsHPROFILE profile;
|
||||
storeID_t sProf;
|
||||
jbyte* dataArray;
|
||||
int tagSize;
|
||||
|
||||
if (tagSig == SigHead) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_setTagData on icSigHead not "
|
||||
"permitted");
|
||||
return;
|
||||
}
|
||||
|
||||
sProf.j = id;
|
||||
profile = (cmsHPROFILE) sProf.pf;
|
||||
dataArray = (*env)->GetByteArrayElements(env, data, 0);
|
||||
tagSize =(*env)->GetArrayLength(env, data);
|
||||
_cmsModifyTagData(profile, (icTagSignature) tagSig, dataArray, tagSize);
|
||||
(*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
|
||||
}
|
||||
|
||||
void* getILData (JNIEnv *env, jobject img, jint* pDataType,
|
||||
@ -507,3 +560,174 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS
|
||||
|
||||
PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
|
||||
}
|
||||
|
||||
BOOL _cmsModifyTagData(cmsHPROFILE hProfile, icTagSignature sig,
|
||||
void *data, size_t size)
|
||||
{
|
||||
BOOL isNew;
|
||||
int i, idx, delta, count;
|
||||
LPBYTE padChars[3] = {0, 0, 0};
|
||||
LPBYTE beforeBuf, afterBuf, ptr;
|
||||
size_t beforeSize, afterSize;
|
||||
icUInt32Number profileSize, temp;
|
||||
LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
|
||||
|
||||
isNew = FALSE;
|
||||
idx = _cmsSearchTag(Icc, sig, FALSE);
|
||||
if (idx < 0) {
|
||||
isNew = TRUE;
|
||||
idx = Icc->TagCount++;
|
||||
if (Icc->TagCount >= MAX_TABLE_TAG) {
|
||||
J2dRlsTraceLn1(J2D_TRACE_ERROR, "_cmsModifyTagData: Too many tags "
|
||||
"(%d)\n", Icc->TagCount);
|
||||
Icc->TagCount = MAX_TABLE_TAG-1;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read in size from header */
|
||||
Icc->Seek(Icc, 0);
|
||||
Icc->Read(&profileSize, sizeof(icUInt32Number), 1, Icc);
|
||||
AdjustEndianess32((LPBYTE) &profileSize);
|
||||
|
||||
/* Compute the change in profile size */
|
||||
if (isNew) {
|
||||
delta = sizeof(icTag) + ALIGNLONG(size);
|
||||
} else {
|
||||
delta = ALIGNLONG(size) - ALIGNLONG(Icc->TagSizes[idx]);
|
||||
}
|
||||
/* Add tag to internal structures */
|
||||
ptr = malloc(size);
|
||||
if (ptr == NULL) {
|
||||
if(isNew) {
|
||||
Icc->TagCount--;
|
||||
}
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR, "_cmsModifyTagData: ptr == NULL");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!Icc->Grow(Icc, delta)) {
|
||||
free(ptr);
|
||||
if(isNew) {
|
||||
Icc->TagCount--;
|
||||
}
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"_cmsModifyTagData: Icc->Grow() == FALSE");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Compute size of tag data before/after the modified tag */
|
||||
beforeSize = ((isNew)?profileSize:Icc->TagOffsets[idx]) -
|
||||
Icc->TagOffsets[0];
|
||||
if (Icc->TagCount == (idx + 1)) {
|
||||
afterSize = 0;
|
||||
} else {
|
||||
afterSize = profileSize - Icc->TagOffsets[idx+1];
|
||||
}
|
||||
/* Make copies of the data before/after the modified tag */
|
||||
if (beforeSize > 0) {
|
||||
beforeBuf = malloc(beforeSize);
|
||||
if (!beforeBuf) {
|
||||
if(isNew) {
|
||||
Icc->TagCount--;
|
||||
}
|
||||
free(ptr);
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"_cmsModifyTagData: beforeBuf == NULL");
|
||||
return FALSE;
|
||||
}
|
||||
Icc->Seek(Icc, Icc->TagOffsets[0]);
|
||||
Icc->Read(beforeBuf, beforeSize, 1, Icc);
|
||||
}
|
||||
|
||||
if (afterSize > 0) {
|
||||
afterBuf = malloc(afterSize);
|
||||
if (!afterBuf) {
|
||||
free(ptr);
|
||||
if(isNew) {
|
||||
Icc->TagCount--;
|
||||
}
|
||||
if (beforeSize > 0) {
|
||||
free(beforeBuf);
|
||||
}
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"_cmsModifyTagData: afterBuf == NULL");
|
||||
return FALSE;
|
||||
}
|
||||
Icc->Seek(Icc, Icc->TagOffsets[idx+1]);
|
||||
Icc->Read(afterBuf, afterSize, 1, Icc);
|
||||
}
|
||||
|
||||
CopyMemory(ptr, data, size);
|
||||
Icc->TagSizes[idx] = size;
|
||||
Icc->TagNames[idx] = sig;
|
||||
if (Icc->TagPtrs[idx]) {
|
||||
free(Icc->TagPtrs[idx]);
|
||||
}
|
||||
Icc->TagPtrs[idx] = ptr;
|
||||
if (isNew) {
|
||||
Icc->TagOffsets[idx] = profileSize;
|
||||
}
|
||||
|
||||
|
||||
/* Update the profile size in the header */
|
||||
profileSize += delta;
|
||||
Icc->Seek(Icc, 0);
|
||||
temp = TransportValue32(profileSize);
|
||||
Icc->Write(Icc, sizeof(icUInt32Number), &temp);
|
||||
|
||||
|
||||
/* Adjust tag offsets: if the tag is new, we must account
|
||||
for the new tag table entry; otherwise, only those tags after
|
||||
the modified tag are changed (by delta) */
|
||||
if (isNew) {
|
||||
for (i = 0; i < Icc->TagCount; ++i) {
|
||||
Icc->TagOffsets[i] += sizeof(icTag);
|
||||
}
|
||||
} else {
|
||||
for (i = idx+1; i < Icc->TagCount; ++i) {
|
||||
Icc->TagOffsets[i] += delta;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out a new tag table */
|
||||
count = 0;
|
||||
for (i = 0; i < Icc->TagCount; ++i) {
|
||||
if (Icc->TagNames[i] != 0) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
Icc->Seek(Icc, sizeof(icHeader));
|
||||
temp = TransportValue32(count);
|
||||
Icc->Write(Icc, sizeof(icUInt32Number), &temp);
|
||||
|
||||
for (i = 0; i < Icc->TagCount; ++i) {
|
||||
if (Icc->TagNames[i] != 0) {
|
||||
icTag tag;
|
||||
tag.sig = TransportValue32(Icc->TagNames[i]);
|
||||
tag.offset = TransportValue32((icInt32Number) Icc->TagOffsets[i]);
|
||||
tag.size = TransportValue32((icInt32Number) Icc->TagSizes[i]);
|
||||
Icc->Write(Icc, sizeof(icTag), &tag);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write unchanged data before the modified tag */
|
||||
if (beforeSize > 0) {
|
||||
Icc->Write(Icc, beforeSize, beforeBuf);
|
||||
free(beforeBuf);
|
||||
}
|
||||
|
||||
/* Write modified tag data */
|
||||
Icc->Write(Icc, size, data);
|
||||
if (size % 4) {
|
||||
Icc->Write(Icc, 4 - (size % 4), padChars);
|
||||
}
|
||||
|
||||
/* Write unchanged data after the modified tag */
|
||||
if (afterSize > 0) {
|
||||
Icc->Write(Icc, afterSize, afterBuf);
|
||||
free(afterBuf);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -157,14 +157,31 @@ BOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr)
|
||||
if (size == 0) return TRUE;
|
||||
|
||||
if (ResData != NULL)
|
||||
CopyMemory(ResData ->Block + Icc ->UsedSpace, Ptr, size);
|
||||
CopyMemory(ResData ->Block + ResData ->Pointer, Ptr, size);
|
||||
|
||||
ResData->Pointer += size;
|
||||
Icc->UsedSpace += size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
BOOL MemoryGrow(struct _lcms_iccprofile_struct* Icc, size_t size)
|
||||
{
|
||||
FILEMEM* ResData = (FILEMEM*) Icc->stream;
|
||||
|
||||
void* newBlock = realloc(ResData->Block, ResData->Size + size);
|
||||
|
||||
if (!newBlock) {
|
||||
return FALSE;
|
||||
}
|
||||
ResData->Block = newBlock;
|
||||
ResData->Size += size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
BOOL MemoryClose(struct _lcms_iccprofile_struct* Icc)
|
||||
{
|
||||
@ -238,6 +255,13 @@ BOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr)
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
BOOL FileGrow(struct _lcms_iccprofile_struct* Icc, size_t size)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
BOOL FileClose(struct _lcms_iccprofile_struct* Icc)
|
||||
{
|
||||
@ -382,6 +406,7 @@ LPLCMSICCPROFILE _cmsCreateProfileFromFilePlaceholder(const char* FileName)
|
||||
NewIcc ->Seek = FileSeek;
|
||||
NewIcc ->Tell = FileTell;
|
||||
NewIcc ->Close = FileClose;
|
||||
NewIcc ->Grow = FileGrow;
|
||||
NewIcc ->Write = NULL;
|
||||
|
||||
NewIcc ->IsWrite = FALSE;
|
||||
@ -419,7 +444,8 @@ LPLCMSICCPROFILE _cmsCreateProfileFromMemPlaceholder(LPVOID MemPtr, DWORD dwSize
|
||||
NewIcc ->Seek = MemorySeek;
|
||||
NewIcc ->Tell = MemoryTell;
|
||||
NewIcc ->Close = MemoryClose;
|
||||
NewIcc ->Write = NULL;
|
||||
NewIcc ->Grow = MemoryGrow;
|
||||
NewIcc ->Write = MemoryWrite;
|
||||
|
||||
NewIcc ->IsWrite = FALSE;
|
||||
|
||||
|
@ -1838,6 +1838,7 @@ typedef struct _lcms_iccprofile_struct {
|
||||
BOOL (* Seek)(struct _lcms_iccprofile_struct* Icc, size_t offset);
|
||||
BOOL (* Close)(struct _lcms_iccprofile_struct* Icc);
|
||||
size_t (* Tell)(struct _lcms_iccprofile_struct* Icc);
|
||||
BOOL (* Grow)(struct _lcms_iccprofile_struct* Icc, size_t amount);
|
||||
|
||||
// Writting
|
||||
|
||||
|
120
jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java
Normal file
120
jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6476665 6523403 6733501
|
||||
* @summary Verifies reading and writing profiles and tags of the standard color
|
||||
* spaces
|
||||
* @run main ReadWriteProfileTest
|
||||
*/
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.color.ICC_Profile;
|
||||
import java.util.*;
|
||||
import java.nio.*;
|
||||
import java.util.Hashtable;
|
||||
|
||||
public class ReadWriteProfileTest implements Runnable {
|
||||
/* Location of the tag sig counter in 4-byte words */
|
||||
final static int TAG_COUNT_OFFSET = 32;
|
||||
|
||||
/* Location of the tag sig table in 4-byte words */
|
||||
final static int TAG_ELEM_OFFSET = 33;
|
||||
|
||||
static byte[][] profiles;
|
||||
static int [][] tagSigs;
|
||||
static Hashtable<Integer,byte[]> [] tags;
|
||||
|
||||
static int [] cspaces = {ColorSpace.CS_sRGB, ColorSpace.CS_PYCC,
|
||||
ColorSpace.CS_LINEAR_RGB, ColorSpace.CS_CIEXYZ,
|
||||
ColorSpace.CS_GRAY};
|
||||
|
||||
static String [] csNames = {"sRGB", "PYCC", "LINEAR_RGB", "CIEXYZ", "GRAY"};
|
||||
|
||||
static void getProfileTags(byte [] data, Hashtable tags) {
|
||||
ByteBuffer byteBuf = ByteBuffer.wrap(data);
|
||||
IntBuffer intBuf = byteBuf.asIntBuffer();
|
||||
int tagCount = intBuf.get(TAG_COUNT_OFFSET);
|
||||
intBuf.position(TAG_ELEM_OFFSET);
|
||||
for (int i = 0; i < tagCount; i++) {
|
||||
int tagSig = intBuf.get();
|
||||
int tagDataOff = intBuf.get();
|
||||
int tagSize = intBuf.get();
|
||||
|
||||
byte [] tagData = new byte[tagSize];
|
||||
byteBuf.position(tagDataOff);
|
||||
byteBuf.get(tagData);
|
||||
tags.put(tagSig, tagData);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
profiles = new byte[cspaces.length][];
|
||||
tags = new Hashtable[cspaces.length];
|
||||
|
||||
for (int i = 0; i < cspaces.length; i++) {
|
||||
ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
|
||||
profiles[i] = pf.getData();
|
||||
tags[i] = new Hashtable();
|
||||
getProfileTags(profiles[i], tags[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
for (int i = 0; i < cspaces.length; i++) {
|
||||
ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
|
||||
byte [] data = pf.getData();
|
||||
pf = ICC_Profile.getInstance(data);
|
||||
if (!Arrays.equals(data, profiles[i])) {
|
||||
System.err.println("Incorrect result of getData() " + "with " +
|
||||
csNames[i] + " profile");
|
||||
throw new RuntimeException("Incorrect result of getData()");
|
||||
}
|
||||
|
||||
for (int tagSig : tags[i].keySet()) {
|
||||
byte [] tagData = pf.getData(tagSig);
|
||||
byte [] empty = new byte[tagData.length];
|
||||
pf.setData(tagSig, empty);
|
||||
pf.setData(tagSig, tagData);
|
||||
|
||||
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) +
|
||||
" of " + csNames[i] + " profile");
|
||||
|
||||
throw new RuntimeException("Incorrect result of " +
|
||||
"getData(int)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String [] args) {
|
||||
ReadWriteProfileTest test = new ReadWriteProfileTest();
|
||||
test.run();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user