include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / gdi32 / tests / pen.c
blob2100f046e85614dafcebae89dba8d3f666a31eb5
1 /*
2 * Unit test suite for pens
4 * Copyright 2006 Dmitry Timoshkov
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
28 #include "wine/test.h"
30 #define expect(expected,got) expect_(__LINE__, expected, got)
31 static inline void expect_(unsigned line, DWORD expected, DWORD got)
33 ok_(__FILE__, line)(expected == got, "Expected %.08lx, got %.08lx\n", expected, got);
35 #define expect2(expected,alt,got) expect2_(__LINE__, expected, alt, got)
36 static inline void expect2_(unsigned line, DWORD expected, DWORD alt, DWORD got)
38 ok_(__FILE__, line)(expected == got || alt == got,
39 "Expected %.08lx or %.08lx, got %.08lx\n", expected, alt, got);
42 static void test_logpen(void)
44 static const struct
46 UINT style;
47 INT width;
48 COLORREF color;
49 UINT ret_style;
50 INT ret_width;
51 COLORREF ret_color;
52 } pen[] = {
53 { PS_SOLID, -123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
54 { PS_SOLID, 0, RGB(0x12,0x34,0x56), PS_SOLID, 0, RGB(0x12,0x34,0x56) },
55 { PS_SOLID, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
56 { PS_DASH, 123, RGB(0x12,0x34,0x56), PS_DASH, 123, RGB(0x12,0x34,0x56) },
57 { PS_DOT, 123, RGB(0x12,0x34,0x56), PS_DOT, 123, RGB(0x12,0x34,0x56) },
58 { PS_DASHDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOT, 123, RGB(0x12,0x34,0x56) },
59 { PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56) },
60 { PS_NULL, -123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
61 { PS_NULL, 123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
62 { PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56), PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56) },
63 { PS_USERSTYLE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
64 { PS_ALTERNATE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
65 { 9, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
66 { 10, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
67 { 11, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
68 { 13, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
69 { 14, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
70 { 15, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
72 INT i, size;
73 HPEN hpen;
74 LOGPEN lp;
75 EXTLOGPEN elp;
76 LOGBRUSH lb;
77 DWORD_PTR unset_hatch;
78 DWORD obj_type, user_style[2] = { 0xabc, 0xdef };
79 char elp_buffer[128];
80 EXTLOGPEN *ext_pen = (EXTLOGPEN *)elp_buffer;
81 DWORD *ext_style = ext_pen->elpStyleEntry;
83 for (i = 0; i < ARRAY_SIZE(pen); i++)
85 trace("%d: testing style %u\n", i, pen[i].style);
87 /********************** cosmetic pens **********************/
88 /* CreatePenIndirect behaviour */
89 lp.lopnStyle = pen[i].style;
90 lp.lopnWidth.x = pen[i].width;
91 lp.lopnWidth.y = 11; /* just in case */
92 lp.lopnColor = pen[i].color;
93 SetLastError(0xdeadbeef);
94 hpen = CreatePenIndirect(&lp);
95 if(hpen == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
97 win_skip("No support for pen style %u (%d)\n", pen[i].style, i);
98 continue;
101 obj_type = GetObjectType(hpen);
102 ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
104 memset(&lp, 0xb0, sizeof(lp));
105 SetLastError(0xdeadbeef);
106 size = GetObjectW(hpen, sizeof(lp), &lp);
107 ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
109 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
110 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
111 ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
112 ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
114 DeleteObject(hpen);
116 /* CreatePen behaviour */
117 SetLastError(0xdeadbeef);
118 hpen = CreatePen(pen[i].style, pen[i].width, pen[i].color);
119 ok(hpen != 0, "CreatePen error %ld\n", GetLastError());
121 obj_type = GetObjectType(hpen);
122 ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
124 /* check what's the real size of the object */
125 size = GetObjectW(hpen, 0, NULL);
126 ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
128 /* ask for truncated data */
129 memset(&lp, 0xb0, sizeof(lp));
130 SetLastError(0xdeadbeef);
131 size = GetObjectW(hpen, sizeof(lp.lopnStyle), &lp);
132 ok(!size, "GetObject should fail: size %d, error %ld\n", size, GetLastError());
134 /* see how larger buffer sizes are handled */
135 memset(&lp, 0xb0, sizeof(lp));
136 SetLastError(0xdeadbeef);
137 size = GetObjectW(hpen, sizeof(lp) * 4, &lp);
138 ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
140 /* see how larger buffer sizes are handled */
141 memset(&elp, 0xb0, sizeof(elp));
142 SetLastError(0xdeadbeef);
143 size = GetObjectW(hpen, sizeof(elp) * 2, &elp);
144 ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
146 memset(&lp, 0xb0, sizeof(lp));
147 SetLastError(0xdeadbeef);
148 size = GetObjectW(hpen, sizeof(lp), &lp);
149 ok(size == sizeof(lp), "GetObject returned %d, error %ld\n", size, GetLastError());
151 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
152 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
153 ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
154 ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
156 memset(&elp, 0xb0, sizeof(elp));
157 SetLastError(0xdeadbeef);
158 size = GetObjectW(hpen, sizeof(elp), &elp);
160 /* for some reason XP differentiates PS_NULL here */
161 if (pen[i].style == PS_NULL)
163 ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
164 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]), "GetObject returned %d, error %ld\n",
165 size, GetLastError());
166 ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %lu\n", pen[i].ret_style, elp.elpPenStyle);
167 ok(elp.elpWidth == 0, "expected 0, got %lu\n", elp.elpWidth);
168 ok(elp.elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, elp.elpColor);
169 ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
170 ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
171 ok(elp.elpNumEntries == 0, "expected 0, got %lx\n", elp.elpNumEntries);
173 else
175 ok(size == sizeof(LOGPEN), "GetObject returned %d, error %ld\n", size, GetLastError());
176 memcpy(&lp, &elp, sizeof(lp));
177 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
178 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
179 ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
180 ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
183 DeleteObject(hpen);
185 /********** cosmetic pens created by ExtCreatePen ***********/
186 lb.lbStyle = BS_SOLID;
187 lb.lbColor = pen[i].color;
188 lb.lbHatch = HS_CROSS; /* just in case */
189 SetLastError(0xdeadbeef);
190 hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style);
191 if (pen[i].style != PS_USERSTYLE)
193 ok(hpen == 0, "ExtCreatePen should fail\n");
194 ok(GetLastError() == ERROR_INVALID_PARAMETER,
195 "wrong last error value %ld\n", GetLastError());
196 SetLastError(0xdeadbeef);
197 hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL);
198 if (pen[i].style != PS_NULL)
200 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
201 ok(GetLastError() == ERROR_INVALID_PARAMETER,
202 "wrong last error value %ld\n", GetLastError());
204 SetLastError(0xdeadbeef);
205 hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
208 else
210 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
211 ok(GetLastError() == ERROR_INVALID_PARAMETER,
212 "wrong last error value %ld\n", GetLastError());
213 SetLastError(0xdeadbeef);
214 hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
216 if (pen[i].style == PS_INSIDEFRAME)
218 /* This style is applicable only for geometric pens */
219 ok(hpen == 0, "ExtCreatePen should fail\n");
220 goto test_geometric_pens;
222 if (pen[i].style > PS_ALTERNATE)
224 ok(hpen == 0, "ExtCreatePen should fail\n");
225 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %ld\n", GetLastError());
226 goto test_geometric_pens;
228 ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
230 obj_type = GetObjectType(hpen);
231 /* for some reason XP differentiates PS_NULL here */
232 if (pen[i].style == PS_NULL)
234 ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
235 ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
237 else
238 ok(obj_type == OBJ_EXTPEN, "wrong object type %lu\n", obj_type);
240 /* check what's the real size of the object */
241 SetLastError(0xdeadbeef);
242 size = GetObjectW(hpen, 0, NULL);
243 switch (pen[i].style)
245 case PS_NULL:
246 ok(size == sizeof(LOGPEN),
247 "GetObject returned %d, error %ld\n", size, GetLastError());
248 break;
250 case PS_USERSTYLE:
251 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
252 "GetObject returned %d, error %ld\n", size, GetLastError());
253 break;
255 default:
256 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
257 "GetObject returned %d, error %ld\n", size, GetLastError());
258 break;
261 /* ask for truncated data */
262 memset(&elp, 0xb0, sizeof(elp));
263 SetLastError(0xdeadbeef);
264 size = GetObjectW(hpen, sizeof(elp.elpPenStyle), &elp);
265 ok(!size, "GetObject should fail: size %d, error %ld\n", size, GetLastError());
267 /* see how larger buffer sizes are handled */
268 memset(elp_buffer, 0xb0, sizeof(elp_buffer));
269 SetLastError(0xdeadbeef);
270 size = GetObjectW(hpen, sizeof(elp_buffer), elp_buffer);
271 switch (pen[i].style)
273 case PS_NULL:
274 ok(size == sizeof(LOGPEN),
275 "GetObject returned %d, error %ld\n", size, GetLastError());
276 memcpy(&lp, ext_pen, sizeof(lp));
277 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
278 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
279 ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
280 ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
282 /* for PS_NULL it also works this way */
283 memset(&elp, 0xb0, sizeof(elp));
284 memset(&unset_hatch, 0xb0, sizeof(unset_hatch));
285 SetLastError(0xdeadbeef);
286 size = GetObjectW(hpen, sizeof(elp), &elp);
287 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]),
288 "GetObject returned %d, error %ld\n", size, GetLastError());
289 ok(ext_pen->elpHatch == unset_hatch, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen->elpHatch);
290 ok(ext_pen->elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %lx\n", ext_pen->elpNumEntries);
291 break;
293 case PS_USERSTYLE:
294 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
295 "GetObject returned %d, error %ld\n", size, GetLastError());
296 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
297 ok(ext_pen->elpNumEntries == 2, "expected 0, got %lx\n", ext_pen->elpNumEntries);
298 ok(ext_style[0] == 0xabc, "expected 0xabc, got %lx\n", ext_style[0]);
299 ok(ext_style[1] == 0xdef, "expected 0xdef, got %lx\n", ext_style[1]);
300 break;
302 default:
303 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
304 "GetObject returned %d, error %ld\n", size, GetLastError());
305 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
306 ok(ext_pen->elpNumEntries == 0, "expected 0, got %lx\n", ext_pen->elpNumEntries);
307 break;
310 ok(ext_pen->elpPenStyle == pen[i].style, "expected %x, got %lx\n", pen[i].style, ext_pen->elpPenStyle);
311 ok(ext_pen->elpWidth == 1, "expected 1, got %lx\n", ext_pen->elpWidth);
312 ok(ext_pen->elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, ext_pen->elpColor);
313 ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle);
315 DeleteObject(hpen);
317 test_geometric_pens:
318 /********************** geometric pens **********************/
319 lb.lbStyle = BS_SOLID;
320 lb.lbColor = pen[i].color;
321 lb.lbHatch = HS_CROSS; /* just in case */
322 SetLastError(0xdeadbeef);
323 hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 2, user_style);
324 if (pen[i].style != PS_USERSTYLE)
326 ok(hpen == 0, "ExtCreatePen should fail\n");
327 SetLastError(0xdeadbeef);
328 hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL);
330 if (pen[i].style == PS_ALTERNATE)
332 /* This style is applicable only for cosmetic pens */
333 ok(hpen == 0, "ExtCreatePen should fail\n");
334 continue;
336 if (pen[i].style > PS_ALTERNATE)
338 ok(hpen == 0, "ExtCreatePen should fail\n");
339 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %ld\n", GetLastError());
340 continue;
342 ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
344 obj_type = GetObjectType(hpen);
345 /* for some reason XP differentiates PS_NULL here */
346 if (pen[i].style == PS_NULL)
347 ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
348 else
349 ok(obj_type == OBJ_EXTPEN, "wrong object type %lu\n", obj_type);
351 /* check what's the real size of the object */
352 size = GetObjectW(hpen, 0, NULL);
353 switch (pen[i].style)
355 case PS_NULL:
356 ok(size == sizeof(LOGPEN),
357 "GetObject returned %d, error %ld\n", size, GetLastError());
358 break;
360 case PS_USERSTYLE:
361 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
362 "GetObject returned %d, error %ld\n", size, GetLastError());
363 break;
365 default:
366 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
367 "GetObject returned %d, error %ld\n", size, GetLastError());
368 break;
371 /* ask for truncated data */
372 memset(&lp, 0xb0, sizeof(lp));
373 SetLastError(0xdeadbeef);
374 size = GetObjectW(hpen, sizeof(lp.lopnStyle), &lp);
375 ok(!size, "GetObject should fail: size %d, error %ld\n", size, GetLastError());
377 memset(&lp, 0xb0, sizeof(lp));
378 SetLastError(0xdeadbeef);
379 size = GetObjectW(hpen, sizeof(lp), &lp);
380 /* for some reason XP differentiates PS_NULL here */
381 if (pen[i].style == PS_NULL)
383 ok(size == sizeof(LOGPEN), "GetObject returned %d, error %ld\n", size, GetLastError());
384 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
385 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
386 ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
387 ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
389 else
390 /* XP doesn't set last error here */
391 ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
392 "GetObject should fail: size %d, error %ld\n", size, GetLastError());
394 memset(elp_buffer, 0xb0, sizeof(elp_buffer));
395 SetLastError(0xdeadbeef);
396 /* buffer is too small for user styles */
397 size = GetObjectW(hpen, offsetof(EXTLOGPEN, elpStyleEntry[1]), elp_buffer);
398 switch (pen[i].style)
400 case PS_NULL:
401 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]),
402 "GetObject returned %d, error %ld\n", size, GetLastError());
403 ok(ext_pen->elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen->elpHatch);
404 ok(ext_pen->elpNumEntries == 0, "expected 0, got %lx\n", ext_pen->elpNumEntries);
406 /* for PS_NULL it also works this way */
407 SetLastError(0xdeadbeef);
408 size = GetObjectW(hpen, sizeof(elp_buffer), &lp);
409 ok(size == sizeof(LOGPEN),
410 "GetObject returned %d, error %ld\n", size, GetLastError());
411 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
412 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %ld\n", pen[i].ret_width, lp.lopnWidth.x);
413 ok(lp.lopnWidth.y == 0, "expected 0, got %ld\n", lp.lopnWidth.y);
414 ok(lp.lopnColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, lp.lopnColor);
415 break;
417 case PS_USERSTYLE:
418 ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
419 "GetObject should fail: size %d, error %ld\n", size, GetLastError());
420 size = GetObjectW(hpen, sizeof(elp_buffer), elp_buffer);
421 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
422 "GetObject returned %d, error %ld\n", size, GetLastError());
423 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
424 ok(ext_pen->elpNumEntries == 2, "expected 0, got %lx\n", ext_pen->elpNumEntries);
425 ok(ext_style[0] == 0xabc, "expected 0xabc, got %lx\n", ext_style[0]);
426 ok(ext_style[1] == 0xdef, "expected 0xdef, got %lx\n", ext_style[1]);
427 break;
429 default:
430 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
431 "GetObject returned %d, error %ld\n", size, GetLastError());
432 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
433 ok(ext_pen->elpNumEntries == 0, "expected 0, got %lx\n", ext_pen->elpNumEntries);
434 break;
437 /* for some reason XP differentiates PS_NULL here */
438 if (pen[i].style == PS_NULL)
439 ok(ext_pen->elpPenStyle == pen[i].ret_style, "expected %x, got %lx\n", pen[i].ret_style, ext_pen->elpPenStyle);
440 else
442 ok(ext_pen->elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %lx\n", PS_GEOMETRIC | pen[i].style, ext_pen->elpPenStyle);
445 if (pen[i].style == PS_NULL)
446 ok(ext_pen->elpWidth == 0, "expected 0, got %lx\n", ext_pen->elpWidth);
447 else
448 ok(ext_pen->elpWidth == pen[i].ret_width, "expected %u, got %lx\n", pen[i].ret_width, ext_pen->elpWidth);
449 ok(ext_pen->elpColor == pen[i].ret_color, "expected %08lx, got %08lx\n", pen[i].ret_color, ext_pen->elpColor);
450 ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle);
452 DeleteObject(hpen);
456 static unsigned int atoi2(const char *s)
458 unsigned int ret = 0;
459 while(*s) ret = (ret << 1) | (*s++ == '1');
460 return ret;
463 #define TEST_LINE(x1, x2, z) \
464 { int buf = 0; \
465 SetBitmapBits(bmp, sizeof(buf), &buf); \
466 MoveToEx(hdc, x1, 0, NULL); \
467 LineTo(hdc, x2, 0); \
468 GetBitmapBits(bmp, sizeof(buf), &buf); \
469 expect(atoi2(z), buf); }
471 static void test_ps_alternate(void)
473 HDC hdc;
474 HBITMAP bmp;
475 HPEN pen;
476 LOGBRUSH lb;
477 INT iRet;
478 HGDIOBJ hRet;
480 lb.lbStyle = BS_SOLID;
481 lb.lbColor = RGB(0xff,0xff,0xff);
483 SetLastError(0xdeadbeef);
484 pen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
485 if(pen == NULL && GetLastError() == 0xdeadbeef) {
486 skip("looks like 9x, skipping PS_ALTERNATE tests\n");
487 return;
489 ok(pen != NULL, "gle=%ld\n", GetLastError());
490 hdc = CreateCompatibleDC(NULL);
491 ok(hdc != NULL, "gle=%ld\n", GetLastError());
492 bmp = CreateBitmap(8, 1, 1, 1, NULL);
493 ok(bmp != NULL, "gle=%ld\n", GetLastError());
494 hRet = SelectObject(hdc, bmp);
495 ok(hRet != NULL, "gle=%ld\n", GetLastError());
496 hRet = SelectObject(hdc, pen);
497 ok(hRet != NULL, "gle=%ld\n", GetLastError());
498 iRet = SetBkMode(hdc, TRANSPARENT);
499 ok(iRet, "gle=%ld\n", GetLastError());
501 TEST_LINE(0, 1, "10000000")
502 TEST_LINE(0, 2, "10000000")
503 TEST_LINE(0, 3, "10100000")
504 TEST_LINE(0, 4, "10100000")
505 TEST_LINE(1, 4, "01010000")
506 TEST_LINE(1, 5, "01010000")
507 TEST_LINE(4, 8, "00001010")
509 DeleteObject(pen);
510 DeleteObject(bmp);
511 DeleteDC(hdc);
514 static void test_ps_userstyle(void)
516 static DWORD style[17] = {0, 2, 0, 4, 5, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 17};
517 static DWORD bad_style[5] = {0, 0, 0, 0, 0};
518 static DWORD bad_style2[5] = {4, 7, 8, 3, -1};
520 LOGBRUSH lb;
521 HPEN pen;
522 INT size, i;
523 char buffer[offsetof(EXTLOGPEN, elpStyleEntry) + 16 * sizeof(DWORD)];
524 EXTLOGPEN *ext_pen = (EXTLOGPEN *)buffer;
526 lb.lbColor = 0x00ff0000;
527 lb.lbStyle = BS_SOLID;
528 lb.lbHatch = 0;
530 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 3, NULL);
531 ok(pen == 0, "ExtCreatePen should fail\n");
532 expect(ERROR_INVALID_PARAMETER, GetLastError());
533 DeleteObject(pen);
534 SetLastError(0xdeadbeef);
536 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style);
537 ok(pen == 0, "ExtCreatePen should fail\n");
538 expect2(0xdeadbeef, ERROR_INVALID_PARAMETER, GetLastError());
539 DeleteObject(pen);
540 SetLastError(0xdeadbeef);
542 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 17, style);
543 ok(pen == 0, "ExtCreatePen should fail\n");
544 expect(ERROR_INVALID_PARAMETER, GetLastError());
545 DeleteObject(pen);
546 SetLastError(0xdeadbeef);
548 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, -1, style);
549 ok(pen == 0, "ExtCreatePen should fail\n");
550 expect(0xdeadbeef, GetLastError());
551 DeleteObject(pen);
552 SetLastError(0xdeadbeef);
554 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style);
555 ok(pen == 0, "ExtCreatePen should fail\n");
556 expect(ERROR_INVALID_PARAMETER, GetLastError());
557 DeleteObject(pen);
558 SetLastError(0xdeadbeef);
560 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style2);
561 ok(pen == 0, "ExtCreatePen should fail\n");
562 expect(ERROR_INVALID_PARAMETER, GetLastError());
563 DeleteObject(pen);
564 SetLastError(0xdeadbeef);
566 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 16, style);
567 ok(pen != 0, "ExtCreatePen should not fail\n");
569 size = GetObjectW(pen, sizeof(buffer), ext_pen);
570 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[16]), "wrong size %d\n", size);
572 for(i = 0; i < 16; i++)
573 expect(style[i], ext_pen->elpStyleEntry[i]);
575 DeleteObject(pen);
578 static void test_brush_pens(void)
580 char buffer[offsetof(EXTLOGPEN, elpStyleEntry) + 16 * sizeof(DWORD)];
581 EXTLOGPEN *elp = (EXTLOGPEN *)buffer;
582 LOGBRUSH lb;
583 HPEN pen = 0;
584 DWORD size;
585 HBITMAP bmp = CreateBitmap( 8, 8, 1, 1, NULL );
586 BITMAPINFO *info;
587 HGLOBAL hmem;
589 hmem = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*info) + 16 * 16 * 4 );
590 info = GlobalLock( hmem );
591 info->bmiHeader.biSize = sizeof(info->bmiHeader);
592 info->bmiHeader.biWidth = 16;
593 info->bmiHeader.biHeight = 16;
594 info->bmiHeader.biPlanes = 1;
595 info->bmiHeader.biBitCount = 32;
596 info->bmiHeader.biCompression = BI_RGB;
598 for (lb.lbStyle = BS_SOLID; lb.lbStyle <= BS_MONOPATTERN + 1; lb.lbStyle++)
600 SetLastError( 0xdeadbeef );
601 memset( buffer, 0xcc, sizeof(buffer) );
602 trace( "testing brush style %u\n", lb.lbStyle );
604 switch (lb.lbStyle)
606 case BS_SOLID:
607 case BS_HATCHED:
608 lb.lbColor = RGB(12,34,56);
609 lb.lbHatch = HS_CROSS;
610 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
611 ok( pen != 0, "ExtCreatePen failed err %lu\n", GetLastError() );
612 size = GetObjectW( pen, sizeof(buffer), elp );
613 ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %lu\n", size );
614 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %lx\n", elp->elpPenStyle );
615 ok( elp->elpBrushStyle == lb.lbStyle, "wrong brush style %x\n", elp->elpBrushStyle );
616 ok( elp->elpColor == RGB(12,34,56), "wrong color %lx\n", elp->elpColor );
617 ok( elp->elpHatch == HS_CROSS, "wrong hatch %Ix\n", elp->elpHatch );
618 ok( elp->elpNumEntries == 0, "wrong entries %lx\n", elp->elpNumEntries );
619 break;
621 case BS_NULL:
622 pen = ExtCreatePen( PS_SOLID | PS_GEOMETRIC, 3, &lb, 0, NULL );
623 ok( pen != 0, "ExtCreatePen failed err %lu\n", GetLastError() );
624 size = GetObjectW( pen, sizeof(buffer), elp );
625 ok( size == sizeof(LOGPEN), "wrong size %lu\n", size );
626 ok( ((LOGPEN *)elp)->lopnStyle == PS_NULL,
627 "wrong pen style %x\n", ((LOGPEN *)elp)->lopnStyle );
628 ok( ((LOGPEN *)elp)->lopnColor == 0,
629 "wrong color %lx\n", ((LOGPEN *)elp)->lopnColor );
630 break;
632 case BS_PATTERN:
633 lb.lbColor = RGB(12,34,56);
634 lb.lbHatch = (ULONG_PTR)bmp;
635 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
636 ok( pen != 0, "ExtCreatePen failed err %lu\n", GetLastError() );
637 size = GetObjectW( pen, sizeof(buffer), elp );
638 ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %lu\n", size );
639 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %lx\n", elp->elpPenStyle );
640 ok( elp->elpBrushStyle == BS_PATTERN, "wrong brush style %x\n", elp->elpBrushStyle );
641 ok( elp->elpColor == 0, "wrong color %lx\n", elp->elpColor );
642 ok( elp->elpHatch == (ULONG_PTR)bmp, "wrong hatch %Ix/%p\n", elp->elpHatch, bmp );
643 ok( elp->elpNumEntries == 0, "wrong entries %lx\n", elp->elpNumEntries );
644 break;
646 case BS_DIBPATTERN:
647 case BS_DIBPATTERNPT:
648 lb.lbColor = DIB_PAL_COLORS;
649 lb.lbHatch = lb.lbStyle == BS_DIBPATTERN ? (ULONG_PTR)hmem : (ULONG_PTR)info;
650 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
651 ok( pen != 0, "ExtCreatePen failed err %lu\n", GetLastError() );
652 size = GetObjectW( pen, sizeof(buffer), elp );
653 ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %lu\n", size );
654 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %lx\n", elp->elpPenStyle );
655 ok( elp->elpBrushStyle == BS_DIBPATTERNPT, "wrong brush style %x\n", elp->elpBrushStyle );
656 ok( elp->elpColor == 0, "wrong color %lx\n", elp->elpColor );
657 ok( elp->elpHatch == lb.lbHatch, "wrong hatch %Ix/%Ix\n", elp->elpHatch, lb.lbHatch );
658 ok( elp->elpNumEntries == 0, "wrong entries %lx\n", elp->elpNumEntries );
659 break;
661 default:
662 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
663 ok( !pen, "ExtCreatePen succeeded\n" );
664 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
665 break;
668 if (pen) DeleteObject( pen );
669 else continue;
671 /* cosmetic pens require BS_SOLID */
672 SetLastError( 0xdeadbeef );
673 pen = ExtCreatePen( PS_DOT, 1, &lb, 0, NULL );
674 if (lb.lbStyle == BS_SOLID)
676 ok( pen != 0, "ExtCreatePen failed err %lu\n", GetLastError() );
677 size = GetObjectW( pen, sizeof(buffer), elp );
678 ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %lu\n", size );
679 ok( elp->elpPenStyle == PS_DOT, "wrong pen style %lx\n", elp->elpPenStyle );
680 ok( elp->elpBrushStyle == BS_SOLID, "wrong brush style %x\n", elp->elpBrushStyle );
681 ok( elp->elpColor == RGB(12,34,56), "wrong color %lx\n", elp->elpColor );
682 ok( elp->elpHatch == HS_CROSS, "wrong hatch %Ix\n", elp->elpHatch );
683 DeleteObject( pen );
685 else
687 ok( !pen, "ExtCreatePen succeeded\n" );
688 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
692 GlobalUnlock( hmem );
693 GlobalFree( hmem );
694 DeleteObject( bmp );
697 START_TEST(pen)
699 test_logpen();
700 test_brush_pens();
701 test_ps_alternate();
702 test_ps_userstyle();