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