diff --git a/dlls/gdiplus/region.c b/dlls/gdiplus/region.c index 69d31f26192..e2be5f5a30d 100644 --- a/dlls/gdiplus/region.c +++ b/dlls/gdiplus/region.c @@ -214,12 +214,122 @@ GpStatus WINGDIPAPI GdipCreateRegion(GpRegion **region) return init_region(*region, RegionDataInfiniteRect); } +/***************************************************************************** + * GdipCreateRegionPath [GDIPLUS.@] + * + * Creates a GpRegion from a GpPath + * + * PARAMS + * path [I] path to base the region on + * region [O] pointer to the newly allocated region + * + * RETURNS + * SUCCESS: Ok + * FAILURE: InvalidParameter + * + * NOTES + * If a path has no floating point points, its points will be stored as shorts + * (INTPATH) + * + * If a path is empty, it is considered to be an INTPATH + */ GpStatus WINGDIPAPI GdipCreateRegionPath(GpPath *path, GpRegion **region) { - FIXME("(%p, %p): stub\n", path, region); + region_element* element; + GpPoint *pointsi; + GpPointF *pointsf; - *region = NULL; - return NotImplemented; + GpStatus stat; + DWORD flags = FLAGS_INTPATH; + INT count, i; + + TRACE("%p, %p\n", path, region); + + if (!(path && region)) + return InvalidParameter; + + *region = GdipAlloc(sizeof(GpRegion)); + if(!*region) + return OutOfMemory; + stat = init_region(*region, RegionDataPath); + if (stat != Ok) + { + GdipDeleteRegion(*region); + return stat; + } + element = &(*region)->node; + count = path->pathdata.Count; + + /* Test to see if the path is an Integer path */ + if (count) + { + pointsi = GdipAlloc(sizeof(GpPoint) * count); + pointsf = GdipAlloc(sizeof(GpPointF) * count); + if (!(pointsi && pointsf)) + { + GdipFree(pointsi); + GdipFree(pointsf); + GdipDeleteRegion(*region); + return OutOfMemory; + } + + stat = GdipGetPathPointsI(path, pointsi, count); + if (stat != Ok) + { + GdipDeleteRegion(*region); + return stat; + } + stat = GdipGetPathPoints(path, pointsf, count); + if (stat != Ok) + { + GdipDeleteRegion(*region); + return stat; + } + + for (i = 0; i < count; i++) + { + if (!(pointsi[i].X == pointsf[i].X && + pointsi[i].Y == pointsf[i].Y )) + { + flags = FLAGS_NOFLAGS; + break; + } + } + GdipFree(pointsi); + GdipFree(pointsf); + } + + stat = GdipClonePath(path, &element->elementdata.pathdata.path); + if (stat != Ok) + { + GdipDeleteRegion(*region); + return stat; + } + + /* 3 for headers, once again size doesn't count itself */ + element->elementdata.pathdata.pathheader.size = ((sizeof(DWORD) * 3)); + switch(flags) + { + /* Floats, sent out as floats */ + case FLAGS_NOFLAGS: + element->elementdata.pathdata.pathheader.size += + (sizeof(DWORD) * count * 2); + break; + /* INTs, sent out as packed shorts */ + case FLAGS_INTPATH: + element->elementdata.pathdata.pathheader.size += + (sizeof(DWORD) * count); + break; + default: + FIXME("Unhandled flags (%08x). Expect wrong results.\n", flags); + } + element->elementdata.pathdata.pathheader.size += get_pathtypes_size(path); + element->elementdata.pathdata.pathheader.magic = VERSION_MAGIC; + element->elementdata.pathdata.pathheader.count = count; + element->elementdata.pathdata.pathheader.flags = flags; + (*region)->header.size = sizeheader_size + get_element_size(element); + + return Ok; } GpStatus WINGDIPAPI GdipCreateRegionRect(GDIPCONST GpRectF *rect, GpRegion **region) diff --git a/dlls/gdiplus/tests/region.c b/dlls/gdiplus/tests/region.c index 01991a260c0..17a4ba44d8d 100644 --- a/dlls/gdiplus/tests/region.c +++ b/dlls/gdiplus/tests/region.c @@ -172,6 +172,7 @@ todo_wine rect.Width = 22; rect.Height = 55; status = GdipCombineRegionRectI(region, &rect, CombineModeExclude); +todo_wine ok(status == Ok, "status %08x\n", status); status = GdipGetRegionDataSize(region, &needed); @@ -233,8 +234,6 @@ todo_wine status = GdipCreatePath(FillModeAlternate, &path); ok(status == Ok, "status %08x\n", status); -todo_wine -{ GdipAddPathRectangle(path, 12.5, 13.0, 14.0, 15.0); status = GdipCreateRegionPath(path, ®ion); @@ -247,11 +246,8 @@ 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)); @@ -273,12 +269,16 @@ todo_wine rect.Width = 10; rect.Height = 20; status = GdipCombineRegionRectI(region, &rect, CombineModeIntersect); +todo_wine ok(status == Ok, "status %08x\n", status); status = GdipGetRegionDataSize(region, &needed); ok(status == Ok, "status %08x\n", status); +todo_wine expect(96, needed); status = GdipGetRegionData(region, (BYTE*)buf, sizeof(buf), &needed); ok(status == Ok, "status %08x\n", status); +todo_wine +{ expect(96, needed); expect_dword(buf, 88); trace("buf[1] = %08x\n", buf[1]); @@ -307,18 +307,16 @@ todo_wine expect_float(buf + 21, 30.0); expect_float(buf + 22, 10.0); expect_float(buf + 23, 20.0); +} status = GdipDeleteRegion(region); ok(status == Ok, "status %08x\n", status); -} status = GdipDeletePath(path); ok(status == Ok, "status %08x\n", status); /* Test an empty path */ status = GdipCreatePath(FillModeAlternate, &path); expect(Ok, status); -todo_wine -{ status = GdipCreateRegionPath(path, ®ion); expect(Ok, status); status = GdipGetRegionDataSize(region, &needed); @@ -329,11 +327,8 @@ 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 */ @@ -344,7 +339,6 @@ todo_wine status = GdipDeleteRegion(region); expect(Ok, status); -} /* Test a simple triangle of INTs */ status = GdipAddPathLine(path, 5, 6, 7, 8); @@ -353,8 +347,6 @@ todo_wine expect(Ok, status); status = GdipClosePathFigure(path); expect(Ok, status); -todo_wine -{ status = GdipCreateRegionPath(path, ®ion); expect(Ok, status); status = GdipGetRegionDataSize(region, &needed); @@ -364,12 +356,9 @@ 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); @@ -387,11 +376,10 @@ todo_wine expect(5, point[3].X); /* buf + 12 */ expect(6, point[3].Y); expect_dword(buf + 13, 0x81010100); /* 0x01010100 if we don't close the path */ -} + status = GdipDeletePath(path); expect(Ok, status); status = GdipDeleteRegion(region); -todo_wine expect(Ok, status); /* Test a floating-point triangle */ @@ -402,8 +390,6 @@ todo_wine status = GdipAddPathLine(path, 8.1, 1.6, 5.6, 6.2); expect(Ok, status); status = GdipCreateRegionPath(path, ®ion); -todo_wine -{ expect(Ok, status); status = GdipGetRegionDataSize(region, &needed); expect(Ok, status); @@ -413,11 +399,8 @@ 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); @@ -432,12 +415,10 @@ todo_wine expect_float(buf + 14, 1.6); expect_float(buf + 15, 5.6); expect_float(buf + 16, 6.2); -} status = GdipDeletePath(path); expect(Ok, status); status = GdipDeleteRegion(region); -todo_wine expect(Ok, status); }