gdiplus: implement GdipTransformPoints
Vincent Povirk
madewokherd+8cd9 at gmail.com
Mon May 18 17:34:33 CDT 2009
It's odd, but it seems like the simplest way to write this.
I've tried what I think was your suggestion, and that's attached. I
don't think it's an improvement.
Vincent Povirk
On Mon, May 18, 2009 at 5:17 PM, Nikolay Sivov <bunglehead at gmail.com> wrote:
> Vincent Povirk wrote:
>
> From 1de9b2291bf9a5617ca1e3b0cba5f1260889c259 Mon Sep 17 00:00:00 2001
> From: Vincent Povirk <vincent at codeweavers.com>
> Date: Mon, 23 Mar 2009 16:34:12 -0500
> Subject: [PATCH] gdiplus: implement GdipTransformPoints
>
>
> It's a strange way to check enumeration with integer comparison, isn't it?
> And not clear in this particular case.
>
>> + if (stat == Ok)
>> + {
>> + unitscale = convert_unit(graphics->hdc, graphics->unit);
>> +
>> + if(graphics->unit != UnitDisplay)
>> + unitscale *= graphics->scale;
>> +
>> + if (src_space <= CoordinateSpaceWorld && dst_space >=
>> CoordinateSpacePage)
>> + GdipMultiplyMatrix(matrix, graphics->worldtrans,
>> MatrixOrderAppend);
>> + if (src_space <= CoordinateSpacePage && dst_space >=
>> CoordinateSpaceDevice)
>> + GdipScaleMatrix(matrix, unitscale, unitscale,
>> MatrixOrderAppend);
>> +
>> + if (dst_space <= CoordinateSpacePage && src_space >=
>> CoordinateSpaceDevice)
>> + GdipScaleMatrix(matrix, 1.0/unitscale, 1.0/unitscale,
>> MatrixOrderAppend);
>> + if (dst_space <= CoordinateSpaceWorld && src_space >=
>> CoordinateSpacePage)
>> + {
>> + GpMatrix *inverted_transform;
>> + stat = GdipCloneMatrix(graphics->worldtrans,
>> &inverted_transform);
>> + if (stat == Ok)
>> + {
>> + GdipInvertMatrix(inverted_transform);
>> + GdipMultiplyMatrix(matrix, inverted_transform,
>> MatrixOrderAppend);
>> + GdipDeleteMatrix(inverted_transform);
>> + }
>> +
>
> Maybe it's better to use 'switch' for source coords with falling and ifs
> inside cases for destination.
>
> <= CoordinateSpaceWorld is just CoordinateSpaceWorld
>>= CoordinateSpaceDevice - is CoordinateSpaceDevice.
>
>
>
>
-------------- next part --------------
diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 5e5883f..0ade037 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -3592,15 +3592,66 @@ 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;
+ stat = GdipCreateMatrix(&matrix);
+ if (stat == Ok)
+ {
+ unitscale = convert_unit(graphics->hdc, graphics->unit);
+
+ if(graphics->unit != UnitDisplay)
+ unitscale *= graphics->scale;
+
+ switch (src_space)
+ {
+ case CoordinateSpaceWorld:
+ if (dst_space == CoordinateSpaceWorld)
+ break;
+ GdipMultiplyMatrix(matrix, graphics->worldtrans, MatrixOrderAppend);
+ case CoordinateSpacePage:
+ if (dst_space == CoordinateSpaceDevice)
+ GdipScaleMatrix(matrix, unitscale, unitscale, MatrixOrderAppend);
+ default: break;
+ }
+
+ switch (src_space)
+ {
+ case CoordinateSpaceDevice:
+ if (dst_space == CoordinateSpaceDevice)
+ break;
+ GdipScaleMatrix(matrix, 1.0/unitscale, 1.0/unitscale, MatrixOrderAppend);
+ case CoordinateSpacePage:
+ if (dst_space == CoordinateSpaceWorld)
+ {
+ GpMatrix *inverted_transform;
+ stat = GdipCloneMatrix(graphics->worldtrans, &inverted_transform);
+ if (stat == Ok)
+ {
+ GdipInvertMatrix(inverted_transform);
+ GdipMultiplyMatrix(matrix, inverted_transform, MatrixOrderAppend);
+ GdipDeleteMatrix(inverted_transform);
+ }
+ }
+ default: 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 7199151..510a148 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);
}
More information about the wine-devel
mailing list