mscms: Rewrite handle management to be thread-safe. Allocate handles dynamically.

This commit is contained in:
Hans Leidekker 2008-03-24 21:33:06 +01:00 committed by Alexandre Julliard
parent 46489aeda2
commit 3e30e29847
5 changed files with 412 additions and 350 deletions

View File

@ -1,7 +1,7 @@
/*
* MSCMS - Color Management System for Wine
*
* Copyright 2004, 2005 Hans Leidekker
* Copyright 2004, 2005, 2008 Hans Leidekker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -19,6 +19,8 @@
*/
#include "config.h"
#include "wine/debug.h"
#include <stdarg.h>
#include "windef.h"
@ -41,247 +43,208 @@ static CRITICAL_SECTION_DEBUG MSCMS_handle_cs_debug =
};
static CRITICAL_SECTION MSCMS_handle_cs = { &MSCMS_handle_cs_debug, -1, 0, 0, 0, 0 };
/* A simple structure to tie together a pointer to an icc profile, an lcms
* color profile handle and a Windows file handle. Windows color profile
* handles are built from indexes into an array of these structures. If
* the profile is memory based the file handle field is set to
* INVALID_HANDLE_VALUE. The 'access' field records the access parameter
* supplied to an OpenColorProfile() call, i.e. PROFILE_READ or PROFILE_READWRITE.
*/
static struct profile *profiletable;
static struct transform *transformtable;
struct profile
static unsigned int num_profile_handles;
static unsigned int num_transform_handles;
WINE_DEFAULT_DEBUG_CHANNEL(mscms);
void free_handle_tables( void )
{
HANDLE file;
DWORD access;
icProfile *iccprofile;
cmsHPROFILE cmsprofile;
};
HeapFree( GetProcessHeap(), 0, profiletable );
profiletable = NULL;
num_profile_handles = 0;
struct transform
HeapFree( GetProcessHeap(), 0, transformtable );
transformtable = NULL;
num_transform_handles = 0;
}
struct profile *grab_profile( HPROFILE handle )
{
cmsHTRANSFORM cmstransform;
};
#define CMSMAXHANDLES 0x80
static struct profile profiletable[CMSMAXHANDLES];
static struct transform transformtable[CMSMAXHANDLES];
HPROFILE MSCMS_handle2hprofile( HANDLE file )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!file) return NULL;
DWORD_PTR index;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
index = (DWORD_PTR)handle - 1;
if (index > num_profile_handles)
{
if (profiletable[i].file == file)
{
profile = (HPROFILE)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return profile;
}
HANDLE MSCMS_hprofile2handle( HPROFILE profile )
{
HANDLE file;
DWORD_PTR i;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
file = profiletable[i].file;
LeaveCriticalSection( &MSCMS_handle_cs );
return file;
}
DWORD MSCMS_hprofile2access( HPROFILE profile )
{
DWORD access;
DWORD_PTR i;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
access = profiletable[i].access;
LeaveCriticalSection( &MSCMS_handle_cs );
return access;
}
HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!cmsprofile) return NULL;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
{
if (profiletable[i].cmsprofile == cmsprofile)
{
profile = (HPROFILE)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return profile;
}
cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile )
{
cmsHPROFILE cmsprofile;
DWORD_PTR i;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
cmsprofile = profiletable[i].cmsprofile;
LeaveCriticalSection( &MSCMS_handle_cs );
return cmsprofile;
}
HPROFILE MSCMS_iccprofile2hprofile( const icProfile *iccprofile )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!iccprofile) return NULL;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
{
if (profiletable[i].iccprofile == iccprofile)
{
profile = (HPROFILE)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return profile;
}
icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile )
{
icProfile *iccprofile;
DWORD_PTR i;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
iccprofile = profiletable[i].iccprofile;
LeaveCriticalSection( &MSCMS_handle_cs );
return iccprofile;
}
HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile,
cmsHPROFILE cmsprofile, DWORD access )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!cmsprofile || !iccprofile) return NULL;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
{
if (profiletable[i].iccprofile == 0)
{
profiletable[i].file = file;
profiletable[i].access = access;
profiletable[i].iccprofile = iccprofile;
profiletable[i].cmsprofile = cmsprofile;
profile = (HPROFILE)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return profile;
}
void MSCMS_destroy_hprofile_handle( HPROFILE profile )
{
DWORD_PTR i;
if (profile)
{
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
memset( &profiletable[i], 0, sizeof(struct profile) );
LeaveCriticalSection( &MSCMS_handle_cs );
return NULL;
}
return &profiletable[index];
}
cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform )
void release_profile( struct profile *profile )
{
cmsHTRANSFORM cmstransform;
DWORD_PTR i;
LeaveCriticalSection( &MSCMS_handle_cs );
}
struct transform *grab_transform( HTRANSFORM handle )
{
DWORD_PTR index;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)transform - 1;
cmstransform = transformtable[i].cmstransform;
LeaveCriticalSection( &MSCMS_handle_cs );
return cmstransform;
}
HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform )
{
HTRANSFORM transform = NULL;
DWORD_PTR i;
if (!cmstransform) return NULL;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
index = (DWORD_PTR)handle - 1;
if (index > num_transform_handles)
{
if (transformtable[i].cmstransform == 0)
{
transformtable[i].cmstransform = cmstransform;
transform = (HTRANSFORM)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return transform;
}
void MSCMS_destroy_htransform_handle( HTRANSFORM transform )
{
DWORD_PTR i;
if (transform)
{
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)transform - 1;
memset( &transformtable[i], 0, sizeof(struct transform) );
LeaveCriticalSection( &MSCMS_handle_cs );
return NULL;
}
return &transformtable[index];
}
void release_transform( struct transform *transform )
{
LeaveCriticalSection( &MSCMS_handle_cs );
}
static HPROFILE alloc_profile_handle( void )
{
DWORD_PTR index;
struct profile *p;
unsigned int count = 128;
for (index = 0; index < num_profile_handles; index++)
{
if (!profiletable[index].iccprofile) return (HPROFILE)(index + 1);
}
if (!profiletable)
{
p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(struct profile) );
}
else
{
count = num_profile_handles * 2;
p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, profiletable, count * sizeof(struct profile) );
}
if (!p) return NULL;
profiletable = p;
num_profile_handles = count;
return (HPROFILE)(index + 1);
}
HPROFILE create_profile( struct profile *profile )
{
HPROFILE handle;
EnterCriticalSection( &MSCMS_handle_cs );
if ((handle = alloc_profile_handle()))
{
DWORD_PTR index = (DWORD_PTR)handle - 1;
memcpy( &profiletable[index], profile, sizeof(struct profile) );
}
LeaveCriticalSection( &MSCMS_handle_cs );
return handle;
}
BOOL close_profile( HPROFILE handle )
{
DWORD_PTR index;
struct profile *profile;
EnterCriticalSection( &MSCMS_handle_cs );
index = (DWORD_PTR)handle - 1;
if (index > num_profile_handles)
{
LeaveCriticalSection( &MSCMS_handle_cs );
return FALSE;
}
profile = &profiletable[index];
if (profile->file != INVALID_HANDLE_VALUE)
{
if (profile->access & PROFILE_READWRITE)
{
DWORD written, size = MSCMS_get_profile_size( profile->iccprofile );
if (SetFilePointer( profile->file, 0, NULL, FILE_BEGIN ) ||
!WriteFile( profile->file, profile->iccprofile, size, &written, NULL ) ||
written != size)
{
ERR( "Unable to write color profile\n" );
}
}
CloseHandle( profile->file );
}
cmsCloseProfile( profile->cmsprofile );
HeapFree( GetProcessHeap(), 0, profile->iccprofile );
memset( profile, 0, sizeof(struct profile) );
LeaveCriticalSection( &MSCMS_handle_cs );
return TRUE;
}
static HTRANSFORM alloc_transform_handle( void )
{
DWORD_PTR index;
struct transform *p;
unsigned int count = 128;
for (index = 0; index < num_transform_handles; index++)
{
if (!transformtable[index].cmstransform) return (HTRANSFORM)(index + 1);
}
if (!transformtable)
{
p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(struct transform) );
}
else
{
count = num_transform_handles * 2;
p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, transformtable, count * sizeof(struct transform) );
}
if (!p) return NULL;
transformtable = p;
num_transform_handles = count;
return (HTRANSFORM)(index + 1);
}
HTRANSFORM create_transform( struct transform *transform )
{
HTRANSFORM handle;
EnterCriticalSection( &MSCMS_handle_cs );
if ((handle = alloc_transform_handle()))
{
DWORD_PTR index = (DWORD_PTR)handle - 1;
memcpy( &transformtable[index], transform, sizeof(struct transform) );
}
LeaveCriticalSection( &MSCMS_handle_cs );
return handle;
}
BOOL close_transform( HTRANSFORM handle )
{
DWORD_PTR index;
struct transform *transform;
EnterCriticalSection( &MSCMS_handle_cs );
index = (DWORD_PTR)handle - 1;
if (index > num_transform_handles)
{
LeaveCriticalSection( &MSCMS_handle_cs );
return FALSE;
}
transform = &transformtable[index];
cmsDeleteTransform( transform->cmstransform );
memset( transform, 0, sizeof(struct transform) );
LeaveCriticalSection( &MSCMS_handle_cs );
return TRUE;
}
#endif /* HAVE_LCMS */

