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@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Vincent Povirk 2018-03-07 11:31:01 -06:00 committed by Alexandre Julliard
parent 2329a2fa3d
commit 989c29870f
2 changed files with 106 additions and 3 deletions

View File

@ -332,14 +332,19 @@ static GpStatus get_clip_hrgn(GpGraphics *graphics, HRGN *hrgn)
GpRegion *rgn; GpRegion *rgn;
GpMatrix transform; GpMatrix transform;
GpStatus stat; GpStatus stat;
BOOL identity;
stat = get_graphics_transform(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceDevice, &transform); stat = get_graphics_transform(graphics, WineCoordinateSpaceGdiDevice, CoordinateSpaceDevice, &transform);
if (stat == Ok)
stat = GdipIsMatrixIdentity(&transform, &identity);
if (stat == Ok) if (stat == Ok)
stat = GdipCloneRegion(graphics->clip, &rgn); stat = GdipCloneRegion(graphics->clip, &rgn);
if (stat == Ok) if (stat == Ok)
{ {
if (!identity)
stat = GdipTransformRegion(rgn, &transform); stat = GdipTransformRegion(rgn, &transform);
if (stat == Ok) if (stat == Ok)
@ -6333,8 +6338,11 @@ GpStatus WINGDIPAPI GdipSetClipRect(GpGraphics *graphics, REAL x, REAL y,
if (status == Ok) if (status == Ok)
{ {
GpMatrix world_to_device; GpMatrix world_to_device;
BOOL identity;
get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device); get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
status = GdipIsMatrixIdentity(&world_to_device, &identity);
if (status == Ok && !identity)
status = GdipTransformRegion(region, &world_to_device); status = GdipTransformRegion(region, &world_to_device);
if (status == Ok) if (status == Ok)
status = GdipCombineRegionRegion(graphics->clip, region, mode); status = GdipCombineRegionRegion(graphics->clip, region, mode);
@ -6384,8 +6392,11 @@ GpStatus WINGDIPAPI GdipSetClipRegion(GpGraphics *graphics, GpRegion *region,
if (status == Ok) if (status == Ok)
{ {
GpMatrix world_to_device; GpMatrix world_to_device;
BOOL identity;
get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device); get_graphics_transform(graphics, CoordinateSpaceDevice, CoordinateSpaceWorld, &world_to_device);
status = GdipIsMatrixIdentity(&world_to_device, &identity);
if (status == Ok && !identity)
status = GdipTransformRegion(clip, &world_to_device); status = GdipTransformRegion(clip, &world_to_device);
if (status == Ok) if (status == Ok)
status = GdipCombineRegionRegion(graphics->clip, clip, mode); status = GdipCombineRegionRegion(graphics->clip, clip, mode);

View File

@ -2060,6 +2060,97 @@ static void test_get_set_clip(void)
ReleaseDC(hwnd, hdc); 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) static void test_isempty(void)
{ {
GpStatus status; GpStatus status;
@ -6713,6 +6804,7 @@ START_TEST(graphics)
test_BeginContainer2(); test_BeginContainer2();
test_transformpoints(); test_transformpoints();
test_get_set_clip(); test_get_set_clip();
test_clip_xform();
test_isempty(); test_isempty();
test_clear(); test_clear();
test_textcontrast(); test_textcontrast();