Commit 3e30e298 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

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

parent 46489aed
/*
* 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
{
HANDLE file;
DWORD access;
icProfile *iccprofile;
cmsHPROFILE cmsprofile;
};
static unsigned int num_profile_handles;
static unsigned int num_transform_handles;
struct transform
{
cmsHTRANSFORM cmstransform;
};
WINE_DEFAULT_DEBUG_CHANNEL(mscms);
#define CMSMAXHANDLES 0x80
void free_handle_tables( void )
{
HeapFree( GetProcessHeap(), 0, profiletable );
profiletable = NULL;
num_profile_handles = 0;
static struct profile profiletable[CMSMAXHANDLES];
static struct transform transformtable[CMSMAXHANDLES];
HeapFree( GetProcessHeap(), 0, transformtable );
transformtable = NULL;
num_transform_handles = 0;
}
HPROFILE MSCMS_handle2hprofile( HANDLE file )
struct profile *grab_profile( HPROFILE handle )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!file) return NULL;
DWORD_PTR index;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
{
if (profiletable[i].file == file)
index = (DWORD_PTR)handle - 1;
if (index > num_profile_handles)
{
profile = (HPROFILE)(i + 1); goto out;
}
LeaveCriticalSection( &MSCMS_handle_cs );
return NULL;
}
return &profiletable[index];
}
out:
void release_profile( struct profile *profile )
{
LeaveCriticalSection( &MSCMS_handle_cs );
return profile;
}
HANDLE MSCMS_hprofile2handle( HPROFILE profile )
struct transform *grab_transform( HTRANSFORM handle )
{
HANDLE file;
DWORD_PTR i;
DWORD_PTR index;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
file = profiletable[i].file;
index = (DWORD_PTR)handle - 1;
if (index > num_transform_handles)
{
LeaveCriticalSection( &MSCMS_handle_cs );
return file;
return NULL;
}
return &transformtable[index];
}
DWORD MSCMS_hprofile2access( HPROFILE profile )
void release_transform( struct transform *transform )
{
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 )
static HPROFILE alloc_profile_handle( void )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!cmsprofile) return NULL;
EnterCriticalSection( &MSCMS_handle_cs );
DWORD_PTR index;
struct profile *p;
unsigned int count = 128;
for (i = 0; i <= CMSMAXHANDLES; i++)
for (index = 0; index < num_profile_handles; index++)
{
if (profiletable[i].cmsprofile == cmsprofile)
if (!profiletable[index].iccprofile) return (HPROFILE)(index + 1);
}
if (!profiletable)
{
profile = (HPROFILE)(i + 1); goto out;
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;
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;
profiletable = p;
num_profile_handles = count;
LeaveCriticalSection( &MSCMS_handle_cs );
return cmsprofile;
return (HPROFILE)(index + 1);
}
HPROFILE MSCMS_iccprofile2hprofile( const icProfile *iccprofile )
HPROFILE create_profile( struct profile *profile )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!iccprofile) return NULL;
HPROFILE handle;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
if ((handle = alloc_profile_handle()))
{
if (profiletable[i].iccprofile == iccprofile)
{
profile = (HPROFILE)(i + 1); goto out;
}
DWORD_PTR index = (DWORD_PTR)handle - 1;
memcpy( &profiletable[index], profile, sizeof(struct profile) );
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return profile;
return handle;
}
icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile )
BOOL close_profile( HPROFILE handle )
{
icProfile *iccprofile;
DWORD_PTR i;
DWORD_PTR index;
struct profile *profile;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
iccprofile = profiletable[i].iccprofile;
index = (DWORD_PTR)handle - 1;
if (index > num_profile_handles)
{
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 );
return FALSE;
}
profile = &profiletable[index];
for (i = 0; i <= CMSMAXHANDLES; i++)
if (profile->file != INVALID_HANDLE_VALUE)
{
if (profiletable[i].iccprofile == 0)
if (profile->access & PROFILE_READWRITE)
{
profiletable[i].file = file;
profiletable[i].access = access;
profiletable[i].iccprofile = iccprofile;
profiletable[i].cmsprofile = cmsprofile;
DWORD written, size = MSCMS_get_profile_size( profile->iccprofile );
profile = (HPROFILE)(i + 1); goto out;
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) );
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return profile;
return TRUE;
}
void MSCMS_destroy_hprofile_handle( HPROFILE profile )
static HTRANSFORM alloc_transform_handle( void )
{
DWORD_PTR i;
DWORD_PTR index;
struct transform *p;
unsigned int count = 128;
if (profile)
for (index = 0; index < num_transform_handles; index++)
{
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
memset( &profiletable[i], 0, sizeof(struct profile) );
LeaveCriticalSection( &MSCMS_handle_cs );
if (!transformtable[index].cmstransform) return (HTRANSFORM)(index + 1);
}
}
cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform )
{
cmsHTRANSFORM cmstransform;
DWORD_PTR i;
EnterCriticalSection( &MSCMS_handle_cs );
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;
i = (DWORD_PTR)transform - 1;
cmstransform = transformtable[i].cmstransform;
transformtable = p;
num_transform_handles = count;
LeaveCriticalSection( &MSCMS_handle_cs );
return cmstransform;
return (HTRANSFORM)(index + 1);
}
HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform )
HTRANSFORM create_transform( struct transform *transform )
{
HTRANSFORM transform = NULL;
DWORD_PTR i;
if (!cmstransform) return NULL;
HTRANSFORM handle;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
if ((handle = alloc_transform_handle()))
{
if (transformtable[i].cmstransform == 0)
{
transformtable[i].cmstransform = cmstransform;
transform = (HTRANSFORM)(i + 1); goto out;
}
DWORD_PTR index = (DWORD_PTR)handle - 1;
memcpy( &transformtable[index], transform, sizeof(struct transform) );
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return transform;
return handle;
}
void MSCMS_destroy_htransform_handle( HTRANSFORM transform )
BOOL close_transform( HTRANSFORM handle )
{
DWORD_PTR i;
DWORD_PTR index;
struct transform *transform;
if (transform)
{
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)transform - 1;
memset( &transformtable[i], 0, sizeof(struct transform) );
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 */
......@@ -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;
......
......@@ -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 );
extern HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile,
cmsHPROFILE cmsprofile, DWORD access );
extern void MSCMS_destroy_hprofile_handle( HPROFILE profile );
extern cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform );
extern HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform );
extern void MSCMS_destroy_htransform_handle( HTRANSFORM transform );
/* 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.
*/
struct profile
{
HANDLE file;
DWORD access;
icProfile *iccprofile;
cmsHPROFILE cmsprofile;
};
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 );
......
......@@ -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 );
if (!iccprofile || !type) return FALSE;
TRACE( "( %p, %d, %p )\n", handle, index, type );
count = MSCMS_get_tag_count( iccprofile );
if (index > count || index < 1) return FALSE;
if (!profile) 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;
if (!header)
{
release_profile( profile );
return FALSE;
}
MSCMS_get_profile_header( profile->iccprofile, header );
MSCMS_get_profile_header( 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", handle, valid );
TRACE( "( %p, %p )\n", profile, valid );
if (!profile) return FALSE;
if (!valid) return FALSE;
if (iccprofile) return *valid = TRUE;
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;
if (!header || !(profile->access & PROFILE_READWRITE))
{
release_profile( profile );
return FALSE;
}
MSCMS_set_profile_header( profile->iccprofile, header );
MSCMS_set_profile_header( 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;
......
......@@ -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,
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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment