1 /* 2 * Unit test suite for customlinecap 3 * 4 * Copyright (C) 2008 Nikolay Sivov 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 #include <limits.h> 21 22 #include "objbase.h" 23 #include "gdiplus.h" 24 #include "wine/test.h" 25 26 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got) 27 #define expectf(expected, got) ok(got == expected, "Expected %.2f, got %.2f\n", expected, got) 28 29 static BOOL compare_float(float f, float g, unsigned int ulps) 30 { 31 int x = *(int *)&f; 32 int y = *(int *)&g; 33 34 if (x < 0) 35 x = INT_MIN - x; 36 if (y < 0) 37 y = INT_MIN - y; 38 39 if (abs(x - y) > ulps) 40 return FALSE; 41 42 return TRUE; 43 } 44 45 static void test_constructor_destructor(void) 46 { 47 GpCustomLineCap *custom; 48 GpPath *path, *path2; 49 GpStatus stat; 50 51 stat = GdipCreatePath(FillModeAlternate, &path); 52 expect(Ok, stat); 53 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); 54 expect(Ok, stat); 55 56 stat = GdipCreatePath(FillModeAlternate, &path2); 57 expect(Ok, stat); 58 stat = GdipAddPathRectangle(path2, 5.0, 5.0, 10.0, 10.0); 59 expect(Ok, stat); 60 61 /* NULL args */ 62 stat = GdipCreateCustomLineCap(NULL, NULL, LineCapFlat, 0.0, NULL); 63 expect(InvalidParameter, stat); 64 stat = GdipCreateCustomLineCap(path, NULL, LineCapFlat, 0.0, NULL); 65 expect(InvalidParameter, stat); 66 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, NULL); 67 expect(InvalidParameter, stat); 68 stat = GdipCreateCustomLineCap(NULL, NULL, LineCapFlat, 0.0, &custom); 69 expect(InvalidParameter, stat); 70 stat = GdipDeleteCustomLineCap(NULL); 71 expect(InvalidParameter, stat); 72 73 /* valid args */ 74 stat = GdipCreateCustomLineCap(NULL, path2, LineCapFlat, 0.0, &custom); 75 expect(Ok, stat); 76 stat = GdipDeleteCustomLineCap(custom); 77 expect(Ok, stat); 78 /* it's strange but native returns NotImplemented on stroke == NULL */ 79 custom = NULL; 80 stat = GdipCreateCustomLineCap(path, NULL, LineCapFlat, 10.0, &custom); 81 todo_wine expect(NotImplemented, stat); 82 todo_wine ok(custom == NULL, "Expected a failure on creation\n"); 83 if(stat == Ok) GdipDeleteCustomLineCap(custom); 84 85 GdipDeletePath(path2); 86 GdipDeletePath(path); 87 } 88 89 static void test_linejoin(void) 90 { 91 GpCustomLineCap *custom; 92 GpPath *path; 93 GpLineJoin join; 94 GpStatus stat; 95 96 stat = GdipCreatePath(FillModeAlternate, &path); 97 expect(Ok, stat); 98 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); 99 expect(Ok, stat); 100 101 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom); 102 expect(Ok, stat); 103 104 /* NULL args */ 105 stat = GdipGetCustomLineCapStrokeJoin(NULL, NULL); 106 expect(InvalidParameter, stat); 107 stat = GdipGetCustomLineCapStrokeJoin(custom, NULL); 108 expect(InvalidParameter, stat); 109 stat = GdipGetCustomLineCapStrokeJoin(NULL, &join); 110 expect(InvalidParameter, stat); 111 stat = GdipSetCustomLineCapStrokeJoin(NULL, LineJoinBevel); 112 expect(InvalidParameter, stat); 113 114 /* LineJoinMiter is default */ 115 stat = GdipGetCustomLineCapStrokeJoin(custom, &join); 116 expect(Ok, stat); 117 expect(LineJoinMiter, join); 118 119 /* set/get */ 120 stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinBevel); 121 expect(Ok, stat); 122 stat = GdipGetCustomLineCapStrokeJoin(custom, &join); 123 expect(Ok, stat); 124 expect(LineJoinBevel, join); 125 stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinRound); 126 expect(Ok, stat); 127 stat = GdipGetCustomLineCapStrokeJoin(custom, &join); 128 expect(Ok, stat); 129 expect(LineJoinRound, join); 130 stat = GdipSetCustomLineCapStrokeJoin(custom, LineJoinMiterClipped); 131 expect(Ok, stat); 132 stat = GdipGetCustomLineCapStrokeJoin(custom, &join); 133 expect(Ok, stat); 134 expect(LineJoinMiterClipped, join); 135 136 GdipDeleteCustomLineCap(custom); 137 GdipDeletePath(path); 138 } 139 140 static void test_inset(void) 141 { 142 GpCustomLineCap *custom; 143 GpPath *path; 144 REAL inset; 145 GpStatus stat; 146 147 stat = GdipCreatePath(FillModeAlternate, &path); 148 expect(Ok, stat); 149 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); 150 expect(Ok, stat); 151 152 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom); 153 expect(Ok, stat); 154 155 /* NULL args */ 156 stat = GdipGetCustomLineCapBaseInset(NULL, NULL); 157 expect(InvalidParameter, stat); 158 stat = GdipGetCustomLineCapBaseInset(NULL, &inset); 159 expect(InvalidParameter, stat); 160 stat = GdipGetCustomLineCapBaseInset(custom, NULL); 161 expect(InvalidParameter, stat); 162 /* valid args */ 163 inset = (REAL)0xdeadbeef; 164 stat = GdipGetCustomLineCapBaseInset(custom, &inset); 165 expect(Ok, stat); 166 expectf(0.0, inset); 167 168 GdipDeleteCustomLineCap(custom); 169 GdipDeletePath(path); 170 } 171 172 static void test_scale(void) 173 { 174 GpCustomLineCap *custom; 175 GpPath *path; 176 REAL scale; 177 GpStatus stat; 178 179 stat = GdipCreatePath(FillModeAlternate, &path); 180 expect(Ok, stat); 181 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); 182 expect(Ok, stat); 183 184 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom); 185 expect(Ok, stat); 186 187 /* NULL args */ 188 stat = GdipGetCustomLineCapWidthScale(NULL, NULL); 189 expect(InvalidParameter, stat); 190 stat = GdipGetCustomLineCapWidthScale(NULL, &scale); 191 expect(InvalidParameter, stat); 192 stat = GdipGetCustomLineCapWidthScale(custom, NULL); 193 expect(InvalidParameter, stat); 194 195 stat = GdipSetCustomLineCapWidthScale(NULL, 2.0); 196 expect(InvalidParameter, stat); 197 198 /* valid args: read default */ 199 scale = (REAL)0xdeadbeef; 200 stat = GdipGetCustomLineCapWidthScale(custom, &scale); 201 expect(Ok, stat); 202 expectf(1.0, scale); 203 204 /* set and read back some scale values: there is no limit for the scale */ 205 stat = GdipSetCustomLineCapWidthScale(custom, 2.5); 206 expect(Ok, stat); 207 scale = (REAL)0xdeadbeef; 208 stat = GdipGetCustomLineCapWidthScale(custom, &scale); 209 expect(Ok, stat); 210 expectf(2.5, scale); 211 212 stat = GdipSetCustomLineCapWidthScale(custom, 42.0); 213 expect(Ok, stat); 214 scale = (REAL)0xdeadbeef; 215 stat = GdipGetCustomLineCapWidthScale(custom, &scale); 216 expect(Ok, stat); 217 expectf(42.0, scale); 218 219 stat = GdipSetCustomLineCapWidthScale(custom, 3000.0); 220 expect(Ok, stat); 221 scale = (REAL)0xdeadbeef; 222 stat = GdipGetCustomLineCapWidthScale(custom, &scale); 223 expect(Ok, stat); 224 expectf(3000.0, scale); 225 226 stat = GdipSetCustomLineCapWidthScale(custom, 0.0); 227 expect(Ok, stat); 228 scale = (REAL)0xdeadbeef; 229 stat = GdipGetCustomLineCapWidthScale(custom, &scale); 230 expect(Ok, stat); 231 expectf(0.0, scale); 232 233 GdipDeleteCustomLineCap(custom); 234 GdipDeletePath(path); 235 } 236 237 static void test_create_adjustable_cap(void) 238 { 239 REAL inset, scale, height, width; 240 GpAdjustableArrowCap *cap; 241 GpLineJoin join; 242 GpStatus stat; 243 GpLineCap base; 244 BOOL ret; 245 246 stat = GdipCreateAdjustableArrowCap(10.0, 10.0, TRUE, NULL); 247 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat); 248 249 stat = GdipCreateAdjustableArrowCap(17.0, 15.0, TRUE, &cap); 250 ok(stat == Ok, "Failed to create adjustable cap, %d\n", stat); 251 252 stat = GdipGetAdjustableArrowCapFillState(cap, NULL); 253 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat); 254 255 ret = FALSE; 256 stat = GdipGetAdjustableArrowCapFillState(cap, &ret); 257 ok(stat == Ok, "Unexpected return code, %d\n", stat); 258 ok(ret, "Unexpected fill state %d\n", ret); 259 260 stat = GdipGetAdjustableArrowCapHeight(cap, NULL); 261 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat); 262 263 stat = GdipGetAdjustableArrowCapHeight(cap, &height); 264 ok(stat == Ok, "Unexpected return code, %d\n", stat); 265 ok(height == 17.0, "Unexpected cap height %f\n", height); 266 267 stat = GdipGetAdjustableArrowCapWidth(cap, NULL); 268 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat); 269 270 stat = GdipGetAdjustableArrowCapWidth(cap, &width); 271 ok(stat == Ok, "Unexpected return code, %d\n", stat); 272 ok(width == 15.0, "Unexpected cap width %f\n", width); 273 274 stat = GdipGetAdjustableArrowCapMiddleInset(cap, NULL); 275 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat); 276 277 stat = GdipGetAdjustableArrowCapMiddleInset(cap, &inset); 278 ok(stat == Ok, "Unexpected return code, %d\n", stat); 279 ok(inset == 0.0f, "Unexpected middle inset %f\n", inset); 280 281 stat = GdipGetCustomLineCapBaseCap((GpCustomLineCap*)cap, &base); 282 ok(stat == Ok, "Unexpected return code, %d\n", stat); 283 ok(base == LineCapTriangle, "Unexpected base cap %d\n", base); 284 285 stat = GdipSetCustomLineCapBaseCap((GpCustomLineCap*)cap, LineCapSquare); 286 todo_wine 287 ok(stat == Ok, "Unexpected return code, %d\n", stat); 288 289 stat = GdipGetCustomLineCapBaseCap((GpCustomLineCap*)cap, &base); 290 ok(stat == Ok, "Unexpected return code, %d\n", stat); 291 todo_wine 292 ok(base == LineCapSquare, "Unexpected base cap %d\n", base); 293 294 /* Base inset */ 295 stat = GdipGetAdjustableArrowCapWidth(cap, &width); 296 ok(stat == Ok, "Unexpected return code, %d\n", stat); 297 298 stat = GdipGetAdjustableArrowCapHeight(cap, &height); 299 ok(stat == Ok, "Unexpected return code, %d\n", stat); 300 301 inset = 0.0; 302 stat = GdipGetCustomLineCapBaseInset((GpCustomLineCap*)cap, &inset); 303 ok(stat == Ok, "Unexpected return code, %d\n", stat); 304 ok(compare_float(inset, height / width, 1), "Unexpected inset %f\n", inset); 305 306 stat = GdipSetAdjustableArrowCapMiddleInset(cap, 1.0); 307 ok(stat == Ok, "Unexpected return code, %d\n", stat); 308 309 inset = 0.0; 310 stat = GdipGetCustomLineCapBaseInset((GpCustomLineCap*)cap, &inset); 311 ok(stat == Ok, "Unexpected return code, %d\n", stat); 312 ok(compare_float(inset, height / width, 1), "Unexpected inset %f\n", inset); 313 314 stat = GdipSetAdjustableArrowCapHeight(cap, 2.0 * height); 315 ok(stat == Ok, "Unexpected return code, %d\n", stat); 316 317 inset = 0.0; 318 stat = GdipGetCustomLineCapBaseInset((GpCustomLineCap*)cap, &inset); 319 ok(stat == Ok, "Unexpected return code, %d\n", stat); 320 ok(compare_float(inset, 2.0 * height / width, 1), "Unexpected inset %f\n", inset); 321 322 stat = GdipGetCustomLineCapWidthScale((GpCustomLineCap*)cap, &scale); 323 ok(stat == Ok, "Unexpected return code, %d\n", stat); 324 ok(scale == 1.0f, "Unexpected width scale %f\n", scale); 325 326 stat = GdipGetCustomLineCapStrokeJoin((GpCustomLineCap*)cap, &join); 327 ok(stat == Ok, "Unexpected return code, %d\n", stat); 328 ok(join == LineJoinMiter, "Unexpected stroke join %d\n", join); 329 330 GdipDeleteCustomLineCap((GpCustomLineCap*)cap); 331 } 332 333 static void test_captype(void) 334 { 335 GpAdjustableArrowCap *arrowcap; 336 GpCustomLineCap *custom; 337 CustomLineCapType type; 338 GpStatus stat; 339 GpPath *path; 340 341 stat = GdipGetCustomLineCapType(NULL, NULL); 342 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat); 343 344 type = 10; 345 stat = GdipGetCustomLineCapType(NULL, &type); 346 ok(stat == InvalidParameter, "Unexpected return code, %d\n", stat); 347 ok(type == 10, "Unexpected cap type, %d\n", type); 348 349 /* default cap */ 350 stat = GdipCreatePath(FillModeAlternate, &path); 351 ok(stat == Ok, "Failed to create path, %d\n", stat); 352 stat = GdipAddPathRectangle(path, 5.0, 5.0, 10.0, 10.0); 353 ok(stat == Ok, "AddPathRectangle failed, %d\n", stat); 354 355 stat = GdipCreateCustomLineCap(NULL, path, LineCapFlat, 0.0, &custom); 356 ok(stat == Ok, "Failed to create cap, %d\n", stat); 357 stat = GdipGetCustomLineCapType(custom, &type); 358 ok(stat == Ok, "Failed to get cap type, %d\n", stat); 359 ok(type == CustomLineCapTypeDefault, "Unexpected cap type %d\n", stat); 360 GdipDeleteCustomLineCap(custom); 361 GdipDeletePath(path); 362 363 /* arrow cap */ 364 stat = GdipCreateAdjustableArrowCap(17.0, 15.0, TRUE, &arrowcap); 365 ok(stat == Ok, "Failed to create adjustable cap, %d\n", stat); 366 367 stat = GdipGetCustomLineCapType((GpCustomLineCap*)arrowcap, &type); 368 ok(stat == Ok, "Failed to get cap type, %d\n", stat); 369 ok(type == CustomLineCapTypeAdjustableArrow, "Unexpected cap type %d\n", stat); 370 371 GdipDeleteCustomLineCap((GpCustomLineCap*)arrowcap); 372 } 373 374 START_TEST(customlinecap) 375 { 376 struct GdiplusStartupInput gdiplusStartupInput; 377 ULONG_PTR gdiplusToken; 378 HMODULE hmsvcrt; 379 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask); 380 381 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */ 382 hmsvcrt = LoadLibraryA("msvcrt"); 383 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s"); 384 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e); 385 386 gdiplusStartupInput.GdiplusVersion = 1; 387 gdiplusStartupInput.DebugEventCallback = NULL; 388 gdiplusStartupInput.SuppressBackgroundThread = 0; 389 gdiplusStartupInput.SuppressExternalCodecs = 0; 390 391 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 392 393 test_constructor_destructor(); 394 test_linejoin(); 395 test_inset(); 396 test_scale(); 397 test_create_adjustable_cap(); 398 test_captype(); 399 400 GdiplusShutdown(gdiplusToken); 401 } 402