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 IsWow64;
97 
98     /* Test NULL paramters */
99     set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
100     set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
101     SetLastError(ERROR_SUCCESS);
102     ok_int(CombineTransform(&xform3, &xform1, NULL), 0);
103     ok_int(CombineTransform(&xform3, NULL, &xform2), 0);
104     ok_int(CombineTransform(NULL, &xform1, &xform2), 0);
105     ok_int(GetLastError(), ERROR_SUCCESS);
106 
107     /* 2 zero matrices */
108     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
109     set_xform(&xform2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
110     SetLastError(ERROR_SUCCESS);
111     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
112     ok_xform(xform3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
113     ok_int(GetLastError(), ERROR_SUCCESS);
114 
115     /* 2 Identity matrices */
116     set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
117     set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
118     SetLastError(ERROR_SUCCESS);
119     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
120     ok_xform(xform3, 1.0, 0., 0., 1.0, 0., 0.);
121     ok_int(GetLastError(), ERROR_SUCCESS);
122 
123     /* 2 Identity matrices with offsets */
124     set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 20.0, -100.0);
125     set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
126     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
127     ok_xform(xform3, 1.0, 0., 0., 1.0, 20.0, -100.0);
128 
129     xform2.eDx = -60.0;
130     xform2.eDy = -20;
131     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
132     ok_flt(xform3.eDx, -40.0);
133     ok_flt(xform3.eDy, -120.0);
134 
135     /* add some stretching */
136     xform2.eM11 = 2;
137     xform2.eM22 = 4;
138     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
139     ok_xform(xform3, 2.0, 0., 0., 4.0, -20.0, -420.0);
140 
141     /* add some more stretching */
142     xform1.eM11 = -2.5;
143     xform1.eM22 = 0.5;
144     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
145     ok_xform(xform3, -5.0, 0., 0., 2.0, -20.0, -420.0);
146 
147     xform1.eM12 = 2.0;
148     xform1.eM21 = -0.5;
149     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
150     ok_xform(xform3, -5.0, 8.0, -1.0, 2.0, -20.0, -420.0);
151 
152     xform2.eM12 = 4.0;
153     xform2.eM21 = 6.5;
154     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
155     ok_xform(xform3, 8.0, -2.0, 2.25, 0.0, -670.0, -340.0);
156 
157     if (IsWow64Process(GetCurrentProcess(), &IsWow64) && IsWow64)
158     {
159         ok_flt(GetMaxValue(0, 0), 4294967296.0);
160         ok_flt(GetMaxValue(0, 1), 4294967296.0);
161         ok_flt(GetMaxValue(0, 2), 4294967296.0);
162         ok_flt(GetMaxValue(0, 3), 4294967296.0);
163         ok_flt(GetMaxValue(0, 4), 4294967040.0);
164         ok_flt(GetMaxValue(0, 5), 4294967040.0);
165 
166         ok_flt(GetMaxValue(1, 0), 4294967296.0);
167         ok_flt(GetMaxValue(1, 1), 4294967296.0);
168         ok_flt(GetMaxValue(1, 2), 4294967296.0);
169         ok_flt(GetMaxValue(1, 3), 4294967296.0);
170         ok_flt(GetMaxValue(1, 4), 4294967296.0);
171         ok_flt(GetMaxValue(1, 5), 4294967296.0);
172     }
173     else
174     {
175         ok_flt(GetMaxValue(0, 0), 4294967296.0);
176         ok_flt(GetMaxValue(0, 1), 4294967296.0);
177         ok_flt(GetMaxValue(0, 2), 4294967296.0);
178         ok_flt(GetMaxValue(0, 3), 4294967296.0);
179         ok_flt(GetMaxValue(0, 4), 2147483520.0);
180         ok_flt(GetMaxValue(0, 5), 2147483520.0);
181 
182         ok_flt(GetMaxValue(1, 0), 4294967296.0);
183         ok_flt(GetMaxValue(1, 1), 4294967296.0);
184         ok_flt(GetMaxValue(1, 2), 4294967296.0);
185         ok_flt(GetMaxValue(1, 3), 4294967296.0);
186         ok_flt(GetMaxValue(1, 4), 4294967296.0);
187         ok_flt(GetMaxValue(1, 5), 4294967296.0);
188     }
189 
190     /* Some undefined values */
191     set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
192     set_xform(&xform2, geIND, 0.0, 0.0, geINF, 0.0, 0.0);
193     SetLastError(ERROR_SUCCESS);
194     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
195     ok_xform(xform3, geIND, 0.0, 0.0, geINF, 0.0, 0.0);
196     ok_int(GetLastError(), ERROR_SUCCESS);
197 
198     set_xform(&xform1, geIND, 0.0, 0.0, geINF, 0.0, 0.0);
199     set_xform(&xform2, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0);
200     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
201     ok_xform(xform3, geIND, geIND, geINF, geINF, 0.0, 0.0);
202     ok_int(GetLastError(), ERROR_SUCCESS);
203 
204     set_xform(&xform1, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0);
205     set_xform(&xform2, geIND, 0.0, 0.0, geINF, 0.0, 0.0);
206     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
207     ok_xform(xform3, geIND, geINF, geIND, geINF, 0.0, 0.0);
208     ok_int(GetLastError(), ERROR_SUCCESS);
209 
210     set_xform(&xform1, (FLOAT)18446743500000000000.0, 0.0, 1.0, 0.0, 0.0, 0.0);
211     xform2 = xform1;
212     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
213     ok_flt(xform3.eM11, 340282326356119260000000000000000000000.0);
214 
215     xform1.eM11 = (FLOAT)18446745000000000000.0;
216     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
217     ok_flt(xform3.eM11, 340282346638528860000000000000000000000.0);
218 
219     xform1.eM11 = (FLOAT)18446746000000000000.0;
220     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
221     ok_long(*(DWORD*)&xform3.eM11, IsWow64 ? 0x7f800000 : 0x7f800001);
222 
223     /* zero matrix + 1 invalid */
224     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
225     set_xform(&xform2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
226     *(DWORD*)&xform2.eM22 = 0x7f800000; // (0.0F/0.0F)
227     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
228     ok_xform(xform3, 0.0, 0.0, 0.0, geIND, 0.0, 0.0);
229 
230     /* zero matrix + 1 invalid */
231     xform2 = xform1;
232     *(DWORD*)&xform2.eM12 = 0x7f800000; // (0.0F/0.0F)
233     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
234     ok_xform(xform3, 0.0, geIND, 0.0, geIND, 0.0, 0.0);
235 
236     /* Some undefined values */
237     set_xform(&xform1, 0.0, geIND, 0.0, 0.0, 0.0, 0.0);
238     set_xform(&xform2, geIND, 0.0, 0.0, geINF, 0.0, 0.0);
239     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
240     ok_xform(xform3, IsWow64 ? geIND : 0.000000, IsWow64 ? geIND : -1.500000, geIND, geIND, 0.0, 0.0);
241 }
242 
243 void Test_CombineTransform_Inval(float eInval, float eOut)
244 {
245     XFORM xform1, xform2, xform3;
246 
247     /* zero matrix / M11 invalid */
248     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
249     set_xform(&xform2, eInval, 0.0, 0.0, 0.0, 0.0, 0.0);
250     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
251     ok_xform(xform3, eOut, 0.0, 0.0, 0.0, 0.0, 0.0); // -> M21
252     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
253     ok_xform(xform3, eOut, 0.0, 0.0, 0.0, 0.0, 0.0); // -> M12
254 
255     /* zero matrix / M12 invalid */
256     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
257     set_xform(&xform2, 0.0, eInval, 0.0, 0.0, 0.0, 0.0);
258     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
259     ok_xform(xform3, 0.0, eOut, 0.0, eOut, 0.0, 0.0);
260     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
261     ok_xform(xform3, eOut, eOut, 0.0, 0.0, 0.0, 0.0);
262 
263     /* zero matrix / M21 invalid */
264     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
265     set_xform(&xform2, 0.0, 0.0, eInval, 0.0, 0.0, 0.0);
266     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
267     ok_xform(xform3, eOut, 0.0, eOut, 0.0, 0.0, 0.0);
268     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
269     ok_xform(xform3, 0.0, 0.0, eOut, eOut, 0.0, 0.0);
270 
271     /* zero matrix / M22 invalid */
272     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
273     set_xform(&xform2, 0.0, 0.0, 0.0, eInval, 0.0, 0.0);
274     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
275     ok_xform(xform3, 0.0, 0.0, 0.0, eOut, 0.0, 0.0); // -> M12
276     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
277     ok_xform(xform3, 0.0, 0.0, 0.0, eOut, 0.0, 0.0); // -> M21
278 
279     /* zero matrix / M11,M12 invalid */
280     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
281     set_xform(&xform2, eInval, eInval, 0.0, 0.0, 0.0, 0.0);
282     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
283     ok_xform(xform3, eOut, eOut, eOut, eOut, 0.0, 0.0);
284     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
285     ok_xform(xform3, eOut, eOut, 0.0, 0.0, 0.0, 0.0);
286 
287     /* zero matrix / M11,M21 invalid */
288     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
289     set_xform(&xform2, eInval, 0.0, eInval, 0.0, 0.0, 0.0);
290     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
291     ok_xform(xform3, eOut, 0.0, eOut, 0.0, 0.0, 0.0);
292     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
293     ok_xform(xform3, eOut, eOut, eOut, eOut, 0.0, 0.0);
294 
295     /* zero matrix / M11,M22 invalid */
296     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
297     set_xform(&xform2, eInval, 0.0, 0.0, eInval, 0.0, 0.0);
298     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
299     ok_xform(xform3, eOut, 0.0, 0.0, eOut, 0.0, 0.0); // -> M12, M21
300     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
301     ok_xform(xform3, eOut, 0.0, 0.0, eOut, 0.0, 0.0);
302 
303     /* zero matrix / M12,M21 invalid */
304     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
305     set_xform(&xform2, 0.0, eInval, eInval, 0.0, 0.0, 0.0);
306     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
307     ok_xform(xform3, eOut, eOut, eOut, eOut, 0.0, 0.0);
308     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
309     ok_xform(xform3, eOut, eOut, eOut, eOut, 0.0, 0.0);
310 }
311 
312 START_TEST(CombineTransform)
313 {
314     *(DWORD*)&geINF = 0x7f800000;
315     *(DWORD*)&geIND = 0xffc00000;
316     *(DWORD*)&geQNAN = 0x7fc00000;
317 
318     Test_CombineTransform();
319 
320     Test_CombineTransform_Inval(geINF, geIND);
321     Test_CombineTransform_Inval(geIND, geIND);
322     Test_CombineTransform_Inval(geQNAN, geQNAN);
323 
324 }
325 
326