include: Implement C_ASSERT() using the C11 _Static_assert() if available.
[wine.git] / dlls / mscms / icc.c
blob2765888709c0b8dda8bc3ea45b2f0524d8c7c3b0
1 /*
2 * MSCMS - Color Management System for Wine
4 * Copyright 2004, 2005 Hans Leidekker
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * 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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winternl.h"
28 #include "icm.h"
30 #include "mscms_priv.h"
32 static inline void adjust_endianness32( ULONG *ptr )
34 #ifndef WORDS_BIGENDIAN
35 *ptr = RtlUlongByteSwap(*ptr);
36 #endif
39 static const struct tag_entry *first_tag( const struct profile *profile )
41 return (const struct tag_entry *)(profile->data + sizeof(PROFILEHEADER) + sizeof(DWORD));
44 void get_profile_header( const struct profile *profile, PROFILEHEADER *header )
46 unsigned int i;
48 memcpy( header, profile->data, sizeof(PROFILEHEADER) );
50 /* ICC format is big-endian, swap bytes if necessary */
51 for (i = 0; i < sizeof(PROFILEHEADER) / sizeof(ULONG); i++)
52 adjust_endianness32( (ULONG *)header + i );
55 void set_profile_header( const struct profile *profile, const PROFILEHEADER *header )
57 unsigned int i;
59 memcpy( profile->data, header, sizeof(PROFILEHEADER) );
61 /* ICC format is big-endian, swap bytes if necessary */
62 for (i = 0; i < sizeof(PROFILEHEADER) / sizeof(ULONG); i++)
63 adjust_endianness32( (ULONG *)profile->data + i );
66 DWORD get_tag_count( const struct profile *profile )
68 DWORD num_tags = *(DWORD *)(profile->data + sizeof(PROFILEHEADER));
69 adjust_endianness32( &num_tags );
70 if ((const BYTE *)(first_tag( profile ) + num_tags) > (const BYTE *)profile->data + profile->size)
71 return 0;
72 return num_tags;
75 BOOL get_tag_entry( const struct profile *profile, DWORD index, struct tag_entry *tag )
77 const struct tag_entry *entry = first_tag( profile );
79 if (index < 1 || index > get_tag_count( profile )) return FALSE;
80 *tag = entry[index - 1];
81 adjust_endianness32( &tag->sig );
82 adjust_endianness32( &tag->offset );
83 adjust_endianness32( &tag->size );
84 if (tag->offset > profile->size || tag->size > profile->size - tag->offset) return FALSE;
85 return TRUE;
88 BOOL get_adjusted_tag( const struct profile *profile, TAGTYPE type, struct tag_entry *tag )
90 const struct tag_entry *entry = first_tag( profile );
91 DWORD sig, i;
93 for (i = get_tag_count(profile); i > 0; i--, entry++)
95 sig = entry->sig;
96 adjust_endianness32( &sig );
97 if (sig == type)
99 *tag = *entry;
100 adjust_endianness32( &tag->sig );
101 adjust_endianness32( &tag->offset );
102 adjust_endianness32( &tag->size );
103 if (tag->offset > profile->size || tag->size > profile->size - tag->offset) return FALSE;
104 return TRUE;
107 return FALSE;
110 static BOOL get_linked_tag( const struct profile *profile, struct tag_entry *ret )
112 const struct tag_entry *entry = first_tag( profile );
113 DWORD sig, offset, size, i;
115 for (i = get_tag_count(profile); i > 0; i--, entry++)
117 sig = entry->sig;
118 adjust_endianness32( &sig );
119 if (sig == ret->sig) continue;
120 offset = entry->offset;
121 size = entry->size;
122 adjust_endianness32( &offset );
123 adjust_endianness32( &size );
124 if (size == ret->size && offset == ret->offset)
126 ret->sig = sig;
127 return TRUE;
130 return FALSE;
133 BOOL get_tag_data( const struct profile *profile, TAGTYPE type, DWORD offset, void *buffer,
134 DWORD *len, BOOL *linked )
136 struct tag_entry tag;
138 if (!get_adjusted_tag( profile, type, &tag )) return FALSE;
140 if (!buffer) offset = 0;
141 if (offset > tag.size) return FALSE;
142 if (*len < tag.size - offset || !buffer)
144 *len = tag.size - offset;
145 return FALSE;
147 memcpy( buffer, profile->data + tag.offset + offset, tag.size - offset );
148 *len = tag.size - offset;
149 if (linked) *linked = get_linked_tag( profile, &tag );
150 return TRUE;
153 BOOL set_tag_data( const struct profile *profile, TAGTYPE type, DWORD offset, const void *buffer, DWORD *len )
155 struct tag_entry tag;
157 if (!get_adjusted_tag( profile, type, &tag )) return FALSE;
159 if (offset > tag.size) return FALSE;
160 *len = min( tag.size - offset, *len );
161 memcpy( profile->data + tag.offset + offset, buffer, *len );
162 return TRUE;