Module: wine Branch: master Commit: 0a15e163dbfcd568963465c9c56c96023089a5d3 URL: http://source.winehq.org/git/wine.git/?a=commit;h=0a15e163dbfcd568963465c9c5...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Tue Jun 9 09:35:38 2015 +0300
gdiplus: Implement trivial case of GdipCreateRegionRgnData for empty and infinite regions.
---
dlls/gdiplus/gdiplus_private.h | 3 +- dlls/gdiplus/region.c | 99 ++++++++++++++++++++++++++++++++++-------- dlls/gdiplus/tests/region.c | 63 +++++++++++++++++++++++++++ 3 files changed, 145 insertions(+), 20 deletions(-)
diff --git a/dlls/gdiplus/gdiplus_private.h b/dlls/gdiplus/gdiplus_private.h index 57b3de3..1f0f47d 100644 --- a/dlls/gdiplus/gdiplus_private.h +++ b/dlls/gdiplus/gdiplus_private.h @@ -39,7 +39,8 @@ #define MAX_DASHLEN (16) /* this is a limitation of gdi */ #define INCH_HIMETRIC (2540)
-#define VERSION_MAGIC 0xdbc01001 +#define VERSION_MAGIC 0xdbc01001 +#define VERSION_MAGIC2 0xdbc01002 #define TENSION_CONST (0.3)
#define GIF_DISPOSE_UNSPECIFIED 0 diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c index 4ba86eb..572df62 100644 --- a/dlls/gdiplus/region.c +++ b/dlls/gdiplus/region.c @@ -522,15 +522,6 @@ GpStatus WINGDIPAPI GdipCreateRegionRectI(GDIPCONST GpRect *rect, return GdipCreateRegionRect(&rectf, region); }
-GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRegion **region) -{ - FIXME("(%p, %d, %p): stub\n", data, size, region); - - *region = NULL; - return NotImplemented; -} - - /****************************************************************************** * GdipCreateRegionHrgn [GDIPLUS.@] */ @@ -787,6 +778,14 @@ static void write_element(const region_element* element, DWORD *buffer, } }
+struct region_header +{ + DWORD size; + DWORD checksum; + DWORD magic; + DWORD num_children; +}; + /***************************************************************************** * GdipGetRegionData [GDIPLUS.@] * @@ -823,13 +822,7 @@ static void write_element(const region_element* element, DWORD *buffer, GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, UINT *needed) { - struct _region_header - { - DWORD size; - DWORD checksum; - DWORD magic; - DWORD num_children; - } *region_header; + struct region_header *region_header; INT filled = 0; UINT required; GpStatus status; @@ -847,7 +840,7 @@ GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, return InsufficientBuffer; }
- region_header = (struct _region_header *)buffer; + region_header = (struct region_header *)buffer; region_header->size = sizeheader_size + get_element_size(®ion->node); region_header->checksum = 0; region_header->magic = VERSION_MAGIC; @@ -863,6 +856,74 @@ GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, return Ok; }
+static inline GpStatus read_dword(DWORD **buffer, INT *size, DWORD *ret) +{ + if (*size < sizeof(DWORD)) + return GenericError; + + *ret = **buffer; + (*buffer)++; + (*size) -= sizeof(DWORD); + return Ok; +} + +static GpStatus read_element(GpRegion *region, region_element *element, DWORD **buffer, INT *size) +{ + GpStatus status; + + status = read_dword(buffer, size, &element->type); + if (status != Ok) + return status; + + switch (element->type) + { + case RegionDataInfiniteRect: + case RegionDataEmptyRect: + break; + default: + FIXME("region element type 0x%08x not supported\n", element->type); + return NotImplemented; + } + + return Ok; +} + +/***************************************************************************** + * GdipCreateRegionRgnData [GDIPLUS.@] + */ +GpStatus WINGDIPAPI GdipCreateRegionRgnData(GDIPCONST BYTE *data, INT size, GpRegion **region) +{ + struct region_header *region_header; + DWORD *buffer = (DWORD*)data; + GpStatus status; + + TRACE("(%p, %d, %p)\n", data, size, region); + + if (!data || size < sizeof(*region_header) || !region) + return InvalidParameter; + + region_header = (struct region_header *)buffer; + if (region_header->magic != VERSION_MAGIC && region_header->magic != VERSION_MAGIC2) + return InvalidParameter; + + status = GdipCreateRegion(region); + if (status != Ok) + return status; + + /* skip header */ + buffer += 4; + size -= sizeof(*region_header); + + status = read_element(*region, &(*region)->node, &buffer, &size); + if (status != Ok) + { + GdipDeleteRegion(*region); + *region = NULL; + } + + return status; +} + /***************************************************************************** * GdipGetRegionDataSize [GDIPLUS.@] */ @@ -988,7 +1049,7 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap case CombineModeIntersect: return get_region_hrgn(element->elementdata.combine.right, graphics, hrgn); case CombineModeXor: case CombineModeExclude: - left = CreateRectRgn(-4194304, -4194304, 4194304, 4194304); + left = CreateRectRgn(-(1 << 22), -(1 << 22), 1 << 22, 1 << 22); break; case CombineModeUnion: case CombineModeComplement: *hrgn = NULL; @@ -1013,7 +1074,7 @@ static GpStatus get_region_hrgn(struct region_element *element, GpGraphics *grap *hrgn = left; return Ok; case CombineModeXor: case CombineModeComplement: - right = CreateRectRgn(-4194304, -4194304, 4194304, 4194304); + right = CreateRectRgn(-(1 << 22), -(1 << 22), 1 << 22, 1 << 22); break; case CombineModeUnion: case CombineModeExclude: DeleteObject(left); diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c index 5632e4d..92569c7 100644 --- a/dlls/gdiplus/tests/region.c +++ b/dlls/gdiplus/tests/region.c @@ -2132,6 +2132,68 @@ static void test_excludeinfinite(void) GdipDeleteMatrix(identity); }
+static void test_GdipCreateRegionRgnData(void) +{ + GpGraphics *graphics = NULL; + GpRegion *region, *region2; + HDC hdc = GetDC(0); + GpStatus status; + BYTE buf[512]; + UINT needed; + BOOL ret; + + status = GdipCreateRegionRgnData(NULL, 0, NULL); + ok(status == InvalidParameter, "status %d\n", status); + + status = GdipCreateFromHDC(hdc, &graphics); + ok(status == Ok, "status %d\n", status); + + status = GdipCreateRegion(®ion); + ok(status == Ok, "status %d\n", status); + + /* infinite region */ + memset(buf, 0xee, sizeof(buf)); + needed = 0; + status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed); + ok(status == Ok, "status %d\n", status); + expect(20, needed); + + status = GdipCreateRegionRgnData(buf, needed, NULL); + ok(status == InvalidParameter, "status %d\n", status); + + status = GdipCreateRegionRgnData(buf, needed, ®ion2); + ok(status == Ok, "status %d\n", status); + + ret = FALSE; + status = GdipIsInfiniteRegion(region2, graphics, &ret); + ok(status == Ok, "status %d\n", status); + ok(ret, "got %d\n", ret); + GdipDeleteRegion(region2); + + /* empty region */ + status = GdipSetEmpty(region); + ok(status == Ok, "status %d\n", status); + + memset(buf, 0xee, sizeof(buf)); + needed = 0; + status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed); + ok(status == Ok, "status %d\n", status); + expect(20, needed); + + status = GdipCreateRegionRgnData(buf, needed, ®ion2); + ok(status == Ok, "status %d\n", status); + + ret = FALSE; + status = GdipIsEmptyRegion(region2, graphics, &ret); + ok(status == Ok, "status %d\n", status); + ok(ret, "got %d\n", ret); + GdipDeleteRegion(region2); + + GdipDeleteGraphics(graphics); + GdipDeleteRegion(region); + ReleaseDC(0, hdc); +} + START_TEST(region) { struct GdiplusStartupInput gdiplusStartupInput; @@ -2158,6 +2220,7 @@ START_TEST(region) test_isvisiblepoint(); test_isvisiblerect(); test_excludeinfinite(); + test_GdipCreateRegionRgnData();
GdiplusShutdown(gdiplusToken); }