View File

@ -32,6 +32,8 @@
#include "winuser.h"
#include "icm.h"
#include "mscms_priv.h"
WINE_DEFAULT_DEBUG_CHANNEL(mscms);
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
@ -44,6 +46,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
DisableThreadLibraryCalls( hinst );
break;
case DLL_PROCESS_DETACH:
free_handle_tables();
break;
}
return TRUE;

View File

@ -66,21 +66,39 @@
#define DWORD DWORD
#define LPDWORD LPDWORD
extern DWORD MSCMS_hprofile2access( HPROFILE );
extern HPROFILE MSCMS_handle2hprofile( HANDLE file );
extern HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile );
extern HPROFILE MSCMS_iccprofile2hprofile( const icProfile *iccprofile );
extern HANDLE MSCMS_hprofile2handle( HPROFILE profile );
extern cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile );
extern icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile );
/* A simple structure to tie together a pointer to an icc profile, an lcms
* color profile handle and a Windows file handle. If the profile is memory
* based the file handle field is set to INVALID_HANDLE_VALUE. The 'access'
* field records the access parameter supplied to an OpenColorProfile()
* call, i.e. PROFILE_READ or PROFILE_READWRITE.
*/
extern HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile,
cmsHPROFILE cmsprofile, DWORD access );
extern void MSCMS_destroy_hprofile_handle( HPROFILE profile );
struct profile
{
HANDLE file;
DWORD access;
icProfile *iccprofile;
cmsHPROFILE cmsprofile;
};
extern cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform );
extern HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform );
extern void MSCMS_destroy_htransform_handle( HTRANSFORM transform );
struct transform
{
cmsHTRANSFORM cmstransform;
};
extern HPROFILE create_profile( struct profile * );
extern BOOL close_profile( HPROFILE );
extern HTRANSFORM create_transform( struct transform * );
extern BOOL close_transform( HTRANSFORM );
struct profile *grab_profile( HPROFILE );
struct transform *grab_transform( HTRANSFORM );
void release_profile( struct profile * );
void release_transform( struct transform * );
extern void free_handle_tables( void );
extern DWORD MSCMS_get_tag_count( const icProfile *iccprofile );
extern void MSCMS_get_tag_by_index( icProfile *iccprofile, DWORD index, icTag *tag );

