ReactOS 0.4.15-dev-7897-g78dc504
matrix.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 Google (Evan Stade)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#include <stdarg.h>
20#include <math.h>
21
22#include "windef.h"
23#include "winbase.h"
24#include "wingdi.h"
25
26#include "objbase.h"
27
28#include "gdiplus.h"
29#include "gdiplus_private.h"
30#include "wine/debug.h"
31
33
34/* Multiplies two matrices of the form
35 *
36 * idx:0 idx:1 0
37 * idx:2 idx:3 0
38 * idx:4 idx:5 1
39 *
40 * and puts the output in out.
41 * */
43{
44 REAL temp[6];
45 int i, odd;
46
47 for(i = 0; i < 6; i++){
48 odd = i % 2;
49 temp[i] = left[i - odd] * right[odd] + left[i - odd + 1] * right[odd + 2] +
50 (i >= 4 ? right[odd + 4] : 0.0);
51 }
52
53 memcpy(out, temp, 6 * sizeof(REAL));
54}
55
57{
58 return matrix->matrix[0]*matrix->matrix[3] - matrix->matrix[1]*matrix->matrix[2];
59}
60
63{
64 TRACE("(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p)\n", m11, m12, m21, m22, dx, dy, matrix);
65
66 if(!matrix)
67 return InvalidParameter;
68
69 *matrix = heap_alloc_zero(sizeof(GpMatrix));
70 if(!*matrix) return OutOfMemory;
71
72 /* first row */
73 (*matrix)->matrix[0] = m11;
74 (*matrix)->matrix[1] = m12;
75 /* second row */
76 (*matrix)->matrix[2] = m21;
77 (*matrix)->matrix[3] = m22;
78 /* third row */
79 (*matrix)->matrix[4] = dx;
80 (*matrix)->matrix[5] = dy;
81
82 return Ok;
83}
84
87{
88 REAL m11, m12, m21, m22, dx, dy;
89 TRACE("(%p, %p, %p)\n", rect, pt, matrix);
90
91 if(!matrix || !pt)
92 return InvalidParameter;
93
94 m11 = (pt[1].X - pt[0].X) / rect->Width;
95 m21 = (pt[2].X - pt[0].X) / rect->Height;
96 dx = pt[0].X - m11 * rect->X - m21 * rect->Y;
97 m12 = (pt[1].Y - pt[0].Y) / rect->Width;
98 m22 = (pt[2].Y - pt[0].Y) / rect->Height;
99 dy = pt[0].Y - m12 * rect->X - m22 * rect->Y;
100
101 return GdipCreateMatrix2(m11, m12, m21, m22, dx, dy, matrix);
102}
103
106{
107 GpRectF rectF;
108 GpPointF ptF[3];
109 int i;
110
111 TRACE("(%p, %p, %p)\n", rect, pt, matrix);
112
113 rectF.X = (REAL)rect->X;
114 rectF.Y = (REAL)rect->Y;
115 rectF.Width = (REAL)rect->Width;
116 rectF.Height = (REAL)rect->Height;
117
118 for (i = 0; i < 3; i++) {
119 ptF[i].X = (REAL)pt[i].X;
120 ptF[i].Y = (REAL)pt[i].Y;
121 }
122 return GdipCreateMatrix3(&rectF, ptF, matrix);
123}
124
126{
127 TRACE("(%p, %p)\n", matrix, clone);
128
129 if(!matrix || !clone)
130 return InvalidParameter;
131
132 *clone = heap_alloc_zero(sizeof(GpMatrix));
133 if(!*clone) return OutOfMemory;
134
135 **clone = *matrix;
136
137 return Ok;
138}
139
141{
142 TRACE("(%p)\n", matrix);
143
144 if(!matrix)
145 return InvalidParameter;
146
147 *matrix = heap_alloc_zero(sizeof(GpMatrix));
148 if(!*matrix) return OutOfMemory;
149
150 (*matrix)->matrix[0] = 1.0;
151 (*matrix)->matrix[1] = 0.0;
152 (*matrix)->matrix[2] = 0.0;
153 (*matrix)->matrix[3] = 1.0;
154 (*matrix)->matrix[4] = 0.0;
155 (*matrix)->matrix[5] = 0.0;
156
157 return Ok;
158}
159
161{
162 TRACE("(%p)\n", matrix);
163
164 if(!matrix)
165 return InvalidParameter;
166
168
169 return Ok;
170}
171
173 REAL *out)
174{
175 TRACE("(%p, %p)\n", matrix, out);
176
177 if(!matrix || !out)
178 return InvalidParameter;
179
180 memcpy(out, matrix->matrix, sizeof(matrix->matrix));
181
182 return Ok;
183}
184
186{
188 REAL det;
189 BOOL invertible;
190
191 TRACE("(%p)\n", matrix);
192
193 if(!matrix)
194 return InvalidParameter;
195
196 GdipIsMatrixInvertible(matrix, &invertible);
197 if(!invertible)
198 return InvalidParameter;
199
200 /* optimize inverting simple scaling and translation matrices */
201 if(matrix->matrix[1] == 0 && matrix->matrix[2] == 0)
202 {
203 matrix->matrix[4] = -matrix->matrix[4] / matrix->matrix[0];
204 matrix->matrix[5] = -matrix->matrix[5] / matrix->matrix[3];
205 matrix->matrix[0] = 1 / matrix->matrix[0];
206 matrix->matrix[3] = 1 / matrix->matrix[3];
207
208 return Ok;
209 }
210
211 det = matrix_det(matrix);
212
213 copy = *matrix;
214 /* store result */
215 matrix->matrix[0] = copy.matrix[3] / det;
216 matrix->matrix[1] = -copy.matrix[1] / det;
217 matrix->matrix[2] = -copy.matrix[2] / det;
218 matrix->matrix[3] = copy.matrix[0] / det;
219 matrix->matrix[4] = (copy.matrix[2]*copy.matrix[5]-copy.matrix[3]*copy.matrix[4]) / det;
220 matrix->matrix[5] = -(copy.matrix[0]*copy.matrix[5]-copy.matrix[1]*copy.matrix[4]) / det;
221
222 return Ok;
223}
224
226{
227 TRACE("(%p, %p)\n", matrix, result);
228
229 if(!matrix || !result)
230 return InvalidParameter;
231
232 if(matrix->matrix[1] == 0 && matrix->matrix[2] == 0)
233 *result = matrix->matrix[0] != 0 && matrix->matrix[3] != 0;
234 else
235 *result = (fabs(matrix_det(matrix)) >= 1e-5);
236
237 return Ok;
238}
239
242{
243 TRACE("(%p, %p, %d)\n", matrix, matrix2, order);
244
245 if(!matrix || !matrix2)
246 return InvalidParameter;
247
249 matrix_multiply(matrix->matrix, matrix2->matrix, matrix->matrix);
250 else if (order == MatrixOrderPrepend)
251 matrix_multiply(matrix2->matrix, matrix->matrix, matrix->matrix);
252 else
253 return InvalidParameter;
254
255 return Ok;
256}
257
260{
261 REAL cos_theta, sin_theta, rotate[6];
262
263 TRACE("(%p, %.2f, %d)\n", matrix, angle, order);
264
265 if(!matrix)
266 return InvalidParameter;
267
269 cos_theta = cos(angle);
270 sin_theta = sin(angle);
271
272 rotate[0] = cos_theta;
273 rotate[1] = sin_theta;
274 rotate[2] = -sin_theta;
275 rotate[3] = cos_theta;
276 rotate[4] = 0.0;
277 rotate[5] = 0.0;
278
280 matrix_multiply(matrix->matrix, rotate, matrix->matrix);
281 else if (order == MatrixOrderPrepend)
282 matrix_multiply(rotate, matrix->matrix, matrix->matrix);
283 else
284 return InvalidParameter;
285
286 return Ok;
287}
288
291{
292 REAL scale[6];
293
294 TRACE("(%p, %.2f, %.2f, %d)\n", matrix, scaleX, scaleY, order);
295
296 if(!matrix)
297 return InvalidParameter;
298
299 scale[0] = scaleX;
300 scale[1] = 0.0;
301 scale[2] = 0.0;
302 scale[3] = scaleY;
303 scale[4] = 0.0;
304 scale[5] = 0.0;
305
307 matrix_multiply(matrix->matrix, scale, matrix->matrix);
308 else if (order == MatrixOrderPrepend)
309 matrix_multiply(scale, matrix->matrix, matrix->matrix);
310 else
311 return InvalidParameter;
312
313 return Ok;
314}
315
318{
319 TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", matrix, m11, m12,
320 m21, m22, dx, dy);
321
322 if(!matrix)
323 return InvalidParameter;
324
325 matrix->matrix[0] = m11;
326 matrix->matrix[1] = m12;
327 matrix->matrix[2] = m21;
328 matrix->matrix[3] = m22;
329 matrix->matrix[4] = dx;
330 matrix->matrix[5] = dy;
331
332 return Ok;
333}
334
337{
338 REAL shear[6];
339
340 TRACE("(%p, %.2f, %.2f, %d)\n", matrix, shearX, shearY, order);
341
342 if(!matrix)
343 return InvalidParameter;
344
345 /* prepare transformation matrix */
346 shear[0] = 1.0;
347 shear[1] = shearY;
348 shear[2] = shearX;
349 shear[3] = 1.0;
350 shear[4] = 0.0;
351 shear[5] = 0.0;
352
354 matrix_multiply(matrix->matrix, shear, matrix->matrix);
355 else if (order == MatrixOrderPrepend)
356 matrix_multiply(shear, matrix->matrix, matrix->matrix);
357 else
358 return InvalidParameter;
359
360 return Ok;
361}
362
364 INT count)
365{
366 REAL x, y;
367 INT i;
368
369 TRACE("(%p, %p, %d)\n", matrix, pts, count);
370
371 if(!matrix || !pts || count <= 0)
372 return InvalidParameter;
373
374 for(i = 0; i < count; i++)
375 {
376 x = pts[i].X;
377 y = pts[i].Y;
378
379 pts[i].X = x * matrix->matrix[0] + y * matrix->matrix[2] + matrix->matrix[4];
380 pts[i].Y = x * matrix->matrix[1] + y * matrix->matrix[3] + matrix->matrix[5];
381 }
382
383 return Ok;
384}
385
387{
388 GpPointF *ptsF;
390 INT i;
391
392 TRACE("(%p, %p, %d)\n", matrix, pts, count);
393
394 if(count <= 0)
395 return InvalidParameter;
396
397 ptsF = heap_alloc_zero(sizeof(GpPointF) * count);
398 if(!ptsF)
399 return OutOfMemory;
400
401 for(i = 0; i < count; i++){
402 ptsF[i].X = (REAL)pts[i].X;
403 ptsF[i].Y = (REAL)pts[i].Y;
404 }
405
407
408 if(ret == Ok)
409 for(i = 0; i < count; i++){
410 pts[i].X = gdip_round(ptsF[i].X);
411 pts[i].Y = gdip_round(ptsF[i].Y);
412 }
413 heap_free(ptsF);
414
415 return ret;
416}
417
419 REAL offsetY, GpMatrixOrder order)
420{
421 REAL translate[6];
422
423 TRACE("(%p, %.2f, %.2f, %d)\n", matrix, offsetX, offsetY, order);
424
425 if(!matrix)
426 return InvalidParameter;
427
428 translate[0] = 1.0;
429 translate[1] = 0.0;
430 translate[2] = 0.0;
431 translate[3] = 1.0;
432 translate[4] = offsetX;
433 translate[5] = offsetY;
434
436 matrix_multiply(matrix->matrix, translate, matrix->matrix);
437 else if (order == MatrixOrderPrepend)
438 matrix_multiply(translate, matrix->matrix, matrix->matrix);
439 else
440 return InvalidParameter;
441
442 return Ok;
443}
444
446{
447 REAL x, y;
448 INT i;
449
450 TRACE("(%p, %p, %d)\n", matrix, pts, count);
451
452 if(!matrix || !pts || count <= 0)
453 return InvalidParameter;
454
455 for(i = 0; i < count; i++)
456 {
457 x = pts[i].X;
458 y = pts[i].Y;
459
460 pts[i].X = x * matrix->matrix[0] + y * matrix->matrix[2];
461 pts[i].Y = x * matrix->matrix[1] + y * matrix->matrix[3];
462 }
463
464 return Ok;
465}
466
468{
469 GpPointF *ptsF;
471 INT i;
472
473 TRACE("(%p, %p, %d)\n", matrix, pts, count);
474
475 if(count <= 0)
476 return InvalidParameter;
477
478 ptsF = heap_alloc_zero(sizeof(GpPointF) * count);
479 if(!ptsF)
480 return OutOfMemory;
481
482 for(i = 0; i < count; i++){
483 ptsF[i].X = (REAL)pts[i].X;
484 ptsF[i].Y = (REAL)pts[i].Y;
485 }
486
488 /* store back */
489 if(ret == Ok)
490 for(i = 0; i < count; i++){
491 pts[i].X = gdip_round(ptsF[i].X);
492 pts[i].Y = gdip_round(ptsF[i].Y);
493 }
494 heap_free(ptsF);
495
496 return ret;
497}
498
500 BOOL *result)
501{
502 TRACE("(%p, %p, %p)\n", matrix, matrix2, result);
503
504 if(!matrix || !matrix2 || !result)
505 return InvalidParameter;
506 /* based on single array member of GpMatrix */
507 *result = (memcmp(matrix->matrix, matrix2->matrix, sizeof(GpMatrix)) == 0);
508
509 return Ok;
510}
511
513{
514 static const GpMatrix identity =
515 {
516 { 1.0, 0.0,
517 0.0, 1.0,
518 0.0, 0.0 }
519 };
520
521 TRACE("(%p, %p)\n", matrix, result);
522
523 if(!matrix || !result)
524 return InvalidParameter;
525
527}
_STLP_MOVE_TO_STD_NAMESPACE void rotate(_ForwardIter __first, _ForwardIter __middle, _ForwardIter __last)
Definition: _algo.c:519
_STLP_DECLSPEC complex< float > _STLP_CALL cos(const complex< float > &)
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
float REAL
Definition: types.h:41
#define Y(I)
#define m22
#define m11
#define m12
#define m21
GpStatus WINGDIPAPI GdipScaleMatrix(GpMatrix *matrix, REAL scaleX, REAL scaleY, GpMatrixOrder order)
Definition: matrix.c:289
GpStatus WINGDIPAPI GdipMultiplyMatrix(GpMatrix *matrix, GDIPCONST GpMatrix *matrix2, GpMatrixOrder order)
Definition: matrix.c:240
GpStatus WINGDIPAPI GdipCreateMatrix2(REAL m11, REAL m12, REAL m21, REAL m22, REAL dx, REAL dy, GpMatrix **matrix)
Definition: matrix.c:61
GpStatus WINGDIPAPI GdipShearMatrix(GpMatrix *matrix, REAL shearX, REAL shearY, GpMatrixOrder order)
Definition: matrix.c:335
GpStatus WINGDIPAPI GdipTranslateMatrix(GpMatrix *matrix, REAL offsetX, REAL offsetY, GpMatrixOrder order)
Definition: matrix.c:418
static void matrix_multiply(GDIPCONST REAL *left, GDIPCONST REAL *right, REAL *out)
Definition: matrix.c:42
GpStatus WINGDIPAPI GdipCreateMatrix3(GDIPCONST GpRectF *rect, GDIPCONST GpPointF *pt, GpMatrix **matrix)
Definition: matrix.c:85
GpStatus WINGDIPAPI GdipIsMatrixEqual(GDIPCONST GpMatrix *matrix, GDIPCONST GpMatrix *matrix2, BOOL *result)
Definition: matrix.c:499
GpStatus WINGDIPAPI GdipVectorTransformMatrixPointsI(GpMatrix *matrix, GpPoint *pts, INT count)
Definition: matrix.c:467
GpStatus WINGDIPAPI GdipVectorTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count)
Definition: matrix.c:445
GpStatus WINGDIPAPI GdipGetMatrixElements(GDIPCONST GpMatrix *matrix, REAL *out)
Definition: matrix.c:172
GpStatus WINGDIPAPI GdipSetMatrixElements(GpMatrix *matrix, REAL m11, REAL m12, REAL m21, REAL m22, REAL dx, REAL dy)
Definition: matrix.c:316
GpStatus WINGDIPAPI GdipRotateMatrix(GpMatrix *matrix, REAL angle, GpMatrixOrder order)
Definition: matrix.c:258
GpStatus WINGDIPAPI GdipIsMatrixIdentity(GDIPCONST GpMatrix *matrix, BOOL *result)
Definition: matrix.c:512
GpStatus WINGDIPAPI GdipDeleteMatrix(GpMatrix *matrix)
Definition: matrix.c:160
GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count)
Definition: matrix.c:363
GpStatus WINGDIPAPI GdipTransformMatrixPointsI(GpMatrix *matrix, GpPoint *pts, INT count)
Definition: matrix.c:386
GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix **matrix)
Definition: matrix.c:140
GpStatus WINGDIPAPI GdipCreateMatrix3I(GDIPCONST GpRect *rect, GDIPCONST GpPoint *pt, GpMatrix **matrix)
Definition: matrix.c:104
GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix)
Definition: matrix.c:185
GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix *matrix, BOOL *result)
Definition: matrix.c:225
static REAL matrix_det(GDIPCONST GpMatrix *matrix)
Definition: matrix.c:56
GpStatus WINGDIPAPI GdipCloneMatrix(GpMatrix *matrix, GpMatrix **clone)
Definition: matrix.c:125
#define pt(x, y)
Definition: drawing.c:79
unsigned int BOOL
Definition: ntddk_ex.h:94
static INT gdip_round(REAL x)
static REAL deg2rad(REAL degrees)
MatrixOrder
Definition: gdiplusenums.h:187
@ MatrixOrderAppend
Definition: gdiplusenums.h:189
@ MatrixOrderPrepend
Definition: gdiplusenums.h:188
#define GDIPCONST
Definition: gdiplusflat.h:24
#define WINGDIPAPI
Definition: gdiplusflat.h:22
Status
Definition: gdiplustypes.h:25
@ Ok
Definition: gdiplustypes.h:26
@ InvalidParameter
Definition: gdiplustypes.h:28
@ OutOfMemory
Definition: gdiplustypes.h:29
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLdouble GLdouble right
Definition: glext.h:10859
GLuint GLenum matrix
Definition: glext.h:9407
GLint left
Definition: glext.h:7726
GLfloat angle
Definition: glext.h:10853
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
Definition: fabs.c:17
#define e
Definition: ke_i.h:82
GLint dy
Definition: linetemp.h:97
GLint dx
Definition: linetemp.h:97
#define odd(x)
Definition: bidi.c:51
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static void translate(POINT *pt, UINT count, const XFORM *xform)
Definition: metafile.c:2586
static FILE * out
Definition: regtests2xml.c:44
static calc_node_t temp
Definition: rpn_ieee.c:38
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
REAL Y
Definition: gdiplustypes.h:649
REAL X
Definition: gdiplustypes.h:648
REAL Height
Definition: gdiplustypes.h:664
REAL X
Definition: gdiplustypes.h:661
REAL Width
Definition: gdiplustypes.h:663
REAL Y
Definition: gdiplustypes.h:662
Definition: unary.h:11
int32_t INT
Definition: typedefs.h:58
int ret