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(a)codeweavers.com>
---
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 06fb89e5d32..acee695e9fc 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 96df1a2743e..6acc656c8f4 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*)®ion_data, sizeof(region_data), ®ion_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*)®ion_data, sizeof(region_data), ®ion_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();
--
2.14.1