ReactOS 0.4.16-dev-197-g92996da
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) 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)
33
34static void test_logpen(void)
35{
36 static const struct
37 {
38 UINT style;
39 INT width;
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) },
63 };
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;
74
75 for (i = 0; i < sizeof(pen)/sizeof(pen[0]); i++)
76 {
77 trace("%d: testing style %u\n", i, pen[i].style);
78
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);
88 {
89 win_skip("No support for pen style %u (%d)\n", pen[i].style, i);
90 continue;
91 }
92
93 obj_type = GetObjectType(hpen);
94 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
95
96 memset(&lp, 0xb0, sizeof(lp));
97 SetLastError(0xdeadbeef);
98 size = GetObjectW(hpen, sizeof(lp), &lp);
99 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
100
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);
105
107
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());
112
113 obj_type = GetObjectType(hpen);
114 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
115
116 /* check what's the real size of the object */
117 size = GetObjectW(hpen, 0, NULL);
118 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
119
120 /* ask for truncated data */
121 memset(&lp, 0xb0, sizeof(lp));
122 SetLastError(0xdeadbeef);
123 size = GetObjectW(hpen, sizeof(lp.lopnStyle), &lp);
124 ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
125
126 /* see how larger buffer sizes are handled */
127 memset(&lp, 0xb0, sizeof(lp));
128 SetLastError(0xdeadbeef);
129 size = GetObjectW(hpen, sizeof(lp) * 4, &lp);
130 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
131
132 /* see how larger buffer sizes are handled */
133 memset(&elp, 0xb0, sizeof(elp));
134 SetLastError(0xdeadbeef);
135 size = GetObjectW(hpen, sizeof(elp) * 2, &elp);
136 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
137
138 memset(&lp, 0xb0, sizeof(lp));
139 SetLastError(0xdeadbeef);
140 size = GetObjectW(hpen, sizeof(lp), &lp);
141 ok(size == sizeof(lp), "GetObject returned %d, error %d\n", size, GetLastError());
142
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);
147
148 memset(&elp, 0xb0, sizeof(elp));
149 SetLastError(0xdeadbeef);
150 size = GetObjectW(hpen, sizeof(elp), &elp);
151
152 /* for some reason XP differentiates PS_NULL here */
153 if (pen[i].style == PS_NULL)
154 {
155 ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
156 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]), "GetObject returned %d, error %d\n",
157 size, GetLastError());
158 ok(elp.elpPenStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, elp.elpPenStyle);
159 ok(elp.elpWidth == 0, "expected 0, got %u\n", elp.elpWidth);
160 ok(elp.elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, elp.elpColor);
161 ok(elp.elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %u\n", elp.elpBrushStyle);
162 ok(elp.elpHatch == 0, "expected 0, got %p\n", (void *)elp.elpHatch);
163 ok(elp.elpNumEntries == 0, "expected 0, got %x\n", elp.elpNumEntries);
164 }
165 else
166 {
167 ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
168 memcpy(&lp, &elp, sizeof(lp));
169 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
170 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
171 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
172 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
173 }
174
176
177 /********** cosmetic pens created by ExtCreatePen ***********/
178 lb.lbStyle = BS_SOLID;
179 lb.lbColor = pen[i].color;
180 lb.lbHatch = HS_CROSS; /* just in case */
181 SetLastError(0xdeadbeef);
182 hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 2, user_style);
183 if (pen[i].style != PS_USERSTYLE)
184 {
185 ok(hpen == 0, "ExtCreatePen should fail\n");
187 "wrong last error value %d\n", GetLastError());
188 SetLastError(0xdeadbeef);
189 hpen = ExtCreatePen(pen[i].style, pen[i].width, &lb, 0, NULL);
190 if (pen[i].style != PS_NULL)
191 {
192 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
194 "wrong last error value %d\n", GetLastError());
195
196 SetLastError(0xdeadbeef);
197 hpen = ExtCreatePen(pen[i].style, 1, &lb, 0, NULL);
198 }
199 }
200 else
201 {
202 ok(hpen == 0, "ExtCreatePen with width != 1 should fail\n");
204 "wrong last error value %d\n", GetLastError());
205 SetLastError(0xdeadbeef);
206 hpen = ExtCreatePen(pen[i].style, 1, &lb, 2, user_style);
207 }
208 if (pen[i].style == PS_INSIDEFRAME)
209 {
210 /* This style is applicable only for geometric pens */
211 ok(hpen == 0, "ExtCreatePen should fail\n");
212 goto test_geometric_pens;
213 }
214 if (pen[i].style > PS_ALTERNATE)
215 {
216 ok(hpen == 0, "ExtCreatePen should fail\n");
217 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError());
218 goto test_geometric_pens;
219 }
220 ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
221
222 obj_type = GetObjectType(hpen);
223 /* for some reason XP differentiates PS_NULL here */
224 if (pen[i].style == PS_NULL)
225 {
226 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
227 ok(hpen == GetStockObject(NULL_PEN), "hpen should be a stock NULL_PEN\n");
228 }
229 else
230 ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
231
232 /* check what's the real size of the object */
233 SetLastError(0xdeadbeef);
234 size = GetObjectW(hpen, 0, NULL);
235 switch (pen[i].style)
236 {
237 case PS_NULL:
238 ok(size == sizeof(LOGPEN),
239 "GetObject returned %d, error %d\n", size, GetLastError());
240 break;
241
242 case PS_USERSTYLE:
243 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
244 "GetObject returned %d, error %d\n", size, GetLastError());
245 break;
246
247 default:
248 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
249 "GetObject returned %d, error %d\n", size, GetLastError());
250 break;
251 }
252
253 /* ask for truncated data */
254 memset(&elp, 0xb0, sizeof(elp));
255 SetLastError(0xdeadbeef);
256 size = GetObjectW(hpen, sizeof(elp.elpPenStyle), &elp);
257 ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
258
259 /* see how larger buffer sizes are handled */
260 memset(elp_buffer, 0xb0, sizeof(elp_buffer));
261 SetLastError(0xdeadbeef);
262 size = GetObjectW(hpen, sizeof(elp_buffer), elp_buffer);
263 switch (pen[i].style)
264 {
265 case PS_NULL:
266 ok(size == sizeof(LOGPEN),
267 "GetObject returned %d, error %d\n", size, GetLastError());
268 memcpy(&lp, ext_pen, sizeof(lp));
269 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
270 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
271 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
272 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
273
274 /* for PS_NULL it also works this way */
275 memset(&elp, 0xb0, sizeof(elp));
276 memset(&unset_hatch, 0xb0, sizeof(unset_hatch));
277 SetLastError(0xdeadbeef);
278 size = GetObjectW(hpen, sizeof(elp), &elp);
279 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]),
280 "GetObject returned %d, error %d\n", size, GetLastError());
281 ok(ext_pen->elpHatch == unset_hatch, "expected 0xb0b0b0b0, got %p\n", (void *)ext_pen->elpHatch);
282 ok(ext_pen->elpNumEntries == 0xb0b0b0b0, "expected 0xb0b0b0b0, got %x\n", ext_pen->elpNumEntries);
283 break;
284
285 case PS_USERSTYLE:
286 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
287 "GetObject returned %d, error %d\n", size, GetLastError());
288 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
289 ok(ext_pen->elpNumEntries == 2, "expected 0, got %x\n", ext_pen->elpNumEntries);
290 ok(ext_style[0] == 0xabc, "expected 0xabc, got %x\n", ext_style[0]);
291 ok(ext_style[1] == 0xdef, "expected 0xdef, got %x\n", ext_style[1]);
292 break;
293
294 default:
295 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
296 "GetObject returned %d, error %d\n", size, GetLastError());
297 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
298 ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
299 break;
300 }
301
302 ok(ext_pen->elpPenStyle == pen[i].style, "expected %x, got %x\n", pen[i].style, ext_pen->elpPenStyle);
303 ok(ext_pen->elpWidth == 1, "expected 1, got %x\n", ext_pen->elpWidth);
304 ok(ext_pen->elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen->elpColor);
305 ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle);
306
308
309test_geometric_pens:
310 /********************** geometric pens **********************/
311 lb.lbStyle = BS_SOLID;
312 lb.lbColor = pen[i].color;
313 lb.lbHatch = HS_CROSS; /* just in case */
314 SetLastError(0xdeadbeef);
315 hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 2, user_style);
316 if (pen[i].style != PS_USERSTYLE)
317 {
318 ok(hpen == 0, "ExtCreatePen should fail\n");
319 SetLastError(0xdeadbeef);
320 hpen = ExtCreatePen(PS_GEOMETRIC | pen[i].style, pen[i].width, &lb, 0, NULL);
321 }
322 if (pen[i].style == PS_ALTERNATE)
323 {
324 /* This style is applicable only for cosmetic pens */
325 ok(hpen == 0, "ExtCreatePen should fail\n");
326 continue;
327 }
328 if (pen[i].style > PS_ALTERNATE)
329 {
330 ok(hpen == 0, "ExtCreatePen should fail\n");
331 ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong last error value %d\n", GetLastError());
332 continue;
333 }
334 ok(hpen != 0, "ExtCreatePen error %d\n", GetLastError());
335
336 obj_type = GetObjectType(hpen);
337 /* for some reason XP differentiates PS_NULL here */
338 if (pen[i].style == PS_NULL)
339 ok(obj_type == OBJ_PEN, "wrong object type %u\n", obj_type);
340 else
341 ok(obj_type == OBJ_EXTPEN, "wrong object type %u\n", obj_type);
342
343 /* check what's the real size of the object */
344 size = GetObjectW(hpen, 0, NULL);
345 switch (pen[i].style)
346 {
347 case PS_NULL:
348 ok(size == sizeof(LOGPEN),
349 "GetObject returned %d, error %d\n", size, GetLastError());
350 break;
351
352 case PS_USERSTYLE:
353 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
354 "GetObject returned %d, error %d\n", size, GetLastError());
355 break;
356
357 default:
358 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
359 "GetObject returned %d, error %d\n", size, GetLastError());
360 break;
361 }
362
363 /* ask for truncated data */
364 memset(&lp, 0xb0, sizeof(lp));
365 SetLastError(0xdeadbeef);
366 size = GetObjectW(hpen, sizeof(lp.lopnStyle), &lp);
367 ok(!size, "GetObject should fail: size %d, error %d\n", size, GetLastError());
368
369 memset(&lp, 0xb0, sizeof(lp));
370 SetLastError(0xdeadbeef);
371 size = GetObjectW(hpen, sizeof(lp), &lp);
372 /* for some reason XP differentiates PS_NULL here */
373 if (pen[i].style == PS_NULL)
374 {
375 ok(size == sizeof(LOGPEN), "GetObject returned %d, error %d\n", size, GetLastError());
376 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
377 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
378 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
379 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
380 }
381 else
382 /* XP doesn't set last error here */
383 ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
384 "GetObject should fail: size %d, error %d\n", size, GetLastError());
385
386 memset(elp_buffer, 0xb0, sizeof(elp_buffer));
387 SetLastError(0xdeadbeef);
388 /* buffer is too small for user styles */
389 size = GetObjectW(hpen, offsetof(EXTLOGPEN, elpStyleEntry[1]), elp_buffer);
390 switch (pen[i].style)
391 {
392 case PS_NULL:
393 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[1]),
394 "GetObject returned %d, error %d\n", size, GetLastError());
395 ok(ext_pen->elpHatch == 0, "expected 0, got %p\n", (void *)ext_pen->elpHatch);
396 ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
397
398 /* for PS_NULL it also works this way */
399 SetLastError(0xdeadbeef);
400 size = GetObjectW(hpen, sizeof(elp_buffer), &lp);
401 ok(size == sizeof(LOGPEN),
402 "GetObject returned %d, error %d\n", size, GetLastError());
403 ok(lp.lopnStyle == pen[i].ret_style, "expected %u, got %u\n", pen[i].ret_style, lp.lopnStyle);
404 ok(lp.lopnWidth.x == pen[i].ret_width, "expected %u, got %d\n", pen[i].ret_width, lp.lopnWidth.x);
405 ok(lp.lopnWidth.y == 0, "expected 0, got %d\n", lp.lopnWidth.y);
406 ok(lp.lopnColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, lp.lopnColor);
407 break;
408
409 case PS_USERSTYLE:
410 ok(!size /*&& GetLastError() == ERROR_INVALID_PARAMETER*/,
411 "GetObject should fail: size %d, error %d\n", size, GetLastError());
412 size = GetObjectW(hpen, sizeof(elp_buffer), elp_buffer);
413 ok(size == offsetof( EXTLOGPEN, elpStyleEntry[2] ),
414 "GetObject returned %d, error %d\n", size, GetLastError());
415 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
416 ok(ext_pen->elpNumEntries == 2, "expected 0, got %x\n", ext_pen->elpNumEntries);
417 ok(ext_style[0] == 0xabc, "expected 0xabc, got %x\n", ext_style[0]);
418 ok(ext_style[1] == 0xdef, "expected 0xdef, got %x\n", ext_style[1]);
419 break;
420
421 default:
422 ok(size == offsetof( EXTLOGPEN, elpStyleEntry ),
423 "GetObject returned %d, error %d\n", size, GetLastError());
424 ok(ext_pen->elpHatch == HS_CROSS, "expected HS_CROSS, got %p\n", (void *)ext_pen->elpHatch);
425 ok(ext_pen->elpNumEntries == 0, "expected 0, got %x\n", ext_pen->elpNumEntries);
426 break;
427 }
428
429 /* for some reason XP differentiates PS_NULL here */
430 if (pen[i].style == PS_NULL)
431 ok(ext_pen->elpPenStyle == pen[i].ret_style, "expected %x, got %x\n", pen[i].ret_style, ext_pen->elpPenStyle);
432 else
433 {
434 ok(ext_pen->elpPenStyle == (PS_GEOMETRIC | pen[i].style), "expected %x, got %x\n", PS_GEOMETRIC | pen[i].style, ext_pen->elpPenStyle);
435 }
436
437 if (pen[i].style == PS_NULL)
438 ok(ext_pen->elpWidth == 0, "expected 0, got %x\n", ext_pen->elpWidth);
439 else
440 ok(ext_pen->elpWidth == pen[i].ret_width, "expected %u, got %x\n", pen[i].ret_width, ext_pen->elpWidth);
441 ok(ext_pen->elpColor == pen[i].ret_color, "expected %08x, got %08x\n", pen[i].ret_color, ext_pen->elpColor);
442 ok(ext_pen->elpBrushStyle == BS_SOLID, "expected BS_SOLID, got %x\n", ext_pen->elpBrushStyle);
443
445 }
446}
447
448static unsigned int atoi2(const char *s)
449{
450 unsigned int ret = 0;
451 while(*s) ret = (ret << 1) | (*s++ == '1');
452 return ret;
453}
454
455#define TEST_LINE(x1, x2, z) \
456 { int buf = 0; \
457 SetBitmapBits(bmp, sizeof(buf), &buf); \
458 MoveToEx(hdc, x1, 0, NULL); \
459 LineTo(hdc, x2, 0); \
460 GetBitmapBits(bmp, sizeof(buf), &buf); \
461 expect(atoi2(z), buf); }
462
463static void test_ps_alternate(void)
464{
465 HDC hdc;
466 HBITMAP bmp;
467 HPEN pen;
468 LOGBRUSH lb;
469 INT iRet;
470 HGDIOBJ hRet;
471
472 lb.lbStyle = BS_SOLID;
473 lb.lbColor = RGB(0xff,0xff,0xff);
474
475 SetLastError(0xdeadbeef);
476 pen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL);
477 if(pen == NULL && GetLastError() == 0xdeadbeef) {
478 skip("looks like 9x, skipping PS_ALTERNATE tests\n");
479 return;
480 }
481 ok(pen != NULL, "gle=%d\n", GetLastError());
483 ok(hdc != NULL, "gle=%d\n", GetLastError());
484 bmp = CreateBitmap(8, 1, 1, 1, NULL);
485 ok(bmp != NULL, "gle=%d\n", GetLastError());
486 hRet = SelectObject(hdc, bmp);
487 ok(hRet != NULL, "gle=%d\n", GetLastError());
488 hRet = SelectObject(hdc, pen);
489 ok(hRet != NULL, "gle=%d\n", GetLastError());
490 iRet = SetBkMode(hdc, TRANSPARENT);
491 ok(iRet, "gle=%d\n", GetLastError());
492
493 TEST_LINE(0, 1, "10000000")
494 TEST_LINE(0, 2, "10000000")
495 TEST_LINE(0, 3, "10100000")
496 TEST_LINE(0, 4, "10100000")
497 TEST_LINE(1, 4, "01010000")
498 TEST_LINE(1, 5, "01010000")
499 TEST_LINE(4, 8, "00001010")
500
501 DeleteObject(pen);
503 DeleteDC(hdc);
504}
505
506static void test_ps_userstyle(void)
507{
508 static DWORD style[17] = {0, 2, 0, 4, 5, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 17};
509 static DWORD bad_style[5] = {0, 0, 0, 0, 0};
510 static DWORD bad_style2[5] = {4, 7, 8, 3, -1};
511
512 LOGBRUSH lb;
513 HPEN pen;
514 INT size, i;
515 char buffer[offsetof(EXTLOGPEN, elpStyleEntry) + 16 * sizeof(DWORD)];
516 EXTLOGPEN *ext_pen = (EXTLOGPEN *)buffer;
517
518 lb.lbColor = 0x00ff0000;
519 lb.lbStyle = BS_SOLID;
520 lb.lbHatch = 0;
521
522 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 3, NULL);
523 ok(pen == 0, "ExtCreatePen should fail\n");
525 DeleteObject(pen);
526 SetLastError(0xdeadbeef);
527
528 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 0, style);
529 ok(pen == 0, "ExtCreatePen should fail\n");
531 DeleteObject(pen);
532 SetLastError(0xdeadbeef);
533
534 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 17, style);
535 ok(pen == 0, "ExtCreatePen should fail\n");
537 DeleteObject(pen);
538 SetLastError(0xdeadbeef);
539
540 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, -1, style);
541 ok(pen == 0, "ExtCreatePen should fail\n");
542 expect(0xdeadbeef, GetLastError());
543 DeleteObject(pen);
544 SetLastError(0xdeadbeef);
545
546 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style);
547 ok(pen == 0, "ExtCreatePen should fail\n");
549 DeleteObject(pen);
550 SetLastError(0xdeadbeef);
551
552 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 5, bad_style2);
553 ok(pen == 0, "ExtCreatePen should fail\n");
555 DeleteObject(pen);
556 SetLastError(0xdeadbeef);
557
558 pen = ExtCreatePen(PS_GEOMETRIC | PS_USERSTYLE, 50, &lb, 16, style);
559 ok(pen != 0, "ExtCreatePen should not fail\n");
560
561 size = GetObjectW(pen, sizeof(buffer), ext_pen);
562 ok(size == offsetof(EXTLOGPEN, elpStyleEntry[16]), "wrong size %d\n", size);
563
564 for(i = 0; i < 16; i++)
565 expect(style[i], ext_pen->elpStyleEntry[i]);
566
567 DeleteObject(pen);
568}
569
570static void test_brush_pens(void)
571{
572 char buffer[offsetof(EXTLOGPEN, elpStyleEntry) + 16 * sizeof(DWORD)];
573 EXTLOGPEN *elp = (EXTLOGPEN *)buffer;
574 LOGBRUSH lb;
575 HPEN pen = 0;
576 DWORD size;
577 HBITMAP bmp = CreateBitmap( 8, 8, 1, 1, NULL );
579 HGLOBAL hmem;
580
581 hmem = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*info) + 16 * 16 * 4 );
582 info = GlobalLock( hmem );
583 info->bmiHeader.biSize = sizeof(info->bmiHeader);
584 info->bmiHeader.biWidth = 16;
585 info->bmiHeader.biHeight = 16;
586 info->bmiHeader.biPlanes = 1;
587 info->bmiHeader.biBitCount = 32;
588 info->bmiHeader.biCompression = BI_RGB;
589
590 for (lb.lbStyle = BS_SOLID; lb.lbStyle <= BS_MONOPATTERN + 1; lb.lbStyle++)
591 {
592 SetLastError( 0xdeadbeef );
593 memset( buffer, 0xcc, sizeof(buffer) );
594 trace( "testing brush style %u\n", lb.lbStyle );
595
596 switch (lb.lbStyle)
597 {
598 case BS_SOLID:
599 case BS_HATCHED:
600 lb.lbColor = RGB(12,34,56);
601 lb.lbHatch = HS_CROSS;
602 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
603 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
604 size = GetObjectW( pen, sizeof(buffer), elp );
605 ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
606 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
607 ok( elp->elpBrushStyle == lb.lbStyle, "wrong brush style %x\n", elp->elpBrushStyle );
608 ok( elp->elpColor == RGB(12,34,56), "wrong color %x\n", elp->elpColor );
609 ok( elp->elpHatch == HS_CROSS, "wrong hatch %lx\n", elp->elpHatch );
610 ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
611 break;
612
613 case BS_NULL:
614 pen = ExtCreatePen( PS_SOLID | PS_GEOMETRIC, 3, &lb, 0, NULL );
615 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
616 size = GetObjectW( pen, sizeof(buffer), elp );
617 ok( size == sizeof(LOGPEN), "wrong size %u\n", size );
618 ok( ((LOGPEN *)elp)->lopnStyle == PS_NULL,
619 "wrong pen style %x\n", ((LOGPEN *)elp)->lopnStyle );
620 ok( ((LOGPEN *)elp)->lopnColor == 0,
621 "wrong color %x\n", ((LOGPEN *)elp)->lopnColor );
622 break;
623
624 case BS_PATTERN:
625 lb.lbColor = RGB(12,34,56);
626 lb.lbHatch = (ULONG_PTR)bmp;
627 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
628 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
629 size = GetObjectW( pen, sizeof(buffer), elp );
630 ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
631 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
632 ok( elp->elpBrushStyle == BS_PATTERN, "wrong brush style %x\n", elp->elpBrushStyle );
633 ok( elp->elpColor == 0, "wrong color %x\n", elp->elpColor );
634 ok( elp->elpHatch == (ULONG_PTR)bmp, "wrong hatch %lx/%p\n", elp->elpHatch, bmp );
635 ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
636 break;
637
638 case BS_DIBPATTERN:
639 case BS_DIBPATTERNPT:
641 lb.lbHatch = lb.lbStyle == BS_DIBPATTERN ? (ULONG_PTR)hmem : (ULONG_PTR)info;
642 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
643 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
644 size = GetObjectW( pen, sizeof(buffer), elp );
645 ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
646 ok( elp->elpPenStyle == (PS_DOT | PS_GEOMETRIC), "wrong pen style %x\n", elp->elpPenStyle );
647 ok( elp->elpBrushStyle == BS_DIBPATTERNPT, "wrong brush style %x\n", elp->elpBrushStyle );
648 ok( elp->elpColor == 0, "wrong color %x\n", elp->elpColor );
649 ok( elp->elpHatch == lb.lbHatch || broken(elp->elpHatch != lb.lbHatch), /* <= w2k */
650 "wrong hatch %lx/%lx\n", elp->elpHatch, lb.lbHatch );
651 ok( elp->elpNumEntries == 0, "wrong entries %x\n", elp->elpNumEntries );
652 break;
653
654 default:
655 pen = ExtCreatePen( PS_DOT | PS_GEOMETRIC, 3, &lb, 0, NULL );
656 ok( !pen, "ExtCreatePen succeeded\n" );
657 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
658 break;
659 }
660
661 if (pen) DeleteObject( pen );
662 else continue;
663
664 /* cosmetic pens require BS_SOLID */
665 SetLastError( 0xdeadbeef );
666 pen = ExtCreatePen( PS_DOT, 1, &lb, 0, NULL );
667 if (lb.lbStyle == BS_SOLID)
668 {
669 ok( pen != 0, "ExtCreatePen failed err %u\n", GetLastError() );
670 size = GetObjectW( pen, sizeof(buffer), elp );
671 ok( size == offsetof( EXTLOGPEN, elpStyleEntry ), "wrong size %u\n", size );
672 ok( elp->elpPenStyle == PS_DOT, "wrong pen style %x\n", elp->elpPenStyle );
673 ok( elp->elpBrushStyle == BS_SOLID, "wrong brush style %x\n", elp->elpBrushStyle );
674 ok( elp->elpColor == RGB(12,34,56), "wrong color %x\n", elp->elpColor );
675 ok( elp->elpHatch == HS_CROSS, "wrong hatch %lx\n", elp->elpHatch );
676 DeleteObject( pen );
677 }
678 else
679 {
680 ok( !pen, "ExtCreatePen succeeded\n" );
681 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
682 }
683 }
684
685 GlobalUnlock( hmem );
686 GlobalFree( hmem );
687 DeleteObject( bmp );
688}
689
691{
692 test_logpen();
696}
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 broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define NULL
Definition: types.h:112
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define BI_RGB
Definition: precomp.h:56
#define RGB(r, g, b)
Definition: precomp.h:71
#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
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
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
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
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
#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
static unsigned int atoi2(const char *s)
Definition: pen.c:448
static void test_ps_userstyle(void)
Definition: pen.c:506
static void test_ps_alternate(void)
Definition: pen.c:463
static void test_logpen(void)
Definition: pen.c:34
#define expect(expected, got)
Definition: pen.c:30
#define TEST_LINE(x1, x2, z)
Definition: pen.c:455
static void test_brush_pens(void)
Definition: pen.c:570
#define expect2(expected, alt, got)
Definition: pen.c:31
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
#define OBJ_EXTPEN
Definition: objidl.idl:1419
#define OBJ_PEN
Definition: objidl.idl:1409
#define offsetof(TYPE, MEMBER)
#define win_skip
Definition: test.h:163
#define memset(x, y, z)
Definition: compat.h:39
DWORD elpNumEntries
Definition: wingdi.h:1947
DWORD elpWidth
Definition: wingdi.h:1943
DWORD elpPenStyle
Definition: wingdi.h:1942
UINT elpBrushStyle
Definition: wingdi.h:1944
DWORD elpStyleEntry[1]
Definition: wingdi.h:1948
ULONG_PTR elpHatch
Definition: wingdi.h:1946
COLORREF elpColor
Definition: wingdi.h:1945
UINT lbStyle
Definition: wingdi.h:1747
ULONG_PTR lbHatch
Definition: wingdi.h:1749
COLORREF lbColor
Definition: wingdi.h:1748
COLORREF lopnColor
Definition: wingdi.h:1847
POINT lopnWidth
Definition: wingdi.h:1846
UINT lopnStyle
Definition: wingdi.h:1845
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
int ret
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define GMEM_ZEROINIT
Definition: winbase.h:331
#define GMEM_MOVEABLE
Definition: winbase.h:319
DWORD COLORREF
Definition: windef.h:300
#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