1 /*
2 * Unit test suite for customlinecap
3 *
4 * Copyright (C) 2008 Nikolay Sivov
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 #include <limits.h>
21
22 #include "objbase.h"
23 #include "gdiplus.h"
24 #include "wine/test.h"
25
26 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
27 #define expectf(expected, got) ok(got == expected, "Expected %.2f, got %.2f\n", expected, got)
28
compare_float(float f,float g,unsigned int ulps)29 static BOOL compare_float(float f, float g, unsigned int ulps)
30 {
31 int x = *(int *)&f;
32 int y = *(int *)&g;
33
34 if (x < 0)
35 x = INT_MIN - x;
36 if (y < 0)
37 y = INT_MIN - y;
38
39 if (abs(x - y) > ulps)
40 return FALSE;
41
42 return TRUE;
43 }
44
test_constructor_destructor(void)45 static void test_constructor_destructor(void)
46 {
47 GpCustomLineCap *custom;
48 GpPath *path, *path2;
49 GpStatus stat;
50
51 stat = GdipCreatePath(FillModeAlternate, &path);
52 expect(Ok, stat);
53 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
54 expect(Ok, stat);
55
56 stat = GdipCreatePath(FillModeAlternate, &path2);
57 expect(Ok, stat);
58 stat = GdipAddPathRectangle(path2, 5.0, 5.0, 10.0, 10.0);
59 expect(Ok, stat);
60
61 /* NULL args */
62 stat = GdipCreateCustomLineCap(NULL, NULL, LineCapFlat, 0.0, NULL);
63 expect(InvalidParameter, stat);
64 stat = GdipCreateCustomLineCap(path, NULL, LineCapFlat, 0.0, NULL);
65 expect(InvalidParameter, stat);
66 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, NULL);
67 expect(InvalidParameter, stat);
68 stat = GdipCreateCustomLineCap(NULL, NULL, LineCapFlat, 0.0, &custom);
69 expect(InvalidParameter, stat);
70 stat = GdipDeleteCustomLineCap(NULL);
71 expect(InvalidParameter, stat);
72
73 /* valid args */
74 stat = GdipCreateCustomLineCap(NULL, path2, LineCapFlat, 0.0, &custom);
75 expect(Ok, stat);
76 stat = GdipDeleteCustomLineCap(custom);
77 expect(Ok, stat);
78 /* it's strange but native returns NotImplemented on stroke == NULL */
79 custom = NULL;
80 stat = GdipCreateCustomLineCap(path, NULL, LineCapFlat, 10.0, &custom);
81 todo_wine expect(NotImplemented, stat);
82 todo_wine ok(custom == NULL, "Expected a failure on creation\n");
83 if(stat == Ok) GdipDeleteCustomLineCap(custom);
84
85 GdipDeletePath(path2);
86 GdipDeletePath(path);
87 }
88
test_linejoin(void)89 static void test_linejoin(void)
90 {
91 GpCustomLineCap *custom;
92 GpPath *path;
93 GpLineJoin join;
94 GpStatus stat;
95
96 stat = GdipCreatePath(FillModeAlternate, &path);
97 expect(Ok, stat);
98 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
99 expect(Ok, stat);
100
101 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom);
102 expect(Ok, stat);
103
104 /* NULL args */
105 stat = GdipGetCustomLineCapStrokeJoin(NULL, NULL);
106 expect(InvalidParameter, stat);
107 stat = GdipGetCustomLineCapStrokeJoin(custom, NULL);
108 expect(InvalidParameter, stat);
109 stat = GdipGetCustomLineCapStrokeJoin(NULL, &join);
110 expect(InvalidParameter, stat);
111 stat = GdipSetCustomLineCapStrokeJoin(NULL, LineJoinBevel);
112 expect(InvalidParameter, stat);
113
114 /* LineJoinMiter is default */
115 stat = GdipGetCustomLineCapStrokeJoin(custom, &join);
116 expect(Ok, stat);
117 expect(LineJoinMiter, join);
118
119 /* set/get */
120 stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinBevel);
121 expect(Ok, stat);
122 stat = GdipGetCustomLineCapStrokeJoin(custom, &join);
123 expect(Ok, stat);
124 expect(LineJoinBevel, join);
125 stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinRound);
126 expect(Ok, stat);
127 stat = GdipGetCustomLineCapStrokeJoin(custom, &join);
128 expect(Ok, stat);
129 expect(LineJoinRound, join);
130 stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinMiterClipped);
131 expect(Ok, stat);
132 stat = GdipGetCustomLineCapStrokeJoin(custom, &join);
133 expect(Ok, stat);
134 expect(LineJoinMiterClipped, join);
135
136 GdipDeleteCustomLineCap(custom);
137 GdipDeletePath(path);
138 }
139
test_inset(void)140 static void test_inset(void)
141 {
142 GpCustomLineCap *custom;
143 GpPath *path;
144 REAL inset;
145 GpStatus stat;
146
147 stat = GdipCreatePath(FillModeAlternate, &path);
148 expect(Ok, stat);
149 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
150 expect(Ok, stat);
151
152 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom);
153 expect(Ok, stat);
154
155 /* NULL args */
156 stat = GdipGetCustomLineCapBaseInset(NULL, NULL);
157 expect(InvalidParameter, stat);
158 stat = GdipGetCustomLineCapBaseInset(NULL, &inset);
159 expect(InvalidParameter, stat);
160 stat = GdipGetCustomLineCapBaseInset(custom, NULL);
161 expect(InvalidParameter, stat);
162 /* valid args */
163 inset = (REAL)0xdeadbeef;
164 stat = GdipGetCustomLineCapBaseInset(custom, &inset);
165 expect(Ok, stat);
166 expectf(0.0, inset);
167
168 GdipDeleteCustomLineCap(custom);
169 GdipDeletePath(path);
170 }
171
test_scale(void)172 static void test_scale(void)
173 {
174 GpCustomLineCap *custom;
175 GpPath *path;
176 REAL scale;
177 GpStatus stat;
178
179 stat = GdipCreatePath(FillModeAlternate, &path);
180 expect(Ok, stat);
181 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
182 expect(Ok, stat);
183
184 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom);
185 expect(Ok, stat);
186
187 /* NULL args */
188 stat = GdipGetCustomLineCapWidthScale(NULL, NULL);
189 expect(InvalidParameter, stat);
190 stat = GdipGetCustomLineCapWidthScale(NULL, &scale);
191 expect(InvalidParameter, stat);
192 stat = GdipGetCustomLineCapWidthScale(custom, NULL);
193 expect(InvalidParameter, stat);
194
195 stat = GdipSetCustomLineCapWidthScale(NULL, 2.0);
196 expect(InvalidParameter, stat);
197
198 /* valid args: read default */
199 scale = (REAL)0xdeadbeef;
200 stat = GdipGetCustomLineCapWidthScale(custom, &scale);
201 expect(Ok, stat);
202 expectf(1.0, scale);
203
204 /* set and read back some scale values: there is no limit for the scale */
205 stat = GdipSetCustomLineCapWidthScale(custom, 2.5);
206 expect(Ok, stat);
207 scale = (REAL)0xdeadbeef;
208 stat = GdipGetCustomLineCapWidthScale(custom, &scale);
209 expect(Ok, stat);
210 expectf(2.5, scale);
211
212 stat = GdipSetCustomLineCapWidthScale(custom, 42.0);
213 expect(Ok, stat);
214 scale = (REAL)0xdeadbeef;
215 stat = GdipGetCustomLineCapWidthScale(custom, &scale);
216 expect(Ok, stat);
217 expectf(42.0, scale);
218
219 stat = GdipSetCustomLineCapWidthScale(custom, 3000.0);
220 expect(Ok, stat);
221 scale = (REAL)0xdeadbeef;
222 stat = GdipGetCustomLineCapWidthScale(custom, &scale);
223 expect(Ok, stat);
224 expectf(3000.0, scale);
225
226 stat = GdipSetCustomLineCapWidthScale(custom, 0.0);
227 expect(Ok, stat);
228 scale = (REAL)0xdeadbeef;
229 stat = GdipGetCustomLineCapWidthScale(custom, &scale);
230 expect(Ok, stat);
231 expectf(0.0, scale);
232
233 GdipDeleteCustomLineCap(custom);
234 GdipDeletePath(path);
235 }
236
test_create_adjustable_cap(void)237 static void test_create_adjustable_cap(void)
238 {
239 REAL inset, scale, height, width;
240 GpAdjustableArrowCap *cap;
241 GpLineJoin join;
242 GpStatus stat;
243 GpLineCap base;
244 BOOL ret;
245
246 stat = GdipCreateAdjustableArrowCap(10.0, 10.0, TRUE, NULL);
247 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat);
248
249 stat = GdipCreateAdjustableArrowCap(17.0, 15.0, TRUE, &cap);
250 ok(stat == Ok, "Failed to create adjustable cap, %d\n", stat);
251
252 stat = GdipGetAdjustableArrowCapFillState(cap, NULL);
253 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat);
254
255 ret = FALSE;
256 stat = GdipGetAdjustableArrowCapFillState(cap, &ret);
257 ok(stat == Ok, "Unexpected return code, %d\n", stat);
258 ok(ret, "Unexpected fill state %d\n", ret);
259
260 stat = GdipGetAdjustableArrowCapHeight(cap, NULL);
261 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat);
262
263 stat = GdipGetAdjustableArrowCapHeight(cap, &height);
264 ok(stat == Ok, "Unexpected return code, %d\n", stat);
265 ok(height == 17.0, "Unexpected cap height %f\n", height);
266
267 stat = GdipGetAdjustableArrowCapWidth(cap, NULL);
268 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat);
269
270 stat = GdipGetAdjustableArrowCapWidth(cap, &width);
271 ok(stat == Ok, "Unexpected return code, %d\n", stat);
272 ok(width == 15.0, "Unexpected cap width %f\n", width);
273
274 stat = GdipGetAdjustableArrowCapMiddleInset(cap, NULL);
275 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat);
276
277 stat = GdipGetAdjustableArrowCapMiddleInset(cap, &inset);
278 ok(stat == Ok, "Unexpected return code, %d\n", stat);
279 ok(inset == 0.0f, "Unexpected middle inset %f\n", inset);
280
281 stat = GdipGetCustomLineCapBaseCap((GpCustomLineCap*)cap, &base);
282 ok(stat == Ok, "Unexpected return code, %d\n", stat);
283 ok(base == LineCapTriangle, "Unexpected base cap %d\n", base);
284
285 stat = GdipSetCustomLineCapBaseCap((GpCustomLineCap*)cap, LineCapSquare);
286 todo_wine
287 ok(stat == Ok, "Unexpected return code, %d\n", stat);
288
289 stat = GdipGetCustomLineCapBaseCap((GpCustomLineCap*)cap, &base);
290 ok(stat == Ok, "Unexpected return code, %d\n", stat);
291 todo_wine
292 ok(base == LineCapSquare, "Unexpected base cap %d\n", base);
293
294 /* Base inset */
295 stat = GdipGetAdjustableArrowCapWidth(cap, &width);
296 ok(stat == Ok, "Unexpected return code, %d\n", stat);
297
298 stat = GdipGetAdjustableArrowCapHeight(cap, &height);
299 ok(stat == Ok, "Unexpected return code, %d\n", stat);
300
301 inset = 0.0;
302 stat = GdipGetCustomLineCapBaseInset((GpCustomLineCap*)cap, &inset);
303 ok(stat == Ok, "Unexpected return code, %d\n", stat);
304 ok(compare_float(inset, height / width, 1), "Unexpected inset %f\n", inset);
305
306 stat = GdipSetAdjustableArrowCapMiddleInset(cap, 1.0);
307 ok(stat == Ok, "Unexpected return code, %d\n", stat);
308
309 inset = 0.0;
310 stat = GdipGetCustomLineCapBaseInset((GpCustomLineCap*)cap, &inset);
311 ok(stat == Ok, "Unexpected return code, %d\n", stat);
312 ok(compare_float(inset, height / width, 1), "Unexpected inset %f\n", inset);
313
314 stat = GdipSetAdjustableArrowCapHeight(cap, 2.0 * height);
315 ok(stat == Ok, "Unexpected return code, %d\n", stat);
316
317 inset = 0.0;
318 stat = GdipGetCustomLineCapBaseInset((GpCustomLineCap*)cap, &inset);
319 ok(stat == Ok, "Unexpected return code, %d\n", stat);
320 ok(compare_float(inset, 2.0 * height / width, 1), "Unexpected inset %f\n", inset);
321
322 stat = GdipGetCustomLineCapWidthScale((GpCustomLineCap*)cap, &scale);
323 ok(stat == Ok, "Unexpected return code, %d\n", stat);
324 ok(scale == 1.0f, "Unexpected width scale %f\n", scale);
325
326 stat = GdipGetCustomLineCapStrokeJoin((GpCustomLineCap*)cap, &join);
327 ok(stat == Ok, "Unexpected return code, %d\n", stat);
328 ok(join == LineJoinMiter, "Unexpected stroke join %d\n", join);
329
330 GdipDeleteCustomLineCap((GpCustomLineCap*)cap);
331 }
332
test_captype(void)333 static void test_captype(void)
334 {
335 GpAdjustableArrowCap *arrowcap;
336 GpCustomLineCap *custom;
337 CustomLineCapType type;
338 GpStatus stat;
339 GpPath *path;
340
341 stat = GdipGetCustomLineCapType(NULL, NULL);
342 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat);
343
344 type = 10;
345 stat = GdipGetCustomLineCapType(NULL, &type);
346 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat);
347 ok(type == 10, "Unexpected cap type, %d\n", type);
348
349 /* default cap */
350 stat = GdipCreatePath(FillModeAlternate, &path);
351 ok(stat == Ok, "Failed to create path, %d\n", stat);
352 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0);
353 ok(stat == Ok, "AddPathRectangle failed, %d\n", stat);
354
355 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom);
356 ok(stat == Ok, "Failed to create cap, %d\n", stat);
357 stat = GdipGetCustomLineCapType(custom, &type);
358 ok(stat == Ok, "Failed to get cap type, %d\n", stat);
359 ok(type == CustomLineCapTypeDefault, "Unexpected cap type %d\n", stat);
360 GdipDeleteCustomLineCap(custom);
361 GdipDeletePath(path);
362
363 /* arrow cap */
364 stat = GdipCreateAdjustableArrowCap(17.0, 15.0, TRUE, &arrowcap);
365 ok(stat == Ok, "Failed to create adjustable cap, %d\n", stat);
366
367 stat = GdipGetCustomLineCapType((GpCustomLineCap*)arrowcap, &type);
368 ok(stat == Ok, "Failed to get cap type, %d\n", stat);
369 ok(type == CustomLineCapTypeAdjustableArrow, "Unexpected cap type %d\n", stat);
370
371 GdipDeleteCustomLineCap((GpCustomLineCap*)arrowcap);
372 }
373
START_TEST(customlinecap)374 START_TEST(customlinecap)
375 {
376 struct GdiplusStartupInput gdiplusStartupInput;
377 ULONG_PTR gdiplusToken;
378 HMODULE hmsvcrt;
379 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
380
381 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
382 hmsvcrt = LoadLibraryA("msvcrt");
383 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
384 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
385
386 gdiplusStartupInput.GdiplusVersion = 1;
387 gdiplusStartupInput.DebugEventCallback = NULL;
388 gdiplusStartupInput.SuppressBackgroundThread = 0;
389 gdiplusStartupInput.SuppressExternalCodecs = 0;
390
391 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
392
393 test_constructor_destructor();
394 test_linejoin();
395 test_inset();
396 test_scale();
397 test_create_adjustable_cap();
398 test_captype();
399
400 GdiplusShutdown(gdiplusToken);
401 }
402