1 /* 2 * Unit test suite for pens (and init) 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(got - expected) < 0.1, "Expected %.2f, got %.2f\n", expected, got) 25 26 static void test_startup(void) 27 { 28 GpPen *pen = NULL; 29 Status status; 30 struct GdiplusStartupInput gdiplusStartupInput; 31 ULONG_PTR gdiplusToken; 32 int gpversion; 33 34 gdiplusStartupInput.DebugEventCallback = NULL; 35 gdiplusStartupInput.SuppressBackgroundThread = 0; 36 gdiplusStartupInput.SuppressExternalCodecs = 0; 37 38 for (gpversion=1; gpversion<256; gpversion++) 39 { 40 gdiplusStartupInput.GdiplusVersion = gpversion; 41 status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 42 ok(status == Ok || status == UnsupportedGdiplusVersion, 43 "GdiplusStartup returned %x\n", status); 44 GdiplusShutdown(gdiplusToken); 45 if (status != Ok) 46 { 47 gpversion--; 48 break; 49 } 50 } 51 52 ok(gpversion > 0 && gpversion <= 2, "unexpected gdiplus version %i\n", gpversion); 53 trace("gdiplus version is %i\n", gpversion); 54 55 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); 56 57 todo_wine 58 expect(GdiplusNotInitialized, status); 59 60 GdipDeletePen(pen); 61 } 62 63 static void test_constructor_destructor(void) 64 { 65 GpStatus status; 66 GpPen *pen = NULL; 67 68 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, NULL); 69 expect(InvalidParameter, status); 70 ok(pen == NULL, "Expected pen to be NULL\n"); 71 72 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); 73 expect(Ok, status); 74 ok(pen != NULL, "Expected pen to be initialized\n"); 75 76 status = GdipDeletePen(NULL); 77 expect(InvalidParameter, status); 78 79 status = GdipDeletePen(pen); 80 expect(Ok, status); 81 } 82 83 static void test_constructor_destructor2(void) 84 { 85 GpStatus status; 86 GpPen *pen = NULL; 87 GpBrush *brush = NULL; 88 GpPointF points[2]; 89 90 status = GdipCreatePen2(NULL, 10.0f, UnitPixel, &pen); 91 expect(InvalidParameter, status); 92 ok(pen == NULL, "Expected pen to be NULL\n"); 93 94 points[0].X = 7.0; 95 points[0].Y = 11.0; 96 points[1].X = 13.0; 97 points[1].Y = 17.0; 98 99 status = GdipCreateLineBrush(&points[0], &points[1], (ARGB)0xffff00ff, 100 (ARGB)0xff0000ff, WrapModeTile, (GpLineGradient **)&brush); 101 expect(Ok, status); 102 ok(brush != NULL, "Expected brush to be initialized\n"); 103 104 status = GdipCreatePen2(brush, 10.0f, UnitPixel, &pen); 105 expect(Ok, status); 106 ok(pen != NULL, "Expected pen to be initialized\n"); 107 108 status = GdipDeletePen(pen); 109 expect(Ok, status); 110 111 status = GdipDeleteBrush(brush); 112 expect(Ok, status); 113 } 114 115 static void test_brushfill(void) 116 { 117 GpStatus status; 118 GpPen *pen; 119 GpBrush *brush, *brush2; 120 GpBrushType type; 121 ARGB color = 0; 122 123 /* default solid */ 124 GdipCreatePen1(0xdeadbeef, 4.5, UnitWorld, &pen); 125 status = GdipGetPenBrushFill(pen, &brush); 126 expect(Ok, status); 127 GdipGetBrushType(brush, &type); 128 expect(BrushTypeSolidColor, type); 129 GdipGetPenColor(pen, &color); 130 expect(0xdeadbeef, color); 131 GdipDeleteBrush(brush); 132 133 /* color controlled by brush */ 134 GdipCreateSolidFill(0xabaddeed, (GpSolidFill**)&brush); 135 status = GdipSetPenBrushFill(pen, brush); 136 expect(Ok, status); 137 GdipGetPenColor(pen, &color); 138 expect(0xabaddeed, color); 139 GdipDeleteBrush(brush); 140 color = 0; 141 142 /* get returns a clone, not a reference */ 143 GdipGetPenBrushFill(pen, &brush); 144 GdipSetSolidFillColor((GpSolidFill*)brush, 0xbeadfeed); 145 GdipGetPenBrushFill(pen, &brush2); 146 ok(brush != brush2, "Expected to get a clone, not a copy of the reference\n"); 147 GdipGetSolidFillColor((GpSolidFill*)brush2, &color); 148 expect(0xabaddeed, color); 149 GdipDeleteBrush(brush); 150 GdipDeleteBrush(brush2); 151 152 /* brush cannot be NULL */ 153 status = GdipSetPenBrushFill(pen, NULL); 154 expect(InvalidParameter, status); 155 156 GdipDeletePen(pen); 157 } 158 159 static void test_dasharray(void) 160 { 161 GpPen *pen; 162 GpDashStyle style; 163 GpStatus status; 164 REAL dashes[12]; 165 166 GdipCreatePen1(0xdeadbeef, 10.0, UnitWorld, &pen); 167 dashes[0] = 10.0; 168 dashes[1] = 11.0; 169 dashes[2] = 12.0; 170 dashes[3] = 13.0; 171 dashes[4] = 14.0; 172 dashes[5] = -100.0; 173 dashes[6] = -100.0; 174 dashes[7] = dashes[8] = dashes[9] = dashes[10] = dashes[11] = 0.0; 175 176 /* setting the array sets the type to custom */ 177 GdipGetPenDashStyle(pen, &style); 178 expect(DashStyleSolid, style); 179 status = GdipSetPenDashArray(pen, dashes, 2); 180 expect(Ok, status); 181 GdipGetPenDashStyle(pen, &style); 182 expect(DashStyleCustom, style); 183 184 /* Getting the array on a non-custom pen returns invalid parameter (unless 185 * you are getting 0 elements).*/ 186 GdipSetPenDashStyle(pen, DashStyleSolid); 187 status = GdipGetPenDashArray(pen, &dashes[5], 2); 188 expect(InvalidParameter, status); 189 status = GdipGetPenDashArray(pen, &dashes[5], 0); 190 expect(Ok, status); 191 192 /* What does setting DashStyleCustom do to the array length? */ 193 GdipSetPenDashArray(pen, dashes, 2); 194 GdipSetPenDashStyle(pen, DashStyleCustom); 195 status = GdipGetPenDashArray(pen, &dashes[5], 2); 196 expect(Ok, status); 197 expectf(10.0, dashes[5]); 198 expectf(11.0, dashes[6]); 199 200 /* Set the array, then get with different sized buffers. */ 201 status = GdipSetPenDashArray(pen, dashes, 5); 202 expect(Ok, status); 203 dashes[5] = -100.0; 204 dashes[6] = -100.0; 205 status = GdipGetPenDashArray(pen, &dashes[5], 1); 206 expect(Ok, status); /* not InsufficientBuffer! */ 207 expectf(10.0, dashes[5]); 208 expectf(-100.0, dashes[6]); 209 dashes[5] = -100.0; 210 status = GdipGetPenDashArray(pen, &dashes[5], 6); 211 expect(InvalidParameter, status); /* not Ok! */ 212 expectf(-100.0, dashes[5]); 213 expectf(-100.0, dashes[6]); 214 215 /* Some invalid array values. */ 216 status = GdipSetPenDashArray(pen, &dashes[7], 5); 217 expect(InvalidParameter, status); 218 dashes[9] = -1.0; 219 status = GdipSetPenDashArray(pen, &dashes[7], 5); 220 expect(InvalidParameter, status); 221 222 /* Try to set with count = 0. */ 223 GdipSetPenDashStyle(pen, DashStyleDot); 224 if (0) /* corrupts stack on 64-bit Vista */ 225 { 226 status = GdipSetPenDashArray(pen, dashes, 0); 227 ok(status == OutOfMemory || status == InvalidParameter, 228 "Expected OutOfMemory or InvalidParameter, got %.8x\n", status); 229 } 230 status = GdipSetPenDashArray(pen, dashes, -1); 231 ok(status == OutOfMemory || status == InvalidParameter, 232 "Expected OutOfMemory or InvalidParameter, got %.8x\n", status); 233 GdipGetPenDashStyle(pen, &style); 234 expect(DashStyleDot, style); 235 236 GdipDeletePen(pen); 237 } 238 239 static void test_customcap(void) 240 { 241 GpPen *pen; 242 GpStatus status; 243 GpCustomLineCap *custom; 244 245 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); 246 expect(Ok, status); 247 248 /* NULL args */ 249 status = GdipGetPenCustomStartCap(NULL, NULL); 250 expect(InvalidParameter, status); 251 status = GdipGetPenCustomStartCap(pen, NULL); 252 expect(InvalidParameter, status); 253 status = GdipGetPenCustomStartCap(NULL, &custom); 254 expect(InvalidParameter, status); 255 256 status = GdipGetPenCustomEndCap(NULL, NULL); 257 expect(InvalidParameter, status); 258 status = GdipGetPenCustomEndCap(pen, NULL); 259 expect(InvalidParameter, status); 260 status = GdipGetPenCustomEndCap(NULL, &custom); 261 expect(InvalidParameter, status); 262 263 /* native crashes on pen == NULL, custom != NULL */ 264 status = GdipSetPenCustomStartCap(NULL, NULL); 265 expect(InvalidParameter, status); 266 status = GdipSetPenCustomStartCap(pen, NULL); 267 expect(InvalidParameter, status); 268 269 status = GdipSetPenCustomEndCap(NULL, NULL); 270 expect(InvalidParameter, status); 271 status = GdipSetPenCustomEndCap(pen, NULL); 272 expect(InvalidParameter, status); 273 274 /* get without setting previously */ 275 custom = (GpCustomLineCap*)0xdeadbeef; 276 status = GdipGetPenCustomEndCap(pen, &custom); 277 expect(Ok, status); 278 ok(custom == NULL,"Expect CustomCap == NULL\n"); 279 280 custom = (GpCustomLineCap*)0xdeadbeef; 281 status = GdipGetPenCustomStartCap(pen, &custom); 282 expect(Ok, status); 283 ok(custom == NULL,"Expect CustomCap == NULL\n"); 284 285 GdipDeletePen(pen); 286 } 287 288 static void test_penfilltype(void) 289 { 290 GpPen *pen; 291 GpSolidFill *solid; 292 GpLineGradient *line; 293 GpPointF a, b; 294 GpStatus status; 295 GpPenType type; 296 297 /* NULL */ 298 status = GdipGetPenFillType(NULL, NULL); 299 expect(InvalidParameter, status); 300 301 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); 302 expect(Ok, status); 303 status = GdipGetPenFillType(pen, NULL); 304 expect(InvalidParameter, status); 305 306 /* created with GdipCreatePen1() */ 307 status = GdipGetPenFillType(pen, &type); 308 expect(Ok, status); 309 expect(PenTypeSolidColor, type); 310 GdipDeletePen(pen); 311 312 /* based on SolidBrush */ 313 status = GdipCreateSolidFill((ARGB)0xffff00ff, &solid); 314 expect(Ok, status); 315 status = GdipCreatePen2((GpBrush*)solid, 10.0f, UnitPixel, &pen); 316 expect(Ok, status); 317 status = GdipGetPenFillType(pen, &type); 318 expect(Ok, status); 319 expect(PenTypeSolidColor, type); 320 GdipDeletePen(pen); 321 GdipDeleteBrush((GpBrush*)solid); 322 323 /* based on LinearGradientBrush */ 324 a.X = a.Y = 0.0; 325 b.X = b.Y = 10.0; 326 status = GdipCreateLineBrush(&a, &b, (ARGB)0xffff00ff, (ARGB)0xffff0000, 327 WrapModeTile, &line); 328 expect(Ok, status); 329 status = GdipCreatePen2((GpBrush*)line, 10.0f, UnitPixel, &pen); 330 expect(Ok, status); 331 status = GdipGetPenFillType(pen, &type); 332 expect(Ok, status); 333 expect(PenTypeLinearGradient, type); 334 GdipDeletePen(pen); 335 GdipDeleteBrush((GpBrush*)line); 336 } 337 338 static void test_compoundarray(void) 339 { 340 GpStatus status; 341 GpPen *pen; 342 static const REAL testvalues[] = {0.2, 0.4, 0.6, 0.8}; 343 INT count; 344 345 status = GdipSetPenCompoundArray(NULL, testvalues, 4); 346 expect(InvalidParameter, status); 347 348 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); 349 expect(Ok, status); 350 351 status = GdipGetPenCompoundCount(NULL, NULL); 352 expect(InvalidParameter, status); 353 354 status = GdipGetPenCompoundCount(pen, NULL); 355 expect(InvalidParameter, status); 356 357 count = 10; 358 status = GdipGetPenCompoundCount(pen, &count); 359 todo_wine { 360 expect(Ok, status); 361 ok(count == 0, "Unexpected compound count %d\n", count); 362 } 363 status = GdipSetPenCompoundArray(pen, NULL, 0); 364 expect(InvalidParameter, status); 365 status = GdipSetPenCompoundArray(pen, NULL, 4); 366 expect(InvalidParameter, status); 367 status = GdipSetPenCompoundArray(pen, testvalues, 3); 368 expect(InvalidParameter, status); 369 status = GdipSetPenCompoundArray(pen, testvalues, 0); 370 expect(InvalidParameter, status); 371 status = GdipSetPenCompoundArray(pen, testvalues, -2); 372 expect(InvalidParameter, status); 373 374 status = GdipSetPenCompoundArray(pen, testvalues, 4); 375 todo_wine expect(Ok, status); 376 status = GdipSetPenCompoundArray(pen, NULL, 0); 377 expect(InvalidParameter, status); 378 379 count = 0; 380 status = GdipGetPenCompoundCount(pen, &count); 381 todo_wine { 382 expect(Ok, status); 383 ok(count == 4, "Unexpected compound count %d\n", count); 384 } 385 GdipDeletePen(pen); 386 } 387 388 static void test_transform(void) 389 { 390 GpStatus status; 391 GpPen *pen; 392 GpMatrix *matrix, *matrix2; 393 REAL values[6]; 394 395 status = GdipCreatePen1((ARGB)0xffff00ff, 10.0f, UnitPixel, &pen); 396 expect(Ok, status); 397 398 status = GdipCreateMatrix(&matrix); 399 expect(Ok, status); 400 401 status = GdipGetPenTransform(pen, matrix); 402 expect(Ok, status); 403 404 status = GdipGetMatrixElements(matrix, values); 405 expect(Ok, status); 406 407 expectf(1.0, values[0]); 408 expectf(0.0, values[1]); 409 expectf(0.0, values[2]); 410 expectf(1.0, values[3]); 411 expectf(0.0, values[4]); 412 expectf(0.0, values[5]); 413 414 GdipCreateMatrix2(3.0, -2.0, 5.0, 2.0, 6.0, 3.0, &matrix2); 415 status = GdipSetPenTransform(pen, matrix2); 416 expect(Ok, status); 417 GdipDeleteMatrix(matrix2); 418 419 status = GdipGetPenTransform(pen, matrix); 420 expect(Ok, status); 421 status = GdipGetMatrixElements(matrix, values); 422 expect(Ok, status); 423 expectf(3.0, values[0]); 424 expectf(-2.0, values[1]); 425 expectf(5.0, values[2]); 426 expectf(2.0, values[3]); 427 expectf(6.0, values[4]); 428 expectf(3.0, values[5]); 429 430 status = GdipResetPenTransform(pen); 431 expect(Ok, status); 432 433 status = GdipGetPenTransform(pen, matrix); 434 expect(Ok, status); 435 status = GdipGetMatrixElements(matrix, values); 436 expect(Ok, status); 437 438 expectf(1.0, values[0]); 439 expectf(0.0, values[1]); 440 expectf(0.0, values[2]); 441 expectf(1.0, values[3]); 442 expectf(0.0, values[4]); 443 expectf(0.0, values[5]); 444 445 GdipDeletePen(pen); 446 447 GdipDeleteMatrix(matrix); 448 } 449 450 START_TEST(pen) 451 { 452 struct GdiplusStartupInput gdiplusStartupInput; 453 ULONG_PTR gdiplusToken; 454 HMODULE hmsvcrt; 455 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask); 456 457 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */ 458 hmsvcrt = LoadLibraryA("msvcrt"); 459 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s"); 460 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e); 461 462 test_startup(); 463 464 gdiplusStartupInput.GdiplusVersion = 1; 465 gdiplusStartupInput.DebugEventCallback = NULL; 466 gdiplusStartupInput.SuppressBackgroundThread = 0; 467 gdiplusStartupInput.SuppressExternalCodecs = 0; 468 469 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 470 471 test_constructor_destructor(); 472 test_constructor_destructor2(); 473 test_brushfill(); 474 test_dasharray(); 475 test_customcap(); 476 test_penfilltype(); 477 test_compoundarray(); 478 test_transform(); 479 480 GdiplusShutdown(gdiplusToken); 481 } 482