gdiplus: Fix default tension for GdipAddPathCurve and GdipAddPathClosedCurve.
[wine.git] / dlls / gdiplus / tests / graphicspath.c
blob238305c3c24052ac888e12d6a2164f51f60088fb
1 /*
2 * Unit test suite for paths
4 * Copyright (C) 2007 Google (Evan Stade)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "objbase.h"
22 #include "gdiplus.h"
23 #include "wine/test.h"
24 #include <math.h>
26 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
27 #define expectf(expected, got) ok(fabs(expected - got) < 2.0, "Expected %.2f, got %.2f\n", expected, got)
28 #define POINT_TYPE_MAX_LEN (75)
30 static void stringify_point_type(PathPointType type, char * name)
32 *name = '\0';
34 switch(type & PathPointTypePathTypeMask){
35 case PathPointTypeStart:
36 strcat(name, "PathPointTypeStart");
37 break;
38 case PathPointTypeLine:
39 strcat(name, "PathPointTypeLine");
40 break;
41 case PathPointTypeBezier:
42 strcat(name, "PathPointTypeBezier");
43 break;
44 default:
45 strcat(name, "Unknown type");
46 return;
49 type &= ~PathPointTypePathTypeMask;
50 if(type & ~((PathPointTypePathMarker | PathPointTypeCloseSubpath))){
51 *name = '\0';
52 strcat(name, "Unknown type");
53 return;
56 if(type & PathPointTypePathMarker)
57 strcat(name, " | PathPointTypePathMarker");
58 if(type & PathPointTypeCloseSubpath)
59 strcat(name, " | PathPointTypeCloseSubpath");
62 /* this helper structure and function modeled after gdi path.c test */
63 typedef struct
65 REAL X, Y;
66 BYTE type;
68 /* How many extra entries before this one only on wine
69 * but not on native? */
70 int wine_only_entries_preceding;
72 /* 0 - This entry matches on wine.
73 * 1 - This entry corresponds to a single entry on wine that does not match the native entry.
74 * 2 - This entry is currently skipped on wine but present on native. */
75 int todo;
76 } path_test_t;
78 #define ok_path(a,b,c,d) _ok_path_fudge(a,b,c,d,1.0,__LINE__)
79 #define ok_path_fudge(a,b,c,d,e) _ok_path_fudge(a,b,c,d,e,__LINE__)
80 static void _ok_path_fudge(GpPath* path, const path_test_t *expected, INT expected_size,
81 BOOL todo_size, REAL fudge, int line)
83 BYTE * types;
84 INT size, idx = 0, eidx = 0, numskip;
85 GpPointF * points;
86 char ename[POINT_TYPE_MAX_LEN], name[POINT_TYPE_MAX_LEN];
88 if(GdipGetPointCount(path, &size) != Ok){
89 skip("Cannot perform path comparisons due to failure to retrieve path.\n");
90 return;
93 todo_wine_if (todo_size)
94 ok_(__FILE__,line)(size == expected_size, "Path size %d does not match expected size %d\n",
95 size, expected_size);
97 points = HeapAlloc(GetProcessHeap(), 0, size * sizeof(GpPointF));
98 types = HeapAlloc(GetProcessHeap(), 0, size);
100 if(GdipGetPathPoints(path, points, size) != Ok || GdipGetPathTypes(path, types, size) != Ok){
101 skip("Cannot perform path comparisons due to failure to retrieve path.\n");
102 goto end;
105 numskip = expected_size ? expected[eidx].wine_only_entries_preceding : 0;
106 while (idx < size && eidx < expected_size){
107 /* We allow a few pixels fudge in matching X and Y coordinates to account for imprecision in
108 * floating point to integer conversion */
109 BOOL match = (types[idx] == expected[eidx].type) &&
110 fabs(points[idx].X - expected[eidx].X) <= fudge &&
111 fabs(points[idx].Y - expected[eidx].Y) <= fudge;
113 stringify_point_type(expected[eidx].type, ename);
114 stringify_point_type(types[idx], name);
116 todo_wine_if (expected[eidx].todo || numskip)
117 ok_(__FILE__,line)(match, "Expected #%d: %s (%.6f,%.6f) but got %s (%.6f,%.6f)\n", eidx,
118 ename, expected[eidx].X, expected[eidx].Y,
119 name, points[idx].X, points[idx].Y);
121 if (match || expected[eidx].todo != 2)
122 idx++;
123 if (match || !numskip--)
124 numskip = expected[++eidx].wine_only_entries_preceding;
127 end:
128 HeapFree(GetProcessHeap(), 0, types);
129 HeapFree(GetProcessHeap(), 0, points);
132 static void test_constructor_destructor(void)
134 GpStatus status;
135 GpPath* path = NULL;
137 status = GdipCreatePath(FillModeAlternate, &path);
138 expect(Ok, status);
139 ok(path != NULL, "Expected path to be initialized\n");
141 status = GdipDeletePath(NULL);
142 expect(InvalidParameter, status);
144 status = GdipDeletePath(path);
145 expect(Ok, status);
148 static void test_getpathdata(void)
150 GpPath *path;
151 GpPathData data;
152 GpStatus status;
153 INT count;
155 status = GdipCreatePath(FillModeAlternate, &path);
156 expect(Ok, status);
157 status = GdipAddPathLine(path, 5.0, 5.0, 100.0, 50.0);
158 expect(Ok, status);
160 status = GdipGetPointCount(path, &count);
161 expect(Ok, status);
162 expect(2, count);
164 data.Count = count;
165 data.Types = GdipAlloc(sizeof(BYTE) * count);
166 data.Points = GdipAlloc(sizeof(PointF) * count);
168 status = GdipGetPathData(path, &data);
169 expect(Ok, status);
170 expect((data.Points[0].X == 5.0) && (data.Points[0].Y == 5.0) &&
171 (data.Points[1].X == 100.0) && (data.Points[1].Y == 50.0), TRUE);
172 expect((data.Types[0] == PathPointTypeStart) && (data.Types[1] == PathPointTypeLine), TRUE);
174 GdipFree(data.Points);
175 GdipFree(data.Types);
176 GdipDeletePath(path);
179 static void test_createpath2(void)
181 GpStatus status;
182 GpPath* path = NULL;
183 GpPathData data;
184 INT i, count, expect_count;
186 PointF test_line_points[] = {{1.0,1.0}, {2.0,1.0}, {2.0,2.0}};
187 BYTE test_line_types[] = {PathPointTypeStart, PathPointTypeLine, PathPointTypeStart};
189 PointF test_bez_points[] = {{1.0,1.0}, {2.0,1.0}, {3.0,1.0}, {4.0,1.0},
190 {5.0,1.0}, {6.0,1.0}, {7.0,1.0}};
191 BYTE test_bez_types[] = {PathPointTypeStart, PathPointTypeBezier,
192 PathPointTypeBezier, PathPointTypeBezier, PathPointTypeBezier,
193 PathPointTypeBezier, PathPointTypeBezier};
195 status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, &path);
196 expect(Ok, status);
197 status = GdipGetPointCount(path, &count);
198 expect(Ok, status);
199 expect(2, count);
200 GdipDeletePath(path);
202 status = GdipCreatePath2(test_line_points, test_line_types, 1, FillModeAlternate, &path);
203 expect(Ok, status);
204 status = GdipGetPointCount(path, &count);
205 expect(Ok, status);
206 expect(1, count);
207 GdipDeletePath(path);
209 path = (void *)0xdeadbeef;
210 status = GdipCreatePath2(test_line_points, test_line_types, 0, FillModeAlternate, &path);
211 expect(OutOfMemory, status);
212 ok(!path, "Expected NULL, got %p\n", path);
213 if(path && path != (void *)0xdeadbeef)
214 GdipDeletePath(path);
216 path = (void *)0xdeadbeef;
217 status = GdipCreatePath2(test_line_points, test_line_types, -1, FillModeAlternate, &path);
218 expect(OutOfMemory, status);
219 ok(!path, "Expected NULL, got %p\n", path);
220 if(path && path != (void *)0xdeadbeef)
221 GdipDeletePath(path);
223 path = (void *)0xdeadbeef;
224 status = GdipCreatePath2(NULL, test_line_types, 2, FillModeAlternate, &path);
225 expect(InvalidParameter, status);
226 ok(path == (void *)0xdeadbeef, "Expected %p, got %p\n", (void *)0xdeadbeef, path);
227 if(path && path != (void *)0xdeadbeef)
228 GdipDeletePath(path);
230 path = (void *)0xdeadbeef;
231 status = GdipCreatePath2(test_line_points, NULL, 2, FillModeAlternate, &path);
232 expect(InvalidParameter, status);
233 ok(path == (void *)0xdeadbeef, "Expected %p, got %p\n", (void *)0xdeadbeef, path);
234 if(path && path != (void *)0xdeadbeef)
235 GdipDeletePath(path);
237 status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, NULL);
238 expect(InvalidParameter, status);
240 /* Multi-point paths should not end with Start */
241 status = GdipCreatePath2(test_line_points, test_line_types, 3, FillModeAlternate, &path);
242 expect(Ok, status);
243 status = GdipGetPointCount(path, &count);
244 expect(Ok, status);
245 expect(0, count);
246 GdipDeletePath(path);
248 /* Zero-length line points do not get altered */
249 test_line_points[1].X = test_line_points[0].X;
250 test_line_points[1].Y = test_line_points[0].Y;
251 status = GdipCreatePath2(test_line_points, test_line_types, 2, FillModeAlternate, &path);
252 expect(Ok, status);
253 status = GdipGetPointCount(path, &count);
254 expect(Ok, status);
255 expect(2, count);
256 GdipDeletePath(path);
258 /* The type of the first point is always converted to PathPointTypeStart */
259 test_line_types[0] = PathPointTypeLine;
260 status = GdipCreatePath2(test_line_points, test_line_types, 1, FillModeAlternate, &path);
261 expect(Ok, status);
262 status = GdipGetPointCount(path, &count);
263 expect(Ok, status);
264 expect(1, count);
265 data.Count = count;
266 data.Types = GdipAlloc(sizeof(BYTE) * count);
267 data.Points = GdipAlloc(sizeof(PointF) * count);
268 status = GdipGetPathData(path, &data);
269 expect(Ok, status);
270 expect((data.Points[0].X == 1.0) && (data.Points[0].Y == 1.0), TRUE);
271 expect(data.Types[0], PathPointTypeStart);
272 GdipFree(data.Points);
273 GdipFree(data.Types);
274 GdipDeletePath(path);
276 /* Bezier points must come in groups of three */
277 for(i = 2; i <= 7; i++) {
278 expect_count = (i % 3 == 1) ? i : 0;
279 status = GdipCreatePath2(test_bez_points, test_bez_types, i, FillModeAlternate, &path);
280 expect(Ok, status);
281 status = GdipGetPointCount(path, &count);
282 expect(Ok, status);
283 expect(expect_count, count);
284 GdipDeletePath(path);
288 static path_test_t line2_path[] = {
289 {0.0, 50.0, PathPointTypeStart, 0, 0}, /*0*/
290 {5.0, 45.0, PathPointTypeLine, 0, 0}, /*1*/
291 {0.0, 40.0, PathPointTypeLine, 0, 0}, /*2*/
292 {15.0, 35.0, PathPointTypeLine, 0, 0}, /*3*/
293 {0.0, 30.0, PathPointTypeLine, 0, 0}, /*4*/
294 {25.0, 25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*5*/
295 {0.0, 20.0, PathPointTypeStart, 0, 0}, /*6*/
296 {35.0, 15.0, PathPointTypeLine, 0, 0}, /*7*/
297 {0.0, 10.0, PathPointTypeLine, 0, 0} /*8*/
300 static void test_line2(void)
302 GpStatus status;
303 GpPath* path;
304 int i;
305 GpPointF line2_points[9];
307 for(i = 0; i < 9; i ++){
308 line2_points[i].X = i * 5.0 * (REAL)(i % 2);
309 line2_points[i].Y = 50.0 - i * 5.0;
312 GdipCreatePath(FillModeAlternate, &path);
314 status = GdipAddPathLine2(NULL, line2_points, 2);
315 expect(InvalidParameter, status);
316 status = GdipAddPathLine2(path, NULL, 2);
317 expect(InvalidParameter, status);
318 status = GdipAddPathLine2(path, line2_points, 0);
319 expect(InvalidParameter, status);
320 status = GdipAddPathLine2(path, line2_points, -1);
321 expect(InvalidParameter, status);
323 status = GdipAddPathLine2(path, line2_points, 3);
324 expect(Ok, status);
325 status = GdipAddPathLine2(path, &(line2_points[3]), 3);
326 expect(Ok, status);
327 status = GdipClosePathFigure(path);
328 expect(Ok, status);
329 status = GdipAddPathLine2(path, &(line2_points[6]), 3);
330 expect(Ok, status);
332 ok_path(path, line2_path, ARRAY_SIZE(line2_path), FALSE);
334 GdipResetPath(path);
335 status = GdipAddPathLine2(path, line2_points, 3);
336 expect(Ok, status);
337 status = GdipAddPathLine2(path, &(line2_points[2]), 3);
338 expect(Ok, status);
340 ok_path(path, line2_path, 5, FALSE);
342 GdipDeletePath(path);
345 static path_test_t bezier_path[] = {
346 {10.0, 10.0, PathPointTypeStart, 0, 0}, /*0*/
347 {20.0, 10.0, PathPointTypeBezier, 0, 0}, /*1*/
348 {20.0, 20.0, PathPointTypeBezier, 0, 0}, /*2*/
349 {30.0, 20.0, PathPointTypeBezier, 0, 0}, /*3*/
350 {40.0, 20.0, PathPointTypeBezier, 0, 0}, /*4*/
351 {40.0, 30.0, PathPointTypeBezier, 0, 0}, /*5*/
352 {50.0, 30.0, PathPointTypeBezier, 0, 0}, /*6*/
353 {50.0, 10.0, PathPointTypeLine, 0, 0}, /*7*/
354 {60.0, 10.0, PathPointTypeBezier, 0, 0}, /*8*/
355 {60.0, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
356 {70.0, 20.0, PathPointTypeBezier, 0, 0} /*10*/
359 static void test_bezier(void)
361 GpStatus status;
362 GpPath* path;
364 GdipCreatePath(FillModeAlternate, &path);
366 status = GdipAddPathBezier(path, 10.0, 10.0, 20.0, 10.0, 20.0, 20.0, 30.0, 20.0);
367 expect(Ok, status);
368 status = GdipAddPathBezier(path, 30.0, 20.0, 40.0, 20.0, 40.0, 30.0, 50.0, 30.0);
369 expect(Ok, status);
370 status = GdipAddPathBezier(path, 50.0, 10.0, 60.0, 10.0, 60.0, 20.0, 70.0, 20.0);
371 expect(Ok, status);
373 ok_path(path, bezier_path, ARRAY_SIZE(bezier_path), FALSE);
375 GdipDeletePath(path);
378 static void test_beziers(void)
380 GpStatus status;
381 GpPath* path;
382 PointF bezier_points1[] = {{10.0,10.0}, {20.0,10.0}, {20.0,20.0}, {30.0,20.0}};
383 PointF bezier_points2[] = {{30.0,20.0}, {40.0,20.0}, {40.0,30.0}, {50.0,30.0}};
384 PointF bezier_points3[] = {{50.0,10.0}, {60.0,10.0}, {60.0,20.0}, {70.0,20.0}};
386 GdipCreatePath(FillModeAlternate, &path);
388 status = GdipAddPathBeziers(path, bezier_points1, 4);
389 expect(Ok, status);
390 status = GdipAddPathBeziers(path, bezier_points2, 4);
391 expect(Ok, status);
392 status = GdipAddPathBeziers(path, bezier_points3, 4);
393 expect(Ok, status);
395 ok_path(path, bezier_path, ARRAY_SIZE(bezier_path), FALSE);
397 GdipDeletePath(path);
400 static path_test_t arc_path[] = {
401 {600.0, 450.0, PathPointTypeStart, 0, 0}, /*0*/
402 {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*1*/
403 {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*2*/
404 {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*3*/
405 {600.0, 450.0, PathPointTypeLine, 0, 0}, /*4*/
406 {600.0, 643.3, PathPointTypeBezier, 0, 0}, /*5*/
407 {488.1, 800.0, PathPointTypeBezier, 0, 0}, /*6*/
408 {350.0, 800.0, PathPointTypeBezier, 0, 0}, /*7*/
409 {329.8, 800.0, PathPointTypeBezier, 0, 0}, /*8*/
410 {309.7, 796.6, PathPointTypeBezier, 0, 0}, /*9*/
411 {290.1, 789.8, PathPointTypeBezier, 0, 0}, /*10*/
412 {409.9, 110.2, PathPointTypeLine, 0, 0}, /*11*/
413 {544.0, 156.5, PathPointTypeBezier, 0, 0}, /*12*/
414 {625.8, 346.2, PathPointTypeBezier, 0, 0}, /*13*/
415 {592.7, 533.9, PathPointTypeBezier, 0, 0}, /*14*/
416 {592.5, 535.3, PathPointTypeBezier, 0, 0}, /*15*/
417 {592.2, 536.7, PathPointTypeBezier, 0, 0}, /*16*/
418 {592.0, 538.1, PathPointTypeBezier, 0, 0}, /*17*/
419 {409.9, 789.8, PathPointTypeLine, 0, 0}, /*18*/
420 {544.0, 743.5, PathPointTypeBezier, 0, 0}, /*19*/
421 {625.8, 553.8, PathPointTypeBezier, 0, 0}, /*20*/
422 {592.7, 366.1, PathPointTypeBezier, 0, 0}, /*21*/
423 {592.5, 364.7, PathPointTypeBezier, 0, 0}, /*22*/
424 {592.2, 363.3, PathPointTypeBezier, 0, 0}, /*23*/
425 {592.0, 361.9, PathPointTypeBezier, 0, 0}, /*24*/
426 {540.4, 676.9, PathPointTypeLine, 0, 0}, /*25*/
427 {629.9, 529.7, PathPointTypeBezier, 0, 0}, /*26*/
428 {617.2, 308.8, PathPointTypeBezier, 0, 0}, /*27*/
429 {512.1, 183.5, PathPointTypeBezier, 0, 0}, /*28*/
430 {406.9, 58.2, PathPointTypeBezier, 0, 0}, /*29*/
431 {249.1, 75.9, PathPointTypeBezier, 0, 0}, /*30*/
432 {159.6, 223.1, PathPointTypeBezier, 0, 0}, /*31*/
433 {70.1, 370.3, PathPointTypeBezier, 0, 0}, /*32*/
434 {82.8, 591.2, PathPointTypeBezier, 0, 0}, /*33*/
435 {187.9, 716.5, PathPointTypeBezier, 0, 0}, /*34*/
436 {293.1, 841.8, PathPointTypeBezier, 0, 0}, /*35*/
437 {450.9, 824.1, PathPointTypeBezier, 0, 0}, /*36*/
438 {540.4, 676.9, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 1} /*37*/
440 static path_test_t arc_path2[] = {
441 {1.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
442 {1.0, 0.5, PathPointTypeLine, 0, 0}, /*1*/
443 {1.0, 0.776142, PathPointTypeBezier, 0, 0}, /*2*/
444 {0.776142, 1.0, PathPointTypeBezier, 0, 0}, /*3*/
445 {0.5, 1.0, PathPointTypeBezier, 0, 0} /*4*/
448 static void test_arc(void)
450 GpStatus status;
451 GpPath* path;
453 GdipCreatePath(FillModeAlternate, &path);
455 status = GdipAddPathArc(path, 100.0, 100.0, 1.0, 0.0, 0.0, 90.0);
456 expect(InvalidParameter, status);
458 status = GdipAddPathArc(path, 100.0, 100.0, 0.0, 1.0, 0.0, 90.0);
459 expect(InvalidParameter, status);
461 status = GdipAddPathArc(path, 100.0, 100.0, -40, 1.0, 0.0, 90.0);
462 expect(InvalidParameter, status);
464 status = GdipAddPathArc(path, 100.0, 100.0, 1.0, -50.0, 0.0, 90.0);
465 expect(InvalidParameter, status);
467 GdipResetPath(path);
468 /* Exactly 90 degrees */
469 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
470 expect(Ok, status);
471 /* Over 90 degrees */
472 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
473 expect(Ok, status);
474 /* Negative start angle */
475 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
476 expect(Ok, status);
477 /* Negative sweep angle */
478 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 80.0, -100.0);
479 expect(Ok, status);
480 /* More than a full revolution */
481 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, -400.0);
482 expect(Ok, status);
483 /* 0 sweep angle */
484 status = GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 50.0, 0.0);
485 expect(Ok, status);
487 ok_path(path, arc_path, ARRAY_SIZE(arc_path), FALSE);
489 GdipResetPath(path);
490 GdipAddPathLine(path, 1.0, 0.0, 1.0, 0.5);
491 status = GdipAddPathArc(path, 0.0, 0.0, 1.0, 1.0, 0.0, 90.0);
492 expect(Ok, status);
494 ok_path_fudge(path, arc_path2, ARRAY_SIZE(arc_path2), FALSE, 0.000005);
496 GdipDeletePath(path);
499 static void test_worldbounds(void)
501 GpStatus status;
502 GpPath *path;
503 GpPen *pen;
504 GpMatrix *matrix;
505 GpRectF bounds;
506 GpPointF line2_points[10];
507 int i;
509 for(i = 0; i < 10; i ++){
510 line2_points[i].X = 200.0 + i * 50.0 * (i % 2);
511 line2_points[i].Y = 200.0 + i * 50.0 * !(i % 2);
513 GdipCreatePen1((ARGB)0xdeadbeef, 20.0, UnitWorld, &pen);
514 GdipSetPenEndCap(pen, LineCapSquareAnchor);
515 GdipCreateMatrix2(1.5, 0.0, 1.0, 1.2, 10.4, 10.2, &matrix);
517 GdipCreatePath(FillModeAlternate, &path);
518 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
519 GdipAddPathLine2(path, &(line2_points[0]), 10);
520 status = GdipGetPathWorldBounds(path, &bounds, NULL, NULL);
521 expect(Ok, status);
522 GdipDeletePath(path);
524 expectf(200.0, bounds.X);
525 expectf(200.0, bounds.Y);
526 expectf(450.0, bounds.Width);
527 expectf(600.0, bounds.Height);
529 GdipCreatePath(FillModeAlternate, &path);
530 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
531 GdipAddPathLine2(path, &(line2_points[0]), 10);
532 status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
533 expect(Ok, status);
534 GdipDeletePath(path);
536 expectf(510.4, bounds.X);
537 expectf(250.2, bounds.Y);
538 expectf(1275.0, bounds.Width);
539 expectf(720.0, bounds.Height);
541 GdipCreatePath(FillModeAlternate, &path);
542 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
543 GdipAddPathLine2(path, &(line2_points[0]), 10);
544 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
545 expect(Ok, status);
546 GdipDeletePath(path);
548 expectf(100.0, bounds.X);
549 expectf(100.0, bounds.Y);
550 expectf(650.0, bounds.Width);
551 expectf(800.0, bounds.Height);
553 GdipCreatePath(FillModeAlternate, &path);
554 GdipAddPathLine2(path, &(line2_points[0]), 2);
555 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
556 expect(Ok, status);
557 GdipDeletePath(path);
559 expectf(156.0, bounds.X);
560 expectf(156.0, bounds.Y);
561 expectf(138.0, bounds.Width);
562 expectf(88.0, bounds.Height);
564 line2_points[2].X = 2 * line2_points[1].X - line2_points[0].X;
565 line2_points[2].Y = 2 * line2_points[1].Y - line2_points[0].Y;
567 GdipCreatePath(FillModeAlternate, &path);
568 GdipAddPathLine2(path, &(line2_points[0]), 3);
569 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
570 expect(Ok, status);
571 GdipDeletePath(path);
573 expectf(100.0, bounds.X);
574 expectf(100.0, bounds.Y);
575 expectf(300.0, bounds.Width);
576 expectf(200.0, bounds.Height);
578 GdipCreatePath(FillModeAlternate, &path);
579 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 45.0, 20.0);
580 status = GdipGetPathWorldBounds(path, &bounds, NULL, pen);
581 expect(Ok, status);
582 GdipDeletePath(path);
584 expectf(386.7, bounds.X);
585 expectf(553.4, bounds.Y);
586 expectf(266.8, bounds.Width);
587 expectf(289.6, bounds.Height);
589 GdipCreatePath(FillModeAlternate, &path);
590 status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
591 expect(Ok, status);
592 GdipDeletePath(path);
594 expectf(0.0, bounds.X);
595 expectf(0.0, bounds.Y);
596 expectf(0.0, bounds.Width);
597 expectf(0.0, bounds.Height);
599 GdipCreatePath(FillModeAlternate, &path);
600 GdipAddPathLine2(path, &(line2_points[0]), 2);
601 status = GdipGetPathWorldBounds(path, &bounds, matrix, pen);
602 expect(Ok, status);
603 GdipDeletePath(path);
605 todo_wine{
606 expectf(427.9, bounds.X);
607 expectf(167.7, bounds.Y);
608 expectf(239.9, bounds.Width);
609 expectf(164.9, bounds.Height);
612 GdipDeleteMatrix(matrix);
613 GdipCreateMatrix2(0.9, -0.5, -0.5, -1.2, 10.4, 10.2, &matrix);
614 GdipCreatePath(FillModeAlternate, &path);
615 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, 0.0, 100.0);
616 GdipAddPathLine2(path, &(line2_points[0]), 10);
617 status = GdipGetPathWorldBounds(path, &bounds, matrix, NULL);
618 expect(Ok, status);
619 GdipDeletePath(path);
620 GdipDeleteMatrix(matrix);
622 expectf(-209.6, bounds.X);
623 expectf(-1274.8, bounds.Y);
624 expectf(705.0, bounds.Width);
625 expectf(945.0, bounds.Height);
627 GdipDeletePen(pen);
630 static path_test_t pathpath_path[] = {
631 {600.00, 450.00, PathPointTypeStart, 0, 0}, /*0*/
632 {600.00, 643.30, PathPointTypeBezier, 0, 0}, /*1*/
633 {488.07, 800.00, PathPointTypeBezier, 0, 0}, /*2*/
634 {350.00, 800.00, PathPointTypeBezier, 0, 0}, /*3*/
635 {319.61, 797.40, PathPointTypeStart, 0, 0}, /*4*/
636 {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*5*/
637 {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*6*/
638 {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*7*/
639 {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*8*/
640 {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*9*/
641 {104.46, 384.21, PathPointTypeBezier, 0, 0}, /*10*/
642 {409.92, 110.20, PathPointTypeLine, 0, 0}, /*11*/
643 {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*12*/
644 {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*13*/
645 {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*14*/
646 {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*15*/
647 {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*16*/
648 {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*17*/
649 {319.61, 797.40, PathPointTypeLine, 0, 0}, /*18*/
650 {182.56, 773.90, PathPointTypeBezier, 0, 0}, /*19*/
651 {85.07, 599.31, PathPointTypeBezier, 0, 0}, /*20*/
652 {101.85, 407.45, PathPointTypeBezier, 0, 0}, /*21*/
653 {102.54, 399.66, PathPointTypeBezier, 0, 0}, /*22*/
654 {103.40, 391.91, PathPointTypeBezier, 0, 0}, /*23*/
655 {104.46, 384.21, PathPointTypeBezier, 0, 0} /*24*/
658 static void test_pathpath(void)
660 GpStatus status;
661 GpPath* path1, *path2;
663 GdipCreatePath(FillModeAlternate, &path2);
664 GdipAddPathArc(path2, 100.0, 100.0, 500.0, 700.0, 95.0, 100.0);
666 GdipCreatePath(FillModeAlternate, &path1);
667 GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, 0.0, 90.0);
668 status = GdipAddPathPath(path1, path2, FALSE);
669 expect(Ok, status);
670 GdipAddPathArc(path1, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
671 status = GdipAddPathPath(path1, path2, TRUE);
672 expect(Ok, status);
674 ok_path(path1, pathpath_path, ARRAY_SIZE(pathpath_path), FALSE);
676 GdipDeletePath(path1);
677 GdipDeletePath(path2);
680 static path_test_t ellipse_path[] = {
681 {30.00, 125.25, PathPointTypeStart, 0, 0}, /*0*/
682 {30.00, 139.20, PathPointTypeBezier, 0, 0}, /*1*/
683 {25.52, 150.50, PathPointTypeBezier, 0, 0}, /*2*/
684 {20.00, 150.50, PathPointTypeBezier, 0, 0}, /*3*/
685 {14.48, 150.50, PathPointTypeBezier, 0, 0}, /*4*/
686 {10.00, 139.20, PathPointTypeBezier, 0, 0}, /*5*/
687 {10.00, 125.25, PathPointTypeBezier, 0, 0}, /*6*/
688 {10.00, 111.30, PathPointTypeBezier, 0, 0}, /*7*/
689 {14.48, 100.00, PathPointTypeBezier, 0, 0}, /*8*/
690 {20.00, 100.00, PathPointTypeBezier, 0, 0}, /*9*/
691 {25.52, 100.00, PathPointTypeBezier, 0, 0}, /*10*/
692 {30.00, 111.30, PathPointTypeBezier, 0, 0}, /*11*/
693 {30.00, 125.25, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*12*/
694 {7.00, 11.00, PathPointTypeStart, 0, 0}, /*13*/
695 {13.00, 17.00, PathPointTypeLine, 0, 0}, /*14*/
696 {5.00, 195.00, PathPointTypeStart, 0, 0}, /*15*/
697 {5.00, 192.24, PathPointTypeBezier, 0, 0}, /*16*/
698 {6.12, 190.00, PathPointTypeBezier, 0, 0}, /*17*/
699 {7.50, 190.00, PathPointTypeBezier, 0, 0}, /*18*/
700 {8.88, 190.00, PathPointTypeBezier, 0, 0}, /*19*/
701 {10.00, 192.24, PathPointTypeBezier, 0, 0}, /*20*/
702 {10.00, 195.00, PathPointTypeBezier, 0, 0}, /*21*/
703 {10.00, 197.76, PathPointTypeBezier, 0, 0}, /*22*/
704 {8.88, 200.00, PathPointTypeBezier, 0, 0}, /*23*/
705 {7.50, 200.00, PathPointTypeBezier, 0, 0}, /*24*/
706 {6.12, 200.00, PathPointTypeBezier, 0, 0}, /*25*/
707 {5.00, 197.76, PathPointTypeBezier, 0, 0}, /*26*/
708 {5.00, 195.00, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0}, /*27*/
709 {10.00, 300.50, PathPointTypeStart, 0, 0}, /*28*/
710 {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*29*/
711 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*30*/
712 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*31*/
713 {10.00, 301.00, PathPointTypeBezier, 0, 0}, /*32*/
714 {10.00, 300.78, PathPointTypeBezier, 0, 0}, /*33*/
715 {10.00, 300.50, PathPointTypeBezier, 0, 0}, /*34*/
716 {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*35*/
717 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*36*/
718 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*37*/
719 {10.00, 300.00, PathPointTypeBezier, 0, 0}, /*38*/
720 {10.00, 300.22, PathPointTypeBezier, 0, 0}, /*39*/
721 {10.00, 300.50, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*40*/
724 static void test_ellipse(void)
726 GpStatus status;
727 GpPath *path;
728 GpPointF points[2];
730 points[0].X = 7.0;
731 points[0].Y = 11.0;
732 points[1].X = 13.0;
733 points[1].Y = 17.0;
735 GdipCreatePath(FillModeAlternate, &path);
736 status = GdipAddPathEllipse(path, 10.0, 100.0, 20.0, 50.5);
737 expect(Ok, status);
738 GdipAddPathLine2(path, points, 2);
739 status = GdipAddPathEllipse(path, 10.0, 200.0, -5.0, -10.0);
740 expect(Ok, status);
741 GdipClosePathFigure(path);
742 status = GdipAddPathEllipse(path, 10.0, 300.0, 0.0, 1.0);
743 expect(Ok, status);
745 ok_path(path, ellipse_path, ARRAY_SIZE(ellipse_path), FALSE);
747 GdipDeletePath(path);
750 static path_test_t linei_path[] = {
751 {5.00, 5.00, PathPointTypeStart, 0, 0}, /*0*/
752 {6.00, 8.00, PathPointTypeLine, 0, 0}, /*1*/
753 {409.92, 110.20, PathPointTypeLine, 0, 0}, /*2*/
754 {543.96, 156.53, PathPointTypeBezier, 0, 0}, /*3*/
755 {625.80, 346.22, PathPointTypeBezier, 0, 0}, /*4*/
756 {592.71, 533.88, PathPointTypeBezier, 0, 0}, /*5*/
757 {592.47, 535.28, PathPointTypeBezier, 0, 0}, /*6*/
758 {592.22, 536.67, PathPointTypeBezier, 0, 0}, /*7*/
759 {591.96, 538.06, PathPointTypeBezier, 0, 0}, /*8*/
760 {15.00, 15.00, PathPointTypeLine, 0, 0}, /*9*/
761 {26.00, 28.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*10*/
762 {35.00, 35.00, PathPointTypeStart, 0, 0}, /*11*/
763 {36.00, 38.00, PathPointTypeLine, 0, 0}, /*12*/
764 {39.00, 40.00, PathPointTypeLine, 0, 0} /*13*/
767 static void test_linei(void)
769 GpStatus status;
770 GpPath *path;
772 GdipCreatePath(FillModeAlternate, &path);
773 status = GdipAddPathLineI(path, 5.0, 5.0, 6.0, 8.0);
774 expect(Ok, status);
775 GdipAddPathArc(path, 100.0, 100.0, 500.0, 700.0, -80.0, 100.0);
776 status = GdipAddPathLineI(path, 15.0, 15.0, 26.0, 28.0);
777 expect(Ok, status);
778 GdipClosePathFigure(path);
779 status = GdipAddPathLineI(path, 35.0, 35.0, 36.0, 38.0);
780 expect(Ok, status);
781 status = GdipAddPathLineI(path, 36, 38, 39, 40);
782 expect(Ok, status);
784 ok_path(path, linei_path, ARRAY_SIZE(linei_path), FALSE);
786 GdipDeletePath(path);
789 static path_test_t poly_path[] = {
790 {5.00, 5.00, PathPointTypeStart, 0, 0}, /*1*/
791 {6.00, 8.00, PathPointTypeLine, 0, 0}, /*2*/
792 {0.00, 0.00, PathPointTypeStart, 0, 0}, /*3*/
793 {10.00, 10.00, PathPointTypeLine, 0, 0}, /*4*/
794 {10.00, 20.00, PathPointTypeLine, 0, 0}, /*5*/
795 {30.00, 10.00, PathPointTypeLine, 0, 0}, /*6*/
796 {20.00, 0.00, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*7*/
799 static void test_polygon(void)
801 GpStatus status;
802 GpPath *path;
803 GpPointF points[5];
805 points[0].X = 0.0;
806 points[0].Y = 0.0;
807 points[1].X = 10.0;
808 points[1].Y = 10.0;
809 points[2].X = 10.0;
810 points[2].Y = 20.0;
811 points[3].X = 30.0;
812 points[3].Y = 10.0;
813 points[4].X = 20.0;
814 points[4].Y = 0.0;
816 GdipCreatePath(FillModeAlternate, &path);
818 /* NULL args */
819 status = GdipAddPathPolygon(NULL, points, 5);
820 expect(InvalidParameter, status);
821 status = GdipAddPathPolygon(path, NULL, 5);
822 expect(InvalidParameter, status);
823 /* Polygon should have 3 points at least */
824 status = GdipAddPathPolygon(path, points, 2);
825 expect(InvalidParameter, status);
827 /* to test how it prolongs not empty path */
828 status = GdipAddPathLine(path, 5.0, 5.0, 6.0, 8.0);
829 expect(Ok, status);
830 status = GdipAddPathPolygon(path, points, 5);
831 expect(Ok, status);
832 /* check resulting path */
833 ok_path(path, poly_path, ARRAY_SIZE(poly_path), FALSE);
835 GdipDeletePath(path);
838 static path_test_t rect_path[] = {
839 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
840 {105.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
841 {105.0, 55.0, PathPointTypeLine, 0, 0}, /*2*/
842 {5.0, 55.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0}, /*3*/
844 {100.0, 50.0, PathPointTypeStart, 0, 0}, /*4*/
845 {220.0, 50.0, PathPointTypeLine, 0, 0}, /*5*/
846 {220.0, 80.0, PathPointTypeLine, 0, 0}, /*6*/
847 {100.0, 80.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*7*/
850 static void test_rect(void)
852 GpStatus status;
853 GpPath *path;
854 GpRectF rects[2];
856 GdipCreatePath(FillModeAlternate, &path);
857 status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
858 expect(Ok, status);
859 status = GdipAddPathRectangle(path, 100.0, 50.0, 120.0, 30.0);
860 expect(Ok, status);
862 ok_path(path, rect_path, ARRAY_SIZE(rect_path), FALSE);
864 GdipDeletePath(path);
866 GdipCreatePath(FillModeAlternate, &path);
868 rects[0].X = 5.0;
869 rects[0].Y = 5.0;
870 rects[0].Width = 100.0;
871 rects[0].Height = 50.0;
872 rects[1].X = 100.0;
873 rects[1].Y = 50.0;
874 rects[1].Width = 120.0;
875 rects[1].Height = 30.0;
877 status = GdipAddPathRectangles(path, (GDIPCONST GpRectF*)&rects, 2);
878 expect(Ok, status);
880 ok_path(path, rect_path, ARRAY_SIZE(rect_path), FALSE);
882 GdipDeletePath(path);
885 static void test_lastpoint(void)
887 GpStatus status;
888 GpPath *path;
889 GpPointF ptf;
891 GdipCreatePath(FillModeAlternate, &path);
892 status = GdipAddPathRectangle(path, 5.0, 5.0, 100.0, 50.0);
893 expect(Ok, status);
895 /* invalid args */
896 status = GdipGetPathLastPoint(NULL, &ptf);
897 expect(InvalidParameter, status);
898 status = GdipGetPathLastPoint(path, NULL);
899 expect(InvalidParameter, status);
900 status = GdipGetPathLastPoint(NULL, NULL);
901 expect(InvalidParameter, status);
903 status = GdipGetPathLastPoint(path, &ptf);
904 expect(Ok, status);
905 expect(TRUE, (ptf.X == 5.0) && (ptf.Y == 55.0));
907 GdipDeletePath(path);
910 static path_test_t addcurve_path[] = {
911 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
912 {3.3, 3.3, PathPointTypeBezier, 0, 0}, /*1*/
913 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*2*/
914 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
915 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
916 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
917 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
918 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
919 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*8*/
920 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*9*/
922 static path_test_t addcurve_path_default_tension[] = {
923 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
924 {1.66, 1.66, PathPointTypeBezier, 0, 0}, /*1*/
925 {8.33, 6.66, PathPointTypeBezier, 0, 0}, /*2*/
926 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
927 {11.6, 13.3, PathPointTypeBezier, 0, 0}, /*4*/
928 {6.66, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
929 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
930 {13.3, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
931 {26.6, 11.6, PathPointTypeBezier, 0, 0}, /*8*/
932 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*9*/
934 static path_test_t addcurve_path2[] = {
935 {100.0,120.0,PathPointTypeStart, 0, 0}, /*0*/
936 {123.0,10.0, PathPointTypeLine, 0, 0}, /*1*/
937 {0.0, 0.0, PathPointTypeLine, 0, 0}, /*2*/
938 {3.3, 3.3, PathPointTypeBezier, 0, 0}, /*3*/
939 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*4*/
940 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*5*/
941 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*6*/
942 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
943 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*8*/
944 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*9*/
945 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*10*/
946 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*11*/
948 static path_test_t addcurve_path3[] = {
949 {10.0, 10.0, PathPointTypeStart, 0, 0}, /*0*/
950 {13.3, 16.7, PathPointTypeBezier, 0, 1}, /*1*/
951 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*2*/
952 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*3*/
953 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*4*/
954 {23.3, 13.3, PathPointTypeBezier, 0, 0}, /*5*/
955 {30.0, 10.0, PathPointTypeBezier, 0, 0} /*6*/
957 static void test_addcurve(void)
959 GpStatus status;
960 GpPath *path;
961 GpPointF points[4];
963 points[0].X = 0.0;
964 points[0].Y = 0.0;
965 points[1].X = 10.0;
966 points[1].Y = 10.0;
967 points[2].X = 10.0;
968 points[2].Y = 20.0;
969 points[3].X = 30.0;
970 points[3].Y = 10.0;
972 GdipCreatePath(FillModeAlternate, &path);
974 /* NULL args */
975 status = GdipAddPathCurve2(NULL, NULL, 0, 0.0);
976 expect(InvalidParameter, status);
977 status = GdipAddPathCurve2(path, NULL, 0, 0.0);
978 expect(InvalidParameter, status);
979 status = GdipAddPathCurve2(path, points, -1, 0.0);
980 expect(InvalidParameter, status);
981 status = GdipAddPathCurve2(path, points, 1, 1.0);
982 expect(InvalidParameter, status);
984 /* add to empty path */
985 status = GdipAddPathCurve2(path, points, 4, 1.0);
986 expect(Ok, status);
987 ok_path(path, addcurve_path, ARRAY_SIZE(addcurve_path), FALSE);
988 GdipDeletePath(path);
990 /* add to empty path with default tension */
991 GdipCreatePath(FillModeAlternate, &path);
992 status = GdipAddPathCurve(path, points, 4);
993 expect(Ok, status);
994 ok_path(path, addcurve_path_default_tension, ARRAY_SIZE(addcurve_path_default_tension), FALSE);
995 GdipDeletePath(path);
997 /* add to notempty path and opened figure */
998 GdipCreatePath(FillModeAlternate, &path);
999 GdipAddPathLine(path, 100.0, 120.0, 123.0, 10.0);
1000 status = GdipAddPathCurve2(path, points, 4, 1.0);
1001 expect(Ok, status);
1002 ok_path(path, addcurve_path2, ARRAY_SIZE(addcurve_path2), FALSE);
1004 /* NULL args */
1005 GdipResetPath(path);
1006 status = GdipAddPathCurve3(NULL, NULL, 0, 0, 0, 0.0);
1007 expect(InvalidParameter, status);
1008 status = GdipAddPathCurve3(path, NULL, 0, 0, 0, 0.0);
1009 expect(InvalidParameter, status);
1010 /* wrong count, offset.. */
1011 status = GdipAddPathCurve3(path, points, 0, 0, 0, 0.0);
1012 expect(InvalidParameter, status);
1013 status = GdipAddPathCurve3(path, points, 4, 0, 0, 0.0);
1014 expect(InvalidParameter, status);
1015 status = GdipAddPathCurve3(path, points, 4, 0, 4, 0.0);
1016 expect(InvalidParameter, status);
1017 status = GdipAddPathCurve3(path, points, 4, 1, 3, 0.0);
1018 expect(InvalidParameter, status);
1019 status = GdipAddPathCurve3(path, points, 4, 1, 0, 0.0);
1020 expect(InvalidParameter, status);
1021 status = GdipAddPathCurve3(path, points, 4, 3, 1, 0.0);
1022 expect(InvalidParameter, status);
1024 /* use all points */
1025 status = GdipAddPathCurve3(path, points, 4, 0, 3, 1.0);
1026 expect(Ok, status);
1027 ok_path(path, addcurve_path, ARRAY_SIZE(addcurve_path), FALSE);
1028 GdipResetPath(path);
1030 status = GdipAddPathCurve3(path, points, 4, 1, 2, 1.0);
1031 expect(Ok, status);
1032 ok_path(path, addcurve_path3, ARRAY_SIZE(addcurve_path3), FALSE);
1034 GdipDeletePath(path);
1037 static path_test_t addclosedcurve_path[] = {
1038 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
1039 {-6.7, 0.0, PathPointTypeBezier, 0, 0}, /*1*/
1040 {6.7, 3.3, PathPointTypeBezier, 0, 0}, /*2*/
1041 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
1042 {13.3, 16.7, PathPointTypeBezier, 0, 0}, /*4*/
1043 {3.3, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
1044 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
1045 {16.7, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
1046 {33.3, 16.7, PathPointTypeBezier, 0, 0}, /*8*/
1047 {30.0, 10.0, PathPointTypeBezier, 0, 0}, /*9*/
1048 {26.7, 3.3, PathPointTypeBezier, 0, 0}, /*10*/
1049 {6.7, 0.0, PathPointTypeBezier, 0, 0}, /*11*/
1050 {0.0, 0.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*12*/
1052 static path_test_t addclosedcurve_path_default_tension[] = {
1053 {0.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
1054 {-3.33, 0.0, PathPointTypeBezier, 0, 0}, /*1*/
1055 {8.33, 6.66, PathPointTypeBezier, 0, 0}, /*2*/
1056 {10.0, 10.0, PathPointTypeBezier, 0, 0}, /*3*/
1057 {11.6, 13.3, PathPointTypeBezier, 0, 0}, /*4*/
1058 {6.66, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
1059 {10.0, 20.0, PathPointTypeBezier, 0, 0}, /*6*/
1060 {13.3, 20.0, PathPointTypeBezier, 0, 0}, /*7*/
1061 {31.6, 13.3, PathPointTypeBezier, 0, 0}, /*8*/
1062 {30.0, 10.0, PathPointTypeBezier, 0, 0}, /*9*/
1063 {28.3, 6.66, PathPointTypeBezier, 0, 0}, /*10*/
1064 {3.33, 0.0, PathPointTypeBezier, 0, 0}, /*11*/
1065 {0.0, 0.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*12*/
1067 static void test_addclosedcurve(void)
1069 GpStatus status;
1070 GpPath *path;
1071 GpPointF points[4];
1073 points[0].X = 0.0;
1074 points[0].Y = 0.0;
1075 points[1].X = 10.0;
1076 points[1].Y = 10.0;
1077 points[2].X = 10.0;
1078 points[2].Y = 20.0;
1079 points[3].X = 30.0;
1080 points[3].Y = 10.0;
1082 GdipCreatePath(FillModeAlternate, &path);
1084 /* NULL args */
1085 status = GdipAddPathClosedCurve2(NULL, NULL, 0, 0.0);
1086 expect(InvalidParameter, status);
1087 status = GdipAddPathClosedCurve2(path, NULL, 0, 0.0);
1088 expect(InvalidParameter, status);
1089 status = GdipAddPathClosedCurve2(path, points, -1, 0.0);
1090 expect(InvalidParameter, status);
1091 status = GdipAddPathClosedCurve2(path, points, 1, 1.0);
1092 expect(InvalidParameter, status);
1094 /* add to empty path */
1095 status = GdipAddPathClosedCurve2(path, points, 4, 1.0);
1096 expect(Ok, status);
1097 ok_path(path, addclosedcurve_path, ARRAY_SIZE(addclosedcurve_path), FALSE);
1098 GdipDeletePath(path);
1100 /* add to empty path with default tension */
1101 GdipCreatePath(FillModeAlternate, &path);
1102 status = GdipAddPathClosedCurve(path, points, 4);
1103 expect(Ok, status);
1104 ok_path(path, addclosedcurve_path_default_tension, ARRAY_SIZE(addclosedcurve_path_default_tension), FALSE);
1105 GdipDeletePath(path);
1108 static path_test_t reverse_path[] = {
1109 {0.0, 20.0, PathPointTypeStart, 0, 0}, /*0*/
1110 {25.0, 25.0, PathPointTypeLine, 0, 0}, /*1*/
1111 {0.0, 30.0, PathPointTypeLine, 0, 0}, /*2*/
1112 {15.0, 35.0, PathPointTypeStart, 0, 0}, /*3*/
1113 {0.0, 40.0, PathPointTypeLine, 0, 0}, /*4*/
1114 {5.0, 45.0, PathPointTypeLine, 0, 0}, /*5*/
1115 {0.0, 50.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 0} /*6*/
1118 static void test_reverse(void)
1120 GpStatus status;
1121 GpPath *path;
1122 GpPointF pts[7];
1123 INT i;
1125 for(i = 0; i < 7; i++){
1126 pts[i].X = i * 5.0 * (REAL)(i % 2);
1127 pts[i].Y = 50.0 - i * 5.0;
1130 GdipCreatePath(FillModeAlternate, &path);
1132 /* NULL argument */
1133 status = GdipReversePath(NULL);
1134 expect(InvalidParameter, status);
1136 /* empty path */
1137 status = GdipReversePath(path);
1138 expect(Ok, status);
1140 GdipAddPathLine2(path, pts, 4);
1141 GdipClosePathFigure(path);
1142 GdipAddPathLine2(path, &(pts[4]), 3);
1144 status = GdipReversePath(path);
1145 expect(Ok, status);
1146 ok_path(path, reverse_path, ARRAY_SIZE(reverse_path), FALSE);
1148 GdipDeletePath(path);
1151 static path_test_t addpie_path[] = {
1152 {50.0, 25.0, PathPointTypeStart, 0, 0}, /*0*/
1153 {97.2, 33.3, PathPointTypeLine, 0, 0}, /*1*/
1154 {91.8, 40.9, PathPointTypeBezier,0, 0}, /*2*/
1155 {79.4, 46.8, PathPointTypeBezier,0, 0}, /*3*/
1156 {63.9, 49.0, PathPointTypeBezier | PathPointTypeCloseSubpath, 0, 0} /*4*/
1158 static path_test_t addpie_path2[] = {
1159 {0.0, 30.0, PathPointTypeStart | PathPointTypeCloseSubpath, 0, 0} /*0*/
1161 static path_test_t addpie_path3[] = {
1162 {30.0, 0.0, PathPointTypeStart | PathPointTypeCloseSubpath, 0, 0} /*0*/
1164 static void test_addpie(void)
1166 GpStatus status;
1167 GpPath *path;
1169 GdipCreatePath(FillModeAlternate, &path);
1171 /* NULL argument */
1172 status = GdipAddPathPie(NULL, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
1173 expect(InvalidParameter, status);
1175 status = GdipAddPathPie(path, 0.0, 0.0, 100.0, 50.0, 10.0, 50.0);
1176 expect(Ok, status);
1177 ok_path(path, addpie_path, ARRAY_SIZE(addpie_path), FALSE);
1178 status = GdipResetPath(path);
1179 expect(Ok, status);
1181 /* zero width base ellipse */
1182 status = GdipAddPathPie(path, 0.0, 0.0, 0.0, 60.0, -90.0, 24.0);
1183 expect(InvalidParameter, status);
1184 ok_path(path, addpie_path2, ARRAY_SIZE(addpie_path2), FALSE);
1185 status = GdipResetPath(path);
1186 expect(Ok, status);
1188 /* zero height base ellipse */
1189 status = GdipAddPathPie(path, 0.0, 0.0, 60.0, 0.0 , -90.0, 24.0);
1190 expect(InvalidParameter, status);
1191 ok_path(path, addpie_path3, ARRAY_SIZE(addpie_path3), FALSE);
1193 GdipDeletePath(path);
1196 static path_test_t flattenellipse_path[] = {
1197 {100.0, 25.0,PathPointTypeStart, 0, 0}, /*0*/
1198 {99.0, 30.0, PathPointTypeLine, 0, 0}, /*1*/
1199 {96.0, 34.8, PathPointTypeLine, 0, 0}, /*2*/
1200 {91.5, 39.0, PathPointTypeLine, 0, 0}, /*3*/
1201 {85.5, 42.8, PathPointTypeLine, 0, 0}, /*4*/
1202 {69.5, 48.0, PathPointTypeLine, 0, 1}, /*5*/
1203 {50.0, 50.0, PathPointTypeLine, 0, 1}, /*6*/
1204 {30.5, 48.0, PathPointTypeLine, 0, 1}, /*7*/
1205 {14.8, 42.8, PathPointTypeLine, 0, 1}, /*8*/
1206 {8.5, 39.0, PathPointTypeLine, 0, 1}, /*9*/
1207 {4.0, 34.8, PathPointTypeLine, 0, 1}, /*10*/
1208 {1.0, 30.0, PathPointTypeLine, 0, 1}, /*11*/
1209 {0.0, 25.0, PathPointTypeLine, 0, 1}, /*12*/
1210 {1.0, 20.0, PathPointTypeLine, 0, 1}, /*13*/
1211 {4.0, 15.3, PathPointTypeLine, 0, 1}, /*14*/
1212 {8.5, 11.0, PathPointTypeLine, 0, 1}, /*15*/
1213 {14.8, 7.3, PathPointTypeLine, 0, 1}, /*16*/
1214 {30.5, 2.0, PathPointTypeLine, 0, 1}, /*17*/
1215 {50.0, 0.0, PathPointTypeLine, 0, 1}, /*18*/
1216 {69.5, 2.0, PathPointTypeLine, 0, 1}, /*19*/
1217 {85.5, 7.3, PathPointTypeLine, 0, 1}, /*20*/
1218 {91.5, 11.0, PathPointTypeLine, 0, 1}, /*21*/
1219 {96.0, 15.3, PathPointTypeLine, 0, 1}, /*22*/
1220 {99.0, 20.0, PathPointTypeLine, 0, 1}, /*23*/
1221 {100.0,25.0, PathPointTypeLine | PathPointTypeCloseSubpath, 0, 1} /*24*/
1224 static path_test_t flattenline_path[] = {
1225 {5.0, 10.0,PathPointTypeStart, 0, 0}, /*0*/
1226 {50.0, 100.0, PathPointTypeLine, 0, 0} /*1*/
1229 static path_test_t flattenarc_path[] = {
1230 {100.0, 25.0,PathPointTypeStart, 0, 0}, /*0*/
1231 {99.0, 30.0, PathPointTypeLine, 0, 0}, /*1*/
1232 {96.0, 34.8, PathPointTypeLine, 0, 0}, /*2*/
1233 {91.5, 39.0, PathPointTypeLine, 0, 0}, /*3*/
1234 {85.5, 42.8, PathPointTypeLine, 0, 0}, /*4*/
1235 {69.5, 48.0, PathPointTypeLine, 0, 1}, /*5*/
1236 {50.0, 50.0, PathPointTypeLine, 0, 1} /*6*/
1239 static path_test_t flattenquater_path[] = {
1240 {100.0, 50.0,PathPointTypeStart, 0, 0}, /*0*/
1241 {99.0, 60.0, PathPointTypeLine, 0, 0}, /*1*/
1242 {96.0, 69.5, PathPointTypeLine, 0, 0}, /*2*/
1243 {91.5, 78.0, PathPointTypeLine, 0, 0}, /*3*/
1244 {85.5, 85.5, PathPointTypeLine, 0, 0}, /*4*/
1245 {78.0, 91.5, PathPointTypeLine, 0, 0}, /*5*/
1246 {69.5, 96.0, PathPointTypeLine, 0, 0}, /*6*/
1247 {60.0, 99.0, PathPointTypeLine, 0, 0}, /*7*/
1248 {50.0, 100.0,PathPointTypeLine, 0, 0} /*8*/
1251 static void test_flatten(void)
1253 GpStatus status;
1254 GpPath *path;
1255 GpMatrix *m;
1257 status = GdipCreatePath(FillModeAlternate, &path);
1258 expect(Ok, status);
1259 status = GdipCreateMatrix(&m);
1260 expect(Ok, status);
1262 /* NULL arguments */
1263 status = GdipFlattenPath(NULL, NULL, 0.0);
1264 expect(InvalidParameter, status);
1265 status = GdipFlattenPath(NULL, m, 0.0);
1266 expect(InvalidParameter, status);
1268 /* flatten empty path */
1269 status = GdipFlattenPath(path, NULL, 1.0);
1270 expect(Ok, status);
1272 status = GdipTransformPath(path, 0);
1273 expect(Ok, status);
1275 status = GdipAddPathEllipse(path, 0.0, 0.0, 100.0, 50.0);
1276 expect(Ok, status);
1278 status = GdipFlattenPath(path, NULL, 1.0);
1279 expect(Ok, status);
1280 ok_path(path, flattenellipse_path, ARRAY_SIZE(flattenellipse_path), TRUE);
1282 status = GdipResetPath(path);
1283 expect(Ok, status);
1284 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 100.0);
1285 expect(Ok, status);
1286 status = GdipFlattenPath(path, NULL, 1.0);
1287 expect(Ok, status);
1288 ok_path(path, flattenline_path, ARRAY_SIZE(flattenline_path), FALSE);
1290 status = GdipResetPath(path);
1291 expect(Ok, status);
1292 status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 50.0, 0.0, 90.0);
1293 expect(Ok, status);
1294 status = GdipFlattenPath(path, NULL, 1.0);
1295 expect(Ok, status);
1296 ok_path(path, flattenarc_path, ARRAY_SIZE(flattenarc_path), TRUE);
1298 /* easy case - quater of a full circle */
1299 status = GdipResetPath(path);
1300 expect(Ok, status);
1301 status = GdipAddPathArc(path, 0.0, 0.0, 100.0, 100.0, 0.0, 90.0);
1302 expect(Ok, status);
1303 status = GdipFlattenPath(path, NULL, 1.0);
1304 expect(Ok, status);
1305 ok_path(path, flattenquater_path, ARRAY_SIZE(flattenquater_path), FALSE);
1307 status = GdipResetPath(path);
1308 expect(Ok, status);
1309 status = GdipStartPathFigure(path);
1310 expect(Ok, status);
1312 /* path seen in the wild that caused a stack overflow */
1313 /* same path but redo with the manual points that caused a crash */
1314 status = GdipAddPathBezier(path, 154.950806, 33.391144, 221.586075, 15.536285, 291.747314, 15.536285, 358.382568, 33.391144);
1315 expect(Ok, status);
1316 status = GdipAddPathBezier(path, 256.666809, 412.999512, 256.666718, 412.999481, 256.666656, 412.999481, 256.666565, 412.999512);
1317 expect(Ok, status);
1318 status = GdipClosePathFigure(path);
1319 expect(Ok, status);
1320 status = GdipFlattenPath(path, NULL, 1.0);
1321 expect(Ok, status);
1323 GdipDeleteMatrix(m);
1324 GdipDeletePath(path);
1327 static path_test_t widenline_path[] = {
1328 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1329 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1330 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1331 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1334 static path_test_t widenline_wide_path[] = {
1335 {5.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
1336 {50.0, 0.0, PathPointTypeLine, 0, 0}, /*1*/
1337 {50.0, 20.0, PathPointTypeLine, 0, 0}, /*2*/
1338 {5.0, 20.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1341 static path_test_t widenline_dash_path[] = {
1342 {5.0, 0.0, PathPointTypeStart, 0, 0}, /*0*/
1343 {35.0, 0.0, PathPointTypeLine, 0, 0}, /*1*/
1344 {35.0, 10.0, PathPointTypeLine, 0, 0}, /*2*/
1345 {5.0, 10.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1346 {45.0, 0.0, PathPointTypeStart, 0, 0}, /*4*/
1347 {50.0, 0.0, PathPointTypeLine, 0, 0}, /*5*/
1348 {50.0, 10.0, PathPointTypeLine, 0, 0}, /*6*/
1349 {45.0, 10.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1352 static path_test_t widenline_thin_dash_path[] = {
1353 {5.0, 4.75, PathPointTypeStart, 0, 0}, /*0*/
1354 {8.0, 4.75, PathPointTypeLine, 0, 0}, /*1*/
1355 {8.0, 5.25, PathPointTypeLine, 0, 0}, /*2*/
1356 {5.0, 5.25, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1357 {9.0, 4.75, PathPointTypeStart, 0, 0}, /*4*/
1358 {9.5, 4.75, PathPointTypeLine, 0, 0}, /*5*/
1359 {9.5, 5.25, PathPointTypeLine, 0, 0}, /*6*/
1360 {9.0, 5.25, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1363 static path_test_t widenline_unit_path[] = {
1364 {5.0, 9.5, PathPointTypeStart, 0, 0}, /*0*/
1365 {50.0, 9.5, PathPointTypeLine, 0, 0}, /*1*/
1366 {50.0, 10.5, PathPointTypeLine, 0, 0}, /*2*/
1367 {5.0, 10.5, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1370 static void test_widen(void)
1372 GpStatus status;
1373 GpPath *path;
1374 GpPen *pen;
1375 GpMatrix *m;
1376 INT count=-1;
1378 status = GdipCreatePath(FillModeAlternate, &path);
1379 expect(Ok, status);
1380 status = GdipCreatePen1(0xffffffff, 10.0, UnitPixel, &pen);
1381 expect(Ok, status);
1382 status = GdipCreateMatrix(&m);
1383 expect(Ok, status);
1385 /* NULL arguments */
1386 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1387 expect(Ok, status);
1388 status = GdipWidenPath(NULL, NULL, NULL, 0.0);
1389 expect(InvalidParameter, status);
1390 status = GdipWidenPath(path, pen, m, 0.0);
1391 expect(Ok, status);
1392 status = GdipWidenPath(path, pen, NULL, 1.0);
1393 expect(Ok, status);
1394 status = GdipWidenPath(path, NULL, m, 1.0);
1395 expect(InvalidParameter, status);
1396 status = GdipWidenPath(NULL, pen, m, 1.0);
1397 expect(InvalidParameter, status);
1399 /* widen empty path */
1400 status = GdipResetPath(path);
1401 expect(Ok, status);
1402 status = GdipWidenPath(path, pen, m, 1.0);
1403 expect(OutOfMemory, status);
1405 /* horizontal line */
1406 status = GdipResetPath(path);
1407 expect(Ok, status);
1408 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1409 expect(Ok, status);
1411 status = GdipWidenPath(path, pen, m, 1.0);
1412 expect(Ok, status);
1413 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1415 /* horizontal 2x stretch */
1416 status = GdipResetPath(path);
1417 expect(Ok, status);
1418 status = GdipAddPathLine(path, 2.5, 10.0, 25.0, 10.0);
1419 expect(Ok, status);
1421 status = GdipScaleMatrix(m, 2.0, 1.0, MatrixOrderAppend);
1422 expect(Ok, status);
1424 status = GdipWidenPath(path, pen, m, 1.0);
1425 expect(Ok, status);
1426 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1428 /* vertical 2x stretch */
1429 status = GdipResetPath(path);
1430 expect(Ok, status);
1431 status = GdipAddPathLine(path, 5.0, 5.0, 50.0, 5.0);
1432 expect(Ok, status);
1434 status = GdipScaleMatrix(m, 0.5, 2.0, MatrixOrderAppend);
1435 expect(Ok, status);
1437 status = GdipWidenPath(path, pen, m, 1.0);
1438 expect(Ok, status);
1439 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1441 status = GdipScaleMatrix(m, 1.0, 0.5, MatrixOrderAppend);
1442 expect(Ok, status);
1444 /* dashed line */
1445 status = GdipResetPath(path);
1446 expect(Ok, status);
1447 status = GdipAddPathLine(path, 5.0, 5.0, 50.0, 5.0);
1448 expect(Ok, status);
1450 status = GdipSetPenDashStyle(pen, DashStyleDash);
1451 expect(Ok, status);
1453 status = GdipWidenPath(path, pen, m, 1.0);
1454 expect(Ok, status);
1455 ok_path(path, widenline_dash_path, ARRAY_SIZE(widenline_dash_path), FALSE);
1457 status = GdipSetPenDashStyle(pen, DashStyleSolid);
1458 expect(Ok, status);
1460 /* dashed line less than 1 pixel wide */
1461 GdipDeletePen(pen);
1462 GdipCreatePen1(0xffffffff, 0.5, UnitPixel, &pen);
1463 GdipSetPenDashStyle(pen, DashStyleDash);
1465 GdipResetPath(path);
1466 GdipAddPathLine(path, 5.0, 5.0, 9.5, 5.0);
1468 status = GdipWidenPath(path, pen, m, 1.0);
1469 expect(Ok, status);
1470 ok_path_fudge(path, widenline_thin_dash_path, ARRAY_SIZE(widenline_thin_dash_path), FALSE, 0.000005);
1472 /* pen width in UnitWorld */
1473 GdipDeletePen(pen);
1474 status = GdipCreatePen1(0xffffffff, 10.0, UnitWorld, &pen);
1475 expect(Ok, status);
1477 status = GdipResetPath(path);
1478 expect(Ok, status);
1479 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1480 expect(Ok, status);
1482 status = GdipWidenPath(path, pen, m, 1.0);
1483 expect(Ok, status);
1484 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1486 /* horizontal 2x stretch */
1487 status = GdipResetPath(path);
1488 expect(Ok, status);
1489 status = GdipAddPathLine(path, 2.5, 10.0, 25.0, 10.0);
1490 expect(Ok, status);
1492 status = GdipScaleMatrix(m, 2.0, 1.0, MatrixOrderAppend);
1493 expect(Ok, status);
1495 status = GdipWidenPath(path, pen, m, 1.0);
1496 expect(Ok, status);
1497 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1499 /* vertical 2x stretch */
1500 status = GdipResetPath(path);
1501 expect(Ok, status);
1502 status = GdipAddPathLine(path, 5.0, 5.0, 50.0, 5.0);
1503 expect(Ok, status);
1505 status = GdipScaleMatrix(m, 0.5, 2.0, MatrixOrderAppend);
1506 expect(Ok, status);
1508 status = GdipWidenPath(path, pen, m, 1.0);
1509 expect(Ok, status);
1510 ok_path(path, widenline_wide_path, ARRAY_SIZE(widenline_wide_path), FALSE);
1512 status = GdipScaleMatrix(m, 1.0, 0.5, MatrixOrderAppend);
1513 expect(Ok, status);
1515 /* pen width in UnitInch */
1516 GdipDeletePen(pen);
1517 status = GdipCreatePen1(0xffffffff, 10.0, UnitWorld, &pen);
1518 expect(Ok, status);
1520 status = GdipResetPath(path);
1521 expect(Ok, status);
1522 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1523 expect(Ok, status);
1525 status = GdipWidenPath(path, pen, m, 1.0);
1526 expect(Ok, status);
1527 ok_path(path, widenline_path, ARRAY_SIZE(widenline_path), FALSE);
1529 /* pen width = 0 pixels - native fails to widen but can draw with this pen */
1530 GdipDeletePen(pen);
1531 status = GdipCreatePen1(0xffffffff, 0.0, UnitPixel, &pen);
1532 expect(Ok, status);
1534 status = GdipResetPath(path);
1535 expect(Ok, status);
1536 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1537 expect(Ok, status);
1539 status = GdipWidenPath(path, pen, m, 1.0);
1540 expect(Ok, status);
1542 status = GdipGetPointCount(path, &count);
1543 expect(Ok, status);
1544 ok(count == 0 || broken(count == 4), "expected 0, got %i\n", count);
1546 /* pen width = 0 pixels, UnitWorld - result is a path 1 unit wide */
1547 GdipDeletePen(pen);
1548 status = GdipCreatePen1(0xffffffff, 0.0, UnitWorld, &pen);
1549 expect(Ok, status);
1551 status = GdipResetPath(path);
1552 expect(Ok, status);
1553 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1554 expect(Ok, status);
1556 status = GdipWidenPath(path, pen, m, 1.0);
1557 expect(Ok, status);
1559 status = GdipGetPointCount(path, &count);
1560 expect(Ok, status);
1561 ok_path_fudge(path, widenline_unit_path, ARRAY_SIZE(widenline_unit_path), FALSE, 0.000005);
1563 GdipDeleteMatrix(m);
1564 GdipDeletePen(pen);
1565 GdipDeletePath(path);
1568 static path_test_t widenline_capflat_path[] = {
1569 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1570 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1571 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1572 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1575 static path_test_t widenline_capsquare_path[] = {
1576 {0.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1577 {55.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1578 {55.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1579 {0.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*3*/
1582 static path_test_t widenline_capround_path[] = {
1583 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1584 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1585 {52.761421, 5.0, PathPointTypeBezier, 0, 0}, /*2*/
1586 {55.0, 7.238576, PathPointTypeBezier, 0, 0}, /*3*/
1587 {55.0, 10.0, PathPointTypeBezier, 0, 0}, /*4*/
1588 {55.0, 12.761423, PathPointTypeBezier, 0, 0}, /*5*/
1589 {52.761421, 15.0, PathPointTypeBezier, 0, 0}, /*6*/
1590 {50.0, 15.0, PathPointTypeBezier, 0, 0}, /*7*/
1591 {5.0, 15.0, PathPointTypeLine, 0, 0}, /*8*/
1592 {2.238576, 15.0, PathPointTypeBezier, 0, 0}, /*9*/
1593 {0.0, 12.761423, PathPointTypeBezier, 0, 0}, /*10*/
1594 {0.0, 10.0, PathPointTypeBezier, 0, 0}, /*11*/
1595 {0.0, 7.238576, PathPointTypeBezier, 0, 0}, /*12*/
1596 {2.238576, 5.0, PathPointTypeBezier, 0, 0}, /*13*/
1597 {5.0, 5.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*14*/
1600 static path_test_t widenline_captriangle_path[] = {
1601 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1602 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1603 {55.0, 10.0, PathPointTypeLine, 0, 0}, /*2*/
1604 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*3*/
1605 {5.0, 15.0, PathPointTypeLine, 0, 0}, /*4*/
1606 {0.0, 10.0, PathPointTypeLine, 0, 0}, /*5*/
1607 {5.0, 5.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0} /*6*/
1610 static path_test_t widenline_capsquareanchor_path[] = {
1611 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1612 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1613 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1614 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1615 {12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*4*/
1616 {12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*5*/
1617 {-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*6*/
1618 {-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1619 {42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*8*/
1620 {42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*9*/
1621 {57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*10*/
1622 {57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
1625 static path_test_t widenline_caproundanchor_path[] = {
1626 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1627 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1628 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1629 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1630 {5.0, 20.0, PathPointTypeStart, 0, 0}, /*4*/
1631 {-0.522847, 20.0, PathPointTypeBezier, 0, 0}, /*5*/
1632 {-5.0, 15.522846, PathPointTypeBezier, 0, 0}, /*6*/
1633 {-5.0, 10.0, PathPointTypeBezier, 0, 0}, /*7*/
1634 {-5.0, 4.477152, PathPointTypeBezier, 0, 0}, /*8*/
1635 {-0.522847, 0.0, PathPointTypeBezier, 0, 0}, /*9*/
1636 {5.0, 0.0, PathPointTypeBezier, 0, 0}, /*10*/
1637 {10.522847, 0.0, PathPointTypeBezier, 0, 0}, /*11*/
1638 {15.0, 4.477152, PathPointTypeBezier, 0, 0}, /*12*/
1639 {15.0, 10.0, PathPointTypeBezier, 0, 0}, /*13*/
1640 {15.0, 15.522846, PathPointTypeBezier, 0, 0}, /*14*/
1641 {10.522847, 20.0, PathPointTypeBezier, 0, 0}, /*15*/
1642 {5.0, 20.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*16*/
1643 {50.0, 0.0, PathPointTypeStart, 0, 0}, /*17*/
1644 {55.522846, 0.0, PathPointTypeBezier, 0, 0}, /*18*/
1645 {60.0, 4.477153, PathPointTypeBezier, 0, 0}, /*19*/
1646 {60.0, 10.0, PathPointTypeBezier, 0, 0}, /*20*/
1647 {60.0, 15.522847, PathPointTypeBezier, 0, 0}, /*21*/
1648 {55.522846, 20.0, PathPointTypeBezier, 0, 0}, /*22*/
1649 {50.0, 20.0, PathPointTypeBezier, 0, 0}, /*23*/
1650 {44.477150, 20.0, PathPointTypeBezier, 0, 0}, /*24*/
1651 {40.0, 15.522847, PathPointTypeBezier, 0, 0}, /*25*/
1652 {40.0, 10.0, PathPointTypeBezier, 0, 0}, /*26*/
1653 {40.0, 4.477153, PathPointTypeBezier, 0, 0}, /*27*/
1654 {44.477150, 0.0, PathPointTypeBezier, 0, 0}, /*28*/
1655 {50.0, 0.0, PathPointTypeBezier|PathPointTypeCloseSubpath, 0, 0}, /*29*/
1658 static path_test_t widenline_capdiamondanchor_path[] = {
1659 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1660 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1661 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1662 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1663 {-5.0, 10.0, PathPointTypeStart, 0, 0}, /*4*/
1664 {5.0, 0.0, PathPointTypeLine, 0, 0}, /*5*/
1665 {15.0, 10.0, PathPointTypeLine, 0, 0}, /*6*/
1666 {5.0, 20.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1667 {60.0, 10.0, PathPointTypeStart, 0, 0}, /*8*/
1668 {50.0, 20.0, PathPointTypeLine, 0, 0}, /*9*/
1669 {40.0, 10.0, PathPointTypeLine, 0, 0}, /*10*/
1670 {50.0, 0.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
1673 static path_test_t widenline_caparrowanchor_path[] = {
1674 {15.0, 5.0, PathPointTypeStart, 0, 1}, /*0*/
1675 {40.0, 5.0, PathPointTypeLine, 0, 1}, /*1*/
1676 {40.0, 15.0, PathPointTypeLine, 0, 1}, /*2*/
1677 {15.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 1}, /*3*/
1678 {5.0, 10.0, PathPointTypeStart, 0, 0}, /*4*/
1679 {22.320507, 0.0, PathPointTypeLine, 0, 0}, /*5*/
1680 {22.320507, 20.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*6*/
1681 {50.0, 10.0, PathPointTypeStart, 0, 0}, /*7*/
1682 {32.679489, 20.0, PathPointTypeLine, 0, 0}, /*8*/
1683 {32.679489, 0.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*9*/
1686 static path_test_t widenline_capsquareanchor_thin_path[] = {
1687 {6.414213, 8.585786, PathPointTypeStart, 0, 0}, /*0*/
1688 {6.414213, 11.414213, PathPointTypeLine, 0, 0}, /*1*/
1689 {3.585786, 11.414213, PathPointTypeLine, 0, 0}, /*2*/
1690 {3.585786, 8.585786, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1691 {48.585785, 11.414213, PathPointTypeStart, 0, 0}, /*4*/
1692 {48.585785, 8.585786, PathPointTypeLine, 0, 0}, /*5*/
1693 {51.414211, 8.585786, PathPointTypeLine, 0, 0}, /*6*/
1694 {51.414211, 11.414213, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1697 static path_test_t widenline_capsquareanchor_dashed_path[] = {
1698 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1699 {35.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1700 {35.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1701 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1702 {45.0, 5.0, PathPointTypeStart, 0, 0}, /*4*/
1703 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*5*/
1704 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*6*/
1705 {45.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1706 {12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*8*/
1707 {12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*9*/
1708 {-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*10*/
1709 {-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
1710 {42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*12*/
1711 {42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*13*/
1712 {57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*14*/
1713 {57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*15*/
1716 static path_test_t widenline_capsquareanchor_multifigure_path[] = {
1717 {5.0, 5.0, PathPointTypeStart, 0, 0}, /*0*/
1718 {25.0, 5.0, PathPointTypeLine, 0, 0}, /*1*/
1719 {25.0, 15.0, PathPointTypeLine, 0, 0}, /*2*/
1720 {5.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*3*/
1721 {30.0, 5.0, PathPointTypeStart, 0, 0}, /*4*/
1722 {50.0, 5.0, PathPointTypeLine, 0, 0}, /*5*/
1723 {50.0, 15.0, PathPointTypeLine, 0, 0}, /*6*/
1724 {30.0, 15.0, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*7*/
1725 {12.071068, 2.928932, PathPointTypeStart, 0, 0}, /*8*/
1726 {12.071068, 17.071066, PathPointTypeLine, 0, 0}, /*9*/
1727 {-2.071068, 17.071066, PathPointTypeLine, 0, 0}, /*10*/
1728 {-2.071068, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*11*/
1729 {17.928930, 17.071068, PathPointTypeStart, 0, 0}, /*12*/
1730 {17.928930, 2.928932, PathPointTypeLine, 0, 0}, /*13*/
1731 {32.071068, 2.928932, PathPointTypeLine, 0, 0}, /*14*/
1732 {32.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*15*/
1733 {37.071068, 2.928932, PathPointTypeStart, 0, 0}, /*16*/
1734 {37.071068, 17.071066, PathPointTypeLine, 0, 0}, /*17*/
1735 {22.928930, 17.071066, PathPointTypeLine, 0, 0}, /*18*/
1736 {22.928930, 2.928932, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*19*/
1737 {42.928928, 17.071068, PathPointTypeStart, 0, 0}, /*20*/
1738 {42.928928, 2.928932, PathPointTypeLine, 0, 0}, /*21*/
1739 {57.071068, 2.928932, PathPointTypeLine, 0, 0}, /*22*/
1740 {57.071068, 17.071068, PathPointTypeLine|PathPointTypeCloseSubpath, 0, 0}, /*23*/
1743 static void test_widen_cap(void)
1745 struct
1747 LineCap type;
1748 REAL line_width;
1749 const path_test_t *expected;
1750 INT expected_size;
1751 BOOL dashed;
1753 caps[] =
1755 { LineCapFlat, 10.0, widenline_capflat_path,
1756 ARRAY_SIZE(widenline_capflat_path) },
1757 { LineCapSquare, 10.0, widenline_capsquare_path,
1758 ARRAY_SIZE(widenline_capsquare_path) },
1759 { LineCapRound, 10.0, widenline_capround_path,
1760 ARRAY_SIZE(widenline_capround_path) },
1761 { LineCapTriangle, 10.0, widenline_captriangle_path,
1762 ARRAY_SIZE(widenline_captriangle_path) },
1763 { LineCapNoAnchor, 10.0, widenline_capflat_path,
1764 ARRAY_SIZE(widenline_capflat_path) },
1765 { LineCapSquareAnchor, 10.0, widenline_capsquareanchor_path,
1766 ARRAY_SIZE(widenline_capsquareanchor_path) },
1767 { LineCapRoundAnchor, 10.0, widenline_caproundanchor_path,
1768 ARRAY_SIZE(widenline_caproundanchor_path) },
1769 { LineCapDiamondAnchor, 10.0, widenline_capdiamondanchor_path,
1770 ARRAY_SIZE(widenline_capdiamondanchor_path) },
1771 { LineCapArrowAnchor, 10.0, widenline_caparrowanchor_path,
1772 ARRAY_SIZE(widenline_caparrowanchor_path) },
1773 { LineCapSquareAnchor, 0.0, widenline_capsquareanchor_thin_path,
1774 ARRAY_SIZE(widenline_capsquareanchor_thin_path) },
1775 { LineCapSquareAnchor, 10.0, widenline_capsquareanchor_dashed_path,
1776 ARRAY_SIZE(widenline_capsquareanchor_dashed_path), TRUE },
1779 GpAdjustableArrowCap *arrowcap;
1780 GpStatus status;
1781 GpPath *path;
1782 GpPen *pen;
1784 int i;
1786 status = GdipCreatePath(FillModeAlternate, &path);
1787 expect(Ok, status);
1789 for (i = 0; i < ARRAY_SIZE(caps); i++)
1791 status = GdipCreatePen1(0xffffffff, caps[i].line_width, UnitPixel, &pen);
1792 expect(Ok, status);
1793 if (caps[i].dashed)
1795 status = GdipSetPenDashStyle(pen, DashStyleDash);
1796 expect(Ok, status);
1799 status = GdipResetPath(path);
1800 expect(Ok, status);
1801 status = GdipAddPathLine(path, 5.0, 10.0, 50.0, 10.0);
1802 expect(Ok, status);
1803 status = GdipSetPenStartCap(pen, caps[i].type);
1804 expect(Ok, status);
1805 status = GdipSetPenEndCap(pen, caps[i].type);
1806 expect(Ok, status);
1808 status = GdipWidenPath(path, pen, NULL, FlatnessDefault);
1809 expect(Ok, status);
1811 if (i == 9)
1813 INT size;
1814 status = GdipGetPointCount(path, &size);
1815 expect(Ok, status);
1816 ok(size == caps[i].expected_size || broken(size == 12), "unexpected path size %i\n", size);
1818 if (size == 12)
1820 GdipDeletePen(pen);
1821 continue;
1825 ok_path_fudge(path, caps[i].expected, caps[i].expected_size, FALSE, 0.000005);
1827 GdipDeletePen(pen);
1830 status = GdipCreatePen1(0xffffffff, 10.0, UnitPixel, &pen);
1831 expect(Ok, status);
1832 status = GdipResetPath(path);
1833 expect(Ok, status);
1834 status = GdipAddPathLine(path, 5.0, 10.0, 25.0, 10.0);
1835 expect(Ok, status);
1836 status = GdipStartPathFigure(path);
1837 expect(Ok, status);
1838 status = GdipAddPathLine(path, 30.0, 10.0, 50.0, 10.0);
1839 expect(Ok, status);
1840 status = GdipSetPenStartCap(pen, LineCapSquareAnchor);
1841 expect(Ok, status);
1842 status = GdipSetPenEndCap(pen, LineCapSquareAnchor);
1843 expect(Ok, status);
1844 status = GdipWidenPath(path, pen, NULL, FlatnessDefault);
1845 expect(Ok, status);
1846 ok_path_fudge(path, widenline_capsquareanchor_multifigure_path,
1847 ARRAY_SIZE(widenline_capsquareanchor_multifigure_path), FALSE, 0.000005);
1849 status = GdipCreateAdjustableArrowCap(4.0, 4.0, TRUE, &arrowcap);
1850 ok(status == Ok, "Failed to create adjustable cap, %d\n", status);
1851 status = GdipSetAdjustableArrowCapMiddleInset(arrowcap, 1.0);
1852 ok(status == Ok, "Failed to set middle inset inadjustable cap, %d\n", status);
1853 status = GdipSetPenCustomEndCap(pen, (GpCustomLineCap*)arrowcap);
1854 ok(status == Ok, "Failed to create custom end cap, %d\n", status);
1855 status = GdipWidenPath(path, pen, NULL, FlatnessDefault);
1856 expect(Ok, status);
1858 GdipDeletePen(pen);
1860 GdipDeletePath(path);
1863 static void test_isvisible(void)
1865 GpPath *path;
1866 GpGraphics *graphics = NULL;
1867 HDC hdc = GetDC(0);
1868 BOOL result;
1869 GpStatus status;
1871 status = GdipCreateFromHDC(hdc, &graphics);
1872 expect(Ok, status);
1873 status = GdipCreatePath(FillModeAlternate, &path);
1874 expect(Ok, status);
1876 /* NULL */
1877 status = GdipIsVisiblePathPoint(NULL, 0.0, 0.0, NULL, NULL);
1878 expect(InvalidParameter, status);
1879 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, NULL);
1880 expect(InvalidParameter, status);
1881 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, NULL);
1882 expect(InvalidParameter, status);
1883 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, graphics, NULL);
1884 expect(InvalidParameter, status);
1886 /* empty path */
1887 result = TRUE;
1888 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, &result);
1889 expect(Ok, status);
1890 expect(FALSE, result);
1891 /* rect */
1892 status = GdipAddPathRectangle(path, 0.0, 0.0, 10.0, 10.0);
1893 expect(Ok, status);
1894 result = FALSE;
1895 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, NULL, &result);
1896 expect(Ok, status);
1897 expect(TRUE, result);
1898 result = TRUE;
1899 status = GdipIsVisiblePathPoint(path, 11.0, 11.0, NULL, &result);
1900 expect(Ok, status);
1901 expect(FALSE, result);
1902 /* not affected by clipping */
1903 status = GdipSetClipRect(graphics, 5.0, 5.0, 5.0, 5.0, CombineModeReplace);
1904 expect(Ok, status);
1905 result = FALSE;
1906 status = GdipIsVisiblePathPoint(path, 0.0, 0.0, graphics, &result);
1907 expect(Ok, status);
1908 expect(TRUE, result);
1909 /* not affected by world transform */
1910 status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
1911 expect(Ok, status);
1912 result = FALSE;
1913 status = GdipIsVisiblePathPoint(path, 9.0, 9.0, graphics, &result);
1914 expect(Ok, status);
1915 expect(TRUE, result);
1916 result = TRUE;
1917 status = GdipIsVisiblePathPoint(path, 11.0, 11.0, graphics, &result);
1918 expect(Ok, status);
1919 expect(FALSE, result);
1920 GdipResetWorldTransform(graphics);
1922 GdipDeletePath(path);
1923 GdipDeleteGraphics(graphics);
1924 ReleaseDC(0, hdc);
1927 static void test_is_outline_visible_path_point(void)
1929 BOOL result;
1930 GpBitmap *bitmap;
1931 GpGraphics *graphics = NULL;
1932 GpPath *path;
1933 GpPen *pen = NULL;
1934 GpStatus status;
1935 static const int width = 20, height = 20;
1937 /* Graphics associated with an Image object.*/
1938 status = GdipCreateBitmapFromScan0(width, height, 0, PixelFormat32bppRGB, NULL, &bitmap);
1939 expect(Ok, status);
1940 status = GdipGetImageGraphicsContext((GpImage *)bitmap, &graphics);
1941 expect(Ok, status);
1942 ok(graphics != NULL, "Expected the graphics context to be initialized.\n");
1944 status = GdipCreatePath(FillModeAlternate, &path);
1945 expect(Ok, status);
1947 status = GdipAddPathRectangle(path, 2.0, 0.0, 13.0, 15.0);
1948 expect(Ok, status);
1950 status = GdipCreatePen1((ARGB)0xffff00ff, 3.0f, UnitPixel, &pen);
1951 expect(Ok, status);
1952 ok(pen != NULL, "Expected pen to be initialized\n");
1954 /* With NULL pen */
1955 result = 9;
1956 status = GdipIsOutlineVisiblePathPoint(path, 0.0, 1.0, NULL, graphics, &result);
1957 expect(InvalidParameter, status);
1958 expect(9, result);
1960 /* Without transformation */
1961 result = TRUE;
1962 status = GdipIsOutlineVisiblePathPoint(path, 0.0, 1.0, pen, graphics, &result);
1963 expect(Ok, status);
1964 expect(FALSE, result);
1965 result = FALSE;
1966 status = GdipIsOutlineVisiblePathPoint(path, 1.0, 1.0, pen, graphics, &result);
1967 expect(Ok, status);
1968 expect(TRUE, result);
1969 result = FALSE;
1970 status = GdipIsOutlineVisiblePathPoint(path, 10.0, 1.0, pen, graphics, &result);
1971 expect(Ok, status);
1972 expect(TRUE, result);
1973 result = FALSE;
1974 status = GdipIsOutlineVisiblePathPoint(path, 16.0, 1.0, pen, graphics, &result);
1975 expect(Ok, status);
1976 expect(TRUE, result);
1977 result = TRUE;
1978 status = GdipIsOutlineVisiblePathPoint(path, 17.0, 1.0, pen, graphics, &result);
1979 expect(Ok, status);
1980 expect(FALSE, result);
1982 /* Translating */
1983 status = GdipTranslateWorldTransform(graphics, 50.0, 50.0, MatrixOrderPrepend);
1984 expect(Ok, status);
1985 result = FALSE;
1986 status = GdipIsOutlineVisiblePathPoint(path, 10.0, 1.0, pen, graphics, &result);
1987 expect(Ok, status);
1988 expect(TRUE, result);
1989 result = FALSE;
1990 status = GdipIsOutlineVisiblePathPoint(path, 15.0, 1.0, pen, graphics, &result);
1991 expect(Ok, status);
1992 expect(TRUE, result);
1993 result = FALSE;
1994 status = GdipIsOutlineVisiblePathPoint(path, 16.0, 1.0, pen, graphics, &result);
1995 expect(Ok, status);
1996 expect(TRUE, result);
1998 /* Scaling */
1999 status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderPrepend);
2000 expect(Ok, status);
2001 result = TRUE;
2002 status = GdipIsOutlineVisiblePathPoint(path, 0.0, 1.0, pen, graphics, &result);
2003 expect(Ok, status);
2004 expect(FALSE, result);
2005 result = TRUE;
2006 status = GdipIsOutlineVisiblePathPoint(path, 1.0, 1.0, pen, graphics, &result);
2007 expect(Ok, status);
2008 expect(FALSE, result);
2009 result = FALSE;
2010 status = GdipIsOutlineVisiblePathPoint(path, 2.0, 1.0, pen, graphics, &result);
2011 expect(Ok, status);
2012 expect(TRUE, result);
2013 result = TRUE;
2014 status = GdipIsOutlineVisiblePathPoint(path, 3.0, 1.0, pen, graphics, &result);
2015 expect(Ok, status);
2016 expect(FALSE, result);
2017 result = TRUE;
2018 status = GdipIsOutlineVisiblePathPoint(path, 14.0, 1.0, pen, graphics, &result);
2019 expect(Ok, status);
2020 expect(FALSE, result);
2021 result = FALSE;
2022 status = GdipIsOutlineVisiblePathPoint(path, 15.0, 1.0, pen, graphics, &result);
2023 expect(Ok, status);
2024 expect(TRUE, result);
2025 result = TRUE;
2026 status = GdipIsOutlineVisiblePathPoint(path, 16.0, 1.0, pen, graphics, &result);
2027 expect(Ok, status);
2028 expect(FALSE, result);
2030 /* Page Unit */
2031 GdipResetWorldTransform(graphics);
2032 status = GdipSetPageUnit(graphics, UnitMillimeter);
2033 expect(Ok, status);
2034 result = TRUE;
2035 status = GdipIsOutlineVisiblePathPoint(path, 0.0, 1.0, pen, graphics, &result);
2036 expect(Ok, status);
2037 expect(FALSE, result);
2038 result = TRUE;
2039 status = GdipIsOutlineVisiblePathPoint(path, 1.0, 1.0, pen, graphics, &result);
2040 expect(Ok, status);
2041 expect(FALSE, result);
2042 result = FALSE;
2043 status = GdipIsOutlineVisiblePathPoint(path, 2.0, 1.0, pen, graphics, &result);
2044 expect(Ok, status);
2045 expect(TRUE, result);
2046 result = TRUE;
2047 status = GdipIsOutlineVisiblePathPoint(path, 3.0, 1.0, pen, graphics, &result);
2048 expect(Ok, status);
2049 expect(FALSE, result);
2050 result = TRUE;
2051 status = GdipIsOutlineVisiblePathPoint(path, 14.0, 1.0, pen, graphics, &result);
2052 expect(Ok, status);
2053 expect(FALSE, result);
2054 result = FALSE;
2055 status = GdipIsOutlineVisiblePathPoint(path, 15.0, 1.0, pen, graphics, &result);
2056 expect(Ok, status);
2057 expect(TRUE, result);
2058 result = TRUE;
2059 status = GdipIsOutlineVisiblePathPoint(path, 16.0, 1.0, pen, graphics, &result);
2060 expect(Ok, status);
2061 expect(FALSE, result);
2063 GdipResetWorldTransform(graphics);
2064 GdipDeletePath(path);
2065 GdipDeleteGraphics(graphics);
2068 static void test_empty_rect(void)
2070 GpPath *path;
2071 GpStatus status;
2072 INT count;
2073 BOOL result;
2075 status = GdipCreatePath(FillModeAlternate, &path);
2076 expect(Ok, status);
2078 status = GdipAddPathRectangle(path, 0.0, 0.0, -5.0, 5.0);
2079 expect(Ok, status);
2081 status = GdipGetPointCount(path, &count);
2082 expect(Ok, status);
2083 expect(0, count);
2085 status = GdipIsVisiblePathPoint(path, -2.0, 2.0, NULL, &result);
2086 expect(Ok, status);
2087 expect(FALSE, result);
2089 status = GdipAddPathRectangle(path, 0.0, 0.0, 5.0, -5.0);
2090 expect(Ok, status);
2092 status = GdipGetPointCount(path, &count);
2093 expect(Ok, status);
2094 expect(0, count);
2096 status = GdipAddPathRectangle(path, 0.0, 0.0, 0.0, 5.0);
2097 expect(Ok, status);
2099 status = GdipGetPointCount(path, &count);
2100 expect(Ok, status);
2101 expect(0, count);
2103 status = GdipAddPathRectangle(path, 0.0, 0.0, 5.0, 0.0);
2104 expect(Ok, status);
2106 status = GdipGetPointCount(path, &count);
2107 expect(Ok, status);
2108 expect(0, count);
2110 status = GdipAddPathRectangle(path, 0.0, 0.0, 5.0, 0.1);
2111 expect(Ok, status);
2113 status = GdipGetPointCount(path, &count);
2114 expect(Ok, status);
2115 expect(4, count);
2117 GdipDeletePath(path);
2120 START_TEST(graphicspath)
2122 struct GdiplusStartupInput gdiplusStartupInput;
2123 ULONG_PTR gdiplusToken;
2124 HMODULE hmsvcrt;
2125 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
2127 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
2128 hmsvcrt = LoadLibraryA("msvcrt");
2129 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
2130 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
2132 gdiplusStartupInput.GdiplusVersion = 1;
2133 gdiplusStartupInput.DebugEventCallback = NULL;
2134 gdiplusStartupInput.SuppressBackgroundThread = 0;
2135 gdiplusStartupInput.SuppressExternalCodecs = 0;
2137 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
2139 test_constructor_destructor();
2140 test_getpathdata();
2141 test_createpath2();
2142 test_line2();
2143 test_bezier();
2144 test_beziers();
2145 test_arc();
2146 test_worldbounds();
2147 test_pathpath();
2148 test_ellipse();
2149 test_linei();
2150 test_rect();
2151 test_polygon();
2152 test_lastpoint();
2153 test_addcurve();
2154 test_addclosedcurve();
2155 test_reverse();
2156 test_addpie();
2157 test_flatten();
2158 test_widen();
2159 test_widen_cap();
2160 test_isvisible();
2161 test_is_outline_visible_path_point();
2162 test_empty_rect();
2164 GdiplusShutdown(gdiplusToken);