View File

@ -333,38 +333,46 @@ BOOL WINAPI GetColorDirectoryW( PCWSTR machine, PWSTR buffer, PDWORD size )
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI GetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset, PDWORD size,
BOOL WINAPI GetColorProfileElement( HPROFILE handle, TAGTYPE type, DWORD offset, PDWORD size,
PVOID buffer, PBOOL ref )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
struct profile *profile = grab_profile( handle );
DWORD i, count;
icTag tag;
TRACE( "( %p, 0x%08x, %d, %p, %p, %p )\n", profile, type, offset, size, buffer, ref );
TRACE( "( %p, 0x%08x, %d, %p, %p, %p )\n", handle, type, offset, size, buffer, ref );
if (!iccprofile || !size || !ref) return FALSE;
count = MSCMS_get_tag_count( iccprofile );
if (!profile) return FALSE;
if (!size || !ref)
{
release_profile( profile );
return FALSE;
}
count = MSCMS_get_tag_count( profile->iccprofile );
for (i = 0; i < count; i++)
{
MSCMS_get_tag_by_index( iccprofile, i, &tag );
MSCMS_get_tag_by_index( profile->iccprofile, i, &tag );
if (tag.sig == type)
{
if ((tag.size - offset) > *size || !buffer)
{
*size = (tag.size - offset);
release_profile( profile );
return FALSE;
}
MSCMS_get_tag_data( iccprofile, &tag, offset, buffer );
MSCMS_get_tag_data( profile->iccprofile, &tag, offset, buffer );
*ref = FALSE; /* FIXME: calculate properly */
release_profile( profile );
return TRUE;
}
}
release_profile( profile );
#endif /* HAVE_LCMS */
return ret;
@ -388,24 +396,33 @@ BOOL WINAPI GetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset
* The tag table index starts at 1.
* Use GetCountColorProfileElements to retrieve a count of tagged elements.
*/
BOOL WINAPI GetColorProfileElementTag( HPROFILE profile, DWORD index, PTAGTYPE type )
BOOL WINAPI GetColorProfileElementTag( HPROFILE handle, DWORD index, PTAGTYPE type )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
struct profile *profile = grab_profile( handle );
DWORD count;
icTag tag;
TRACE( "( %p, %d, %p )\n", profile, index, type );
TRACE( "( %p, %d, %p )\n", handle, index, type );
if (!iccprofile || !type) return FALSE;
if (!profile) return FALSE;
count = MSCMS_get_tag_count( iccprofile );
if (index > count || index < 1) return FALSE;
MSCMS_get_tag_by_index( iccprofile, index - 1, &tag );
if (!type)
{
release_profile( profile );
return FALSE;
}
count = MSCMS_get_tag_count( profile->iccprofile );
if (index > count || index < 1)
{
release_profile( profile );
return FALSE;
}
MSCMS_get_tag_by_index( profile->iccprofile, index - 1, &tag );
*type = tag.sig;
release_profile( profile );
ret = TRUE;
#endif /* HAVE_LCMS */
@ -430,28 +447,36 @@ BOOL WINAPI GetColorProfileElementTag( HPROFILE profile, DWORD index, PTAGTYPE t
* NOTES
* The profile returned will be in big-endian format.
*/
BOOL WINAPI GetColorProfileFromHandle( HPROFILE profile, PBYTE buffer, PDWORD size )
BOOL WINAPI GetColorProfileFromHandle( HPROFILE handle, PBYTE buffer, PDWORD size )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
struct profile *profile = grab_profile( handle );
PROFILEHEADER header;
TRACE( "( %p, %p, %p )\n", profile, buffer, size );
TRACE( "( %p, %p, %p )\n", handle, buffer, size );
if (!iccprofile || !size) return FALSE;
MSCMS_get_profile_header( iccprofile, &header );
if (!profile) return FALSE;
if (!size)
{
release_profile( profile );
return FALSE;
}
MSCMS_get_profile_header( profile->iccprofile, &header );
if (!buffer || header.phSize > *size)
{
*size = header.phSize;
release_profile( profile );
return FALSE;
}
/* No endian conversion needed */
memcpy( buffer, iccprofile, header.phSize );
memcpy( buffer, profile->iccprofile, header.phSize );
*size = header.phSize;
release_profile( profile );
ret = TRUE;
#endif /* HAVE_LCMS */
@ -474,16 +499,23 @@ BOOL WINAPI GetColorProfileFromHandle( HPROFILE profile, PBYTE buffer, PDWORD si
* NOTES
* The profile header returned will be adjusted for endianess.
*/
BOOL WINAPI GetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header )
BOOL WINAPI GetColorProfileHeader( HPROFILE handle, PPROFILEHEADER header )
{
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
struct profile *profile = grab_profile( handle );
TRACE( "( %p, %p )\n", profile, header );
TRACE( "( %p, %p )\n", handle, header );
if (!iccprofile || !header) return FALSE;
if (!profile) return FALSE;
MSCMS_get_profile_header( iccprofile, header );
if (!header)
{
release_profile( profile );
return FALSE;
}
MSCMS_get_profile_header( profile->iccprofile, header );
release_profile( profile );
return TRUE;
#else
@ -505,16 +537,24 @@ BOOL WINAPI GetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header )
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI GetCountColorProfileElements( HPROFILE profile, PDWORD count )
BOOL WINAPI GetCountColorProfileElements( HPROFILE handle, PDWORD count )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
struct profile *profile = grab_profile( handle );
TRACE( "( %p, %p )\n", profile, count );
TRACE( "( %p, %p )\n", handle, count );
if (!iccprofile || !count) return FALSE;
*count = MSCMS_get_tag_count( iccprofile );
if (!profile) return FALSE;
if (!count)
{
release_profile( profile );
return FALSE;
}
*count = MSCMS_get_tag_count( profile->iccprofile );
release_profile( profile );
ret = TRUE;
#endif /* HAVE_LCMS */
@ -1113,23 +1153,28 @@ BOOL WINAPI InstallColorProfileW( PCWSTR machine, PCWSTR profile )
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL present )
BOOL WINAPI IsColorProfileTagPresent( HPROFILE handle, TAGTYPE type, PBOOL present )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
struct profile *profile = grab_profile( handle );
DWORD i, count;
icTag tag;
TRACE( "( %p, 0x%08x, %p )\n", profile, type, present );
TRACE( "( %p, 0x%08x, %p )\n", handle, type, present );
if (!iccprofile || !present) return FALSE;
if (!profile) return FALSE;
count = MSCMS_get_tag_count( iccprofile );
if (!present)
{
release_profile( profile );
return FALSE;
}
count = MSCMS_get_tag_count( profile->iccprofile );
for (i = 0; i < count; i++)
{
MSCMS_get_tag_by_index( iccprofile, i, &tag );
MSCMS_get_tag_by_index( profile->iccprofile, i, &tag );
if (tag.sig == type)
{
@ -1137,6 +1182,7 @@ BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL pres
break;
}
}
release_profile( profile );
#endif /* HAVE_LCMS */
return ret;
@ -1156,16 +1202,23 @@ BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL pres
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI IsColorProfileValid( HPROFILE profile, PBOOL valid )
BOOL WINAPI IsColorProfileValid( HPROFILE handle, PBOOL valid )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
struct profile *profile = grab_profile( handle );
TRACE( "( %p, %p )\n", profile, valid );
TRACE( "( %p, %p )\n", handle, valid );
if (!valid) return FALSE;
if (iccprofile) return *valid = TRUE;
if (!profile) return FALSE;
if (!valid)
{
release_profile( profile );
return FALSE;
}
if (profile->iccprofile) ret = *valid = TRUE;
release_profile( profile );
#endif /* HAVE_LCMS */
return ret;
@ -1188,34 +1241,44 @@ BOOL WINAPI IsColorProfileValid( HPROFILE profile, PBOOL valid )
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI SetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset, PDWORD size,
BOOL WINAPI SetColorProfileElement( HPROFILE handle, TAGTYPE type, DWORD offset, PDWORD size,
PVOID buffer )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
DWORD i, count, access = MSCMS_hprofile2access( profile );
struct profile *profile = grab_profile( handle );
DWORD i, count;
icTag tag;
TRACE( "( %p, 0x%08x, %d, %p, %p )\n", profile, type, offset, size, buffer );
TRACE( "( %p, 0x%08x, %d, %p, %p )\n", handle, type, offset, size, buffer );
if (!iccprofile || !size || !buffer) return FALSE;
if (!(access & PROFILE_READWRITE)) return FALSE;
if (!profile) return FALSE;
count = MSCMS_get_tag_count( iccprofile );
if (!size || !buffer || !(profile->access & PROFILE_READWRITE))
{
release_profile( profile );
return FALSE;
}
count = MSCMS_get_tag_count( profile->iccprofile );
for (i = 0; i < count; i++)
{
MSCMS_get_tag_by_index( iccprofile, i, &tag );
MSCMS_get_tag_by_index( profile->iccprofile, i, &tag );
if (tag.sig == type)
{
if (offset > tag.size) return FALSE;
if (offset > tag.size)
{
release_profile( profile );
return FALSE;
}
MSCMS_set_tag_data( profile->iccprofile, &tag, offset, buffer );
MSCMS_set_tag_data( iccprofile, &tag, offset, buffer );
release_profile( profile );
return TRUE;
}
}
release_profile( profile );
#endif /* HAVE_LCMS */
return ret;
@ -1234,18 +1297,23 @@ BOOL WINAPI SetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI SetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header )
BOOL WINAPI SetColorProfileHeader( HPROFILE handle, PPROFILEHEADER header )
{
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
DWORD access = MSCMS_hprofile2access( profile );
struct profile *profile = grab_profile( handle );
TRACE( "( %p, %p )\n", profile, header );
TRACE( "( %p, %p )\n", handle, header );
if (!iccprofile || !header) return FALSE;
if (!(access & PROFILE_READWRITE)) return FALSE;
if (!profile) return FALSE;
MSCMS_set_profile_header( iccprofile, header );
if (!header || !(profile->access & PROFILE_READWRITE))
{
release_profile( profile );
return FALSE;
}
MSCMS_set_profile_header( profile->iccprofile, header );
release_profile( profile );
return TRUE;
#else
@ -1441,7 +1509,16 @@ HPROFILE WINAPI OpenColorProfileW( PPROFILE profile, DWORD access, DWORD sharing
}
if (cmsprofile)
return MSCMS_create_hprofile_handle( handle, iccprofile, cmsprofile, access );
{
struct profile profile;
profile.file = handle;
profile.access = access;
profile.iccprofile = iccprofile;
profile.cmsprofile = cmsprofile;
return create_profile( &profile );
}
#endif /* HAVE_LCMS */
return NULL;
@ -1463,30 +1540,9 @@ BOOL WINAPI CloseColorProfile( HPROFILE profile )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
HANDLE file = MSCMS_hprofile2handle( profile );
DWORD access = MSCMS_hprofile2access( profile );
TRACE( "( %p )\n", profile );
if (file != INVALID_HANDLE_VALUE)
{
if (access & PROFILE_READWRITE)
{
DWORD written, size = MSCMS_get_profile_size( iccprofile );
if (SetFilePointer( file, 0, NULL, FILE_BEGIN ) ||
!WriteFile( file, iccprofile, size, &written, NULL ) || written != size)
{
ERR( "Unable to write color profile\n" );
}
}
CloseHandle( file );
}
ret = cmsCloseProfile( MSCMS_hprofile2cmsprofile( profile ) );
HeapFree( GetProcessHeap(), 0, iccprofile );
MSCMS_destroy_hprofile_handle( profile );
ret = close_profile( profile );
#endif /* HAVE_LCMS */
return ret;

View File

@ -135,15 +135,21 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest,
{
HTRANSFORM ret = NULL;
#ifdef HAVE_LCMS
cmsHTRANSFORM cmstransform;
struct transform transform;
struct profile *dst, *tgt = NULL;
cmsHPROFILE cmsinput, cmsoutput, cmstarget = NULL;
DWORD in_format, out_format, proofing = 0;
int intent;
TRACE( "( %p, %p, %p, 0x%08x )\n", space, dest, target, flags );
if (!space || !dest) return FALSE;
if (!space || !(dst = grab_profile( dest ))) return FALSE;
if (target && !(tgt = grab_profile( target )))
{
release_profile( dst );
return FALSE;
}
intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent;
TRACE( "lcsIntent: %x\n", space->lcsIntent );
@ -157,13 +163,16 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest,
if (target)
{
proofing = cmsFLAGS_SOFTPROOFING;
cmstarget = MSCMS_hprofile2cmsprofile( target );
cmstarget = tgt->cmsprofile;
}
cmsoutput = MSCMS_hprofile2cmsprofile( dest );
cmstransform = cmsCreateProofingTransform(cmsinput, in_format, cmsoutput, out_format, cmstarget,
intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing);
cmsoutput = dst->cmsprofile;
transform.cmstransform = cmsCreateProofingTransform(cmsinput, in_format, cmsoutput, out_format, cmstarget,
intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing);
ret = MSCMS_create_htransform_handle( cmstransform );
ret = create_transform( &transform );
if (tgt) release_profile( tgt );
release_profile( dst );
#endif /* HAVE_LCMS */
return ret;
@ -191,7 +200,8 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
HTRANSFORM ret = NULL;
#ifdef HAVE_LCMS
cmsHPROFILE *cmsprofiles, cmsconvert = NULL;
cmsHTRANSFORM cmstransform;
struct transform transform;
struct profile *profile0, *profile1;
DWORD in_format, out_format;
TRACE( "( %p, 0x%08x, %p, 0x%08x, 0x%08x, 0x%08x )\n",
@ -205,6 +215,14 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
return NULL;
}
profile0 = grab_profile( profiles[0] );
if (!profile0) return NULL;
profile1 = grab_profile( profiles[1] );
if (!profile1)
{
release_profile( profile0 );
return NULL;
}
in_format = from_profile( profiles[0] );
out_format = from_profile( profiles[nprofiles - 1] );
@ -218,23 +236,26 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
cmsprofiles = HeapAlloc( GetProcessHeap(), 0, (nprofiles + 1) * sizeof(cmsHPROFILE *) );
if (cmsprofiles)
{
cmsprofiles[0] = MSCMS_hprofile2cmsprofile( profiles[0] );
cmsprofiles[0] = profile0->cmsprofile;
if (cmsconvert)
{
cmsprofiles[1] = cmsconvert;
cmsprofiles[2] = MSCMS_hprofile2cmsprofile( profiles[1] );
cmsprofiles[2] = profile1->cmsprofile;
nprofiles++;
}
else
{
cmsprofiles[1] = MSCMS_hprofile2cmsprofile( profiles[1] );
cmsprofiles[1] = profile1->cmsprofile;
}
cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, in_format, out_format, *intents, 0 );
transform.cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, in_format, out_format, *intents, 0 );
HeapFree( GetProcessHeap(), 0, cmsprofiles );
ret = MSCMS_create_htransform_handle( cmstransform );
ret = create_transform( &transform );
}
release_profile( profile0 );
release_profile( profile1 );
#endif /* HAVE_LCMS */
return ret;
}
@ -251,19 +272,14 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI DeleteColorTransform( HTRANSFORM transform )
BOOL WINAPI DeleteColorTransform( HTRANSFORM handle )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
cmsHTRANSFORM cmstransform;
TRACE( "( %p )\n", transform );
TRACE( "( %p )\n", handle );
cmstransform = MSCMS_htransform2cmstransform( transform );
cmsDeleteTransform( cmstransform );
MSCMS_destroy_htransform_handle( transform );
ret = TRUE;
ret = close_transform( handle );
#endif /* HAVE_LCMS */
return ret;
@ -291,22 +307,23 @@ BOOL WINAPI DeleteColorTransform( HTRANSFORM transform )
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI TranslateBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT input,
BOOL WINAPI TranslateBitmapBits( HTRANSFORM handle, PVOID srcbits, BMFORMAT input,
DWORD width, DWORD height, DWORD inputstride, PVOID destbits, BMFORMAT output,
DWORD outputstride, PBMCALLBACKFN callback, ULONG data )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
cmsHTRANSFORM cmstransform;
struct transform *transform = grab_transform( handle );
TRACE( "( %p, %p, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x )\n",
transform, srcbits, input, width, height, inputstride, destbits, output,
handle, srcbits, input, width, height, inputstride, destbits, output,
outputstride, callback, data );
cmstransform = MSCMS_htransform2cmstransform( transform );
cmsChangeBuffersFormat( cmstransform, from_bmformat(input), from_bmformat(output) );
if (!transform) return FALSE;
cmsChangeBuffersFormat( transform->cmstransform, from_bmformat(input), from_bmformat(output) );
cmsDoTransform( cmstransform, srcbits, destbits, width * height );
cmsDoTransform( transform->cmstransform, srcbits, destbits, width * height );
release_transform( transform );
ret = TRUE;
#endif /* HAVE_LCMS */
@ -330,16 +347,20 @@ BOOL WINAPI TranslateBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT i
* Success: TRUE
* Failure: FALSE
*/
BOOL WINAPI TranslateColors( HTRANSFORM transform, PCOLOR in, DWORD count,
BOOL WINAPI TranslateColors( HTRANSFORM handle, PCOLOR in, DWORD count,
COLORTYPE input_type, PCOLOR out, COLORTYPE output_type )
{
BOOL ret = FALSE;
#ifdef HAVE_LCMS
cmsHTRANSFORM xfrm = MSCMS_htransform2cmstransform( transform );
struct transform *transform = grab_transform( handle );
cmsHTRANSFORM xfrm;
unsigned int i;
TRACE( "( %p, %p, %d, %d, %p, %d )\n", transform, in, count, input_type, out, output_type );
TRACE( "( %p, %p, %d, %d, %p, %d )\n", handle, in, count, input_type, out, output_type );
if (!transform) return FALSE;
xfrm = transform->cmstransform;
cmsChangeBuffersFormat( xfrm, from_type(input_type), from_type(output_type) );
switch (input_type)
@ -418,6 +439,7 @@ BOOL WINAPI TranslateColors( HTRANSFORM transform, PCOLOR in, DWORD count,
FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type);
break;
}
release_transform( transform );
#endif /* HAVE_LCMS */
return ret;