diff --git a/dlls/gdiplus/gdiplus.spec b/dlls/gdiplus/gdiplus.spec index b40b8a2610..f62ccaa9ae 100644 --- a/dlls/gdiplus/gdiplus.spec +++ b/dlls/gdiplus/gdiplus.spec @@ -598,7 +598,7 @@ @ stdcall GdipSetTextureTransform(ptr ptr) @ stub GdipSetTextureWrapMode @ stdcall GdipSetWorldTransform(ptr ptr) -@ stub GdipShearMatrix +@ stdcall GdipShearMatrix(ptr long long long) @ stdcall GdipStartPathFigure(ptr) @ stub GdipStringFormatGetGenericDefault @ stub GdipStringFormatGetGenericTypographic diff --git a/dlls/gdiplus/matrix.c b/dlls/gdiplus/matrix.c index 871490824f..a29508db8b 100644 --- a/dlls/gdiplus/matrix.c +++ b/dlls/gdiplus/matrix.c @@ -280,6 +280,30 @@ GpStatus WINGDIPAPI GdipSetMatrixElements(GpMatrix *matrix, REAL m11, REAL m12, return Ok; } +GpStatus WINGDIPAPI GdipShearMatrix(GpMatrix *matrix, REAL shearX, REAL shearY, + GpMatrixOrder order) +{ + REAL shear[6]; + + if(!matrix) + return InvalidParameter; + + /* prepare transformation matrix */ + shear[0] = 1.0; + shear[1] = shearY; + shear[2] = shearX; + shear[3] = 1.0; + shear[4] = 0.0; + shear[5] = 0.0; + + if(order == MatrixOrderAppend) + matrix_multiply(matrix->matrix, shear, matrix->matrix); + else + matrix_multiply(shear, matrix->matrix, matrix->matrix); + + return Ok; +} + GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count) { diff --git a/dlls/gdiplus/tests/matrix.c b/dlls/gdiplus/tests/matrix.c index 3d3c4842ea..16c15173ea 100644 --- a/dlls/gdiplus/tests/matrix.c +++ b/dlls/gdiplus/tests/matrix.c @@ -149,6 +149,78 @@ static void test_invert(void) GdipDeleteMatrix(matrix); } +static void test_shear(void) +{ + GpStatus status; + GpMatrix *matrix = NULL; + GpMatrix *sheared = NULL; + BOOL equal; + + /* NULL */ + status = GdipShearMatrix(NULL, 0.0, 0.0, MatrixOrderPrepend); + expect(InvalidParameter, status); + + /* X only shearing, MatrixOrderPrepend */ + GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix); + status = GdipShearMatrix(matrix, 1.5, 0.0, MatrixOrderPrepend); + expect(Ok, status); + GdipCreateMatrix2(1.0, 2.0, 5.5, 2.0, 6.0, 3.0, &sheared); + GdipIsMatrixEqual(matrix, sheared, &equal); + expect(TRUE, equal); + GdipDeleteMatrix(sheared); + GdipDeleteMatrix(matrix); + + /* X only shearing, MatrixOrderAppend */ + GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix); + status = GdipShearMatrix(matrix, 1.5, 0.0, MatrixOrderAppend); + expect(Ok, status); + GdipCreateMatrix2(4.0, 2.0, 2.5, -1.0, 10.5, 3.0, &sheared); + GdipIsMatrixEqual(matrix, sheared, &equal); + expect(TRUE, equal); + GdipDeleteMatrix(sheared); + GdipDeleteMatrix(matrix); + + /* Y only shearing, MatrixOrderPrepend */ + GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix); + status = GdipShearMatrix(matrix, 0.0, 1.5, MatrixOrderPrepend); + expect(Ok, status); + GdipCreateMatrix2(7.0, 0.5, 4.0, -1.0, 6.0, 3.0, &sheared); + GdipIsMatrixEqual(matrix, sheared, &equal); + expect(TRUE, equal); + GdipDeleteMatrix(sheared); + GdipDeleteMatrix(matrix); + + /* Y only shearing, MatrixOrderAppend */ + GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix); + status = GdipShearMatrix(matrix, 0.0, 1.5, MatrixOrderAppend); + expect(Ok, status); + GdipCreateMatrix2(1.0, 3.5, 4.0, 5.0, 6.0, 12.0, &sheared); + GdipIsMatrixEqual(matrix, sheared, &equal); + expect(TRUE, equal); + GdipDeleteMatrix(sheared); + GdipDeleteMatrix(matrix); + + /* X,Y shearing, MatrixOrderPrepend */ + GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix); + status = GdipShearMatrix(matrix, 4.0, 1.5, MatrixOrderPrepend); + expect(Ok, status); + GdipCreateMatrix2(7.0, 0.5, 8.0, 7.0, 6.0, 3.0, &sheared); + GdipIsMatrixEqual(matrix, sheared, &equal); + expect(TRUE, equal); + GdipDeleteMatrix(sheared); + GdipDeleteMatrix(matrix); + + /* X,Y shearing, MatrixOrderAppend */ + GdipCreateMatrix2(1.0, 2.0, 4.0, -1.0, 6.0, 3.0, &matrix); + status = GdipShearMatrix(matrix, 4.0, 1.5, MatrixOrderAppend); + expect(Ok, status); + GdipCreateMatrix2(9.0, 3.5, 0.0, 5.0, 18.0, 12.0, &sheared); + GdipIsMatrixEqual(matrix, sheared, &equal); + expect(TRUE, equal); + GdipDeleteMatrix(sheared); + GdipDeleteMatrix(matrix); +} + START_TEST(matrix) { struct GdiplusStartupInput gdiplusStartupInput; @@ -165,6 +237,7 @@ START_TEST(matrix) test_transform(); test_isinvertible(); test_invert(); + test_shear(); GdiplusShutdown(gdiplusToken); } diff --git a/include/gdiplusflat.h b/include/gdiplusflat.h index cdc2db0c10..1cc90c59f8 100644 --- a/include/gdiplusflat.h +++ b/include/gdiplusflat.h @@ -263,6 +263,7 @@ 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 GdipShearMatrix(GpMatrix*,REAL,REAL,GpMatrixOrder); GpStatus WINGDIPAPI GdipIsMatrixEqual(GDIPCONST GpMatrix*, GDIPCONST GpMatrix*, BOOL*); GpStatus WINGDIPAPI GdipIsMatrixIdentity(GDIPCONST GpMatrix*, BOOL*); GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix*, BOOL*);