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