include/ddk: Add _KAPC_STATE structure definition.
[wine.git] / dlls / gdiplus / tests / graphicspath.c
bloba987cd165dca0eded369531aa0f023137cc9d217
1 /*
2 * Unit test suite for paths
4 * Copyright (C) 2007 Google (Evan Stade)
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 "objbase.h"
22 #include "gdiplus.h"
23 #include "wine/test.h"
24 #include <math.h>
26 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
27 #define expectf(expected, got) ok(fabs(expected - got) < 2.0, "Expected %.2f, got %.2f\n", expected, got)
28 #define POINT_TYPE_MAX_LEN (75)
30 static void stringify_point_type(PathPointType type, char * name)
32 *name = '\0';
34 switch(type & PathPointTypePathTypeMask){
35 case PathPointTypeStart:
36 strcat(name, "PathPointTypeStart");
37 break;
38 case PathPointTypeLine:
39 strcat(name, "PathPointTypeLine");
40 break;
41 case PathPointTypeBezier:
42 strcat(name, "PathPointTypeBezier");
43 break;
44 default:
45 strcat(name, "Unknown type");
46 return;
49 type &= ~PathPointTypePathTypeMask;
50 if(type & ~((PathPointTypePathMarker | PathPointTypeCloseSubpath))){
51 *name = '\0';
52 strcat(name, "Unknown type");
53 return;
56 if(type & PathPointTypePathMarker)
57 strcat(name, " | PathPointTypePathMarker");
58 if(type & PathPointTypeCloseSubpath)
59 strcat(name, " | PathPointTypeCloseSubpath");
62 /* this helper structure and function modeled after gdi path.c test */
63 typedef struct
65 REAL X, Y;
66 BYTE type;
68 /* How many extra entries before this one only on wine
69 * but not on native? */
70 int wine_only_entries_preceding;
72 /* 0 - This entry matches on wine.
73 * 1 - This entry corresponds to a single entry on wine that does not match the native entry.
74 * 2 - This entry is currently skipped on wine but present on native. */
75 int todo;
76 } path_test_t;
78 #define ok_path(a,b,c,d) _ok_path_fudge(a,b,c,d,2.0,__LINE__)
79 #define ok_path_fudge(a,b,c,d,e) _ok_path_fudge(a,b,c,d,e,__LINE__)
80 static void _ok_path_fudge(GpPath* path, const path_test_t *expected, INT expected_size,
81 BOOL todo_size, REAL fudge, int line)
83 BYTE * types;
84 INT size, idx = 0, eidx = 0, numskip;
85 GpPointF * points;
86 char ename[POINT_TYPE_MAX_LEN], name[POINT_TYPE_MAX_LEN];
88 if(GdipGetPointCount(path, &size) != Ok){
89 skip("Cannot perform path comparisons due to failure to retrieve path.\n");
90 return;
93 todo_wine_if (todo_size)
94 ok_(__FILE__,line)(size == expected_size, "Path size %d does not match expected size %d\n",
95 size, expected_size);
97 points = HeapAlloc(GetProcessHeap(), 0, size * sizeof(GpPointF));
98 types = HeapAlloc(GetProcessHeap(), 0, size);
100 if(GdipGetPathPoints(path, points, size) != Ok || GdipGetPathTypes(path, types, size) != Ok){
101 skip("Cannot perform path comparisons due to failure to retrieve path.\n");
102 goto end;
105 numskip = expected_size ? expected[eidx].wine_only_entries_preceding : 0;
106 while (idx < size && eidx < expected_size){
107 /* We allow a few pixels fudge in matching X and Y coordinates to account for imprecision in
108 * floating point to integer conversion */
109 BOOL match = (types[idx] == expected[eidx].type) &&
110 fabs(points[idx].X - expected[eidx].X) <= fudge &&
111 fabs(points[idx].Y - expected[eidx].Y) <= fudge;
113 stringify_point_type(expected[eidx].type, ename);
114 stringify_point_type(types[idx], name);
116 todo_wine_if (expected[eidx].todo || numskip)
117 ok_(__FILE__,line)(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx,
118 ename, expected[eidx].X, expected[eidx].Y,
119 name, points[idx].X, points[idx].Y);
121 if (match || expected[eidx].todo != 2)
122 idx++;
123 if (match || !numskip--)
124 numskip = expected[++eidx].wine_only_entries_preceding;
127 end:
128 HeapFree(GetProcessHeap(), 0, types);
129 HeapFree(GetProcessHeap(), 0, points);
132 static void test_constructor_destructor(void)
134 GpStatus status;
135 GpPath* path = NULL;
137 status = GdipCreatePath(FillModeAlternate, &path);
138 expect(Ok, status);
139 ok(path != NULL, "Expected path to be initialized\n");
141 status = GdipDeletePath(NULL);
142 expect(InvalidParameter, status);
144 status = GdipDeletePath(path);
145 expect(Ok, status);
148 static void test_getpathdata(void)
150 GpPath *path;
151 GpPathData data;
152 GpStatus status;
153 INT count;
155 status = GdipCreatePath(FillModeAlternate, &path);
156 expect(Ok, status);
157 status = GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
158 expect(Ok, status);
160 status = GdipGetPointCount(path, &count);
161 expect(Ok, status);
162 expect(2, count);
164 data.Count = count;
165 data.Types = GdipAlloc(sizeof(BYTE) * count);
166 data.Points = GdipAlloc(sizeof(PointF) * count);
168 status = GdipGetPathData(path, &data);
169 expect(Ok, status);
170 expect((data.Points[0].X == 5.0) && (data.Points[0].Y == 5.0) &&
171 (data.Points[1].X == 100.0) && (data.Points[1].Y == 50.0), TRUE);
172 expect((data.Types[0] == PathPointTypeStart) && (data.Types[1] == PathPointTypeLine), TRUE);
174 GdipFree(data.Points);
175 GdipFree(data.Types);
176 GdipDeletePath(path);
179 static void test_createpath2(void)
181 GpStatus status;
182 GpPath* path = NULL;
183 GpPathData data;
184 INT i, count, expect_count;
186 PointF test_line_points[] = {{1.0,1.0}, {2.0,1.0}, {2.0,2.0}};
187 BYTE test_line_types[] = {PathPointTypeStart, PathPointTypeLine, PathPointTypeStart};
189 PointF test_bez_points[] = {{1.0,1.0}, {2.0,1.0}, {3.0,1.0}, {4.0,1.0},
190 {5.0,1.0}, {6.0,1.0}, {7.0,1.0}};
191 BYTE test_bez_types[] = {PathPointTypeStart, PathPointTypeBezier,
192 PathPointTypeBezier, PathPointTypeBezier, PathPointTypeBezier,
193 PathPointTypeBezier, PathPointTypeBezier};
195 status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, &path);
196 expect(Ok, status);
197 status = GdipGetPointCount(path, &count);
198 expect(Ok, status);
199 expect(2, count);
200 GdipDeletePath(path);
202 status = GdipCreatePath2(test_line_points, test_line_types, 1, FillModeAlternate, &path);
203 expect(Ok, status);
204 status = GdipGetPointCount(path, &count);
205 expect(Ok, status);
206 expect(1, count);
207 GdipDeletePath(path);
209 path = (void *)0xdeadbeef;
210 status = GdipCreatePath2(test_line_points, test_line_types, 0, FillModeAlternate, &path);
211 expect(OutOfMemory, status);
212 ok(!path, "Expected NULL, got %p\n", path);
213 if(path && path != (void *)0xdeadbeef)
214 GdipDeletePath(path);
216 path = (void *)0xdeadbeef;
217 status = GdipCreatePath2(test_line_points, test_line_types, -1, FillModeAlternate, &path);
218 expect(OutOfMemory, status);
219 ok(!path, "Expected NULL, got %p\n", path);
220 if(path && path != (void *)0xdeadbeef)
221 GdipDeletePath(path);
223 path = (void *)0xdeadbeef;
224 status = GdipCreatePath2(NULL, test_line_types, 2, FillModeAlternate, &path);
225 expect(InvalidParameter, status);
226 ok(path == (void *)0xdeadbeef, "Expected %p, got %p\n", (void *)0xdeadbeef, path);
227 if(path && path != (void *)0xdeadbeef)
228 GdipDeletePath(path);
230 path = (void *)0xdeadbeef;
231 status = GdipCreatePath2(test_line_points, NULL, 2, FillModeAlternate, &path);
232 expect(InvalidParameter, status);
233 ok(path == (void *)0xdeadbeef, "Expected %p, got %p\n", (void *)0xdeadbeef, path);
234 if(path && path != (void *)0xdeadbeef)
235 GdipDeletePath(path);
237 status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, NULL);
238 expect(InvalidParameter, status);
240 /* Multi-point paths should not end with Start */
241 status = GdipCreatePath2(test_line_points, test_line_types, 3, FillModeAlternate, &path);
242 expect(Ok, status);
243 status = GdipGetPointCount(path, &count);
244 expect(Ok, status);
245 expect(0, count);
246 GdipDeletePath(path);
248 /* Zero-length line points do not get altered */
249 test_line_points[1].X = test_line_points[0].X;
250 test_line_points[1].Y = test_line_points[0].Y;
251 status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, &path);
252 expect(Ok, status);
253 status = GdipGetPointCount(path, &count);
254 expect(Ok, status);
255 expect(2, count);
256 GdipDeletePath(path);
258 /* The type of the first point is always converted to PathPointTypeStart */
259 test_line_types[0] = PathPointTypeLine;
260 status = GdipCreatePath2(test_line_points, test_line_types, 1, FillModeAlternate, &path);
261 expect(Ok, status);
262 status = GdipGetPointCount(path, &count);
263 expect(Ok, status);
264 expect(1, count);
265 data.Count = count;
266 data.Types = GdipAlloc(sizeof(BYTE) * count);
267 data.Points = GdipAlloc(sizeof(PointF) * count);
268 status = GdipGetPathData(path, &data);
269 expect(Ok, status);
270 expect((data.Points[0].X == 1.0) && (data.Points[0].Y == 1.0), TRUE);
271 expect(data.Types[0], PathPointTypeStart);
272 GdipFree(data.Points);
273 GdipFree(data.Types);
274 GdipDeletePath(path);
276 /* Bezier points must come in groups of three */
277 for(i = 2; i <= 7; i++) {
278 expect_count = (i % 3 == 1) ? i : 0;
279 status = GdipCreatePath2(test_bez_points, test_bez_types, i, FillModeAlternate, &path);
280 expect(Ok, status);
281 status = GdipGetPointCount(path, &count);
282 expect(Ok, status);
283 expect(expect_count, count);
284 GdipDeletePath(path);
288 static path_test_t line2_path[] = {
289 {0.0, 50.0, PathPointTypeStart, 0, 0}, /*0*/
290 {5.0, 45.0, PathPointTypeLine, 0, 0}, /*1*/
291 {0.0, 40.0, PathPointTypeLine, 0, 0}, /*2*/
292 {15.0, 35.0, PathPointTypeLine, 0, 0}, /*3*/
293 {0.0, 30.0, PathPointTypeLine, 0, 0}, /*4*/
294 {25.0, 25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*5*/
295 {0.0, 20.0, PathPointTypeStart, 0, 0}, /*6*/
296 {35.0, 15.0, PathPointTypeLine, 0, 0}, /*7*/
297 {0.0, 10.0, PathPointTypeLine, 0, 0} /*8*/
300 static void test_line2(void)
302 GpStatus status;
303 GpPath* path;
304 int i;
305 GpPointF line2_points[9];
307 for(i = 0; i < 9; i ++){
308 line2_points[i].X = i * 5.0 * (REAL)(i % 2);
309 line2_points[i].Y = 50.0 - i * 5.0;
312 GdipCreatePath(FillModeAlternate, &path);
314 status = GdipAddPathLine2(NULL, line2_points, 2);
315 expect(InvalidParameter, status);
316 status = GdipAddPathLine2(path, NULL, 2);
317 expect(InvalidParameter, status);
318 status = GdipAddPathLine2(path, line2_points, 0);
319 expect(InvalidParameter, status);
320 status = GdipAddPathLine2(path, line2_points, -1);
321 expect(InvalidParameter, status);
323 status = GdipAddPathLine2(path, line2_points, 3);
324 expect(Ok, status);
325 status = GdipAddPathLine2(path, &(line2_points[3]), 3);
326 expect(Ok, status);
327 status = GdipClosePathFigure(path);
328 expect(Ok, status);
329 status = GdipAddPathLine2(path, &(line2_points[6]), 3);
330 expect(Ok, status);
332 ok_path(path, line2_path, ARRAY_SIZE(line2_path), FALSE);
334 GdipResetPath(path);
335 status = GdipAddPathLine2(path, line2_points, 3);
336 expect(Ok, status);
337 status = GdipAddPathLine2(path, &(line2_points[2]), 3);
338 expect(Ok, status);
340 ok_path(path, line2_path, 5, FALSE);
342 GdipDeletePath(path);
345 static path_test_t bezier_path[] = {
346 {10.0, 10.0, PathPointTypeStart, 0, 0}, /*0*/
347 {20.0, 10.0, PathPointTypeBezier, 0, 0}, /*1*/
348 {20.0, 20.0, PathPointTypeBezier, 0, 0}, /*2*/
349 {30.0, 20.0, PathPointTypeBezier, 0, 0}, /*3*/
350 {40.0, 20.0, PathPointTypeBezier, 0, 0}, /*4*/
351 {40.0, 30.0, PathPointTypeBezier, 0, 0}, /*5*/
352 {50.0, 30.0, PathPointTypeBezier, 0, 0}, /*6*/
353 {50.0, 10.0, PathPointTypeLine, 0, 0}, /*7*/
354 {60.0, 10.0, PathPointTypeBezier, 0, 0}, /*8*/
355 {60.0, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
356 {70.0, 20.0, PathPointTypeBezier, 0, 0} /*10*/
359 static void test_bezier(void)
361 GpStatus status;
362 GpPath* path;
364 GdipCreatePath(FillModeAlternate, &path);
366 status = GdipAddPathBezier(path, 10.0, 10.0, 20.0, 10.0, 20.0, 20.0, 30.0, 20.0);
367 expect(Ok, status);
368 status = GdipAddPathBezier(path, 30.0, 20.0, 40.0, 20.0, 40.0, 30.0, 50.0, 30.0);
369 expect(Ok, status);
370 status = GdipAddPathBezier(path, 50.0, 10.0, 60.0, 10.0, 60.0, 20.0, 70.0, 20.0);
371 expect(Ok, status);
373 ok_path(path, bezier_path, ARRAY_SIZE(bezier_path), FALSE);
375 GdipDeletePath(path);
378 static void test_beziers(void)
380 GpStatus status;
381 GpPath* path;
382 PointF bezier_points1[] = {{10.0,10.0}, {20.0,10.0}, {20.0,20.0}, {30.0,20.0}};
383 PointF bezier_points2[] = {{30.0,20.0}, {40.0,20.0}, {40.0,30.0}, {50.0,30.0}};
384 PointF bezier_points3[] = {{50.0,10.0}, {60.0,10.0}, {60.0,20.0}, {70.0,20.0}};
386 GdipCreatePath(FillModeAlternate, &path);
388 status = GdipAddPathBeziers(path, bezier_points1, 4);
389 expect(Ok, status);
390 status = GdipAddPathBeziers(path, bezier_points2, 4);
391 expect(Ok, status);
392 status = GdipAddPathBeziers(path, bezier_points3, 4);
393 expect(Ok, status);
395 ok_path(path, bezier_path, ARRAY_SIZE(bezier_path), FALSE);
397 GdipDeletePath(path);
400 static path_test_t arc_path[] = {
401 {600.0, 450.0, PathPointTypeStart, 0, 0}, /*0*/
402 {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*1*/
403 {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*2*/
404 {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*3*/
405 {600.0, 450.0, PathPointTypeLine, 0, 0}, /*4*/
406 {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*5*/
407 {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*6*/
408 {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*7*/
409 {329.8, 800.0, PathPointTypeBezier, 0, 0}, /*8*/
410 {309.7, 796.6, PathPointTypeBezier, 0, 0}, /*9*/
411 {290.1, 789.8, PathPointTypeBezier, 0, 0}, /*10*/
412 {409.9, 110.2, PathPointTypeLine, 0, 0}, /*11*/
413 {544.0, 156.5, PathPointTypeBezier, 0, 0}, /*12*/
414 {625.8, 346.2, PathPointTypeBezier, 0, 0}, /*13*/
415 {592.7, 533.9, PathPointTypeBezier, 0, 0}, /*14*/
416 {592.5, 535.3, PathPointTypeBezier, 0, 0}, /*15*/
417 {592.2, 536.7, PathPointTypeBezier, 0, 0}, /*16*/
418 {592.0, 538.1, PathPointTypeBezier, 0, 0}, /*17*/
419 {409.9, 789.8, PathPointTypeLine, 0, 0}, /*18*/
420 {544.0, 743.5, PathPointTypeBezier, 0, 0}, /*19*/
421 {625.8, 553.8, PathPointTypeBezier, 0, 0}, /*20*/
422 {592.7, 366.1, PathPointTypeBezier, 0, 0}, /*21*/
423 {592.5, 364.7, PathPointTypeBezier, 0, 0}, /*22*/
424 {592.2, 363.3, PathPointTypeBezier, 0, 0}, /*23*/
425 {592.0, 361.9, PathPointTypeBezier, 0, 0}, /*24*/
426 {540.4, 676.9, PathPointTypeLine, 0, 0}, /*25*/
427 {629.9, 529.7, PathPointTypeBezier, 0, 0}, /*26*/
428 {617.2, 308.8, PathPointTypeBezier, 0, 0}, /*27*/
429 {512.1, 183.5, PathPointTypeBezier, 0, 0}, /*28*/
430 {406.9, 58.2, PathPointTypeBezier, 0, 0}, /*29*/
431 {249.1, 75.9, PathPointTypeBezier, 0, 0}, /*30*/
432 {159.6, 223.1, PathPointTypeBezier, 0, 0}, /*31*/
433 {70.1, 370.3, PathPointTypeBezier, 0, 0}, /*32*/
434 {82.8, 591.2, PathPointTypeBezier, 0, 0}, /*33*/
435 {187.9, 716.5, PathPointTypeBezier, 0, 0}, /*34*/
436 {293.1, 841.8, PathPointTypeBezier, 0, 0}, /*35*/
437 {450.9, 824.1, PathPointTypeBezier, 0, 0}, /*36*/
438 {540.4, 676.9, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 1} /*37*/
440 static path_test_t arc_path2[] = {
441 {1.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
442 {1.0, 0.5, PathPointTypeLine, 0, 0}, /*1*/
443 {1.0, 0.776142, PathPointTypeBezier, 0, 0}, /*2*/
444 {0.776142, 1.0, PathPointTypeBezier, 0, 0}, /*3*/
445 {0.5, 1.0, PathPointTypeBezier, 0, 0} /*4*/
448 static void test_arc(void)
450 GpStatus status;
451 GpPath* path;
453 GdipCreatePath(FillModeAlternate, &path);
454 /* Exactly 90 degrees */
455 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
456 expect(Ok, status);
457 /* Over 90 degrees */
458 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
459 expect(Ok, status);
460 /* Negative start angle */
461 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
462 expect(Ok, status);
463 /* Negative sweep angle */
464 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 80.0, -100.0);
465 expect(Ok, status);
466 /* More than a full revolution */
467 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, -400.0);
468 expect(Ok, status);
469 /* 0 sweep angle */
470 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, 0.0);
471 expect(Ok, status);
473 ok_path(path, arc_path, ARRAY_SIZE(arc_path), FALSE);
475 GdipResetPath(path);
476 GdipAddPathLine(path, 1.0, 0.0, 1.0, 0.5);
477 status = GdipAddPathArc(path, 0.0, 0.0, 1.0, 1.0, 0.0, 90.0);
478 expect(Ok, status);
480 ok_path_fudge(path, arc_path2, ARRAY_SIZE(arc_path2), FALSE, 0.000005);
482 GdipDeletePath(path);
485 static void test_worldbounds(void)
487 GpStatus status;
488 GpPath *path;
489 GpPen *pen;
490 GpMatrix *matrix;
491 GpRectF bounds;
492 GpPointF line2_points[10];
493 int i;
495 for(i = 0; i < 10; i ++){
496 line2_points[i].X = 200.0 + i * 50.0 * (i % 2);
497 line2_points[i].Y = 200.0 + i * 50.0 * !(i % 2);
499 GdipCreatePen1((ARGB)0xdeadbeef, 20.0, UnitWorld, &pen);
500 GdipSetPenEndCap(pen, LineCapSquareAnchor);
501 GdipCreateMatrix2(1.5, 0.0, 1.0, 1.2, 10.4, 10.2, &matrix);
503 GdipCreatePath(FillModeAlternate, &path);
504 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
505 GdipAddPathLine2(path, &(line2_points[0]), 10);
506 status = GdipGetPathWorldBounds(path, &bounds, NULL, NULL);
507 expect(Ok, status);
508 GdipDeletePath(path);
510 expectf(200.0, bounds.X);
511 expectf(200.0, bounds.Y);
512 expectf(450.0, bounds.Width);
513 expectf(600.0, bounds.Height);
515 GdipCreatePath(FillModeAlternate, &path);
516 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
517 GdipAddPathLine2(path, &(line2_points[0]), 10);
518 status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
519 expect(Ok, status);
520 GdipDeletePath(path);
522 expectf(510.4, bounds.X);
523 expectf(250.2, bounds.Y);
524 expectf(1275.0, bounds.Width);
525 expectf(720.0, bounds.Height);
527 GdipCreatePath(FillModeAlternate, &path);
528 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
529 GdipAddPathLine2(path, &(line2_points[0]), 10);
530 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
531 expect(Ok, status);
532 GdipDeletePath(path);
534 expectf(100.0, bounds.X);
535 expectf(100.0, bounds.Y);
536 expectf(650.0, bounds.Width);
537 expectf(800.0, bounds.Height);
539 GdipCreatePath(FillModeAlternate, &path);
540 GdipAddPathLine2(path, &(line2_points[0]), 2);
541 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
542 expect(Ok, status);
543 GdipDeletePath(path);
545 expectf(156.0, bounds.X);
546 expectf(156.0, bounds.Y);
547 expectf(138.0, bounds.Width);
548 expectf(88.0, bounds.Height);
550 line2_points[2].X = 2 * line2_points[1].X - line2_points[0].X;
551 line2_points[2].Y = 2 * line2_points[1].Y - line2_points[0].Y;
553 GdipCreatePath(FillModeAlternate, &path);
554 GdipAddPathLine2(path, &(line2_points[0]), 3);
555 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
556 expect(Ok, status);
557 GdipDeletePath(path);
559 expectf(100.0, bounds.X);
560 expectf(100.0, bounds.Y);
561 expectf(300.0, bounds.Width);
562 expectf(200.0, bounds.Height);
564 GdipCreatePath(FillModeAlternate, &path);
565 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 45.0, 20.0);
566 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
567 expect(Ok, status);
568 GdipDeletePath(path);
570 expectf(386.7, bounds.X);
571 expectf(553.4, bounds.Y);
572 expectf(266.8, bounds.Width);
573 expectf(289.6, bounds.Height);
575 GdipCreatePath(FillModeAlternate, &path);
576 status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
577 expect(Ok, status);
578 GdipDeletePath(path);
580 expectf(0.0, bounds.X);
581 expectf(0.0, bounds.Y);
582 expectf(0.0, bounds.Width);
583 expectf(0.0, bounds.Height);
585 GdipCreatePath(FillModeAlternate, &path);
586 GdipAddPathLine2(path, &(line2_points[0]), 2);
587 status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
588 expect(Ok, status);
589 GdipDeletePath(path);
591 todo_wine{
592 expectf(427.9, bounds.X);
593 expectf(167.7, bounds.Y);
594 expectf(239.9, bounds.Width);
595 expectf(164.9, bounds.Height);
598 GdipDeleteMatrix(matrix);
599 GdipCreateMatrix2(0.9, -0.5, -0.5, -1.2, 10.4, 10.2, &matrix);
600 GdipCreatePath(FillModeAlternate, &path);
601 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
602 GdipAddPathLine2(path, &(line2_points[0]), 10);
603 status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
604 expect(Ok, status);
605 GdipDeletePath(path);
606 GdipDeleteMatrix(matrix);
608 expectf(-209.6, bounds.X);
609 expectf(-1274.8, bounds.Y);
610 expectf(705.0, bounds.Width);
611 expectf(945.0, bounds.Height);
613 GdipDeletePen(pen);
616 static path_test_t pathpath_path[] = {
617 {600.00, 450.00, PathPointTypeStart, 0, 0}, /*0*/
618 {600.00, 643.30, PathPointTypeBezier, 0, 0}, /*1*/
619 {488.07, 800.00, PathPointTypeBezier, 0, 0}, /*2*/
620 {350.00, 800.00, PathPointTypeBezier, 0, 0}, /*3*/
621 {319.61, 797.40, PathPointTypeStart, 0, 0}, /*4*/
622 {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*5*/
623 {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*6*/
624 {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*7*/
625 {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*8*/
626 {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*9*/
627 {104.46, 384.21, PathPointTypeBezier, 0, 0}, /*10*/
628 {409.92, 110.20, PathPointTypeLine, 0, 0}, /*11*/
629 {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*12*/
630 {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*13*/
631 {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*14*/
632 {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*15*/
633 {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*16*/
634 {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*17*/
635 {319.61, 797.40, PathPointTypeLine, 0, 0}, /*18*/
636 {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*19*/
637 {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*20*/
638 {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*21*/
639 {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*22*/
640 {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*23*/
641 {104.46, 384.21, PathPointTypeBezier, 0, 0} /*24*/
644 static void test_pathpath(void)
646 GpStatus status;
647 GpPath* path1, *path2;
649 GdipCreatePath(FillModeAlternate, &path2);
650 GdipAddPathArc(path2, 100.0, 100.0, 500.0, 700.0, 95.0, 100.0);
652 GdipCreatePath(FillModeAlternate, &path1);
653 GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
654 status = GdipAddPathPath(path1, path2, FALSE);
655 expect(Ok, status);
656 GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
657 status = GdipAddPathPath(path1, path2, TRUE);
658 expect(Ok, status);
660 ok_path(path1, pathpath_path, ARRAY_SIZE(pathpath_path), FALSE);
662 GdipDeletePath(path1);
663 GdipDeletePath(path2);
666 static path_test_t ellipse_path[] = {
667 {30.00, 125.25, PathPointTypeStart, 0, 0}, /*0*/
668 {30.00, 139.20, PathPointTypeBezier, 0, 0}, /*1*/
669 {25.52, 150.50, PathPointTypeBezier, 0, 0}, /*2*/
670 {20.00, 150.50, PathPointTypeBezier, 0, 0}, /*3*/
671 {14.48, 150.50, PathPointTypeBezier, 0, 0}, /*4*/
672 {10.00, 139.20, PathPointTypeBezier, 0, 0}, /*5*/
673 {10.00, 125.25, PathPointTypeBezier, 0, 0}, /*6*/
674 {10.00, 111.30, PathPointTypeBezier, 0, 0}, /*7*/
675 {14.48, 100.00, PathPointTypeBezier, 0, 0}, /*8*/
676 {20.00, 100.00, PathPointTypeBezier, 0, 0}, /*9*/
677 {25.52, 100.00, PathPointTypeBezier, 0, 0}, /*10*/
678 {30.00, 111.30, PathPointTypeBezier, 0, 0}, /*11*/
679 {30.00, 125.25, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*12*/
680 {7.00, 11.00, PathPointTypeStart, 0, 0}, /*13*/
681 {13.00, 17.00, PathPointTypeLine, 0, 0}, /*14*/
682 {5.00, 195.00, PathPointTypeStart, 0, 0}, /*15*/
683 {5.00, 192.24, PathPointTypeBezier, 0, 0}, /*16*/
684 {6.12, 190.00, PathPointTypeBezier, 0, 0}, /*17*/
685 {7.50, 190.00, PathPointTypeBezier, 0, 0}, /*18*/
686 {8.88, 190.00, PathPointTypeBezier, 0, 0}, /*19*/
687 {10.00, 192.24, PathPointTypeBezier, 0, 0}, /*20*/
688 {10.00, 195.00, PathPointTypeBezier, 0, 0}, /*21*/
689 {10.00, 197.76, PathPointTypeBezier, 0, 0}, /*22*/
690 {8.88, 200.00, PathPointTypeBezier, 0, 0}, /*23*/
691 {7.50, 200.00, PathPointTypeBezier, 0, 0}, /*24*/
692 {6.12, 200.00, PathPointTypeBezier, 0, 0}, /*25*/
693 {5.00, 197.76, PathPointTypeBezier, 0, 0}, /*26*/
694 {5.00, 195.00, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*27*/
695 {10.00, 300.50, PathPointTypeStart, 0, 0}, /*28*/
696 {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*29*/
697 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*30*/
698 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*31*/
699 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*32*/
700 {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*33*/
701 {10.00, 300.50, PathPointTypeBezier, 0, 0}, /*34*/
702 {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*35*/
703 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*36*/
704 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*37*/
705 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*38*/
706 {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*39*/
707 {10.00, 300.50, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*40*/
710 static void test_ellipse(void)
712 GpStatus status;
713 GpPath *path;
714 GpPointF points[2];
716 points[0].X = 7.0;
717 points[0].Y = 11.0;
718 points[1].X = 13.0;
719 points[1].Y = 17.0;
721 GdipCreatePath(FillModeAlternate, &path);
722 status = GdipAddPathEllipse(path, 10.0, 100.0, 20.0, 50.5);
723 expect(Ok, status);
724 GdipAddPathLine2(path, points, 2);
725 status = GdipAddPathEllipse(path, 10.0, 200.0, -5.0, -10.0);
726 expect(Ok, status);
727 GdipClosePathFigure(path);
728 status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0);
729 expect(Ok, status);
731 ok_path(path, ellipse_path, ARRAY_SIZE(ellipse_path), FALSE);
733 GdipDeletePath(path);
736 static path_test_t linei_path[] = {
737 {5.00, 5.00, PathPointTypeStart, 0, 0}, /*0*/
738 {6.00, 8.00, PathPointTypeLine, 0, 0}, /*1*/
739 {409.92, 110.20, PathPointTypeLine, 0, 0}, /*2*/
740 {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*3*/
741 {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*4*/
742 {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*5*/
743 {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*6*/
744 {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*7*/
745 {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*8*/
746 {15.00, 15.00, PathPointTypeLine, 0, 0}, /*9*/
747 {26.00, 28.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*10*/
748 {35.00, 35.00, PathPointTypeStart, 0, 0}, /*11*/
749 {36.00, 38.00, PathPointTypeLine, 0, 0}, /*12*/
750 {39.00, 40.00, PathPointTypeLine, 0, 0} /*13*/
753 static void test_linei(void)
755 GpStatus status;
756 GpPath *path;
758 GdipCreatePath(FillModeAlternate, &path);
759 status = GdipAddPathLineI(path, 5.0, 5.0, 6.0, 8.0);
760 expect(Ok, status);
761 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
762 status = GdipAddPathLineI(path, 15.0, 15.0, 26.0, 28.0);
763 expect(Ok, status);
764 GdipClosePathFigure(path);
765 status = GdipAddPathLineI(path, 35.0, 35.0, 36.0, 38.0);
766 expect(Ok, status);
767 status = GdipAddPathLineI(path, 36, 38, 39, 40);
768 expect(Ok, status);
770 ok_path(path, linei_path, ARRAY_SIZE(linei_path), FALSE);
772 GdipDeletePath(path);
775 static path_test_t poly_path[] = {
776 {5.00, 5.00, PathPointTypeStart, 0, 0}, /*1*/
777 {6.00, 8.00, PathPointTypeLine, 0, 0}, /*2*/
778 {0.00, 0.00, PathPointTypeStart, 0, 0}, /*3*/
779 {10.00, 10.00, PathPointTypeLine, 0, 0}, /*4*/
780 {10.00, 20.00, PathPointTypeLine, 0, 0}, /*5*/
781 {30.00, 10.00, PathPointTypeLine, 0, 0}, /*6*/
782 {20.00, 0.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*7*/
785 static void test_polygon(void)
787 GpStatus status;
788 GpPath *path;
789 GpPointF points[5];
791 points[0].X = 0.0;
792 points[0].Y = 0.0;
793 points[1].X = 10.0;
794 points[1].Y = 10.0;
795 points[2].X = 10.0;
796 points[2].Y = 20.0;
797 points[3].X = 30.0;
798 points[3].Y = 10.0;
799 points[4].X = 20.0;
800 points[4].Y = 0.0;
802 GdipCreatePath(FillModeAlternate, &path);
804 /* NULL args */
805 status = GdipAddPathPolygon(NULL, points, 5);
806 expect(InvalidParameter, status);
807 status = GdipAddPathPolygon(path, NULL, 5);
808 expect(InvalidParameter, status);
809 /* Polygon should have 3 points at least */
810 status = GdipAddPathPolygon(path, points, 2);
811 expect(InvalidParameter, status);
813 /* to test how it prolongs not empty path */
814 status = GdipAddPathLine(path, 5.0, 5.0, 6.0, 8.0);
815 expect(Ok, status);
816 status = GdipAddPathPolygon(path, points, 5);
817 expect(Ok, status);
818 /* check resulting path */
819 ok_path(path, poly_path, ARRAY_SIZE(poly_path), FALSE);
821 GdipDeletePath(path);
824 static path_test_t rect_path[] = {
825 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
826 {105.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
827 {105.0, 55.0, PathPointTypeLine, 0, 0}, /*2*/
828 {5.0, 55.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*3*/
830 {100.0, 50.0, PathPointTypeStart, 0, 0}, /*4*/
831 {220.0, 50.0, PathPointTypeLine, 0, 0}, /*5*/
832 {220.0, 80.0, PathPointTypeLine, 0, 0}, /*6*/
833 {100.0, 80.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*7*/
836 static void test_rect(void)
838 GpStatus status;
839 GpPath *path;
840 GpRectF rects[2];
842 GdipCreatePath(FillModeAlternate, &path);
843 status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
844 expect(Ok, status);
845 status = GdipAddPathRectangle(path, 100.0, 50.0, 120.0, 30.0);
846 expect(Ok, status);
848 ok_path(path, rect_path, ARRAY_SIZE(rect_path), FALSE);
850 GdipDeletePath(path);
852 GdipCreatePath(FillModeAlternate, &path);
854 rects[0].X = 5.0;
855 rects[0].Y = 5.0;
856 rects[0].Width = 100.0;
857 rects[0].Height = 50.0;
858 rects[1].X = 100.0;
859 rects[1].Y = 50.0;
860 rects[1].Width = 120.0;
861 rects[1].Height = 30.0;
863 status = GdipAddPathRectangles(path, (GDIPCONST GpRectF*)&rects, 2);
864 expect(Ok, status);
866 ok_path(path, rect_path, ARRAY_SIZE(rect_path), FALSE);
868 GdipDeletePath(path);
871 static void test_lastpoint(void)
873 GpStatus status;
874 GpPath *path;
875 GpPointF ptf;
877 GdipCreatePath(FillModeAlternate, &path);
878 status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
879 expect(Ok, status);
881 /* invalid args */
882 status = GdipGetPathLastPoint(NULL, &ptf);
883 expect(InvalidParameter, status);
884 status = GdipGetPathLastPoint(path, NULL);
885 expect(InvalidParameter, status);
886 status = GdipGetPathLastPoint(NULL, NULL);
887 expect(InvalidParameter, status);
889 status = GdipGetPathLastPoint(path, &ptf);
890 expect(Ok, status);
891 expect(TRUE, (ptf.X == 5.0) && (ptf.Y == 55.0));
893 GdipDeletePath(path);
896 static path_test_t addcurve_path[] = {
897 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
898 {3.3, 3.3, PathPointTypeBezier, 0, 0}, /*1*/
899 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*2*/
900 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
901 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
902 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
903 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
904 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
905 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*8*/
906 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*9*/
908 static path_test_t addcurve_path2[] = {
909 {100.0,120.0,PathPointTypeStart, 0, 0}, /*0*/
910 {123.0,10.0, PathPointTypeLine, 0, 0}, /*1*/
911 {0.0, 0.0, PathPointTypeLine, 0, 0}, /*2*/
912 {3.3, 3.3, PathPointTypeBezier, 0, 0}, /*3*/
913 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*4*/
914 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*5*/
915 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*6*/
916 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
917 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*8*/
918 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
919 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*10*/
920 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*11*/
922 static path_test_t addcurve_path3[] = {
923 {10.0, 10.0, PathPointTypeStart, 0, 0}, /*0*/
924 {13.3, 16.7, PathPointTypeBezier, 0, 1}, /*1*/
925 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*2*/
926 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*3*/
927 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*4*/
928 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*5*/
929 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*6*/
931 static void test_addcurve(void)
933 GpStatus status;
934 GpPath *path;
935 GpPointF points[4];
937 points[0].X = 0.0;
938 points[0].Y = 0.0;
939 points[1].X = 10.0;
940 points[1].Y = 10.0;
941 points[2].X = 10.0;
942 points[2].Y = 20.0;
943 points[3].X = 30.0;
944 points[3].Y = 10.0;
946 GdipCreatePath(FillModeAlternate, &path);
948 /* NULL args */
949 status = GdipAddPathCurve2(NULL, NULL, 0, 0.0);
950 expect(InvalidParameter, status);
951 status = GdipAddPathCurve2(path, NULL, 0, 0.0);
952 expect(InvalidParameter, status);
953 status = GdipAddPathCurve2(path, points, -1, 0.0);
954 expect(InvalidParameter, status);
955 status = GdipAddPathCurve2(path, points, 1, 1.0);
956 expect(InvalidParameter, status);
958 /* add to empty path */
959 status = GdipAddPathCurve2(path, points, 4, 1.0);
960 expect(Ok, status);
961 ok_path(path, addcurve_path, ARRAY_SIZE(addcurve_path), FALSE);
962 GdipDeletePath(path);
964 /* add to notempty path and opened figure */
965 GdipCreatePath(FillModeAlternate, &path);
966 GdipAddPathLine(path, 100.0, 120.0, 123.0, 10.0);
967 status = GdipAddPathCurve2(path, points, 4, 1.0);
968 expect(Ok, status);
969 ok_path(path, addcurve_path2, ARRAY_SIZE(addcurve_path2), FALSE);
971 /* NULL args */
972 GdipResetPath(path);
973 status = GdipAddPathCurve3(NULL, NULL, 0, 0, 0, 0.0);
974 expect(InvalidParameter, status);
975 status = GdipAddPathCurve3(path, NULL, 0, 0, 0, 0.0);
976 expect(InvalidParameter, status);
977 /* wrong count, offset.. */
978 status = GdipAddPathCurve3(path, points, 0, 0, 0, 0.0);
979 expect(InvalidParameter, status);
980 status = GdipAddPathCurve3(path, points, 4, 0, 0, 0.0);
981 expect(InvalidParameter, status);
982 status = GdipAddPathCurve3(path, points, 4, 0, 4, 0.0);
983 expect(InvalidParameter, status);
984 status = GdipAddPathCurve3(path, points, 4, 1, 3, 0.0);
985 expect(InvalidParameter, status);
986 status = GdipAddPathCurve3(path, points, 4, 1, 0, 0.0);
987 expect(InvalidParameter, status);
988 status = GdipAddPathCurve3(path, points, 4, 3, 1, 0.0);
989 expect(InvalidParameter, status);
991 /* use all points */
992 status = GdipAddPathCurve3(path, points, 4, 0, 3, 1.0);
993 expect(Ok, status);
994 ok_path(path, addcurve_path, ARRAY_SIZE(addcurve_path), FALSE);
995 GdipResetPath(path);
997 status = GdipAddPathCurve3(path, points, 4, 1, 2, 1.0);
998 expect(Ok, status);
999 ok_path(path, addcurve_path3, ARRAY_SIZE(addcurve_path3), FALSE);
1001 GdipDeletePath(path);
1004 static path_test_t addclosedcurve_path[] = {
1005 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
1006 {-6.7, 0.0, PathPointTypeBezier, 0, 0}, /*1*/
1007 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*2*/
1008 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
1009 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
1010 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
1011 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
1012 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
1013 {33.3, 16.7, PathPointTypeBezier, 0, 0}, /*8*/
1014 {30.0, 10.0, PathPointTypeBezier, 0, 0}, /*9*/
1015 {26.7, 3.3, PathPointTypeBezier, 0, 0}, /*10*/
1016 {6.7, 0.0, PathPointTypeBezier, 0, 0}, /*11*/
1017 {0.0, 0.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*12*/
1019 static void test_addclosedcurve(void)
1021 GpStatus status;
1022 GpPath *path;
1023 GpPointF points[4];
1025 points[0].X = 0.0;
1026 points[0].Y = 0.0;
1027 points[1].X = 10.0;
1028 points[1].Y = 10.0;
1029 points[2].X = 10.0;
1030 points[2].Y = 20.0;
1031 points[3].X = 30.0;
1032 points[3].Y = 10.0;
1034 GdipCreatePath(FillModeAlternate, &path);
1036 /* NULL args */
1037 status = GdipAddPathClosedCurve2(NULL, NULL, 0, 0.0);
1038 expect(InvalidParameter, status);
1039 status = GdipAddPathClosedCurve2(path, NULL, 0, 0.0);
1040 expect(InvalidParameter, status);
1041 status = GdipAddPathClosedCurve2(path, points, -1, 0.0);
1042 expect(InvalidParameter, status);
1043 status = GdipAddPathClosedCurve2(path, points, 1, 1.0);
1044 expect(InvalidParameter, status);
1046 /* add to empty path */
1047 status = GdipAddPathClosedCurve2(path, points, 4, 1.0);
1048 expect(Ok, status);
1049 ok_path(path, addclosedcurve_path, ARRAY_SIZE(addclosedcurve_path), FALSE);
1050 GdipDeletePath(path);
1053 static path_test_t reverse_path[] = {
1054 {0.0, 20.0, PathPointTypeStart, 0, 0}, /*0*/
1055 {25.0, 25.0, PathPointTypeLine, 0, 0}, /*1*/
1056 {0.0, 30.0, PathPointTypeLine, 0, 0}, /*2*/
1057 {15.0, 35.0, PathPointTypeStart, 0, 0}, /*3*/
1058 {0.0, 40.0, PathPointTypeLine, 0, 0}, /*4*/
1059 {5.0, 45.0, PathPointTypeLine, 0, 0}, /*5*/
1060 {0.0, 50.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*6*/
1063 static void test_reverse(void)
1065 GpStatus status;
1066 GpPath *path;
1067 GpPointF pts[7];
1068 INT i;
1070 for(i = 0; i < 7; i++){
1071 pts[i].X = i * 5.0 * (REAL)(i % 2);
1072 pts[i].Y = 50.0 - i * 5.0;
1075 GdipCreatePath(FillModeAlternate, &path);
1077 /* NULL argument */
1078 status = GdipReversePath(NULL);
1079 expect(InvalidParameter, status);
1081 /* empty path */
1082 status = GdipReversePath(path);
1083 expect(Ok, status);
1085 GdipAddPathLine2(path, pts, 4);
1086 GdipClosePathFigure(path);
1087 GdipAddPathLine2(path, &(pts[4]), 3);
1089 status = GdipReversePath(path);
1090 expect(Ok, status);
1091 ok_path(path, reverse_path, ARRAY_SIZE(reverse_path), FALSE);
1093 GdipDeletePath(path);
1096 static path_test_t addpie_path[] = {
1097 {50.0, 25.0, PathPointTypeStart, 0, 0}, /*0*/
1098 {97.2, 33.3, PathPointTypeLine, 0, 0}, /*1*/
1099 {91.8, 40.9, PathPointTypeBezier,0, 0}, /*2*/
1100 {79.4, 46.8, PathPointTypeBezier,0, 0}, /*3*/
1101 {63.9, 49.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*4*/
1103 static path_test_t addpie_path2[] = {
1104 {0.0, 30.0, PathPointTypeStart | PathPointTypeCloseSubpath, 0, 0} /*0*/
1106 static path_test_t addpie_path3[] = {
1107 {30.0, 0.0, PathPointTypeStart | PathPointTypeCloseSubpath, 0, 0} /*0*/
1109 static void test_addpie(void)
1111 GpStatus status;
1112 GpPath *path;
1114 GdipCreatePath(FillModeAlternate, &path);
1116 /* NULL argument */
1117 status = GdipAddPathPie(NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
1118 expect(InvalidParameter, status);
1120 status = GdipAddPathPie(path, 0.0, 0.0, 100.0, 50.0, 10.0, 50.0);
1121 expect(Ok, status);
1122 ok_path(path, addpie_path, ARRAY_SIZE(addpie_path), FALSE);
1123 status = GdipResetPath(path);
1124 expect(Ok, status);
1126 /* zero width base ellipse */
1127 status = GdipAddPathPie(path, 0.0, 0.0, 0.0, 60.0, -90.0, 24.0);
1128 expect(InvalidParameter, status);
1129 ok_path(path, addpie_path2, ARRAY_SIZE(addpie_path2), FALSE);
1130 status = GdipResetPath(path);
1131 expect(Ok, status);
1133 /* zero height base ellipse */
1134 status = GdipAddPathPie(path, 0.0, 0.0, 60.0, 0.0 , -90.0, 24.0);
1135 expect(InvalidParameter, status);
1136 ok_path(path, addpie_path3, ARRAY_SIZE(addpie_path3), FALSE);
1138 GdipDeletePath(path);
1141 static path_test_t flattenellipse_path[] = {
1142 {100.0, 25.0,PathPointTypeStart, 0, 0}, /*0*/
1143 {99.0, 30.0, PathPointTypeLine, 0, 0}, /*1*/
1144 {96.0, 34.8, PathPointTypeLine, 0, 0}, /*2*/
1145 {91.5, 39.0, PathPointTypeLine, 0, 0}, /*3*/
1146 {85.5, 42.8, PathPointTypeLine, 0, 0}, /*4*/
1147 {69.5, 48.0, PathPointTypeLine, 0, 1}, /*5*/
1148 {50.0, 50.0, PathPointTypeLine, 0, 1}, /*6*/
1149 {30.5, 48.0, PathPointTypeLine, 0, 1}, /*7*/
1150 {14.8, 42.8, PathPointTypeLine, 0, 1}, /*8*/
1151 {8.5, 39.0, PathPointTypeLine, 0, 1}, /*9*/
1152 {4.0, 34.8, PathPointTypeLine, 0, 1}, /*10*/
1153 {1.0, 30.0, PathPointTypeLine, 0, 1}, /*11*/
1154 {0.0, 25.0, PathPointTypeLine, 0, 1}, /*12*/
1155 {1.0, 20.0, PathPointTypeLine, 0, 1}, /*13*/
1156 {4.0, 15.3, PathPointTypeLine, 0, 1}, /*14*/
1157 {8.5, 11.0, PathPointTypeLine, 0, 1}, /*15*/
1158 {14.8, 7.3, PathPointTypeLine, 0, 1}, /*16*/
1159 {30.5, 2.0, PathPointTypeLine, 0, 1}, /*17*/
1160 {50.0, 0.0, PathPointTypeLine, 0, 1}, /*18*/
1161 {69.5, 2.0, PathPointTypeLine, 0, 1}, /*19*/
1162 {85.5, 7.3, PathPointTypeLine, 0, 1}, /*20*/
1163 {91.5, 11.0, PathPointTypeLine, 0, 1}, /*21*/
1164 {96.0, 15.3, PathPointTypeLine, 0, 1}, /*22*/
1165 {99.0, 20.0, PathPointTypeLine, 0, 1}, /*23*/
1166 {100.0,25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 1} /*24*/
1169 static path_test_t flattenline_path[] = {
1170 {5.0, 10.0,PathPointTypeStart, 0, 0}, /*0*/
1171 {50.0, 100.0, PathPointTypeLine, 0, 0} /*1*/
1174 static path_test_t flattenarc_path[] = {
1175 {100.0, 25.0,PathPointTypeStart, 0, 0}, /*0*/
1176 {99.0, 30.0, PathPointTypeLine, 0, 0}, /*1*/
1177 {96.0, 34.8, PathPointTypeLine, 0, 0}, /*2*/
1178 {91.5, 39.0, PathPointTypeLine, 0, 0}, /*3*/
1179 {85.5, 42.8, PathPointTypeLine, 0, 0}, /*4*/
1180 {69.5, 48.0, PathPointTypeLine, 0, 1}, /*5*/
1181 {50.0, 50.0, PathPointTypeLine, 0, 1} /*6*/
1184 static path_test_t flattenquater_path[] = {
1185 {100.0, 50.0,PathPointTypeStart, 0, 0}, /*0*/
1186 {99.0, 60.0, PathPointTypeLine, 0, 0}, /*1*/
1187 {96.0, 69.5, PathPointTypeLine, 0, 0}, /*2*/
1188 {91.5, 78.0, PathPointTypeLine, 0, 0}, /*3*/
1189 {85.5, 85.5, PathPointTypeLine, 0, 0}, /*4*/
1190 {78.0, 91.5, PathPointTypeLine, 0, 0}, /*5*/
1191 {69.5, 96.0, PathPointTypeLine, 0, 0}, /*6*/
1192 {60.0, 99.0, PathPointTypeLine, 0, 0}, /*7*/
1193 {50.0, 100.0,PathPointTypeLine, 0, 0} /*8*/
1196 static void test_flatten(void)
1198 GpStatus status;
1199 GpPath *path;
1200 GpMatrix *m;
1202 status = GdipCreatePath(FillModeAlternate, &path);
1203 expect(Ok, status);
1204 status = GdipCreateMatrix(&m);
1205 expect(Ok, status);
1207 /* NULL arguments */
1208 status = GdipFlattenPath(NULL, NULL, 0.0);
1209 expect(InvalidParameter, status);
1210 status = GdipFlattenPath(NULL, m, 0.0);
1211 expect(InvalidParameter, status);
1213 /* flatten empty path */
1214 status = GdipFlattenPath(path, NULL, 1.0);
1215 expect(Ok, status);
1217 status = GdipTransformPath(path, 0);
1218 expect(Ok, status);
1220 status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 50.0);
1221 expect(Ok, status);
1223 status = GdipFlattenPath(path, NULL, 1.0);
1224 expect(Ok, status);
1225 ok_path(path, flattenellipse_path, ARRAY_SIZE(flattenellipse_path), TRUE);
1227 status = GdipResetPath(path);
1228 expect(Ok, status);
1229 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 100.0);
1230 expect(Ok, status);
1231 status = GdipFlattenPath(path, NULL, 1.0);
1232 expect(Ok, status);
1233 ok_path(path, flattenline_path, ARRAY_SIZE(flattenline_path), FALSE);
1235 status = GdipResetPath(path);
1236 expect(Ok, status);
1237 status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 50.0, 0.0, 90.0);
1238 expect(Ok, status);
1239 status = GdipFlattenPath(path, NULL, 1.0);
1240 expect(Ok, status);
1241 ok_path(path, flattenarc_path, ARRAY_SIZE(flattenarc_path), TRUE);
1243 /* easy case - quater of a full circle */
1244 status = GdipResetPath(path);
1245 expect(Ok, status);
1246 status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0);
1247 expect(Ok, status);
1248 status = GdipFlattenPath(path, NULL, 1.0);
1249 expect(Ok, status);
1250 ok_path(path, flattenquater_path, ARRAY_SIZE(flattenquater_path), FALSE);
1252 GdipDeleteMatrix(m);
1253 GdipDeletePath(path);
1256 static path_test_t widenline_path[] = {
1257 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1258 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1259 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1260 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1263 static path_test_t widenline_wide_path[] = {
1264 {5.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
1265 {50.0, 0.0, PathPointTypeLine, 0, 0}, /*1*/
1266 {50.0, 20.0, PathPointTypeLine, 0, 0}, /*2*/
1267 {5.0, 20.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1270 static path_test_t widenline_dash_path[] = {
1271 {5.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
1272 {35.0, 0.0, PathPointTypeLine, 0, 0}, /*1*/
1273 {35.0, 10.0, PathPointTypeLine, 0, 0}, /*2*/
1274 {5.0, 10.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1275 {45.0, 0.0, PathPointTypeStart, 0, 0}, /*4*/
1276 {50.0, 0.0, PathPointTypeLine, 0, 0}, /*5*/
1277 {50.0, 10.0, PathPointTypeLine, 0, 0}, /*6*/
1278 {45.0, 10.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1281 static path_test_t widenline_unit_path[] = {
1282 {5.0, 9.5, PathPointTypeStart, 0, 0}, /*0*/
1283 {50.0, 9.5, PathPointTypeLine, 0, 0}, /*1*/
1284 {50.0, 10.5, PathPointTypeLine, 0, 0}, /*2*/
1285 {5.0, 10.5, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1288 static void test_widen(void)
1290 GpStatus status;
1291 GpPath *path;
1292 GpPen *pen;
1293 GpMatrix *m;
1294 INT count=-1;
1296 status = GdipCreatePath(FillModeAlternate, &path);
1297 expect(Ok, status);
1298 status = GdipCreatePen1(0xffffffff, 10.0, UnitPixel, &pen);
1299 expect(Ok, status);
1300 status = GdipCreateMatrix(&m);
1301 expect(Ok, status);
1303 /* NULL arguments */
1304 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1305 expect(Ok, status);
1306 status = GdipWidenPath(NULL, NULL, NULL, 0.0);
1307 expect(InvalidParameter, status);
1308 status = GdipWidenPath(path, pen, m, 0.0);
1309 expect(Ok, status);
1310 status = GdipWidenPath(path, pen, NULL, 1.0);
1311 expect(Ok, status);
1312 status = GdipWidenPath(path, NULL, m, 1.0);
1313 expect(InvalidParameter, status);
1314 status = GdipWidenPath(NULL, pen, m, 1.0);
1315 expect(InvalidParameter, status);
1317 /* widen empty path */
1318 status = GdipResetPath(path);
1319 expect(Ok, status);
1320 status = GdipWidenPath(path, pen, m, 1.0);
1321 expect(OutOfMemory, status);
1323 /* horizontal line */
1324 status = GdipResetPath(path);
1325 expect(Ok, status);
1326 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1327 expect(Ok, status);
1329 status = GdipWidenPath(path, pen, m, 1.0);
1330 expect(Ok, status);
1331 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1333 /* horizontal 2x stretch */
1334 status = GdipResetPath(path);
1335 expect(Ok, status);
1336 status = GdipAddPathLine(path, 2.5, 10.0, 25.0, 10.0);
1337 expect(Ok, status);
1339 status = GdipScaleMatrix(m, 2.0, 1.0, MatrixOrderAppend);
1340 expect(Ok, status);
1342 status = GdipWidenPath(path, pen, m, 1.0);
1343 expect(Ok, status);
1344 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1346 /* vertical 2x stretch */
1347 status = GdipResetPath(path);
1348 expect(Ok, status);
1349 status = GdipAddPathLine(path, 5.0, 5.0, 50.0, 5.0);
1350 expect(Ok, status);
1352 status = GdipScaleMatrix(m, 0.5, 2.0, MatrixOrderAppend);
1353 expect(Ok, status);
1355 status = GdipWidenPath(path, pen, m, 1.0);
1356 expect(Ok, status);
1357 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1359 status = GdipScaleMatrix(m, 1.0, 0.5, MatrixOrderAppend);
1360 expect(Ok, status);
1362 /* dashed line */
1363 status = GdipResetPath(path);
1364 expect(Ok, status);
1365 status = GdipAddPathLine(path, 5.0, 5.0, 50.0, 5.0);
1366 expect(Ok, status);
1368 status = GdipSetPenDashStyle(pen, DashStyleDash);
1369 expect(Ok, status);
1371 status = GdipWidenPath(path, pen, m, 1.0);
1372 expect(Ok, status);
1373 ok_path(path, widenline_dash_path, ARRAY_SIZE(widenline_dash_path), FALSE);
1375 status = GdipSetPenDashStyle(pen, DashStyleSolid);
1376 expect(Ok, status);
1378 /* pen width in UnitWorld */
1379 GdipDeletePen(pen);
1380 status = GdipCreatePen1(0xffffffff, 10.0, UnitWorld, &pen);
1381 expect(Ok, status);
1383 status = GdipResetPath(path);
1384 expect(Ok, status);
1385 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1386 expect(Ok, status);
1388 status = GdipWidenPath(path, pen, m, 1.0);
1389 expect(Ok, status);
1390 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1392 /* horizontal 2x stretch */
1393 status = GdipResetPath(path);
1394 expect(Ok, status);
1395 status = GdipAddPathLine(path, 2.5, 10.0, 25.0, 10.0);
1396 expect(Ok, status);
1398 status = GdipScaleMatrix(m, 2.0, 1.0, MatrixOrderAppend);
1399 expect(Ok, status);
1401 status = GdipWidenPath(path, pen, m, 1.0);
1402 expect(Ok, status);
1403 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1405 /* vertical 2x stretch */
1406 status = GdipResetPath(path);
1407 expect(Ok, status);
1408 status = GdipAddPathLine(path, 5.0, 5.0, 50.0, 5.0);
1409 expect(Ok, status);
1411 status = GdipScaleMatrix(m, 0.5, 2.0, MatrixOrderAppend);
1412 expect(Ok, status);
1414 status = GdipWidenPath(path, pen, m, 1.0);
1415 expect(Ok, status);
1416 ok_path(path, widenline_wide_path, ARRAY_SIZE(widenline_wide_path), FALSE);
1418 status = GdipScaleMatrix(m, 1.0, 0.5, MatrixOrderAppend);
1419 expect(Ok, status);
1421 /* pen width in UnitInch */
1422 GdipDeletePen(pen);
1423 status = GdipCreatePen1(0xffffffff, 10.0, UnitWorld, &pen);
1424 expect(Ok, status);
1426 status = GdipResetPath(path);
1427 expect(Ok, status);
1428 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1429 expect(Ok, status);
1431 status = GdipWidenPath(path, pen, m, 1.0);
1432 expect(Ok, status);
1433 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1435 /* pen width = 0 pixels - native fails to widen but can draw with this pen */
1436 GdipDeletePen(pen);
1437 status = GdipCreatePen1(0xffffffff, 0.0, UnitPixel, &pen);
1438 expect(Ok, status);
1440 status = GdipResetPath(path);
1441 expect(Ok, status);
1442 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1443 expect(Ok, status);
1445 status = GdipWidenPath(path, pen, m, 1.0);
1446 expect(Ok, status);
1448 status = GdipGetPointCount(path, &count);
1449 expect(Ok, status);
1450 expect(0, count);
1452 /* pen width = 0 pixels, UnitWorld - result is a path 1 unit wide */
1453 GdipDeletePen(pen);
1454 status = GdipCreatePen1(0xffffffff, 0.0, UnitWorld, &pen);
1455 expect(Ok, status);
1457 status = GdipResetPath(path);
1458 expect(Ok, status);
1459 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1460 expect(Ok, status);
1462 status = GdipWidenPath(path, pen, m, 1.0);
1463 expect(Ok, status);
1465 status = GdipGetPointCount(path, &count);
1466 expect(Ok, status);
1467 ok_path_fudge(path, widenline_unit_path, ARRAY_SIZE(widenline_unit_path), FALSE, 0.000005);
1469 GdipDeleteMatrix(m);
1470 GdipDeletePen(pen);
1471 GdipDeletePath(path);
1474 static path_test_t widenline_capflat_path[] = {
1475 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1476 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1477 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1478 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1481 static path_test_t widenline_capsquare_path[] = {
1482 {0.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1483 {55.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1484 {55.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1485 {0.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1488 static path_test_t widenline_capround_path[] = {
1489 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1490 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1491 {52.761421, 5.0, PathPointTypeBezier, 0, 0}, /*2*/
1492 {55.0, 7.238576, PathPointTypeBezier, 0, 0}, /*3*/
1493 {55.0, 10.0, PathPointTypeBezier, 0, 0}, /*4*/
1494 {55.0, 12.761423, PathPointTypeBezier, 0, 0}, /*5*/
1495 {52.761421, 15.0, PathPointTypeBezier, 0, 0}, /*6*/
1496 {50.0, 15.0, PathPointTypeBezier, 0, 0}, /*7*/
1497 {5.0, 15.0, PathPointTypeLine, 0, 0}, /*8*/
1498 {2.238576, 15.0, PathPointTypeBezier, 0, 0}, /*9*/
1499 {0.0, 12.761423, PathPointTypeBezier, 0, 0}, /*10*/
1500 {0.0, 10.0, PathPointTypeBezier, 0, 0}, /*11*/
1501 {0.0, 7.238576, PathPointTypeBezier, 0, 0}, /*12*/
1502 {2.238576, 5.0, PathPointTypeBezier, 0, 0}, /*13*/
1503 {5.0, 5.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*14*/
1506 static path_test_t widenline_captriangle_path[] = {
1507 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1508 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1509 {55.0, 10.0, PathPointTypeLine, 0, 0}, /*2*/
1510 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*3*/
1511 {5.0, 15.0, PathPointTypeLine, 0, 0}, /*4*/
1512 {0.0, 10.0, PathPointTypeLine, 0, 0}, /*5*/
1513 {5.0, 5.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*6*/
1516 static path_test_t widenline_capsquareanchor_path[] = {
1517 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1518 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1519 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1520 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1521 {12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*4*/
1522 {12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*5*/
1523 {-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*6*/
1524 {-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1525 {42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*8*/
1526 {42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*9*/
1527 {57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*10*/
1528 {57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
1531 static path_test_t widenline_caproundanchor_path[] = {
1532 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1533 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1534 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1535 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1536 {5.0, 20.0, PathPointTypeStart, 0, 0}, /*4*/
1537 {-0.522847, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
1538 {-5.0, 15.522846, PathPointTypeBezier, 0, 0}, /*6*/
1539 {-5.0, 10.0, PathPointTypeBezier, 0, 0}, /*7*/
1540 {-5.0, 4.477152, PathPointTypeBezier, 0, 0}, /*8*/
1541 {-0.522847, 0.0, PathPointTypeBezier, 0, 0}, /*9*/
1542 {5.0, 0.0, PathPointTypeBezier, 0, 0}, /*10*/
1543 {10.522847, 0.0, PathPointTypeBezier, 0, 0}, /*11*/
1544 {15.0, 4.477152, PathPointTypeBezier, 0, 0}, /*12*/
1545 {15.0, 10.0, PathPointTypeBezier, 0, 0}, /*13*/
1546 {15.0, 15.522846, PathPointTypeBezier, 0, 0}, /*14*/
1547 {10.522847, 20.0, PathPointTypeBezier, 0, 0}, /*15*/
1548 {5.0, 20.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*16*/
1549 {50.0, 0.0, PathPointTypeStart, 0, 0}, /*17*/
1550 {55.522846, 0.0, PathPointTypeBezier, 0, 0}, /*18*/
1551 {60.0, 4.477153, PathPointTypeBezier, 0, 0}, /*19*/
1552 {60.0, 10.0, PathPointTypeBezier, 0, 0}, /*20*/
1553 {60.0, 15.522847, PathPointTypeBezier, 0, 0}, /*21*/
1554 {55.522846, 20.0, PathPointTypeBezier, 0, 0}, /*22*/
1555 {50.0, 20.0, PathPointTypeBezier, 0, 0}, /*23*/
1556 {44.477150, 20.0, PathPointTypeBezier, 0, 0}, /*24*/
1557 {40.0, 15.522847, PathPointTypeBezier, 0, 0}, /*25*/
1558 {40.0, 10.0, PathPointTypeBezier, 0, 0}, /*26*/
1559 {40.0, 4.477153, PathPointTypeBezier, 0, 0}, /*27*/
1560 {44.477150, 0.0, PathPointTypeBezier, 0, 0}, /*28*/
1561 {50.0, 0.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*29*/
1564 static path_test_t widenline_capdiamondanchor_path[] = {
1565 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1566 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1567 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1568 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1569 {-5.0, 10.0, PathPointTypeStart, 0, 0}, /*4*/
1570 {5.0, 0.0, PathPointTypeLine, 0, 0}, /*5*/
1571 {15.0, 10.0, PathPointTypeLine, 0, 0}, /*6*/
1572 {5.0, 20.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1573 {60.0, 10.0, PathPointTypeStart, 0, 0}, /*8*/
1574 {50.0, 20.0, PathPointTypeLine, 0, 0}, /*9*/
1575 {40.0, 10.0, PathPointTypeLine, 0, 0}, /*10*/
1576 {50.0, 0.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
1579 static path_test_t widenline_caparrowanchor_path[] = {
1580 {15.0, 5.0, PathPointTypeStart, 0, 1}, /*0*/
1581 {40.0, 5.0, PathPointTypeLine, 0, 1}, /*1*/
1582 {40.0, 15.0, PathPointTypeLine, 0, 1}, /*2*/
1583 {15.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 1}, /*3*/
1584 {5.0, 10.0, PathPointTypeStart, 0, 0}, /*4*/
1585 {22.320507, 0.0, PathPointTypeLine, 0, 0}, /*5*/
1586 {22.320507, 20.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*6*/
1587 {50.0, 10.0, PathPointTypeStart, 0, 0}, /*7*/
1588 {32.679489, 20.0, PathPointTypeLine, 0, 0}, /*8*/
1589 {32.679489, 0.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*9*/
1592 static path_test_t widenline_capsquareanchor_thin_path[] = {
1593 {6.414213, 8.585786, PathPointTypeStart, 0, 0}, /*0*/
1594 {6.414213, 11.414213, PathPointTypeLine, 0, 0}, /*1*/
1595 {3.585786, 11.414213, PathPointTypeLine, 0, 0}, /*2*/
1596 {3.585786, 8.585786, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1597 {48.585785, 11.414213, PathPointTypeStart, 0, 0}, /*4*/
1598 {48.585785, 8.585786, PathPointTypeLine, 0, 0}, /*5*/
1599 {51.414211, 8.585786, PathPointTypeLine, 0, 0}, /*6*/
1600 {51.414211, 11.414213, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1603 static path_test_t widenline_capsquareanchor_dashed_path[] = {
1604 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1605 {35.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1606 {35.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1607 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1608 {45.0, 5.0, PathPointTypeStart, 0, 0}, /*4*/
1609 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*5*/
1610 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*6*/
1611 {45.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1612 {12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*8*/
1613 {12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*9*/
1614 {-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*10*/
1615 {-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
1616 {42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*12*/
1617 {42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*13*/
1618 {57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*14*/
1619 {57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*15*/
1622 static path_test_t widenline_capsquareanchor_multifigure_path[] = {
1623 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1624 {25.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1625 {25.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1626 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1627 {30.0, 5.0, PathPointTypeStart, 0, 0}, /*4*/
1628 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*5*/
1629 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*6*/
1630 {30.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1631 {12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*8*/
1632 {12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*9*/
1633 {-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*10*/
1634 {-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
1635 {17.928930, 17.071068, PathPointTypeStart, 0, 0}, /*12*/
1636 {17.928930, 2.928932, PathPointTypeLine, 0, 0}, /*13*/
1637 {32.071068, 2.928932, PathPointTypeLine, 0, 0}, /*14*/
1638 {32.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*15*/
1639 {37.071068, 2.928932, PathPointTypeStart, 0, 0}, /*16*/
1640 {37.071068, 17.071066, PathPointTypeLine, 0, 0}, /*17*/
1641 {22.928930, 17.071066, PathPointTypeLine, 0, 0}, /*18*/
1642 {22.928930, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*19*/
1643 {42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*20*/
1644 {42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*21*/
1645 {57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*22*/
1646 {57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*23*/
1649 static void test_widen_cap(void)
1651 struct
1653 LineCap type;
1654 REAL line_width;
1655 const path_test_t *expected;
1656 INT expected_size;
1657 BOOL dashed;
1658 BOOL todo_size;
1660 caps[] =
1662 { LineCapFlat, 10.0, widenline_capflat_path,
1663 ARRAY_SIZE(widenline_capflat_path) },
1664 { LineCapSquare, 10.0, widenline_capsquare_path,
1665 ARRAY_SIZE(widenline_capsquare_path) },
1666 { LineCapRound, 10.0, widenline_capround_path,
1667 ARRAY_SIZE(widenline_capround_path) },
1668 { LineCapTriangle, 10.0, widenline_captriangle_path,
1669 ARRAY_SIZE(widenline_captriangle_path) },
1670 { LineCapNoAnchor, 10.0, widenline_capflat_path,
1671 ARRAY_SIZE(widenline_capflat_path) },
1672 { LineCapSquareAnchor, 10.0, widenline_capsquareanchor_path,
1673 ARRAY_SIZE(widenline_capsquareanchor_path) },
1674 { LineCapRoundAnchor, 10.0, widenline_caproundanchor_path,
1675 ARRAY_SIZE(widenline_caproundanchor_path) },
1676 { LineCapDiamondAnchor, 10.0, widenline_capdiamondanchor_path,
1677 ARRAY_SIZE(widenline_capdiamondanchor_path) },
1678 { LineCapArrowAnchor, 10.0, widenline_caparrowanchor_path,
1679 ARRAY_SIZE(widenline_caparrowanchor_path), FALSE, TRUE },
1680 { LineCapSquareAnchor, 0.0, widenline_capsquareanchor_thin_path,
1681 ARRAY_SIZE(widenline_capsquareanchor_thin_path) },
1682 { LineCapSquareAnchor, 10.0, widenline_capsquareanchor_dashed_path,
1683 ARRAY_SIZE(widenline_capsquareanchor_dashed_path), TRUE },
1685 GpStatus status;
1686 GpPath *path;
1687 GpPen *pen;
1688 int i;
1690 status = GdipCreatePath(FillModeAlternate, &path);
1691 expect(Ok, status);
1693 for (i = 0; i < ARRAY_SIZE(caps); i++)
1695 status = GdipCreatePen1(0xffffffff, caps[i].line_width, UnitPixel, &pen);
1696 expect(Ok, status);
1697 if (caps[i].dashed)
1699 status = GdipSetPenDashStyle(pen, DashStyleDash);
1700 expect(Ok, status);
1703 status = GdipResetPath(path);
1704 expect(Ok, status);
1705 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1706 expect(Ok, status);
1707 status = GdipSetPenStartCap(pen, caps[i].type);
1708 expect(Ok, status);
1709 status = GdipSetPenEndCap(pen, caps[i].type);
1710 expect(Ok, status);
1712 status = GdipWidenPath(path, pen, NULL, FlatnessDefault);
1713 expect(Ok, status);
1714 ok_path_fudge(path, caps[i].expected, caps[i].expected_size, caps[i].todo_size, 0.000005);
1716 GdipDeletePen(pen);
1719 status = GdipCreatePen1(0xffffffff, 10.0, UnitPixel, &pen);
1720 expect(Ok, status);
1721 status = GdipResetPath(path);
1722 expect(Ok, status);
1723 status = GdipAddPathLine(path, 5.0, 10.0, 25.0, 10.0);
1724 expect(Ok, status);
1725 status = GdipStartPathFigure(path);
1726 expect(Ok, status);
1727 status = GdipAddPathLine(path, 30.0, 10.0, 50.0, 10.0);
1728 expect(Ok, status);
1729 status = GdipSetPenStartCap(pen, LineCapSquareAnchor);
1730 expect(Ok, status);
1731 status = GdipSetPenEndCap(pen, LineCapSquareAnchor);
1732 expect(Ok, status);
1733 status = GdipWidenPath(path, pen, NULL, FlatnessDefault);
1734 expect(Ok, status);
1735 ok_path_fudge(path, widenline_capsquareanchor_multifigure_path,
1736 ARRAY_SIZE(widenline_capsquareanchor_multifigure_path), FALSE, 0.000005);
1737 GdipDeletePen(pen);
1739 GdipDeletePath(path);
1742 static void test_isvisible(void)
1744 GpPath *path;
1745 GpGraphics *graphics = NULL;
1746 HDC hdc = GetDC(0);
1747 BOOL result;
1748 GpStatus status;
1750 status = GdipCreateFromHDC(hdc, &graphics);
1751 expect(Ok, status);
1752 status = GdipCreatePath(FillModeAlternate, &path);
1753 expect(Ok, status);
1755 /* NULL */
1756 status = GdipIsVisiblePathPoint(NULL, 0.0, 0.0, NULL, NULL);
1757 expect(InvalidParameter, status);
1758 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, NULL);
1759 expect(InvalidParameter, status);
1760 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, NULL);
1761 expect(InvalidParameter, status);
1762 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, graphics, NULL);
1763 expect(InvalidParameter, status);
1765 /* empty path */
1766 result = TRUE;
1767 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, &result);
1768 expect(Ok, status);
1769 expect(FALSE, result);
1770 /* rect */
1771 status = GdipAddPathRectangle(path, 0.0, 0.0, 10.0, 10.0);
1772 expect(Ok, status);
1773 result = FALSE;
1774 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, &result);
1775 expect(Ok, status);
1776 expect(TRUE, result);
1777 result = TRUE;
1778 status = GdipIsVisiblePathPoint(path, 11.0, 11.0, NULL, &result);
1779 expect(Ok, status);
1780 expect(FALSE, result);
1781 /* not affected by clipping */
1782 status = GdipSetClipRect(graphics, 5.0, 5.0, 5.0, 5.0, CombineModeReplace);
1783 expect(Ok, status);
1784 result = FALSE;
1785 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, graphics, &result);
1786 expect(Ok, status);
1787 expect(TRUE, result);
1789 GdipDeletePath(path);
1790 GdipDeleteGraphics(graphics);
1791 ReleaseDC(0, hdc);
1794 static void test_empty_rect(void)
1796 GpPath *path;
1797 GpStatus status;
1798 INT count;
1799 BOOL result;
1801 status = GdipCreatePath(FillModeAlternate, &path);
1802 expect(Ok, status);
1804 status = GdipAddPathRectangle(path, 0.0, 0.0, -5.0, 5.0);
1805 expect(Ok, status);
1807 status = GdipGetPointCount(path, &count);
1808 expect(Ok, status);
1809 expect(0, count);
1811 status = GdipIsVisiblePathPoint(path, -2.0, 2.0, NULL, &result);
1812 expect(Ok, status);
1813 expect(FALSE, result);
1815 status = GdipAddPathRectangle(path, 0.0, 0.0, 5.0, -5.0);
1816 expect(Ok, status);
1818 status = GdipGetPointCount(path, &count);
1819 expect(Ok, status);
1820 expect(0, count);
1822 status = GdipAddPathRectangle(path, 0.0, 0.0, 0.0, 5.0);
1823 expect(Ok, status);
1825 status = GdipGetPointCount(path, &count);
1826 expect(Ok, status);
1827 expect(0, count);
1829 status = GdipAddPathRectangle(path, 0.0, 0.0, 5.0, 0.0);
1830 expect(Ok, status);
1832 status = GdipGetPointCount(path, &count);
1833 expect(Ok, status);
1834 expect(0, count);
1836 status = GdipAddPathRectangle(path, 0.0, 0.0, 5.0, 0.1);
1837 expect(Ok, status);
1839 status = GdipGetPointCount(path, &count);
1840 expect(Ok, status);
1841 expect(4, count);
1843 GdipDeletePath(path);
1846 START_TEST(graphicspath)
1848 struct GdiplusStartupInput gdiplusStartupInput;
1849 ULONG_PTR gdiplusToken;
1850 HMODULE hmsvcrt;
1851 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
1853 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
1854 hmsvcrt = LoadLibraryA("msvcrt");
1855 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
1856 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
1858 gdiplusStartupInput.GdiplusVersion = 1;
1859 gdiplusStartupInput.DebugEventCallback = NULL;
1860 gdiplusStartupInput.SuppressBackgroundThread = 0;
1861 gdiplusStartupInput.SuppressExternalCodecs = 0;
1863 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
1865 test_constructor_destructor();
1866 test_getpathdata();
1867 test_createpath2();
1868 test_line2();
1869 test_bezier();
1870 test_beziers();
1871 test_arc();
1872 test_worldbounds();
1873 test_pathpath();
1874 test_ellipse();
1875 test_linei();
1876 test_rect();
1877 test_polygon();
1878 test_lastpoint();
1879 test_addcurve();
1880 test_addclosedcurve();
1881 test_reverse();
1882 test_addpie();
1883 test_flatten();
1884 test_widen();
1885 test_widen_cap();
1886 test_isvisible();
1887 test_empty_rect();
1889 GdiplusShutdown(gdiplusToken);