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 } 1366