1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL - See COPYING in the top level directory 4 * PURPOSE: Test for CombineTransform 5 * PROGRAMMERS: Timo Kreuzer 6 */ 7 8 #include "precomp.h" 9 10 typedef union 11 { 12 float e; 13 long l; 14 } FLT_LONG; 15 16 #define ok_flt(x, y) \ 17 { \ 18 FLT_LONG __x, __y; \ 19 __x.e = (x); \ 20 __y.e = (y); \ 21 if (_isnan(y)) {\ 22 ok((__x.l == __y.l) || (__x.l == 0), "Wrong value for " #x ", expected " #y " (%f), got %f\n", (double)(y), (double)(x)); \ 23 } else {\ 24 ok(__x.l == __y.l, "Wrong value for " #x ", expected " #y " (%f), got %f\n", (double)(y), (double)(x)); \ 25 } \ 26 } 27 28 #define ok_xform(xform, m11, m12, m21, m22, dx, dy) \ 29 ok_flt(xform.eM11, m11); \ 30 ok_flt(xform.eM12, m12); \ 31 ok_flt(xform.eM21, m21); \ 32 ok_flt(xform.eM22, m22); \ 33 ok_flt(xform.eDx, dx); \ 34 ok_flt(xform.eDy, dy); 35 36 #define set_xform(pxform, m11, m12, m21, m22, dx, dy) \ 37 (pxform)->eM11 = m11; \ 38 (pxform)->eM12 = m12; \ 39 (pxform)->eM21 = m21; \ 40 (pxform)->eM22 = m22; \ 41 (pxform)->eDx = dx; \ 42 (pxform)->eDy = dy; 43 44 float geINF; 45 float geIND; 46 float geQNAN; 47 48 FLOAT 49 GetMaxValue(unsigned int Parameter, unsigned int Field) 50 { 51 XFORM xform1, xform2, xform3; 52 FLOAT fmin, fmax, fmid; 53 PFLOAT target; 54 55 if (Parameter == 0) 56 { 57 target = &xform1.eM11 + Field; 58 } 59 else 60 { 61 target = &xform2.eM11 + Field; 62 } 63 64 fmin = 0; 65 fmax = 4294967296.0f; 66 fmid = (fmin + fmax) / 2; 67 while (fmin < fmax) 68 { 69 fmid = (fmin + fmax) / 2; 70 71 //printf("fmin = %f, fmid = %f, fmax = %f\n", (double)fmin, (double)fmid, (double)fmax); 72 set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); 73 set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); 74 set_xform(&xform3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 75 *target = fmid; 76 77 if (CombineTransform(&xform3, &xform1, &xform2)) 78 { 79 if (fmid == fmin) break; 80 fmin = fmid; 81 } 82 else 83 { 84 if (fmid == fmax) break; 85 fmax = fmid; 86 } 87 } 88 //printf("fmin = %f, fmid = %f, fmax = %f\n", (double)fmin, (double)fmid, (double)fmax); 89 return fmin; 90 } 91 92 93 void Test_CombineTransform() 94 { 95 XFORM xform1, xform2, xform3; 96 BOOL IsWin64; 97 #ifndef _WIN64 98 BOOL IsWow64; 99 #endif 100 101 // TODO: Check results for ARM/ARM64 102 #ifdef _WIN64 103 IsWin64 = TRUE; 104 #else 105 IsWin64 = (IsWow64Process(GetCurrentProcess(), &IsWow64) && IsWow64); 106 #endif 107 108 /* Test NULL paramters */ 109 set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); 110 set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); 111 SetLastError(ERROR_SUCCESS); 112 ok_int(CombineTransform(&xform3, &xform1, NULL), 0); 113 ok_int(CombineTransform(&xform3, NULL, &xform2), 0); 114 ok_int(CombineTransform(NULL, &xform1, &xform2), 0); 115 ok_int(GetLastError(), ERROR_SUCCESS); 116 117 /* 2 zero matrices */ 118 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 119 set_xform(&xform2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 120 SetLastError(ERROR_SUCCESS); 121 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 122 ok_xform(xform3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 123 ok_int(GetLastError(), ERROR_SUCCESS); 124 125 /* 2 Identity matrices */ 126 set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); 127 set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); 128 SetLastError(ERROR_SUCCESS); 129 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 130 ok_xform(xform3, 1.0, 0., 0., 1.0, 0., 0.); 131 ok_int(GetLastError(), ERROR_SUCCESS); 132 133 /* 2 Identity matrices with offsets */ 134 set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 20.0, -100.0); 135 set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); 136 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 137 ok_xform(xform3, 1.0, 0., 0., 1.0, 20.0, -100.0); 138 139 xform2.eDx = -60.0; 140 xform2.eDy = -20; 141 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 142 ok_flt(xform3.eDx, -40.0); 143 ok_flt(xform3.eDy, -120.0); 144 145 /* add some stretching */ 146 xform2.eM11 = 2; 147 xform2.eM22 = 4; 148 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 149 ok_xform(xform3, 2.0, 0., 0., 4.0, -20.0, -420.0); 150 151 /* add some more stretching */ 152 xform1.eM11 = -2.5; 153 xform1.eM22 = 0.5; 154 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 155 ok_xform(xform3, -5.0, 0., 0., 2.0, -20.0, -420.0); 156 157 xform1.eM12 = 2.0; 158 xform1.eM21 = -0.5; 159 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 160 ok_xform(xform3, -5.0, 8.0, -1.0, 2.0, -20.0, -420.0); 161 162 xform2.eM12 = 4.0; 163 xform2.eM21 = 6.5; 164 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 165 ok_xform(xform3, 8.0, -2.0, 2.25, 0.0, -670.0, -340.0); 166 167 if (IsWin64) 168 { 169 ok_flt(GetMaxValue(0, 0), 4294967296.0); 170 ok_flt(GetMaxValue(0, 1), 4294967296.0); 171 ok_flt(GetMaxValue(0, 2), 4294967296.0); 172 ok_flt(GetMaxValue(0, 3), 4294967296.0); 173 ok_flt(GetMaxValue(0, 4), 4294967040.0); 174 ok_flt(GetMaxValue(0, 5), 4294967040.0); 175 176 ok_flt(GetMaxValue(1, 0), 4294967296.0); 177 ok_flt(GetMaxValue(1, 1), 4294967296.0); 178 ok_flt(GetMaxValue(1, 2), 4294967296.0); 179 ok_flt(GetMaxValue(1, 3), 4294967296.0); 180 ok_flt(GetMaxValue(1, 4), 4294967296.0); 181 ok_flt(GetMaxValue(1, 5), 4294967296.0); 182 } 183 else 184 { 185 ok_flt(GetMaxValue(0, 0), 4294967296.0); 186 ok_flt(GetMaxValue(0, 1), 4294967296.0); 187 ok_flt(GetMaxValue(0, 2), 4294967296.0); 188 ok_flt(GetMaxValue(0, 3), 4294967296.0); 189 ok_flt(GetMaxValue(0, 4), 2147483520.0); 190 ok_flt(GetMaxValue(0, 5), 2147483520.0); 191 192 ok_flt(GetMaxValue(1, 0), 4294967296.0); 193 ok_flt(GetMaxValue(1, 1), 4294967296.0); 194 ok_flt(GetMaxValue(1, 2), 4294967296.0); 195 ok_flt(GetMaxValue(1, 3), 4294967296.0); 196 ok_flt(GetMaxValue(1, 4), 4294967296.0); 197 ok_flt(GetMaxValue(1, 5), 4294967296.0); 198 } 199 200 /* Some undefined values */ 201 set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0); 202 set_xform(&xform2, geIND, 0.0, 0.0, geINF, 0.0, 0.0); 203 SetLastError(ERROR_SUCCESS); 204 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 205 ok_xform(xform3, geIND, 0.0, 0.0, geINF, 0.0, 0.0); 206 ok_int(GetLastError(), ERROR_SUCCESS); 207 208 set_xform(&xform1, geIND, 0.0, 0.0, geINF, 0.0, 0.0); 209 set_xform(&xform2, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0); 210 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 211 ok_xform(xform3, geIND, geIND, geINF, geINF, 0.0, 0.0); 212 ok_int(GetLastError(), ERROR_SUCCESS); 213 214 set_xform(&xform1, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0); 215 set_xform(&xform2, geIND, 0.0, 0.0, geINF, 0.0, 0.0); 216 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 217 ok_xform(xform3, geIND, geINF, geIND, geINF, 0.0, 0.0); 218 ok_int(GetLastError(), ERROR_SUCCESS); 219 220 set_xform(&xform1, (FLOAT)18446743500000000000.0, 0.0, 1.0, 0.0, 0.0, 0.0); 221 xform2 = xform1; 222 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 223 ok_flt(xform3.eM11, 340282326356119260000000000000000000000.0); 224 225 xform1.eM11 = (FLOAT)18446745000000000000.0; 226 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 227 ok_flt(xform3.eM11, 340282346638528860000000000000000000000.0); 228 229 xform1.eM11 = (FLOAT)18446746000000000000.0; 230 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 231 ok_long(*(DWORD*)&xform3.eM11, IsWin64 ? 0x7f800000 : 0x7f800001); 232 233 /* zero matrix + 1 invalid */ 234 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 235 set_xform(&xform2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 236 *(DWORD*)&xform2.eM22 = 0x7f800000; // (0.0F/0.0F) 237 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 238 ok_xform(xform3, 0.0, 0.0, 0.0, geIND, 0.0, 0.0); 239 240 /* zero matrix + 1 invalid */ 241 xform2 = xform1; 242 *(DWORD*)&xform2.eM12 = 0x7f800000; // (0.0F/0.0F) 243 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 244 ok_xform(xform3, 0.0, geIND, 0.0, geIND, 0.0, 0.0); 245 246 /* Some undefined values */ 247 set_xform(&xform1, 0.0, geIND, 0.0, 0.0, 0.0, 0.0); 248 set_xform(&xform2, geIND, 0.0, 0.0, geINF, 0.0, 0.0); 249 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 250 ok_xform(xform3, IsWin64 ? geIND : 0.000000, IsWin64 ? geIND : -1.500000, geIND, geIND, 0.0, 0.0); 251 } 252 253 void Test_CombineTransform_Inval(float eInval, float eOut) 254 { 255 XFORM xform1, xform2, xform3; 256 257 /* zero matrix / M11 invalid */ 258 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 259 set_xform(&xform2, eInval, 0.0, 0.0, 0.0, 0.0, 0.0); 260 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 261 ok_xform(xform3, eOut, 0.0, 0.0, 0.0, 0.0, 0.0); // -> M21 262 ok_int(CombineTransform(&xform3, &xform2, &xform1), 1); 263 ok_xform(xform3, eOut, 0.0, 0.0, 0.0, 0.0, 0.0); // -> M12 264 265 /* zero matrix / M12 invalid */ 266 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 267 set_xform(&xform2, 0.0, eInval, 0.0, 0.0, 0.0, 0.0); 268 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 269 ok_xform(xform3, 0.0, eOut, 0.0, eOut, 0.0, 0.0); 270 ok_int(CombineTransform(&xform3, &xform2, &xform1), 1); 271 ok_xform(xform3, eOut, eOut, 0.0, 0.0, 0.0, 0.0); 272 273 /* zero matrix / M21 invalid */ 274 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 275 set_xform(&xform2, 0.0, 0.0, eInval, 0.0, 0.0, 0.0); 276 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 277 ok_xform(xform3, eOut, 0.0, eOut, 0.0, 0.0, 0.0); 278 ok_int(CombineTransform(&xform3, &xform2, &xform1), 1); 279 ok_xform(xform3, 0.0, 0.0, eOut, eOut, 0.0, 0.0); 280 281 /* zero matrix / M22 invalid */ 282 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 283 set_xform(&xform2, 0.0, 0.0, 0.0, eInval, 0.0, 0.0); 284 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 285 ok_xform(xform3, 0.0, 0.0, 0.0, eOut, 0.0, 0.0); // -> M12 286 ok_int(CombineTransform(&xform3, &xform2, &xform1), 1); 287 ok_xform(xform3, 0.0, 0.0, 0.0, eOut, 0.0, 0.0); // -> M21 288 289 /* zero matrix / M11,M12 invalid */ 290 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 291 set_xform(&xform2, eInval, eInval, 0.0, 0.0, 0.0, 0.0); 292 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 293 ok_xform(xform3, eOut, eOut, eOut, eOut, 0.0, 0.0); 294 ok_int(CombineTransform(&xform3, &xform2, &xform1), 1); 295 ok_xform(xform3, eOut, eOut, 0.0, 0.0, 0.0, 0.0); 296 297 /* zero matrix / M11,M21 invalid */ 298 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 299 set_xform(&xform2, eInval, 0.0, eInval, 0.0, 0.0, 0.0); 300 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 301 ok_xform(xform3, eOut, 0.0, eOut, 0.0, 0.0, 0.0); 302 ok_int(CombineTransform(&xform3, &xform2, &xform1), 1); 303 ok_xform(xform3, eOut, eOut, eOut, eOut, 0.0, 0.0); 304 305 /* zero matrix / M11,M22 invalid */ 306 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 307 set_xform(&xform2, eInval, 0.0, 0.0, eInval, 0.0, 0.0); 308 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 309 ok_xform(xform3, eOut, 0.0, 0.0, eOut, 0.0, 0.0); // -> M12, M21 310 ok_int(CombineTransform(&xform3, &xform2, &xform1), 1); 311 ok_xform(xform3, eOut, 0.0, 0.0, eOut, 0.0, 0.0); 312 313 /* zero matrix / M12,M21 invalid */ 314 set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); 315 set_xform(&xform2, 0.0, eInval, eInval, 0.0, 0.0, 0.0); 316 ok_int(CombineTransform(&xform3, &xform1, &xform2), 1); 317 ok_xform(xform3, eOut, eOut, eOut, eOut, 0.0, 0.0); 318 ok_int(CombineTransform(&xform3, &xform2, &xform1), 1); 319 ok_xform(xform3, eOut, eOut, eOut, eOut, 0.0, 0.0); 320 } 321 322 START_TEST(CombineTransform) 323 { 324 *(DWORD*)&geINF = 0x7f800000; 325 *(DWORD*)&geIND = 0xffc00000; 326 *(DWORD*)&geQNAN = 0x7fc00000; 327 328 Test_CombineTransform(); 329 330 Test_CombineTransform_Inval(geINF, geIND); 331 Test_CombineTransform_Inval(geIND, geIND); 332 Test_CombineTransform_Inval(geQNAN, geQNAN); 333 334 } 335 336