[GDIPLUS_WINETEST]
[reactos.git] / rostests / winetests / gdiplus / graphicspath.c
1 /*
2 * Unit test suite for paths
3 *
4 * Copyright (C) 2007 Google (Evan Stade)
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 //#include "windows.h"
26 #include <wine/test.h>
27 #include <wingdi.h>
28 #include <objbase.h>
29 #include <gdiplus.h>
30 #include <math.h>
31
32 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
33 #define expectf(expected, got) ok(fabs(expected - got) < 2.0, "Expected %.2f, got %.2f\n", expected, got)
34 #define POINT_TYPE_MAX_LEN (75)
35
36 static void stringify_point_type(PathPointType type, char * name)
37 {
38 *name = '\0';
39
40 switch(type & PathPointTypePathTypeMask){
41 case PathPointTypeStart:
42 strcat(name, "PathPointTypeStart");
43 break;
44 case PathPointTypeLine:
45 strcat(name, "PathPointTypeLine");
46 break;
47 case PathPointTypeBezier:
48 strcat(name, "PathPointTypeBezier");
49 break;
50 default:
51 strcat(name, "Unknown type");
52 return;
53 }
54
55 type &= ~PathPointTypePathTypeMask;
56 if(type & ~((PathPointTypePathMarker | PathPointTypeCloseSubpath))){
57 *name = '\0';
58 strcat(name, "Unknown type");
59 return;
60 }
61
62 if(type & PathPointTypePathMarker)
63 strcat(name, " | PathPointTypePathMarker");
64 if(type & PathPointTypeCloseSubpath)
65 strcat(name, " | PathPointTypeCloseSubpath");
66 }
67
68 /* this helper structure and function modeled after gdi path.c test */
69 typedef struct
70 {
71 REAL X, Y;
72 BYTE type;
73
74 /* How many extra entries before this one only on wine
75 * but not on native? */
76 int wine_only_entries_preceding;
77
78 /* 0 - This entry matches on wine.
79 * 1 - This entry corresponds to a single entry on wine that does not match the native entry.
80 * 2 - This entry is currently skipped on wine but present on native. */
81 int todo;
82 } path_test_t;
83
84 static void ok_path(GpPath* path, const path_test_t *expected, INT expected_size, BOOL todo_size)
85 {
86 BYTE * types;
87 INT size, idx = 0, eidx = 0, numskip;
88 GpPointF * points;
89 char ename[POINT_TYPE_MAX_LEN], name[POINT_TYPE_MAX_LEN];
90
91 if(GdipGetPointCount(path, &size) != Ok){
92 skip("Cannot perform path comparisons due to failure to retrieve path.\n");
93 return;
94 }
95
96 if(todo_size) todo_wine
97 ok(size == expected_size, "Path size %d does not match expected size %d\n",
98 size, expected_size);
99 else
100 ok(size == expected_size, "Path size %d does not match expected size %d\n",
101 size, expected_size);
102
103 points = HeapAlloc(GetProcessHeap(), 0, size * sizeof(GpPointF));
104 types = HeapAlloc(GetProcessHeap(), 0, size);
105
106 if(GdipGetPathPoints(path, points, size) != Ok || GdipGetPathTypes(path, types, size) != Ok){
107 skip("Cannot perform path comparisons due to failure to retrieve path.\n");
108 goto end;
109 }
110
111 numskip = expected_size ? expected[eidx].wine_only_entries_preceding : 0;
112 while (idx < size && eidx < expected_size){
113 /* We allow a few pixels fudge in matching X and Y coordinates to account for imprecision in
114 * floating point to integer conversion */
115 BOOL match = (types[idx] == expected[eidx].type) &&
116 fabs(points[idx].X - expected[eidx].X) <= 2.0 &&
117 fabs(points[idx].Y - expected[eidx].Y) <= 2.0;
118
119 stringify_point_type(expected[eidx].type, ename);
120 stringify_point_type(types[idx], name);
121
122 if (expected[eidx].todo || numskip) todo_wine
123 ok(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx,
124 ename, expected[eidx].X, expected[eidx].Y,
125 name, points[idx].X, points[idx].Y);
126 else
127 ok(match, "Expected #%d: %s (%.1f,%.1f) but got %s (%.1f,%.1f)\n", eidx,
128 ename, expected[eidx].X, expected[eidx].Y,
129 name, points[idx].X, points[idx].Y);
130
131 if (match || expected[eidx].todo != 2)
132 idx++;
133 if (match || !numskip--)
134 numskip = expected[++eidx].wine_only_entries_preceding;
135 }
136
137 end:
138 HeapFree(GetProcessHeap(), 0, types);
139 HeapFree(GetProcessHeap(), 0, points);
140 }
141
142 static void test_constructor_destructor(void)
143 {
144 GpStatus status;
145 GpPath* path = NULL;
146
147 status = GdipCreatePath(FillModeAlternate, &path);
148 expect(Ok, status);
149 ok(path != NULL, "Expected path to be initialized\n");
150
151 status = GdipDeletePath(NULL);
152 expect(InvalidParameter, status);
153
154 status = GdipDeletePath(path);
155 expect(Ok, status);
156 }
157
158 static void test_getpathdata(void)
159 {
160 GpPath *path;
161 GpPathData data;
162 GpStatus status;
163 INT count;
164
165 status = GdipCreatePath(FillModeAlternate, &path);
166 expect(Ok, status);
167 status = GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
168 expect(Ok, status);
169
170 status = GdipGetPointCount(path, &count);
171 expect(Ok, status);
172 expect(2, count);
173
174 data.Count = count;
175 data.Types = GdipAlloc(sizeof(BYTE) * count);
176 data.Points = GdipAlloc(sizeof(PointF) * count);
177
178 status = GdipGetPathData(path, &data);
179 expect(Ok, status);
180 expect((data.Points[0].X == 5.0) && (data.Points[0].Y == 5.0) &&
181 (data.Points[1].X == 100.0) && (data.Points[1].Y == 50.0), TRUE);
182 expect((data.Types[0] == PathPointTypeStart) && (data.Types[1] == PathPointTypeLine), TRUE);
183
184 GdipFree(data.Points);
185 GdipFree(data.Types);
186 GdipDeletePath(path);
187 }
188
189 static path_test_t line2_path[] = {
190 {0.0, 50.0, PathPointTypeStart, 0, 0}, /*0*/
191 {5.0, 45.0, PathPointTypeLine, 0, 0}, /*1*/
192 {0.0, 40.0, PathPointTypeLine, 0, 0}, /*2*/
193 {15.0, 35.0, PathPointTypeLine, 0, 0}, /*3*/
194 {0.0, 30.0, PathPointTypeLine, 0, 0}, /*4*/
195 {25.0, 25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*5*/
196 {0.0, 20.0, PathPointTypeStart, 0, 0}, /*6*/
197 {35.0, 15.0, PathPointTypeLine, 0, 0}, /*7*/
198 {0.0, 10.0, PathPointTypeLine, 0, 0} /*8*/
199 };
200
201 static void test_line2(void)
202 {
203 GpStatus status;
204 GpPath* path;
205 int i;
206 GpPointF line2_points[9];
207
208 for(i = 0; i < 9; i ++){
209 line2_points[i].X = i * 5.0 * (REAL)(i % 2);
210 line2_points[i].Y = 50.0 - i * 5.0;
211 }
212
213 GdipCreatePath(FillModeAlternate, &path);
214 status = GdipAddPathLine2(path, line2_points, 3);
215 expect(Ok, status);
216 status = GdipAddPathLine2(path, &(line2_points[3]), 3);
217 expect(Ok, status);
218 status = GdipClosePathFigure(path);
219 expect(Ok, status);
220 status = GdipAddPathLine2(path, &(line2_points[6]), 3);
221 expect(Ok, status);
222
223 ok_path(path, line2_path, sizeof(line2_path)/sizeof(path_test_t), FALSE);
224
225 GdipDeletePath(path);
226 }
227
228 static path_test_t arc_path[] = {
229 {600.0, 450.0, PathPointTypeStart, 0, 0}, /*0*/
230 {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*1*/
231 {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*2*/
232 {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*3*/
233 {600.0, 450.0, PathPointTypeLine, 0, 0}, /*4*/
234 {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*5*/
235 {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*6*/
236 {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*7*/
237 {329.8, 800.0, PathPointTypeBezier, 0, 0}, /*8*/
238 {309.7, 796.6, PathPointTypeBezier, 0, 0}, /*9*/
239 {290.1, 789.8, PathPointTypeBezier, 0, 0}, /*10*/
240 {409.9, 110.2, PathPointTypeLine, 0, 0}, /*11*/
241 {544.0, 156.5, PathPointTypeBezier, 0, 0}, /*12*/
242 {625.8, 346.2, PathPointTypeBezier, 0, 0}, /*13*/
243 {592.7, 533.9, PathPointTypeBezier, 0, 0}, /*14*/
244 {592.5, 535.3, PathPointTypeBezier, 0, 0}, /*15*/
245 {592.2, 536.7, PathPointTypeBezier, 0, 0}, /*16*/
246 {592.0, 538.1, PathPointTypeBezier, 0, 0}, /*17*/
247 {409.9, 789.8, PathPointTypeLine, 0, 0}, /*18*/
248 {544.0, 743.5, PathPointTypeBezier, 0, 0}, /*19*/
249 {625.8, 553.8, PathPointTypeBezier, 0, 0}, /*20*/
250 {592.7, 366.1, PathPointTypeBezier, 0, 0}, /*21*/
251 {592.5, 364.7, PathPointTypeBezier, 0, 0}, /*22*/
252 {592.2, 363.3, PathPointTypeBezier, 0, 0}, /*23*/
253 {592.0, 361.9, PathPointTypeBezier, 0, 0}, /*24*/
254 {540.4, 676.9, PathPointTypeLine, 0, 0}, /*25*/
255 {629.9, 529.7, PathPointTypeBezier, 0, 0}, /*26*/
256 {617.2, 308.8, PathPointTypeBezier, 0, 0}, /*27*/
257 {512.1, 183.5, PathPointTypeBezier, 0, 0}, /*28*/
258 {406.9, 58.2, PathPointTypeBezier, 0, 0}, /*29*/
259 {249.1, 75.9, PathPointTypeBezier, 0, 0}, /*30*/
260 {159.6, 223.1, PathPointTypeBezier, 0, 0}, /*31*/
261 {70.1, 370.3, PathPointTypeBezier, 0, 0}, /*32*/
262 {82.8, 591.2, PathPointTypeBezier, 0, 0}, /*33*/
263 {187.9, 716.5, PathPointTypeBezier, 0, 0}, /*34*/
264 {293.1, 841.8, PathPointTypeBezier, 0, 0}, /*35*/
265 {450.9, 824.1, PathPointTypeBezier, 0, 0}, /*36*/
266 {540.4, 676.9, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 1} /*37*/
267 };
268
269 static void test_arc(void)
270 {
271 GpStatus status;
272 GpPath* path;
273
274 GdipCreatePath(FillModeAlternate, &path);
275 /* Exactly 90 degrees */
276 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
277 expect(Ok, status);
278 /* Over 90 degrees */
279 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
280 expect(Ok, status);
281 /* Negative start angle */
282 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
283 expect(Ok, status);
284 /* Negative sweep angle */
285 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 80.0, -100.0);
286 expect(Ok, status);
287 /* More than a full revolution */
288 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, -400.0);
289 expect(Ok, status);
290 /* 0 sweep angle */
291 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, 0.0);
292 expect(Ok, status);
293
294 ok_path(path, arc_path, sizeof(arc_path)/sizeof(path_test_t), FALSE);
295
296 GdipDeletePath(path);
297 }
298
299 static void test_worldbounds(void)
300 {
301 GpStatus status;
302 GpPath *path;
303 GpPen *pen;
304 GpMatrix *matrix;
305 GpRectF bounds;
306 GpPointF line2_points[10];
307 int i;
308
309 for(i = 0; i < 10; i ++){
310 line2_points[i].X = 200.0 + i * 50.0 * (i % 2);
311 line2_points[i].Y = 200.0 + i * 50.0 * !(i % 2);
312 }
313 GdipCreatePen1((ARGB)0xdeadbeef, 20.0, UnitWorld, &pen);
314 GdipSetPenEndCap(pen, LineCapSquareAnchor);
315 GdipCreateMatrix2(1.5, 0.0, 1.0, 1.2, 10.4, 10.2, &matrix);
316
317 GdipCreatePath(FillModeAlternate, &path);
318 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
319 GdipAddPathLine2(path, &(line2_points[0]), 10);
320 status = GdipGetPathWorldBounds(path, &bounds, NULL, NULL);
321 expect(Ok, status);
322 GdipDeletePath(path);
323
324 expectf(200.0, bounds.X);
325 expectf(200.0, bounds.Y);
326 expectf(450.0, bounds.Width);
327 expectf(600.0, bounds.Height);
328
329 GdipCreatePath(FillModeAlternate, &path);
330 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
331 GdipAddPathLine2(path, &(line2_points[0]), 10);
332 status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
333 expect(Ok, status);
334 GdipDeletePath(path);
335
336 expectf(510.4, bounds.X);
337 expectf(250.2, bounds.Y);
338 expectf(1275.0, bounds.Width);
339 expectf(720.0, bounds.Height);
340
341 GdipCreatePath(FillModeAlternate, &path);
342 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
343 GdipAddPathLine2(path, &(line2_points[0]), 10);
344 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
345 expect(Ok, status);
346 GdipDeletePath(path);
347
348 expectf(100.0, bounds.X);
349 expectf(100.0, bounds.Y);
350 expectf(650.0, bounds.Width);
351 expectf(800.0, bounds.Height);
352
353 GdipCreatePath(FillModeAlternate, &path);
354 GdipAddPathLine2(path, &(line2_points[0]), 2);
355 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
356 expect(Ok, status);
357 GdipDeletePath(path);
358
359 expectf(156.0, bounds.X);
360 expectf(156.0, bounds.Y);
361 expectf(138.0, bounds.Width);
362 expectf(88.0, bounds.Height);
363
364 line2_points[2].X = 2 * line2_points[1].X - line2_points[0].X;
365 line2_points[2].Y = 2 * line2_points[1].Y - line2_points[0].Y;
366
367 GdipCreatePath(FillModeAlternate, &path);
368 GdipAddPathLine2(path, &(line2_points[0]), 3);
369 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
370 expect(Ok, status);
371 GdipDeletePath(path);
372
373 expectf(100.0, bounds.X);
374 expectf(100.0, bounds.Y);
375 expectf(300.0, bounds.Width);
376 expectf(200.0, bounds.Height);
377
378 GdipCreatePath(FillModeAlternate, &path);
379 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 45.0, 20.0);
380 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
381 expect(Ok, status);
382 GdipDeletePath(path);
383
384 expectf(386.7, bounds.X);
385 expectf(553.4, bounds.Y);
386 expectf(266.8, bounds.Width);
387 expectf(289.6, bounds.Height);
388
389 GdipCreatePath(FillModeAlternate, &path);
390 status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
391 expect(Ok, status);
392 GdipDeletePath(path);
393
394 expectf(0.0, bounds.X);
395 expectf(0.0, bounds.Y);
396 expectf(0.0, bounds.Width);
397 expectf(0.0, bounds.Height);
398
399 GdipCreatePath(FillModeAlternate, &path);
400 GdipAddPathLine2(path, &(line2_points[0]), 2);
401 status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
402 expect(Ok, status);
403 GdipDeletePath(path);
404
405 todo_wine{
406 expectf(427.9, bounds.X);
407 expectf(167.7, bounds.Y);
408 expectf(239.9, bounds.Width);
409 expectf(164.9, bounds.Height);
410 }
411
412 GdipDeleteMatrix(matrix);
413 GdipCreateMatrix2(0.9, -0.5, -0.5, -1.2, 10.4, 10.2, &matrix);
414 GdipCreatePath(FillModeAlternate, &path);
415 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
416 GdipAddPathLine2(path, &(line2_points[0]), 10);
417 status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
418 expect(Ok, status);
419 GdipDeletePath(path);
420 GdipDeleteMatrix(matrix);
421
422 expectf(-209.6, bounds.X);
423 expectf(-1274.8, bounds.Y);
424 expectf(705.0, bounds.Width);
425 expectf(945.0, bounds.Height);
426
427 GdipDeletePen(pen);
428 }
429
430 static path_test_t pathpath_path[] = {
431 {600.00, 450.00, PathPointTypeStart, 0, 0}, /*0*/
432 {600.00, 643.30, PathPointTypeBezier, 0, 0}, /*1*/
433 {488.07, 800.00, PathPointTypeBezier, 0, 0}, /*2*/
434 {350.00, 800.00, PathPointTypeBezier, 0, 0}, /*3*/
435 {319.61, 797.40, PathPointTypeStart, 0, 0}, /*4*/
436 {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*5*/
437 {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*6*/
438 {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*7*/
439 {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*8*/
440 {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*9*/
441 {104.46, 384.21, PathPointTypeBezier, 0, 0}, /*10*/
442 {409.92, 110.20, PathPointTypeLine, 0, 0}, /*11*/
443 {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*12*/
444 {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*13*/
445 {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*14*/
446 {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*15*/
447 {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*16*/
448 {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*17*/
449 {319.61, 797.40, PathPointTypeLine, 0, 0}, /*18*/
450 {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*19*/
451 {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*20*/
452 {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*21*/
453 {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*22*/
454 {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*23*/
455 {104.46, 384.21, PathPointTypeBezier, 0, 0} /*24*/
456 };
457
458 static void test_pathpath(void)
459 {
460 GpStatus status;
461 GpPath* path1, *path2;
462
463 GdipCreatePath(FillModeAlternate, &path2);
464 GdipAddPathArc(path2, 100.0, 100.0, 500.0, 700.0, 95.0, 100.0);
465
466 GdipCreatePath(FillModeAlternate, &path1);
467 GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
468 status = GdipAddPathPath(path1, path2, FALSE);
469 expect(Ok, status);
470 GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
471 status = GdipAddPathPath(path1, path2, TRUE);
472 expect(Ok, status);
473
474 ok_path(path1, pathpath_path, sizeof(pathpath_path)/sizeof(path_test_t), FALSE);
475
476 GdipDeletePath(path1);
477 GdipDeletePath(path2);
478 }
479
480 static path_test_t ellipse_path[] = {
481 {30.00, 125.25, PathPointTypeStart, 0, 0}, /*0*/
482 {30.00, 139.20, PathPointTypeBezier, 0, 0}, /*1*/
483 {25.52, 150.50, PathPointTypeBezier, 0, 0}, /*2*/
484 {20.00, 150.50, PathPointTypeBezier, 0, 0}, /*3*/
485 {14.48, 150.50, PathPointTypeBezier, 0, 0}, /*4*/
486 {10.00, 139.20, PathPointTypeBezier, 0, 0}, /*5*/
487 {10.00, 125.25, PathPointTypeBezier, 0, 0}, /*6*/
488 {10.00, 111.30, PathPointTypeBezier, 0, 0}, /*7*/
489 {14.48, 100.00, PathPointTypeBezier, 0, 0}, /*8*/
490 {20.00, 100.00, PathPointTypeBezier, 0, 0}, /*9*/
491 {25.52, 100.00, PathPointTypeBezier, 0, 0}, /*10*/
492 {30.00, 111.30, PathPointTypeBezier, 0, 0}, /*11*/
493 {30.00, 125.25, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*12*/
494 {7.00, 11.00, PathPointTypeStart, 0, 0}, /*13*/
495 {13.00, 17.00, PathPointTypeLine, 0, 0}, /*14*/
496 {5.00, 195.00, PathPointTypeStart, 0, 0}, /*15*/
497 {5.00, 192.24, PathPointTypeBezier, 0, 0}, /*16*/
498 {6.12, 190.00, PathPointTypeBezier, 0, 0}, /*17*/
499 {7.50, 190.00, PathPointTypeBezier, 0, 0}, /*18*/
500 {8.88, 190.00, PathPointTypeBezier, 0, 0}, /*19*/
501 {10.00, 192.24, PathPointTypeBezier, 0, 0}, /*20*/
502 {10.00, 195.00, PathPointTypeBezier, 0, 0}, /*21*/
503 {10.00, 197.76, PathPointTypeBezier, 0, 0}, /*22*/
504 {8.88, 200.00, PathPointTypeBezier, 0, 0}, /*23*/
505 {7.50, 200.00, PathPointTypeBezier, 0, 0}, /*24*/
506 {6.12, 200.00, PathPointTypeBezier, 0, 0}, /*25*/
507 {5.00, 197.76, PathPointTypeBezier, 0, 0}, /*26*/
508 {5.00, 195.00, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*27*/
509 {10.00, 300.50, PathPointTypeStart, 0, 0}, /*28*/
510 {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*29*/
511 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*30*/
512 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*31*/
513 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*32*/
514 {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*33*/
515 {10.00, 300.50, PathPointTypeBezier, 0, 0}, /*34*/
516 {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*35*/
517 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*36*/
518 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*37*/
519 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*38*/
520 {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*39*/
521 {10.00, 300.50, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*40*/
522 };
523
524 static void test_ellipse(void)
525 {
526 GpStatus status;
527 GpPath *path;
528 GpPointF points[2];
529
530 points[0].X = 7.0;
531 points[0].Y = 11.0;
532 points[1].X = 13.0;
533 points[1].Y = 17.0;
534
535 GdipCreatePath(FillModeAlternate, &path);
536 status = GdipAddPathEllipse(path, 10.0, 100.0, 20.0, 50.5);
537 expect(Ok, status);
538 GdipAddPathLine2(path, points, 2);
539 status = GdipAddPathEllipse(path, 10.0, 200.0, -5.0, -10.0);
540 expect(Ok, status);
541 GdipClosePathFigure(path);
542 status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0);
543 expect(Ok, status);
544
545 ok_path(path, ellipse_path, sizeof(ellipse_path)/sizeof(path_test_t), FALSE);
546
547 GdipDeletePath(path);
548 }
549
550 static path_test_t linei_path[] = {
551 {5.00, 5.00, PathPointTypeStart, 0, 0}, /*0*/
552 {6.00, 8.00, PathPointTypeLine, 0, 0}, /*1*/
553 {409.92, 110.20, PathPointTypeLine, 0, 0}, /*2*/
554 {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*3*/
555 {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*4*/
556 {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*5*/
557 {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*6*/
558 {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*7*/
559 {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*8*/
560 {15.00, 15.00, PathPointTypeLine, 0, 0}, /*9*/
561 {26.00, 28.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*10*/
562 {35.00, 35.00, PathPointTypeStart, 0, 0}, /*11*/
563 {36.00, 38.00, PathPointTypeLine, 0, 0} /*12*/
564 };
565
566 static void test_linei(void)
567 {
568 GpStatus status;
569 GpPath *path;
570
571 GdipCreatePath(FillModeAlternate, &path);
572 status = GdipAddPathLineI(path, 5.0, 5.0, 6.0, 8.0);
573 expect(Ok, status);
574 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
575 status = GdipAddPathLineI(path, 15.0, 15.0, 26.0, 28.0);
576 expect(Ok, status);
577 GdipClosePathFigure(path);
578 status = GdipAddPathLineI(path, 35.0, 35.0, 36.0, 38.0);
579 expect(Ok, status);
580
581 ok_path(path, linei_path, sizeof(linei_path)/sizeof(path_test_t), FALSE);
582
583 GdipDeletePath(path);
584 }
585
586 static path_test_t poly_path[] = {
587 {5.00, 5.00, PathPointTypeStart, 0, 0}, /*1*/
588 {6.00, 8.00, PathPointTypeLine, 0, 0}, /*2*/
589 {0.00, 0.00, PathPointTypeStart, 0, 0}, /*3*/
590 {10.00, 10.00, PathPointTypeLine, 0, 0}, /*4*/
591 {10.00, 20.00, PathPointTypeLine, 0, 0}, /*5*/
592 {30.00, 10.00, PathPointTypeLine, 0, 0}, /*6*/
593 {20.00, 0.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*7*/
594 };
595
596 static void test_polygon(void)
597 {
598 GpStatus status;
599 GpPath *path;
600 GpPointF points[5];
601
602 points[0].X = 0.0;
603 points[0].Y = 0.0;
604 points[1].X = 10.0;
605 points[1].Y = 10.0;
606 points[2].X = 10.0;
607 points[2].Y = 20.0;
608 points[3].X = 30.0;
609 points[3].Y = 10.0;
610 points[4].X = 20.0;
611 points[4].Y = 0.0;
612
613 GdipCreatePath(FillModeAlternate, &path);
614
615 /* NULL args */
616 status = GdipAddPathPolygon(NULL, points, 5);
617 expect(InvalidParameter, status);
618 status = GdipAddPathPolygon(path, NULL, 5);
619 expect(InvalidParameter, status);
620 /* Polygon should have 3 points at least */
621 status = GdipAddPathPolygon(path, points, 2);
622 expect(InvalidParameter, status);
623
624 /* to test how it prolongs not empty path */
625 status = GdipAddPathLine(path, 5.0, 5.0, 6.0, 8.0);
626 expect(Ok, status);
627 status = GdipAddPathPolygon(path, points, 5);
628 expect(Ok, status);
629 /* check resulting path */
630 ok_path(path, poly_path, sizeof(poly_path)/sizeof(path_test_t), FALSE);
631
632 GdipDeletePath(path);
633 }
634
635 static path_test_t rect_path[] = {
636 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
637 {105.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
638 {105.0, 55.0, PathPointTypeLine, 0, 0}, /*2*/
639 {5.0, 55.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*3*/
640
641 {100.0, 50.0, PathPointTypeStart, 0, 0}, /*4*/
642 {220.0, 50.0, PathPointTypeLine, 0, 0}, /*5*/
643 {220.0, 80.0, PathPointTypeLine, 0, 0}, /*6*/
644 {100.0, 80.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*7*/
645 };
646
647 static void test_rect(void)
648 {
649 GpStatus status;
650 GpPath *path;
651 GpRectF rects[2];
652
653 GdipCreatePath(FillModeAlternate, &path);
654 status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
655 expect(Ok, status);
656 status = GdipAddPathRectangle(path, 100.0, 50.0, 120.0, 30.0);
657 expect(Ok, status);
658
659 ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE);
660
661 GdipDeletePath(path);
662
663 GdipCreatePath(FillModeAlternate, &path);
664
665 rects[0].X = 5.0;
666 rects[0].Y = 5.0;
667 rects[0].Width = 100.0;
668 rects[0].Height = 50.0;
669 rects[1].X = 100.0;
670 rects[1].Y = 50.0;
671 rects[1].Width = 120.0;
672 rects[1].Height = 30.0;
673
674 status = GdipAddPathRectangles(path, (GDIPCONST GpRectF*)&rects, 2);
675 expect(Ok, status);
676
677 ok_path(path, rect_path, sizeof(rect_path)/sizeof(path_test_t), FALSE);
678
679 GdipDeletePath(path);
680 }
681
682 static void test_lastpoint(void)
683 {
684 GpStatus status;
685 GpPath *path;
686 GpPointF ptf;
687
688 GdipCreatePath(FillModeAlternate, &path);
689 status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
690 expect(Ok, status);
691
692 /* invalid args */
693 status = GdipGetPathLastPoint(NULL, &ptf);
694 expect(InvalidParameter, status);
695 status = GdipGetPathLastPoint(path, NULL);
696 expect(InvalidParameter, status);
697 status = GdipGetPathLastPoint(NULL, NULL);
698 expect(InvalidParameter, status);
699
700 status = GdipGetPathLastPoint(path, &ptf);
701 expect(Ok, status);
702 expect(TRUE, (ptf.X == 5.0) && (ptf.Y == 55.0));
703
704 GdipDeletePath(path);
705 }
706
707 static path_test_t addcurve_path[] = {
708 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
709 {3.3, 3.3, PathPointTypeBezier, 0, 0}, /*1*/
710 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*2*/
711 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
712 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
713 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
714 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
715 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
716 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*8*/
717 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*9*/
718 };
719 static path_test_t addcurve_path2[] = {
720 {100.0,120.0,PathPointTypeStart, 0, 0}, /*0*/
721 {123.0,10.0, PathPointTypeLine, 0, 0}, /*1*/
722 {0.0, 0.0, PathPointTypeLine, 0, 0}, /*2*/
723 {3.3, 3.3, PathPointTypeBezier, 0, 0}, /*3*/
724 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*4*/
725 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*5*/
726 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*6*/
727 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
728 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*8*/
729 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
730 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*10*/
731 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*11*/
732 };
733 static path_test_t addcurve_path3[] = {
734 {10.0, 10.0, PathPointTypeStart, 0, 0}, /*0*/
735 {13.3, 16.7, PathPointTypeBezier, 0, 1}, /*1*/
736 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*2*/
737 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*3*/
738 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*4*/
739 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*5*/
740 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*6*/
741 };
742 static void test_addcurve(void)
743 {
744 GpStatus status;
745 GpPath *path;
746 GpPointF points[4];
747
748 points[0].X = 0.0;
749 points[0].Y = 0.0;
750 points[1].X = 10.0;
751 points[1].Y = 10.0;
752 points[2].X = 10.0;
753 points[2].Y = 20.0;
754 points[3].X = 30.0;
755 points[3].Y = 10.0;
756
757 GdipCreatePath(FillModeAlternate, &path);
758
759 /* NULL args */
760 status = GdipAddPathCurve2(NULL, NULL, 0, 0.0);
761 expect(InvalidParameter, status);
762 status = GdipAddPathCurve2(path, NULL, 0, 0.0);
763 expect(InvalidParameter, status);
764 status = GdipAddPathCurve2(path, points, -1, 0.0);
765 expect(InvalidParameter, status);
766 status = GdipAddPathCurve2(path, points, 1, 1.0);
767 expect(InvalidParameter, status);
768
769 /* add to empty path */
770 status = GdipAddPathCurve2(path, points, 4, 1.0);
771 expect(Ok, status);
772 ok_path(path, addcurve_path, sizeof(addcurve_path)/sizeof(path_test_t), FALSE);
773 GdipDeletePath(path);
774
775 /* add to notempty path and opened figure */
776 GdipCreatePath(FillModeAlternate, &path);
777 GdipAddPathLine(path, 100.0, 120.0, 123.0, 10.0);
778 status = GdipAddPathCurve2(path, points, 4, 1.0);
779 expect(Ok, status);
780 ok_path(path, addcurve_path2, sizeof(addcurve_path2)/sizeof(path_test_t), FALSE);
781
782 /* NULL args */
783 GdipResetPath(path);
784 status = GdipAddPathCurve3(NULL, NULL, 0, 0, 0, 0.0);
785 expect(InvalidParameter, status);
786 status = GdipAddPathCurve3(path, NULL, 0, 0, 0, 0.0);
787 expect(InvalidParameter, status);
788 /* wrong count, offset.. */
789 status = GdipAddPathCurve3(path, points, 0, 0, 0, 0.0);
790 expect(InvalidParameter, status);
791 status = GdipAddPathCurve3(path, points, 4, 0, 0, 0.0);
792 expect(InvalidParameter, status);
793 status = GdipAddPathCurve3(path, points, 4, 0, 4, 0.0);
794 expect(InvalidParameter, status);
795 status = GdipAddPathCurve3(path, points, 4, 1, 3, 0.0);
796 expect(InvalidParameter, status);
797 status = GdipAddPathCurve3(path, points, 4, 1, 0, 0.0);
798 expect(InvalidParameter, status);
799 status = GdipAddPathCurve3(path, points, 4, 3, 1, 0.0);
800 expect(InvalidParameter, status);
801
802 /* use all points */
803 status = GdipAddPathCurve3(path, points, 4, 0, 3, 1.0);
804 expect(Ok, status);
805 ok_path(path, addcurve_path, sizeof(addcurve_path)/sizeof(path_test_t), FALSE);
806 GdipResetPath(path);
807
808 status = GdipAddPathCurve3(path, points, 4, 1, 2, 1.0);
809 expect(Ok, status);
810 ok_path(path, addcurve_path3, sizeof(addcurve_path3)/sizeof(path_test_t), FALSE);
811
812 GdipDeletePath(path);
813 }
814
815 static path_test_t addclosedcurve_path[] = {
816 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
817 {-6.7, 0.0, PathPointTypeBezier, 0, 0}, /*1*/
818 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*2*/
819 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
820 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
821 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
822 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
823 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
824 {33.3, 16.7, PathPointTypeBezier, 0, 0}, /*8*/
825 {30.0, 10.0, PathPointTypeBezier, 0, 0}, /*9*/
826 {26.7, 3.3, PathPointTypeBezier, 0, 0}, /*10*/
827 {6.7, 0.0, PathPointTypeBezier, 0, 0}, /*11*/
828 {0.0, 0.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*12*/
829 };
830 static void test_addclosedcurve(void)
831 {
832 GpStatus status;
833 GpPath *path;
834 GpPointF points[4];
835
836 points[0].X = 0.0;
837 points[0].Y = 0.0;
838 points[1].X = 10.0;
839 points[1].Y = 10.0;
840 points[2].X = 10.0;
841 points[2].Y = 20.0;
842 points[3].X = 30.0;
843 points[3].Y = 10.0;
844
845 GdipCreatePath(FillModeAlternate, &path);
846
847 /* NULL args */
848 status = GdipAddPathClosedCurve2(NULL, NULL, 0, 0.0);
849 expect(InvalidParameter, status);
850 status = GdipAddPathClosedCurve2(path, NULL, 0, 0.0);
851 expect(InvalidParameter, status);
852 status = GdipAddPathClosedCurve2(path, points, -1, 0.0);
853 expect(InvalidParameter, status);
854 status = GdipAddPathClosedCurve2(path, points, 1, 1.0);
855 expect(InvalidParameter, status);
856
857 /* add to empty path */
858 status = GdipAddPathClosedCurve2(path, points, 4, 1.0);
859 expect(Ok, status);
860 ok_path(path, addclosedcurve_path, sizeof(addclosedcurve_path)/sizeof(path_test_t), FALSE);
861 GdipDeletePath(path);
862 }
863
864 static path_test_t reverse_path[] = {
865 {0.0, 20.0, PathPointTypeStart, 0, 0}, /*0*/
866 {25.0, 25.0, PathPointTypeLine, 0, 0}, /*1*/
867 {0.0, 30.0, PathPointTypeLine, 0, 0}, /*2*/
868 {15.0, 35.0, PathPointTypeStart, 0, 0}, /*3*/
869 {0.0, 40.0, PathPointTypeLine, 0, 0}, /*4*/
870 {5.0, 45.0, PathPointTypeLine, 0, 0}, /*5*/
871 {0.0, 50.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*6*/
872 };
873
874 static void test_reverse(void)
875 {
876 GpStatus status;
877 GpPath *path;
878 GpPointF pts[7];
879 INT i;
880
881 for(i = 0; i < 7; i++){
882 pts[i].X = i * 5.0 * (REAL)(i % 2);
883 pts[i].Y = 50.0 - i * 5.0;
884 }
885
886 GdipCreatePath(FillModeAlternate, &path);
887
888 /* NULL argument */
889 status = GdipReversePath(NULL);
890 expect(InvalidParameter, status);
891
892 /* empty path */
893 status = GdipReversePath(path);
894 expect(Ok, status);
895
896 GdipAddPathLine2(path, pts, 4);
897 GdipClosePathFigure(path);
898 GdipAddPathLine2(path, &(pts[4]), 3);
899
900 status = GdipReversePath(path);
901 expect(Ok, status);
902 ok_path(path, reverse_path, sizeof(reverse_path)/sizeof(path_test_t), FALSE);
903
904 GdipDeletePath(path);
905 }
906
907 static path_test_t addpie_path[] = {
908 {50.0, 25.0, PathPointTypeStart, 0, 0}, /*0*/
909 {97.2, 33.3, PathPointTypeLine, 0, 0}, /*1*/
910 {91.8, 40.9, PathPointTypeBezier,0, 0}, /*2*/
911 {79.4, 46.8, PathPointTypeBezier,0, 0}, /*3*/
912 {63.9, 49.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*4*/
913 };
914 static path_test_t addpie_path2[] = {
915 {0.0, 30.0, PathPointTypeStart | PathPointTypeCloseSubpath, 0, 0} /*0*/
916 };
917 static path_test_t addpie_path3[] = {
918 {30.0, 0.0, PathPointTypeStart | PathPointTypeCloseSubpath, 0, 0} /*0*/
919 };
920 static void test_addpie(void)
921 {
922 GpStatus status;
923 GpPath *path;
924
925 GdipCreatePath(FillModeAlternate, &path);
926
927 /* NULL argument */
928 status = GdipAddPathPie(NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
929 expect(InvalidParameter, status);
930
931 status = GdipAddPathPie(path, 0.0, 0.0, 100.0, 50.0, 10.0, 50.0);
932 expect(Ok, status);
933 ok_path(path, addpie_path, sizeof(addpie_path)/sizeof(path_test_t), FALSE);
934 status = GdipResetPath(path);
935 expect(Ok, status);
936
937 /* zero width base ellipse */
938 status = GdipAddPathPie(path, 0.0, 0.0, 0.0, 60.0, -90.0, 24.0);
939 expect(InvalidParameter, status);
940 ok_path(path, addpie_path2, sizeof(addpie_path2)/sizeof(path_test_t), FALSE);
941 status = GdipResetPath(path);
942 expect(Ok, status);
943
944 /* zero height base ellipse */
945 status = GdipAddPathPie(path, 0.0, 0.0, 60.0, 0.0 , -90.0, 24.0);
946 expect(InvalidParameter, status);
947 ok_path(path, addpie_path3, sizeof(addpie_path3)/sizeof(path_test_t), FALSE);
948
949 GdipDeletePath(path);
950 }
951
952 static path_test_t flattenellipse_path[] = {
953 {100.0, 25.0,PathPointTypeStart, 0, 0}, /*0*/
954 {99.0, 30.0, PathPointTypeLine, 0, 0}, /*1*/
955 {96.0, 34.8, PathPointTypeLine, 0, 0}, /*2*/
956 {91.5, 39.0, PathPointTypeLine, 0, 0}, /*3*/
957 {85.5, 42.8, PathPointTypeLine, 0, 0}, /*4*/
958 {69.5, 48.0, PathPointTypeLine, 0, 1}, /*5*/
959 {50.0, 50.0, PathPointTypeLine, 0, 1}, /*6*/
960 {30.5, 48.0, PathPointTypeLine, 0, 1}, /*7*/
961 {14.8, 42.8, PathPointTypeLine, 0, 1}, /*8*/
962 {8.5, 39.0, PathPointTypeLine, 0, 1}, /*9*/
963 {4.0, 34.8, PathPointTypeLine, 0, 1}, /*10*/
964 {1.0, 30.0, PathPointTypeLine, 0, 1}, /*11*/
965 {0.0, 25.0, PathPointTypeLine, 0, 1}, /*12*/
966 {1.0, 20.0, PathPointTypeLine, 0, 1}, /*13*/
967 {4.0, 15.3, PathPointTypeLine, 0, 1}, /*14*/
968 {8.5, 11.0, PathPointTypeLine, 0, 1}, /*15*/
969 {14.8, 7.3, PathPointTypeLine, 0, 1}, /*16*/
970 {30.5, 2.0, PathPointTypeLine, 0, 1}, /*17*/
971 {50.0, 0.0, PathPointTypeLine, 0, 1}, /*18*/
972 {69.5, 2.0, PathPointTypeLine, 0, 1}, /*19*/
973 {85.5, 7.3, PathPointTypeLine, 0, 1}, /*20*/
974 {91.5, 11.0, PathPointTypeLine, 0, 1}, /*21*/
975 {96.0, 15.3, PathPointTypeLine, 0, 1}, /*22*/
976 {99.0, 20.0, PathPointTypeLine, 0, 1}, /*23*/
977 {100.0,25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 1} /*24*/
978 };
979
980 static path_test_t flattenline_path[] = {
981 {5.0, 10.0,PathPointTypeStart, 0, 0}, /*0*/
982 {50.0, 100.0, PathPointTypeLine, 0, 0} /*1*/
983 };
984
985 static path_test_t flattenarc_path[] = {
986 {100.0, 25.0,PathPointTypeStart, 0, 0}, /*0*/
987 {99.0, 30.0, PathPointTypeLine, 0, 0}, /*1*/
988 {96.0, 34.8, PathPointTypeLine, 0, 0}, /*2*/
989 {91.5, 39.0, PathPointTypeLine, 0, 0}, /*3*/
990 {85.5, 42.8, PathPointTypeLine, 0, 0}, /*4*/
991 {69.5, 48.0, PathPointTypeLine, 0, 1}, /*5*/
992 {50.0, 50.0, PathPointTypeLine, 0, 1} /*6*/
993 };
994
995 static path_test_t flattenquater_path[] = {
996 {100.0, 50.0,PathPointTypeStart, 0, 0}, /*0*/
997 {99.0, 60.0, PathPointTypeLine, 0, 0}, /*1*/
998 {96.0, 69.5, PathPointTypeLine, 0, 0}, /*2*/
999 {91.5, 78.0, PathPointTypeLine, 0, 0}, /*3*/
1000 {85.5, 85.5, PathPointTypeLine, 0, 0}, /*4*/
1001 {78.0, 91.5, PathPointTypeLine, 0, 0}, /*5*/
1002 {69.5, 96.0, PathPointTypeLine, 0, 0}, /*6*/
1003 {60.0, 99.0, PathPointTypeLine, 0, 0}, /*7*/
1004 {50.0, 100.0,PathPointTypeLine, 0, 0} /*8*/
1005 };
1006
1007 static void test_flatten(void)
1008 {
1009 GpStatus status;
1010 GpPath *path;
1011 GpMatrix *m;
1012
1013 status = GdipCreatePath(FillModeAlternate, &path);
1014 expect(Ok, status);
1015 status = GdipCreateMatrix(&m);
1016 expect(Ok, status);
1017
1018 /* NULL arguments */
1019 status = GdipFlattenPath(NULL, NULL, 0.0);
1020 expect(InvalidParameter, status);
1021 status = GdipFlattenPath(NULL, m, 0.0);
1022 expect(InvalidParameter, status);
1023
1024 /* flatten empty path */
1025 status = GdipFlattenPath(path, NULL, 1.0);
1026 expect(Ok, status);
1027
1028 status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 50.0);
1029 expect(Ok, status);
1030
1031 status = GdipFlattenPath(path, NULL, 1.0);
1032 expect(Ok, status);
1033 ok_path(path, flattenellipse_path, sizeof(flattenellipse_path)/sizeof(path_test_t), TRUE);
1034
1035 status = GdipResetPath(path);
1036 expect(Ok, status);
1037 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 100.0);
1038 expect(Ok, status);
1039 status = GdipFlattenPath(path, NULL, 1.0);
1040 expect(Ok, status);
1041 ok_path(path, flattenline_path, sizeof(flattenline_path)/sizeof(path_test_t), FALSE);
1042
1043 status = GdipResetPath(path);
1044 expect(Ok, status);
1045 status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 50.0, 0.0, 90.0);
1046 expect(Ok, status);
1047 status = GdipFlattenPath(path, NULL, 1.0);
1048 expect(Ok, status);
1049 ok_path(path, flattenarc_path, sizeof(flattenarc_path)/sizeof(path_test_t), TRUE);
1050
1051 /* easy case - quater of a full circle */
1052 status = GdipResetPath(path);
1053 expect(Ok, status);
1054 status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0);
1055 expect(Ok, status);
1056 status = GdipFlattenPath(path, NULL, 1.0);
1057 expect(Ok, status);
1058 ok_path(path, flattenquater_path, sizeof(flattenquater_path)/sizeof(path_test_t), FALSE);
1059
1060 GdipDeleteMatrix(m);
1061 GdipDeletePath(path);
1062 }
1063
1064 static void test_isvisible(void)
1065 {
1066 GpPath *path;
1067 GpGraphics *graphics = NULL;
1068 HDC hdc = GetDC(0);
1069 BOOL result;
1070 GpStatus status;
1071
1072 status = GdipCreateFromHDC(hdc, &graphics);
1073 expect(Ok, status);
1074 status = GdipCreatePath(FillModeAlternate, &path);
1075 expect(Ok, status);
1076
1077 /* NULL */
1078 status = GdipIsVisiblePathPoint(NULL, 0.0, 0.0, NULL, NULL);
1079 expect(InvalidParameter, status);
1080 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, NULL);
1081 expect(InvalidParameter, status);
1082 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, NULL);
1083 expect(InvalidParameter, status);
1084 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, graphics, NULL);
1085 expect(InvalidParameter, status);
1086
1087 /* empty path */
1088 result = TRUE;
1089 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, &result);
1090 expect(Ok, status);
1091 expect(FALSE, result);
1092 /* rect */
1093 status = GdipAddPathRectangle(path, 0.0, 0.0, 10.0, 10.0);
1094 expect(Ok, status);
1095 result = FALSE;
1096 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, &result);
1097 expect(Ok, status);
1098 expect(TRUE, result);
1099 result = TRUE;
1100 status = GdipIsVisiblePathPoint(path, 11.0, 11.0, NULL, &result);
1101 expect(Ok, status);
1102 expect(FALSE, result);
1103 /* not affected by clipping */
1104 status = GdipSetClipRect(graphics, 5.0, 5.0, 5.0, 5.0, CombineModeReplace);
1105 expect(Ok, status);
1106 result = FALSE;
1107 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, graphics, &result);
1108 expect(Ok, status);
1109 expect(TRUE, result);
1110
1111 GdipDeletePath(path);
1112 GdipDeleteGraphics(graphics);
1113 ReleaseDC(0, hdc);
1114 }
1115
1116 static void test_empty_rect(void)
1117 {
1118 GpPath *path;
1119 GpStatus status;
1120 BOOL result;
1121
1122 status = GdipCreatePath(FillModeAlternate, &path);
1123 expect(Ok, status);
1124
1125 status = GdipAddPathRectangle(path, 0.0, 0.0, -5.0, 5.0);
1126 expect(Ok, status);
1127
1128 status = GdipIsVisiblePathPoint(path, -2.0, 2.0, NULL, &result);
1129 expect(Ok, status);
1130 expect(FALSE, status);
1131
1132 status = GdipAddPathRectangle(path, 0.0, 0.0, 5.0, -5.0);
1133 expect(Ok, status);
1134
1135 status = GdipAddPathRectangle(path, 0.0, 0.0, 0.0, 5.0);
1136 expect(Ok, status);
1137
1138 status = GdipAddPathRectangle(path, 0.0, 0.0, 5.0, 0.0);
1139 expect(Ok, status);
1140
1141 GdipDeletePath(path);
1142 }
1143
1144 START_TEST(graphicspath)
1145 {
1146 struct GdiplusStartupInput gdiplusStartupInput;
1147 ULONG_PTR gdiplusToken;
1148
1149 gdiplusStartupInput.GdiplusVersion = 1;
1150 gdiplusStartupInput.DebugEventCallback = NULL;
1151 gdiplusStartupInput.SuppressBackgroundThread = 0;
1152 gdiplusStartupInput.SuppressExternalCodecs = 0;
1153
1154 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
1155
1156 test_constructor_destructor();
1157 test_getpathdata();
1158 test_line2();
1159 test_arc();
1160 test_worldbounds();
1161 test_pathpath();
1162 test_ellipse();
1163 test_linei();
1164 test_rect();
1165 test_polygon();
1166 test_lastpoint();
1167 test_addcurve();
1168 test_addclosedcurve();
1169 test_reverse();
1170 test_addpie();
1171 test_flatten();
1172 test_isvisible();
1173 test_empty_rect();
1174
1175 GdiplusShutdown(gdiplusToken);
1176 }