Vincent Povirk : gdiplus: Optimize clip region transforms.

Alexandre Julliard julliard at winehq.org
Wed Mar 7 17:14:07 CST 2018


Module: wine
Branch: master
Commit: 989c29870f3bdd3f67ca5bb9a2c5dfd42659f7aa
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=989c29870f3bdd3f67ca5bb9a2c5dfd42659f7aa

Author: Vincent Povirk <vincent at codeweavers.com>
Date:   Wed Mar  7 11:31:01 2018 -0600

gdiplus: Optimize clip region transforms.

Testing shows that this affects behavior. Transforming a region turns
empty rectangles (with negative width or height) into non-empty
rectangles. If an empty rectangle is set, it's treated as non-empty
only when there is a world transform.

Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdiplus/graphics.c       | 17 ++++++--
 dlls/gdiplus/tests/graphics.c | 92 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 106 insertions(+), 3 deletions(-)

diff --git a/dlls/gdiplus/graphics.c b/dlls/gdiplus/graphics.c
index 06fb89e..acee695 100644
--- a/dlls/gdiplus/graphics.c
+++ b/dlls/gdiplus/graphics.c
@@ -332,15 +332,20 @@ static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn)
     GpRegion *rgn;
     GpMatrix transform;
     GpStatus stat;
+    BOOL identity;
 
     stat = get_graphics_transform(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceDevice, &transform);
 
     if (stat == Ok)
+        stat = GdipIsMatrixIdentity(&transform, &identity);
+
+    if (stat == Ok)
         stat = GdipCloneRegion(graphics->clip, &rgn);
 
     if (stat == Ok)
     {
-        stat = GdipTransformRegion(rgn, &transform);
+        if (!identity)
+            stat = GdipTransformRegion(rgn, &transform);
 
         if (stat == Ok)
             stat = GdipGetRegionHRgn(rgn, NULL, hrgn);
@@ -6333,9 +6338,12 @@ GpStatus WINGDIPAPI GdipSetClipRect(GpGraphics *graphics, REAL x, REAL y,
     if (status == Ok)
     {
         GpMatrix world_to_device;
+        BOOL identity;
 
         get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
-        status = GdipTransformRegion(region, &world_to_device);
+        status = GdipIsMatrixIdentity(&world_to_device, &identity);
+        if (status == Ok && !identity)
+            status = GdipTransformRegion(region, &world_to_device);
         if (status == Ok)
             status = GdipCombineRegionRegion(graphics->clip, region, mode);
 
@@ -6384,9 +6392,12 @@ GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region,
     if (status == Ok)
     {
         GpMatrix world_to_device;
+        BOOL identity;
 
         get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
-        status = GdipTransformRegion(clip, &world_to_device);
+        status = GdipIsMatrixIdentity(&world_to_device, &identity);
+        if (status == Ok && !identity)
+            status = GdipTransformRegion(clip, &world_to_device);
         if (status == Ok)
             status = GdipCombineRegionRegion(graphics->clip, clip, mode);
 
diff --git a/dlls/gdiplus/tests/graphics.c b/dlls/gdiplus/tests/graphics.c
index 96df1a2..6acc656 100644
--- a/dlls/gdiplus/tests/graphics.c
+++ b/dlls/gdiplus/tests/graphics.c
@@ -2060,6 +2060,97 @@ static void test_get_set_clip(void)
     ReleaseDC(hwnd, hdc);
 }
 
+static void test_clip_xform(void)
+{
+    GpStatus status;
+    GpGraphics *graphics = NULL;
+    HDC hdc = GetDC( hwnd );
+    GpRegion *clip;
+    COLORREF color;
+    UINT region_data_size;
+    struct {
+        DWORD size;
+        DWORD checksum;
+        DWORD magic;
+        DWORD num_children;
+        DWORD element_type;
+        REAL x;
+        REAL y;
+        REAL width;
+        REAL height;
+    } region_data;
+
+    status = GdipCreateFromHDC(hdc, &graphics);
+    expect(Ok, status);
+    status = GdipCreateRegion(&clip);
+    expect(Ok, status);
+
+    status = GdipGraphicsClear(graphics, 0xff000000);
+    expect(Ok, status);
+
+    status = GdipSetClipRect(graphics, 10, 10, -10, -10, CombineModeReplace);
+    expect(Ok, status);
+    status = GdipGetClip(graphics, clip);
+    expect(Ok, status);
+    status = GdipGetRegionData(clip, (BYTE*)&region_data, sizeof(region_data), &region_data_size);
+    expect(Ok, status);
+    expect(36, region_data_size);
+    expect(28, region_data.size);
+    expect(0, region_data.num_children);
+    expect(0x10000000 /* RegionDataRect */, region_data.element_type);
+    expectf(0.0, region_data.x);
+    expectf(0.0, region_data.y);
+    expectf(10.0, region_data.width);
+    expectf(10.0, region_data.height);
+
+    /* No effect with negative width/height */
+    status = GdipGraphicsClear(graphics, 0xffff0000);
+    expect(Ok, status);
+    color = GetPixel(hdc, 5, 5);
+    expect(0, color);
+
+    status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderAppend);
+    expect(Ok, status);
+
+    status = GdipGraphicsClear(graphics, 0xffff0000);
+    expect(Ok, status);
+    color = GetPixel(hdc, 5, 5);
+    expect(0, color);
+
+    status = GdipResetClip(graphics);
+    expect(Ok, status);
+    status = GdipResetWorldTransform(graphics);
+    expect(Ok, status);
+    status = GdipGraphicsClear(graphics, 0xff000000);
+    expect(Ok, status);
+
+    status = GdipScaleWorldTransform(graphics, 2.0, 2.0, MatrixOrderAppend);
+    expect(Ok, status);
+
+    status = GdipSetClipRect(graphics, 5, 5, -5, -5, CombineModeReplace);
+    expect(Ok, status);
+    status = GdipGetClip(graphics, clip);
+    expect(Ok, status);
+    status = GdipGetRegionData(clip, (BYTE*)&region_data, sizeof(region_data), &region_data_size);
+    expect(Ok, status);
+    expect(36, region_data_size);
+    expect(28, region_data.size);
+    expect(0, region_data.num_children);
+    expect(0x10000000 /* RegionDataRect */, region_data.element_type);
+    expectf(0.0, region_data.x);
+    expectf(0.0, region_data.y);
+    expectf(5.0, region_data.width);
+    expectf(5.0, region_data.height);
+
+    status = GdipGraphicsClear(graphics, 0xffff0000);
+    expect(Ok, status);
+    color = GetPixel(hdc, 5, 5);
+    expect(0xff, color);
+
+    GdipDeleteGraphics(graphics);
+    ReleaseDC(hwnd, hdc);
+}
+
 static void test_isempty(void)
 {
     GpStatus status;
@@ -6713,6 +6804,7 @@ START_TEST(graphics)
     test_BeginContainer2();
     test_transformpoints();
     test_get_set_clip();
+    test_clip_xform();
     test_isempty();
     test_clear();
     test_textcontrast();




More information about the wine-cvs mailing list