Nikolay Sivov : gdiplus: GdipInvertMatrix implementation with tests.
Alexandre Julliard
julliard at winehq.org
Tue Jul 8 06:11:15 CDT 2008
Module: wine
Branch: master
Commit: d7999a008be5d7e95fcd86019adc79b0359ae8d4
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d7999a008be5d7e95fcd86019adc79b0359ae8d4
Author: Nikolay Sivov <bunglehead at gmail.com>
Date: Tue Jul 8 01:32:36 2008 +0400
gdiplus: GdipInvertMatrix implementation with tests.
---
dlls/gdiplus/gdiplus.spec | 2 +-
dlls/gdiplus/matrix.c | 36 ++++++++++++++++++++++++++++++++----
dlls/gdiplus/tests/matrix.c | 32 ++++++++++++++++++++++++++++++++
include/gdiplusflat.h | 1 +
4 files changed, 66 insertions(+), 5 deletions(-)
diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec
index 34e094d..b40b8a2 100644
--- a/dlls/gdiplus/gdiplus.spec
+++ b/dlls/gdiplus/gdiplus.spec
@@ -413,7 +413,7 @@
@ stdcall GdipImageSelectActiveFrame(ptr ptr long)
@ stub GdipImageSetAbort
@ stub GdipInitializePalette
-@ stub GdipInvertMatrix
+@ stdcall GdipInvertMatrix(ptr)
@ stub GdipIsClipEmpty
@ stdcall GdipIsEmptyRegion(ptr ptr ptr)
@ stdcall GdipIsEqualRegion(ptr ptr ptr ptr)
diff --git a/dlls/gdiplus/matrix.c b/dlls/gdiplus/matrix.c
index dcdc2bd..8714908 100644
--- a/dlls/gdiplus/matrix.c
+++ b/dlls/gdiplus/matrix.c
@@ -50,6 +50,11 @@ static void matrix_multiply(GDIPCONST REAL * left, GDIPCONST REAL * right, REAL
memcpy(out, temp, 6 * sizeof(REAL));
}
+static REAL matrix_det(GDIPCONST GpMatrix *matrix)
+{
+ return matrix->matrix[0]*matrix->matrix[3] - matrix->matrix[1]*matrix->matrix[2];
+}
+
GpStatus WINGDIPAPI GdipCreateMatrix2(REAL m11, REAL m12, REAL m21, REAL m22,
REAL dx, REAL dy, GpMatrix **matrix)
{
@@ -158,16 +163,39 @@ GpStatus WINGDIPAPI GdipGetMatrixElements(GDIPCONST GpMatrix *matrix,
return Ok;
}
-GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix *matrix, BOOL *result)
+GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix)
{
+ GpMatrix copy;
REAL det;
+ BOOL invertible;
- if(!matrix || !result)
+ if(!matrix)
+ return InvalidParameter;
+
+ GdipIsMatrixInvertible(matrix, &invertible);
+ if(!invertible)
return InvalidParameter;
- det = matrix->matrix[0]*matrix->matrix[3] - matrix->matrix[1]*matrix->matrix[2];
+ det = matrix_det(matrix);
+
+ copy = *matrix;
+ /* store result */
+ matrix->matrix[0] = copy.matrix[3] / det;
+ matrix->matrix[1] = -copy.matrix[1] / det;
+ matrix->matrix[2] = -copy.matrix[2] / det;
+ matrix->matrix[3] = copy.matrix[0] / det;
+ matrix->matrix[4] = (copy.matrix[2]*copy.matrix[5]-copy.matrix[3]*copy.matrix[4]) / det;
+ matrix->matrix[5] = -(copy.matrix[0]*copy.matrix[5]-copy.matrix[1]*copy.matrix[4]) / det;
+
+ return Ok;
+}
+
+GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix *matrix, BOOL *result)
+{
+ if(!matrix || !result)
+ return InvalidParameter;
- *result = (fabs(det) >= 1e-5);
+ *result = (fabs(matrix_det(matrix)) >= 1e-5);
return Ok;
}
diff --git a/dlls/gdiplus/tests/matrix.c b/dlls/gdiplus/tests/matrix.c
index 7d5e798..3d3c484 100644
--- a/dlls/gdiplus/tests/matrix.c
+++ b/dlls/gdiplus/tests/matrix.c
@@ -21,6 +21,7 @@
#include <math.h>
#include "windows.h"
+#include <stdio.h>
#include "gdiplus.h"
#include "wine/test.h"
@@ -118,6 +119,36 @@ static void test_isinvertible(void)
GdipDeleteMatrix(matrix);
}
+static void test_invert(void)
+{
+ GpStatus status;
+ GpMatrix *matrix = NULL;
+ GpMatrix *inverted = NULL;
+ BOOL equal;
+
+ /* NULL */
+ status = GdipInvertMatrix(NULL);
+ expect(InvalidParameter, status);
+
+ /* noninvertible */
+ GdipCreateMatrix2(2.0, -1.0, 6.0, -3.0, 2.2, 3.0, &matrix);
+ status = GdipInvertMatrix(matrix);
+ expect(InvalidParameter, status);
+ GdipDeleteMatrix(matrix);
+
+ /* invertible */
+ GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix);
+ status = GdipInvertMatrix(matrix);
+ expect(Ok, status);
+
+ GdipCreateMatrix2(1.0/9.0, 2.0/9.0, 4.0/9.0, -1.0/9.0, -2.0, -1.0, &inverted);
+ GdipIsMatrixEqual(matrix, inverted, &equal);
+ expect(TRUE, equal);
+
+ GdipDeleteMatrix(inverted);
+ GdipDeleteMatrix(matrix);
+}
+
START_TEST(matrix)
{
struct GdiplusStartupInput gdiplusStartupInput;
@@ -133,6 +164,7 @@ START_TEST(matrix)
test_constructor_destructor();
test_transform();
test_isinvertible();
+ test_invert();
GdiplusShutdown(gdiplusToken);
}
diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h
index 92cb286..cdc2db0 100644
--- a/include/gdiplusflat.h
+++ b/include/gdiplusflat.h
@@ -262,6 +262,7 @@ GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix**);
GpStatus WINGDIPAPI GdipCreateMatrix2(REAL,REAL,REAL,REAL,REAL,REAL,GpMatrix**);
GpStatus WINGDIPAPI GdipCreateMatrix3(GDIPCONST GpRectF *,GDIPCONST GpPointF*,GpMatrix**);
GpStatus WINGDIPAPI GdipCreateMatrix3I(GDIPCONST GpRect*,GDIPCONST GpPoint*,GpMatrix**);
+GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix*);
GpStatus WINGDIPAPI GdipIsMatrixEqual(GDIPCONST GpMatrix*, GDIPCONST GpMatrix*, BOOL*);
GpStatus WINGDIPAPI GdipIsMatrixIdentity(GDIPCONST GpMatrix*, BOOL*);
GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix*, BOOL*);
More information about the wine-cvs
mailing list