icc.c 3.44 KB
Newer Older
1 2 3
/*
 * MSCMS - Color Management System for Wine
 *
4
 * Copyright 2004, 2005 Hans Leidekker
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20 21 22 23 24 25 26 27 28 29 30 31
 */

#include "config.h"

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winternl.h"
#include "icm.h"

32
#include "mscms_priv.h"
33

34
#ifdef HAVE_LCMS2
35

36
static inline void adjust_endianness32( ULONG *ptr )
37 38 39 40 41 42
{
#ifndef WORDS_BIGENDIAN
    *ptr = RtlUlongByteSwap(*ptr);
#endif
}

43
void get_profile_header( const struct profile *profile, PROFILEHEADER *header )
44 45 46
{
    unsigned int i;

47
    memcpy( header, profile->data, sizeof(PROFILEHEADER) );
48 49 50

    /* ICC format is big-endian, swap bytes if necessary */
    for (i = 0; i < sizeof(PROFILEHEADER) / sizeof(ULONG); i++)
51
        adjust_endianness32( (ULONG *)header + i );
52 53
}

54
void set_profile_header( const struct profile *profile, const PROFILEHEADER *header )
55 56 57
{
    unsigned int i;

58
    memcpy( profile->data, header, sizeof(PROFILEHEADER) );
59 60

    /* ICC format is big-endian, swap bytes if necessary */
61 62
    for (i = 0; i < sizeof(PROFILEHEADER) / sizeof(ULONG); i++)
        adjust_endianness32( (ULONG *)profile->data + i );
63 64
}

65
static BOOL get_adjusted_tag( const struct profile *profile, TAGTYPE type, cmsTagEntry *tag )
66
{
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
    DWORD i, num_tags = *(DWORD *)(profile->data + sizeof(cmsICCHeader));
    cmsTagEntry *entry;
    ULONG sig;

    adjust_endianness32( &num_tags );
    for (i = 0; i < num_tags; i++)
    {
        entry = (cmsTagEntry *)(profile->data + sizeof(cmsICCHeader) + sizeof(DWORD) + i * sizeof(*tag));
        sig = entry->sig;
        adjust_endianness32( &sig );
        if (sig == type)
        {
            tag->sig    = sig;
            tag->offset = entry->offset;
            tag->size   = entry->size;
            adjust_endianness32( &tag->offset );
            adjust_endianness32( &tag->size );
            return TRUE;
        }
    }
    return FALSE;
88 89
}

90
BOOL get_tag_data( const struct profile *profile, TAGTYPE type, DWORD offset, void *buffer, DWORD *len )
91
{
92 93 94 95 96 97 98 99 100 101 102 103 104 105
    cmsTagEntry tag;

    if (!get_adjusted_tag( profile, type, &tag )) return FALSE;

    if (!buffer) offset = 0;
    if (offset > tag.size) return FALSE;
    if (*len < tag.size - offset || !buffer)
    {
        *len = tag.size - offset;
        return FALSE;
    }
    memcpy( buffer, profile->data + tag.offset + offset, tag.size - offset );
    *len = tag.size - offset;
    return TRUE;
106 107
}

108
BOOL set_tag_data( const struct profile *profile, TAGTYPE type, DWORD offset, const void *buffer, DWORD *len )
109
{
110
    cmsTagEntry tag;
111

112
    if (!get_adjusted_tag( profile, type, &tag )) return FALSE;
113

114 115 116 117
    if (offset > tag.size) return FALSE;
    *len = min( tag.size - offset, *len );
    memcpy( profile->data + tag.offset + offset, buffer, *len );
    return TRUE;
118 119
}

120
#endif /* HAVE_LCMS2 */