libwine: Add libwine's directory (@loader_path) to rpath.
[wine.git] / dlls / gdi32 / tests / pen.c
blobed7927a334308f3a55c4a92002ff21cfbee11dc5
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) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
31 #define expect2(expected, alt, got) ok(got == expected || got == alt, \
32 "Expected %.8x or %.8x, got %.8x\n", expected, alt, got)
34 static void test_logpen(void)
36 static const struct
38 UINT style;
39 INT width;
40 COLORREF color;
41 UINT ret_style;
42 INT ret_width;
43 COLORREF ret_color;
44 } pen[] = {
45 { PS_SOLID, -123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
46 { PS_SOLID, 0, RGB(0x12,0x34,0x56), PS_SOLID, 0, RGB(0x12,0x34,0x56) },
47 { PS_SOLID, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
48 { PS_DASH, 123, RGB(0x12,0x34,0x56), PS_DASH, 123, RGB(0x12,0x34,0x56) },
49 { PS_DOT, 123, RGB(0x12,0x34,0x56), PS_DOT, 123, RGB(0x12,0x34,0x56) },
50 { PS_DASHDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOT, 123, RGB(0x12,0x34,0x56) },
51 { PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56), PS_DASHDOTDOT, 123, RGB(0x12,0x34,0x56) },
52 { PS_NULL, -123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
53 { PS_NULL, 123, RGB(0x12,0x34,0x56), PS_NULL, 1, 0 },
54 { PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56), PS_INSIDEFRAME, 123, RGB(0x12,0x34,0x56) },
55 { PS_USERSTYLE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
56 { PS_ALTERNATE, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
57 { 9, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
58 { 10, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
59 { 11, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
60 { 13, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
61 { 14, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
62 { 15, 123, RGB(0x12,0x34,0x56), PS_SOLID, 123, RGB(0x12,0x34,0x56) },
64 INT i, size;
65 HPEN hpen;
66 LOGPEN lp;
67 EXTLOGPEN elp;
68 LOGBRUSH lb;
69 DWORD_PTR unset_hatch;
70 DWORD obj_type, user_style[2] = { 0xabc, 0xdef };
71 char elp_buffer[128];
72 EXTLOGPEN *ext_pen = (EXTLOGPEN *)elp_buffer;
73 DWORD *ext_style = ext_pen->elpStyleEntry;
75 for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++)
77 trace("%d: testing style %u\n", i, pen[i].style);
79 /********************** cosmetic pens **********************/
80 /* CreatePenIndirect behaviour */
81 lp.lopnStyle = pen[i].style,
82 lp.lopnWidth.x = pen[i].width;
83 lp.lopnWidth.y = 11; /* just in case */
84 lp.lopnColor = pen[i].color;
85 SetLastError(0xdeadbeef);
86 hpen = CreatePenIndirect(&lp);
87 if(hpen == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
89 win_skip("No support for pen style %u (%d)\n", pen[i].style, i);
90 continue;
93 obj_type = GetObjectType(hpen);
94 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
96 memset(&lp, 0xb0, sizeof(lp));
97 SetLastError(0xdeadbeef);
98 size = GetObject(hpen, sizeof(lp), &lp);
99 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
101 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
102 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
103 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
104 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
106 DeleteObject(hpen);
108 /* CreatePen behaviour */
109 SetLastError(0xdeadbeef);
110 hpen = CreatePen(pen[i].style, pen[i].width, pen[i].color);
111 ok(hpen != 0, "CreatePen error %d\n", GetLastError());
113 obj_type = GetObjectType(hpen);
114 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
116 /* check what's the real size of the object */
117 size = GetObject(hpen, 0, NULL);
118 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
120 /* ask for truncated data */
121 memset(&lp, 0xb0, sizeof(lp));
122 SetLastError(0xdeadbeef);
123 size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
124 ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
126 /* see how larger buffer sizes are handled */
127 memset(&lp, 0xb0, sizeof(lp));
128 SetLastError(0xdeadbeef);
129 size = GetObject(hpen, sizeof(lp) * 4, &lp);
130 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
132 /* see how larger buffer sizes are handled */
133 memset(&elp, 0xb0, sizeof(elp));
134 SetLastError(0xdeadbeef);
135 size = GetObject(hpen, sizeof(elp) * 2, &elp);
136 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
138 memset(&lp, 0xb0, sizeof(lp));
139 SetLastError(0xdeadbeef);
140 size = GetObject(hpen, sizeof(lp), &lp);
141 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
143 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
144 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
145 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
146 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
148 memset(&elp, 0xb0, sizeof(elp));
149 SetLastError(0xdeadbeef);
150 size = GetObject(hpen, sizeof(elp), &elp);
152 /* for some reason XP differentiates PS_NULL here */
153 if (pen[i].style == PS_NULL)
155 ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
156 ok(size == sizeof(EXTLOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
157 ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, elp.elpPenStyle);
158 ok(elp.elpWidth == 0, "expected 0, got %u\n", elp.elpWidth);
159 ok(elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, elp.elpColor);
160 ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
161 ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
162 ok(elp.elpNumEntries == 0, "expected 0, got %x\n", elp.elpNumEntries);
164 else
166 ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
167 memcpy(&lp, &elp, sizeof(lp));
168 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
169 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
170 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
171 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
174 DeleteObject(hpen);
176 /********** cosmetic pens created by ExtCreatePen ***********/
177 lb.lbStyle = BS_SOLID;
178 lb.lbColor = pen[i].color;
179 lb.lbHatch = HS_CROSS; /* just in case */
180 SetLastError(0xdeadbeef);
181 hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style);
182 if (pen[i].style != PS_USERSTYLE)
184 ok(hpen == 0, "ExtCreatePen should fail\n");
185 ok(GetLastError() == ERROR_INVALID_PARAMETER,
186 "wrong last error value %d\n", GetLastError());
187 SetLastError(0xdeadbeef);
188 hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL);
189 if (pen[i].style != PS_NULL)
191 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
192 ok(GetLastError() == ERROR_INVALID_PARAMETER,
193 "wrong last error value %d\n", GetLastError());
195 SetLastError(0xdeadbeef);
196 hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
199 else
201 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
202 ok(GetLastError() == ERROR_INVALID_PARAMETER,
203 "wrong last error value %d\n", GetLastError());
204 SetLastError(0xdeadbeef);
205 hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
207 if (pen[i].style == PS_INSIDEFRAME)
209 /* This style is applicable only for geometric pens */
210 ok(hpen == 0, "ExtCreatePen should fail\n");
211 goto test_geometric_pens;
213 if (pen[i].style > PS_ALTERNATE)
215 ok(hpen == 0, "ExtCreatePen should fail\n");
216 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError());
217 goto test_geometric_pens;
219 ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
221 obj_type = GetObjectType(hpen);
222 /* for some reason XP differentiates PS_NULL here */
223 if (pen[i].style == PS_NULL)
225 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
226 ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
228 else
229 ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
231 /* check what's the real size of the object */
232 SetLastError(0xdeadbeef);
233 size = GetObject(hpen, 0, NULL);
234 switch (pen[i].style)
236 case PS_NULL:
237 ok(size == sizeof(LOGPEN),
238 "GetObject returned %d, error %d\n", size, GetLastError());
239 break;
241 case PS_USERSTYLE:
242 ok(size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry[2] ),
243 "GetObject returned %d, error %d\n", size, GetLastError());
244 break;
246 default:
247 ok(size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ),
248 "GetObject returned %d, error %d\n", size, GetLastError());
249 break;
252 /* ask for truncated data */
253 memset(&elp, 0xb0, sizeof(elp));
254 SetLastError(0xdeadbeef);
255 size = GetObject(hpen, sizeof(elp.elpPenStyle), &elp);
256 ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
258 /* see how larger buffer sizes are handled */
259 memset(elp_buffer, 0xb0, sizeof(elp_buffer));
260 SetLastError(0xdeadbeef);
261 size = GetObject(hpen, sizeof(elp_buffer), elp_buffer);
262 switch (pen[i].style)
264 case PS_NULL:
265 ok(size == sizeof(LOGPEN),
266 "GetObject returned %d, error %d\n", size, GetLastError());
267 memcpy(&lp, ext_pen, sizeof(lp));
268 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
269 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
270 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
271 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
273 /* for PS_NULL it also works this way */
274 memset(&elp, 0xb0, sizeof(elp));
275 memset(&unset_hatch, 0xb0, sizeof(unset_hatch));
276 SetLastError(0xdeadbeef);
277 size = GetObject(hpen, sizeof(elp), &elp);
278 ok(size == sizeof(EXTLOGPEN),
279 "GetObject returned %d, error %d\n", size, GetLastError());
280 ok(ext_pen->elpHatch == unset_hatch, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen->elpHatch);
281 ok(ext_pen->elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %x\n", ext_pen->elpNumEntries);
282 break;
284 case PS_USERSTYLE:
285 ok(size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry[2] ),
286 "GetObject returned %d, error %d\n", size, GetLastError());
287 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
288 ok(ext_pen->elpNumEntries == 2, "expected 0, got %x\n", ext_pen->elpNumEntries);
289 ok(ext_style[0] == 0xabc, "expected 0xabc, got %x\n", ext_style[0]);
290 ok(ext_style[1] == 0xdef, "expected 0xdef, got %x\n", ext_style[1]);
291 break;
293 default:
294 ok(size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ),
295 "GetObject returned %d, error %d\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 == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
298 break;
301 ok(ext_pen->elpPenStyle == pen[i].style, "expected %x, got %x\n", pen[i].style, ext_pen->elpPenStyle);
302 ok(ext_pen->elpWidth == 1, "expected 1, got %x\n", ext_pen->elpWidth);
303 ok(ext_pen->elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen->elpColor);
304 ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle);
306 DeleteObject(hpen);
308 test_geometric_pens:
309 /********************** geometric pens **********************/
310 lb.lbStyle = BS_SOLID;
311 lb.lbColor = pen[i].color;
312 lb.lbHatch = HS_CROSS; /* just in case */
313 SetLastError(0xdeadbeef);
314 hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 2, user_style);
315 if (pen[i].style != PS_USERSTYLE)
317 ok(hpen == 0, "ExtCreatePen should fail\n");
318 SetLastError(0xdeadbeef);
319 hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL);
321 if (pen[i].style == PS_ALTERNATE)
323 /* This style is applicable only for cosmetic pens */
324 ok(hpen == 0, "ExtCreatePen should fail\n");
325 continue;
327 if (pen[i].style > PS_ALTERNATE)
329 ok(hpen == 0, "ExtCreatePen should fail\n");
330 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError());
331 continue;
333 ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
335 obj_type = GetObjectType(hpen);
336 /* for some reason XP differentiates PS_NULL here */
337 if (pen[i].style == PS_NULL)
338 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
339 else
340 ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
342 /* check what's the real size of the object */
343 size = GetObject(hpen, 0, NULL);
344 switch (pen[i].style)
346 case PS_NULL:
347 ok(size == sizeof(LOGPEN),
348 "GetObject returned %d, error %d\n", size, GetLastError());
349 break;
351 case PS_USERSTYLE:
352 ok(size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry[2] ),
353 "GetObject returned %d, error %d\n", size, GetLastError());
354 break;
356 default:
357 ok(size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ),
358 "GetObject returned %d, error %d\n", size, GetLastError());
359 break;
362 /* ask for truncated data */
363 memset(&lp, 0xb0, sizeof(lp));
364 SetLastError(0xdeadbeef);
365 size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
366 ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
368 memset(&lp, 0xb0, sizeof(lp));
369 SetLastError(0xdeadbeef);
370 size = GetObject(hpen, sizeof(lp), &lp);
371 /* for some reason XP differentiates PS_NULL here */
372 if (pen[i].style == PS_NULL)
374 ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
375 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
376 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
377 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
378 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
380 else
381 /* XP doesn't set last error here */
382 ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
383 "GetObject should fail: size %d, error %d\n", size, GetLastError());
385 memset(elp_buffer, 0xb0, sizeof(elp_buffer));
386 SetLastError(0xdeadbeef);
387 /* buffer is too small for user styles */
388 size = GetObject(hpen, sizeof(EXTLOGPEN), elp_buffer);
389 switch (pen[i].style)
391 case PS_NULL:
392 ok(size == sizeof(EXTLOGPEN),
393 "GetObject returned %d, error %d\n", size, GetLastError());
394 ok(ext_pen->elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen->elpHatch);
395 ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
397 /* for PS_NULL it also works this way */
398 SetLastError(0xdeadbeef);
399 size = GetObject(hpen, sizeof(elp_buffer), &lp);
400 ok(size == sizeof(LOGPEN),
401 "GetObject returned %d, error %d\n", size, GetLastError());
402 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
403 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
404 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
405 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
406 break;
408 case PS_USERSTYLE:
409 ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
410 "GetObject should fail: size %d, error %d\n", size, GetLastError());
411 size = GetObject(hpen, sizeof(elp_buffer), elp_buffer);
412 ok(size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry[2] ),
413 "GetObject returned %d, error %d\n", size, GetLastError());
414 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
415 ok(ext_pen->elpNumEntries == 2, "expected 0, got %x\n", ext_pen->elpNumEntries);
416 ok(ext_style[0] == 0xabc, "expected 0xabc, got %x\n", ext_style[0]);
417 ok(ext_style[1] == 0xdef, "expected 0xdef, got %x\n", ext_style[1]);
418 break;
420 default:
421 ok(size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ),
422 "GetObject returned %d, error %d\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 == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
425 break;
428 /* for some reason XP differentiates PS_NULL here */
429 if (pen[i].style == PS_NULL)
430 ok(ext_pen->elpPenStyle == pen[i].ret_style, "expected %x, got %x\n", pen[i].ret_style, ext_pen->elpPenStyle);
431 else
433 ok(ext_pen->elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %x\n", PS_GEOMETRIC | pen[i].style, ext_pen->elpPenStyle);
436 if (pen[i].style == PS_NULL)
437 ok(ext_pen->elpWidth == 0, "expected 0, got %x\n", ext_pen->elpWidth);
438 else
439 ok(ext_pen->elpWidth == pen[i].ret_width, "expected %u, got %x\n", pen[i].ret_width, ext_pen->elpWidth);
440 ok(ext_pen->elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen->elpColor);
441 ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle);
443 DeleteObject(hpen);
447 static unsigned int atoi2(const char *s)
449 unsigned int ret = 0;
450 while(*s) ret = (ret << 1) | (*s++ == '1');
451 return ret;
454 #define TEST_LINE(x1, x2, z) \
455 { int buf = 0; \
456 SetBitmapBits(bmp, sizeof(buf), &buf); \
457 MoveToEx(hdc, x1, 0, NULL); \
458 LineTo(hdc, x2, 0); \
459 GetBitmapBits(bmp, sizeof(buf), &buf); \
460 expect(atoi2(z), buf); }
462 static void test_ps_alternate(void)
464 HDC hdc;
465 HBITMAP bmp;
466 HPEN pen;
467 LOGBRUSH lb;
468 INT iRet;
469 HGDIOBJ hRet;
471 lb.lbStyle = BS_SOLID;
472 lb.lbColor = RGB(0xff,0xff,0xff);
474 SetLastError(0xdeadbeef);
475 pen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
476 if(pen == NULL && GetLastError() == 0xdeadbeef) {
477 skip("looks like 9x, skipping PS_ALTERNATE tests\n");
478 return;
480 ok(pen != NULL, "gle=%d\n", GetLastError());
481 hdc = CreateCompatibleDC(NULL);
482 ok(hdc != NULL, "gle=%d\n", GetLastError());
483 bmp = CreateBitmap(8, 1, 1, 1, NULL);
484 ok(bmp != NULL, "gle=%d\n", GetLastError());
485 hRet = SelectObject(hdc, bmp);
486 ok(hRet != NULL, "gle=%d\n", GetLastError());
487 hRet = SelectObject(hdc, pen);
488 ok(hRet != NULL, "gle=%d\n", GetLastError());
489 iRet = SetBkMode(hdc, TRANSPARENT);
490 ok(iRet, "gle=%d\n", GetLastError());
492 TEST_LINE(0, 1, "10000000")
493 TEST_LINE(0, 2, "10000000")
494 TEST_LINE(0, 3, "10100000")
495 TEST_LINE(0, 4, "10100000")
496 TEST_LINE(1, 4, "01010000")
497 TEST_LINE(1, 5, "01010000")
498 TEST_LINE(4, 8, "00001010")
500 DeleteObject(pen);
501 DeleteObject(bmp);
502 DeleteDC(hdc);
505 static void test_ps_userstyle(void)
507 static DWORD style[17] = {0, 2, 0, 4, 5, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 17};
508 static DWORD bad_style[5] = {0, 0, 0, 0, 0};
509 static DWORD bad_style2[5] = {4, 7, 8, 3, -1};
511 LOGBRUSH lb;
512 HPEN pen;
513 INT size, i;
515 struct
517 EXTLOGPEN elp;
518 DWORD style_data[15];
519 } ext_pen;
521 lb.lbColor = 0x00ff0000;
522 lb.lbStyle = BS_SOLID;
523 lb.lbHatch = 0;
525 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 3, NULL);
526 ok(pen == 0, "ExtCreatePen should fail\n");
527 expect(ERROR_INVALID_PARAMETER, GetLastError());
528 DeleteObject(pen);
529 SetLastError(0xdeadbeef);
531 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style);
532 ok(pen == 0, "ExtCreatePen should fail\n");
533 expect2(0xdeadbeef, ERROR_INVALID_PARAMETER, GetLastError());
534 DeleteObject(pen);
535 SetLastError(0xdeadbeef);
537 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 17, style);
538 ok(pen == 0, "ExtCreatePen should fail\n");
539 expect(ERROR_INVALID_PARAMETER, GetLastError());
540 DeleteObject(pen);
541 SetLastError(0xdeadbeef);
543 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, -1, style);
544 ok(pen == 0, "ExtCreatePen should fail\n");
545 expect(0xdeadbeef, GetLastError());
546 DeleteObject(pen);
547 SetLastError(0xdeadbeef);
549 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style);
550 ok(pen == 0, "ExtCreatePen should fail\n");
551 expect(ERROR_INVALID_PARAMETER, GetLastError());
552 DeleteObject(pen);
553 SetLastError(0xdeadbeef);
555 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style2);
556 ok(pen == 0, "ExtCreatePen should fail\n");
557 expect(ERROR_INVALID_PARAMETER, GetLastError());
558 DeleteObject(pen);
559 SetLastError(0xdeadbeef);
561 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 16, style);
562 ok(pen != 0, "ExtCreatePen should not fail\n");
564 size = GetObject(pen, sizeof(ext_pen), &ext_pen);
565 expect(FIELD_OFFSET(EXTLOGPEN,elpStyleEntry[16]), size);
567 for(i = 0; i < 16; i++)
568 expect(style[i], ext_pen.elp.elpStyleEntry[i]);
570 DeleteObject(pen);
573 static void test_brush_pens(void)
575 char buffer[sizeof(EXTLOGPEN) + 15 * sizeof(DWORD)];
576 EXTLOGPEN *elp = (EXTLOGPEN *)buffer;
577 LOGBRUSH lb;
578 HPEN pen = 0;
579 DWORD size;
580 HBITMAP bmp = CreateBitmap( 8, 8, 1, 1, NULL );
581 BITMAPINFO *info;
582 HGLOBAL hmem;
584 hmem = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*info) + 16 * 16 * 4 );
585 info = GlobalLock( hmem );
586 info->bmiHeader.biSize = sizeof(info->bmiHeader);
587 info->bmiHeader.biWidth = 16;
588 info->bmiHeader.biHeight = 16;
589 info->bmiHeader.biPlanes = 1;
590 info->bmiHeader.biBitCount = 32;
591 info->bmiHeader.biCompression = BI_RGB;
593 for (lb.lbStyle = BS_SOLID; lb.lbStyle <= BS_MONOPATTERN + 1; lb.lbStyle++)
595 SetLastError( 0xdeadbeef );
596 memset( buffer, 0xcc, sizeof(buffer) );
597 trace( "testing brush style %u\n", lb.lbStyle );
599 switch (lb.lbStyle)
601 case BS_SOLID:
602 case BS_HATCHED:
603 lb.lbColor = RGB(12,34,56);
604 lb.lbHatch = HS_CROSS;
605 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
606 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
607 size = GetObject( pen, sizeof(buffer), elp );
608 ok( size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
609 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
610 ok( elp->elpBrushStyle == lb.lbStyle, "wrong brush style %x\n", elp->elpBrushStyle );
611 ok( elp->elpColor == RGB(12,34,56), "wrong color %x\n", elp->elpColor );
612 ok( elp->elpHatch == HS_CROSS, "wrong hatch %lx\n", elp->elpHatch );
613 ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
614 break;
616 case BS_NULL:
617 pen = ExtCreatePen( PS_SOLID | PS_GEOMETRIC, 3, &lb, 0, NULL );
618 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
619 size = GetObject( pen, sizeof(buffer), elp );
620 ok( size == sizeof(LOGPEN), "wrong size %u\n", size );
621 ok( ((LOGPEN *)elp)->lopnStyle == PS_NULL,
622 "wrong pen style %x\n", ((LOGPEN *)elp)->lopnStyle );
623 ok( ((LOGPEN *)elp)->lopnColor == 0,
624 "wrong color %x\n", ((LOGPEN *)elp)->lopnColor );
625 break;
627 case BS_PATTERN:
628 lb.lbColor = RGB(12,34,56);
629 lb.lbHatch = (ULONG_PTR)bmp;
630 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
631 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
632 size = GetObject( pen, sizeof(buffer), elp );
633 ok( size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
634 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
635 ok( elp->elpBrushStyle == BS_PATTERN, "wrong brush style %x\n", elp->elpBrushStyle );
636 ok( elp->elpColor == 0, "wrong color %x\n", elp->elpColor );
637 ok( elp->elpHatch == (ULONG_PTR)bmp, "wrong hatch %lx/%p\n", elp->elpHatch, bmp );
638 ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
639 break;
641 case BS_DIBPATTERN:
642 case BS_DIBPATTERNPT:
643 lb.lbColor = DIB_PAL_COLORS;
644 lb.lbHatch = lb.lbStyle == BS_DIBPATTERN ? (ULONG_PTR)hmem : (ULONG_PTR)info;
645 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
646 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
647 size = GetObject( pen, sizeof(buffer), elp );
648 ok( size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
649 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
650 ok( elp->elpBrushStyle == BS_DIBPATTERNPT, "wrong brush style %x\n", elp->elpBrushStyle );
651 ok( elp->elpColor == 0, "wrong color %x\n", elp->elpColor );
652 ok( elp->elpHatch == lb.lbHatch || broken(elp->elpHatch != lb.lbHatch), /* <= w2k */
653 "wrong hatch %lx/%lx\n", elp->elpHatch, lb.lbHatch );
654 ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
655 break;
657 default:
658 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
659 ok( !pen, "ExtCreatePen succeeded\n" );
660 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
661 break;
664 if (pen) DeleteObject( pen );
665 else continue;
667 /* cosmetic pens require BS_SOLID */
668 SetLastError( 0xdeadbeef );
669 pen = ExtCreatePen( PS_DOT, 1, &lb, 0, NULL );
670 if (lb.lbStyle == BS_SOLID)
672 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
673 size = GetObject( pen, sizeof(buffer), elp );
674 ok( size == FIELD_OFFSET( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
675 ok( elp->elpPenStyle == PS_DOT, "wrong pen style %x\n", elp->elpPenStyle );
676 ok( elp->elpBrushStyle == BS_SOLID, "wrong brush style %x\n", elp->elpBrushStyle );
677 ok( elp->elpColor == RGB(12,34,56), "wrong color %x\n", elp->elpColor );
678 ok( elp->elpHatch == HS_CROSS, "wrong hatch %lx\n", elp->elpHatch );
679 DeleteObject( pen );
681 else
683 ok( !pen, "ExtCreatePen succeeded\n" );
684 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
688 GlobalUnlock( hmem );
689 GlobalFree( hmem );
690 DeleteObject( bmp );
693 START_TEST(pen)
695 test_logpen();
696 test_brush_pens();
697 test_ps_alternate();
698 test_ps_userstyle();