From d7999a008be5d7e95fcd86019adc79b0359ae8d4 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Tue, 8 Jul 2008 01:32:36 +0400 Subject: [PATCH] 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 34e094d1644..b40b8a26105 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 dcdc2bdb3c1..871490824fa 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 7d5e79889d2..3d3c4842eaa 100644 --- a/dlls/gdiplus/tests/matrix.c +++ b/dlls/gdiplus/tests/matrix.c @@ -21,6 +21,7 @@ #include #include "windows.h" +#include #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 92cb2866983..cdc2db0c102 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*); -- 2.11.4.GIT