Delete all Trailing spaces in code.
[reactos.git] / rostests / winetests / gdi32 / bitmap.c
1 /*
2 * Unit test suite for bitmaps
3 *
4 * Copyright 2004 Huw Davies
5 * Copyright 2006 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <stdarg.h>
23 #include <assert.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "mmsystem.h"
31
32 #include "wine/test.h"
33
34 static BOOL is_win9x;
35
36 static INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp )
37 {
38 switch(bpp)
39 {
40 case 1:
41 return 2 * ((bmWidth+15) >> 4);
42
43 case 24:
44 bmWidth *= 3; /* fall through */
45 case 8:
46 return bmWidth + (bmWidth & 1);
47
48 case 32:
49 return bmWidth * 4;
50
51 case 16:
52 case 15:
53 return bmWidth * 2;
54
55 case 4:
56 return 2 * ((bmWidth+3) >> 2);
57
58 default:
59 trace("Unknown depth %d, please report.\n", bpp );
60 assert(0);
61 }
62 return -1;
63 }
64
65 static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHEADER *bmih)
66 {
67 BITMAP bm;
68 INT ret, width_bytes;
69 char buf[512], buf_cmp[512];
70
71 ret = GetObject(hbm, sizeof(bm), &bm);
72 ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
73
74 ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
75 ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
76 ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
77 width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
78 ok(bm.bmWidthBytes == width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, width_bytes);
79 ok(bm.bmPlanes == bmih->biPlanes, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
80 ok(bm.bmBitsPixel == expected_depth, "wrong bm.bmBitsPixel %d != %d\n", bm.bmBitsPixel, expected_depth);
81 ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
82
83 assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight);
84 assert(sizeof(buf) == sizeof(buf_cmp));
85
86 ret = GetBitmapBits(hbm, 0, NULL);
87 ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
88
89 memset(buf_cmp, 0xAA, sizeof(buf_cmp));
90 memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
91
92 memset(buf, 0xAA, sizeof(buf));
93 ret = GetBitmapBits(hbm, sizeof(buf), buf);
94 ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
95 ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
96
97 /* test various buffer sizes for GetObject */
98 ret = GetObject(hbm, 0, NULL);
99 ok(ret == sizeof(bm), "wrong size %d\n", ret);
100
101 ret = GetObject(hbm, sizeof(bm) * 2, &bm);
102 ok(ret == sizeof(bm), "wrong size %d\n", ret);
103
104 ret = GetObject(hbm, sizeof(bm) / 2, &bm);
105 ok(ret == 0, "%d != 0\n", ret);
106
107 ret = GetObject(hbm, 0, &bm);
108 ok(ret == 0, "%d != 0\n", ret);
109
110 ret = GetObject(hbm, 1, &bm);
111 ok(ret == 0, "%d != 0\n", ret);
112 }
113
114 static void test_createdibitmap(void)
115 {
116 HDC hdc, hdcmem;
117 BITMAPINFOHEADER bmih;
118 HBITMAP hbm, hbm_colour, hbm_old;
119 INT screen_depth;
120
121 hdc = GetDC(0);
122 screen_depth = GetDeviceCaps(hdc, BITSPIXEL);
123 memset(&bmih, 0, sizeof(bmih));
124 bmih.biSize = sizeof(bmih);
125 bmih.biWidth = 10;
126 bmih.biHeight = 10;
127 bmih.biPlanes = 1;
128 bmih.biBitCount = 32;
129 bmih.biCompression = BI_RGB;
130
131 /* First create an un-initialised bitmap. The depth of the bitmap
132 should match that of the hdc and not that supplied in bmih.
133 */
134
135 /* First try 32 bits */
136 hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
137 ok(hbm != NULL, "CreateDIBitmap failed\n");
138 test_bitmap_info(hbm, screen_depth, &bmih);
139 DeleteObject(hbm);
140
141 /* Then 16 */
142 bmih.biBitCount = 16;
143 hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
144 ok(hbm != NULL, "CreateDIBitmap failed\n");
145 test_bitmap_info(hbm, screen_depth, &bmih);
146 DeleteObject(hbm);
147
148 /* Then 1 */
149 bmih.biBitCount = 1;
150 hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
151 ok(hbm != NULL, "CreateDIBitmap failed\n");
152 test_bitmap_info(hbm, screen_depth, &bmih);
153 DeleteObject(hbm);
154
155 /* Now with a monochrome dc we expect a monochrome bitmap */
156 hdcmem = CreateCompatibleDC(hdc);
157
158 /* First try 32 bits */
159 bmih.biBitCount = 32;
160 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
161 ok(hbm != NULL, "CreateDIBitmap failed\n");
162 test_bitmap_info(hbm, 1, &bmih);
163 DeleteObject(hbm);
164
165 /* Then 16 */
166 bmih.biBitCount = 16;
167 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
168 ok(hbm != NULL, "CreateDIBitmap failed\n");
169 test_bitmap_info(hbm, 1, &bmih);
170 DeleteObject(hbm);
171
172 /* Then 1 */
173 bmih.biBitCount = 1;
174 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
175 ok(hbm != NULL, "CreateDIBitmap failed\n");
176 test_bitmap_info(hbm, 1, &bmih);
177 DeleteObject(hbm);
178
179 /* Now select a polychrome bitmap into the dc and we expect
180 screen_depth bitmaps again */
181 hbm_colour = CreateCompatibleBitmap(hdc, 1, 1);
182 hbm_old = SelectObject(hdcmem, hbm_colour);
183
184 /* First try 32 bits */
185 bmih.biBitCount = 32;
186 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
187 ok(hbm != NULL, "CreateDIBitmap failed\n");
188 test_bitmap_info(hbm, screen_depth, &bmih);
189 DeleteObject(hbm);
190
191 /* Then 16 */
192 bmih.biBitCount = 16;
193 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
194 ok(hbm != NULL, "CreateDIBitmap failed\n");
195 test_bitmap_info(hbm, screen_depth, &bmih);
196 DeleteObject(hbm);
197
198 /* Then 1 */
199 bmih.biBitCount = 1;
200 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
201 ok(hbm != NULL, "CreateDIBitmap failed\n");
202 test_bitmap_info(hbm, screen_depth, &bmih);
203 DeleteObject(hbm);
204
205 SelectObject(hdcmem, hbm_old);
206 DeleteObject(hbm_colour);
207 DeleteDC(hdcmem);
208
209 /* If hdc == 0 then we get a 1 bpp bitmap */
210 if (!is_win9x) {
211 bmih.biBitCount = 32;
212 hbm = CreateDIBitmap(0, &bmih, 0, NULL, NULL, 0);
213 ok(hbm != NULL, "CreateDIBitmap failed\n");
214 test_bitmap_info(hbm, 1, &bmih);
215 DeleteObject(hbm);
216 }
217
218 ReleaseDC(0, hdc);
219 }
220
221 static INT DIB_GetWidthBytes( int width, int bpp )
222 {
223 int words;
224
225 switch (bpp)
226 {
227 case 1: words = (width + 31) / 32; break;
228 case 4: words = (width + 7) / 8; break;
229 case 8: words = (width + 3) / 4; break;
230 case 15:
231 case 16: words = (width + 1) / 2; break;
232 case 24: words = (width * 3 + 3)/4; break;
233 case 32: words = width; break;
234
235 default:
236 words=0;
237 trace("Unknown depth %d, please report.\n", bpp );
238 assert(0);
239 break;
240 }
241 return 4 * words;
242 }
243
244 static void test_dib_info(HBITMAP hbm, const void *bits, const BITMAPINFOHEADER *bmih)
245 {
246 BITMAP bm;
247 DIBSECTION ds;
248 INT ret, width_bytes;
249 BYTE *buf;
250
251 ret = GetObject(hbm, sizeof(bm), &bm);
252 ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
253
254 ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
255 ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
256 ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
257 width_bytes = DIB_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
258 ok(bm.bmWidthBytes == width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, width_bytes);
259 ok(bm.bmPlanes == bmih->biPlanes, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
260 ok(bm.bmBitsPixel == bmih->biBitCount, "bm.bmBitsPixel %d != %d\n", bm.bmBitsPixel, bmih->biBitCount);
261 ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits);
262
263 buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight + 4096);
264
265 width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
266
267 /* GetBitmapBits returns not 32-bit aligned data */
268 ret = GetBitmapBits(hbm, 0, NULL);
269 ok(ret == width_bytes * bm.bmHeight, "%d != %d\n", ret, width_bytes * bm.bmHeight);
270
271 memset(buf, 0xAA, bm.bmWidthBytes * bm.bmHeight + 4096);
272 ret = GetBitmapBits(hbm, bm.bmWidthBytes * bm.bmHeight + 4096, buf);
273 ok(ret == width_bytes * bm.bmHeight, "%d != %d\n", ret, width_bytes * bm.bmHeight);
274
275 HeapFree(GetProcessHeap(), 0, buf);
276
277 /* test various buffer sizes for GetObject */
278 memset(&ds, 0xAA, sizeof(ds));
279 ret = GetObject(hbm, sizeof(bm) * 2, &bm);
280 ok(ret == sizeof(bm), "wrong size %d\n", ret);
281 ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
282 ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
283 ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits);
284
285 ret = GetObject(hbm, sizeof(bm) / 2, &bm);
286 ok(ret == 0, "%d != 0\n", ret);
287
288 ret = GetObject(hbm, 0, &bm);
289 ok(ret == 0, "%d != 0\n", ret);
290
291 ret = GetObject(hbm, 1, &bm);
292 ok(ret == 0, "%d != 0\n", ret);
293
294 /* test various buffer sizes for GetObject */
295 ret = GetObject(hbm, 0, NULL);
296 ok(ret == sizeof(bm), "wrong size %d\n", ret);
297
298 memset(&ds, 0xAA, sizeof(ds));
299 ret = GetObject(hbm, sizeof(ds) * 2, &ds);
300 ok(ret == sizeof(ds), "wrong size %d\n", ret);
301
302 ok(ds.dsBm.bmBits == bits, "wrong bm.bmBits %p != %p\n", ds.dsBm.bmBits, bits);
303 ok(ds.dsBmih.biSizeImage == ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight, "%lu != %u\n",
304 ds.dsBmih.biSizeImage, ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight);
305 ok(bmih->biSizeImage == 0, "%lu != 0\n", bmih->biSizeImage);
306 ds.dsBmih.biSizeImage = 0;
307
308 ok(ds.dsBmih.biSize == bmih->biSize, "%lu != %lu\n", ds.dsBmih.biSize, bmih->biSize);
309 ok(ds.dsBmih.biWidth == bmih->biWidth, "%lu != %lu\n", ds.dsBmih.biWidth, bmih->biWidth);
310 ok(ds.dsBmih.biHeight == bmih->biHeight, "%lu != %lu\n", ds.dsBmih.biHeight, bmih->biHeight);
311 ok(ds.dsBmih.biPlanes == bmih->biPlanes, "%u != %u\n", ds.dsBmih.biPlanes, bmih->biPlanes);
312 ok(ds.dsBmih.biBitCount == bmih->biBitCount, "%u != %u\n", ds.dsBmih.biBitCount, bmih->biBitCount);
313 ok(ds.dsBmih.biCompression == bmih->biCompression, "%lu != %lu\n", ds.dsBmih.biCompression, bmih->biCompression);
314 ok(ds.dsBmih.biSizeImage == bmih->biSizeImage, "%lu != %lu\n", ds.dsBmih.biSizeImage, bmih->biSizeImage);
315 ok(ds.dsBmih.biXPelsPerMeter == bmih->biXPelsPerMeter, "%lu != %lu\n", ds.dsBmih.biXPelsPerMeter, bmih->biXPelsPerMeter);
316 ok(ds.dsBmih.biYPelsPerMeter == bmih->biYPelsPerMeter, "%lu != %lu\n", ds.dsBmih.biYPelsPerMeter, bmih->biYPelsPerMeter);
317
318 memset(&ds, 0xAA, sizeof(ds));
319 ret = GetObject(hbm, sizeof(ds) - 4, &ds);
320 ok(ret == sizeof(ds.dsBm), "wrong size %d\n", ret);
321 ok(ds.dsBm.bmWidth == bmih->biWidth, "%lu != %lu\n", ds.dsBmih.biWidth, bmih->biWidth);
322 ok(ds.dsBm.bmHeight == bmih->biHeight, "%lu != %lu\n", ds.dsBmih.biHeight, bmih->biHeight);
323 ok(ds.dsBm.bmBits == bits, "%p != %p\n", ds.dsBm.bmBits, bits);
324
325 ret = GetObject(hbm, 0, &ds);
326 ok(ret == 0, "%d != 0\n", ret);
327
328 ret = GetObject(hbm, 1, &ds);
329 ok(ret == 0, "%d != 0\n", ret);
330 }
331
332 #define test_color_todo(got, exp, txt, todo) \
333 if (!todo && got != exp && screen_depth < 24) { \
334 todo_wine ok(0, #txt " failed at %d-bit screen depth: got 0x%06x expected 0x%06x - skipping DIB tests\n", \
335 screen_depth, (UINT)got, (UINT)exp); \
336 return; \
337 } else if (todo) todo_wine { ok(got == exp, #txt " failed: got 0x%06x expected 0x%06x\n", (UINT)got, (UINT)exp); } \
338 else ok(got == exp, #txt " failed: got 0x%06x expected 0x%06x\n", (UINT)got, (UINT)exp) \
339
340 #define test_color(hdc, color, exp, todo_setp, todo_getp) \
341 { \
342 COLORREF c; \
343 c = SetPixel(hdc, 0, 0, color); \
344 if (!is_win9x) { test_color_todo(c, exp, SetPixel, todo_setp); } \
345 c = GetPixel(hdc, 0, 0); \
346 test_color_todo(c, exp, GetPixel, todo_getp); \
347 }
348
349 static void test_dibsections(void)
350 {
351 HDC hdc, hdcmem, hdcmem2;
352 HBITMAP hdib, oldbm, hdib2, oldbm2;
353 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
354 char bcibuf[sizeof(BITMAPCOREINFO) + 256 * sizeof(RGBTRIPLE)];
355 BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
356 BITMAPCOREINFO *pbci = (BITMAPCOREINFO *)bcibuf;
357 HBITMAP hcoredib;
358 char coreBits[256];
359 BYTE *bits;
360 RGBQUAD rgb[256];
361 int ret;
362 char logpalbuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
363 LOGPALETTE *plogpal = (LOGPALETTE*)logpalbuf;
364 WORD *index;
365 DWORD *bits32;
366 HPALETTE hpal, oldpal;
367 DIBSECTION dibsec;
368 COLORREF c0, c1;
369 int i;
370 int screen_depth;
371 MEMORY_BASIC_INFORMATION info;
372
373 hdc = GetDC(0);
374 screen_depth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
375
376 memset(pbmi, 0, sizeof(bmibuf));
377 pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
378 pbmi->bmiHeader.biHeight = 100;
379 pbmi->bmiHeader.biWidth = 512;
380 pbmi->bmiHeader.biBitCount = 24;
381 pbmi->bmiHeader.biPlanes = 1;
382 pbmi->bmiHeader.biCompression = BI_RGB;
383
384 SetLastError(0xdeadbeef);
385 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
386 ok(hdib != NULL, "CreateDIBSection error %ld\n", GetLastError());
387 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n");
388 ok(dibsec.dsBm.bmBits == bits, "dibsec.dsBits %p != bits %p\n", dibsec.dsBm.bmBits, bits);
389
390 /* test the DIB memory */
391 ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info),
392 "VirtualQuery failed\n");
393 ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits);
394 ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits);
395 ok(info.AllocationProtect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.AllocationProtect);
396 ok(info.RegionSize == 0x26000, "0x%lx != 0x26000\n", info.RegionSize);
397 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State);
398 ok(info.Protect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.Protect);
399 ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type);
400
401 test_dib_info(hdib, bits, &pbmi->bmiHeader);
402 DeleteObject(hdib);
403
404 pbmi->bmiHeader.biBitCount = 8;
405 pbmi->bmiHeader.biCompression = BI_RLE8;
406 SetLastError(0xdeadbeef);
407 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
408 ok(hdib == NULL, "CreateDIBSection should fail when asked to create a compressed DIB section\n");
409 ok(GetLastError() == 0xdeadbeef, "wrong error %ld\n", GetLastError());
410
411 pbmi->bmiHeader.biBitCount = 16;
412 pbmi->bmiHeader.biCompression = BI_BITFIELDS;
413 ((PDWORD)pbmi->bmiColors)[0] = 0xf800;
414 ((PDWORD)pbmi->bmiColors)[1] = 0x07e0;
415 ((PDWORD)pbmi->bmiColors)[2] = 0x001f;
416 SetLastError(0xdeadbeef);
417 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
418 ok(hdib != NULL, "CreateDIBSection error %ld\n", GetLastError());
419
420 /* test the DIB memory */
421 ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info),
422 "VirtualQuery failed\n");
423 ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits);
424 ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits);
425 ok(info.AllocationProtect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.AllocationProtect);
426 ok(info.RegionSize == 0x19000, "0x%lx != 0x19000\n", info.RegionSize);
427 ok(info.State == MEM_COMMIT, "%lx != MEM_COMMIT\n", info.State);
428 ok(info.Protect == PAGE_READWRITE, "%lx != PAGE_READWRITE\n", info.Protect);
429 ok(info.Type == MEM_PRIVATE, "%lx != MEM_PRIVATE\n", info.Type);
430
431 test_dib_info(hdib, bits, &pbmi->bmiHeader);
432 DeleteObject(hdib);
433
434 memset(pbmi, 0, sizeof(bmibuf));
435 pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
436 pbmi->bmiHeader.biHeight = 16;
437 pbmi->bmiHeader.biWidth = 16;
438 pbmi->bmiHeader.biBitCount = 1;
439 pbmi->bmiHeader.biPlanes = 1;
440 pbmi->bmiHeader.biCompression = BI_RGB;
441 pbmi->bmiColors[0].rgbRed = 0xff;
442 pbmi->bmiColors[0].rgbGreen = 0;
443 pbmi->bmiColors[0].rgbBlue = 0;
444 pbmi->bmiColors[1].rgbRed = 0;
445 pbmi->bmiColors[1].rgbGreen = 0;
446 pbmi->bmiColors[1].rgbBlue = 0xff;
447
448 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
449 ok(hdib != NULL, "CreateDIBSection failed\n");
450 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n");
451 ok(dibsec.dsBmih.biClrUsed == 2,
452 "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 2);
453
454 /* Test if the old BITMAPCOREINFO structure is supported */
455
456 pbci->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
457 pbci->bmciHeader.bcBitCount = 0;
458
459 if (!is_win9x) {
460 ret = GetDIBits(hdc, hdib, 0, 16, NULL, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
461 ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
462 ok((pbci->bmciHeader.bcWidth == 16) && (pbci->bmciHeader.bcHeight == 16)
463 && (pbci->bmciHeader.bcBitCount == 1) && (pbci->bmciHeader.bcPlanes == 1),
464 "GetDIBits did't fill in the BITMAPCOREHEADER structure properly\n");
465
466 ret = GetDIBits(hdc, hdib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
467 ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
468 ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
469 (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
470 (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
471 "The color table has not been translated to the old BITMAPCOREINFO format\n");
472
473 hcoredib = CreateDIBSection(hdc, (BITMAPINFO*) pbci, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
474 ok(hcoredib != NULL, "CreateDIBSection failed with a BITMAPCOREINFO\n");
475
476 ZeroMemory(pbci->bmciColors, 256 * sizeof(RGBTRIPLE));
477 ret = GetDIBits(hdc, hcoredib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
478 ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
479 ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
480 (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
481 (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
482 "The color table has not been translated to the old BITMAPCOREINFO format\n");
483
484 DeleteObject(hcoredib);
485 }
486
487 hdcmem = CreateCompatibleDC(hdc);
488 oldbm = SelectObject(hdcmem, hdib);
489
490 ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
491 ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
492 ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
493 "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
494 rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
495 rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
496
497 c0 = RGB(pbmi->bmiColors[0].rgbRed, pbmi->bmiColors[0].rgbGreen, pbmi->bmiColors[0].rgbBlue);
498 c1 = RGB(pbmi->bmiColors[1].rgbRed, pbmi->bmiColors[1].rgbGreen, pbmi->bmiColors[1].rgbBlue);
499
500 test_color(hdcmem, DIBINDEX(0), c0, 0, 1);
501 test_color(hdcmem, DIBINDEX(1), c1, 0, 1);
502 test_color(hdcmem, DIBINDEX(2), c0, 1, 1);
503 test_color(hdcmem, PALETTEINDEX(0), c0, 1, 1);
504 test_color(hdcmem, PALETTEINDEX(1), c0, 1, 1);
505 test_color(hdcmem, PALETTEINDEX(2), c0, 1, 1);
506 test_color(hdcmem, PALETTERGB(pbmi->bmiColors[0].rgbRed, pbmi->bmiColors[0].rgbGreen,
507 pbmi->bmiColors[0].rgbBlue), c0, 1, 1);
508 test_color(hdcmem, PALETTERGB(pbmi->bmiColors[1].rgbRed, pbmi->bmiColors[1].rgbGreen,
509 pbmi->bmiColors[1].rgbBlue), c1, 1, 1);
510 test_color(hdcmem, PALETTERGB(0, 0, 0), c0, 1, 1);
511 test_color(hdcmem, PALETTERGB(0xff, 0xff, 0xff), c0, 1, 1);
512 test_color(hdcmem, PALETTERGB(0, 0, 0xfe), c1, 1, 1);
513
514 SelectObject(hdcmem, oldbm);
515 DeleteObject(hdib);
516
517 pbmi->bmiColors[0].rgbRed = 0xff;
518 pbmi->bmiColors[0].rgbGreen = 0xff;
519 pbmi->bmiColors[0].rgbBlue = 0xff;
520 pbmi->bmiColors[1].rgbRed = 0;
521 pbmi->bmiColors[1].rgbGreen = 0;
522 pbmi->bmiColors[1].rgbBlue = 0;
523
524 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
525 ok(hdib != NULL, "CreateDIBSection failed\n");
526
527 test_dib_info(hdib, bits, &pbmi->bmiHeader);
528
529 oldbm = SelectObject(hdcmem, hdib);
530
531 ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
532 ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
533 ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
534 "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
535 rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
536 rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
537
538 SelectObject(hdcmem, oldbm);
539 test_dib_info(hdib, bits, &pbmi->bmiHeader);
540 DeleteObject(hdib);
541
542 pbmi->bmiHeader.biBitCount = 4;
543 for (i = 0; i < 16; i++) {
544 pbmi->bmiColors[i].rgbRed = i;
545 pbmi->bmiColors[i].rgbGreen = 16-i;
546 pbmi->bmiColors[i].rgbBlue = 0;
547 }
548 hdib = CreateDIBSection(hdcmem, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
549 ok(hdib != NULL, "CreateDIBSection failed\n");
550 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
551 ok(dibsec.dsBmih.biClrUsed == 16,
552 "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 16);
553 test_dib_info(hdib, bits, &pbmi->bmiHeader);
554 DeleteObject(hdib);
555
556 pbmi->bmiHeader.biBitCount = 8;
557
558 for (i = 0; i < 128; i++) {
559 pbmi->bmiColors[i].rgbRed = 255 - i * 2;
560 pbmi->bmiColors[i].rgbGreen = i * 2;
561 pbmi->bmiColors[i].rgbBlue = 0;
562 pbmi->bmiColors[255 - i].rgbRed = 0;
563 pbmi->bmiColors[255 - i].rgbGreen = i * 2;
564 pbmi->bmiColors[255 - i].rgbBlue = 255 - i * 2;
565 }
566 hdib = CreateDIBSection(hdcmem, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
567 ok(hdib != NULL, "CreateDIBSection failed\n");
568 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
569 ok(dibsec.dsBmih.biClrUsed == 256,
570 "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 256);
571
572 oldbm = SelectObject(hdcmem, hdib);
573
574 for (i = 0; i < 256; i++) {
575 test_color(hdcmem, DIBINDEX(i),
576 RGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue), 0, 0);
577 test_color(hdcmem, PALETTERGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue),
578 RGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue), 0, 0);
579 }
580
581 SelectObject(hdcmem, oldbm);
582 test_dib_info(hdib, bits, &pbmi->bmiHeader);
583 DeleteObject(hdib);
584
585 pbmi->bmiHeader.biBitCount = 1;
586
587 /* Now create a palette and a palette indexed dib section */
588 memset(plogpal, 0, sizeof(logpalbuf));
589 plogpal->palVersion = 0x300;
590 plogpal->palNumEntries = 2;
591 plogpal->palPalEntry[0].peRed = 0xff;
592 plogpal->palPalEntry[0].peBlue = 0xff;
593 plogpal->palPalEntry[1].peGreen = 0xff;
594
595 index = (WORD*)pbmi->bmiColors;
596 *index++ = 0;
597 *index = 1;
598 hpal = CreatePalette(plogpal);
599 ok(hpal != NULL, "CreatePalette failed\n");
600 oldpal = SelectPalette(hdc, hpal, TRUE);
601 hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0);
602 ok(hdib != NULL, "CreateDIBSection failed\n");
603 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
604 ok(dibsec.dsBmih.biClrUsed == 2,
605 "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 2);
606
607 /* The colour table has already been grabbed from the dc, so we select back the
608 old palette */
609
610 SelectPalette(hdc, oldpal, TRUE);
611 oldbm = SelectObject(hdcmem, hdib);
612 oldpal = SelectPalette(hdcmem, hpal, TRUE);
613
614 ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
615 ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
616 ok(rgb[0].rgbRed == 0xff && rgb[0].rgbBlue == 0xff && rgb[0].rgbGreen == 0 &&
617 rgb[1].rgbRed == 0 && rgb[1].rgbBlue == 0 && rgb[1].rgbGreen == 0xff,
618 "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
619 rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
620 rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
621
622 c0 = RGB(plogpal->palPalEntry[0].peRed, plogpal->palPalEntry[0].peGreen, plogpal->palPalEntry[0].peBlue);
623 c1 = RGB(plogpal->palPalEntry[1].peRed, plogpal->palPalEntry[1].peGreen, plogpal->palPalEntry[1].peBlue);
624
625 test_color(hdcmem, DIBINDEX(0), c0, 0, 1);
626 test_color(hdcmem, DIBINDEX(1), c1, 0, 1);
627 test_color(hdcmem, DIBINDEX(2), c0, 1, 1);
628 test_color(hdcmem, PALETTEINDEX(0), c0, 0, 1);
629 test_color(hdcmem, PALETTEINDEX(1), c1, 0, 1);
630 test_color(hdcmem, PALETTEINDEX(2), c0, 1, 1);
631 test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[0].peRed, plogpal->palPalEntry[0].peGreen,
632 plogpal->palPalEntry[0].peBlue), c0, 1, 1);
633 test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[1].peRed, plogpal->palPalEntry[1].peGreen,
634 plogpal->palPalEntry[1].peBlue), c1, 1, 1);
635 test_color(hdcmem, PALETTERGB(0, 0, 0), c1, 1, 1);
636 test_color(hdcmem, PALETTERGB(0xff, 0xff, 0xff), c0, 1, 1);
637 test_color(hdcmem, PALETTERGB(0, 0, 0xfe), c0, 1, 1);
638 test_color(hdcmem, PALETTERGB(0, 1, 0), c1, 1, 1);
639 test_color(hdcmem, PALETTERGB(0x3f, 0, 0x3f), c1, 1, 1);
640 test_color(hdcmem, PALETTERGB(0x40, 0, 0x40), c0, 1, 1);
641
642 /* Bottom and 2nd row from top green, everything else magenta */
643 bits[0] = bits[1] = 0xff;
644 bits[13 * 4] = bits[13*4 + 1] = 0xff;
645
646 test_dib_info(hdib, bits, &pbmi->bmiHeader);
647
648 pbmi->bmiHeader.biBitCount = 32;
649
650 hdib2 = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, (void **)&bits32, NULL, 0);
651 ok(hdib2 != NULL, "CreateDIBSection failed\n");
652 hdcmem2 = CreateCompatibleDC(hdc);
653 oldbm2 = SelectObject(hdcmem2, hdib2);
654
655 BitBlt(hdcmem2, 0, 0, 16,16, hdcmem, 0, 0, SRCCOPY);
656
657 ok(bits32[0] == 0xff00, "lower left pixel is %08lx\n", bits32[0]);
658 ok(bits32[17] == 0xff00ff, "bottom but one, left pixel is %08lx\n", bits32[17]);
659
660 SelectObject(hdcmem2, oldbm2);
661 test_dib_info(hdib2, bits32, &pbmi->bmiHeader);
662 DeleteObject(hdib2);
663
664 SelectObject(hdcmem, oldbm);
665 SelectObject(hdcmem, oldpal);
666 DeleteObject(hdib);
667 DeleteObject(hpal);
668
669
670 pbmi->bmiHeader.biBitCount = 8;
671
672 memset(plogpal, 0, sizeof(logpalbuf));
673 plogpal->palVersion = 0x300;
674 plogpal->palNumEntries = 256;
675
676 for (i = 0; i < 128; i++) {
677 plogpal->palPalEntry[i].peRed = 255 - i * 2;
678 plogpal->palPalEntry[i].peBlue = i * 2;
679 plogpal->palPalEntry[i].peGreen = 0;
680 plogpal->palPalEntry[255 - i].peRed = 0;
681 plogpal->palPalEntry[255 - i].peGreen = i * 2;
682 plogpal->palPalEntry[255 - i].peBlue = 255 - i * 2;
683 }
684
685 index = (WORD*)pbmi->bmiColors;
686 for (i = 0; i < 256; i++) {
687 *index++ = i;
688 }
689
690 hpal = CreatePalette(plogpal);
691 ok(hpal != NULL, "CreatePalette failed\n");
692 oldpal = SelectPalette(hdc, hpal, TRUE);
693 hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0);
694 ok(hdib != NULL, "CreateDIBSection failed\n");
695 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
696 ok(dibsec.dsBmih.biClrUsed == 256,
697 "created DIBSection: wrong biClrUsed field: %lu, should be: %u\n", dibsec.dsBmih.biClrUsed, 256);
698
699 test_dib_info(hdib, bits, &pbmi->bmiHeader);
700
701 SelectPalette(hdc, oldpal, TRUE);
702 oldbm = SelectObject(hdcmem, hdib);
703 oldpal = SelectPalette(hdcmem, hpal, TRUE);
704
705 ret = GetDIBColorTable(hdcmem, 0, 256, rgb);
706 ok(ret == 256, "GetDIBColorTable returned %d\n", ret);
707 for (i = 0; i < 256; i++) {
708 ok(rgb[i].rgbRed == plogpal->palPalEntry[i].peRed &&
709 rgb[i].rgbBlue == plogpal->palPalEntry[i].peBlue &&
710 rgb[i].rgbGreen == plogpal->palPalEntry[i].peGreen,
711 "GetDIBColorTable returns table %d: r%02x g%02x b%02x res%02x\n",
712 i, rgb[i].rgbRed, rgb[i].rgbGreen, rgb[i].rgbBlue, rgb[i].rgbReserved);
713 }
714
715 for (i = 0; i < 256; i++) {
716 test_color(hdcmem, DIBINDEX(i),
717 RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
718 test_color(hdcmem, PALETTEINDEX(i),
719 RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
720 test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue),
721 RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
722 }
723
724 SelectPalette(hdcmem, oldpal, TRUE);
725 SelectObject(hdcmem, oldbm);
726 DeleteObject(hdib);
727 DeleteObject(hpal);
728
729
730 DeleteDC(hdcmem);
731 ReleaseDC(0, hdc);
732 }
733
734 void test_mono_dibsection(void)
735 {
736 HDC hdc, memdc;
737 HBITMAP old_bm, mono_ds;
738 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
739 BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
740 BYTE bits[10 * 4];
741 BYTE *ds_bits;
742 int num;
743
744 hdc = GetDC(0);
745
746 memdc = CreateCompatibleDC(hdc);
747
748 memset(pbmi, 0, sizeof(bmibuf));
749 pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
750 pbmi->bmiHeader.biHeight = 10;
751 pbmi->bmiHeader.biWidth = 10;
752 pbmi->bmiHeader.biBitCount = 1;
753 pbmi->bmiHeader.biPlanes = 1;
754 pbmi->bmiHeader.biCompression = BI_RGB;
755 pbmi->bmiColors[0].rgbRed = 0xff;
756 pbmi->bmiColors[0].rgbGreen = 0xff;
757 pbmi->bmiColors[0].rgbBlue = 0xff;
758 pbmi->bmiColors[1].rgbRed = 0x0;
759 pbmi->bmiColors[1].rgbGreen = 0x0;
760 pbmi->bmiColors[1].rgbBlue = 0x0;
761
762 /*
763 * First dib section is 'inverted' ie color[0] is white, color[1] is black
764 */
765
766 mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
767 ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
768 old_bm = SelectObject(memdc, mono_ds);
769
770 /* black border, white interior */
771 Rectangle(memdc, 0, 0, 10, 10);
772 ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
773 ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
774
775 /* SetDIBitsToDevice with an inverted bmi -> inverted dib section */
776
777 memset(bits, 0, sizeof(bits));
778 bits[0] = 0xaa;
779
780 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
781 ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
782
783 /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
784
785 pbmi->bmiColors[0].rgbRed = 0x0;
786 pbmi->bmiColors[0].rgbGreen = 0x0;
787 pbmi->bmiColors[0].rgbBlue = 0x0;
788 pbmi->bmiColors[1].rgbRed = 0xff;
789 pbmi->bmiColors[1].rgbGreen = 0xff;
790 pbmi->bmiColors[1].rgbBlue = 0xff;
791
792 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
793 ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
794
795 SelectObject(memdc, old_bm);
796 DeleteObject(mono_ds);
797
798 /*
799 * Next dib section is 'normal' ie color[0] is black, color[1] is white
800 */
801
802 pbmi->bmiColors[0].rgbRed = 0x0;
803 pbmi->bmiColors[0].rgbGreen = 0x0;
804 pbmi->bmiColors[0].rgbBlue = 0x0;
805 pbmi->bmiColors[1].rgbRed = 0xff;
806 pbmi->bmiColors[1].rgbGreen = 0xff;
807 pbmi->bmiColors[1].rgbBlue = 0xff;
808
809 mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
810 ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
811 old_bm = SelectObject(memdc, mono_ds);
812
813 /* black border, white interior */
814 Rectangle(memdc, 0, 0, 10, 10);
815 ok(ds_bits[0] == 0x00, "out_bits %02x\n", ds_bits[0]);
816 ok(ds_bits[4] == 0x7f, "out_bits %02x\n", ds_bits[4]);
817
818 /* SetDIBitsToDevice with a normal bmi -> normal dib section */
819
820 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
821 ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
822
823 /* SetDIBitsToDevice with a inverted bmi -> normal dib section */
824
825 pbmi->bmiColors[0].rgbRed = 0xff;
826 pbmi->bmiColors[0].rgbGreen = 0xff;
827 pbmi->bmiColors[0].rgbBlue = 0xff;
828 pbmi->bmiColors[1].rgbRed = 0x0;
829 pbmi->bmiColors[1].rgbGreen = 0x0;
830 pbmi->bmiColors[1].rgbBlue = 0x0;
831
832 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
833 ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
834
835 /*
836 * Take that 'normal' dibsection and change its colour table to an 'inverted' one
837 */
838
839 pbmi->bmiColors[0].rgbRed = 0xff;
840 pbmi->bmiColors[0].rgbGreen = 0xff;
841 pbmi->bmiColors[0].rgbBlue = 0xff;
842 pbmi->bmiColors[1].rgbRed = 0x0;
843 pbmi->bmiColors[1].rgbGreen = 0x0;
844 pbmi->bmiColors[1].rgbBlue = 0x0;
845 num = SetDIBColorTable(memdc, 0, 2, pbmi->bmiColors);
846 ok(num == 2, "num = %d\n", num);
847
848 /* black border, white interior */
849 Rectangle(memdc, 0, 0, 10, 10);
850 todo_wine {
851 ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
852 ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
853 }
854 /* SetDIBitsToDevice with an inverted bmi -> inverted dib section */
855
856 memset(bits, 0, sizeof(bits));
857 bits[0] = 0xaa;
858
859 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
860 ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
861
862 /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
863
864 pbmi->bmiColors[0].rgbRed = 0x0;
865 pbmi->bmiColors[0].rgbGreen = 0x0;
866 pbmi->bmiColors[0].rgbBlue = 0x0;
867 pbmi->bmiColors[1].rgbRed = 0xff;
868 pbmi->bmiColors[1].rgbGreen = 0xff;
869 pbmi->bmiColors[1].rgbBlue = 0xff;
870
871 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
872 ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
873
874 SelectObject(memdc, old_bm);
875 DeleteObject(mono_ds);
876
877 /*
878 * Now a dib section with a strange colour map just for fun. This behaves just like an inverted one.
879 */
880
881 pbmi->bmiColors[0].rgbRed = 0xff;
882 pbmi->bmiColors[0].rgbGreen = 0x0;
883 pbmi->bmiColors[0].rgbBlue = 0x0;
884 pbmi->bmiColors[1].rgbRed = 0xfe;
885 pbmi->bmiColors[1].rgbGreen = 0x0;
886 pbmi->bmiColors[1].rgbBlue = 0x0;
887
888 mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
889 ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
890 old_bm = SelectObject(memdc, mono_ds);
891
892 /* black border, white interior */
893 Rectangle(memdc, 0, 0, 10, 10);
894 ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
895 ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
896
897 /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
898
899 pbmi->bmiColors[0].rgbRed = 0x0;
900 pbmi->bmiColors[0].rgbGreen = 0x0;
901 pbmi->bmiColors[0].rgbBlue = 0x0;
902 pbmi->bmiColors[1].rgbRed = 0xff;
903 pbmi->bmiColors[1].rgbGreen = 0xff;
904 pbmi->bmiColors[1].rgbBlue = 0xff;
905
906 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
907 ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
908
909 /* SetDIBitsToDevice with a inverted bmi -> inverted dib section */
910
911 pbmi->bmiColors[0].rgbRed = 0xff;
912 pbmi->bmiColors[0].rgbGreen = 0xff;
913 pbmi->bmiColors[0].rgbBlue = 0xff;
914 pbmi->bmiColors[1].rgbRed = 0x0;
915 pbmi->bmiColors[1].rgbGreen = 0x0;
916 pbmi->bmiColors[1].rgbBlue = 0x0;
917
918 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
919 ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
920
921 SelectObject(memdc, old_bm);
922 DeleteObject(mono_ds);
923
924 DeleteDC(memdc);
925 ReleaseDC(0, hdc);
926 }
927
928 static void test_bitmap(void)
929 {
930 char buf[256], buf_cmp[256];
931 HBITMAP hbmp, hbmp_old;
932 HDC hdc;
933 BITMAP bm;
934 INT ret;
935
936 hdc = CreateCompatibleDC(0);
937 assert(hdc != 0);
938
939 hbmp = CreateBitmap(15, 15, 1, 1, NULL);
940 assert(hbmp != NULL);
941
942 ret = GetObject(hbmp, sizeof(bm), &bm);
943 ok(ret == sizeof(bm), "wrong size %d\n", ret);
944
945 ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
946 ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth);
947 ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight);
948 ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes);
949 ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
950 ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel);
951 ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
952
953 assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight);
954 assert(sizeof(buf) == sizeof(buf_cmp));
955
956 ret = GetBitmapBits(hbmp, 0, NULL);
957 ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
958
959 memset(buf_cmp, 0xAA, sizeof(buf_cmp));
960 memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
961
962 memset(buf, 0xAA, sizeof(buf));
963 ret = GetBitmapBits(hbmp, sizeof(buf), buf);
964 ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
965 ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
966
967 hbmp_old = SelectObject(hdc, hbmp);
968
969 ret = GetObject(hbmp, sizeof(bm), &bm);
970 ok(ret == sizeof(bm), "wrong size %d\n", ret);
971
972 ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
973 ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth);
974 ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight);
975 ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes);
976 ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
977 ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel);
978 ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
979
980 memset(buf, 0xAA, sizeof(buf));
981 ret = GetBitmapBits(hbmp, sizeof(buf), buf);
982 ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
983 ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
984
985 hbmp_old = SelectObject(hdc, hbmp_old);
986 ok(hbmp_old == hbmp, "wrong old bitmap %p\n", hbmp_old);
987
988 /* test various buffer sizes for GetObject */
989 ret = GetObject(hbmp, sizeof(bm) * 2, &bm);
990 ok(ret == sizeof(bm), "wrong size %d\n", ret);
991
992 ret = GetObject(hbmp, sizeof(bm) / 2, &bm);
993 ok(ret == 0, "%d != 0\n", ret);
994
995 ret = GetObject(hbmp, 0, &bm);
996 ok(ret == 0, "%d != 0\n", ret);
997
998 ret = GetObject(hbmp, 1, &bm);
999 ok(ret == 0, "%d != 0\n", ret);
1000
1001 DeleteObject(hbmp);
1002 DeleteDC(hdc);
1003 }
1004
1005 static void test_bmBits(void)
1006 {
1007 BYTE bits[4];
1008 HBITMAP hbmp;
1009 BITMAP bmp;
1010
1011 memset(bits, 0, sizeof(bits));
1012 hbmp = CreateBitmap(2, 2, 1, 4, bits);
1013 ok(hbmp != NULL, "CreateBitmap failed\n");
1014
1015 memset(&bmp, 0xFF, sizeof(bmp));
1016 ok(GetObject(hbmp, sizeof(bmp), &bmp) == sizeof(bmp),
1017 "GetObject failed or returned a wrong structure size\n");
1018 ok(!bmp.bmBits, "bmBits must be NULL for device-dependent bitmaps\n");
1019
1020 DeleteObject(hbmp);
1021 }
1022
1023 static void test_GetDIBits_selected_DIB(UINT bpp)
1024 {
1025 HBITMAP dib;
1026 BITMAPINFO * info;
1027 BITMAPINFO * info2;
1028 void * bits;
1029 void * bits2;
1030 UINT dib_size;
1031 HDC dib_dc, dc;
1032 HBITMAP old_bmp;
1033 BOOL equalContents;
1034 UINT i;
1035 int res;
1036
1037 /* Create a DIB section with a color table */
1038
1039 info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD));
1040 info2 = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD));
1041 assert(info);
1042 assert(info2);
1043
1044 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1045
1046 /* Choose width and height such that the row length (in bytes)
1047 is a multiple of 4 (makes things easier) */
1048 info->bmiHeader.biWidth = 32;
1049 info->bmiHeader.biHeight = 32;
1050 info->bmiHeader.biPlanes = 1;
1051 info->bmiHeader.biBitCount = bpp;
1052 info->bmiHeader.biCompression = BI_RGB;
1053
1054 for (i=0; i < (1 << bpp); i++)
1055 {
1056 BYTE c = i * (1 << (8 - bpp));
1057 info->bmiColors[i].rgbRed = c;
1058 info->bmiColors[i].rgbGreen = c;
1059 info->bmiColors[i].rgbBlue = c;
1060 info->bmiColors[i].rgbReserved = 0;
1061 }
1062
1063 dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
1064 assert(dib);
1065 dib_size = bpp * (info->bmiHeader.biWidth * info->bmiHeader.biHeight) / 8;
1066
1067 /* Set the bits of the DIB section */
1068 for (i=0; i < dib_size; i++)
1069 {
1070 ((BYTE *)bits)[i] = i % 256;
1071 }
1072
1073 /* Select the DIB into a DC */
1074 dib_dc = CreateCompatibleDC(NULL);
1075 old_bmp = (HBITMAP) SelectObject(dib_dc, dib);
1076 dc = CreateCompatibleDC(NULL);
1077 bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dib_size);
1078 assert(bits2);
1079
1080 /* Copy the DIB attributes but not the color table */
1081 memcpy(info2, info, sizeof(BITMAPINFOHEADER));
1082
1083 res = GetDIBits(dc, dib, 0, info->bmiHeader.biHeight, bits2, info2, DIB_RGB_COLORS);
1084 ok(res, "GetDIBits failed\n");
1085
1086 /* Compare the color table and the bits */
1087 equalContents = TRUE;
1088 for (i=0; i < (1 << bpp); i++)
1089 {
1090 if ((info->bmiColors[i].rgbRed != info2->bmiColors[i].rgbRed)
1091 || (info->bmiColors[i].rgbGreen != info2->bmiColors[i].rgbGreen)
1092 || (info->bmiColors[i].rgbBlue != info2->bmiColors[i].rgbBlue)
1093 || (info->bmiColors[i].rgbReserved != info2->bmiColors[i].rgbReserved))
1094 {
1095 equalContents = FALSE;
1096 break;
1097 }
1098 }
1099 todo_wine
1100 {
1101 ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB color table\n");
1102 }
1103
1104 equalContents = TRUE;
1105 for (i=0; i < dib_size / sizeof(DWORD); i++)
1106 {
1107 if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i])
1108 {
1109 equalContents = FALSE;
1110 break;
1111 }
1112 }
1113 todo_wine
1114 {
1115 ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB bits\n");
1116 }
1117
1118 HeapFree(GetProcessHeap(), 0, bits2);
1119 DeleteDC(dc);
1120
1121 SelectObject(dib_dc, old_bmp);
1122 DeleteDC(dib_dc);
1123 DeleteObject(dib);
1124
1125 HeapFree(GetProcessHeap(), 0, info2);
1126 HeapFree(GetProcessHeap(), 0, info);
1127 }
1128
1129 static void test_GetDIBits_selected_DDB(BOOL monochrome)
1130 {
1131 HBITMAP ddb;
1132 BITMAPINFO * info;
1133 BITMAPINFO * info2;
1134 void * bits;
1135 void * bits2;
1136 HDC ddb_dc, dc;
1137 HBITMAP old_bmp;
1138 BOOL equalContents;
1139 UINT width, height;
1140 UINT bpp;
1141 UINT i, j;
1142 int res;
1143
1144 width = height = 16;
1145
1146 /* Create a DDB (device-dependent bitmap) */
1147 if (monochrome)
1148 {
1149 bpp = 1;
1150 ddb = CreateBitmap(width, height, 1, 1, NULL);
1151 }
1152 else
1153 {
1154 HDC screen_dc = GetDC(NULL);
1155 bpp = GetDeviceCaps(screen_dc, BITSPIXEL) * GetDeviceCaps(screen_dc, PLANES);
1156 ddb = CreateCompatibleBitmap(screen_dc, width, height);
1157 ReleaseDC(NULL, screen_dc);
1158 }
1159
1160 /* Set the pixels */
1161 ddb_dc = CreateCompatibleDC(NULL);
1162 old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb);
1163 for (i = 0; i < width; i++)
1164 {
1165 for (j=0; j < height; j++)
1166 {
1167 BYTE c = (i * width + j) % 256;
1168 SetPixelV(ddb_dc, i, j, RGB(c, c, c));
1169 }
1170 }
1171 SelectObject(ddb_dc, old_bmp);
1172
1173 info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1174 info2 = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1175 assert(info);
1176 assert(info2);
1177
1178 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1179 info->bmiHeader.biWidth = width;
1180 info->bmiHeader.biHeight = height;
1181 info->bmiHeader.biPlanes = 1;
1182 info->bmiHeader.biBitCount = bpp;
1183 info->bmiHeader.biCompression = BI_RGB;
1184
1185 dc = CreateCompatibleDC(NULL);
1186
1187 /* Fill in biSizeImage */
1188 GetDIBits(dc, ddb, 0, height, NULL, info, DIB_RGB_COLORS);
1189 ok(info->bmiHeader.biSizeImage != 0, "GetDIBits failed to get the DIB attributes\n");
1190
1191 bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage);
1192 bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage);
1193 assert(bits);
1194 assert(bits2);
1195
1196 /* Get the bits */
1197 res = GetDIBits(dc, ddb, 0, height, bits, info, DIB_RGB_COLORS);
1198 ok(res, "GetDIBits failed\n");
1199
1200 /* Copy the DIB attributes but not the color table */
1201 memcpy(info2, info, sizeof(BITMAPINFOHEADER));
1202
1203 /* Select the DDB into another DC */
1204 old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb);
1205
1206 /* Get the bits */
1207 res = GetDIBits(dc, ddb, 0, height, bits2, info2, DIB_RGB_COLORS);
1208 ok(res, "GetDIBits failed\n");
1209
1210 /* Compare the color table and the bits */
1211 if (bpp <= 8)
1212 {
1213 equalContents = TRUE;
1214 for (i=0; i < (1 << bpp); i++)
1215 {
1216 if ((info->bmiColors[i].rgbRed != info2->bmiColors[i].rgbRed)
1217 || (info->bmiColors[i].rgbGreen != info2->bmiColors[i].rgbGreen)
1218 || (info->bmiColors[i].rgbBlue != info2->bmiColors[i].rgbBlue)
1219 || (info->bmiColors[i].rgbReserved != info2->bmiColors[i].rgbReserved))
1220 {
1221 equalContents = FALSE;
1222 break;
1223 }
1224 }
1225 ok(equalContents, "GetDIBits with DDB selected in DC: Got a different color table\n");
1226 }
1227
1228 equalContents = TRUE;
1229 for (i=0; i < info->bmiHeader.biSizeImage / sizeof(DWORD); i++)
1230 {
1231 if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i])
1232 {
1233 equalContents = FALSE;
1234 }
1235 }
1236 ok(equalContents, "GetDIBits with DDB selected in DC: Got different DIB bits\n");
1237
1238 HeapFree(GetProcessHeap(), 0, bits2);
1239 HeapFree(GetProcessHeap(), 0, bits);
1240 DeleteDC(dc);
1241
1242 SelectObject(ddb_dc, old_bmp);
1243 DeleteDC(ddb_dc);
1244 DeleteObject(ddb);
1245
1246 HeapFree(GetProcessHeap(), 0, info2);
1247 HeapFree(GetProcessHeap(), 0, info);
1248 }
1249
1250 START_TEST(bitmap)
1251 {
1252 is_win9x = GetWindowLongPtrW(GetDesktopWindow(), GWLP_WNDPROC) == 0;
1253
1254 test_createdibitmap();
1255 test_dibsections();
1256 test_mono_dibsection();
1257 test_bitmap();
1258 test_bmBits();
1259 test_GetDIBits_selected_DIB(1);
1260 test_GetDIBits_selected_DIB(4);
1261 test_GetDIBits_selected_DIB(8);
1262 test_GetDIBits_selected_DDB(TRUE);
1263 test_GetDIBits_selected_DDB(FALSE);
1264 }