提交 f7208fec 编写于 作者: A avu

6733501: Apply IcedTea little cms patches

Reviewed-by: bae, prr
上级 e5e0f13a
......@@ -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
......
/*
* 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();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册