gdiplus: GdipInvertMatrix implementation with tests.
This commit is contained in:
parent
d4554ad5d5
commit
d7999a008b
|
@ -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 GdipInvertMatrix(GpMatrix *matrix)
|
||||
{
|
||||
GpMatrix copy;
|
||||
REAL det;
|
||||
BOOL invertible;
|
||||
|
||||
if(!matrix)
|
||||
return InvalidParameter;
|
||||
|
||||
GdipIsMatrixInvertible(matrix, &invertible);
|
||||
if(!invertible)
|
||||
return InvalidParameter;
|
||||
|
||||
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)
|
||||
{
|
||||
REAL det;
|
||||
|
||||
if(!matrix || !result)
|
||||
return InvalidParameter;
|
||||
|
||||
det = matrix->matrix[0]*matrix->matrix[3] - matrix->matrix[1]*matrix->matrix[2];
|
||||
|
||||
*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*);
|
||||
|
|
Loading…
Reference in New Issue