mf/session: Forward more events to the application.
[wine/zf.git] / dlls / gdiplus / tests / matrix.c
blob5ca0209f6a950efe691ac6b42040351d52ca76db
1 /*
2 * Unit test suite for matrices
4 * Copyright (C) 2007 Google (Evan Stade)
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.
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.
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
21 #include <math.h>
22 #include <limits.h>
24 #include "objbase.h"
25 #include "gdiplus.h"
26 #include "wine/test.h"
28 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
29 #define expectf(expected, got) ok(fabs(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
31 static BOOL compare_float(float f, float g, unsigned int ulps)
33 int x = *(int *)&f;
34 int y = *(int *)&g;
36 if (x < 0)
37 x = INT_MIN - x;
38 if (y < 0)
39 y = INT_MIN - y;
41 if (abs(x - y) > ulps)
42 return FALSE;
44 return TRUE;
47 static void test_constructor_destructor(void)
49 GpStatus status;
50 GpMatrix *matrix = NULL;
52 status = GdipCreateMatrix2(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, &matrix);
53 expect(Ok, status);
54 ok(matrix != NULL, "Expected matrix to be initialized\n");
56 status = GdipDeleteMatrix(NULL);
57 expect(InvalidParameter, status);
59 status = GdipDeleteMatrix(matrix);
60 expect(Ok, status);
63 typedef struct{
64 REAL X;
65 REAL Y;
66 } real_point;
68 static real_point transform_points[] = {
69 {1000.00, 2600.00}, /*0*/
70 {855.00, 2390.00}, /*1*/
71 {700.00, 2200.00}, /*2*/
72 {565.00, 1970.00}, /*3*/
73 {400.00, 1800.00}, /*4*/
74 {275.00, 1550.00}, /*5*/
75 {100.00, 1400.00}, /*6*/
76 {-15.00, 1130.00}, /*7*/
77 {-200.00, 1000.00}, /*8*/
78 {-305.00, 710.00} /*9*/
81 static void test_transform(void)
83 GpStatus status;
84 GpMatrix *matrix = NULL;
85 GpPointF pts[10];
86 INT i;
87 BOOL match;
89 for(i = 0; i < 10; i ++){
90 pts[i].X = i * 5.0 * (REAL)(i % 2);
91 pts[i].Y = 50.0 - i * 5.0;
94 GdipCreateMatrix2(1.0, -2.0, 30.0, 40.0, -500.0, 600.0, &matrix);
96 status = GdipTransformMatrixPoints(matrix, pts, 0);
97 expect(InvalidParameter, status);
99 status = GdipTransformMatrixPoints(matrix, pts, 10);
100 expect(Ok, status);
102 for(i = 0; i < 10; i ++){
103 match = fabs(transform_points[i].X - pts[i].X) < 2.0
104 && fabs(transform_points[i].Y - pts[i].Y) < 2.0;
106 ok(match, "Expected #%d to be (%.2f, %.2f) but got (%.2f, %.2f)\n", i,
107 transform_points[i].X, transform_points[i].Y, pts[i].X, pts[i].Y);
110 GdipDeleteMatrix(matrix);
113 static void test_isinvertible(void)
115 GpStatus status;
116 GpMatrix *matrix = NULL;
117 BOOL result;
119 /* NULL arguments */
120 status = GdipIsMatrixInvertible(NULL, &result);
121 expect(InvalidParameter, status);
122 status = GdipIsMatrixInvertible((GpMatrix*)0xdeadbeef, NULL);
123 expect(InvalidParameter, status);
124 status = GdipIsMatrixInvertible(NULL, NULL);
125 expect(InvalidParameter, status);
127 /* invertible */
128 GdipCreateMatrix2(1.0, 1.2, 2.3, -1.0, 2.0, 3.0, &matrix);
129 status = GdipIsMatrixInvertible(matrix, &result);
130 expect(Ok, status);
131 expect(TRUE, result);
132 GdipDeleteMatrix(matrix);
134 /* noninvertible */
135 GdipCreateMatrix2(2.0, -1.0, 6.0, -3.0, 2.2, 3.0, &matrix);
136 status = GdipIsMatrixInvertible(matrix, &result);
137 expect(Ok, status);
138 expect(FALSE, result);
139 GdipDeleteMatrix(matrix);
142 static void test_invert(void)
144 GpStatus status;
145 GpMatrix *matrix = NULL;
146 GpMatrix *inverted = NULL;
147 BOOL equal = FALSE;
148 REAL elems[6];
150 /* NULL */
151 status = GdipInvertMatrix(NULL);
152 expect(InvalidParameter, status);
154 /* noninvertible */
155 GdipCreateMatrix2(2.0, -1.0, 6.0, -3.0, 2.2, 3.0, &matrix);
156 status = GdipInvertMatrix(matrix);
157 expect(InvalidParameter, status);
158 GdipDeleteMatrix(matrix);
160 /* invertible */
161 GdipCreateMatrix2(3.0, -2.0, 5.0, 2.0, 6.0, 3.0, &matrix);
162 status = GdipInvertMatrix(matrix);
163 expect(Ok, status);
164 GdipCreateMatrix2(2.0/16.0, 2.0/16.0, -5.0/16.0, 3.0/16.0, 3.0/16.0, -21.0/16.0, &inverted);
165 GdipIsMatrixEqual(matrix, inverted, &equal);
166 expect(TRUE, equal);
167 GdipDeleteMatrix(matrix);
169 GdipCreateMatrix2(0.0006, 0, 0, 0.0006, 400, 400, &matrix);
170 status = GdipInvertMatrix(matrix);
171 expect(Ok, status);
172 status = GdipGetMatrixElements(matrix, elems);
173 expect(Ok, status);
174 ok(compare_float(elems[0], 1666.666504, 1), "elems[0] = %.10g\n", elems[0]);
175 ok(compare_float(elems[1], 0, 0), "elems[1] = %.10g\n", elems[1]);
176 ok(compare_float(elems[2], 0, 0), "elems[2] = %.10g\n", elems[2]);
177 ok(compare_float(elems[3], 1666.666504, 1), "elems[3] = %.10g\n", elems[3]);
178 ok(compare_float(elems[4], -666666.6875, 1), "elems[4] = %.10g\n", elems[4]);
179 ok(compare_float(elems[5], -666666.6875, 1), "elems[5] = %.10g\n", elems[5]);
181 GdipDeleteMatrix(inverted);
182 GdipDeleteMatrix(matrix);
185 static void test_shear(void)
187 GpStatus status;
188 GpMatrix *matrix = NULL;
189 GpMatrix *sheared = NULL;
190 BOOL equal;
192 /* NULL */
193 status = GdipShearMatrix(NULL, 0.0, 0.0, MatrixOrderPrepend);
194 expect(InvalidParameter, status);
196 /* X only shearing, MatrixOrderPrepend */
197 GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
198 status = GdipShearMatrix(matrix, 1.5, 0.0, MatrixOrderPrepend);
199 expect(Ok, status);
200 GdipCreateMatrix2(1.0, 2.0, 5.5, 2.0, 6.0, 3.0, &sheared);
201 GdipIsMatrixEqual(matrix, sheared, &equal);
202 expect(TRUE, equal);
203 GdipDeleteMatrix(sheared);
204 GdipDeleteMatrix(matrix);
206 /* X only shearing, MatrixOrderAppend */
207 GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
208 status = GdipShearMatrix(matrix, 1.5, 0.0, MatrixOrderAppend);
209 expect(Ok, status);
210 GdipCreateMatrix2(4.0, 2.0, 2.5, -1.0, 10.5, 3.0, &sheared);
211 GdipIsMatrixEqual(matrix, sheared, &equal);
212 expect(TRUE, equal);
213 GdipDeleteMatrix(sheared);
214 GdipDeleteMatrix(matrix);
216 /* Y only shearing, MatrixOrderPrepend */
217 GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
218 status = GdipShearMatrix(matrix, 0.0, 1.5, MatrixOrderPrepend);
219 expect(Ok, status);
220 GdipCreateMatrix2(7.0, 0.5, 4.0, -1.0, 6.0, 3.0, &sheared);
221 GdipIsMatrixEqual(matrix, sheared, &equal);
222 expect(TRUE, equal);
223 GdipDeleteMatrix(sheared);
224 GdipDeleteMatrix(matrix);
226 /* Y only shearing, MatrixOrderAppend */
227 GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
228 status = GdipShearMatrix(matrix, 0.0, 1.5, MatrixOrderAppend);
229 expect(Ok, status);
230 GdipCreateMatrix2(1.0, 3.5, 4.0, 5.0, 6.0, 12.0, &sheared);
231 GdipIsMatrixEqual(matrix, sheared, &equal);
232 expect(TRUE, equal);
233 GdipDeleteMatrix(sheared);
234 GdipDeleteMatrix(matrix);
236 /* X,Y shearing, MatrixOrderPrepend */
237 GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
238 status = GdipShearMatrix(matrix, 4.0, 1.5, MatrixOrderPrepend);
239 expect(Ok, status);
240 GdipCreateMatrix2(7.0, 0.5, 8.0, 7.0, 6.0, 3.0, &sheared);
241 GdipIsMatrixEqual(matrix, sheared, &equal);
242 expect(TRUE, equal);
243 GdipDeleteMatrix(sheared);
244 GdipDeleteMatrix(matrix);
246 /* X,Y shearing, MatrixOrderAppend */
247 GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
248 status = GdipShearMatrix(matrix, 4.0, 1.5, MatrixOrderAppend);
249 expect(Ok, status);
250 GdipCreateMatrix2(9.0, 3.5, 0.0, 5.0, 18.0, 12.0, &sheared);
251 GdipIsMatrixEqual(matrix, sheared, &equal);
252 expect(TRUE, equal);
253 GdipDeleteMatrix(sheared);
254 GdipDeleteMatrix(matrix);
257 static void test_constructor3(void)
259 /* MSDN is on crack. GdipCreateMatrix3 makes a matrix that transforms the
260 * corners of the given rectangle to the three points given. */
261 GpMatrix *matrix;
262 REAL values[6];
263 GpRectF rc;
264 GpPointF pt[3];
265 GpStatus stat;
267 rc.X = 10;
268 rc.Y = 10;
269 rc.Width = 10;
270 rc.Height = 10;
272 pt[0].X = 10;
273 pt[0].Y = 10;
274 pt[1].X = 20;
275 pt[1].Y = 10;
276 pt[2].X = 10;
277 pt[2].Y = 20;
279 stat = GdipCreateMatrix3(&rc, pt, &matrix);
280 expect(Ok, stat);
282 stat = GdipGetMatrixElements(matrix, values);
283 expect(Ok, stat);
285 expectf(1.0, values[0]);
286 expectf(0.0, values[1]);
287 expectf(0.0, values[2]);
288 expectf(1.0, values[3]);
289 expectf(0.0, values[4]);
290 expectf(0.0, values[5]);
292 GdipDeleteMatrix(matrix);
294 pt[0].X = 20;
295 pt[0].Y = 10;
296 pt[1].X = 40;
297 pt[1].Y = 10;
298 pt[2].X = 20;
299 pt[2].Y = 20;
301 stat = GdipCreateMatrix3(&rc, pt, &matrix);
302 expect(Ok, stat);
304 stat = GdipGetMatrixElements(matrix, values);
305 expect(Ok, stat);
307 expectf(2.0, values[0]);
308 expectf(0.0, values[1]);
309 expectf(0.0, values[2]);
310 expectf(1.0, values[3]);
311 expectf(0.0, values[4]);
312 expectf(0.0, values[5]);
314 GdipDeleteMatrix(matrix);
316 pt[0].X = 10;
317 pt[0].Y = 20;
318 pt[1].X = 20;
319 pt[1].Y = 30;
320 pt[2].X = 10;
321 pt[2].Y = 30;
323 stat = GdipCreateMatrix3(&rc, pt, &matrix);
324 expect(Ok, stat);
326 stat = GdipGetMatrixElements(matrix, values);
327 expect(Ok, stat);
329 expectf(1.0, values[0]);
330 expectf(1.0, values[1]);
331 expectf(0.0, values[2]);
332 expectf(1.0, values[3]);
333 expectf(0.0, values[4]);
334 expectf(0.0, values[5]);
336 GdipDeleteMatrix(matrix);
339 static void test_isidentity(void)
341 GpMatrix *matrix;
342 GpStatus stat;
343 BOOL result;
345 stat = GdipIsMatrixIdentity(NULL, NULL);
346 expect(InvalidParameter, stat);
348 stat = GdipIsMatrixIdentity(NULL, &result);
349 expect(InvalidParameter, stat);
351 stat = GdipCreateMatrix2(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
352 expect(Ok, stat);
354 stat = GdipIsMatrixIdentity(matrix, NULL);
355 expect(InvalidParameter, stat);
357 result = FALSE;
358 stat = GdipIsMatrixIdentity(matrix, &result);
359 expect(Ok, stat);
360 ok(!!result, "got %d\n", result);
362 stat = GdipSetMatrixElements(matrix, 1.0, 0.0, 0.0, 1.0, 0.1, 0.0);
363 expect(Ok, stat);
365 result = TRUE;
366 stat = GdipIsMatrixIdentity(matrix, &result);
367 expect(Ok, stat);
368 ok(!result, "got %d\n", result);
370 GdipDeleteMatrix(matrix);
373 START_TEST(matrix)
375 struct GdiplusStartupInput gdiplusStartupInput;
376 ULONG_PTR gdiplusToken;
377 HMODULE hmsvcrt;
378 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
380 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
381 hmsvcrt = LoadLibraryA("msvcrt");
382 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
383 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
385 gdiplusStartupInput.GdiplusVersion = 1;
386 gdiplusStartupInput.DebugEventCallback = NULL;
387 gdiplusStartupInput.SuppressBackgroundThread = 0;
388 gdiplusStartupInput.SuppressExternalCodecs = 0;
390 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
392 test_constructor_destructor();
393 test_transform();
394 test_isinvertible();
395 test_invert();
396 test_shear();
397 test_constructor3();
398 test_isidentity();
400 GdiplusShutdown(gdiplusToken);