From 25cf029e36cfbd04203e0ffda3b2944126077192 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Thu, 30 Sep 2010 14:39:27 -0500 Subject: [PATCH 1/3] gdiplus: Implement GdipTransformRegion. --- dlls/gdiplus/region.c | 59 ++++++++++++++++++++++- dlls/gdiplus/tests/region.c | 108 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 2 deletions(-) diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c index decaaf9..9b8ed18 100644 --- a/dlls/gdiplus/region.c +++ b/dlls/gdiplus/region.c @@ -1248,11 +1248,66 @@ GpStatus WINGDIPAPI GdipSetInfinite(GpRegion *region) return stat; } +/* Transforms GpRegion elements with given matrix */ +static GpStatus transform_region_element(region_element* element, GpMatrix *matrix) +{ + GpStatus stat; + + switch(element->type) + { + case RegionDataEmptyRect: + case RegionDataInfiniteRect: + return Ok; + case RegionDataRect: + { + /* We can't transform a rectangle, so convert it to a path. */ + GpRegion *new_region; + GpPath *path; + + stat = GdipCreatePath(FillModeAlternate, &path); + if (stat == Ok) + { + stat = GdipAddPathRectangle(path, + element->elementdata.rect.X, element->elementdata.rect.Y, + element->elementdata.rect.Width, element->elementdata.rect.Height); + + if (stat == Ok) + stat = GdipCreateRegionPath(path, &new_region); + + GdipDeletePath(path); + } + + if (stat == Ok) + { + /* Steal the element from the created region. */ + memcpy(element, &new_region->node, sizeof(region_element)); + HeapFree(GetProcessHeap(), 0, new_region); + } + else + return stat; + } + /* Fall-through to do the actual conversion. */ + case RegionDataPath: + stat = GdipTransformMatrixPoints(matrix, + element->elementdata.pathdata.path->pathdata.Points, + element->elementdata.pathdata.path->pathdata.Count); + return stat; + default: + stat = transform_region_element(element->elementdata.combine.left, matrix); + if (stat == Ok) + stat = transform_region_element(element->elementdata.combine.right, matrix); + return stat; + } +} + GpStatus WINGDIPAPI GdipTransformRegion(GpRegion *region, GpMatrix *matrix) { - FIXME("(%p, %p): stub\n", region, matrix); + TRACE("(%p, %p)\n", region, matrix); - return NotImplemented; + if (!region || !matrix) + return InvalidParameter; + + return transform_region_element(®ion->node, matrix); } /* Translates GpRegion elements with specified offsets */ diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c index efd2115..96ac40e 100644 --- a/dlls/gdiplus/tests/region.c +++ b/dlls/gdiplus/tests/region.c @@ -1123,6 +1123,113 @@ static void test_translate(void) ReleaseDC(0, hdc); } +static void test_transform(void) +{ + GpRegion *region, *region2; + GpMatrix *matrix; + GpGraphics *graphics; + GpPath *path; + GpRectF rectf; + GpStatus status; + HDC hdc = GetDC(0); + BOOL res; + + status = GdipCreateFromHDC(hdc, &graphics); + expect(Ok, status); + + status = GdipCreatePath(FillModeAlternate, &path); + expect(Ok, status); + + status = GdipCreateRegion(®ion); + expect(Ok, status); + status = GdipCreateRegion(®ion2); + expect(Ok, status); + + status = GdipCreateMatrix(&matrix); + expect(Ok, status); + status = GdipScaleMatrix(matrix, 2.0, 3.0, MatrixOrderAppend); + expect(Ok, status); + + /* NULL */ + status = GdipTransformRegion(NULL, matrix); + expect(InvalidParameter, status); + + status = GdipTransformRegion(region, NULL); + expect(InvalidParameter, status); + + /* infinite */ + status = GdipTransformRegion(region, matrix); + expect(Ok, status); + + res = FALSE; + status = GdipIsEqualRegion(region, region2, graphics, &res); + expect(Ok, status); + ok(res, "Expected to be equal.\n"); + + /* empty */ + status = GdipSetEmpty(region); + expect(Ok, status); + status = GdipTransformRegion(region, matrix); + expect(Ok, status); + + status = GdipSetEmpty(region2); + expect(Ok, status); + + res = FALSE; + status = GdipIsEqualRegion(region, region2, graphics, &res); + expect(Ok, status); + ok(res, "Expected to be equal.\n"); + + /* rect */ + rectf.X = 10.0; + rectf.Y = 0.0; + rectf.Width = rectf.Height = 100.0; + status = GdipCombineRegionRect(region, &rectf, CombineModeReplace); + expect(Ok, status); + rectf.X = 20.0; + rectf.Y = 0.0; + rectf.Width = 200.0; + rectf.Height = 300.0; + status = GdipCombineRegionRect(region2, &rectf, CombineModeReplace); + expect(Ok, status); + status = GdipTransformRegion(region, matrix); + expect(Ok, status); + res = FALSE; + status = GdipIsEqualRegion(region, region2, graphics, &res); + expect(Ok, status); + ok(res, "Expected to be equal.\n"); + + /* path */ + status = GdipAddPathEllipse(path, 0.0, 10.0, 100.0, 150.0); + expect(Ok, status); + status = GdipCombineRegionPath(region, path, CombineModeReplace); + expect(Ok, status); + status = GdipResetPath(path); + expect(Ok, status); + status = GdipAddPathEllipse(path, 0.0, 30.0, 200.0, 450.0); + expect(Ok, status); + status = GdipCombineRegionPath(region2, path, CombineModeReplace); + expect(Ok, status); + status = GdipTransformRegion(region, matrix); + expect(Ok, status); + res = FALSE; + status = GdipIsEqualRegion(region, region2, graphics, &res); + expect(Ok, status); + ok(res, "Expected to be equal.\n"); + + status = GdipDeleteRegion(region); + expect(Ok, status); + status = GdipDeleteRegion(region2); + expect(Ok, status); + status = GdipDeleteGraphics(graphics); + expect(Ok, status); + status = GdipDeletePath(path); + expect(Ok, status); + status = GdipDeleteMatrix(matrix); + expect(Ok, status); + ReleaseDC(0, hdc); +} + static void test_getbounds(void) { GpRegion *region; @@ -1634,6 +1741,7 @@ START_TEST(region) test_gethrgn(); test_isequal(); test_translate(); + test_transform(); test_getbounds(); test_isvisiblepoint(); test_isvisiblerect(); -- 1.7.0.4