[PATCH 1/2] gdiplus: Transform region rects as rects when possible.

Vincent Povirk vincent at codeweavers.com
Wed Mar 7 11:31:00 CST 2018


Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
---
For bug 44640.

 dlls/gdiplus/region.c       | 38 +++++++++++++++++++++++++++++++++++++-
 dlls/gdiplus/tests/region.c | 38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 1 deletion(-)

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




More information about the wine-devel mailing list