summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarti Maria <info@littlecms.com>2011-05-23 14:25:35 +0200
committerMarti Maria <info@littlecms.com>2011-05-23 14:25:35 +0200
commitb972648a0e5ad083a2b7c345b24b3bb08480cbef (patch)
tree8aa513277b89e5ee88b28520e026749d99a56898
parentdd1c51f91dabf54cb38708530c2ab1510f4ef428 (diff)
downloadlcms2-b972648a0e5ad083a2b7c345b24b3bb08480cbef.tar.gz
Dicctionary tag implementation. 2.2 version bump
-rw-r--r--Projects/BorlandC_5.5/lcms2.rc6
-rw-r--r--Projects/VC2008/lcms2.rc10
-rw-r--r--Projects/VC2010/lcms2.rc10
-rw-r--r--Projects/VC2010/resource.h2
-rw-r--r--include/lcms2.h32
-rw-r--r--src/cmsio1.c3
-rw-r--r--src/cmsnamed.c369
-rw-r--r--src/cmstypes.c379
-rw-r--r--testbed/testcms2.c139
9 files changed, 792 insertions, 158 deletions
diff --git a/Projects/BorlandC_5.5/lcms2.rc b/Projects/BorlandC_5.5/lcms2.rc
index 960d4ee..4ce60b7 100644
--- a/Projects/BorlandC_5.5/lcms2.rc
+++ b/Projects/BorlandC_5.5/lcms2.rc
@@ -1,8 +1,8 @@
1 VERSIONINFO
-FILEVERSION 2, 1, 0, 0
-PRODUCTVERSION 2, 1, 0, 0
+FILEVERSION 2, 2, 0, 0
+PRODUCTVERSION 2, 2, 0, 0
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
{
@@ -14,7 +14,7 @@ FILETYPE VFT_DLL
VALUE "FileDescription", "lcms color engine\000"
VALUE "FileVersion", "2.01\000\000"
VALUE "InternalName", "lcms\000"
- VALUE "LegalCopyright", "Copyright © Marti Maria 2010\000\000"
+ VALUE "LegalCopyright", "Copyright © Marti Maria 2011\000\000"
VALUE "OriginalFilename", "lcms.dll\000"
}
diff --git a/Projects/VC2008/lcms2.rc b/Projects/VC2008/lcms2.rc
index fa98520..3593fed 100644
--- a/Projects/VC2008/lcms2.rc
+++ b/Projects/VC2008/lcms2.rc
@@ -30,8 +30,8 @@ LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN
//
1 VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,0,0
+ PRODUCTVERSION 2,2,0,0
FILEFLAGSMASK 0x0L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -49,14 +49,14 @@ BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Marti Maria\0"
VALUE "FileDescription", "lcms color engine\0"
- VALUE "FileVersion", "2.0\0"
+ VALUE "FileVersion", "2.2\0"
VALUE "InternalName", "lcms\0"
- VALUE "LegalCopyright", "Copyright © Marti Maria 2010\0"
+ VALUE "LegalCopyright", "Copyright © Marti Maria 2011\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "lcms2.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "LittleCMS color engine\0"
- VALUE "ProductVersion", "2, 0, 0, 0\0"
+ VALUE "ProductVersion", "2, 0, 2, 0\0"
VALUE "SpecialBuild", "\0"
END
END
diff --git a/Projects/VC2010/lcms2.rc b/Projects/VC2010/lcms2.rc
index fa98520..3593fed 100644
--- a/Projects/VC2010/lcms2.rc
+++ b/Projects/VC2010/lcms2.rc
@@ -30,8 +30,8 @@ LANGUAGE LANG_SPANISH, SUBLANG_SPANISH_MODERN
//
1 VERSIONINFO
- FILEVERSION 2,1,0,0
- PRODUCTVERSION 2,1,0,0
+ FILEVERSION 2,2,0,0
+ PRODUCTVERSION 2,2,0,0
FILEFLAGSMASK 0x0L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -49,14 +49,14 @@ BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Marti Maria\0"
VALUE "FileDescription", "lcms color engine\0"
- VALUE "FileVersion", "2.0\0"
+ VALUE "FileVersion", "2.2\0"
VALUE "InternalName", "lcms\0"
- VALUE "LegalCopyright", "Copyright © Marti Maria 2010\0"
+ VALUE "LegalCopyright", "Copyright © Marti Maria 2011\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "lcms2.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "LittleCMS color engine\0"
- VALUE "ProductVersion", "2, 0, 0, 0\0"
+ VALUE "ProductVersion", "2, 0, 2, 0\0"
VALUE "SpecialBuild", "\0"
END
END
diff --git a/Projects/VC2010/resource.h b/Projects/VC2010/resource.h
index a989cba..7655978 100644
--- a/Projects/VC2010/resource.h
+++ b/Projects/VC2010/resource.h
@@ -1,5 +1,5 @@
//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
+// Microsoft Visual C++ generated include file.
// Used by lcms2.rc
//
diff --git a/include/lcms2.h b/include/lcms2.h
index acdc6b5..d5a77ae 100644
--- a/include/lcms2.h
+++ b/include/lcms2.h
@@ -248,6 +248,7 @@ typedef enum {
cmsSigCrdInfoType = 0x63726469, // 'crdi'
cmsSigCurveType = 0x63757276, // 'curv'
cmsSigDataType = 0x64617461, // 'data'
+ cmsSigDictType = 0x64696374, // 'dict'
cmsSigDateTimeType = 0x6474696D, // 'dtim'
cmsSigDeviceSettingsType = 0x64657673, // 'devs'
cmsSigLut16Type = 0x6d667432, // 'mft2'
@@ -273,10 +274,11 @@ typedef enum {
cmsSigUInt16ArrayType = 0x75693136, // 'ui16'
cmsSigUInt32ArrayType = 0x75693332, // 'ui32'
cmsSigUInt64ArrayType = 0x75693634, // 'ui64'
- cmsSigUInt8ArrayType = 0x75693038, // 'ui08'
+ cmsSigUInt8ArrayType = 0x75693038, // 'ui08'
+ cmsSigVcgtType = 0x76636774, // 'vcgt'
cmsSigViewingConditionsType = 0x76696577, // 'view'
- cmsSigXYZType = 0x58595A20, // 'XYZ '
- cmsSigVcgtType = 0x76636774 // 'vcgt'
+ cmsSigXYZType = 0x58595A20 // 'XYZ '
+
} cmsTagTypeSignature;
@@ -349,7 +351,8 @@ typedef enum {
cmsSigUcrBgTag = 0x62666420, // 'bfd '
cmsSigViewingCondDescTag = 0x76756564, // 'vued'
cmsSigViewingConditionsTag = 0x76696577, // 'view'
- cmsSigVcgtTag = 0x76636774 // 'vcgt'
+ cmsSigVcgtTag = 0x76636774, // 'vcgt'
+ cmsSigMetaTag = 0x6D657461 // 'meta'
} cmsTagSignature;
@@ -1299,6 +1302,27 @@ CMSAPI cmsSEQ* CMSEXPORT cmsAllocProfileSequenceDescription(cmsContext
CMSAPI cmsSEQ* CMSEXPORT cmsDupProfileSequenceDescription(const cmsSEQ* pseq);
CMSAPI void CMSEXPORT cmsFreeProfileSequenceDescription(cmsSEQ* pseq);
+// Dictionaries --------------------------------------------------------------------------------------------------------
+
+typedef struct _cmsDICTentry_struct {
+
+ struct _cmsDICTentry_struct* Next;
+
+ cmsMLU *DisplayName;
+ cmsMLU *DisplayValue;
+ wchar_t* Name;
+ wchar_t* Value;
+
+} cmsDICTentry;
+
+CMSAPI cmsHANDLE CMSEXPORT cmsDictAlloc(cmsContext ContextID);
+CMSAPI void CMSEXPORT cmsDictFree(cmsHANDLE hDict);
+CMSAPI cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict);
+
+CMSAPI cmsBool CMSEXPORT cmsDictAddEntry(cmsHANDLE hDict, const wchar_t* Name, const wchar_t* Value, const cmsMLU *DisplayName, const cmsMLU *DisplayValue);
+CMSAPI const cmsDICTentry* CMSEXPORT cmsDictGetEntryList(cmsHANDLE hDict);
+CMSAPI const cmsDICTentry* CMSEXPORT cmsDictNextEntry(const cmsDICTentry* e);
+
// Access to Profile data ----------------------------------------------------------------------------------------------
CMSAPI cmsHPROFILE CMSEXPORT cmsCreateProfilePlaceholder(cmsContext ContextID);
diff --git a/src/cmsio1.c b/src/cmsio1.c
index f746d81..9c7d245 100644
--- a/src/cmsio1.c
+++ b/src/cmsio1.c
@@ -512,8 +512,7 @@ cmsPipeline* _cmsReadDevicelinkLUT(cmsHPROFILE hProfile, int Intent)
// On named color, take the appropiate tag
if (cmsGetDeviceClass(hProfile) == cmsSigNamedColorClass) {
-
- cmsPipeline* Lut;
+
cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) cmsReadTag(hProfile, cmsSigNamedColor2Tag);
if (nc == NULL) return NULL;
diff --git a/src/cmsnamed.c b/src/cmsnamed.c
index f4f423d..a36abf8 100644
--- a/src/cmsnamed.c
+++ b/src/cmsnamed.c
@@ -32,29 +32,29 @@
// Allocates an empty multi localizad unicode object
cmsMLU* CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems)
{
- cmsMLU* mlu;
+ cmsMLU* mlu;
- // nItems should be positive if given
- if (nItems <= 0) nItems = 2;
+ // nItems should be positive if given
+ if (nItems <= 0) nItems = 2;
- // Create the container
- mlu = (cmsMLU*) _cmsMallocZero(ContextID, sizeof(cmsMLU));
- if (mlu == NULL) return NULL;
+ // Create the container
+ mlu = (cmsMLU*) _cmsMallocZero(ContextID, sizeof(cmsMLU));
+ if (mlu == NULL) return NULL;
- mlu ->ContextID = ContextID;
+ mlu ->ContextID = ContextID;
- // Create entry array
- mlu ->Entries = (_cmsMLUentry*) _cmsCalloc(ContextID, nItems, sizeof(_cmsMLUentry));
- if (mlu ->Entries == NULL) {
- _cmsFree(ContextID, mlu);
- return NULL;
- }
+ // Create entry array
+ mlu ->Entries = (_cmsMLUentry*) _cmsCalloc(ContextID, nItems, sizeof(_cmsMLUentry));
+ if (mlu ->Entries == NULL) {
+ _cmsFree(ContextID, mlu);
+ return NULL;
+ }
- // Ok, keep indexes up to date
- mlu ->AllocatedEntries = nItems;
- mlu ->UsedEntries = 0;
+ // Ok, keep indexes up to date
+ mlu ->AllocatedEntries = nItems;
+ mlu ->UsedEntries = 0;
- return mlu;
+ return mlu;
}
@@ -62,29 +62,29 @@ cmsMLU* CMSEXPORT cmsMLUalloc(cmsContext ContextID, cmsUInt32Number nItems)
static
cmsBool GrowMLUpool(cmsMLU* mlu)
{
- cmsUInt32Number size;
- void *NewPtr;
+ cmsUInt32Number size;
+ void *NewPtr;
- // Sanity check
- if (mlu == NULL) return FALSE;
+ // Sanity check
+ if (mlu == NULL) return FALSE;
- if (mlu ->PoolSize == 0)
- size = 256;
- else
- size = mlu ->PoolSize * 2;
+ if (mlu ->PoolSize == 0)
+ size = 256;
+ else
+ size = mlu ->PoolSize * 2;
- // Check for overflow
- if (size < mlu ->PoolSize) return FALSE;
+ // Check for overflow
+ if (size < mlu ->PoolSize) return FALSE;
- // Reallocate the pool
- NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size);
- if (NewPtr == NULL) return FALSE;
+ // Reallocate the pool
+ NewPtr = _cmsRealloc(mlu ->ContextID, mlu ->MemPool, size);
+ if (NewPtr == NULL) return FALSE;
- mlu ->MemPool = NewPtr;
- mlu ->PoolSize = size;
+ mlu ->MemPool = NewPtr;
+ mlu ->PoolSize = size;
- return TRUE;
+ return TRUE;
}
@@ -94,16 +94,16 @@ cmsBool GrowMLUtable(cmsMLU* mlu)
{
int AllocatedEntries;
_cmsMLUentry *NewPtr;
-
- // Sanity check
- if (mlu == NULL) return FALSE;
+
+ // Sanity check
+ if (mlu == NULL) return FALSE;
AllocatedEntries = mlu ->AllocatedEntries * 2;
- // Check for overflow
- if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE;
+ // Check for overflow
+ if (AllocatedEntries / 2 != mlu ->AllocatedEntries) return FALSE;
- // Reallocate the memory
+ // Reallocate the memory
NewPtr = (_cmsMLUentry*)_cmsRealloc(mlu ->ContextID, mlu ->Entries, AllocatedEntries*sizeof(_cmsMLUentry));
if (NewPtr == NULL) return FALSE;
@@ -119,18 +119,18 @@ static
int SearchMLUEntry(cmsMLU* mlu, cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode)
{
int i;
-
- // Sanity check
- if (mlu == NULL) return -1;
+
+ // Sanity check
+ if (mlu == NULL) return -1;
- // Iterate whole table
+ // Iterate whole table
for (i=0; i < mlu ->UsedEntries; i++) {
if (mlu ->Entries[i].Country == CountryCode &&
mlu ->Entries[i].Language == LanguageCode) return i;
}
- // Not found
+ // Not found
return -1;
}
@@ -143,8 +143,8 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
cmsUInt32Number Offset;
cmsUInt8Number* Ptr;
- // Sanity check
- if (mlu == NULL) return FALSE;
+ // Sanity check
+ if (mlu == NULL) return FALSE;
// Is there any room available?
if (mlu ->UsedEntries >= mlu ->AllocatedEntries) {
@@ -155,17 +155,17 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
if (SearchMLUEntry(mlu, LanguageCode, CountryCode) >= 0) return FALSE; // Only one is allowed!
// Check for size
- while ((mlu ->PoolSize - mlu ->PoolUsed) < size) {
+ while ((mlu ->PoolSize - mlu ->PoolUsed) < size) {
if (!GrowMLUpool(mlu)) return FALSE;
- }
+ }
Offset = mlu ->PoolUsed;
- Ptr = (cmsUInt8Number*) mlu ->MemPool;
- if (Ptr == NULL) return FALSE;
+ Ptr = (cmsUInt8Number*) mlu ->MemPool;
+ if (Ptr == NULL) return FALSE;
- // Set the entry
+ // Set the entry
memmove(Ptr + Offset, Block, size);
mlu ->PoolUsed += size;
@@ -209,7 +209,7 @@ cmsUInt32Number mywcslen(const wchar_t *s)
{
const wchar_t *p;
- p = s;
+ p = s;
while (*p)
p++;
@@ -225,7 +225,7 @@ cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char
cmsUInt32Number len;
if (mlu == NULL) return FALSE;
- if (WideString == NULL) return FALSE;
+ if (WideString == NULL) return FALSE;
len = (cmsUInt32Number) (mywcslen(WideString) + 1) * sizeof(wchar_t);
return AddMLUBlock(mlu, len, WideString, Lang, Cntry);
@@ -234,59 +234,59 @@ cmsBool CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char
// Duplicating a MLU is as easy as copying all members
cmsMLU* CMSEXPORT cmsMLUdup(const cmsMLU* mlu)
{
- cmsMLU* NewMlu = NULL;
+ cmsMLU* NewMlu = NULL;
- // Duplicating a NULL obtains a NULL
- if (mlu == NULL) return NULL;
+ // Duplicating a NULL obtains a NULL
+ if (mlu == NULL) return NULL;
- NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries);
- if (NewMlu == NULL) return NULL;
+ NewMlu = cmsMLUalloc(mlu ->ContextID, mlu ->UsedEntries);
+ if (NewMlu == NULL) return NULL;
- // Should never happen
- if (NewMlu ->AllocatedEntries < mlu ->UsedEntries)
- goto Error;
+ // Should never happen
+ if (NewMlu ->AllocatedEntries < mlu ->UsedEntries)
+ goto Error;
- // Sanitize...
- if (NewMlu ->Entries == NULL || mlu ->Entries == NULL) goto Error;
+ // Sanitize...
+ if (NewMlu ->Entries == NULL || mlu ->Entries == NULL) goto Error;
- memmove(NewMlu ->Entries, mlu ->Entries, mlu ->UsedEntries * sizeof(_cmsMLUentry));
- NewMlu ->UsedEntries = mlu ->UsedEntries;
+ memmove(NewMlu ->Entries, mlu ->Entries, mlu ->UsedEntries * sizeof(_cmsMLUentry));
+ NewMlu ->UsedEntries = mlu ->UsedEntries;
- // The MLU may be empty
- if (mlu ->PoolUsed == 0) {
- NewMlu ->MemPool = NULL;
- }
- else {
- // It is not empty
- NewMlu ->MemPool = _cmsMalloc(mlu ->ContextID, mlu ->PoolUsed);
- if (NewMlu ->MemPool == NULL) goto Error;
- }
+ // The MLU may be empty
+ if (mlu ->PoolUsed == 0) {
+ NewMlu ->MemPool = NULL;
+ }
+ else {
+ // It is not empty
+ NewMlu ->MemPool = _cmsMalloc(mlu ->ContextID, mlu ->PoolUsed);
+ if (NewMlu ->MemPool == NULL) goto Error;
+ }
- NewMlu ->PoolSize = mlu ->PoolUsed;
+ NewMlu ->PoolSize = mlu ->PoolUsed;
- if (NewMlu ->MemPool == NULL || mlu ->MemPool == NULL) goto Error;
+ if (NewMlu ->MemPool == NULL || mlu ->MemPool == NULL) goto Error;
- memmove(NewMlu ->MemPool, mlu->MemPool, mlu ->PoolUsed);
- NewMlu ->PoolUsed = mlu ->PoolUsed;
+ memmove(NewMlu ->MemPool, mlu->MemPool, mlu ->PoolUsed);
+ NewMlu ->PoolUsed = mlu ->PoolUsed;
- return NewMlu;
+ return NewMlu;
Error:
- if (NewMlu != NULL) cmsMLUfree(NewMlu);
- return NULL;
+ if (NewMlu != NULL) cmsMLUfree(NewMlu);
+ return NULL;
}
// Free any used memory
void CMSEXPORT cmsMLUfree(cmsMLU* mlu)
{
- if (mlu) {
+ if (mlu) {
- if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries);
- if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool);
+ if (mlu -> Entries) _cmsFree(mlu ->ContextID, mlu->Entries);
+ if (mlu -> MemPool) _cmsFree(mlu ->ContextID, mlu->MemPool);
- _cmsFree(mlu ->ContextID, mlu);
- }
+ _cmsFree(mlu ->ContextID, mlu);
+ }
}
@@ -294,13 +294,13 @@ void CMSEXPORT cmsMLUfree(cmsMLU* mlu)
// the Language. If none is found, first entry is used instead.
static
const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
- cmsUInt32Number *len,
- cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode,
- cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
+ cmsUInt32Number *len,
+ cmsUInt16Number LanguageCode, cmsUInt16Number CountryCode,
+ cmsUInt16Number* UsedLanguageCode, cmsUInt16Number* UsedCountryCode)
{
int i;
int Best = -1;
- _cmsMLUentry* v;
+ _cmsMLUentry* v;
if (mlu == NULL) return NULL;
@@ -316,8 +316,8 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
if (v -> Country == CountryCode) {
- if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
- if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
+ if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
+ if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
if (len != NULL) *len = v ->Len;
@@ -330,30 +330,30 @@ const wchar_t* _cmsMLUgetWide(const cmsMLU* mlu,
if (Best == -1)
Best = 0;
- v = mlu ->Entries + Best;
+ v = mlu ->Entries + Best;
- if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
- if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
+ if (UsedLanguageCode != NULL) *UsedLanguageCode = v ->Language;
+ if (UsedCountryCode != NULL) *UsedCountryCode = v ->Country;
if (len != NULL) *len = v ->Len;
- return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
+ return(wchar_t*) ((cmsUInt8Number*) mlu ->MemPool + v ->StrW);
}
// Obtain an ASCII representation of the wide string. Setting buffer to NULL returns the len
cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
- const char LanguageCode[3], const char CountryCode[3],
- char* Buffer, cmsUInt32Number BufferSize)
+ const char LanguageCode[3], const char CountryCode[3],
+ char* Buffer, cmsUInt32Number BufferSize)
{
const wchar_t *Wide;
cmsUInt32Number StrLen = 0;
cmsUInt32Number ASCIIlen, i;
- cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
+ cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
- // Sanitize
+ // Sanitize
if (mlu == NULL) return 0;
// Get WideChar
@@ -381,23 +381,23 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
Buffer[i] = (char) Wide[i];
}
- // We put a termination "\0"
+ // We put a termination "\0"
Buffer[ASCIIlen] = 0;
return ASCIIlen + 1;
}
// Obtain a wide representation of the MLU, on depending on current locale settings
cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
- const char LanguageCode[3], const char CountryCode[3],
- wchar_t* Buffer, cmsUInt32Number BufferSize)
+ const char LanguageCode[3], const char CountryCode[3],
+ wchar_t* Buffer, cmsUInt32Number BufferSize)
{
const wchar_t *Wide;
cmsUInt32Number StrLen = 0;
- cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
+ cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
- // Sanitize
+ // Sanitize
if (mlu == NULL) return 0;
Wide = _cmsMLUgetWide(mlu, &StrLen, Lang, Cntry, NULL, NULL);
@@ -414,7 +414,7 @@ cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
StrLen = BufferSize - + sizeof(wchar_t);
memmove(Buffer, Wide, StrLen);
- Buffer[StrLen / sizeof(wchar_t)] = 0;
+ Buffer[StrLen / sizeof(wchar_t)] = 0;
return StrLen + sizeof(wchar_t);
}
@@ -422,27 +422,27 @@ cmsUInt32Number CMSEXPORT cmsMLUgetWide(const cmsMLU* mlu,
// Get also the language and country
CMSAPI cmsBool CMSEXPORT cmsMLUgetTranslation(const cmsMLU* mlu,
- const char LanguageCode[3], const char CountryCode[3],
- char ObtainedLanguage[3], char ObtainedCountry[3])
+ const char LanguageCode[3], const char CountryCode[3],
+ char ObtainedLanguage[3], char ObtainedCountry[3])
{
- const wchar_t *Wide;
+ const wchar_t *Wide;
- cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
+ cmsUInt16Number Lang = _cmsAdjustEndianess16(*(cmsUInt16Number*) LanguageCode);
cmsUInt16Number Cntry = _cmsAdjustEndianess16(*(cmsUInt16Number*) CountryCode);
cmsUInt16Number ObtLang, ObtCode;
- // Sanitize
+ // Sanitize
if (mlu == NULL) return FALSE;
Wide = _cmsMLUgetWide(mlu, NULL, Lang, Cntry, &ObtLang, &ObtCode);
- if (Wide == NULL) return FALSE;
+ if (Wide == NULL) return FALSE;
- // Get used language and code
+ // Get used language and code
*(cmsUInt16Number *)ObtainedLanguage = _cmsAdjustEndianess16(ObtLang);
- *(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode);
+ *(cmsUInt16Number *)ObtainedCountry = _cmsAdjustEndianess16(ObtCode);
- ObtainedLanguage[2] = ObtainedCountry[2] = 0;
- return TRUE;
+ ObtainedLanguage[2] = ObtainedCountry[2] = 0;
+ return TRUE;
}
@@ -657,12 +657,12 @@ void EvalNamedColor(const cmsFloat32Number In[], cmsFloat32Number Out[], const c
cmsStage* _cmsStageAllocNamedColor(cmsNAMEDCOLORLIST* NamedColorList, cmsBool UsePCS)
{
return _cmsStageAllocPlaceholder(NamedColorList ->ContextID,
- cmsSigNamedColorElemType,
+ cmsSigNamedColorElemType,
1, UsePCS ? 3 : NamedColorList ->ColorantCount,
- UsePCS ? EvalNamedColorPCS : EvalNamedColor,
- DupNamedColorList,
- FreeNamedColorList,
- cmsDupNamedColorList(NamedColorList));
+ UsePCS ? EvalNamedColorPCS : EvalNamedColor,
+ DupNamedColorList,
+ FreeNamedColorList,
+ cmsDupNamedColorList(NamedColorList));
}
@@ -763,6 +763,133 @@ Error:
return NULL;
}
+// Dictionaries --------------------------------------------------------------------------------------------------------
+
+// Dictionaries are just very simple linked lists
+
+
+typedef struct _cmsDICT_struct {
+ cmsDICTentry* head;
+ cmsContext ContextID;
+} _cmsDICT;
+
+
+// Allocate an empty dictionary
+cmsHANDLE CMSEXPORT cmsDictAlloc(cmsContext ContextID)
+{
+ _cmsDICT* dict = (_cmsDICT*) _cmsMallocZero(ContextID, sizeof(_cmsDICT));
+ if (dict == NULL) return NULL;
+ dict ->ContextID = ContextID;
+ return (cmsHANDLE) dict;
+}
+
+// Dispose resources
+void CMSEXPORT cmsDictFree(cmsHANDLE hDict)
+{
+ _cmsDICT* dict = (_cmsDICT*) hDict;
+ cmsDICTentry *entry, *next;
+
+ _cmsAssert(dict != NULL);
+
+ // Walk the list freeing all nodes
+ entry = dict ->head;
+ while (entry != NULL) {
+
+ if (entry ->DisplayName != NULL) cmsMLUfree(entry ->DisplayName);
+ if (entry ->DisplayValue != NULL) cmsMLUfree(entry ->DisplayValue);
+ if (entry ->Name != NULL) _cmsFree(dict ->ContextID, entry -> Name);
+ if (entry ->Value != NULL) _cmsFree(dict ->ContextID, entry -> Value);
+
+ // Don't fall in the habitual trap...
+ next = entry ->Next;
+ _cmsFree(dict ->ContextID, entry);
+
+ entry = next;
+ }
+ _cmsFree(dict ->ContextID, dict);
+}
+
+
+// Duplicate a wide char string
+static
+wchar_t* DupWcs(cmsContext ContextID, const wchar_t* ptr)
+{
+ _cmsAssert(ptr != NULL);
+
+ return (wchar_t*) _cmsDupMem(ContextID, ptr, (mywcslen(ptr) + 1) * sizeof(wchar_t));
+}
+
+// Add a new entry to the linked list
+cmsBool CMSEXPORT cmsDictAddEntry(cmsHANDLE hDict, const wchar_t* Name, const wchar_t* Value, const cmsMLU *DisplayName, const cmsMLU *DisplayValue)
+{
+ _cmsDICT* dict = (_cmsDICT*) hDict;
+ cmsDICTentry *entry;
+
+ _cmsAssert(dict != NULL);
+ _cmsAssert(Name != NULL);
+ _cmsAssert(Value != NULL);
+
+ entry = (cmsDICTentry*) _cmsMallocZero(dict ->ContextID, sizeof(cmsDICTentry));
+ if (entry == NULL) return FALSE;
+
+ entry ->DisplayName = cmsMLUdup(DisplayName);
+ entry ->DisplayValue = cmsMLUdup(DisplayValue);
+ entry ->Name = DupWcs(dict ->ContextID, Name);
+ entry ->Value = DupWcs(dict ->ContextID, Value);
+
+ entry ->Next = dict ->head;
+ dict ->head = entry;
+
+ return TRUE;
+}
+
+
+// Duplicates an existing dictionary
+cmsHANDLE CMSEXPORT cmsDictDup(cmsHANDLE hDict)
+{
+ _cmsDICT* old_dict = (_cmsDICT*) hDict;
+ cmsHANDLE hNew;
+ _cmsDICT* new_dict;
+ cmsDICTentry *entry;
+
+ _cmsAssert(old_dict != NULL);
+
+ hNew = cmsDictAlloc(old_dict ->ContextID);
+ if (hNew == NULL) return NULL;
+
+ new_dict = (_cmsDICT*) hNew;
+
+ // Walk the list freeing all nodes
+ entry = old_dict ->head;
+ while (entry != NULL) {
+
+ if (!cmsDictAddEntry(hNew, entry ->Name, entry ->Value, entry ->DisplayName, entry ->DisplayValue)) {
+
+ cmsDictFree(hNew);
+ return NULL;
+ }
+
+ entry = entry -> Next;
+ }
+
+ return hNew;
+}
+
+// Get a pointer to the linked list
+const cmsDICTentry* CMSEXPORT cmsDictGetEntryList(cmsHANDLE hDict)
+{
+ _cmsDICT* dict = (_cmsDICT*) hDict;
+
+ if (dict == NULL) return NULL;
+ return dict ->head;
+}
+
+// Helper For external languages
+const cmsDICTentry* CMSEXPORT cmsDictNextEntry(const cmsDICTentry* e)
+{
+ if (e == NULL) return NULL;
+ return e ->Next;
+}
diff --git a/src/cmstypes.c b/src/cmstypes.c
index ad5e0bc..462e85c 100644
--- a/src/cmstypes.c
+++ b/src/cmstypes.c
@@ -4734,46 +4734,399 @@ void Type_vcgt_Free(struct _cms_typehandler_struct* self, void* Ptr)
}
-
-
// ********************************************************************************
// Type cmsSigDictType
// ********************************************************************************
+// Single column of the table can point to wchar or MLUC elements. Holds arrays of data
+typedef struct {
+ cmsContext ContextID;
+ cmsUInt32Number *Offsets;
+ cmsUInt32Number *Sizes;
+} _cmsDICelem;
+
+typedef struct {
+ _cmsDICelem Name, Value, DisplayName, DisplayValue;
+
+} _cmsDICarray;
+
+// Allocate an empty array element
+static
+cmsBool AllocElem(cmsContext ContextID, _cmsDICelem* e, cmsUInt32Number Count)
+{
+ e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number *));
+ if (e->Offsets == NULL) return FALSE;
+
+ e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number *));
+ if (e->Sizes == NULL) {
+
+ _cmsFree(ContextID, e -> Offsets);
+ return FALSE;
+ }
+
+ e ->ContextID = ContextID;
+ return TRUE;
+}
+
+// Free an array element
+static
+void FreeElem(_cmsDICelem* e)
+{
+ if (e ->Offsets != NULL) _cmsFree(e -> ContextID, e -> Offsets);
+ if (e ->Sizes != NULL) _cmsFree(e -> ContextID, e ->Sizes);
+ e->Offsets = e ->Sizes = NULL;
+}
+
+// Get rid of whole array
+static
+void FreeArray( _cmsDICarray* a)
+{
+ if (a ->Name.Offsets != NULL) FreeElem(&a->Name);
+ if (a ->Value.Offsets != NULL) FreeElem(&a ->Value);
+ if (a ->DisplayName.Offsets != NULL) FreeElem(&a->DisplayName);
+ if (a ->DisplayValue.Offsets != NULL) FreeElem(&a ->DisplayValue);
+}
+
+
+// Allocate whole array
+static
+cmsBool AllocArray(cmsContext ContextID, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length)
+{
+ // Empty values
+ memset(a, 0, sizeof(_cmsDICarray));
+
+ // On depending on record size, create column arrays
+ if (!AllocElem(ContextID, &a ->Name, Count)) goto Error;
+ if (!AllocElem(ContextID, &a ->Value, Count)) goto Error;
+
+ if (Length > 16) {
+ if (!AllocElem(ContextID, &a -> DisplayName, Count)) goto Error;
+
+ }
+ if (Length > 24) {
+ if (!AllocElem(ContextID, &a ->DisplayValue, Count)) goto Error;
+ }
+ return TRUE;
+
+Error:
+ FreeArray(a);
+ return FALSE;
+}
+
+// Read one element
+static
+cmsBool ReadOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsUInt32Number BaseOffset)
+{
+ if (!_cmsReadUInt32Number(io, &e->Offsets[i])) return FALSE;
+ if (!_cmsReadUInt32Number(io, &e ->Sizes[i])) return FALSE;
+
+ e ->Offsets[i] += BaseOffset;
+ return TRUE;
+}
+
+
+static
+cmsBool ReadOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length, cmsUInt32Number BaseOffset)
+{
+ cmsUInt32Number i;
+
+ // Read column arrays
+ for (i=0; i < Count; i++) {
+
+ if (!ReadOneElem(io, &a -> Name, i, BaseOffset)) return FALSE;
+ if (!ReadOneElem(io, &a -> Value, i, BaseOffset)) return FALSE;
+
+ if (Length > 16) {
+
+ if (!ReadOneElem(io, &a ->DisplayName, i, BaseOffset)) return FALSE;
+
+ }
+
+ if (Length > 24) {
+
+ if (!ReadOneElem(io, & a -> DisplayValue, i, BaseOffset)) return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+// Write one element
+static
+cmsBool WriteOneElem(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i)
+{
+ if (!_cmsWriteUInt32Number(io, e->Offsets[i])) return FALSE;
+ if (!_cmsWriteUInt32Number(io, e ->Sizes[i])) return FALSE;
+
+ return TRUE;
+}
+
+static
+cmsBool WriteOffsetArray(cmsIOHANDLER* io, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length)
+{
+ cmsUInt32Number i;
+
+ for (i=0; i < Count; i++) {
+
+ if (!WriteOneElem(io, &a -> Name, i)) return FALSE;
+ if (!WriteOneElem(io, &a -> Value, i)) return FALSE;
+
+ if (Length > 16) {
+
+ if (!WriteOneElem(io, &a -> DisplayName, i)) return FALSE;
+ }
+
+ if (Length > 24) {
+
+ if (!WriteOneElem(io, &a -> DisplayValue, i)) return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static
+cmsBool ReadOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, wchar_t ** wcstr)
+{
+
+ cmsUInt32Number nChars;
+
+ if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
+
+ nChars = e ->Sizes[i] / sizeof(cmsUInt16Number);
+
+ *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t));
+ if (*wcstr == NULL) return FALSE;
+
+ if (!_cmsReadWCharArray(io, nChars, *wcstr)) {
+ _cmsFree(e ->ContextID, *wcstr);
+ return FALSE;
+ }
+
+ // End of string marker
+ (*wcstr)[nChars] = 0;
+ return TRUE;
+}
+
+static
+cmsUInt32Number mywcslen(const wchar_t *s)
+{
+ const wchar_t *p;
+
+ p = s;
+ while (*p)
+ p++;
+
+ return (cmsUInt32Number)(p - s);
+}
+
+static
+cmsBool WriteOneWChar(cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, const wchar_t * wcstr, cmsUInt32Number BaseOffset)
+{
+ cmsUInt32Number Before = io ->Tell(io);
+ cmsUInt32Number n = mywcslen(wcstr);
+
+ e ->Offsets[i] = Before - BaseOffset;
+
+ if (!_cmsWriteWCharArray(io, n, wcstr)) return FALSE;
+
+ e ->Sizes[i] = io ->Tell(io) - Before;
+ return TRUE;
+}
+
+static
+cmsBool ReadOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, cmsMLU** mlu)
+{
+ cmsUInt32Number nItems = 0;
+
+ if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
+
+ *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, e ->Sizes[i]);
+ return *mlu != NULL;
+}
+
+static
+cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, _cmsDICelem* e, cmsUInt32Number i, const cmsMLU* mlu, cmsUInt32Number BaseOffset)
+{
+ cmsUInt32Number Before = io ->Tell(io);
+
+ e ->Offsets[i] = Before - BaseOffset;
+
+ if (!Type_MLU_Write(self, io, (void*) mlu, 1)) return FALSE;
+
+ e ->Sizes[i] = io ->Tell(io) - Before;
+ return TRUE;
+}
+
+
static
void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
-
+ cmsHANDLE hDict;
+ cmsUInt32Number i, Count, Length;
+ cmsUInt32Number BaseOffset;
+ _cmsDICarray a;
+ wchar_t *NameWCS = NULL, *ValueWCS = NULL;
+ cmsMLU *DisplayNameMLU = NULL, *DisplayValueMLU=NULL;
+ cmsBool rc;
+
+ *nItems = 0;
+
+ // Get actual position as a basis for element offsets
+ BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
+
+ // Get name-value record count
+ if (!_cmsReadUInt32Number(io, &Count)) return NULL;
+ SizeOfTag -= sizeof(cmsUInt32Number);
+
+ // Get rec lenghth
+ if (!_cmsReadUInt32Number(io, &Length)) return NULL;
+ SizeOfTag -= sizeof(cmsUInt32Number);
+
+ // Check for valid lengths
+ if (Length != 16 && Length != 24 && Length != 32) {
+ cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown record length in dictionary '%d'", Length);
+ return NULL;
+ }
+
+ // Creates an empty dictionary
+ hDict = cmsDictAlloc(self -> ContextID);
+ if (hDict == NULL) return NULL;
+
+ // On depending on record size, create column arrays
+ if (!AllocArray(self -> ContextID, &a, Count, Length)) goto Error;
+
+ // Read column arrays
+ if (!ReadOffsetArray(io, &a, Count, Length, BaseOffset)) goto Error;
+
+ // Seek to each element and read it
+ for (i=0; i < Count; i++) {
+
+ if (!ReadOneWChar(io, &a.Name, i, &NameWCS)) goto Error;
+ if (!ReadOneWChar(io, &a.Value, i, &ValueWCS)) goto Error;
+
+ if (Length > 16) {
+ if (!ReadOneMLUC(self, io, &a.DisplayName, i, &DisplayNameMLU)) goto Error;
+ }
+
+ if (Length > 24) {
+ if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error;
+ }
+
+ rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU);
+
+ if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS);
+ if (ValueWCS != NULL) _cmsFree(self ->ContextID, ValueWCS);
+ if (DisplayNameMLU != NULL) cmsMLUfree(DisplayNameMLU);
+ if (DisplayValueMLU != NULL) cmsMLUfree(DisplayValueMLU);
+
+ if (!rc) return FALSE;
+ }
+
+ FreeArray(&a);
+ *nItems = 1;
+ return (void*) hDict;
+
+Error:
+ FreeArray(&a);
+ cmsDictFree(hDict);
+ return NULL;
}
static
cmsBool Type_Dictionary_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
+ cmsHANDLE hDict = (cmsHANDLE) Ptr;
+ const cmsDICTentry* p;
+ cmsBool AnyName, AnyValue;
+ cmsUInt32Number i, Count, Length;
+ cmsUInt32Number DirectoryPos, CurrentPos, BaseOffset;
+ _cmsDICarray a;
+
+ if (hDict == NULL) return FALSE;
+
+ BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
+
+ // Let's inspect the dictionary
+ Count = 0; AnyName = FALSE; AnyValue = FALSE;
+ for (p = cmsDictGetEntryList(hDict); p != NULL; p = cmsDictNextEntry(p)) {
+
+ if (p ->DisplayName != NULL) AnyName = TRUE;
+ if (p ->DisplayValue != NULL) AnyValue = TRUE;
+ Count++;
+ }
+
+ Length = 16;
+ if (AnyName) Length += 8;
+ if (AnyValue) Length += 8;
+
+ if (!_cmsWriteUInt32Number(io, Count)) return FALSE;
+ if (!_cmsWriteUInt32Number(io, Length)) return FALSE;
+
+ // Keep starting position of offsets table
+ DirectoryPos = io ->Tell(io);
+
+ // Allocate offsets array
+ if (!AllocArray(self ->ContextID, &a, Count, Length)) goto Error;
+
+ // Write a fake directory to be filled latter on
+ if (!WriteOffsetArray(io, &a, Count, Length)) goto Error;
+
+ // Write each element. Keep track of the size as well.
+ p = cmsDictGetEntryList(hDict);
+ for (i=0; i < Count; i++) {
+
+ if (!WriteOneWChar(io, &a.Name, i, p ->Name, BaseOffset)) goto Error;
+ if (!WriteOneWChar(io, &a.Value, i, p ->Value, BaseOffset)) goto Error;
+
+ if (p ->DisplayName != NULL) {
+ if (!WriteOneMLUC(self, io, &a.DisplayName, i, p ->DisplayName, BaseOffset)) goto Error;
+ }
+
+ if (p ->DisplayValue != NULL) {
+ if (!WriteOneMLUC(self, io, &a.DisplayValue, i, p ->DisplayValue, BaseOffset)) goto Error;
+ }
+
+ p = cmsDictNextEntry(p);
+ }
+
+ // Write the directory
+ CurrentPos = io ->Tell(io);
+ if (!io ->Seek(io, DirectoryPos)) goto Error;
+
+ if (!WriteOffsetArray(io, &a, Count, Length)) goto Error;
+
+ if (!io ->Seek(io, CurrentPos)) goto Error;
+
+ FreeArray(&a);
+ return TRUE;
+
+Error:
+ FreeArray(&a);
+ return FALSE;
+
+ cmsUNUSED_PARAMETER(nItems);
}
static
void* Type_Dictionary_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
{
+ return (void*) cmsDictDup((cmsHANDLE) Ptr);
+
+ cmsUNUSED_PARAMETER(n);
+ cmsUNUSED_PARAMETER(self);
}
static
void Type_Dictionary_Free(struct _cms_typehandler_struct* self, void* Ptr)
{
+ cmsDictFree((cmsHANDLE) Ptr);
+ cmsUNUSED_PARAMETER(self);
}
-/*
-cmsHANDLE cmsDictAlloc();
-cmsHANDLE cmsDictFree(cmsHANDLE hDict);
-cmsUInt32Number cmsDictPut(cmsHANDLE hDict, const char LanguageCode[3], const char CountryCode[3],
- wchar_t* DisplayName, wchar_t* DisplayValue, const wchar_t* Name, const wchar_t* Value);
-cmsUInt32Number cmsDictCount(cmsHANDLE hDict);
-cmsBool cmsDictGetData(cmsHANDLE hDict, cmsUInt32Number n, wchar_t* Name, wchar_t* Value);
-cmsBool cmsDictGetDisplayData(cmsHANDLE hDict, cmsUInt32Number n, const char LanguageCode[3], const char CountryCode[3],
- wchar_t* DisplayName, wchar_t* DisplayValue);
-*/
// ********************************************************************************
// Type support main routines
diff --git a/testbed/testcms2.c b/testbed/testcms2.c
index 6536c61..2d108d7 100644
--- a/testbed/testcms2.c
+++ b/testbed/testcms2.c
@@ -2008,6 +2008,37 @@ cmsInt32Number Check7DinterpGranular(void)
return 1;
}
+
+
+static
+cmsInt32Number Check8DinterpGranular(void)
+{
+ cmsPipeline* lut;
+ cmsStage* mpe;
+ cmsUInt32Number Dimensions[] = { 4, 3, 3, 2, 2, 2, 2, 2 };
+
+ lut = cmsPipelineAlloc(DbgThread(), 8, 3);
+ mpe = cmsStageAllocCLut16bitGranular(DbgThread(), Dimensions, 8, 3, NULL);
+ cmsStageSampleCLut16bit(mpe, Sampler8D, NULL, 0);
+ cmsPipelineInsertStage(lut, cmsAT_BEGIN, mpe);
+
+ // Check accuracy
+
+ if (!CheckOne8D(lut, 0, 0, 0, 0, 0, 0, 0, 0)) return 0;
+ if (!CheckOne8D(lut, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff)) return 0;
+
+ if (!CheckOne8D(lut, 0x8080, 0x8080, 0x8080, 0x8080, 0x1234, 0x1122, 0x0056, 0x0011)) return 0;
+ if (!CheckOne8D(lut, 0x0000, 0xFE00, 0x80FF, 0x8888, 0x8078, 0x2233, 0x0088, 0x2020)) return 0;
+ if (!CheckOne8D(lut, 0x1111, 0x2222, 0x3333, 0x4444, 0x1455, 0x3344, 0x1987, 0x4532)) return 0;
+ if (!CheckOne8D(lut, 0x0000, 0x0012, 0x0013, 0x0014, 0x2333, 0x4455, 0x9988, 0x1200)) return 0;
+ if (!CheckOne8D(lut, 0x3141, 0x1415, 0x1592, 0x9261, 0x4567, 0x5566, 0xfe56, 0x6666)) return 0;
+ if (!CheckOne8D(lut, 0xFF00, 0xFF01, 0xFF12, 0xFF13, 0xF344, 0x6677, 0xbabe, 0xface)) return 0;
+
+ cmsPipelineFree(lut);
+
+ return 1;
+}
+
// Colorimetric conversions -------------------------------------------------------------------------------------------------
// Lab to LCh and back should be performed at 1E-12 accuracy at least
@@ -4795,6 +4826,42 @@ cmsInt32Number CheckVCGT(cmsInt32Number Pass, cmsHPROFILE hProfile)
return 0;
}
+static
+cmsInt32Number CheckDictionary16(cmsInt32Number Pass, cmsHPROFILE hProfile)
+{
+ cmsHANDLE hDict;
+ const cmsDICTentry* e;
+ switch (Pass) {
+
+ case 1:
+ hDict = cmsDictAlloc(DbgThread());
+
+ cmsDictAddEntry(hDict, L"Name", L"String", NULL, NULL);
+ cmsDictAddEntry(hDict, L"Name2", L"12", NULL, NULL);
+ if (!cmsWriteTag(hProfile, cmsSigMetaTag, hDict)) return 0;
+ cmsDictFree(hDict);
+ return 1;
+
+
+ case 2:
+
+ hDict = cmsReadTag(hProfile, cmsSigMetaTag);
+ if (hDict == NULL) return 0;
+
+ e = cmsDictGetEntryList(hDict);
+ if (memcmp(e ->Name, L"Name2", sizeof(wchar_t) * 5) != 0) return 0;
+ if (memcmp(e ->Value, L"12", sizeof(wchar_t) * 2) != 0) return 0;
+ e = cmsDictNextEntry(e);
+ if (memcmp(e ->Name, L"Name", sizeof(wchar_t) * 4) != 0) return 0;
+ if (memcmp(e ->Value, L"String", sizeof(wchar_t) * 5) != 0) return 0;
+ return 1;
+
+ default:;
+ }
+
+ return 0;
+}
+
static
cmsInt32Number CheckRAWtags(cmsInt32Number Pass, cmsHPROFILE hProfile)
@@ -4957,6 +5024,8 @@ cmsInt32Number CheckProfileCreation(void)
SubTest("RAW tags");
if (!CheckRAWtags(Pass, h)) return 0;
+ SubTest("Dictionary meta tags");
+ if (!CheckDictionary16(Pass, h)) return 0;
if (Pass == 1) {
cmsSaveProfileToFile(h, "alltags.icc");
@@ -6726,6 +6795,33 @@ cmsInt32Number CheckGBD(void)
}
+static
+int CheckMD5(void)
+{
+ _cmsICCPROFILE* h;
+ cmsHPROFILE pProfile = cmsOpenProfileFromFile("sRGBlcms2.icc", "r");
+ cmsProfileID ProfileID1, ProfileID2, ProfileID3, ProfileID4;
+
+ h =(_cmsICCPROFILE*) pProfile;
+ if (cmsMD5computeID(pProfile)) cmsGetHeaderProfileID(pProfile, ProfileID1.ID8);
+ if (cmsMD5computeID(pProfile)) cmsGetHeaderProfileID(pProfile,ProfileID2.ID8);
+
+ cmsCloseProfile(pProfile);
+
+
+ pProfile = cmsOpenProfileFromFile("sRGBlcms2.icc", "r");
+
+ h =(_cmsICCPROFILE*) pProfile;
+ if (cmsMD5computeID(pProfile)) cmsGetHeaderProfileID(pProfile, ProfileID3.ID8);
+ if (cmsMD5computeID(pProfile)) cmsGetHeaderProfileID(pProfile,ProfileID4.ID8);
+
+ cmsCloseProfile(pProfile);
+
+ return ((memcmp(ProfileID1.ID8, ProfileID3.ID8, sizeof(ProfileID1)) == 0) &&
+ (memcmp(ProfileID2.ID8, ProfileID4.ID8, sizeof(ProfileID2)) == 0));
+}
+
+
// --------------------------------------------------------------------------------------------------
// P E R F O R M A N C E C H E C K S
// --------------------------------------------------------------------------------------------------
@@ -7342,6 +7438,39 @@ void CheckProfileZOO(void)
#endif
+
+
+#define TYPE_709 709
+static double Rec709Math(int Type, const double Params[], double R)
+{ double Fun;
+
+switch (Type)
+{
+case 709:
+
+if (R <= (Params[3]*Params[4])) Fun = R / Params[3];
+else Fun = pow(((R - Params[2])/Params[1]), Params[0]);
+break;
+
+case -709:
+
+if (R <= Params[4]) Fun = R * Params[3];
+else Fun = Params[1] * pow(R, (1/Params[0])) + Params[2];
+break;
+}
+return Fun;
+}
+
+
+// Add nonstandard TRC curves -> Rec709
+cmsPluginParametricCurves NewCurvePlugin = {
+{ cmsPluginMagicNumber, 2000, cmsPluginParametricCurveSig, NULL },
+1, {TYPE_709}, {5}, Rec709Math};
+
+
+
+
+
// ---------------------------------------------------------------------------------------
int main(int argc, char* argv[])
@@ -7349,6 +7478,7 @@ int main(int argc, char* argv[])
cmsInt32Number Exhaustive = 0;
cmsInt32Number DoSpeedTests = 1;
+
#ifdef _MSC_VER
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif
@@ -7430,7 +7560,7 @@ int main(int argc, char* argv[])
Check("5D interpolation with granularity", Check5DinterpGranular);
Check("6D interpolation with granularity", Check6DinterpGranular);
Check("7D interpolation with granularity", Check7DinterpGranular);
-
+ Check("8D interpolation with granularity", Check8DinterpGranular);
// Encoding of colorspaces
Check("Lab to LCh and back (float only) ", CheckLab2LCh);
@@ -7547,6 +7677,7 @@ int main(int argc, char* argv[])
Check("CGATS parser", CheckCGATS);
Check("PostScript generator", CheckPostScript);
Check("Segment maxima GBD", CheckGBD);
+ Check("MD5 digest", CheckMD5);
if (DoSpeedTests)
@@ -7557,9 +7688,9 @@ int main(int argc, char* argv[])
cmsUnregisterPlugins();
// Cleanup
- RemoveTestProfiles();
-
- return TotalFail;
+ RemoveTestProfiles();
+
+ return TotalFail;
}