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