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:
parent
2329a2fa3d
commit
989c29870f
|
@ -332,15 +332,20 @@ 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)
|
||||||
{
|
{
|
||||||
stat = GdipTransformRegion(rgn, &transform);
|
if (!identity)
|
||||||
|
stat = GdipTransformRegion(rgn, &transform);
|
||||||
|
|
||||||
if (stat == Ok)
|
if (stat == Ok)
|
||||||
stat = GdipGetRegionHRgn(rgn, NULL, hrgn);
|
stat = GdipGetRegionHRgn(rgn, NULL, hrgn);
|
||||||
|
@ -6333,9 +6338,12 @@ 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 = GdipTransformRegion(region, &world_to_device);
|
status = GdipIsMatrixIdentity(&world_to_device, &identity);
|
||||||
|
if (status == Ok && !identity)
|
||||||
|
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,9 +6392,12 @@ 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 = GdipTransformRegion(clip, &world_to_device);
|
status = GdipIsMatrixIdentity(&world_to_device, &identity);
|
||||||
|
if (status == Ok && !identity)
|
||||||
|
status = GdipTransformRegion(clip, &world_to_device);
|
||||||
if (status == Ok)
|
if (status == Ok)
|
||||||
status = GdipCombineRegionRegion(graphics->clip, clip, mode);
|
status = GdipCombineRegionRegion(graphics->clip, clip, mode);
|
||||||
|
|
||||||
|
|
|
@ -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*)®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)
|
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();
|
||||||
|
|
Loading…
Reference in New Issue