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