gdiplus: Add more accurate algorithm for inverting scaling and translation matrices in GdipInvertMatrix.
Signed-off-by: Piotr Caban <piotr@codeweavers.com> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
dee9eaa248
commit
595959c771
|
@ -197,6 +197,17 @@ GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix)
|
|||
if(!invertible)
|
||||
return InvalidParameter;
|
||||
|
||||
/* optimize inverting simple scaling and translation matrices */
|
||||
if(matrix->matrix[1] == 0 && matrix->matrix[2] == 0)
|
||||
{
|
||||
matrix->matrix[4] = -matrix->matrix[4] / matrix->matrix[0];
|
||||
matrix->matrix[5] = -matrix->matrix[5] / matrix->matrix[3];
|
||||
matrix->matrix[0] = 1 / matrix->matrix[0];
|
||||
matrix->matrix[3] = 1 / matrix->matrix[3];
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
det = matrix_det(matrix);
|
||||
|
||||
copy = *matrix;
|
||||
|
@ -218,7 +229,10 @@ GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix *matrix, BOOL *res
|
|||
if(!matrix || !result)
|
||||
return InvalidParameter;
|
||||
|
||||
*result = (fabs(matrix_det(matrix)) >= 1e-5);
|
||||
if(matrix->matrix[1] == 0 && matrix->matrix[2] == 0)
|
||||
*result = matrix->matrix[0] != 0 && matrix->matrix[3] != 0;
|
||||
else
|
||||
*result = (fabs(matrix_det(matrix)) >= 1e-5);
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "objbase.h"
|
||||
#include "gdiplus.h"
|
||||
|
@ -27,6 +28,22 @@
|
|||
#define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
|
||||
#define expectf(expected, got) ok(fabs(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
|
||||
|
||||
static BOOL compare_float(float f, float g, unsigned int ulps)
|
||||
{
|
||||
int x = *(int *)&f;
|
||||
int y = *(int *)&g;
|
||||
|
||||
if (x < 0)
|
||||
x = INT_MIN - x;
|
||||
if (y < 0)
|
||||
y = INT_MIN - y;
|
||||
|
||||
if (abs(x - y) > ulps)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void test_constructor_destructor(void)
|
||||
{
|
||||
GpStatus status;
|
||||
|
@ -128,6 +145,7 @@ static void test_invert(void)
|
|||
GpMatrix *matrix = NULL;
|
||||
GpMatrix *inverted = NULL;
|
||||
BOOL equal = FALSE;
|
||||
REAL elems[6];
|
||||
|
||||
/* NULL */
|
||||
status = GdipInvertMatrix(NULL);
|
||||
|
@ -147,6 +165,18 @@ static void test_invert(void)
|
|||
GdipIsMatrixEqual(matrix, inverted, &equal);
|
||||
expect(TRUE, equal);
|
||||
|
||||
GdipCreateMatrix2(0.0006, 0, 0, 0.0006, 400, 400, &matrix);
|
||||
status = GdipInvertMatrix(matrix);
|
||||
expect(Ok, status);
|
||||
status = GdipGetMatrixElements(matrix, elems);
|
||||
expect(Ok, status);
|
||||
ok(compare_float(elems[0], 1666.666504, 1), "elems[0] = %.10g\n", elems[0]);
|
||||
ok(compare_float(elems[1], 0, 0), "elems[1] = %.10g\n", elems[1]);
|
||||
ok(compare_float(elems[2], 0, 0), "elems[2] = %.10g\n", elems[2]);
|
||||
ok(compare_float(elems[3], 1666.666504, 1), "elems[3] = %.10g\n", elems[3]);
|
||||
ok(compare_float(elems[4], -666666.6875, 1), "elems[4] = %.10g\n", elems[4]);
|
||||
ok(compare_float(elems[5], -666666.6875, 1), "elems[5] = %.10g\n", elems[5]);
|
||||
|
||||
GdipDeleteMatrix(inverted);
|
||||
GdipDeleteMatrix(matrix);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue