wineps: Fix a couple of typos in the path painting function.
[wine/testsucceed.git] / dlls / gdi32 / tests / pen.c
blob86250a0ea1c92850b5b02016129f8aa6f4761807
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) }
58 INT i, size;
59 HPEN hpen;
60 LOGPEN lp;
61 EXTLOGPEN elp;
62 LOGBRUSH lb;
63 DWORD_PTR unset_hatch;
64 DWORD obj_type, user_style[2] = { 0xabc, 0xdef };
65 struct
67 EXTLOGPEN elp;
68 DWORD style_data[10];
69 } ext_pen;
71 for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++)
73 trace("%d: testing style %u\n", i, pen[i].style);
75 /********************** cosmetic pens **********************/
76 /* CreatePenIndirect behaviour */
77 lp.lopnStyle = pen[i].style,
78 lp.lopnWidth.x = pen[i].width;
79 lp.lopnWidth.y = 11; /* just in case */
80 lp.lopnColor = pen[i].color;
81 SetLastError(0xdeadbeef);
82 hpen = CreatePenIndirect(&lp);
83 if(hpen == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
85 win_skip("No support for pen style %u (%d)\n", pen[i].style, i);
86 continue;
89 obj_type = GetObjectType(hpen);
90 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
92 memset(&lp, 0xb0, sizeof(lp));
93 SetLastError(0xdeadbeef);
94 size = GetObject(hpen, sizeof(lp), &lp);
95 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
97 if (pen[i].style == PS_USERSTYLE || pen[i].style == PS_ALTERNATE)
99 if (lp.lopnStyle == pen[i].style)
101 win_skip("Skipping PS_USERSTYLE and PS_ALTERNATE tests on Win9x\n");
102 continue;
105 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
106 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
107 ok(lp.lopnWidth.y == 0 ||
108 broken(lp.lopnWidth.y == 0xb), /* Win9x */
109 "expected 0, got %d\n", lp.lopnWidth.y);
110 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
112 DeleteObject(hpen);
114 /* CreatePen behaviour */
115 SetLastError(0xdeadbeef);
116 hpen = CreatePen(pen[i].style, pen[i].width, pen[i].color);
117 ok(hpen != 0, "CreatePen error %d\n", GetLastError());
119 obj_type = GetObjectType(hpen);
120 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
122 /* check what's the real size of the object */
123 size = GetObject(hpen, 0, NULL);
124 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
126 /* ask for truncated data */
127 memset(&lp, 0xb0, sizeof(lp));
128 SetLastError(0xdeadbeef);
129 size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
130 ok(!size ||
131 broken(size == sizeof(lp.lopnStyle)), /* Win9x */
132 "GetObject should fail: size %d, error %d\n", size, GetLastError());
134 /* see how larger buffer sizes are handled */
135 memset(&lp, 0xb0, sizeof(lp));
136 SetLastError(0xdeadbeef);
137 size = GetObject(hpen, sizeof(lp) * 4, &lp);
138 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
140 /* see how larger buffer sizes are handled */
141 memset(&elp, 0xb0, sizeof(elp));
142 SetLastError(0xdeadbeef);
143 size = GetObject(hpen, sizeof(elp) * 2, &elp);
144 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
146 memset(&lp, 0xb0, sizeof(lp));
147 SetLastError(0xdeadbeef);
148 size = GetObject(hpen, sizeof(lp), &lp);
149 ok(size == sizeof(lp), "GetObject returned %d, error %d\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 %d\n", pen[i].ret_width, lp.lopnWidth.x);
153 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
154 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
156 memset(&elp, 0xb0, sizeof(elp));
157 SetLastError(0xdeadbeef);
158 size = GetObject(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 == sizeof(EXTLOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
165 ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, elp.elpPenStyle);
166 ok(elp.elpWidth == 0, "expected 0, got %u\n", elp.elpWidth);
167 ok(elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, elp.elpColor);
168 ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
169 ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
170 ok(elp.elpNumEntries == 0, "expected 0, got %x\n", elp.elpNumEntries);
172 else
174 ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
175 memcpy(&lp, &elp, sizeof(lp));
176 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
177 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
178 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
179 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
182 DeleteObject(hpen);
184 /********** cosmetic pens created by ExtCreatePen ***********/
185 lb.lbStyle = BS_SOLID;
186 lb.lbColor = pen[i].color;
187 lb.lbHatch = HS_CROSS; /* just in case */
188 SetLastError(0xdeadbeef);
189 hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style);
190 if (pen[i].style != PS_USERSTYLE)
192 ok(hpen == 0, "ExtCreatePen should fail\n");
193 ok(GetLastError() == ERROR_INVALID_PARAMETER,
194 "wrong last error value %d\n", GetLastError());
195 SetLastError(0xdeadbeef);
196 hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL);
197 if (pen[i].style != PS_NULL)
199 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
200 ok(GetLastError() == ERROR_INVALID_PARAMETER,
201 "wrong last error value %d\n", GetLastError());
203 SetLastError(0xdeadbeef);
204 hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
207 else
209 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
210 ok(GetLastError() == ERROR_INVALID_PARAMETER,
211 "wrong last error value %d\n", GetLastError());
212 SetLastError(0xdeadbeef);
213 hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
215 if (pen[i].style == PS_INSIDEFRAME)
217 /* This style is applicable only for geometric pens */
218 ok(hpen == 0, "ExtCreatePen should fail\n");
219 goto test_geometric_pens;
221 ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
223 obj_type = GetObjectType(hpen);
224 /* for some reason XP differentiates PS_NULL here */
225 if (pen[i].style == PS_NULL)
227 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
228 ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
230 else
231 ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
233 /* check what's the real size of the object */
234 SetLastError(0xdeadbeef);
235 size = GetObject(hpen, 0, NULL);
236 switch (pen[i].style)
238 case PS_NULL:
239 ok(size == sizeof(LOGPEN),
240 "GetObject returned %d, error %d\n", size, GetLastError());
241 break;
243 case PS_USERSTYLE:
244 ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style) ||
245 broken(size == 0 && GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
246 "GetObject returned %d, error %d\n", size, GetLastError());
247 break;
249 default:
250 ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) ||
251 broken(size == sizeof(LOGPEN)) || /* Win9x */
252 broken(pen[i].style == PS_ALTERNATE &&
253 size == 0 &&
254 GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
255 "GetObject returned %d, error %d\n", size, GetLastError());
256 break;
259 /* ask for truncated data */
260 memset(&elp, 0xb0, sizeof(elp));
261 SetLastError(0xdeadbeef);
262 size = GetObject(hpen, sizeof(elp.elpPenStyle), &elp);
263 ok(!size ||
264 broken(size == sizeof(elp.elpPenStyle)), /* Win9x */
265 "GetObject should fail: size %d, error %d\n", size, GetLastError());
267 /* see how larger buffer sizes are handled */
268 memset(&ext_pen, 0xb0, sizeof(ext_pen));
269 SetLastError(0xdeadbeef);
270 size = GetObject(hpen, sizeof(ext_pen), &ext_pen.elp);
271 switch (pen[i].style)
273 case PS_NULL:
274 ok(size == sizeof(LOGPEN),
275 "GetObject returned %d, error %d\n", size, GetLastError());
276 memcpy(&lp, &ext_pen.elp, 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 %d\n", pen[i].ret_width, lp.lopnWidth.x);
279 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
280 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\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 = GetObject(hpen, sizeof(elp), &elp);
287 ok(size == sizeof(EXTLOGPEN),
288 "GetObject returned %d, error %d\n", size, GetLastError());
289 ok(ext_pen.elp.elpHatch == unset_hatch, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen.elp.elpHatch);
290 ok(ext_pen.elp.elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %x\n", ext_pen.elp.elpNumEntries);
291 break;
293 case PS_USERSTYLE:
294 ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
295 "GetObject returned %d, error %d\n", size, GetLastError());
296 ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
297 ok(ext_pen.elp.elpNumEntries == 2, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
298 ok(ext_pen.elp.elpStyleEntry[0] == 0xabc, "expected 0xabc, got %x\n", ext_pen.elp.elpStyleEntry[0]);
299 ok(ext_pen.elp.elpStyleEntry[1] == 0xdef, "expected 0xdef, got %x\n", ext_pen.elp.elpStyleEntry[1]);
300 break;
302 default:
303 ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) ||
304 broken(size == sizeof(LOGPEN)) || /* Win9x */
305 broken(pen[i].style == PS_ALTERNATE &&
306 size == 0 &&
307 GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
308 "GetObject returned %d, error %d\n", size, GetLastError());
309 ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
310 ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
311 break;
314 ok(ext_pen.elp.elpPenStyle == pen[i].style, "expected %x, got %x\n", pen[i].style, ext_pen.elp.elpPenStyle);
315 ok(ext_pen.elp.elpWidth == 1, "expected 1, got %x\n", ext_pen.elp.elpWidth);
316 ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen.elp.elpColor);
317 ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
319 DeleteObject(hpen);
321 test_geometric_pens:
322 /********************** geometric pens **********************/
323 lb.lbStyle = BS_SOLID;
324 lb.lbColor = pen[i].color;
325 lb.lbHatch = HS_CROSS; /* just in case */
326 SetLastError(0xdeadbeef);
327 hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 2, user_style);
328 if (pen[i].style != PS_USERSTYLE)
330 ok(hpen == 0, "ExtCreatePen should fail\n");
331 SetLastError(0xdeadbeef);
332 hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL);
334 if (pen[i].style == PS_ALTERNATE)
336 /* This style is applicable only for cosmetic pens */
337 ok(hpen == 0, "ExtCreatePen should fail\n");
338 continue;
340 ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
342 obj_type = GetObjectType(hpen);
343 /* for some reason XP differentiates PS_NULL here */
344 if (pen[i].style == PS_NULL)
345 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
346 else
347 ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
349 /* check what's the real size of the object */
350 size = GetObject(hpen, 0, NULL);
351 switch (pen[i].style)
353 case PS_NULL:
354 ok(size == sizeof(LOGPEN),
355 "GetObject returned %d, error %d\n", size, GetLastError());
356 break;
358 case PS_USERSTYLE:
359 ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
360 "GetObject returned %d, error %d\n", size, GetLastError());
361 break;
363 default:
364 ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
365 "GetObject returned %d, error %d\n", size, GetLastError());
366 break;
369 /* ask for truncated data */
370 memset(&lp, 0xb0, sizeof(lp));
371 SetLastError(0xdeadbeef);
372 size = GetObject(hpen, sizeof(lp.lopnStyle), &lp);
373 ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
375 memset(&lp, 0xb0, sizeof(lp));
376 SetLastError(0xdeadbeef);
377 size = GetObject(hpen, sizeof(lp), &lp);
378 /* for some reason XP differentiates PS_NULL here */
379 if (pen[i].style == PS_NULL)
381 ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
382 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
383 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
384 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
385 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
387 else
388 /* XP doesn't set last error here */
389 ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
390 "GetObject should fail: size %d, error %d\n", size, GetLastError());
392 memset(&ext_pen, 0xb0, sizeof(ext_pen));
393 SetLastError(0xdeadbeef);
394 /* buffer is too small for user styles */
395 size = GetObject(hpen, sizeof(elp), &ext_pen.elp);
396 switch (pen[i].style)
398 case PS_NULL:
399 ok(size == sizeof(EXTLOGPEN),
400 "GetObject returned %d, error %d\n", size, GetLastError());
401 ok(ext_pen.elp.elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen.elp.elpHatch);
402 ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
404 /* for PS_NULL it also works this way */
405 SetLastError(0xdeadbeef);
406 size = GetObject(hpen, sizeof(ext_pen), &lp);
407 ok(size == sizeof(LOGPEN),
408 "GetObject returned %d, error %d\n", size, GetLastError());
409 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
410 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
411 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
412 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
413 break;
415 case PS_USERSTYLE:
416 ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
417 "GetObject should fail: size %d, error %d\n", size, GetLastError());
418 size = GetObject(hpen, sizeof(ext_pen), &ext_pen.elp);
419 ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry) + sizeof(user_style),
420 "GetObject returned %d, error %d\n", size, GetLastError());
421 ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
422 ok(ext_pen.elp.elpNumEntries == 2, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
423 ok(ext_pen.elp.elpStyleEntry[0] == 0xabc, "expected 0xabc, got %x\n", ext_pen.elp.elpStyleEntry[0]);
424 ok(ext_pen.elp.elpStyleEntry[1] == 0xdef, "expected 0xdef, got %x\n", ext_pen.elp.elpStyleEntry[1]);
425 break;
427 default:
428 ok(size == sizeof(EXTLOGPEN) - sizeof(elp.elpStyleEntry),
429 "GetObject returned %d, error %d\n", size, GetLastError());
430 ok(ext_pen.elp.elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen.elp.elpHatch);
431 ok(ext_pen.elp.elpNumEntries == 0, "expected 0, got %x\n", ext_pen.elp.elpNumEntries);
432 break;
435 /* for some reason XP differentiates PS_NULL here */
436 if (pen[i].style == PS_NULL)
437 ok(ext_pen.elp.elpPenStyle == pen[i].ret_style, "expected %x, got %x\n", pen[i].ret_style, ext_pen.elp.elpPenStyle);
438 else
440 ok(ext_pen.elp.elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %x\n", PS_GEOMETRIC | pen[i].style, ext_pen.elp.elpPenStyle);
443 if (pen[i].style == PS_NULL)
444 ok(ext_pen.elp.elpWidth == 0, "expected 0, got %x\n", ext_pen.elp.elpWidth);
445 else
446 ok(ext_pen.elp.elpWidth == pen[i].ret_width, "expected %u, got %x\n", pen[i].ret_width, ext_pen.elp.elpWidth);
447 ok(ext_pen.elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen.elp.elpColor);
448 ok(ext_pen.elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen.elp.elpBrushStyle);
450 DeleteObject(hpen);
454 static unsigned int atoi2(const char *s)
456 unsigned int ret = 0;
457 while(*s) ret = (ret << 1) | (*s++ == '1');
458 return ret;
461 #define TEST_LINE(x1, x2, z) \
462 { int buf = 0; \
463 SetBitmapBits(bmp, sizeof(buf), &buf); \
464 MoveToEx(hdc, x1, 0, NULL); \
465 LineTo(hdc, x2, 0); \
466 GetBitmapBits(bmp, sizeof(buf), &buf); \
467 expect(atoi2(z), buf); }
469 static void test_ps_alternate(void)
471 HDC hdc;
472 HBITMAP bmp;
473 HPEN pen;
474 LOGBRUSH lb;
475 INT iRet;
476 HGDIOBJ hRet;
478 lb.lbStyle = BS_SOLID;
479 lb.lbColor = RGB(0xff,0xff,0xff);
481 SetLastError(0xdeadbeef);
482 pen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
483 if(pen == NULL && GetLastError() == 0xdeadbeef) {
484 skip("looks like 9x, skipping PS_ALTERNATE tests\n");
485 return;
487 ok(pen != NULL, "gle=%d\n", GetLastError());
488 hdc = CreateCompatibleDC(NULL);
489 ok(hdc != NULL, "gle=%d\n", GetLastError());
490 bmp = CreateBitmap(8, 1, 1, 1, NULL);
491 ok(bmp != NULL, "gle=%d\n", GetLastError());
492 hRet = SelectObject(hdc, bmp);
493 ok(hRet != NULL, "gle=%d\n", GetLastError());
494 hRet = SelectObject(hdc, pen);
495 ok(hRet != NULL, "gle=%d\n", GetLastError());
496 iRet = SetBkMode(hdc, TRANSPARENT);
497 ok(iRet, "gle=%d\n", GetLastError());
499 TEST_LINE(0, 1, "10000000")
500 TEST_LINE(0, 2, "10000000")
501 TEST_LINE(0, 3, "10100000")
502 TEST_LINE(0, 4, "10100000")
503 TEST_LINE(1, 4, "01010000")
504 TEST_LINE(1, 5, "01010000")
505 TEST_LINE(4, 8, "00001010")
507 DeleteObject(pen);
508 DeleteObject(bmp);
509 DeleteDC(hdc);
512 static void test_ps_userstyle(void)
514 static DWORD style[17] = {0, 2, 0, 4, 5, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 17};
515 static DWORD bad_style[5] = {0, 0, 0, 0, 0};
516 static DWORD bad_style2[5] = {4, 7, 8, 3, -1};
518 LOGBRUSH lb;
519 HPEN pen;
520 INT size, i;
522 struct
524 EXTLOGPEN elp;
525 DWORD style_data[15];
526 } ext_pen;
528 lb.lbColor = 0x00ff0000;
529 lb.lbStyle = BS_SOLID;
530 lb.lbHatch = 0;
532 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 3, NULL);
533 ok(pen == 0, "ExtCreatePen should fail\n");
534 if (pen == 0 && GetLastError() == 0xdeadbeef)
536 win_skip("Looks like 9x, skipping PS_USERSTYLE tests\n");
537 return;
539 expect(ERROR_INVALID_PARAMETER, GetLastError());
540 DeleteObject(pen);
541 SetLastError(0xdeadbeef);
543 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style);
544 ok(pen == 0, "ExtCreatePen should fail\n");
545 expect2(0xdeadbeef, ERROR_INVALID_PARAMETER, GetLastError());
546 DeleteObject(pen);
547 SetLastError(0xdeadbeef);
549 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 17, 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, -1, style);
556 ok(pen == 0, "ExtCreatePen should fail\n");
557 expect(0xdeadbeef, GetLastError());
558 DeleteObject(pen);
559 SetLastError(0xdeadbeef);
561 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style);
562 ok(pen == 0, "ExtCreatePen should fail\n");
563 expect(ERROR_INVALID_PARAMETER, GetLastError());
564 DeleteObject(pen);
565 SetLastError(0xdeadbeef);
567 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style2);
568 ok(pen == 0, "ExtCreatePen should fail\n");
569 expect(ERROR_INVALID_PARAMETER, GetLastError());
570 DeleteObject(pen);
571 SetLastError(0xdeadbeef);
573 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 16, style);
574 ok(pen != 0, "ExtCreatePen should not fail\n");
576 size = GetObject(pen, sizeof(ext_pen), &ext_pen);
577 expect(FIELD_OFFSET(EXTLOGPEN,elpStyleEntry[16]), size);
579 for(i = 0; i < 16; i++)
580 expect(style[i], ext_pen.elp.elpStyleEntry[i]);
582 DeleteObject(pen);
585 START_TEST(pen)
587 test_logpen();
588 test_ps_alternate();
589 test_ps_userstyle();