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);
 }