1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Unit test suite for palettes
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2005 Glenn Wurster
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
21*ff449c5fSAmine Khaldi #include <stdarg.h>
22*ff449c5fSAmine Khaldi 
23*ff449c5fSAmine Khaldi #include "windef.h"
24*ff449c5fSAmine Khaldi #include "winbase.h"
25*ff449c5fSAmine Khaldi #include "wingdi.h"
26*ff449c5fSAmine Khaldi #include "winuser.h"
27*ff449c5fSAmine Khaldi #include "mmsystem.h"
28*ff449c5fSAmine Khaldi 
29*ff449c5fSAmine Khaldi #include "wine/test.h"
30c2c66affSColin Finck 
31c2c66affSColin Finck static const PALETTEENTRY logpalettedata[8] = {
32c2c66affSColin Finck     { 0x10, 0x20, 0x30, PC_NOCOLLAPSE },
33c2c66affSColin Finck     { 0x20, 0x30, 0x40, PC_NOCOLLAPSE },
34c2c66affSColin Finck     { 0x30, 0x40, 0x50, PC_NOCOLLAPSE },
35c2c66affSColin Finck     { 0x40, 0x50, 0x60, PC_NOCOLLAPSE },
36c2c66affSColin Finck     { 0x50, 0x60, 0x70, PC_NOCOLLAPSE },
37c2c66affSColin Finck     { 0x60, 0x70, 0x80, PC_NOCOLLAPSE },
38c2c66affSColin Finck     { 0x70, 0x80, 0x90, PC_NOCOLLAPSE },
39c2c66affSColin Finck     { 0x80, 0x90, 0xA0, PC_NOCOLLAPSE },
40c2c66affSColin Finck };
41c2c66affSColin Finck 
test_DIB_PAL_COLORS(void)42c2c66affSColin Finck static void test_DIB_PAL_COLORS(void) {
43c2c66affSColin Finck     HDC hdc = GetDC( NULL );
44c2c66affSColin Finck     HDC memhdc = CreateCompatibleDC( hdc );
45c2c66affSColin Finck     HBITMAP hbmp, hbmpOld;
46c2c66affSColin Finck     char bmpbuf[sizeof(BITMAPINFO) + 10 * sizeof(WORD)];
47c2c66affSColin Finck     PBITMAPINFO bmp = (PBITMAPINFO)bmpbuf;
48c2c66affSColin Finck     WORD * bmpPalPtr;
49c2c66affSColin Finck     char logpalettebuf[sizeof(LOGPALETTE) + sizeof(logpalettedata)];
50c2c66affSColin Finck     PLOGPALETTE logpalette = (PLOGPALETTE)logpalettebuf;
51c2c66affSColin Finck     HPALETTE hpal, hpalOld;
52c2c66affSColin Finck     COLORREF setColor, chkColor, getColor;
53c2c66affSColin Finck     int i;
54c2c66affSColin Finck 
55c2c66affSColin Finck     /* Initialize the logical palette with a few colours */
56c2c66affSColin Finck     logpalette->palVersion = 0x300;
57c2c66affSColin Finck     logpalette->palNumEntries = 8;
58c2c66affSColin Finck     memcpy( logpalette->palPalEntry, logpalettedata, sizeof(logpalettedata) );
59c2c66affSColin Finck     hpal = CreatePalette( logpalette );
60c2c66affSColin Finck     hpalOld = SelectPalette( memhdc, hpal, FALSE );
61c2c66affSColin Finck     ok( hpalOld != NULL, "error=%d\n", GetLastError() );
62c2c66affSColin Finck 
63c2c66affSColin Finck     /* Create a DIB BMP which references colours in the logical palette */
64c2c66affSColin Finck     memset( bmp, 0x00, sizeof(BITMAPINFO) );
65c2c66affSColin Finck     bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
66c2c66affSColin Finck     bmp->bmiHeader.biWidth = 1;
67c2c66affSColin Finck     bmp->bmiHeader.biHeight = 1;
68c2c66affSColin Finck     bmp->bmiHeader.biPlanes = 1;
69c2c66affSColin Finck     bmp->bmiHeader.biBitCount = 8;
70c2c66affSColin Finck     bmp->bmiHeader.biCompression = BI_RGB;
71c2c66affSColin Finck     bmp->bmiHeader.biClrUsed = 10;
72c2c66affSColin Finck     bmp->bmiHeader.biClrImportant = 0;
73c2c66affSColin Finck     bmpPalPtr = (WORD *)&bmp->bmiColors;
74c2c66affSColin Finck     for( i = 0; i < 8; i++ ) {
75c2c66affSColin Finck         *bmpPalPtr++ = i;
76c2c66affSColin Finck     }
77c2c66affSColin Finck     *bmpPalPtr++ = 8; /* Pointer to logical palette index just outside range */
78c2c66affSColin Finck     *bmpPalPtr++ = 19; /* Pointer to bad logical palette index */
79c2c66affSColin Finck 
80c2c66affSColin Finck     hbmp = CreateDIBSection( memhdc, bmp, DIB_PAL_COLORS, 0, 0, 0 );
81c2c66affSColin Finck     ok( hbmp != NULL, "error=%d\n", GetLastError() );
82c2c66affSColin Finck     hbmpOld = SelectObject( memhdc, hbmp );
83c2c66affSColin Finck     ok( hbmpOld != NULL, "error=%d\n", GetLastError() );
84c2c66affSColin Finck 
85c2c66affSColin Finck     /* Test with a RGB to DIB_PAL_COLORS */
86c2c66affSColin Finck     setColor = RGB( logpalettedata[1].peRed, logpalettedata[1].peGreen, logpalettedata[1].peBlue );
87c2c66affSColin Finck     SetPixel( memhdc, 0, 0, setColor );
88c2c66affSColin Finck     chkColor = RGB( logpalettedata[1].peRed, logpalettedata[1].peGreen, logpalettedata[1].peBlue );
89c2c66affSColin Finck     getColor = GetPixel( memhdc, 0, 0 );
90c2c66affSColin Finck     ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
91c2c66affSColin Finck 
92c2c66affSColin Finck     /* Test with a valid DIBINDEX to DIB_PAL_COLORS */
93c2c66affSColin Finck     setColor = DIBINDEX( 2 );
94c2c66affSColin Finck     SetPixel( memhdc, 0, 0, setColor );
95c2c66affSColin Finck     chkColor = RGB( logpalettedata[2].peRed, logpalettedata[2].peGreen, logpalettedata[2].peBlue );
96c2c66affSColin Finck     getColor = GetPixel( memhdc, 0, 0 );
97c2c66affSColin Finck     ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
98c2c66affSColin Finck 
99c2c66affSColin Finck     /* Test with an invalid DIBINDEX to DIB_PAL_COLORS */
100c2c66affSColin Finck     setColor = DIBINDEX( 12 );
101c2c66affSColin Finck     SetPixel( memhdc, 0, 0, setColor );
102c2c66affSColin Finck     chkColor = RGB( 0, 0, 0 );
103c2c66affSColin Finck     getColor = GetPixel( memhdc, 0, 0 );
104c2c66affSColin Finck     ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
105c2c66affSColin Finck 
106c2c66affSColin Finck     /* Test for double wraparound on logical palette references from */
107c2c66affSColin Finck     /* DIBINDEX by DIB_PAL_COLORS. */
108c2c66affSColin Finck     setColor = DIBINDEX( 9 );
109c2c66affSColin Finck     SetPixel( memhdc, 0, 0, setColor );
110c2c66affSColin Finck     chkColor = RGB( logpalettedata[3].peRed, logpalettedata[3].peGreen, logpalettedata[3].peBlue );
111c2c66affSColin Finck     getColor = GetPixel( memhdc, 0, 0 );
112c2c66affSColin Finck     ok( getColor == chkColor, "getColor=%08X\n", (UINT)getColor );
113c2c66affSColin Finck 
114c2c66affSColin Finck     SelectPalette( memhdc, hpalOld, FALSE );
115c2c66affSColin Finck     DeleteObject( hpal );
116c2c66affSColin Finck     SelectObject( memhdc, hbmpOld );
117c2c66affSColin Finck     DeleteObject( hbmp );
118c2c66affSColin Finck     DeleteDC( memhdc );
119c2c66affSColin Finck     ReleaseDC( NULL, hdc );
120c2c66affSColin Finck }
121c2c66affSColin Finck 
test_palette_entries(void)122c2c66affSColin Finck static void test_palette_entries(void)
123c2c66affSColin Finck {
124c2c66affSColin Finck     char logpalettebuf[sizeof(LOGPALETTE) + sizeof(logpalettedata)];
125c2c66affSColin Finck     PLOGPALETTE logpalette = (PLOGPALETTE)logpalettebuf;
126c2c66affSColin Finck     HPALETTE hpal;
127c2c66affSColin Finck     UINT res=0;
128c2c66affSColin Finck     PALETTEENTRY palEntry = { 0x1, 0x2, 0x3, 0xff };
129c2c66affSColin Finck     PALETTEENTRY getEntryResult;
130c2c66affSColin Finck 
131c2c66affSColin Finck     /* Initialize the logical palette with a few colours */
132c2c66affSColin Finck     logpalette->palVersion = 0x300;
133c2c66affSColin Finck     logpalette->palNumEntries = 8;
134c2c66affSColin Finck     memcpy( logpalette->palPalEntry, logpalettedata, sizeof(logpalettedata) );
135c2c66affSColin Finck     hpal = CreatePalette( logpalette );
136c2c66affSColin Finck 
137c2c66affSColin Finck     /* Set a new entry with peFlags to 0xff */
138c2c66affSColin Finck     SetPaletteEntries(hpal, 0, 1, &palEntry);
139c2c66affSColin Finck 
140c2c66affSColin Finck     /* Retrieve the entry to see if GDI32 performs any filtering on peFlags */
141c2c66affSColin Finck     res = GetPaletteEntries(hpal, 0, 1, &getEntryResult);
142c2c66affSColin Finck     ok(res == 1, "GetPaletteEntries should have returned 1 but returned %d\n", res);
143c2c66affSColin Finck 
144c2c66affSColin Finck     ok( palEntry.peFlags == getEntryResult.peFlags, "palEntry.peFlags (%#x) != getEntryResult.peFlags (%#x)\n", palEntry.peFlags, getEntryResult.peFlags );
145c2c66affSColin Finck }
146c2c66affSColin Finck 
test_halftone_palette(void)147c2c66affSColin Finck static void test_halftone_palette(void)
148c2c66affSColin Finck {
149c2c66affSColin Finck     HDC hdc;
150c2c66affSColin Finck     HPALETTE pal;
151c2c66affSColin Finck     PALETTEENTRY entries[256];
152c2c66affSColin Finck     PALETTEENTRY defpal[20];
153c2c66affSColin Finck     int i, count;
154c2c66affSColin Finck 
155c2c66affSColin Finck     hdc = GetDC(0);
156c2c66affSColin Finck 
157c2c66affSColin Finck     count = GetPaletteEntries( GetStockObject(DEFAULT_PALETTE), 0, 20, defpal );
158c2c66affSColin Finck     ok( count == 20, "wrong size %u\n", count );
159c2c66affSColin Finck 
160c2c66affSColin Finck     pal = CreateHalftonePalette( hdc );
161c2c66affSColin Finck     count = GetPaletteEntries( pal, 0, 256, entries );
162c2c66affSColin Finck     ok( count == 256 || broken(count <= 20), /* nt 4 */
163c2c66affSColin Finck         "wrong size %u\n", count );
164c2c66affSColin Finck 
165c2c66affSColin Finck     /* first and last 8 match the default palette */
166c2c66affSColin Finck     if (count >= 20)
167c2c66affSColin Finck     {
168c2c66affSColin Finck         for (i = 0; i < 8; i++)
169c2c66affSColin Finck         {
170c2c66affSColin Finck             ok( entries[i].peRed   == defpal[i].peRed &&
171c2c66affSColin Finck                 entries[i].peGreen == defpal[i].peGreen &&
172c2c66affSColin Finck                 entries[i].peBlue  == defpal[i].peBlue &&
173c2c66affSColin Finck                 !entries[i].peFlags,
174c2c66affSColin Finck                 "%u: wrong color %02x,%02x,%02x,%02x instead of %02x,%02x,%02x\n", i,
175c2c66affSColin Finck                 entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags,
176c2c66affSColin Finck                 defpal[i].peRed, defpal[i].peGreen, defpal[i].peBlue );
177c2c66affSColin Finck         }
178c2c66affSColin Finck         for (i = count - 8; i < count; i++)
179c2c66affSColin Finck         {
180c2c66affSColin Finck             int idx = i - count + 20;
181c2c66affSColin Finck             ok( entries[i].peRed   == defpal[idx].peRed &&
182c2c66affSColin Finck                 entries[i].peGreen == defpal[idx].peGreen &&
183c2c66affSColin Finck                 entries[i].peBlue  == defpal[idx].peBlue &&
184c2c66affSColin Finck                 !entries[i].peFlags,
185c2c66affSColin Finck                 "%u: wrong color %02x,%02x,%02x,%02x instead of %02x,%02x,%02x\n", i,
186c2c66affSColin Finck                 entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags,
187c2c66affSColin Finck                 defpal[idx].peRed, defpal[idx].peGreen, defpal[idx].peBlue );
188c2c66affSColin Finck         }
189c2c66affSColin Finck     }
190c2c66affSColin Finck     DeleteObject( pal );
191c2c66affSColin Finck     ReleaseDC( 0, hdc );
192c2c66affSColin Finck }
193c2c66affSColin Finck 
check_system_palette_entries(HDC hdc)194c2c66affSColin Finck static void check_system_palette_entries(HDC hdc)
195c2c66affSColin Finck {
196c2c66affSColin Finck     PALETTEENTRY entries[256];
197c2c66affSColin Finck     PALETTEENTRY defpal[20];
198c2c66affSColin Finck     int i, count;
199c2c66affSColin Finck 
200c2c66affSColin Finck     memset( defpal, 0xaa, sizeof(defpal) );
201c2c66affSColin Finck     count = GetPaletteEntries( GetStockObject(DEFAULT_PALETTE), 0, 20, defpal );
202c2c66affSColin Finck     ok( count == 20, "wrong size %u\n", count );
203c2c66affSColin Finck 
204c2c66affSColin Finck     memset( entries, 0x55, sizeof(entries) );
205c2c66affSColin Finck     count = GetSystemPaletteEntries( hdc, 0, 256, entries );
206c2c66affSColin Finck     ok( count == 0, "wrong size %u\n", count);
207c2c66affSColin Finck     for (i = 0; i < 10; i++)
208c2c66affSColin Finck     {
209c2c66affSColin Finck         ok( entries[i].peRed   == defpal[i].peRed &&
210c2c66affSColin Finck             entries[i].peGreen == defpal[i].peGreen &&
211c2c66affSColin Finck             entries[i].peBlue  == defpal[i].peBlue &&
212c2c66affSColin Finck             !entries[i].peFlags,
213c2c66affSColin Finck             "%u: wrong color %02x,%02x,%02x,%02x instead of %02x,%02x,%02x\n", i,
214c2c66affSColin Finck             entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags,
215c2c66affSColin Finck             defpal[i].peRed, defpal[i].peGreen, defpal[i].peBlue );
216c2c66affSColin Finck     }
217c2c66affSColin Finck     for (i = 10; i < 246; ++i)
218c2c66affSColin Finck     {
219c2c66affSColin Finck         ok( !entries[i].peRed   &&
220c2c66affSColin Finck             !entries[i].peGreen &&
221c2c66affSColin Finck             !entries[i].peBlue  &&
222c2c66affSColin Finck             !entries[i].peFlags,
223c2c66affSColin Finck             "%u: wrong color %02x,%02x,%02x,%02x instead of 0,0,0\n", i,
224c2c66affSColin Finck             entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags);
225c2c66affSColin Finck     }
226c2c66affSColin Finck     for (i = 246; i < 256; i++)
227c2c66affSColin Finck     {
228c2c66affSColin Finck         int idx = i - 246 + 10;
229c2c66affSColin Finck         ok( entries[i].peRed   == defpal[idx].peRed &&
230c2c66affSColin Finck             entries[i].peGreen == defpal[idx].peGreen &&
231c2c66affSColin Finck             entries[i].peBlue  == defpal[idx].peBlue &&
232c2c66affSColin Finck             !entries[i].peFlags,
233c2c66affSColin Finck             "%u: wrong color %02x,%02x,%02x,%02x instead of %02x,%02x,%02x\n", i,
234c2c66affSColin Finck             entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags,
235c2c66affSColin Finck             defpal[idx].peRed, defpal[idx].peGreen, defpal[idx].peBlue );
236c2c66affSColin Finck     }
237c2c66affSColin Finck 
238c2c66affSColin Finck     memset( entries, 0x55, sizeof(entries) );
239c2c66affSColin Finck     count = GetSystemPaletteEntries( hdc, 0, 10, entries );
240c2c66affSColin Finck     ok( count == 0, "wrong size %u\n", count);
241c2c66affSColin Finck     for (i = 0; i < 10; i++)
242c2c66affSColin Finck     {
243c2c66affSColin Finck         ok( entries[i].peRed   == defpal[i].peRed &&
244c2c66affSColin Finck             entries[i].peGreen == defpal[i].peGreen &&
245c2c66affSColin Finck             entries[i].peBlue  == defpal[i].peBlue &&
246c2c66affSColin Finck             !entries[i].peFlags,
247c2c66affSColin Finck             "%u: wrong color %02x,%02x,%02x,%02x instead of %02x,%02x,%02x\n", i,
248c2c66affSColin Finck             entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags,
249c2c66affSColin Finck             defpal[i].peRed, defpal[i].peGreen, defpal[i].peBlue );
250c2c66affSColin Finck     }
251c2c66affSColin Finck 
252c2c66affSColin Finck     memset( entries, 0x55, sizeof(entries) );
253c2c66affSColin Finck     count = GetSystemPaletteEntries( hdc, 10, 246, entries );
254c2c66affSColin Finck     ok( count == 0, "wrong size %u\n", count);
255c2c66affSColin Finck     for (i = 0; i < 236; ++i)
256c2c66affSColin Finck     {
257c2c66affSColin Finck         ok( !entries[i].peRed   &&
258c2c66affSColin Finck             !entries[i].peGreen &&
259c2c66affSColin Finck             !entries[i].peBlue  &&
260c2c66affSColin Finck             !entries[i].peFlags,
261c2c66affSColin Finck             "%u: wrong color %02x,%02x,%02x,%02x instead of 0,0,0\n", i,
262c2c66affSColin Finck             entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags);
263c2c66affSColin Finck     }
264c2c66affSColin Finck     for (i = 236; i < 246; i++)
265c2c66affSColin Finck     {
266c2c66affSColin Finck         int idx = i - 236 + 10;
267c2c66affSColin Finck         ok( entries[i].peRed   == defpal[idx].peRed &&
268c2c66affSColin Finck             entries[i].peGreen == defpal[idx].peGreen &&
269c2c66affSColin Finck             entries[i].peBlue  == defpal[idx].peBlue &&
270c2c66affSColin Finck             !entries[i].peFlags,
271c2c66affSColin Finck             "%u: wrong color %02x,%02x,%02x,%02x instead of %02x,%02x,%02x\n", i,
272c2c66affSColin Finck             entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags,
273c2c66affSColin Finck             defpal[idx].peRed, defpal[idx].peGreen, defpal[idx].peBlue );
274c2c66affSColin Finck     }
275c2c66affSColin Finck 
276c2c66affSColin Finck     memset( entries, 0x55, sizeof(entries) );
277c2c66affSColin Finck     count = GetSystemPaletteEntries( hdc, 246, 10, entries );
278c2c66affSColin Finck     ok( count == 0, "wrong size %u\n", count);
279c2c66affSColin Finck     for (i = 0; i < 10; i++)
280c2c66affSColin Finck     {
281c2c66affSColin Finck         int idx = i + 10;
282c2c66affSColin Finck         ok( entries[i].peRed   == defpal[idx].peRed &&
283c2c66affSColin Finck             entries[i].peGreen == defpal[idx].peGreen &&
284c2c66affSColin Finck             entries[i].peBlue  == defpal[idx].peBlue &&
285c2c66affSColin Finck             !entries[i].peFlags,
286c2c66affSColin Finck             "%u: wrong color %02x,%02x,%02x,%02x instead of %02x,%02x,%02x\n", i,
287c2c66affSColin Finck             entries[i].peRed, entries[i].peGreen, entries[i].peBlue, entries[i].peFlags,
288c2c66affSColin Finck             defpal[idx].peRed, defpal[idx].peGreen, defpal[idx].peBlue );
289c2c66affSColin Finck     }
290c2c66affSColin Finck }
291c2c66affSColin Finck 
test_system_palette_entries(void)292c2c66affSColin Finck static void test_system_palette_entries(void)
293c2c66affSColin Finck {
294c2c66affSColin Finck     HDC hdc;
295c2c66affSColin Finck     HDC metafile_dc;
296c2c66affSColin Finck     HMETAFILE metafile;
297c2c66affSColin Finck 
298c2c66affSColin Finck     hdc = GetDC(0);
299c2c66affSColin Finck 
300c2c66affSColin Finck     if (!(GetDeviceCaps( hdc, RASTERCAPS ) & RC_PALETTE))
301c2c66affSColin Finck     {
302c2c66affSColin Finck         check_system_palette_entries(hdc);
303c2c66affSColin Finck     }
304c2c66affSColin Finck     else
305c2c66affSColin Finck     {
306c2c66affSColin Finck         skip( "device is palette-based, skipping test\n" );
307c2c66affSColin Finck     }
308c2c66affSColin Finck 
309c2c66affSColin Finck     ReleaseDC( 0, hdc );
310c2c66affSColin Finck 
311c2c66affSColin Finck     metafile_dc = CreateMetaFileA(NULL);
312c2c66affSColin Finck 
313c2c66affSColin Finck     check_system_palette_entries(metafile_dc);
314c2c66affSColin Finck 
315c2c66affSColin Finck     metafile = CloseMetaFile(metafile_dc);
316c2c66affSColin Finck     DeleteMetaFile(metafile);
317c2c66affSColin Finck }
318c2c66affSColin Finck 
START_TEST(palette)319c2c66affSColin Finck START_TEST(palette)
320c2c66affSColin Finck {
321c2c66affSColin Finck     test_DIB_PAL_COLORS();
322c2c66affSColin Finck     test_palette_entries();
323c2c66affSColin Finck     test_halftone_palette();
324c2c66affSColin Finck     test_system_palette_entries();
325c2c66affSColin Finck }
326