push 63c1876572cbb61a874995ad42ef27c14590d232
[wine/hacks.git] / dlls / gdiplus / tests / graphicspath.c
blobd08b20b8411ac86d8610d6c17bf81e92bbdbc899
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 "windows.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 static void ok_path(GpPath* path, const path_test_t *expected, INT expected_size, BOOL todo_size)
80 BYTE * types;
81 INT size, idx = 0, eidx = 0, numskip;
82 GpPointF * points;
83 char ename[POINT_TYPE_MAX_LEN], name[POINT_TYPE_MAX_LEN];
85 if(GdipGetPointCount(path, &size) != Ok){
86 skip("Cannot perform path comparisons due to failure to retrieve path.\n");
87 return;
90 if(todo_size) todo_wine
91 ok(size == expected_size, "Path size %d does not match expected size %d\n",
92 size, expected_size);
93 else
94 ok(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) <= 2.0 &&
111 fabs(points[idx].Y - expected[eidx].Y) <= 2.0;
113 stringify_point_type(expected[eidx].type, ename);
114 stringify_point_type(types[idx], name);
116 if (expected[eidx].todo || numskip) todo_wine
117 ok(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);
120 else
121 ok(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx,
122 ename, expected[eidx].X, expected[eidx].Y,
123 name, points[idx].X, points[idx].Y);
125 if (match || expected[eidx].todo != 2)
126 idx++;
127 if (match || !numskip--)
128 numskip = expected[++eidx].wine_only_entries_preceding;
131 end:
132 HeapFree(GetProcessHeap(), 0, types);
133 HeapFree(GetProcessHeap(), 0, points);
136 static void test_constructor_destructor(void)
138 GpStatus status;
139 GpPath* path = NULL;
141 status = GdipCreatePath(FillModeAlternate, &path);
142 expect(Ok, status);
143 ok(path != NULL, "Expected path to be initialized\n");
145 status = GdipDeletePath(NULL);
146 expect(InvalidParameter, status);
148 status = GdipDeletePath(path);
149 expect(Ok, status);
152 static void test_getpathdata(void)
154 GpPath *path;
155 GpPathData data;
156 GpStatus status;
157 INT count;
159 GdipCreatePath(FillModeAlternate, &path);
160 status = GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
161 expect(Ok, status);
163 /* Prepare storage. Made by wrapper class. */
164 status = GdipGetPointCount(path, &count);
165 expect(Ok, status);
167 data.Count = 2;
168 data.Types = GdipAlloc(sizeof(BYTE) * count);
169 data.Points = GdipAlloc(sizeof(PointF) * count);
171 status = GdipGetPathData(path, &data);
172 expect(Ok, status);
173 expect((data.Points[0].X == 5.0) && (data.Points[0].Y == 5.0) &&
174 (data.Points[1].X == 100.0) && (data.Points[1].Y == 50.0), TRUE);
175 expect((data.Types[0] == PathPointTypeStart) && (data.Types[1] == PathPointTypeLine), TRUE);
177 GdipFree(data.Points);
178 GdipFree(data.Types);
179 GdipDeletePath(path);
182 static path_test_t line2_path[] = {
183 {0.0, 50.0, PathPointTypeStart, 0, 0}, /*0*/
184 {5.0, 45.0, PathPointTypeLine, 0, 0}, /*1*/
185 {0.0, 40.0, PathPointTypeLine, 0, 0}, /*2*/
186 {15.0, 35.0, PathPointTypeLine, 0, 0}, /*3*/
187 {0.0, 30.0, PathPointTypeLine, 0, 0}, /*4*/
188 {25.0, 25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*5*/
189 {0.0, 20.0, PathPointTypeStart, 0, 0}, /*6*/
190 {35.0, 15.0, PathPointTypeLine, 0, 0}, /*7*/
191 {0.0, 10.0, PathPointTypeLine, 0, 0} /*8*/
194 static void test_line2(void)
196 GpStatus status;
197 GpPath* path;
198 int i;
199 GpPointF line2_points[9];
201 for(i = 0; i < 9; i ++){
202 line2_points[i].X = i * 5.0 * (REAL)(i % 2);
203 line2_points[i].Y = 50.0 - i * 5.0;
206 GdipCreatePath(FillModeAlternate, &path);
207 status = GdipAddPathLine2(path, line2_points, 3);
208 expect(Ok, status);
209 status = GdipAddPathLine2(path, &(line2_points[3]), 3);
210 expect(Ok, status);
211 status = GdipClosePathFigure(path);
212 expect(Ok, status);
213 status = GdipAddPathLine2(path, &(line2_points[6]), 3);
214 expect(Ok, status);
216 ok_path(path, line2_path, sizeof(line2_path)/sizeof(path_test_t), FALSE);
219 static path_test_t arc_path[] = {
220 {600.0, 450.0, PathPointTypeStart, 0, 0}, /*0*/
221 {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*1*/
222 {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*2*/
223 {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*3*/
224 {600.0, 450.0, PathPointTypeLine, 0, 0}, /*4*/
225 {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*5*/
226 {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*6*/
227 {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*7*/
228 {329.8, 800.0, PathPointTypeBezier, 0, 0}, /*8*/
229 {309.7, 796.6, PathPointTypeBezier, 0, 0}, /*9*/
230 {290.1, 789.8, PathPointTypeBezier, 0, 0}, /*10*/
231 {409.9, 110.2, PathPointTypeLine, 0, 0}, /*11*/
232 {544.0, 156.5, PathPointTypeBezier, 0, 0}, /*12*/
233 {625.8, 346.2, PathPointTypeBezier, 0, 0}, /*13*/
234 {592.7, 533.9, PathPointTypeBezier, 0, 0}, /*14*/
235 {592.5, 535.3, PathPointTypeBezier, 0, 0}, /*15*/
236 {592.2, 536.7, PathPointTypeBezier, 0, 0}, /*16*/
237 {592.0, 538.1, PathPointTypeBezier, 0, 0}, /*17*/
238 {409.9, 789.8, PathPointTypeLine, 0, 0}, /*18*/
239 {544.0, 743.5, PathPointTypeBezier, 0, 0}, /*19*/
240 {625.8, 553.8, PathPointTypeBezier, 0, 0}, /*20*/
241 {592.7, 366.1, PathPointTypeBezier, 0, 0}, /*21*/
242 {592.5, 364.7, PathPointTypeBezier, 0, 0}, /*22*/
243 {592.2, 363.3, PathPointTypeBezier, 0, 0}, /*23*/
244 {592.0, 361.9, PathPointTypeBezier, 0, 0}, /*24*/
245 {540.4, 676.9, PathPointTypeLine, 0, 0}, /*25*/
246 {629.9, 529.7, PathPointTypeBezier, 0, 0}, /*26*/
247 {617.2, 308.8, PathPointTypeBezier, 0, 0}, /*27*/
248 {512.1, 183.5, PathPointTypeBezier, 0, 0}, /*28*/
249 {406.9, 58.2, PathPointTypeBezier, 0, 0}, /*29*/
250 {249.1, 75.9, PathPointTypeBezier, 0, 0}, /*30*/
251 {159.6, 223.1, PathPointTypeBezier, 0, 0}, /*31*/
252 {70.1, 370.3, PathPointTypeBezier, 0, 0}, /*32*/
253 {82.8, 591.2, PathPointTypeBezier, 0, 0}, /*33*/
254 {187.9, 716.5, PathPointTypeBezier, 0, 0}, /*34*/
255 {293.1, 841.8, PathPointTypeBezier, 0, 0}, /*35*/
256 {450.9, 824.1, PathPointTypeBezier, 0, 0}, /*36*/
257 {540.4, 676.9, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 1} /*37*/
260 static void test_arc(void)
262 GpStatus status;
263 GpPath* path;
265 GdipCreatePath(FillModeAlternate, &path);
266 /* Exactly 90 degrees */
267 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
268 expect(Ok, status);
269 /* Over 90 degrees */
270 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
271 expect(Ok, status);
272 /* Negative start angle */
273 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
274 expect(Ok, status);
275 /* Negative sweep angle */
276 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 80.0, -100.0);
277 expect(Ok, status);
278 /* More than a full revolution */
279 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, -400.0);
280 expect(Ok, status);
281 /* 0 sweep angle */
282 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, 0.0);
283 expect(Ok, status);
285 ok_path(path, arc_path, sizeof(arc_path)/sizeof(path_test_t), FALSE);
288 static void test_worldbounds(void)
290 GpStatus status;
291 GpPath *path;
292 GpPen *pen;
293 GpMatrix *matrix;
294 GpRectF bounds;
295 GpPointF line2_points[10];
296 int i;
298 for(i = 0; i < 10; i ++){
299 line2_points[i].X = 200.0 + i * 50.0 * (i % 2);
300 line2_points[i].Y = 200.0 + i * 50.0 * !(i % 2);
302 GdipCreatePen1((ARGB)0xdeadbeef, 20.0, UnitWorld, &pen);
303 GdipSetPenEndCap(pen, LineCapSquareAnchor);
304 GdipCreateMatrix2(1.5, 0.0, 1.0, 1.2, 10.4, 10.2, &matrix);
306 GdipCreatePath(FillModeAlternate, &path);
307 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
308 GdipAddPathLine2(path, &(line2_points[0]), 10);
309 status = GdipGetPathWorldBounds(path, &bounds, NULL, NULL);
310 expect(Ok, status);
311 GdipDeletePath(path);
313 expectf(200.0, bounds.X);
314 expectf(200.0, bounds.Y);
315 expectf(450.0, bounds.Width);
316 expectf(600.0, bounds.Height);
318 GdipCreatePath(FillModeAlternate, &path);
319 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
320 GdipAddPathLine2(path, &(line2_points[0]), 10);
321 status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
322 expect(Ok, status);
323 GdipDeletePath(path);
325 expectf(510.4, bounds.X);
326 expectf(250.2, bounds.Y);
327 expectf(1275.0, bounds.Width);
328 expectf(720.0, bounds.Height);
330 GdipCreatePath(FillModeAlternate, &path);
331 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
332 GdipAddPathLine2(path, &(line2_points[0]), 10);
333 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
334 expect(Ok, status);
335 GdipDeletePath(path);
337 expectf(100.0, bounds.X);
338 expectf(100.0, bounds.Y);
339 expectf(650.0, bounds.Width);
340 expectf(800.0, bounds.Height);
342 GdipCreatePath(FillModeAlternate, &path);
343 GdipAddPathLine2(path, &(line2_points[0]), 2);
344 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
345 expect(Ok, status);
346 GdipDeletePath(path);
348 expectf(156.0, bounds.X);
349 expectf(156.0, bounds.Y);
350 expectf(138.0, bounds.Width);
351 expectf(88.0, bounds.Height);
353 line2_points[2].X = 2 * line2_points[1].X - line2_points[0].X;
354 line2_points[2].Y = 2 * line2_points[1].Y - line2_points[0].Y;
356 GdipCreatePath(FillModeAlternate, &path);
357 GdipAddPathLine2(path, &(line2_points[0]), 3);
358 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
359 expect(Ok, status);
360 GdipDeletePath(path);
362 expectf(100.0, bounds.X);
363 expectf(100.0, bounds.Y);
364 expectf(300.0, bounds.Width);
365 expectf(200.0, bounds.Height);
367 GdipCreatePath(FillModeAlternate, &path);
368 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 45.0, 20.0);
369 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
370 expect(Ok, status);
371 GdipDeletePath(path);
373 expectf(386.7, bounds.X);
374 expectf(553.4, bounds.Y);
375 expectf(266.8, bounds.Width);
376 expectf(289.6, bounds.Height);
378 GdipCreatePath(FillModeAlternate, &path);
379 status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
380 expect(Ok, status);
381 GdipDeletePath(path);
383 expectf(0.0, bounds.X);
384 expectf(0.0, bounds.Y);
385 expectf(0.0, bounds.Width);
386 expectf(0.0, bounds.Height);
388 GdipCreatePath(FillModeAlternate, &path);
389 GdipAddPathLine2(path, &(line2_points[0]), 2);
390 status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
391 expect(Ok, status);
392 GdipDeletePath(path);
394 todo_wine{
395 expectf(427.9, bounds.X);
396 expectf(167.7, bounds.Y);
397 expectf(239.9, bounds.Width);
398 expectf(164.9, bounds.Height);
401 GdipDeleteMatrix(matrix);
402 GdipCreateMatrix2(0.9, -0.5, -0.5, -1.2, 10.4, 10.2, &matrix);
403 GdipCreatePath(FillModeAlternate, &path);
404 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
405 GdipAddPathLine2(path, &(line2_points[0]), 10);
406 status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
407 expect(Ok, status);
408 GdipDeletePath(path);
410 expectf(-209.6, bounds.X);
411 expectf(-1274.8, bounds.Y);
412 expectf(705.0, bounds.Width);
413 expectf(945.0, bounds.Height);
416 static path_test_t pathpath_path[] = {
417 {600.00, 450.00, PathPointTypeStart, 0, 0}, /*0*/
418 {600.00, 643.30, PathPointTypeBezier, 0, 0}, /*1*/
419 {488.07, 800.00, PathPointTypeBezier, 0, 0}, /*2*/
420 {350.00, 800.00, PathPointTypeBezier, 0, 0}, /*3*/
421 {319.61, 797.40, PathPointTypeStart, 0, 0}, /*4*/
422 {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*5*/
423 {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*6*/
424 {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*7*/
425 {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*8*/
426 {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*9*/
427 {104.46, 384.21, PathPointTypeBezier, 0, 0}, /*10*/
428 {409.92, 110.20, PathPointTypeLine, 0, 0}, /*11*/
429 {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*12*/
430 {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*13*/
431 {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*14*/
432 {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*15*/
433 {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*16*/
434 {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*17*/
435 {319.61, 797.40, PathPointTypeLine, 0, 0}, /*18*/
436 {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*19*/
437 {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*20*/
438 {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*21*/
439 {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*22*/
440 {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*23*/
441 {104.46, 384.21, PathPointTypeBezier, 0, 0} /*24*/
444 static void test_pathpath(void)
446 GpStatus status;
447 GpPath* path1, *path2;
449 GdipCreatePath(FillModeAlternate, &path2);
450 GdipAddPathArc(path2, 100.0, 100.0, 500.0, 700.0, 95.0, 100.0);
452 GdipCreatePath(FillModeAlternate, &path1);
453 GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
454 status = GdipAddPathPath(path1, path2, FALSE);
455 expect(Ok, status);
456 GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
457 status = GdipAddPathPath(path1, path2, TRUE);
458 expect(Ok, status);
460 ok_path(path1, pathpath_path, sizeof(pathpath_path)/sizeof(path_test_t), FALSE);
462 GdipDeletePath(path1);
463 GdipDeletePath(path2);
466 static path_test_t ellipse_path[] = {
467 {30.00, 125.25, PathPointTypeStart, 0, 0}, /*0*/
468 {30.00, 139.20, PathPointTypeBezier, 0, 0}, /*1*/
469 {25.52, 150.50, PathPointTypeBezier, 0, 0}, /*2*/
470 {20.00, 150.50, PathPointTypeBezier, 0, 0}, /*3*/
471 {14.48, 150.50, PathPointTypeBezier, 0, 0}, /*4*/
472 {10.00, 139.20, PathPointTypeBezier, 0, 0}, /*5*/
473 {10.00, 125.25, PathPointTypeBezier, 0, 0}, /*6*/
474 {10.00, 111.30, PathPointTypeBezier, 0, 0}, /*7*/
475 {14.48, 100.00, PathPointTypeBezier, 0, 0}, /*8*/
476 {20.00, 100.00, PathPointTypeBezier, 0, 0}, /*9*/
477 {25.52, 100.00, PathPointTypeBezier, 0, 0}, /*10*/
478 {30.00, 111.30, PathPointTypeBezier, 0, 0}, /*11*/
479 {30.00, 125.25, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*12*/
480 {7.00, 11.00, PathPointTypeStart, 0, 0}, /*13*/
481 {13.00, 17.00, PathPointTypeLine, 0, 0}, /*14*/
482 {5.00, 195.00, PathPointTypeStart, 0, 0}, /*15*/
483 {5.00, 192.24, PathPointTypeBezier, 0, 0}, /*16*/
484 {6.12, 190.00, PathPointTypeBezier, 0, 0}, /*17*/
485 {7.50, 190.00, PathPointTypeBezier, 0, 0}, /*18*/
486 {8.88, 190.00, PathPointTypeBezier, 0, 0}, /*19*/
487 {10.00, 192.24, PathPointTypeBezier, 0, 0}, /*20*/
488 {10.00, 195.00, PathPointTypeBezier, 0, 0}, /*21*/
489 {10.00, 197.76, PathPointTypeBezier, 0, 0}, /*22*/
490 {8.88, 200.00, PathPointTypeBezier, 0, 0}, /*23*/
491 {7.50, 200.00, PathPointTypeBezier, 0, 0}, /*24*/
492 {6.12, 200.00, PathPointTypeBezier, 0, 0}, /*25*/
493 {5.00, 197.76, PathPointTypeBezier, 0, 0}, /*26*/
494 {5.00, 195.00, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*27*/
495 {10.00, 300.50, PathPointTypeStart, 0, 0}, /*28*/
496 {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*29*/
497 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*30*/
498 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*31*/
499 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*32*/
500 {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*33*/
501 {10.00, 300.50, PathPointTypeBezier, 0, 0}, /*34*/
502 {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*35*/
503 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*36*/
504 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*37*/
505 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*38*/
506 {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*39*/
507 {10.00, 300.50, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*40*/
510 static void test_ellipse(void)
512 GpStatus status;
513 GpPath *path;
514 GpPointF points[2];
516 points[0].X = 7.0;
517 points[0].Y = 11.0;
518 points[1].X = 13.0;
519 points[1].Y = 17.0;
521 GdipCreatePath(FillModeAlternate, &path);
522 status = GdipAddPathEllipse(path, 10.0, 100.0, 20.0, 50.5);
523 expect(Ok, status);
524 GdipAddPathLine2(path, points, 2);
525 status = GdipAddPathEllipse(path, 10.0, 200.0, -5.0, -10.0);
526 expect(Ok, status);
527 GdipClosePathFigure(path);
528 status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0);
529 expect(Ok, status);
531 ok_path(path, ellipse_path, sizeof(ellipse_path)/sizeof(path_test_t), FALSE);
533 GdipDeletePath(path);
536 static path_test_t linei_path[] = {
537 {5.00, 5.00, PathPointTypeStart, 0, 0}, /*0*/
538 {6.00, 8.00, PathPointTypeLine, 0, 0}, /*1*/
539 {409.92, 110.20, PathPointTypeLine, 0, 0}, /*2*/
540 {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*3*/
541 {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*4*/
542 {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*5*/
543 {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*6*/
544 {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*7*/
545 {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*8*/
546 {15.00, 15.00, PathPointTypeLine, 0, 0}, /*9*/
547 {26.00, 28.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*10*/
548 {35.00, 35.00, PathPointTypeStart, 0, 0}, /*11*/
549 {36.00, 38.00, PathPointTypeLine, 0, 0} /*12*/
552 static void test_linei(void)
554 GpStatus status;
555 GpPath *path;
556 GpPointF points[2];
558 points[0].X = 7.0;
559 points[0].Y = 11.0;
560 points[1].X = 13.0;
561 points[1].Y = 17.0;
563 GdipCreatePath(FillModeAlternate, &path);
564 status = GdipAddPathLineI(path, 5.0, 5.0, 6.0, 8.0);
565 expect(Ok, status);
566 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
567 status = GdipAddPathLineI(path, 15.0, 15.0, 26.0, 28.0);
568 expect(Ok, status);
569 GdipClosePathFigure(path);
570 status = GdipAddPathLineI(path, 35.0, 35.0, 36.0, 38.0);
571 expect(Ok, status);
573 ok_path(path, linei_path, sizeof(linei_path)/sizeof(path_test_t), FALSE);
575 GdipDeletePath(path);
578 static path_test_t poly_path[] = {
579 {5.00, 5.00, PathPointTypeStart, 0, 0}, /*1*/
580 {6.00, 8.00, PathPointTypeLine, 0, 0}, /*2*/
581 {0.00, 0.00, PathPointTypeStart, 0, 0}, /*3*/
582 {10.00, 10.00, PathPointTypeLine, 0, 0}, /*4*/
583 {10.00, 20.00, PathPointTypeLine, 0, 0}, /*5*/
584 {30.00, 10.00, PathPointTypeLine, 0, 0}, /*6*/
585 {20.00, 0.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*7*/
588 static void test_polygon(void)
590 GpStatus status;
591 GpPath *path;
592 GpPointF points[5];
594 points[0].X = 0.0;
595 points[0].Y = 0.0;
596 points[1].X = 10.0;
597 points[1].Y = 10.0;
598 points[2].X = 10.0;
599 points[2].Y = 20.0;
600 points[3].X = 30.0;
601 points[3].Y = 10.0;
602 points[4].X = 20.0;
603 points[4].Y = 0.0;
605 GdipCreatePath(FillModeAlternate, &path);
607 /* NULL args */
608 status = GdipAddPathPolygon(NULL, points, 5);
609 expect(InvalidParameter, status);
610 status = GdipAddPathPolygon(path, NULL, 5);
611 expect(InvalidParameter, status);
612 /* Polygon should have 3 points at least */
613 status = GdipAddPathPolygon(path, points, 2);
614 expect(InvalidParameter, status);
616 /* to test how it prolongs not empty path */
617 status = GdipAddPathLine(path, 5.0, 5.0, 6.0, 8.0);
618 expect(Ok, status);
619 status = GdipAddPathPolygon(path, points, 5);
620 expect(Ok, status);
621 /* check resulting path */
622 ok_path(path, poly_path, sizeof(poly_path)/sizeof(path_test_t), FALSE);
624 GdipDeletePath(path);
627 static path_test_t rect_path[] = {
628 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
629 {105.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
630 {105.0, 55.0, PathPointTypeLine, 0, 0}, /*2*/
631 {5.0, 55.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*3*/
633 {100.0, 50.0, PathPointTypeStart, 0, 0}, /*4*/
634 {220.0, 50.0, PathPointTypeLine, 0, 0}, /*5*/
635 {220.0, 80.0, PathPointTypeLine, 0, 0}, /*6*/
636 {100.0, 80.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*7*/
639 static void test_rect(void)
641 GpStatus status;
642 GpPath *path;
643 GpRectF rects[2];
645 GdipCreatePath(FillModeAlternate, &path);
646 status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
647 expect(Ok, status);
648 status = GdipAddPathRectangle(path, 100.0, 50.0, 120.0, 30.0);
649 expect(Ok, status);
651 ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE);
653 GdipDeletePath(path);
655 GdipCreatePath(FillModeAlternate, &path);
657 rects[0].X = 5.0;
658 rects[0].Y = 5.0;
659 rects[0].Width = 100.0;
660 rects[0].Height = 50.0;
661 rects[1].X = 100.0;
662 rects[1].Y = 50.0;
663 rects[1].Width = 120.0;
664 rects[1].Height = 30.0;
666 status = GdipAddPathRectangles(path, (GDIPCONST GpRectF*)&rects, 2);
667 expect(Ok, status);
669 ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE);
671 GdipDeletePath(path);
674 static void test_lastpoint(void)
676 GpStatus status;
677 GpPath *path;
678 GpPointF ptf;
680 GdipCreatePath(FillModeAlternate, &path);
681 status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
682 expect(Ok, status);
684 /* invalid args */
685 status = GdipGetPathLastPoint(NULL, &ptf);
686 expect(InvalidParameter, status);
687 status = GdipGetPathLastPoint(path, NULL);
688 expect(InvalidParameter, status);
689 status = GdipGetPathLastPoint(NULL, NULL);
690 expect(InvalidParameter, status);
692 status = GdipGetPathLastPoint(path, &ptf);
693 expect(Ok, status);
694 expect(TRUE, (ptf.X == 5.0) && (ptf.Y == 55.0));
696 GdipDeletePath(path);
699 static path_test_t addcurve_path[] = {
700 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
701 {3.3, 3.3, PathPointTypeBezier, 0, 0}, /*1*/
702 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*2*/
703 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
704 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
705 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
706 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
707 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
708 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*8*/
709 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*9*/
711 static path_test_t addcurve_path2[] = {
712 {100.0,120.0,PathPointTypeStart, 0, 0}, /*0*/
713 {123.0,10.0, PathPointTypeLine, 0, 0}, /*1*/
714 {0.0, 0.0, PathPointTypeLine, 0, 0}, /*2*/
715 {3.3, 3.3, PathPointTypeBezier, 0, 0}, /*3*/
716 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*4*/
717 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*5*/
718 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*6*/
719 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
720 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*8*/
721 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
722 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*10*/
723 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*11*/
725 static void test_addcurve(void)
727 GpStatus status;
728 GpPath *path;
729 GpPointF points[4];
731 points[0].X = 0.0;
732 points[0].Y = 0.0;
733 points[1].X = 10.0;
734 points[1].Y = 10.0;
735 points[2].X = 10.0;
736 points[2].Y = 20.0;
737 points[3].X = 30.0;
738 points[3].Y = 10.0;
740 GdipCreatePath(FillModeAlternate, &path);
742 /* NULL args */
743 status = GdipAddPathCurve2(NULL, NULL, 0, 0.0);
744 expect(InvalidParameter, status);
745 status = GdipAddPathCurve2(path, NULL, 0, 0.0);
746 expect(InvalidParameter, status);
747 status = GdipAddPathCurve2(path, points, -1, 0.0);
748 expect(InvalidParameter, status);
749 status = GdipAddPathCurve2(path, points, 1, 1.0);
750 expect(InvalidParameter, status);
752 /* add to empty path */
753 status = GdipAddPathCurve2(path, points, 4, 1.0);
754 expect(Ok, status);
755 ok_path(path, addcurve_path, sizeof(addcurve_path)/sizeof(path_test_t), FALSE);
756 GdipDeletePath(path);
758 /* add to notempty path and opened figure */
759 GdipCreatePath(FillModeAlternate, &path);
760 GdipAddPathLine(path, 100.0, 120.0, 123.0, 10.0);
761 status = GdipAddPathCurve2(path, points, 4, 1.0);
762 expect(Ok, status);
763 ok_path(path, addcurve_path2, sizeof(addcurve_path2)/sizeof(path_test_t), FALSE);
764 GdipDeletePath(path);
767 static path_test_t addclosedcurve_path[] = {
768 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
769 {-6.7, 0.0, PathPointTypeBezier, 0, 0}, /*1*/
770 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*2*/
771 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
772 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
773 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
774 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
775 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
776 {33.3, 16.7, PathPointTypeBezier, 0, 0}, /*8*/
777 {30.0, 10.0, PathPointTypeBezier, 0, 0}, /*9*/
778 {26.7, 3.3, PathPointTypeBezier, 0, 0}, /*10*/
779 {6.7, 0.0, PathPointTypeBezier, 0, 0}, /*11*/
780 {0.0, 0.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*12*/
782 static void test_addclosedcurve(void)
784 GpStatus status;
785 GpPath *path;
786 GpPointF points[4];
788 points[0].X = 0.0;
789 points[0].Y = 0.0;
790 points[1].X = 10.0;
791 points[1].Y = 10.0;
792 points[2].X = 10.0;
793 points[2].Y = 20.0;
794 points[3].X = 30.0;
795 points[3].Y = 10.0;
797 GdipCreatePath(FillModeAlternate, &path);
799 /* NULL args */
800 status = GdipAddPathClosedCurve2(NULL, NULL, 0, 0.0);
801 expect(InvalidParameter, status);
802 status = GdipAddPathClosedCurve2(path, NULL, 0, 0.0);
803 expect(InvalidParameter, status);
804 status = GdipAddPathClosedCurve2(path, points, -1, 0.0);
805 expect(InvalidParameter, status);
806 status = GdipAddPathClosedCurve2(path, points, 1, 1.0);
807 expect(InvalidParameter, status);
809 /* add to empty path */
810 status = GdipAddPathClosedCurve2(path, points, 4, 1.0);
811 expect(Ok, status);
812 ok_path(path, addclosedcurve_path, sizeof(addclosedcurve_path)/sizeof(path_test_t), FALSE);
813 GdipDeletePath(path);
816 static path_test_t reverse_path[] = {
817 {0.0, 20.0, PathPointTypeStart, 0, 0}, /*0*/
818 {25.0, 25.0, PathPointTypeLine, 0, 0}, /*1*/
819 {0.0, 30.0, PathPointTypeLine, 0, 0}, /*2*/
820 {15.0, 35.0, PathPointTypeStart, 0, 0}, /*3*/
821 {0.0, 40.0, PathPointTypeLine, 0, 0}, /*4*/
822 {5.0, 45.0, PathPointTypeLine, 0, 0}, /*5*/
823 {0.0, 50.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*6*/
826 static void test_reverse(void)
828 GpStatus status;
829 GpPath *path;
830 GpPointF pts[7];
831 INT i;
833 for(i = 0; i < 7; i++){
834 pts[i].X = i * 5.0 * (REAL)(i % 2);
835 pts[i].Y = 50.0 - i * 5.0;
838 GdipCreatePath(FillModeAlternate, &path);
840 /* NULL argument */
841 status = GdipReversePath(NULL);
842 expect(InvalidParameter, status);
844 /* empty path */
845 status = GdipReversePath(path);
846 expect(Ok, status);
848 GdipAddPathLine2(path, pts, 4);
849 GdipClosePathFigure(path);
850 GdipAddPathLine2(path, &(pts[4]), 3);
852 status = GdipReversePath(path);
853 expect(Ok, status);
854 ok_path(path, reverse_path, sizeof(reverse_path)/sizeof(path_test_t), FALSE);
856 GdipDeletePath(path);
859 static path_test_t addpie_path[] = {
860 {50.0, 25.0, PathPointTypeStart, 0, 0}, /*0*/
861 {97.2, 33.3, PathPointTypeLine, 0, 0}, /*1*/
862 {91.8, 40.9, PathPointTypeBezier,0, 0}, /*2*/
863 {79.4, 46.8, PathPointTypeBezier,0, 0}, /*3*/
864 {63.9, 49.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*4*/
867 static void test_addpie(void)
869 GpStatus status;
870 GpPath *path;
872 GdipCreatePath(FillModeAlternate, &path);
874 /* NULL argument */
875 status = GdipAddPathPie(NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
876 expect(InvalidParameter, status);
878 status = GdipAddPathPie(path, 0.0, 0.0, 100.0, 50.0, 10.0, 50.0);
879 expect(Ok, status);
880 ok_path(path, addpie_path, sizeof(addpie_path)/sizeof(path_test_t), FALSE);
882 GdipDeletePath(path);
885 START_TEST(graphicspath)
887 struct GdiplusStartupInput gdiplusStartupInput;
888 ULONG_PTR gdiplusToken;
890 gdiplusStartupInput.GdiplusVersion = 1;
891 gdiplusStartupInput.DebugEventCallback = NULL;
892 gdiplusStartupInput.SuppressBackgroundThread = 0;
893 gdiplusStartupInput.SuppressExternalCodecs = 0;
895 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
897 test_constructor_destructor();
898 test_getpathdata();
899 test_line2();
900 test_arc();
901 test_worldbounds();
902 test_pathpath();
903 test_ellipse();
904 test_linei();
905 test_rect();
906 test_polygon();
907 test_lastpoint();
908 test_addcurve();
909 test_addclosedcurve();
910 test_reverse();
911 test_addpie();
913 GdiplusShutdown(gdiplusToken);