gdi32/tests: Add tests for 8 bpp dibs.
[wine] / dlls / gdi32 / tests / dib.c
1 /*
2  * DIB driver tests.
3  *
4  * Copyright 2011 Huw Davies
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <math.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "wincrypt.h"
30
31 #include "wine/test.h"
32
33 static HCRYPTPROV crypt_prov;
34 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
35
36 static const DWORD rop3[256] =
37 {
38     0x000042, 0x010289, 0x020C89, 0x0300AA, 0x040C88, 0x0500A9, 0x060865, 0x0702C5,
39     0x080F08, 0x090245, 0x0A0329, 0x0B0B2A, 0x0C0324, 0x0D0B25, 0x0E08A5, 0x0F0001,
40     0x100C85, 0x1100A6, 0x120868, 0x1302C8, 0x140869, 0x1502C9, 0x165CCA, 0x171D54,
41     0x180D59, 0x191CC8, 0x1A06C5, 0x1B0768, 0x1C06CA, 0x1D0766, 0x1E01A5, 0x1F0385,
42     0x200F09, 0x210248, 0x220326, 0x230B24, 0x240D55, 0x251CC5, 0x2606C8, 0x271868,
43     0x280369, 0x2916CA, 0x2A0CC9, 0x2B1D58, 0x2C0784, 0x2D060A, 0x2E064A, 0x2F0E2A,
44     0x30032A, 0x310B28, 0x320688, 0x330008, 0x3406C4, 0x351864, 0x3601A8, 0x370388,
45     0x38078A, 0x390604, 0x3A0644, 0x3B0E24, 0x3C004A, 0x3D18A4, 0x3E1B24, 0x3F00EA,
46     0x400F0A, 0x410249, 0x420D5D, 0x431CC4, 0x440328, 0x450B29, 0x4606C6, 0x47076A,
47     0x480368, 0x4916C5, 0x4A0789, 0x4B0605, 0x4C0CC8, 0x4D1954, 0x4E0645, 0x4F0E25,
48     0x500325, 0x510B26, 0x5206C9, 0x530764, 0x5408A9, 0x550009, 0x5601A9, 0x570389,
49     0x580785, 0x590609, 0x5A0049, 0x5B18A9, 0x5C0649, 0x5D0E29, 0x5E1B29, 0x5F00E9,
50     0x600365, 0x6116C6, 0x620786, 0x630608, 0x640788, 0x650606, 0x660046, 0x6718A8,
51     0x6858A6, 0x690145, 0x6A01E9, 0x6B178A, 0x6C01E8, 0x6D1785, 0x6E1E28, 0x6F0C65,
52     0x700CC5, 0x711D5C, 0x720648, 0x730E28, 0x740646, 0x750E26, 0x761B28, 0x7700E6,
53     0x7801E5, 0x791786, 0x7A1E29, 0x7B0C68, 0x7C1E24, 0x7D0C69, 0x7E0955, 0x7F03C9,
54     0x8003E9, 0x810975, 0x820C49, 0x831E04, 0x840C48, 0x851E05, 0x8617A6, 0x8701C5,
55     0x8800C6, 0x891B08, 0x8A0E06, 0x8B0666, 0x8C0E08, 0x8D0668, 0x8E1D7C, 0x8F0CE5,
56     0x900C45, 0x911E08, 0x9217A9, 0x9301C4, 0x9417AA, 0x9501C9, 0x960169, 0x97588A,
57     0x981888, 0x990066, 0x9A0709, 0x9B07A8, 0x9C0704, 0x9D07A6, 0x9E16E6, 0x9F0345,
58     0xA000C9, 0xA11B05, 0xA20E09, 0xA30669, 0xA41885, 0xA50065, 0xA60706, 0xA707A5,
59     0xA803A9, 0xA90189, 0xAA0029, 0xAB0889, 0xAC0744, 0xAD06E9, 0xAE0B06, 0xAF0229,
60     0xB00E05, 0xB10665, 0xB21974, 0xB30CE8, 0xB4070A, 0xB507A9, 0xB616E9, 0xB70348,
61     0xB8074A, 0xB906E6, 0xBA0B09, 0xBB0226, 0xBC1CE4, 0xBD0D7D, 0xBE0269, 0xBF08C9,
62     0xC000CA, 0xC11B04, 0xC21884, 0xC3006A, 0xC40E04, 0xC50664, 0xC60708, 0xC707AA,
63     0xC803A8, 0xC90184, 0xCA0749, 0xCB06E4, 0xCC0020, 0xCD0888, 0xCE0B08, 0xCF0224,
64     0xD00E0A, 0xD1066A, 0xD20705, 0xD307A4, 0xD41D78, 0xD50CE9, 0xD616EA, 0xD70349,
65     0xD80745, 0xD906E8, 0xDA1CE9, 0xDB0D75, 0xDC0B04, 0xDD0228, 0xDE0268, 0xDF08C8,
66     0xE003A5, 0xE10185, 0xE20746, 0xE306EA, 0xE40748, 0xE506E5, 0xE61CE8, 0xE70D79,
67     0xE81D74, 0xE95CE6, 0xEA02E9, 0xEB0849, 0xEC02E8, 0xED0848, 0xEE0086, 0xEF0A08,
68     0xF00021, 0xF10885, 0xF20B05, 0xF3022A, 0xF40B0A, 0xF50225, 0xF60265, 0xF708C5,
69     0xF802E5, 0xF90845, 0xFA0089, 0xFB0A09, 0xFC008A, 0xFD0A0A, 0xFE02A9, 0xFF0062
70 };
71
72 static inline BOOL rop_uses_src(DWORD rop)
73 {
74     return (((rop & 0xcc0000) >> 2) != (rop & 0x330000));
75 }
76
77 static const char *sha1_graphics_a8r8g8b8[] =
78 {
79     "a3cadd34d95d3d5cc23344f69aab1c2e55935fcf",
80     "2426172d9e8fec27d9228088f382ef3c93717da9",
81     "9e8f27ca952cdba01dbf25d07c34e86a7820c012",
82     "664fac17803859a4015c6ae29e5538e314d5c827",
83     "17b2c177bdce5e94433574a928bda5c94a8cdfa5",
84     "fe6cc678fb13a3ead67839481bf22348adc69f52",
85     "d51bd330cec510cdccf5394328bd8e5411901e9e",
86     "df4aebf98d91f11be560dd232123b3ae327303d7",
87     "f2af53dd073a09b1031d0032d28da35c82adc566",
88     "eb5a963a6f7b25533ddfb8915e70865d037bd156",
89     "c387917268455017aa0b28bed73aa6554044bbb3",
90     "dcae44fee010dbf7a107797a503923fd8b1abe2e",
91     "6c530622a025d872a642e8f950867884d7b136cb",
92     "7c07d91b8f68fb31821701b3dcb96de018bf0c66",
93     "b2261353decda2712b83538ab434a49ce21f3172",
94     "ef654fedcb494dae79559f4db8b691ae2d522a3f",
95     "a694872f38e66a7ff471440c3e6a9310ef78328a",
96     "d7398de15b2837a58a62a701ca1b3384625afec4",
97     "e2a8eef4aeda3a0f6c950075acba38f1f9e0814d",
98     "8b66f14d51ecdeea12bc993302bb9b7d3ec085a1",
99     "7da9dd3d40d44d92deb9883fb7110443c2d5769a",
100     NULL
101 };
102
103 static const char *sha1_graphics_a8b8g8r8[] =
104 {
105     "a3cadd34d95d3d5cc23344f69aab1c2e55935fcf",
106     "e0bc877697093ed440e125154e247ca9d65e933c",
107     "c6d7faf5a502299f99d59eef3f7650bd63dbe108",
108     "9d8c05c3ebd786e7d052418e905a80a64bf7853d",
109     "3da12af0a810fd993fa3dbe23328a4fcd2b6c92a",
110     "b91c8f21cc4d7994abc551feff5b6927d267a9db",
111     "d49dd2c6a37e975b6dc3d201ccc217a788b30284",
112     "ca6753f9eb44529cf8c67cd6abcd4ed1ef758904",
113     "18c3ae944e0afb6c43c21cde093ddb22a27611e4",
114     "b753ebb39d90210cc717f57b53dd439f7de6b077",
115     "38c017dd1fff26b492a57e09f3ce2c4370faf225",
116     "94368cea5033b435454daa56d55546310675131e",
117     "bf57a6a37fb107d29ed3d45695919887abcb7902",
118     "3db0f8bcca3d94920aa57be6321202b8c3c08822",
119     "1f1fc165a4dae7ba118ddccb58a279bfe3876b0a",
120     "66da15b6780a4ca3b3d2eb1d1dba4e30f7b74964",
121     "42fefefe4435570fa8038ec759140c66c76570e9",
122     "3369889a67d6c79a24ee15f7d14374f9995215e4",
123     "4851c5b7d5bc18590e787c0c218a592ef504e738",
124     "9aa506e3df33e0d5298755aa4144e10eb4b5adcf",
125     "abdf003699364fe45fab7dc61e67c606d0063b40",
126     NULL
127 };
128
129 static const char *sha1_graphics_r5g5b5[] =
130 {
131     "2a2ab8b3c019e70b788ade028b0e9e53ffc529ae",
132     "847005cf7371f511bcc837251cde07b1796f6113",
133     "a8f75743a930843ec14d516cd048b6e0468e5d89",
134     "d094f51ce9b9daa9c1d9594ea88be2a2db651459",
135     "cf3928e240c9149788e1635b115a4e5baea0dd8f",
136     "a9034a905daa91757b4f63345c0e40638cd53ca8",
137     "15ee915d989e49bb9bab5b834d8f355bd067cd8f",
138     "99474fecf11df7b7035c35be6b8b697be9889418",
139     "cbc2898717f97ebb07c0c7cc04abde936dc5b584",
140     "29c896b591fdf4ddd23e5c0da1818c37e4686d94",
141     "4b5b275d33c1ebfe5bdc61df2ad125e865b800fa",
142     "92df731fa1f89550d9d4f7ea36c13f2e57c4b02a",
143     "420e39ff3bdd04c4b6cc2c98e99cb7993c7a0de5",
144     "1fabf0fdd046857b1974e31c1c1764fa9d1a762f",
145     "449092689226a1172b6086ba1181d6b6d6499f26",
146     "5c636ffadec10fbe440b552fe6436f3dbc607dcf",
147     "4aac89fc18c128eddb69eea658272af53138a1cb",
148     "9d21bcfdeaf1ca5d47eb823bdefc24d7a95f4f56",
149     "3a50ce21b3563a604b4fc9f247a30f5a981f1ba6",
150     "d7d97e28ed316f6596c737eb83baa5948d86b673",
151     "ecc2991277d7314f55b00e0f284ae3703aeef81e",
152     NULL
153 };
154
155 static const char *sha1_graphics_r4g4b4[] =
156 {
157     "2a2ab8b3c019e70b788ade028b0e9e53ffc529ae",
158     "cfa0ab83ee93283ad914c3748f0532da1697af1d",
159     "8bd18697d1ef27492805667a0bc956343ac08667",
160     "e8501c830321584474654f90e40eaf27dc21e6a8",
161     "d95ab10fcfb8447b41742e89f1ae8cd297a32fc4",
162     "821177710961d2cb5f7e7dfc0e06e767b6042753",
163     "667124365ffadeea1d8791bedda77a0c7b898de8",
164     "c9f23e684b600dea17575b4b17175fbd9106c3a9",
165     "7678876e50eae35d1eaa096aae25afaa0b864bf3",
166     "fb52b0c373a5f2a60b981604b120962942d2447a",
167     "5ab8dd07436681d762fa04ad7c6d71291c488924",
168     "0167981d9e1490a2ebd396ff7582f0943aa8e1b8",
169     "115a6bd382410a4a1d3c1fa71d8bf02536863e38",
170     "65c6d1228e3b6d63d42647f14217bc1658b70d9a",
171     "25fcb75aa687aac35b8f72640889fe92413e00c5",
172     "dbc8d66b419880108793db91c05766c0c6efd86d",
173     "6092ccbab6b6e073c6ac8244d122f2cfc453aa38",
174     "32b6e0aa79b7e96cd0ab2da167f6463c011023a8",
175     "d591232bbc2592462c819a9486750f64180518fd",
176     "0e183a4c30b3da345129cffe33fe0fc593d8666b",
177     "f14d9a4bd8a365b7c8f068a0dad481b6eb2b178b",
178     NULL
179 };
180
181 static const char *sha1_graphics_8[] =
182 {
183     "41728d7ff2bb425b5fc06521adeabf6cc73136f3",
184     "512246d4886ab889a090b167ba194577cb95272e",
185     "921e852d4564cb9e5ac15ff68b5207bebea871d1",
186     "9636b0ebefc443ea11949ccd28f6ca454277dd41",
187     "aa9050da55e6b6957c60b7d603fce539cb5c0048",
188     "e2b93aca15fb1233ac09a713dced1f4cd950b1e4",
189     "3e3a603fc26cc305aa27f88da7d2a3b0073877d8",
190     "390b2bf70daba36310683f46af9cd50b9a061396",
191     "82d21737e9a7247397a6c983a9b6d9a0452dd74d",
192     "2a8460af91675e01cbe9384eb6cd3eb2cb420960",
193     "1af53b1218ee9844fcda891b836d42f6b2f66bd5",
194     "da1cc34a9d9b779fc7849e03e214096026506464",
195     "5ba8f99ca034666effa556748c49a0f5a015125f",
196     "b67ba2f55659c75ac72c1112494461bb3086e1a4",
197     "73e2859ce849f756f954718ce3c90f02e31712b6",
198     "196d832d283bf642d2e481e5452ca175f7902761",
199     "9552f48b88982633a44001227abb847dae4d06b0",
200     "cfc67c325c7cdf96d90af9b3cceb8d0504cbb3b0",
201     "1f13ea0034db4b0ffa4ddcff9664fd892058f9cd",
202     "3caf512cfddfd463d0750cfe3cadb58548eb2ae8",
203     "4e5e7d5fd64818b2b3d3e793c88f603b699d2f0f",
204     NULL
205 };
206
207 static inline DWORD get_stride(BITMAPINFO *bmi)
208 {
209     return ((bmi->bmiHeader.biBitCount * bmi->bmiHeader.biWidth + 31) >> 3) & ~3;
210 }
211
212 static inline DWORD get_dib_size(BITMAPINFO *bmi)
213 {
214     return get_stride(bmi) * abs(bmi->bmiHeader.biHeight);
215 }
216
217 static char *hash_dib(BITMAPINFO *bmi, void *bits)
218 {
219     DWORD dib_size = get_dib_size(bmi);
220     HCRYPTHASH hash;
221     char *buf;
222     BYTE hash_buf[20];
223     DWORD hash_size = sizeof(hash_buf);
224     int i;
225     static const char *hex = "0123456789abcdef";
226
227     if(!crypt_prov) return NULL;
228
229     if(!CryptCreateHash(crypt_prov, CALG_SHA1, 0, 0, &hash)) return NULL;
230
231     CryptHashData(hash, bits, dib_size, 0);
232
233     CryptGetHashParam(hash, HP_HASHVAL, NULL, &hash_size, 0);
234     if(hash_size != sizeof(hash_buf)) return NULL;
235
236     CryptGetHashParam(hash, HP_HASHVAL, hash_buf, &hash_size, 0);
237     CryptDestroyHash(hash);
238
239     buf = HeapAlloc(GetProcessHeap(), 0, hash_size * 2 + 1);
240
241     for(i = 0; i < hash_size; i++)
242     {
243         buf[i * 2] = hex[hash_buf[i] >> 4];
244         buf[i * 2 + 1] = hex[hash_buf[i] & 0xf];
245     }
246     buf[i * 2] = '\0';
247
248     return buf;
249 }
250
251 static void compare_hash(BITMAPINFO *bmi, BYTE *bits, const char ***sha1, const char *info)
252 {
253     char *hash = hash_dib(bmi, bits);
254
255     if(!hash)
256     {
257         skip("SHA1 hashing unavailable on this platform\n");
258         return;
259     }
260
261     if(**sha1)
262     {
263         ok(!strcmp(hash, **sha1), "%d: %s: expected hash %s got %s\n",
264            bmi->bmiHeader.biBitCount, info, **sha1, hash);
265         (*sha1)++;
266     }
267     else ok(**sha1 != NULL, "missing hash, got \"%s\",\n", hash);
268
269     HeapFree(GetProcessHeap(), 0, hash);
270 }
271
272 static const RECT bias_check[] =
273 {
274     {100, 100, 200, 150},
275     {100, 100, 150, 200},
276     {100, 100,  50, 200},
277     {100, 100,   0, 150},
278     {100, 100,   0,  50},
279     {100, 100,  50,   0},
280     {100, 100, 150,   0},
281     {100, 100, 200,  50}
282 };
283
284 static const RECT hline_clips[] =
285 {
286     {120, 120, 140, 120}, /* unclipped */
287     {100, 122, 140, 122}, /* l edgecase */
288     { 99, 124, 140, 124}, /* l edgecase clipped */
289     {120, 126, 200, 126}, /* r edgecase */
290     {120, 128, 201, 128}, /* r edgecase clipped */
291     { 99, 130, 201, 130}, /* l and r clipped */
292     {120, 100, 140, 100}, /* t edgecase */
293     {120,  99, 140,  99}, /* t edgecase clipped */
294     {120, 199, 140, 199}, /* b edgecase */
295     {120, 200, 140, 200}, /* b edgecase clipped */
296     {120, 132, 310, 132}, /* inside two clip rects */
297     { 10, 134, 101, 134}, /* r end on l edgecase */
298     { 10, 136, 100, 136}, /* r end on l edgecase clipped */
299     {199, 138, 220, 138}, /* l end on r edgecase */
300     {200, 140, 220, 140}  /* l end on r edgecase clipped */
301 };
302
303 static const RECT vline_clips[] =
304 {
305     {120, 120, 120, 140}, /* unclipped */
306     {100, 120, 100, 140}, /* l edgecase */
307     { 99, 120,  99, 140}, /* l edgecase clipped */
308     {199, 120, 199, 140}, /* r edgecase */
309     {200, 120, 200, 140}, /* r edgecase clipped */
310     {122,  99, 122, 201}, /* t and b clipped */
311     {124, 100, 124, 140}, /* t edgecase */
312     {126,  99, 126, 140}, /* t edgecase clipped */
313     {128, 120, 128, 200}, /* b edgecase */
314     {130, 120, 130, 201}, /* b edgecase clipped */
315     {132,  12, 132, 140}, /* inside two clip rects */
316     {134,  90, 134, 101}, /* b end on t edgecase */
317     {136,  90, 136, 100}, /* b end on t edgecase clipped */
318     {138, 199, 138, 220}, /* t end on b edgecase */
319     {140, 200, 140, 220}  /* t end on b edgecase clipped */
320 };
321
322 static const RECT line_clips[] =
323 {
324     { 90, 110, 310, 120},
325     { 90, 120, 295, 130},
326     { 90, 190, 110, 240}, /* totally clipped, moving outcodes */
327     { 90, 130, 100, 135}, /* totally clipped, end pt on l edge */
328     { 90, 132, 101, 137}, /* end pt just inside l edge */
329     {200, 140, 210, 141}, /* totally clipped, start pt on r edge */
330     {199, 142, 210, 143}  /* start pt just inside r edge */
331 };
332
333 static const RECT patblt_clips[] =
334 {
335     {120, 120, 140, 126}, /* unclipped */
336     {100, 130, 140, 136}, /* l edgecase */
337     { 99, 140, 140, 146}, /* l edgecase clipped */
338     {180, 130, 200, 136}, /* r edgecase */
339     {180, 140, 201, 146}, /* r edgecase clipped */
340     {120, 100, 130, 110}, /* t edgecase */
341     {140,  99, 150, 110}, /* t edgecase clipped */
342     {120, 180, 130, 200}, /* b edgecase */
343     {140, 180, 150, 201}, /* b edgecase */
344     {199, 150, 210, 156}, /* l edge on r edgecase */
345     {200, 160, 210, 166}, /* l edge on r edgecase clipped */
346     { 90, 150, 101, 156}, /* r edge on l edgecase */
347     { 90, 160, 100, 166}, /* r edge on l edgecase clipped */
348     {160,  90, 166, 101}, /* b edge on t edgecase */
349     {170,  90, 176, 101}, /* b edge on t edgecase clipped */
350     {160, 199, 166, 210}, /* t edge on b edgecase */
351     {170, 200, 176, 210}, /* t edge on b edgecase clipped */
352 };
353
354 static const RECT rectangles[] =
355 {
356     {10,   11, 100, 101},
357     {250, 100, 350,  10},
358     {120,  10, 120,  20}, /* zero width */
359     {120,  10, 130,  10}, /* zero height */
360     {120,  40, 121,  41}, /* 1 x 1 */
361     {130,  50, 132,  52}, /* 2 x 2 */
362     {140,  60, 143,  63}, /* 3 x 3 */
363     {150,  70, 154,  74}, /* 4 x 4 */
364     {120,  20, 121,  30}, /* width == 1 */
365     {130,  20, 132,  30}, /* width == 2 */
366     {140,  20, 143,  30}, /* width == 3 */
367     {200,  20, 210,  21}, /* height == 1 */
368     {200,  30, 210,  32}, /* height == 2 */
369     {200,  40, 210,  43}  /* height == 3 */
370 };
371
372 static const BITMAPINFOHEADER dib_brush_header_32   = {sizeof(BITMAPINFOHEADER), 16, -16, 1, 32, BI_RGB, 0, 0, 0, 0, 0};
373 static const BITMAPINFOHEADER dib_brush_header_555  = {sizeof(BITMAPINFOHEADER), 16, -16, 1, 16, BI_RGB, 0, 0, 0, 0, 0};
374
375 static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sha1)
376 {
377     DWORD dib_size = get_dib_size(bmi);
378     HPEN solid_pen, dashed_pen, orig_pen;
379     HBRUSH solid_brush, dib_brush, orig_brush;
380     INT i, y;
381     HRGN hrgn, hrgn2;
382     BYTE dib_brush_buf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD) + 16 * 16 * sizeof(DWORD)]; /* Enough for 16 x 16 at 32 bpp */
383     BITMAPINFO *brush_bi = (BITMAPINFO*)dib_brush_buf;
384     BYTE *brush_bits;
385
386     memset(bits, 0xcc, dib_size);
387     compare_hash(bmi, bits, sha1, "empty");
388
389     solid_pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0xff));
390     orig_pen = SelectObject(hdc, solid_pen);
391     SetBrushOrgEx(hdc, 0, 0, NULL);
392
393     /* horizontal and vertical lines */
394     for(i = 1; i <= 16; i++)
395     {
396         SetROP2(hdc, i);
397         MoveToEx(hdc, 10, i * 3, NULL);
398         LineTo(hdc, 100, i * 3); /* l -> r */
399         MoveToEx(hdc, 100, 50 + i * 3, NULL);
400         LineTo(hdc, 10, 50 + i * 3); /* r -> l */
401         MoveToEx(hdc, 120 + i * 3, 10, NULL);
402         LineTo(hdc, 120 + i * 3, 100); /* t -> b */
403         MoveToEx(hdc, 170 + i * 3, 100, NULL);
404         LineTo(hdc, 170 + i * 3, 10); /* b -> t */
405     }
406     compare_hash(bmi, bits, sha1, "h and v solid lines");
407     memset(bits, 0xcc, dib_size);
408
409     /* diagonal lines */
410     SetROP2(hdc, R2_COPYPEN);
411     for(i = 0; i < 16; i++)
412     {
413         double s = sin(M_PI * i / 8.0);
414         double c = cos(M_PI * i / 8.0);
415
416         MoveToEx(hdc, 200.5 + 10 * c, 200.5 + 10 * s, NULL);
417         LineTo(hdc, 200.5 + 100 * c, 200.5 + 100 * s);
418     }
419     compare_hash(bmi, bits, sha1, "diagonal solid lines");
420     memset(bits, 0xcc, dib_size);
421
422     for(i = 0; i < sizeof(bias_check) / sizeof(bias_check[0]); i++)
423     {
424         MoveToEx(hdc, bias_check[i].left, bias_check[i].top, NULL);
425         LineTo(hdc, bias_check[i].right, bias_check[i].bottom);
426     }
427     compare_hash(bmi, bits, sha1, "more diagonal solid lines");
428     memset(bits, 0xcc, dib_size);
429
430     /* solid brush PatBlt */
431     solid_brush = CreateSolidBrush(RGB(0x33, 0xaa, 0xff));
432     orig_brush = SelectObject(hdc, solid_brush);
433
434     for(i = 0, y = 10; i < 256; i++)
435     {
436         BOOL ret;
437
438         ret = PatBlt(hdc, 10, y, 100, 10, rop3[i]);
439
440         if(rop_uses_src(rop3[i]))
441             ok(ret == FALSE, "got TRUE for %x\n", rop3[i]);
442         else
443         {
444             ok(ret, "got FALSE for %x\n", rop3[i]);
445             y += 20;
446         }
447
448     }
449     compare_hash(bmi, bits, sha1, "solid patblt");
450     memset(bits, 0xcc, dib_size);
451
452     /* clipped lines */
453     hrgn = CreateRectRgn(10, 10, 200, 20);
454     hrgn2 = CreateRectRgn(100, 100, 200, 200);
455     CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
456     SetRectRgn(hrgn2, 290, 100, 300, 200);
457     CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
458     ExtSelectClipRgn(hdc, hrgn, RGN_COPY);
459     DeleteObject(hrgn2);
460
461     for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
462     {
463         MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL);
464         LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom);
465     }
466     compare_hash(bmi, bits, sha1, "clipped solid hlines");
467     memset(bits, 0xcc, dib_size);
468
469     for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
470     {
471         MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL);
472         LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom);
473     }
474     compare_hash(bmi, bits, sha1, "clipped solid vlines");
475     memset(bits, 0xcc, dib_size);
476
477     for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
478     {
479         MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
480         LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
481     }
482     compare_hash(bmi, bits, sha1, "clipped solid diagonal lines");
483     memset(bits, 0xcc, dib_size);
484
485     /* clipped PatBlt */
486     for(i = 0; i < sizeof(patblt_clips) / sizeof(patblt_clips[0]); i++)
487     {
488         PatBlt(hdc, patblt_clips[i].left, patblt_clips[i].top,
489                patblt_clips[i].right - patblt_clips[i].left,
490                patblt_clips[i].bottom - patblt_clips[i].top, PATCOPY);
491     }
492     compare_hash(bmi, bits, sha1, "clipped patblt");
493     memset(bits, 0xcc, dib_size);
494
495     /* clipped dashed lines */
496     dashed_pen = CreatePen(PS_DASH, 1, RGB(0xff, 0, 0));
497     SelectObject(hdc, dashed_pen);
498     SetBkMode(hdc, TRANSPARENT);
499     SetBkColor(hdc, RGB(0, 0xff, 0));
500
501     for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
502     {
503         MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL);
504         LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom);
505     }
506     compare_hash(bmi, bits, sha1, "clipped dashed hlines");
507     memset(bits, 0xcc, dib_size);
508
509     for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
510     {
511         MoveToEx(hdc, hline_clips[i].right - 1, hline_clips[i].bottom, NULL);
512         LineTo(hdc, hline_clips[i].left - 1, hline_clips[i].top);
513     }
514     compare_hash(bmi, bits, sha1, "clipped dashed hlines r -> l");
515     memset(bits, 0xcc, dib_size);
516
517     for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
518     {
519         MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL);
520         LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom);
521     }
522     compare_hash(bmi, bits, sha1, "clipped dashed vlines");
523     memset(bits, 0xcc, dib_size);
524
525     for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
526     {
527         MoveToEx(hdc, vline_clips[i].right, vline_clips[i].bottom - 1, NULL);
528         LineTo(hdc, vline_clips[i].left, vline_clips[i].top - 1);
529     }
530     compare_hash(bmi, bits, sha1, "clipped dashed vlines b -> t");
531     memset(bits, 0xcc, dib_size);
532
533     for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
534     {
535         MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
536         LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
537     }
538     compare_hash(bmi, bits, sha1, "clipped dashed diagonal lines");
539     memset(bits, 0xcc, dib_size);
540
541     SetBkMode(hdc, OPAQUE);
542
543     for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
544     {
545         MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
546         LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
547     }
548     compare_hash(bmi, bits, sha1, "clipped opaque dashed diagonal lines");
549     memset(bits, 0xcc, dib_size);
550
551     ExtSelectClipRgn(hdc, NULL, RGN_COPY);
552
553     /* DIB pattern brush */
554
555     brush_bi->bmiHeader = dib_brush_header_32;
556     brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER);
557     memset(brush_bits, 0, 16 * 16 * sizeof(DWORD));
558     brush_bits[2] = 0xff;
559     brush_bits[6] = 0xff;
560     brush_bits[14] = 0xff;
561     brush_bits[65] = 0xff;
562     brush_bits[69] = 0xff;
563
564     dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS);
565
566     SelectObject(hdc, dib_brush);
567     SetBrushOrgEx(hdc, 1, 1, NULL);
568
569     for(i = 0, y = 10; i < 256; i++)
570     {
571         BOOL ret;
572
573         if(!rop_uses_src(rop3[i]))
574         {
575             ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]);
576             ok(ret, "got FALSE for %x\n", rop3[i]);
577             y += 25;
578         }
579     }
580     compare_hash(bmi, bits, sha1, "top-down dib brush patblt");
581     memset(bits, 0xcc, dib_size);
582
583     SelectObject(hdc, orig_brush);
584     DeleteObject(dib_brush);
585
586     /* Bottom-up DIB pattern brush */
587
588     brush_bi->bmiHeader.biHeight = -brush_bi->bmiHeader.biHeight;
589
590     dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS);
591
592     SelectObject(hdc, dib_brush);
593     SetBrushOrgEx(hdc, 100, 100, NULL);
594
595     for(i = 0, y = 10; i < 256; i++)
596     {
597         BOOL ret;
598
599         if(!rop_uses_src(rop3[i]))
600         {
601             ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]);
602             ok(ret, "got FALSE for %x\n", rop3[i]);
603             y += 25;
604         }
605     }
606     compare_hash(bmi, bits, sha1, "bottom-up dib brush patblt");
607     memset(bits, 0xcc, dib_size);
608
609     /* 555 dib pattern brush */
610
611     brush_bi->bmiHeader = dib_brush_header_555;
612     brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER);
613     memset(brush_bits, 0, 16 * 16 * sizeof(WORD));
614     brush_bits[0] = brush_bits[1] = 0xff;
615     brush_bits[32] = brush_bits[34] = 0x7c;
616
617     dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS);
618
619     SelectObject(hdc, dib_brush);
620     SetBrushOrgEx(hdc, 1, 1, NULL);
621
622     for(i = 0, y = 10; i < 256; i++)
623     {
624         BOOL ret;
625
626         if(!rop_uses_src(rop3[i]))
627         {
628             ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]);
629             ok(ret, "got FALSE for %x\n", rop3[i]);
630             y += 25;
631         }
632     }
633     compare_hash(bmi, bits, sha1, "top-down 555 dib brush patblt");
634     memset(bits, 0xcc, dib_size);
635
636     SelectObject(hdc, orig_brush);
637     DeleteObject(dib_brush);
638
639     SetBrushOrgEx(hdc, 0, 0, NULL);
640
641     /* Rectangle */
642
643     SelectObject(hdc, solid_pen);
644     SelectObject(hdc, solid_brush);
645
646     for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++)
647     {
648         Rectangle(hdc, rectangles[i].left, rectangles[i].top, rectangles[i].right, rectangles[i].bottom);
649     }
650
651     SelectObject(hdc, dashed_pen);
652     for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++)
653     {
654         Rectangle(hdc, rectangles[i].left, rectangles[i].top + 150, rectangles[i].right, rectangles[i].bottom + 150);
655     }
656
657     compare_hash(bmi, bits, sha1, "rectangles");
658     memset(bits, 0xcc, dib_size);
659     SelectObject(hdc, solid_pen);
660
661     /* PaintRgn */
662
663     PaintRgn(hdc, hrgn);
664     compare_hash(bmi, bits, sha1, "PaintRgn");
665     memset(bits, 0xcc, dib_size);
666
667     /* RTL rectangles */
668
669     if( !pSetLayout )
670     {
671         win_skip("Don't have SetLayout\n");
672         (*sha1)++;
673     }
674     else
675     {
676         pSetLayout(hdc, LAYOUT_RTL);
677         PaintRgn(hdc, hrgn);
678         PatBlt(hdc, 10, 250, 10, 10, PATCOPY);
679         Rectangle(hdc, 100, 250, 110, 260);
680         compare_hash(bmi, bits, sha1, "rtl");
681         memset(bits, 0xcc, dib_size);
682
683         pSetLayout(hdc, LAYOUT_LTR);
684     }
685
686     SelectObject(hdc, orig_brush);
687     SelectObject(hdc, orig_pen);
688     DeleteObject(hrgn);
689     DeleteObject(dib_brush);
690     DeleteObject(dashed_pen);
691     DeleteObject(solid_brush);
692     DeleteObject(solid_pen);
693 }
694
695 static void test_simple_graphics(void)
696 {
697     char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
698     BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
699     DWORD *bit_fields = (DWORD*)(bmibuf + sizeof(BITMAPINFOHEADER));
700     HDC mem_dc;
701     BYTE *bits;
702     HBITMAP dib, orig_bm;
703     const char **sha1;
704     DIBSECTION ds;
705
706     mem_dc = CreateCompatibleDC(NULL);
707
708     /* a8r8g8b8 */
709     trace("8888\n");
710     memset(bmi, 0, sizeof(bmibuf));
711     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
712     bmi->bmiHeader.biHeight = 512;
713     bmi->bmiHeader.biWidth = 512;
714     bmi->bmiHeader.biBitCount = 32;
715     bmi->bmiHeader.biPlanes = 1;
716     bmi->bmiHeader.biCompression = BI_RGB;
717
718     dib = CreateDIBSection(0, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
719     ok(dib != NULL, "ret NULL\n");
720     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
721     ok(ds.dsBitfields[0] == 0, "got %08x\n", ds.dsBitfields[0]);
722     ok(ds.dsBitfields[1] == 0, "got %08x\n", ds.dsBitfields[1]);
723     ok(ds.dsBitfields[2] == 0, "got %08x\n", ds.dsBitfields[2]);
724     ok(ds.dsBmih.biCompression == BI_RGB ||
725        broken(ds.dsBmih.biCompression == BI_BITFIELDS), /* nt4 sp1 and 2 */
726        "got %x\n", ds.dsBmih.biCompression);
727
728     orig_bm = SelectObject(mem_dc, dib);
729
730     sha1 = sha1_graphics_a8r8g8b8;
731     draw_graphics(mem_dc, bmi, bits, &sha1);
732
733     SelectObject(mem_dc, orig_bm);
734     DeleteObject(dib);
735
736     /* a8r8g8b8 - bitfields.  Should be the same as the regular 32 bit case.*/
737     trace("8888 - bitfields\n");
738     bmi->bmiHeader.biBitCount = 32;
739     bmi->bmiHeader.biCompression = BI_BITFIELDS;
740     bit_fields[0] = 0xff0000;
741     bit_fields[1] = 0x00ff00;
742     bit_fields[2] = 0x0000ff;
743
744     dib = CreateDIBSection(mem_dc, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
745     ok(dib != NULL, "ret NULL\n");
746     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
747     ok(ds.dsBitfields[0] == 0xff0000, "got %08x\n", ds.dsBitfields[0]);
748     ok(ds.dsBitfields[1] == 0x00ff00, "got %08x\n", ds.dsBitfields[1]);
749     ok(ds.dsBitfields[2] == 0x0000ff, "got %08x\n", ds.dsBitfields[2]);
750     ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression);
751
752     orig_bm = SelectObject(mem_dc, dib);
753
754     sha1 = sha1_graphics_a8r8g8b8;
755     draw_graphics(mem_dc, bmi, bits, &sha1);
756
757     SelectObject(mem_dc, orig_bm);
758     DeleteObject(dib);
759
760     /* a8b8g8r8 - bitfields. */
761     trace("a8b8g8r8 - bitfields\n");
762     bmi->bmiHeader.biBitCount = 32;
763     bmi->bmiHeader.biCompression = BI_BITFIELDS;
764     bit_fields[0] = 0x0000ff;
765     bit_fields[1] = 0x00ff00;
766     bit_fields[2] = 0xff0000;
767
768     dib = CreateDIBSection(mem_dc, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
769     ok(dib != NULL, "ret NULL\n");
770     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
771     ok(ds.dsBitfields[0] == 0x0000ff, "got %08x\n", ds.dsBitfields[0]);
772     ok(ds.dsBitfields[1] == 0x00ff00, "got %08x\n", ds.dsBitfields[1]);
773     ok(ds.dsBitfields[2] == 0xff0000, "got %08x\n", ds.dsBitfields[2]);
774     ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression);
775
776     orig_bm = SelectObject(mem_dc, dib);
777
778     sha1 = sha1_graphics_a8b8g8r8;
779     draw_graphics(mem_dc, bmi, bits, &sha1);
780
781     SelectObject(mem_dc, orig_bm);
782     DeleteObject(dib);
783
784     /* r5g5b5 */
785     trace("555\n");
786     bmi->bmiHeader.biBitCount = 16;
787     bmi->bmiHeader.biCompression = BI_RGB;
788
789     dib = CreateDIBSection(0, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
790     ok(dib != NULL, "ret NULL\n");
791     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
792     ok(ds.dsBitfields[0] == 0x7c00, "got %08x\n", ds.dsBitfields[0]);
793     ok(ds.dsBitfields[1] == 0x03e0, "got %08x\n", ds.dsBitfields[1]);
794     ok(ds.dsBitfields[2] == 0x001f, "got %08x\n", ds.dsBitfields[2]);
795 todo_wine
796     ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression);
797
798     orig_bm = SelectObject(mem_dc, dib);
799
800     sha1 = sha1_graphics_r5g5b5;
801     draw_graphics(mem_dc, bmi, bits, &sha1);
802
803     SelectObject(mem_dc, orig_bm);
804     DeleteObject(dib);
805
806     /* r4g4b4 */
807     trace("444\n");
808     bmi->bmiHeader.biBitCount = 16;
809     bmi->bmiHeader.biCompression = BI_BITFIELDS;
810     bit_fields[0] = 0x0f00;
811     bit_fields[1] = 0x00f0;
812     bit_fields[2] = 0x000f;
813     dib = CreateDIBSection(0, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
814     ok(dib != NULL, "ret NULL\n");
815     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
816     ok(ds.dsBitfields[0] == 0x0f00, "got %08x\n", ds.dsBitfields[0]);
817     ok(ds.dsBitfields[1] == 0x00f0, "got %08x\n", ds.dsBitfields[1]);
818     ok(ds.dsBitfields[2] == 0x000f, "got %08x\n", ds.dsBitfields[2]);
819     ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression);
820
821     orig_bm = SelectObject(mem_dc, dib);
822
823     sha1 = sha1_graphics_r4g4b4;
824     draw_graphics(mem_dc, bmi, bits, &sha1);
825
826     SelectObject(mem_dc, orig_bm);
827     DeleteObject(dib);
828
829     /* 8 */
830     trace("8\n");
831     bmi->bmiHeader.biBitCount = 8;
832     bmi->bmiHeader.biCompression = BI_RGB;
833     bmi->bmiHeader.biClrUsed = 5;
834     bmi->bmiColors[0].rgbRed = 0xff;
835     bmi->bmiColors[0].rgbGreen = 0xff;
836     bmi->bmiColors[0].rgbBlue = 0xff;
837     bmi->bmiColors[1].rgbRed = 0;
838     bmi->bmiColors[1].rgbGreen = 0;
839     bmi->bmiColors[1].rgbBlue = 0;
840     bmi->bmiColors[2].rgbRed = 0xff;
841     bmi->bmiColors[2].rgbGreen = 0;
842     bmi->bmiColors[2].rgbBlue = 0;
843     bmi->bmiColors[3].rgbRed = 0;
844     bmi->bmiColors[3].rgbGreen = 0xff;
845     bmi->bmiColors[3].rgbBlue = 0;
846     bmi->bmiColors[4].rgbRed = 0;
847     bmi->bmiColors[4].rgbGreen = 0;
848     bmi->bmiColors[4].rgbBlue = 0xff;
849
850     dib = CreateDIBSection(0, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
851     ok(dib != NULL, "ret NULL\n");
852
853     orig_bm = SelectObject(mem_dc, dib);
854
855     sha1 = sha1_graphics_8;
856     draw_graphics(mem_dc, bmi, bits, &sha1);
857
858     SelectObject(mem_dc, orig_bm);
859     DeleteObject(dib);
860
861     DeleteDC(mem_dc);
862 }
863
864 START_TEST(dib)
865 {
866     HMODULE mod = GetModuleHandleA("gdi32.dll");
867     pSetLayout = (void *)GetProcAddress( mod, "SetLayout" );
868
869     CryptAcquireContextW(&crypt_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
870
871     test_simple_graphics();
872
873     CryptReleaseContext(crypt_prov, 0);
874 }