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