gdi32/tests: Add tests for 8bpp brushes.
[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     "a78b28472bb7ff480ddedd06b9cf2daa775fa7ae",
98     "e2a8eef4aeda3a0f6c950075acba38f1f9e0814d",
99     "8b66f14d51ecdeea12bc993302bb9b7d3ec085a1",
100     "7da9dd3d40d44d92deb9883fb7110443c2d5769a",
101     NULL
102 };
103
104 static const char *sha1_graphics_a8b8g8r8[] =
105 {
106     "a3cadd34d95d3d5cc23344f69aab1c2e55935fcf",
107     "e0bc877697093ed440e125154e247ca9d65e933c",
108     "c6d7faf5a502299f99d59eef3f7650bd63dbe108",
109     "9d8c05c3ebd786e7d052418e905a80a64bf7853d",
110     "3da12af0a810fd993fa3dbe23328a4fcd2b6c92a",
111     "b91c8f21cc4d7994abc551feff5b6927d267a9db",
112     "d49dd2c6a37e975b6dc3d201ccc217a788b30284",
113     "ca6753f9eb44529cf8c67cd6abcd4ed1ef758904",
114     "18c3ae944e0afb6c43c21cde093ddb22a27611e4",
115     "b753ebb39d90210cc717f57b53dd439f7de6b077",
116     "38c017dd1fff26b492a57e09f3ce2c4370faf225",
117     "94368cea5033b435454daa56d55546310675131e",
118     "bf57a6a37fb107d29ed3d45695919887abcb7902",
119     "3db0f8bcca3d94920aa57be6321202b8c3c08822",
120     "1f1fc165a4dae7ba118ddccb58a279bfe3876b0a",
121     "66da15b6780a4ca3b3d2eb1d1dba4e30f7b74964",
122     "42fefefe4435570fa8038ec759140c66c76570e9",
123     "3369889a67d6c79a24ee15f7d14374f9995215e4",
124     "473a1fd07df800c87a5d3286b642ace10c61c6af",
125     "4851c5b7d5bc18590e787c0c218a592ef504e738",
126     "9aa506e3df33e0d5298755aa4144e10eb4b5adcf",
127     "abdf003699364fe45fab7dc61e67c606d0063b40",
128     NULL
129 };
130
131 static const char *sha1_graphics_r5g5b5[] =
132 {
133     "2a2ab8b3c019e70b788ade028b0e9e53ffc529ae",
134     "847005cf7371f511bcc837251cde07b1796f6113",
135     "a8f75743a930843ec14d516cd048b6e0468e5d89",
136     "d094f51ce9b9daa9c1d9594ea88be2a2db651459",
137     "cf3928e240c9149788e1635b115a4e5baea0dd8f",
138     "a9034a905daa91757b4f63345c0e40638cd53ca8",
139     "15ee915d989e49bb9bab5b834d8f355bd067cd8f",
140     "99474fecf11df7b7035c35be6b8b697be9889418",
141     "cbc2898717f97ebb07c0c7cc04abde936dc5b584",
142     "29c896b591fdf4ddd23e5c0da1818c37e4686d94",
143     "4b5b275d33c1ebfe5bdc61df2ad125e865b800fa",
144     "92df731fa1f89550d9d4f7ea36c13f2e57c4b02a",
145     "420e39ff3bdd04c4b6cc2c98e99cb7993c7a0de5",
146     "1fabf0fdd046857b1974e31c1c1764fa9d1a762f",
147     "449092689226a1172b6086ba1181d6b6d6499f26",
148     "5c636ffadec10fbe440b552fe6436f3dbc607dcf",
149     "4aac89fc18c128eddb69eea658272af53138a1cb",
150     "9d21bcfdeaf1ca5d47eb823bdefc24d7a95f4f56",
151     "6daaf945a955928c5c124c880522ca4634fb2343",
152     "3a50ce21b3563a604b4fc9f247a30f5a981f1ba6",
153     "d7d97e28ed316f6596c737eb83baa5948d86b673",
154     "ecc2991277d7314f55b00e0f284ae3703aeef81e",
155     NULL
156 };
157
158 static const char *sha1_graphics_r4g4b4[] =
159 {
160     "2a2ab8b3c019e70b788ade028b0e9e53ffc529ae",
161     "cfa0ab83ee93283ad914c3748f0532da1697af1d",
162     "8bd18697d1ef27492805667a0bc956343ac08667",
163     "e8501c830321584474654f90e40eaf27dc21e6a8",
164     "d95ab10fcfb8447b41742e89f1ae8cd297a32fc4",
165     "821177710961d2cb5f7e7dfc0e06e767b6042753",
166     "667124365ffadeea1d8791bedda77a0c7b898de8",
167     "c9f23e684b600dea17575b4b17175fbd9106c3a9",
168     "7678876e50eae35d1eaa096aae25afaa0b864bf3",
169     "fb52b0c373a5f2a60b981604b120962942d2447a",
170     "5ab8dd07436681d762fa04ad7c6d71291c488924",
171     "0167981d9e1490a2ebd396ff7582f0943aa8e1b8",
172     "115a6bd382410a4a1d3c1fa71d8bf02536863e38",
173     "65c6d1228e3b6d63d42647f14217bc1658b70d9a",
174     "25fcb75aa687aac35b8f72640889fe92413e00c5",
175     "dbc8d66b419880108793db91c05766c0c6efd86d",
176     "6092ccbab6b6e073c6ac8244d122f2cfc453aa38",
177     "32b6e0aa79b7e96cd0ab2da167f6463c011023a8",
178     "1d283aa4d2b2114f7809fe59357d590c7c779aa7",
179     "d591232bbc2592462c819a9486750f64180518fd",
180     "0e183a4c30b3da345129cffe33fe0fc593d8666b",
181     "f14d9a4bd8a365b7c8f068a0dad481b6eb2b178b",
182     NULL
183 };
184
185 static const char *sha1_graphics_8[] =
186 {
187     "41728d7ff2bb425b5fc06521adeabf6cc73136f3",
188     "512246d4886ab889a090b167ba194577cb95272e",
189     "921e852d4564cb9e5ac15ff68b5207bebea871d1",
190     "9636b0ebefc443ea11949ccd28f6ca454277dd41",
191     "aa9050da55e6b6957c60b7d603fce539cb5c0048",
192     "e2b93aca15fb1233ac09a713dced1f4cd950b1e4",
193     "3e3a603fc26cc305aa27f88da7d2a3b0073877d8",
194     "390b2bf70daba36310683f46af9cd50b9a061396",
195     "82d21737e9a7247397a6c983a9b6d9a0452dd74d",
196     "2a8460af91675e01cbe9384eb6cd3eb2cb420960",
197     "1af53b1218ee9844fcda891b836d42f6b2f66bd5",
198     "da1cc34a9d9b779fc7849e03e214096026506464",
199     "5ba8f99ca034666effa556748c49a0f5a015125f",
200     "b67ba2f55659c75ac72c1112494461bb3086e1a4",
201     "73e2859ce849f756f954718ce3c90f02e31712b6",
202     "196d832d283bf642d2e481e5452ca175f7902761",
203     "9552f48b88982633a44001227abb847dae4d06b0",
204     "cfc67c325c7cdf96d90af9b3cceb8d0504cbb3b0",
205     "7262364067e03c7fa498af1d59d228d6c63b460e",
206     "1f13ea0034db4b0ffa4ddcff9664fd892058f9cd",
207     "3caf512cfddfd463d0750cfe3cadb58548eb2ae8",
208     "4e5e7d5fd64818b2b3d3e793c88f603b699d2f0f",
209     NULL
210 };
211
212 static inline DWORD get_stride(BITMAPINFO *bmi)
213 {
214     return ((bmi->bmiHeader.biBitCount * bmi->bmiHeader.biWidth + 31) >> 3) & ~3;
215 }
216
217 static inline DWORD get_dib_size(BITMAPINFO *bmi)
218 {
219     return get_stride(bmi) * abs(bmi->bmiHeader.biHeight);
220 }
221
222 static char *hash_dib(BITMAPINFO *bmi, void *bits)
223 {
224     DWORD dib_size = get_dib_size(bmi);
225     HCRYPTHASH hash;
226     char *buf;
227     BYTE hash_buf[20];
228     DWORD hash_size = sizeof(hash_buf);
229     int i;
230     static const char *hex = "0123456789abcdef";
231
232     if(!crypt_prov) return NULL;
233
234     if(!CryptCreateHash(crypt_prov, CALG_SHA1, 0, 0, &hash)) return NULL;
235
236     CryptHashData(hash, bits, dib_size, 0);
237
238     CryptGetHashParam(hash, HP_HASHVAL, NULL, &hash_size, 0);
239     if(hash_size != sizeof(hash_buf)) return NULL;
240
241     CryptGetHashParam(hash, HP_HASHVAL, hash_buf, &hash_size, 0);
242     CryptDestroyHash(hash);
243
244     buf = HeapAlloc(GetProcessHeap(), 0, hash_size * 2 + 1);
245
246     for(i = 0; i < hash_size; i++)
247     {
248         buf[i * 2] = hex[hash_buf[i] >> 4];
249         buf[i * 2 + 1] = hex[hash_buf[i] & 0xf];
250     }
251     buf[i * 2] = '\0';
252
253     return buf;
254 }
255
256 static void compare_hash(BITMAPINFO *bmi, BYTE *bits, const char ***sha1, const char *info)
257 {
258     char *hash = hash_dib(bmi, bits);
259
260     if(!hash)
261     {
262         skip("SHA1 hashing unavailable on this platform\n");
263         return;
264     }
265
266     if(**sha1)
267     {
268         ok(!strcmp(hash, **sha1), "%d: %s: expected hash %s got %s\n",
269            bmi->bmiHeader.biBitCount, info, **sha1, hash);
270         (*sha1)++;
271     }
272     else ok(**sha1 != NULL, "missing hash, got \"%s\",\n", hash);
273
274     HeapFree(GetProcessHeap(), 0, hash);
275 }
276
277 static const RECT bias_check[] =
278 {
279     {100, 100, 200, 150},
280     {100, 100, 150, 200},
281     {100, 100,  50, 200},
282     {100, 100,   0, 150},
283     {100, 100,   0,  50},
284     {100, 100,  50,   0},
285     {100, 100, 150,   0},
286     {100, 100, 200,  50}
287 };
288
289 static const RECT hline_clips[] =
290 {
291     {120, 120, 140, 120}, /* unclipped */
292     {100, 122, 140, 122}, /* l edgecase */
293     { 99, 124, 140, 124}, /* l edgecase clipped */
294     {120, 126, 200, 126}, /* r edgecase */
295     {120, 128, 201, 128}, /* r edgecase clipped */
296     { 99, 130, 201, 130}, /* l and r clipped */
297     {120, 100, 140, 100}, /* t edgecase */
298     {120,  99, 140,  99}, /* t edgecase clipped */
299     {120, 199, 140, 199}, /* b edgecase */
300     {120, 200, 140, 200}, /* b edgecase clipped */
301     {120, 132, 310, 132}, /* inside two clip rects */
302     { 10, 134, 101, 134}, /* r end on l edgecase */
303     { 10, 136, 100, 136}, /* r end on l edgecase clipped */
304     {199, 138, 220, 138}, /* l end on r edgecase */
305     {200, 140, 220, 140}  /* l end on r edgecase clipped */
306 };
307
308 static const RECT vline_clips[] =
309 {
310     {120, 120, 120, 140}, /* unclipped */
311     {100, 120, 100, 140}, /* l edgecase */
312     { 99, 120,  99, 140}, /* l edgecase clipped */
313     {199, 120, 199, 140}, /* r edgecase */
314     {200, 120, 200, 140}, /* r edgecase clipped */
315     {122,  99, 122, 201}, /* t and b clipped */
316     {124, 100, 124, 140}, /* t edgecase */
317     {126,  99, 126, 140}, /* t edgecase clipped */
318     {128, 120, 128, 200}, /* b edgecase */
319     {130, 120, 130, 201}, /* b edgecase clipped */
320     {132,  12, 132, 140}, /* inside two clip rects */
321     {134,  90, 134, 101}, /* b end on t edgecase */
322     {136,  90, 136, 100}, /* b end on t edgecase clipped */
323     {138, 199, 138, 220}, /* t end on b edgecase */
324     {140, 200, 140, 220}  /* t end on b edgecase clipped */
325 };
326
327 static const RECT line_clips[] =
328 {
329     { 90, 110, 310, 120},
330     { 90, 120, 295, 130},
331     { 90, 190, 110, 240}, /* totally clipped, moving outcodes */
332     { 90, 130, 100, 135}, /* totally clipped, end pt on l edge */
333     { 90, 132, 101, 137}, /* end pt just inside l edge */
334     {200, 140, 210, 141}, /* totally clipped, start pt on r edge */
335     {199, 142, 210, 143}  /* start pt just inside r edge */
336 };
337
338 static const RECT patblt_clips[] =
339 {
340     {120, 120, 140, 126}, /* unclipped */
341     {100, 130, 140, 136}, /* l edgecase */
342     { 99, 140, 140, 146}, /* l edgecase clipped */
343     {180, 130, 200, 136}, /* r edgecase */
344     {180, 140, 201, 146}, /* r edgecase clipped */
345     {120, 100, 130, 110}, /* t edgecase */
346     {140,  99, 150, 110}, /* t edgecase clipped */
347     {120, 180, 130, 200}, /* b edgecase */
348     {140, 180, 150, 201}, /* b edgecase */
349     {199, 150, 210, 156}, /* l edge on r edgecase */
350     {200, 160, 210, 166}, /* l edge on r edgecase clipped */
351     { 90, 150, 101, 156}, /* r edge on l edgecase */
352     { 90, 160, 100, 166}, /* r edge on l edgecase clipped */
353     {160,  90, 166, 101}, /* b edge on t edgecase */
354     {170,  90, 176, 101}, /* b edge on t edgecase clipped */
355     {160, 199, 166, 210}, /* t edge on b edgecase */
356     {170, 200, 176, 210}, /* t edge on b edgecase clipped */
357 };
358
359 static const RECT rectangles[] =
360 {
361     {10,   11, 100, 101},
362     {250, 100, 350,  10},
363     {120,  10, 120,  20}, /* zero width */
364     {120,  10, 130,  10}, /* zero height */
365     {120,  40, 121,  41}, /* 1 x 1 */
366     {130,  50, 132,  52}, /* 2 x 2 */
367     {140,  60, 143,  63}, /* 3 x 3 */
368     {150,  70, 154,  74}, /* 4 x 4 */
369     {120,  20, 121,  30}, /* width == 1 */
370     {130,  20, 132,  30}, /* width == 2 */
371     {140,  20, 143,  30}, /* width == 3 */
372     {200,  20, 210,  21}, /* height == 1 */
373     {200,  30, 210,  32}, /* height == 2 */
374     {200,  40, 210,  43}  /* height == 3 */
375 };
376
377 static const BITMAPINFOHEADER dib_brush_header_32   = {sizeof(BITMAPINFOHEADER), 16, -16, 1, 32, BI_RGB, 0, 0, 0, 0, 0};
378 static const BITMAPINFOHEADER dib_brush_header_555  = {sizeof(BITMAPINFOHEADER), 16, -16, 1, 16, BI_RGB, 0, 0, 0, 0, 0};
379 static const BITMAPINFOHEADER dib_brush_header_8    = {sizeof(BITMAPINFOHEADER), 16, -16, 1,  8, BI_RGB, 0, 0, 0, 0, 0};
380
381 static void draw_graphics(HDC hdc, BITMAPINFO *bmi, BYTE *bits, const char ***sha1)
382 {
383     DWORD dib_size = get_dib_size(bmi);
384     HPEN solid_pen, dashed_pen, orig_pen;
385     HBRUSH solid_brush, dib_brush, orig_brush;
386     INT i, y;
387     HRGN hrgn, hrgn2;
388     BYTE dib_brush_buf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD) + 16 * 16 * sizeof(DWORD)]; /* Enough for 16 x 16 at 32 bpp */
389     BITMAPINFO *brush_bi = (BITMAPINFO*)dib_brush_buf;
390     BYTE *brush_bits;
391
392     memset(bits, 0xcc, dib_size);
393     compare_hash(bmi, bits, sha1, "empty");
394
395     solid_pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0xff));
396     orig_pen = SelectObject(hdc, solid_pen);
397     SetBrushOrgEx(hdc, 0, 0, NULL);
398
399     /* horizontal and vertical lines */
400     for(i = 1; i <= 16; i++)
401     {
402         SetROP2(hdc, i);
403         MoveToEx(hdc, 10, i * 3, NULL);
404         LineTo(hdc, 100, i * 3); /* l -> r */
405         MoveToEx(hdc, 100, 50 + i * 3, NULL);
406         LineTo(hdc, 10, 50 + i * 3); /* r -> l */
407         MoveToEx(hdc, 120 + i * 3, 10, NULL);
408         LineTo(hdc, 120 + i * 3, 100); /* t -> b */
409         MoveToEx(hdc, 170 + i * 3, 100, NULL);
410         LineTo(hdc, 170 + i * 3, 10); /* b -> t */
411     }
412     compare_hash(bmi, bits, sha1, "h and v solid lines");
413     memset(bits, 0xcc, dib_size);
414
415     /* diagonal lines */
416     SetROP2(hdc, R2_COPYPEN);
417     for(i = 0; i < 16; i++)
418     {
419         double s = sin(M_PI * i / 8.0);
420         double c = cos(M_PI * i / 8.0);
421
422         MoveToEx(hdc, 200.5 + 10 * c, 200.5 + 10 * s, NULL);
423         LineTo(hdc, 200.5 + 100 * c, 200.5 + 100 * s);
424     }
425     compare_hash(bmi, bits, sha1, "diagonal solid lines");
426     memset(bits, 0xcc, dib_size);
427
428     for(i = 0; i < sizeof(bias_check) / sizeof(bias_check[0]); i++)
429     {
430         MoveToEx(hdc, bias_check[i].left, bias_check[i].top, NULL);
431         LineTo(hdc, bias_check[i].right, bias_check[i].bottom);
432     }
433     compare_hash(bmi, bits, sha1, "more diagonal solid lines");
434     memset(bits, 0xcc, dib_size);
435
436     /* solid brush PatBlt */
437     solid_brush = CreateSolidBrush(RGB(0x33, 0xaa, 0xff));
438     orig_brush = SelectObject(hdc, solid_brush);
439
440     for(i = 0, y = 10; i < 256; i++)
441     {
442         BOOL ret;
443
444         ret = PatBlt(hdc, 10, y, 100, 10, rop3[i]);
445
446         if(rop_uses_src(rop3[i]))
447             ok(ret == FALSE, "got TRUE for %x\n", rop3[i]);
448         else
449         {
450             ok(ret, "got FALSE for %x\n", rop3[i]);
451             y += 20;
452         }
453
454     }
455     compare_hash(bmi, bits, sha1, "solid patblt");
456     memset(bits, 0xcc, dib_size);
457
458     /* clipped lines */
459     hrgn = CreateRectRgn(10, 10, 200, 20);
460     hrgn2 = CreateRectRgn(100, 100, 200, 200);
461     CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
462     SetRectRgn(hrgn2, 290, 100, 300, 200);
463     CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
464     ExtSelectClipRgn(hdc, hrgn, RGN_COPY);
465     DeleteObject(hrgn2);
466
467     for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
468     {
469         MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL);
470         LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom);
471     }
472     compare_hash(bmi, bits, sha1, "clipped solid hlines");
473     memset(bits, 0xcc, dib_size);
474
475     for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
476     {
477         MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL);
478         LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom);
479     }
480     compare_hash(bmi, bits, sha1, "clipped solid vlines");
481     memset(bits, 0xcc, dib_size);
482
483     for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
484     {
485         MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
486         LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
487     }
488     compare_hash(bmi, bits, sha1, "clipped solid diagonal lines");
489     memset(bits, 0xcc, dib_size);
490
491     /* clipped PatBlt */
492     for(i = 0; i < sizeof(patblt_clips) / sizeof(patblt_clips[0]); i++)
493     {
494         PatBlt(hdc, patblt_clips[i].left, patblt_clips[i].top,
495                patblt_clips[i].right - patblt_clips[i].left,
496                patblt_clips[i].bottom - patblt_clips[i].top, PATCOPY);
497     }
498     compare_hash(bmi, bits, sha1, "clipped patblt");
499     memset(bits, 0xcc, dib_size);
500
501     /* clipped dashed lines */
502     dashed_pen = CreatePen(PS_DASH, 1, RGB(0xff, 0, 0));
503     SelectObject(hdc, dashed_pen);
504     SetBkMode(hdc, TRANSPARENT);
505     SetBkColor(hdc, RGB(0, 0xff, 0));
506
507     for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
508     {
509         MoveToEx(hdc, hline_clips[i].left, hline_clips[i].top, NULL);
510         LineTo(hdc, hline_clips[i].right, hline_clips[i].bottom);
511     }
512     compare_hash(bmi, bits, sha1, "clipped dashed hlines");
513     memset(bits, 0xcc, dib_size);
514
515     for(i = 0; i < sizeof(hline_clips)/sizeof(hline_clips[0]); i++)
516     {
517         MoveToEx(hdc, hline_clips[i].right - 1, hline_clips[i].bottom, NULL);
518         LineTo(hdc, hline_clips[i].left - 1, hline_clips[i].top);
519     }
520     compare_hash(bmi, bits, sha1, "clipped dashed hlines r -> l");
521     memset(bits, 0xcc, dib_size);
522
523     for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
524     {
525         MoveToEx(hdc, vline_clips[i].left, vline_clips[i].top, NULL);
526         LineTo(hdc, vline_clips[i].right, vline_clips[i].bottom);
527     }
528     compare_hash(bmi, bits, sha1, "clipped dashed vlines");
529     memset(bits, 0xcc, dib_size);
530
531     for(i = 0; i < sizeof(vline_clips)/sizeof(vline_clips[0]); i++)
532     {
533         MoveToEx(hdc, vline_clips[i].right, vline_clips[i].bottom - 1, NULL);
534         LineTo(hdc, vline_clips[i].left, vline_clips[i].top - 1);
535     }
536     compare_hash(bmi, bits, sha1, "clipped dashed vlines b -> t");
537     memset(bits, 0xcc, dib_size);
538
539     for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
540     {
541         MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
542         LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
543     }
544     compare_hash(bmi, bits, sha1, "clipped dashed diagonal lines");
545     memset(bits, 0xcc, dib_size);
546
547     SetBkMode(hdc, OPAQUE);
548
549     for(i = 0; i < sizeof(line_clips)/sizeof(line_clips[0]); i++)
550     {
551         MoveToEx(hdc, line_clips[i].left, line_clips[i].top, NULL);
552         LineTo(hdc, line_clips[i].right, line_clips[i].bottom);
553     }
554     compare_hash(bmi, bits, sha1, "clipped opaque dashed diagonal lines");
555     memset(bits, 0xcc, dib_size);
556
557     ExtSelectClipRgn(hdc, NULL, RGN_COPY);
558
559     /* DIB pattern brush */
560
561     brush_bi->bmiHeader = dib_brush_header_32;
562     brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER);
563     memset(brush_bits, 0, 16 * 16 * sizeof(DWORD));
564     brush_bits[2] = 0xff;
565     brush_bits[6] = 0xff;
566     brush_bits[14] = 0xff;
567     brush_bits[65] = 0xff;
568     brush_bits[69] = 0xff;
569
570     dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS);
571
572     SelectObject(hdc, dib_brush);
573     SetBrushOrgEx(hdc, 1, 1, NULL);
574
575     for(i = 0, y = 10; i < 256; i++)
576     {
577         BOOL ret;
578
579         if(!rop_uses_src(rop3[i]))
580         {
581             ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]);
582             ok(ret, "got FALSE for %x\n", rop3[i]);
583             y += 25;
584         }
585     }
586     compare_hash(bmi, bits, sha1, "top-down dib brush patblt");
587     memset(bits, 0xcc, dib_size);
588
589     SelectObject(hdc, orig_brush);
590     DeleteObject(dib_brush);
591
592     /* Bottom-up DIB pattern brush */
593
594     brush_bi->bmiHeader.biHeight = -brush_bi->bmiHeader.biHeight;
595
596     dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS);
597
598     SelectObject(hdc, dib_brush);
599     SetBrushOrgEx(hdc, 100, 100, NULL);
600
601     for(i = 0, y = 10; i < 256; i++)
602     {
603         BOOL ret;
604
605         if(!rop_uses_src(rop3[i]))
606         {
607             ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]);
608             ok(ret, "got FALSE for %x\n", rop3[i]);
609             y += 25;
610         }
611     }
612     compare_hash(bmi, bits, sha1, "bottom-up dib brush patblt");
613     memset(bits, 0xcc, dib_size);
614
615     /* 555 dib pattern brush */
616
617     brush_bi->bmiHeader = dib_brush_header_555;
618     brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER);
619     memset(brush_bits, 0, 16 * 16 * sizeof(WORD));
620     brush_bits[0] = brush_bits[1] = 0xff;
621     brush_bits[32] = brush_bits[34] = 0x7c;
622
623     dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS);
624
625     SelectObject(hdc, dib_brush);
626     SetBrushOrgEx(hdc, 1, 1, NULL);
627
628     for(i = 0, y = 10; i < 256; i++)
629     {
630         BOOL ret;
631
632         if(!rop_uses_src(rop3[i]))
633         {
634             ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]);
635             ok(ret, "got FALSE for %x\n", rop3[i]);
636             y += 25;
637         }
638     }
639     compare_hash(bmi, bits, sha1, "top-down 555 dib brush patblt");
640     memset(bits, 0xcc, dib_size);
641
642     SelectObject(hdc, orig_brush);
643     DeleteObject(dib_brush);
644
645     SetBrushOrgEx(hdc, 0, 0, NULL);
646
647     /* 8 bpp dib pattern brush */
648
649     brush_bi->bmiHeader = dib_brush_header_8;
650     brush_bi->bmiHeader.biClrUsed = 3;
651     memset(brush_bi->bmiColors, 0, brush_bi->bmiHeader.biClrUsed * sizeof(RGBQUAD));
652     brush_bi->bmiColors[0].rgbRed = 0xff;
653     brush_bi->bmiColors[1].rgbRed = 0xff;
654     brush_bi->bmiColors[1].rgbGreen = 0xff;
655     brush_bi->bmiColors[1].rgbBlue = 0xff;
656
657     brush_bits = (BYTE*)brush_bi + sizeof(BITMAPINFOHEADER) + brush_bi->bmiHeader.biClrUsed * sizeof(RGBQUAD);
658     memset(brush_bits, 0, 16 * 16 * sizeof(BYTE));
659     brush_bits[0] = brush_bits[1] = 1;
660     brush_bits[16] = brush_bits[17] = 2;
661     brush_bits[32] = brush_bits[33] = 6;
662
663     dib_brush = CreateDIBPatternBrushPt(brush_bi, DIB_RGB_COLORS);
664
665     SelectObject(hdc, dib_brush);
666     SetBrushOrgEx(hdc, 1, 1, NULL);
667
668     for(i = 0, y = 10; i < 256; i++)
669     {
670         BOOL ret;
671
672         if(!rop_uses_src(rop3[i]))
673         {
674             ret = PatBlt(hdc, 10 + i, y, 100, 20, rop3[i]);
675             ok(ret, "got FALSE for %x\n", rop3[i]);
676             y += 25;
677         }
678     }
679     compare_hash(bmi, bits, sha1, "top-down 8 bpp dib brush patblt");
680     memset(bits, 0xcc, dib_size);
681
682     SelectObject(hdc, orig_brush);
683     DeleteObject(dib_brush);
684
685     /* Rectangle */
686
687     SelectObject(hdc, solid_pen);
688     SelectObject(hdc, solid_brush);
689
690     for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++)
691     {
692         Rectangle(hdc, rectangles[i].left, rectangles[i].top, rectangles[i].right, rectangles[i].bottom);
693     }
694
695     SelectObject(hdc, dashed_pen);
696     for(i = 0; i < sizeof(rectangles)/sizeof(rectangles[0]); i++)
697     {
698         Rectangle(hdc, rectangles[i].left, rectangles[i].top + 150, rectangles[i].right, rectangles[i].bottom + 150);
699     }
700
701     compare_hash(bmi, bits, sha1, "rectangles");
702     memset(bits, 0xcc, dib_size);
703     SelectObject(hdc, solid_pen);
704
705     /* PaintRgn */
706
707     PaintRgn(hdc, hrgn);
708     compare_hash(bmi, bits, sha1, "PaintRgn");
709     memset(bits, 0xcc, dib_size);
710
711     /* RTL rectangles */
712
713     if( !pSetLayout )
714     {
715         win_skip("Don't have SetLayout\n");
716         (*sha1)++;
717     }
718     else
719     {
720         pSetLayout(hdc, LAYOUT_RTL);
721         PaintRgn(hdc, hrgn);
722         PatBlt(hdc, 10, 250, 10, 10, PATCOPY);
723         Rectangle(hdc, 100, 250, 110, 260);
724         compare_hash(bmi, bits, sha1, "rtl");
725         memset(bits, 0xcc, dib_size);
726
727         pSetLayout(hdc, LAYOUT_LTR);
728     }
729
730     SelectObject(hdc, orig_brush);
731     SelectObject(hdc, orig_pen);
732     DeleteObject(hrgn);
733     DeleteObject(dib_brush);
734     DeleteObject(dashed_pen);
735     DeleteObject(solid_brush);
736     DeleteObject(solid_pen);
737 }
738
739 static void test_simple_graphics(void)
740 {
741     char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
742     BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
743     DWORD *bit_fields = (DWORD*)(bmibuf + sizeof(BITMAPINFOHEADER));
744     HDC mem_dc;
745     BYTE *bits;
746     HBITMAP dib, orig_bm;
747     const char **sha1;
748     DIBSECTION ds;
749
750     mem_dc = CreateCompatibleDC(NULL);
751
752     /* a8r8g8b8 */
753     trace("8888\n");
754     memset(bmi, 0, sizeof(bmibuf));
755     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
756     bmi->bmiHeader.biHeight = 512;
757     bmi->bmiHeader.biWidth = 512;
758     bmi->bmiHeader.biBitCount = 32;
759     bmi->bmiHeader.biPlanes = 1;
760     bmi->bmiHeader.biCompression = BI_RGB;
761
762     dib = CreateDIBSection(0, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
763     ok(dib != NULL, "ret NULL\n");
764     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
765     ok(ds.dsBitfields[0] == 0, "got %08x\n", ds.dsBitfields[0]);
766     ok(ds.dsBitfields[1] == 0, "got %08x\n", ds.dsBitfields[1]);
767     ok(ds.dsBitfields[2] == 0, "got %08x\n", ds.dsBitfields[2]);
768     ok(ds.dsBmih.biCompression == BI_RGB ||
769        broken(ds.dsBmih.biCompression == BI_BITFIELDS), /* nt4 sp1 and 2 */
770        "got %x\n", ds.dsBmih.biCompression);
771
772     orig_bm = SelectObject(mem_dc, dib);
773
774     sha1 = sha1_graphics_a8r8g8b8;
775     draw_graphics(mem_dc, bmi, bits, &sha1);
776
777     SelectObject(mem_dc, orig_bm);
778     DeleteObject(dib);
779
780     /* a8r8g8b8 - bitfields.  Should be the same as the regular 32 bit case.*/
781     trace("8888 - bitfields\n");
782     bmi->bmiHeader.biBitCount = 32;
783     bmi->bmiHeader.biCompression = BI_BITFIELDS;
784     bit_fields[0] = 0xff0000;
785     bit_fields[1] = 0x00ff00;
786     bit_fields[2] = 0x0000ff;
787
788     dib = CreateDIBSection(mem_dc, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
789     ok(dib != NULL, "ret NULL\n");
790     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
791     ok(ds.dsBitfields[0] == 0xff0000, "got %08x\n", ds.dsBitfields[0]);
792     ok(ds.dsBitfields[1] == 0x00ff00, "got %08x\n", ds.dsBitfields[1]);
793     ok(ds.dsBitfields[2] == 0x0000ff, "got %08x\n", ds.dsBitfields[2]);
794     ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression);
795
796     orig_bm = SelectObject(mem_dc, dib);
797
798     sha1 = sha1_graphics_a8r8g8b8;
799     draw_graphics(mem_dc, bmi, bits, &sha1);
800
801     SelectObject(mem_dc, orig_bm);
802     DeleteObject(dib);
803
804     /* a8b8g8r8 - bitfields. */
805     trace("a8b8g8r8 - bitfields\n");
806     bmi->bmiHeader.biBitCount = 32;
807     bmi->bmiHeader.biCompression = BI_BITFIELDS;
808     bit_fields[0] = 0x0000ff;
809     bit_fields[1] = 0x00ff00;
810     bit_fields[2] = 0xff0000;
811
812     dib = CreateDIBSection(mem_dc, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
813     ok(dib != NULL, "ret NULL\n");
814     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
815     ok(ds.dsBitfields[0] == 0x0000ff, "got %08x\n", ds.dsBitfields[0]);
816     ok(ds.dsBitfields[1] == 0x00ff00, "got %08x\n", ds.dsBitfields[1]);
817     ok(ds.dsBitfields[2] == 0xff0000, "got %08x\n", ds.dsBitfields[2]);
818     ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression);
819
820     orig_bm = SelectObject(mem_dc, dib);
821
822     sha1 = sha1_graphics_a8b8g8r8;
823     draw_graphics(mem_dc, bmi, bits, &sha1);
824
825     SelectObject(mem_dc, orig_bm);
826     DeleteObject(dib);
827
828     /* r5g5b5 */
829     trace("555\n");
830     bmi->bmiHeader.biBitCount = 16;
831     bmi->bmiHeader.biCompression = BI_RGB;
832
833     dib = CreateDIBSection(0, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
834     ok(dib != NULL, "ret NULL\n");
835     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
836     ok(ds.dsBitfields[0] == 0x7c00, "got %08x\n", ds.dsBitfields[0]);
837     ok(ds.dsBitfields[1] == 0x03e0, "got %08x\n", ds.dsBitfields[1]);
838     ok(ds.dsBitfields[2] == 0x001f, "got %08x\n", ds.dsBitfields[2]);
839 todo_wine
840     ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression);
841
842     orig_bm = SelectObject(mem_dc, dib);
843
844     sha1 = sha1_graphics_r5g5b5;
845     draw_graphics(mem_dc, bmi, bits, &sha1);
846
847     SelectObject(mem_dc, orig_bm);
848     DeleteObject(dib);
849
850     /* r4g4b4 */
851     trace("444\n");
852     bmi->bmiHeader.biBitCount = 16;
853     bmi->bmiHeader.biCompression = BI_BITFIELDS;
854     bit_fields[0] = 0x0f00;
855     bit_fields[1] = 0x00f0;
856     bit_fields[2] = 0x000f;
857     dib = CreateDIBSection(0, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
858     ok(dib != NULL, "ret NULL\n");
859     ok(GetObjectW( dib, sizeof(ds), &ds ), "GetObject failed\n");
860     ok(ds.dsBitfields[0] == 0x0f00, "got %08x\n", ds.dsBitfields[0]);
861     ok(ds.dsBitfields[1] == 0x00f0, "got %08x\n", ds.dsBitfields[1]);
862     ok(ds.dsBitfields[2] == 0x000f, "got %08x\n", ds.dsBitfields[2]);
863     ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression);
864
865     orig_bm = SelectObject(mem_dc, dib);
866
867     sha1 = sha1_graphics_r4g4b4;
868     draw_graphics(mem_dc, bmi, bits, &sha1);
869
870     SelectObject(mem_dc, orig_bm);
871     DeleteObject(dib);
872
873     /* 8 */
874     trace("8\n");
875     bmi->bmiHeader.biBitCount = 8;
876     bmi->bmiHeader.biCompression = BI_RGB;
877     bmi->bmiHeader.biClrUsed = 5;
878     bmi->bmiColors[0].rgbRed = 0xff;
879     bmi->bmiColors[0].rgbGreen = 0xff;
880     bmi->bmiColors[0].rgbBlue = 0xff;
881     bmi->bmiColors[1].rgbRed = 0;
882     bmi->bmiColors[1].rgbGreen = 0;
883     bmi->bmiColors[1].rgbBlue = 0;
884     bmi->bmiColors[2].rgbRed = 0xff;
885     bmi->bmiColors[2].rgbGreen = 0;
886     bmi->bmiColors[2].rgbBlue = 0;
887     bmi->bmiColors[3].rgbRed = 0;
888     bmi->bmiColors[3].rgbGreen = 0xff;
889     bmi->bmiColors[3].rgbBlue = 0;
890     bmi->bmiColors[4].rgbRed = 0;
891     bmi->bmiColors[4].rgbGreen = 0;
892     bmi->bmiColors[4].rgbBlue = 0xff;
893
894     dib = CreateDIBSection(0, bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
895     ok(dib != NULL, "ret NULL\n");
896
897     orig_bm = SelectObject(mem_dc, dib);
898
899     sha1 = sha1_graphics_8;
900     draw_graphics(mem_dc, bmi, bits, &sha1);
901
902     SelectObject(mem_dc, orig_bm);
903     DeleteObject(dib);
904
905     DeleteDC(mem_dc);
906 }
907
908 START_TEST(dib)
909 {
910     HMODULE mod = GetModuleHandleA("gdi32.dll");
911     pSetLayout = (void *)GetProcAddress( mod, "SetLayout" );
912
913     CryptAcquireContextW(&crypt_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
914
915     test_simple_graphics();
916
917     CryptReleaseContext(crypt_prov, 0);
918 }