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 void Test_CombineTransform()
49 {
50     XFORM xform1, xform2, xform3;
51 
52     /* Test NULL paramters */
53     set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
54     set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
55     SetLastError(ERROR_SUCCESS);
56     ok_int(CombineTransform(&xform3, &xform1, NULL), 0);
57     ok_int(CombineTransform(&xform3, NULL, &xform2), 0);
58     ok_int(CombineTransform(NULL, &xform1, &xform2), 0);
59     ok_int(GetLastError(), ERROR_SUCCESS);
60 
61     /* 2 zero matrices */
62     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
63     set_xform(&xform2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
64     SetLastError(ERROR_SUCCESS);
65     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
66     ok_xform(xform3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
67     ok_int(GetLastError(), ERROR_SUCCESS);
68 
69     /* 2 Identity matrices */
70     set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
71     set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
72     SetLastError(ERROR_SUCCESS);
73     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
74     ok_xform(xform3, 1.0, 0., 0., 1.0, 0., 0.);
75     ok_int(GetLastError(), ERROR_SUCCESS);
76 
77     /* 2 Identity matrices with offsets */
78     set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 20.0, -100.0);
79     set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
80     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
81     ok_xform(xform3, 1.0, 0., 0., 1.0, 20.0, -100.0);
82 
83     xform2.eDx = -60.0;
84     xform2.eDy = -20;
85     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
86     ok_flt(xform3.eDx, -40.0);
87     ok_flt(xform3.eDy, -120.0);
88 
89     /* add some stretching */
90     xform2.eM11 = 2;
91     xform2.eM22 = 4;
92     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
93     ok_xform(xform3, 2.0, 0., 0., 4.0, -20.0, -420.0);
94 
95     /* add some more stretching */
96     xform1.eM11 = -2.5;
97     xform1.eM22 = 0.5;
98     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
99     ok_xform(xform3, -5.0, 0., 0., 2.0, -20.0, -420.0);
100 
101     xform1.eM12 = 2.0;
102     xform1.eM21 = -0.5;
103     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
104     ok_xform(xform3, -5.0, 8.0, -1.0, 2.0, -20.0, -420.0);
105 
106     xform2.eM12 = 4.0;
107     xform2.eM21 = 6.5;
108     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
109     ok_xform(xform3, 8.0, -2.0, 2.25, 0.0, -670.0, -340.0);
110 
111     set_xform(&xform1, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
112     set_xform(&xform2, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
113     set_xform(&xform3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
114     xform1.eDx = (FLOAT)4294967167.999999761;
115     ok(xform1.eDx == 4294967040.0, "float rounding error.\n");
116     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
117     ok_xform(xform3, 1.0, 0.0, 0.0, 1.0, 4294967040.0, 0.0);
118 
119     set_xform(&xform3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
120     xform1.eDx = (FLOAT)4294967167.999999762;
121     ok(xform1.eDx == 4294967296.0, "float rounding error.\n");
122     ok_int(CombineTransform(&xform3, &xform1, &xform2), 0);
123     ok_int(GetLastError(), ERROR_SUCCESS);
124     ok_xform(xform3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
125 
126     xform1.eDx = (FLOAT)-4294967167.999999761;
127     ok(xform1.eDx == -4294967040.0, "float rounding error.\n");
128     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
129 
130     xform1.eDx = (FLOAT)-4294967167.999999762;
131     ok(xform1.eDx == -4294967296.0, "float rounding error.\n");
132     ok_int(CombineTransform(&xform3, &xform1, &xform2), 0);
133     ok_int(GetLastError(), ERROR_SUCCESS);
134 
135     xform1.eDx = 0;
136     xform1.eDy = (FLOAT)4294967167.999999761;
137     ok(xform1.eDy == 4294967040.0, "float rounding error.\n");
138     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
139 
140     xform2.eDy = 1;
141     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
142     ok_flt(xform3.eDy, 4294967040.0);
143 
144     xform1.eDy = (FLOAT)4294967167.999999762;
145     ok(xform1.eDy == 4294967296.0, "float rounding error.\n");
146     ok_int(CombineTransform(&xform3, &xform1, &xform2), 0);
147     ok_int(GetLastError(), ERROR_SUCCESS);
148 
149     xform1.eDy = (FLOAT)-4294967167.999999761;
150     ok(xform1.eDy == -4294967040.0, "float rounding error.\n");
151     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
152 
153     xform1.eDy = (FLOAT)-4294967167.999999762;
154     ok(xform1.eDy == -4294967296.0, "float rounding error.\n");
155     ok_int(CombineTransform(&xform3, &xform1, &xform2), 0);
156     ok_int(GetLastError(), ERROR_SUCCESS);
157 
158     xform2.eDy = 10000;
159     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
160 
161     set_xform(&xform1, 1000.0, 0.0, 0.0, 0.0, 0.0, 0.0);
162     xform1.eDx = (FLOAT)-4294967167.999999762;
163     xform2.eM11 = 1000.0;
164     ok_int(CombineTransform(&xform3, &xform1, &xform2), 0);
165     ok_int(GetLastError(), ERROR_SUCCESS);
166 
167     xform1.eDx = 100000.0;
168     xform2.eM11 = 100000.0;
169     ok_int(CombineTransform(&xform3, &xform1, &xform2), 0);
170     ok_int(GetLastError(), ERROR_SUCCESS);
171 
172     /* Some undefined values */
173     set_xform(&xform1, geIND, 0.0, 0.0, geINF, 0.0, 0.0);
174     xform2 = xform1;
175     SetLastError(ERROR_SUCCESS);
176     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
177     ok_xform(xform3, geIND, 0.0, 0.0, geINF, 0.0, 0.0);
178     ok_int(GetLastError(), ERROR_SUCCESS);
179 
180     set_xform(&xform2, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0);
181     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
182     ok_xform(xform3, geIND, geIND, geINF, geINF, 0.0, 0.0);
183     ok_int(GetLastError(), ERROR_SUCCESS);
184 
185     set_xform(&xform1, (FLOAT)18446743500000000000.0, 0.0, 1.0, 0.0, 0.0, 0.0);
186     xform2 = xform1;
187     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
188     ok_flt(xform3.eM11, 340282326356119260000000000000000000000.0);
189 
190     xform1.eM11 = (FLOAT)18446745000000000000.0;
191     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
192     ok_flt(xform3.eM11, 340282346638528860000000000000000000000.0);
193 
194     xform1.eM11 = (FLOAT)18446746000000000000.0;
195     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
196     ok_long(*(DWORD*)&xform3.eM11, 0x7f800000);
197 
198     /* zero matrix + 1 invalid */
199     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
200     set_xform(&xform2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
201     *(DWORD*)&xform2.eM22 = 0x7f800000; // (0.0F/0.0F)
202     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
203     ok_xform(xform3, 0.0, 0.0, 0.0, geIND, 0.0, 0.0);
204 
205     /* zero matrix + 1 invalid */
206     xform2 = xform1;
207     *(DWORD*)&xform2.eM12 = 0x7f800000; // (0.0F/0.0F)
208     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
209     ok_xform(xform3, 0.0, geIND, 0.0, geIND, 0.0, 0.0);
210 
211     /* Some undefined values */
212     set_xform(&xform1, 0.0, geIND, 0.0, 0.0, 0.0, 0.0);
213     set_xform(&xform2, geIND, 0.0, 0.0, geINF, 0.0, 0.0);
214     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
215     ok_xform(xform3, geIND, geIND, geIND, geIND, 0.0, 0.0);
216 
217 }
218 
219 void Test_CombineTransform_Inval(float eInval, float eOut)
220 {
221     XFORM xform1, xform2, xform3;
222 
223     /* zero matrix / M11 invalid */
224     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
225     set_xform(&xform2, eInval, 0.0, 0.0, 0.0, 0.0, 0.0);
226     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
227     ok_xform(xform3, eOut, 0.0, 0.0, 0.0, 0.0, 0.0); // -> M21
228     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
229     ok_xform(xform3, eOut, 0.0, 0.0, 0.0, 0.0, 0.0); // -> M12
230 
231     /* zero matrix / M12 invalid */
232     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
233     set_xform(&xform2, 0.0, eInval, 0.0, 0.0, 0.0, 0.0);
234     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
235     ok_xform(xform3, 0.0, eOut, 0.0, eOut, 0.0, 0.0);
236     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
237     ok_xform(xform3, eOut, eOut, 0.0, 0.0, 0.0, 0.0);
238 
239     /* zero matrix / M21 invalid */
240     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
241     set_xform(&xform2, 0.0, 0.0, eInval, 0.0, 0.0, 0.0);
242     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
243     ok_xform(xform3, eOut, 0.0, eOut, 0.0, 0.0, 0.0);
244     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
245     ok_xform(xform3, 0.0, 0.0, eOut, eOut, 0.0, 0.0);
246 
247     /* zero matrix / M22 invalid */
248     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
249     set_xform(&xform2, 0.0, 0.0, 0.0, eInval, 0.0, 0.0);
250     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
251     ok_xform(xform3, 0.0, 0.0, 0.0, eOut, 0.0, 0.0); // -> M12
252     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
253     ok_xform(xform3, 0.0, 0.0, 0.0, eOut, 0.0, 0.0); // -> M21
254 
255     /* zero matrix / M11,M12 invalid */
256     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
257     set_xform(&xform2, eInval, eInval, 0.0, 0.0, 0.0, 0.0);
258     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
259     ok_xform(xform3, eOut, eOut, eOut, 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 / M11,M21 invalid */
264     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
265     set_xform(&xform2, eInval, 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, eOut, eOut, eOut, eOut, 0.0, 0.0);
270 
271     /* zero matrix / M11,M22 invalid */
272     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
273     set_xform(&xform2, eInval, 0.0, 0.0, eInval, 0.0, 0.0);
274     ok_int(CombineTransform(&xform3, &xform1, &xform2), 1);
275     ok_xform(xform3, eOut, 0.0, 0.0, eOut, 0.0, 0.0); // -> M12, M21
276     ok_int(CombineTransform(&xform3, &xform2, &xform1), 1);
277     ok_xform(xform3, eOut, 0.0, 0.0, eOut, 0.0, 0.0);
278 
279     /* zero matrix / M12,M21 invalid */
280     set_xform(&xform1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
281     set_xform(&xform2, 0.0, eInval, eInval, 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, eOut, eOut, 0.0, 0.0);
286 }
287 
288 START_TEST(CombineTransform)
289 {
290     *(DWORD*)&geINF = 0x7f800000;
291     *(DWORD*)&geIND = 0xffc00000;
292     *(DWORD*)&geQNAN = 0x7fc00000;
293 
294     Test_CombineTransform();
295 
296     Test_CombineTransform_Inval(geINF, geIND);
297     Test_CombineTransform_Inval(geIND, geIND);
298     Test_CombineTransform_Inval(geQNAN, geQNAN);
299 
300 }
301 
302