ReactOS 0.4.17-dev-116-ga4b6fe9
pen.c
Go to the documentation of this file.
1/*
2 * Unit test suite for pens
3 *
4 * Copyright 2006 Dmitry Timoshkov
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
23#include "windef.h"
24#include "winbase.h"
25#include "wingdi.h"
26#include "winuser.h"
27
28#include "wine/test.h"
29
30#define expect(expected,got) expect_(__LINE__, expected, got)
31static inline void expect_(unsigned line, DWORD expected, DWORD got)
32{
33 ok_(__FILE__, line)(expected == got, "Expected %.08lx, got %.08lx\n", expected, got);
34}
35#define expect2(expected,alt,got) expect2_(__LINE__, expected, alt, got)
36static inline void expect2_(unsigned line, DWORD expected, DWORD alt, DWORD got)
37{
38 ok_(__FILE__, line)(expected == got || alt == got,
39 "Expected %.08lx or %.08lx, got %.08lx\n", expected, alt, got);
40}
41
42static void test_logpen(void)
43{
44 static const struct
45 {
46 UINT style;
47 INT width;
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) },
71 };
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;
82
83 for (i = 0; i < ARRAY_SIZE(pen); i++)
84 {
85 trace("%d: testing style %u\n", i, pen[i].style);
86
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);
96 {
97 win_skip("No support for pen style %u (%d)\n", pen[i].style, i);
98 continue;
99 }
100
101 obj_type = GetObjectType(hpen);
102 ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
103
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());
108
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);
113
115
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());
120
121 obj_type = GetObjectType(hpen);
122 ok(obj_type == OBJ_PEN, "wrong object type %lu\n", obj_type);
123
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());
127
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());
133
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());
139
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());
145
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());
150
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);
155
156 memset(&elp, 0xb0, sizeof(elp));
157 SetLastError(0xdeadbeef);
158 size = GetObjectW(hpen, sizeof(elp), &elp);
159
160 /* for some reason XP differentiates PS_NULL here */
161 if (pen[i].style == PS_NULL)
162 {
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);
172 }
173 else
174 {
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);
181 }
182
184
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)
192 {
193 ok(hpen == 0, "ExtCreatePen should fail\n");
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)
199 {
200 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
202 "wrong last error value %ld\n", GetLastError());
203
204 SetLastError(0xdeadbeef);
205 hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
206 }
207 }
208 else
209 {
210 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
212 "wrong last error value %ld\n", GetLastError());
213 SetLastError(0xdeadbeef);
214 hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
215 }
216 if (pen[i].style == PS_INSIDEFRAME)
217 {
218 /* This style is applicable only for geometric pens */
219 ok(hpen == 0, "ExtCreatePen should fail\n");
220 goto test_geometric_pens;
221 }
222 if (pen[i].style > PS_ALTERNATE)
223 {
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;
227 }
228 ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
229
230 obj_type = GetObjectType(hpen);
231 /* for some reason XP differentiates PS_NULL here */
232 if (pen[i].style == PS_NULL)
233 {
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");
236 }
237 else
238 ok(obj_type == OBJ_EXTPEN, "wrong object type %lu\n", obj_type);
239
240 /* check what's the real size of the object */
241 SetLastError(0xdeadbeef);
242 size = GetObjectW(hpen, 0, NULL);
243 switch (pen[i].style)
244 {
245 case PS_NULL:
246 ok(size == sizeof(LOGPEN),
247 "GetObject returned %d, error %ld\n", size, GetLastError());
248 break;
249
250 case PS_USERSTYLE:
251 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
252 "GetObject returned %d, error %ld\n", size, GetLastError());
253 break;
254
255 default:
256 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
257 "GetObject returned %d, error %ld\n", size, GetLastError());
258 break;
259 }
260
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());
266
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)
272 {
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);
281
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;
292
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;
301
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;
308 }
309
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);
314
316
317test_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)
325 {
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);
329 }
330 if (pen[i].style == PS_ALTERNATE)
331 {
332 /* This style is applicable only for cosmetic pens */
333 ok(hpen == 0, "ExtCreatePen should fail\n");
334 continue;
335 }
336 if (pen[i].style > PS_ALTERNATE)
337 {
338 ok(hpen == 0, "ExtCreatePen should fail\n");
339 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %ld\n", GetLastError());
340 continue;
341 }
342 ok(hpen != 0, "ExtCreatePen error %ld\n", GetLastError());
343
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);
350
351 /* check what's the real size of the object */
352 size = GetObjectW(hpen, 0, NULL);
353 switch (pen[i].style)
354 {
355 case PS_NULL:
356 ok(size == sizeof(LOGPEN),
357 "GetObject returned %d, error %ld\n", size, GetLastError());
358 break;
359
360 case PS_USERSTYLE:
361 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
362 "GetObject returned %d, error %ld\n", size, GetLastError());
363 break;
364
365 default:
366 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
367 "GetObject returned %d, error %ld\n", size, GetLastError());
368 break;
369 }
370
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());
376
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)
382 {
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);
388 }
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());
393
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)
399 {
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);
405
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;
416
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;
428
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;
435 }
436
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
441 {
442 ok(ext_pen->elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %lx\n", PS_GEOMETRIC | pen[i].style, ext_pen->elpPenStyle);
443 }
444
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);
451
453 }
454}
455
456static unsigned int atoi2(const char *s)
457{
458 unsigned int ret = 0;
459 while(*s) ret = (ret << 1) | (*s++ == '1');
460 return ret;
461}
462
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); }
470
471static void test_ps_alternate(void)
472{
473 HDC hdc;
474 HBITMAP bmp;
475 HPEN pen;
476 LOGBRUSH lb;
477 INT iRet;
478 HGDIOBJ hRet;
479
480 lb.lbStyle = BS_SOLID;
481 lb.lbColor = RGB(0xff,0xff,0xff);
482
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;
488 }
489 ok(pen != NULL, "gle=%ld\n", GetLastError());
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());
500
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")
508
509 DeleteObject(pen);
511 DeleteDC(hdc);
512}
513
514static void test_ps_userstyle(void)
515{
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};
519
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;
525
526 lb.lbColor = 0x00ff0000;
527 lb.lbStyle = BS_SOLID;
528 lb.lbHatch = 0;
529
530 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 3, NULL);
531 ok(pen == 0, "ExtCreatePen should fail\n");
533 DeleteObject(pen);
534 SetLastError(0xdeadbeef);
535
536 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style);
537 ok(pen == 0, "ExtCreatePen should fail\n");
539 DeleteObject(pen);
540 SetLastError(0xdeadbeef);
541
542 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 17, style);
543 ok(pen == 0, "ExtCreatePen should fail\n");
545 DeleteObject(pen);
546 SetLastError(0xdeadbeef);
547
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);
553
554 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style);
555 ok(pen == 0, "ExtCreatePen should fail\n");
557 DeleteObject(pen);
558 SetLastError(0xdeadbeef);
559
560 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style2);
561 ok(pen == 0, "ExtCreatePen should fail\n");
563 DeleteObject(pen);
564 SetLastError(0xdeadbeef);
565
566 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 16, style);
567 ok(pen != 0, "ExtCreatePen should not fail\n");
568
569 size = GetObjectW(pen, sizeof(buffer), ext_pen);
570 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[16]), "wrong size %d\n", size);
571
572 for(i = 0; i < 16; i++)
573 expect(style[i], ext_pen->elpStyleEntry[i]);
574
575 DeleteObject(pen);
576}
577
578static void test_brush_pens(void)
579{
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 );
587 HGLOBAL hmem;
588
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;
597
598 for (lb.lbStyle = BS_SOLID; lb.lbStyle <= BS_MONOPATTERN + 1; lb.lbStyle++)
599 {
600 SetLastError( 0xdeadbeef );
601 memset( buffer, 0xcc, sizeof(buffer) );
602 trace( "testing brush style %u\n", lb.lbStyle );
603
604 switch (lb.lbStyle)
605 {
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;
620
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;
631
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;
645
646 case BS_DIBPATTERN:
647 case BS_DIBPATTERNPT:
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;
660
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;
666 }
667
668 if (pen) DeleteObject( pen );
669 else continue;
670
671 /* cosmetic pens require BS_SOLID */
672 SetLastError( 0xdeadbeef );
673 pen = ExtCreatePen( PS_DOT, 1, &lb, 0, NULL );
674 if (lb.lbStyle == BS_SOLID)
675 {
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 );
684 }
685 else
686 {
687 ok( !pen, "ExtCreatePen succeeded\n" );
688 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %lu\n", GetLastError() );
689 }
690 }
691
692 GlobalUnlock( hmem );
693 GlobalFree( hmem );
694 DeleteObject( bmp );
695}
696
698{
699 test_logpen();
703}
static HPEN hpen
static POBJECT_TYPE GetObjectType(IN PCWSTR TypeName)
Definition: ObTypes.c:15
Arabic default style
Definition: afstyles.h:94
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define ARRAY_SIZE(A)
Definition: main.h:20
#define NULL
Definition: types.h:112
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define RGB(r, g, b)
Definition: precomp.h:67
return ret
Definition: mutex.c:146
#define ULONG_PTR
Definition: config.h:101
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
GLdouble s
Definition: gl.h:2039
GLint GLint GLsizei width
Definition: gl.h:1546
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLuint color
Definition: glext.h:6243
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
static ERESOURCE GlobalLock
Definition: sys_arch.c:8
#define win_skip
Definition: minitest.h:67
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
BITMAP bmp
Definition: alphablend.c:62
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
BOOL expected
Definition: store.c:2000
static unsigned int atoi2(const char *s)
Definition: pen.c:456
static void test_ps_userstyle(void)
Definition: pen.c:514
static void test_ps_alternate(void)
Definition: pen.c:471
static void expect2_(unsigned line, DWORD expected, DWORD alt, DWORD got)
Definition: pen.c:36
static void test_logpen(void)
Definition: pen.c:42
#define expect(expected, got)
Definition: pen.c:30
#define TEST_LINE(x1, x2, z)
Definition: pen.c:463
static void test_brush_pens(void)
Definition: pen.c:578
#define expect2(expected, alt, got)
Definition: pen.c:35
#define expect_(expected, got, precision)
Definition: font.c:29
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
#define OBJ_EXTPEN
Definition: objidl.idl:1024
#define OBJ_PEN
Definition: objidl.idl:1014
#define offsetof(TYPE, MEMBER)
#define memset(x, y, z)
Definition: compat.h:39
Definition: parser.c:49
DWORD elpNumEntries
Definition: wingdi.h:2393
DWORD elpWidth
Definition: wingdi.h:2389
DWORD elpPenStyle
Definition: wingdi.h:2388
UINT elpBrushStyle
Definition: wingdi.h:2390
DWORD elpStyleEntry[1]
Definition: wingdi.h:2394
ULONG_PTR elpHatch
Definition: wingdi.h:2392
COLORREF elpColor
Definition: wingdi.h:2391
UINT lbStyle
Definition: wingdi.h:2193
ULONG_PTR lbHatch
Definition: wingdi.h:2195
COLORREF lbColor
Definition: wingdi.h:2194
COLORREF lopnColor
Definition: wingdi.h:2293
POINT lopnWidth
Definition: wingdi.h:2292
UINT lopnStyle
Definition: wingdi.h:2291
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
uint32_t DWORD_PTR
Definition: typedefs.h:65
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define BI_RGB
Definition: uefivid.c:46
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define GMEM_ZEROINIT
Definition: winbase.h:330
#define GMEM_MOVEABLE
Definition: winbase.h:318
DWORD COLORREF
Definition: windef.h:100
#define PS_NULL
Definition: wingdi.h:591
#define PS_DASH
Definition: wingdi.h:587
HGDIOBJ WINAPI GetStockObject(_In_ int)
#define BS_MONOPATTERN
Definition: wingdi.h:1096
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
#define PS_ALTERNATE
Definition: wingdi.h:585
HPEN WINAPI ExtCreatePen(_In_ DWORD iPenStyle, _In_ DWORD cWidth, _In_ const LOGBRUSH *plbrush, _In_ DWORD cStyle, _In_reads_opt_(cStyle) const DWORD *pstyle)
#define BS_HATCHED
Definition: wingdi.h:1089
HPEN WINAPI CreatePenIndirect(_In_ const LOGPEN *)
#define BS_PATTERN
Definition: wingdi.h:1090
#define PS_DOT
Definition: wingdi.h:588
#define PS_COSMETIC
Definition: wingdi.h:584
#define BS_DIBPATTERNPT
Definition: wingdi.h:1093
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
#define PS_GEOMETRIC
Definition: wingdi.h:583
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define DIB_PAL_COLORS
Definition: wingdi.h:366
#define TRANSPARENT
Definition: wingdi.h:950
#define BS_DIBPATTERN
Definition: wingdi.h:1092
#define HS_CROSS
Definition: wingdi.h:577
#define PS_USERSTYLE
Definition: wingdi.h:592
#define NULL_PEN
Definition: wingdi.h:904
#define BS_NULL
Definition: wingdi.h:1087
int WINAPI SetBkMode(_In_ HDC, _In_ int)
Definition: dc.c:1056
BOOL WINAPI DeleteDC(_In_ HDC)
HPEN WINAPI CreatePen(_In_ int, _In_ int, _In_ COLORREF)
#define PS_INSIDEFRAME
Definition: wingdi.h:593
#define BS_SOLID
Definition: wingdi.h:1086
#define PS_SOLID
Definition: wingdi.h:586
#define PS_DASHDOT
Definition: wingdi.h:589
#define PS_DASHDOTDOT
Definition: wingdi.h:590