Commit d7999a00 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

gdiplus: GdipInvertMatrix implementation with tests.

parent d4554ad5
......@@ -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)
......
......@@ -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;
}
......
......@@ -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);
}
......@@ -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*);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment