diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c index 8eb3ff3535a..470bcd20ced 100644 --- a/dlls/gdiplus/region.c +++ b/dlls/gdiplus/region.c @@ -1398,10 +1398,46 @@ static GpStatus transform_region_element(region_element* element, GpMatrix *matr return Ok; case RegionDataRect: { - /* We can't transform a rectangle, so convert it to a path. */ GpRegion *new_region; GpPath *path; + if (matrix->matrix[1] == 0.0 && matrix->matrix[2] == 0.0) + { + GpPointF points[2]; + + points[0].X = element->elementdata.rect.X; + points[0].Y = element->elementdata.rect.Y; + points[1].X = element->elementdata.rect.X + element->elementdata.rect.Width; + points[1].Y = element->elementdata.rect.Y + element->elementdata.rect.Height; + + stat = GdipTransformMatrixPoints(matrix, points, 2); + if (stat != Ok) + return stat; + + if (points[0].X > points[1].X) + { + REAL temp; + temp = points[0].X; + points[0].X = points[1].X; + points[1].X = temp; + } + + if (points[0].Y > points[1].Y) + { + REAL temp; + temp = points[0].Y; + points[0].Y = points[1].Y; + points[1].Y = temp; + } + + element->elementdata.rect.X = points[0].X; + element->elementdata.rect.Y = points[0].Y; + element->elementdata.rect.Width = points[1].X - points[0].X; + element->elementdata.rect.Height = points[1].Y - points[0].Y; + return Ok; + } + + /* We can't rotate/shear a rectangle, so convert it to a path. */ stat = GdipCreatePath(FillModeAlternate, &path); if (stat == Ok) { diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c index 86a2e40fa2f..c2cbff01f69 100644 --- a/dlls/gdiplus/tests/region.c +++ b/dlls/gdiplus/tests/region.c @@ -1441,6 +1441,22 @@ static void test_translate(void) ReleaseDC(0, hdc); } +static DWORD get_region_type(GpRegion *region) +{ + DWORD *data; + DWORD size; + DWORD result; + DWORD status; + status = GdipGetRegionDataSize(region, &size); + expect(Ok, status); + data = GdipAlloc(size); + status = GdipGetRegionData(region, (BYTE*)data, size, NULL); + ok(status == Ok || status == InsufficientBuffer, "unexpected status 0x%x\n", status); + result = data[4]; + GdipFree(data); + return result; +} + static void test_transform(void) { GpRegion *region, *region2; @@ -1451,6 +1467,7 @@ static void test_transform(void) GpStatus status; HDC hdc = GetDC(0); BOOL res; + DWORD type; status = GdipCreateFromHDC(hdc, &graphics); expect(Ok, status); @@ -1483,6 +1500,8 @@ static void test_transform(void) status = GdipIsEqualRegion(region, region2, graphics, &res); expect(Ok, status); ok(res, "Expected to be equal.\n"); + type = get_region_type(region); + expect(0x10000003 /* RegionDataInfiniteRect */, type); /* empty */ status = GdipSetEmpty(region); @@ -1497,6 +1516,8 @@ static void test_transform(void) status = GdipIsEqualRegion(region, region2, graphics, &res); expect(Ok, status); ok(res, "Expected to be equal.\n"); + type = get_region_type(region); + expect(0x10000002 /* RegionDataEmptyRect */, type); /* rect */ rectf.X = 10.0; @@ -1516,6 +1537,8 @@ static void test_transform(void) status = GdipIsEqualRegion(region, region2, graphics, &res); expect(Ok, status); ok(res, "Expected to be equal.\n"); + type = get_region_type(region); + expect(0x10000000 /* RegionDataRect */, type); /* path */ status = GdipAddPathEllipse(path, 0.0, 10.0, 100.0, 150.0); @@ -1534,6 +1557,21 @@ static void test_transform(void) status = GdipIsEqualRegion(region, region2, graphics, &res); expect(Ok, status); ok(res, "Expected to be equal.\n"); + type = get_region_type(region); + expect(0x10000001 /* RegionDataPath */, type); + + /* rotated rect -> path */ + rectf.X = 10.0; + rectf.Y = 0.0; + rectf.Width = rectf.Height = 100.0; + status = GdipCombineRegionRect(region, &rectf, CombineModeReplace); + expect(Ok, status); + status = GdipRotateMatrix(matrix, 45.0, MatrixOrderAppend); + expect(Ok, status); + status = GdipTransformRegion(region, matrix); + expect(Ok, status); + type = get_region_type(region); + expect(0x10000001 /* RegionDataPath */, type); status = GdipDeleteRegion(region); expect(Ok, status);