/* * Class: sun_java2d_cmm_lcms_LCMS * Method: getTagData * Signature: (JI[B)V */ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagData (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) { LPLCMSICCPROFILE Icc; storeID_t sProf; jbyte* dataArray; int i, tagSize; sProf.j = id; Icc = (LPLCMSICCPROFILE) sProf.pf; if (tagSig == SigHead) { dataArray = (*env)->GetByteArrayElements (env, data, 0); tagSize =(*env)->GetArrayLength(env, data); Icc -> Seek(Icc, 0); Icc -> Read(dataArray, sizeof(icHeader), 1, Icc); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0); return; } i = _cmsSearchTag(Icc, tagSig, FALSE); if (i >=0) { tagSize = Icc->TagSizes[i]; dataArray = (*env)->GetByteArrayElements (env, data, 0); Icc->Seek(Icc, Icc->TagOffsets[i]); Icc->Read(dataArray, 1, tagSize, Icc); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0); return; } JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC profile tag not found"); return; }
/* * Class: sun_java2d_cmm_lcms_LCMS * Method: getTagSize * Signature: (JI)I */ JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagSize (JNIEnv *env, jobject obj, jlong id, jint tagSig) { LPLCMSICCPROFILE Icc; storeID_t sProf; int i; jint result; sProf.j = id; Icc = (LPLCMSICCPROFILE) sProf.pf; if (tagSig == SigHead) { result = sizeof(icHeader); } else { i = _cmsSearchTag(Icc, tagSig, FALSE); if (i >= 0) { result = Icc->TagSizes[i]; } else { JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC profile tag not found"); result = -1; } } return result; }
LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const void* Init) { LPVOID Ptr; icInt32Number i; i = _cmsSearchTag(Icc, sig, FALSE); if (i >=0) { if (Icc -> TagPtrs[i]) _cmsFree(Icc -> TagPtrs[i]); } else { i = Icc -> TagCount; Icc -> TagCount++; if (Icc ->TagCount >= MAX_TABLE_TAG) { cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", MAX_TABLE_TAG); Icc ->TagCount = MAX_TABLE_TAG-1; return NULL; } } Ptr = _cmsMalloc(size); if (Ptr == NULL) return NULL; CopyMemory(Ptr, Init, size); Icc ->TagNames[i] = sig; Icc ->TagSizes[i] = size; Icc ->TagPtrs[i] = Ptr; return Ptr; }
LCMSBOOL _cmsModifyTagData(cmsHPROFILE hProfile, icTagSignature sig, void *data, size_t size) { LCMSBOOL 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; } /* We change the size of Icc here only if we know it'll actually * grow: if Icc is about to shrink we must wait until we've read * the previous data. */ if (delta > 0) { 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); /* Shrink Icc, if needed. */ if (delta < 0) { if (!Icc->Grow(Icc, delta)) { free(ptr); if(isNew) { Icc->TagCount--; } J2dRlsTraceLn(J2D_TRACE_ERROR, "_cmsModifyTagData: Icc->Grow() == FALSE"); return FALSE; } } /* 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; }
LCMSBOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig) { LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile; return _cmsSearchTag(Icc, sig, FALSE) >= 0; }