[try 5][Gdiplus 6/6] Implement GdipGetRegionData
Adam Petaccia
adam at tpetaccia.com
Thu Jul 24 18:01:49 CDT 2008
Changelog:
(try4):
region->node is no longer a pointer
Apply const qualifier to helper function
(try2):
We might not write a whole DWORD for pathflags, so make sure its not
garbage; revealed by the added test at the end of this series.
---
dlls/gdiplus/region.c | 119 +++++++++++++++++++++++++++++++++++++++++-
dlls/gdiplus/tests/region.c | 39 ++++++++------
2 files changed, 138 insertions(+), 20 deletions(-)
diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c
index 6c52623..e8886fa 100644
--- a/dlls/gdiplus/region.c
+++ b/dlls/gdiplus/region.c
@@ -81,11 +81,31 @@ typedef enum RegionType
RegionDataInfiniteRect = 0x10000003,
} RegionType;
+#define FLAGS_NOFLAGS 0x0
+#define FLAGS_INTPATH 0x4000
+
/* Header size as far as header->size is concerned. This doesn't include
* header->size or header->checksum
*/
static const INT sizeheader_size = sizeof(DWORD) * 2;
+typedef struct packed_point
+{
+ short X;
+ short Y;
+} packed_point;
+
+/* Everything is measured in DWORDS; round up if there's a remainder */
+static inline INT get_pathtypes_size(const GpPath* path)
+{
+ INT needed = path->pathdata.Count / sizeof(DWORD);
+
+ if (path->pathdata.Count % sizeof(DWORD) > 0)
+ needed++;
+
+ return needed * sizeof(DWORD);
+}
+
static inline INT get_element_size(const region_element* element)
{
INT needed = sizeof(DWORD); /* DWORD for the type */
@@ -258,11 +278,104 @@ GpStatus WINGDIPAPI GdipGetRegionBoundsI(GpRegion *region, GpGraphics *graphics,
return NotImplemented;
}
-GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size, UINT *needed)
+static inline void write_dword(BYTE* location, INT* offset, DWORD write)
{
- FIXME("(%p, %p, %d, %p): stub\n", region, buffer, size, needed);
+ ((DWORD*)location)[*offset] = write;
+ (*offset)++;
+}
- return NotImplemented;
+static inline void write_float(BYTE* location, INT* offset, FLOAT write)
+{
+ ((FLOAT*)location)[*offset] = write;
+ (*offset)++;
+}
+
+static inline void write_packed_point(BYTE* location, INT* offset,
+ GpPointF* write)
+{
+ packed_point point;
+
+ point.X = (short)write->X;
+ point.Y = (short)write->Y;
+ memcpy(location + (*offset * sizeof(DWORD)), &point, sizeof(DWORD));
+ (*offset)++;
+}
+
+static void write_element(const region_element* element, BYTE *buffer,
+ INT* filled)
+{
+ write_dword(buffer, filled, element->type);
+ switch (element->type)
+ {
+ case CombineModeReplace:
+ case CombineModeIntersect:
+ case CombineModeUnion:
+ case CombineModeXor:
+ case CombineModeExclude:
+ case CombineModeComplement:
+ write_element(element->elementdata.combine.left, buffer, filled);
+ write_element(element->elementdata.combine.right, buffer, filled);
+ break;
+ case RegionDataRect:
+ write_float(buffer, filled, element->elementdata.rect.X);
+ write_float(buffer, filled, element->elementdata.rect.Y);
+ write_float(buffer, filled, element->elementdata.rect.Width);
+ write_float(buffer, filled, element->elementdata.rect.Height);
+ break;
+ case RegionDataPath:
+ {
+ INT i;
+ GpPath* path = element->elementdata.pathdata.path;
+ memcpy((DWORD*)buffer +*filled,
+ &element->elementdata.pathdata.pathheader,
+ sizeof(DWORD) * 4);
+ *filled += 4; /* Four DWORDS for the header */
+ switch (element->elementdata.pathdata.pathheader.flags)
+ {
+ case FLAGS_NOFLAGS:
+ for (i = 0; i < path->pathdata.Count; i++)
+ {
+ write_float(buffer, filled, path->pathdata.Points[i].X);
+ write_float(buffer, filled, path->pathdata.Points[i].Y);
+ }
+ break;
+ case FLAGS_INTPATH:
+ for (i = 0; i < path->pathdata.Count; i++)
+ {
+ write_packed_point(buffer, filled,
+ &path->pathdata.Points[i]);
+ }
+ }
+ /* We might not write a whole DWORD so make sure its not garbage */
+ ZeroMemory(buffer + (*filled * 4), get_pathtypes_size(path));
+ GdipGetPathTypes(path, buffer+ (*filled * 4), path->pathdata.Count);
+ *filled += (get_pathtypes_size(path) / sizeof(DWORD));
+ break;
+ }
+ case RegionDataEmptyRect:
+ case RegionDataInfiniteRect:
+ break;
+ }
+}
+
+/* needed may be NULL */
+GpStatus WINGDIPAPI GdipGetRegionData(GpRegion *region, BYTE *buffer, UINT size,
+ UINT *needed)
+{
+ INT filled = 0;
+
+ if (!(region && buffer && size))
+ return InvalidParameter;
+
+ TRACE("%p, %p, %d, %p\n", region, buffer, size, needed);
+ memcpy(buffer, ®ion->header, sizeof(region->header));
+ filled += sizeof(region->header) / sizeof(DWORD);
+ write_element(®ion->node, buffer, &filled);
+
+ if (needed)
+ *needed = filled * sizeof(DWORD);
+
+ return Ok;
}
GpStatus WINGDIPAPI GdipGetRegionDataSize(GpRegion *region, UINT *needed)
diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c
index 8c3bada..01991a2 100644
--- a/dlls/gdiplus/tests/region.c
+++ b/dlls/gdiplus/tests/region.c
@@ -71,13 +71,9 @@ static void test_getregiondata(void)
ok(status == Ok, "status %08x\n", status);
expect(20, needed);
todo_wine
-{
status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
ok(status == Ok, "status %08x\n", status);
-}
expect(20, needed);
-todo_wine
-{
expect_dword(buf, 12);
trace("buf[1] = %08x\n", buf[1]);
expect_magic((DWORD*)(buf + 2));
@@ -85,26 +81,18 @@ todo_wine
expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
status = GdipSetEmpty(region);
-}
ok(status == Ok, "status %08x\n", status);
-todo_wine
-{
status = GdipGetRegionDataSize(region, &needed);
-}
ok(status == Ok, "status %08x\n", status);
expect(20, needed);
status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
-todo_wine
ok(status == Ok, "status %08x\n", status);
expect(20, needed);
-todo_wine
-{
expect_dword(buf, 12);
trace("buf[1] = %08x\n", buf[1]);
expect_magic((DWORD*)(buf + 2));
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_EMPTY_RECT);
-}
status = GdipSetInfinite(region);
ok(status == Ok, "status %08x\n", status);
@@ -112,17 +100,13 @@ todo_wine
ok(status == Ok, "status %08x\n", status);
expect(20, needed);
status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed);
-todo_wine
ok(status == Ok, "status %08x\n", status);
expect(20, needed);
-todo_wine
-{
expect_dword(buf, 12);
trace("buf[1] = %08x\n", buf[1]);
expect_magic((DWORD*)(buf + 2));
expect_dword(buf + 3, 0);
expect_dword(buf + 4, RGNDATA_INFINITE_RECT);
-}
status = GdipDeleteRegion(region);
ok(status == Ok, "status %08x\n", status);
@@ -143,8 +127,11 @@ todo_wine
expect(36, needed);
expect_dword(buf, 28);
trace("buf[1] = %08x\n", buf[1]);
+}
expect_magic((DWORD*)(buf + 2));
expect_dword(buf + 3, 0);
+todo_wine
+{
expect_dword(buf + 4, RGNDATA_RECT);
expect_float(buf + 5, 10.0);
expect_float(buf + 6, 20.0);
@@ -195,7 +182,10 @@ todo_wine
expect(156, needed);
expect_dword(buf, 148);
trace("buf[1] = %08x\n", buf[1]);
+}
expect_magic((DWORD*)(buf + 2));
+todo_wine
+{
expect_dword(buf + 3, 10);
expect_dword(buf + 4, CombineModeExclude);
expect_dword(buf + 5, CombineModeComplement);
@@ -257,8 +247,11 @@ todo_wine
expect(72, needed);
expect_dword(buf, 64);
trace("buf[1] = %08x\n", buf[1]);
+}
expect_magic((DWORD*)(buf + 2));
expect_dword(buf + 3, 0);
+todo_wine
+{
expect_dword(buf + 4, RGNDATA_PATH);
expect_dword(buf + 5, 0x00000030);
expect_magic((DWORD*)(buf + 6));
@@ -289,7 +282,10 @@ todo_wine
expect(96, needed);
expect_dword(buf, 88);
trace("buf[1] = %08x\n", buf[1]);
+}
expect_magic((DWORD*)(buf + 2));
+todo_wine
+{
expect_dword(buf + 3, 2);
expect_dword(buf + 4, CombineModeIntersect);
expect_dword(buf + 5, RGNDATA_PATH);
@@ -333,8 +329,11 @@ todo_wine
expect(36, needed);
expect_dword(buf, 28);
trace("buf[1] = %08x\n", buf[1]);
+}
expect_magic((DWORD*)(buf + 2));
expect_dword(buf + 3, 0);
+todo_wine
+{
expect_dword(buf + 4, RGNDATA_PATH);
/* Second signature for pathdata */
@@ -365,9 +364,12 @@ todo_wine
expect(Ok, status);
expect(56, needed);
expect_dword(buf, 48);
+}
trace("buf[1] = %08x\n", buf[1]);
expect_magic((DWORD*)(buf + 2));
expect_dword(buf + 3 , 0);
+todo_wine
+{
expect_dword(buf + 4 , RGNDATA_PATH);
expect_dword(buf + 5, 32);
@@ -399,9 +401,9 @@ todo_wine
expect(Ok, status);
status = GdipAddPathLine(path, 8.1, 1.6, 5.6, 6.2);
expect(Ok, status);
+ status = GdipCreateRegionPath(path, ®ion);
todo_wine
{
- status = GdipCreateRegionPath(path, ®ion);
expect(Ok, status);
status = GdipGetRegionDataSize(region, &needed);
expect(Ok, status);
@@ -411,8 +413,11 @@ todo_wine
expect(72, needed);
expect_dword(buf, 64);
trace("buf[1] = %08x\n", buf[1]);
+}
expect_magic((DWORD*)(buf + 2));
expect_dword(buf + 3, 0);
+todo_wine
+{
expect_dword(buf + 4, RGNDATA_PATH);
expect_dword(buf + 5, 48);
--
1.5.4.3
More information about the wine-patches
mailing list