diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c index 5e5883f88ebf31d1999ecc117a16e23afcfd9ca7..4762669975e69c8240932e539afc236ccfd3dd45 100644 --- a/dlls/gdiplus/graphics.c +++ b/dlls/gdiplus/graphics.c @@ -3592,15 +3592,71 @@ GpStatus WINGDIPAPI GdipGetClip(GpGraphics *graphics, GpRegion *region) GpStatus WINGDIPAPI GdipTransformPoints(GpGraphics *graphics, GpCoordinateSpace dst_space, GpCoordinateSpace src_space, GpPointF *points, INT count) { + GpMatrix *matrix; + GpStatus stat; + REAL unitscale; + if(!graphics || !points || count <= 0) return InvalidParameter; if(graphics->busy) return ObjectBusy; - FIXME("(%p, %d, %d, %p, %d): stub\n", graphics, dst_space, src_space, points, count); + TRACE("(%p, %d, %d, %p, %d)\n", graphics, dst_space, src_space, points, count); - return NotImplemented; + if (src_space == dst_space) return Ok; + + stat = GdipCreateMatrix(&matrix); + if (stat == Ok) + { + unitscale = convert_unit(graphics->hdc, graphics->unit); + + if(graphics->unit != UnitDisplay) + unitscale *= graphics->scale; + + /* transform from src_space to CoordinateSpacePage */ + switch (src_space) + { + case CoordinateSpaceWorld: + GdipMultiplyMatrix(matrix, graphics->worldtrans, MatrixOrderAppend); + break; + case CoordinateSpacePage: + break; + case CoordinateSpaceDevice: + GdipScaleMatrix(matrix, 1.0/unitscale, 1.0/unitscale, MatrixOrderAppend); + break; + } + + /* transform from CoordinateSpacePage to dst_space */ + switch (dst_space) + { + case CoordinateSpaceWorld: + { + GpMatrix *inverted_transform; + stat = GdipCloneMatrix(graphics->worldtrans, &inverted_transform); + if (stat == Ok) + { + stat = GdipInvertMatrix(inverted_transform); + if (stat == Ok) + GdipMultiplyMatrix(matrix, inverted_transform, MatrixOrderAppend); + GdipDeleteMatrix(inverted_transform); + } + break; + } + case CoordinateSpacePage: + break; + case CoordinateSpaceDevice: + GdipScaleMatrix(matrix, unitscale, unitscale, MatrixOrderAppend); + break; + } + + if (stat == Ok) + stat = GdipTransformMatrixPoints(matrix, points, count); + + GdipDeleteMatrix(matrix); + } + + return stat; } GpStatus WINGDIPAPI GdipTransformPointsI(GpGraphics *graphics, GpCoordinateSpace dst_space, diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c index 71991511072f818f76db22ce25fa0519f25c1755..510a1489a5424c05dc026ac3fb3251393059a001 100644 --- a/dlls/gdiplus/tests/graphics.c +++ b/dlls/gdiplus/tests/graphics.c @@ -22,8 +22,10 @@ #include "gdiplus.h" #include "wingdi.h" #include "wine/test.h" +#include <math.h> #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) #define TABLE_LEN (23) static void test_constructor_destructor(void) @@ -767,17 +769,11 @@ static void test_transformpoints(void) GpStatus status; GpGraphics *graphics = NULL; HDC hdc = GetDC(0); - GpPointF ptf[5]; - INT i; + GpPointF ptf[2]; status = GdipCreateFromHDC(hdc, &graphics); expect(Ok, status); - for(i = 0; i < 5; i++){ - ptf[i].X = 200.0 + i * 50.0 * (i % 2); - ptf[i].Y = 200.0 + i * 50.0 * !(i % 2); - } - /* NULL arguments */ status = GdipTransformPoints(NULL, CoordinateSpacePage, CoordinateSpaceWorld, NULL, 0); expect(InvalidParameter, status); @@ -788,6 +784,90 @@ static void test_transformpoints(void) status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, -1); expect(InvalidParameter, status); + ptf[0].X = 1.0; + ptf[0].Y = 0.0; + ptf[1].X = 0.0; + ptf[1].Y = 1.0; + status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, ptf, 2); + expect(Ok, status); + expectf(1.0, ptf[0].X); + expectf(0.0, ptf[0].Y); + expectf(0.0, ptf[1].X); + expectf(1.0, ptf[1].Y); + + status = GdipTranslateWorldTransform(graphics, 5.0, 5.0, MatrixOrderAppend); + expect(Ok, status); + status = GdipSetPageUnit(graphics, UnitPixel); + expect(Ok, status); + status = GdipSetPageScale(graphics, 3.0); + expect(Ok, status); + + ptf[0].X = 1.0; + ptf[0].Y = 0.0; + ptf[1].X = 0.0; + ptf[1].Y = 1.0; + status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, ptf, 2); + expect(Ok, status); + expectf(18.0, ptf[0].X); + expectf(15.0, ptf[0].Y); + expectf(15.0, ptf[1].X); + expectf(18.0, ptf[1].Y); + + ptf[0].X = 1.0; + ptf[0].Y = 0.0; + ptf[1].X = 0.0; + ptf[1].Y = 1.0; + status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceWorld, ptf, 2); + expect(Ok, status); + expectf(6.0, ptf[0].X); + expectf(5.0, ptf[0].Y); + expectf(5.0, ptf[1].X); + expectf(6.0, ptf[1].Y); + + ptf[0].X = 1.0; + ptf[0].Y = 0.0; + ptf[1].X = 0.0; + ptf[1].Y = 1.0; + status = GdipTransformPoints(graphics, CoordinateSpaceDevice, CoordinateSpacePage, ptf, 2); + expect(Ok, status); + expectf(3.0, ptf[0].X); + expectf(0.0, ptf[0].Y); + expectf(0.0, ptf[1].X); + expectf(3.0, ptf[1].Y); + + ptf[0].X = 18.0; + ptf[0].Y = 15.0; + ptf[1].X = 15.0; + ptf[1].Y = 18.0; + status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpaceDevice, ptf, 2); + expect(Ok, status); + expectf(1.0, ptf[0].X); + expectf(0.0, ptf[0].Y); + expectf(0.0, ptf[1].X); + expectf(1.0, ptf[1].Y); + + ptf[0].X = 6.0; + ptf[0].Y = 5.0; + ptf[1].X = 5.0; + ptf[1].Y = 6.0; + status = GdipTransformPoints(graphics, CoordinateSpaceWorld, CoordinateSpacePage, ptf, 2); + expect(Ok, status); + expectf(1.0, ptf[0].X); + expectf(0.0, ptf[0].Y); + expectf(0.0, ptf[1].X); + expectf(1.0, ptf[1].Y); + + ptf[0].X = 3.0; + ptf[0].Y = 0.0; + ptf[1].X = 0.0; + ptf[1].Y = 3.0; + status = GdipTransformPoints(graphics, CoordinateSpacePage, CoordinateSpaceDevice, ptf, 2); + expect(Ok, status); + expectf(1.0, ptf[0].X); + expectf(0.0, ptf[0].Y); + expectf(0.0, ptf[1].X); + expectf(1.0, ptf[1].Y); + GdipDeleteGraphics(graphics); ReleaseDC(0, hdc); }