Module: wine Branch: master Commit: f52b92efe504044018403e6221ab7d2664be51fb URL: http://source.winehq.org/git/wine.git/?a=commit;h=f52b92efe504044018403e6221...
Author: Dmitry Timoshkov dmitry@codeweavers.com Date: Fri Apr 18 22:42:43 2008 +0900
gdi32: Add a test for ExtCreateRegion, make it pass under Wine.
---
dlls/gdi32/region.c | 61 +++++++++++++++++--- dlls/gdi32/tests/clipping.c | 136 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 8 deletions(-)
diff --git a/dlls/gdi32/region.c b/dlls/gdi32/region.c index d0d8580..c9b9e1d 100644 --- a/dlls/gdi32/region.c +++ b/dlls/gdi32/region.c @@ -985,6 +985,19 @@ DWORD WINAPI GetRegionData(HRGN hrgn, DWORD count, LPRGNDATA rgndata) }
+static void translate( POINT *pt, UINT count, const XFORM *xform ) +{ + while (count--) + { + FLOAT x = pt->x; + FLOAT y = pt->y; + pt->x = floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 ); + pt->y = floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 ); + pt++; + } +} + + /*********************************************************************** * ExtCreateRegion (GDI32.@) * @@ -1008,16 +1021,47 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA*
TRACE(" %p %d %p\n", lpXform, dwCount, rgndata );
- if( lpXform ) - WARN("(Xform not implemented - ignored)\n"); + if (!rgndata) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; + }
+ if (rgndata->rdh.dwSize < sizeof(RGNDATAHEADER)) + return 0; + + /* XP doesn't care about the type */ if( rgndata->rdh.iType != RDH_RECTANGLES ) + WARN("(Unsupported region data type: %u)\n", rgndata->rdh.iType); + + if (lpXform) { - /* FIXME: We can use CreatePolyPolygonRgn() here - * for trapezoidal data */ + RECT *pCurRect, *pEndRect;
- WARN("(Unsupported region data type: %u)\n", rgndata->rdh.iType); - goto fail; + hrgn = CreateRectRgn( 0, 0, 0, 0 ); + + pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount; + for (pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++) + { + static const INT count = 4; + HRGN poly_hrgn; + POINT pt[4]; + + pt[0].x = pCurRect->left; + pt[0].y = pCurRect->top; + pt[1].x = pCurRect->right; + pt[1].y = pCurRect->top; + pt[2].x = pCurRect->right; + pt[2].y = pCurRect->bottom; + pt[3].x = pCurRect->left; + pt[3].y = pCurRect->bottom; + + translate( pt, 4, lpXform ); + poly_hrgn = CreatePolyPolygonRgn( pt, &count, 1, WINDING ); + CombineRgn( hrgn, hrgn, poly_hrgn, RGN_OR ); + DeleteObject( poly_hrgn ); + } + return hrgn; }
if( (hrgn = REGION_CreateRegion( rgndata->rdh.nCount )) ) @@ -1039,8 +1083,7 @@ HRGN WINAPI ExtCreateRegion( const XFORM* lpXform, DWORD dwCount, const RGNDATA* } else ERR("Could not get pointer to newborn Region!\n"); } -fail: - WARN("Failed\n"); + return 0; }
@@ -2743,6 +2786,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, int numFullPtBlocks = 0; INT poly, total;
+ TRACE("%p, count %d, polygons %d, mode %d\n", Pts, *Count, nbpolygons, mode); + if(!(hrgn = REGION_CreateRegion(nbpolygons))) return 0; obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC ); diff --git a/dlls/gdi32/tests/clipping.c b/dlls/gdi32/tests/clipping.c index 5e1d35f..25cc146 100644 --- a/dlls/gdi32/tests/clipping.c +++ b/dlls/gdi32/tests/clipping.c @@ -119,7 +119,143 @@ static void test_GetRandomRgn(void) DestroyWindow(hwnd); }
+static void verify_region(HRGN hrgn, const RECT *rc) +{ + union + { + RGNDATA data; + char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)]; + } rgn; + const RECT *rect; + DWORD ret; + + ret = GetRegionData(hrgn, 0, NULL); + if (IsRectEmpty(rc)) + ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret); + else + ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret); + + if (!ret) return; + + ret = GetRegionData(hrgn, sizeof(rgn), &rgn.data); + if (IsRectEmpty(rc)) + ok(ret == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u\n", ret); + else + ok(ret == sizeof(rgn.data.rdh) + sizeof(RECT), "expected sizeof(rgn), got %u\n", ret); + + trace("size %u, type %u, count %u, rgn size %u, bound (%d,%d-%d,%d)\n", + rgn.data.rdh.dwSize, rgn.data.rdh.iType, + rgn.data.rdh.nCount, rgn.data.rdh.nRgnSize, + rgn.data.rdh.rcBound.left, rgn.data.rdh.rcBound.top, + rgn.data.rdh.rcBound.right, rgn.data.rdh.rcBound.bottom); + if (rgn.data.rdh.nCount != 0) + { + rect = (const RECT *)rgn.data.Buffer; + trace("rect (%d,%d-%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom); + ok(EqualRect(rect, rc), "rects don't match\n"); + } + + ok(rgn.data.rdh.dwSize == sizeof(rgn.data.rdh), "expected sizeof(rdh), got %u", rgn.data.rdh.dwSize); + ok(rgn.data.rdh.iType == RDH_RECTANGLES, "expected RDH_RECTANGLES, got %u\n", rgn.data.rdh.iType); + if (IsRectEmpty(rc)) + { + ok(rgn.data.rdh.nCount == 0, "expected 0, got %u\n", rgn.data.rdh.nCount); + ok(rgn.data.rdh.nRgnSize == 0, "expected 0, got %u\n", rgn.data.rdh.nRgnSize); + } + else + { + ok(rgn.data.rdh.nCount == 1, "expected 1, got %u\n", rgn.data.rdh.nCount); + ok(rgn.data.rdh.nRgnSize == sizeof(RECT), "expected sizeof(RECT), got %u\n", rgn.data.rdh.nRgnSize); + } + ok(EqualRect(&rgn.data.rdh.rcBound, rc), "rects don't match\n"); +} + +static void test_ExtCreateRegion(void) +{ + static const RECT empty_rect; + static const RECT rc = { 111, 222, 333, 444 }; + static const RECT rc_xformed = { 76, 151, 187, 262 }; + union + { + RGNDATA data; + char buf[sizeof(RGNDATAHEADER) + sizeof(RECT)]; + } rgn; + HRGN hrgn; + XFORM xform; + +if (0) /* crashes under Win9x */ +{ + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(NULL, 0, NULL); + ok(!hrgn, "ExtCreateRegion should fail\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "ERROR_INVALID_PARAMETER, got %u\n", GetLastError()); +} + + rgn.data.rdh.dwSize = 0; + rgn.data.rdh.iType = 0; + rgn.data.rdh.nCount = 0; + rgn.data.rdh.nRgnSize = 0; + SetRectEmpty(&rgn.data.rdh.rcBound); + memcpy(rgn.data.Buffer, &rc, sizeof(rc)); + + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data); + ok(!hrgn, "ExtCreateRegion should fail\n"); + ok(GetLastError() == 0xdeadbeef, "0xdeadbeef, got %u\n", GetLastError()); + + rgn.data.rdh.dwSize = sizeof(rgn.data.rdh) - 1; + + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data); + ok(!hrgn, "ExtCreateRegion should fail\n"); + ok(GetLastError() == 0xdeadbeef, "0xdeadbeef, got %u\n", GetLastError()); + + /* although XP doesn't care about the type Win9x does */ + rgn.data.rdh.iType = RDH_RECTANGLES; + rgn.data.rdh.dwSize = sizeof(rgn.data.rdh); + + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data); + ok(hrgn != 0, "ExtCreateRegion error %u\n", GetLastError()); + verify_region(hrgn, &empty_rect); + DeleteObject(hrgn); + + rgn.data.rdh.nCount = 1; + SetRectEmpty(&rgn.data.rdh.rcBound); + memcpy(rgn.data.Buffer, &rc, sizeof(rc)); + + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(NULL, sizeof(rgn), &rgn.data); + ok(hrgn != 0, "ExtCreateRegion error %u\n", GetLastError()); + verify_region(hrgn, &rc); + DeleteObject(hrgn); + + rgn.data.rdh.dwSize = sizeof(rgn.data.rdh) + 1; + + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(NULL, 1, &rgn.data); + ok(hrgn != 0, "ExtCreateRegion error %u\n", GetLastError()); + verify_region(hrgn, &rc); + DeleteObject(hrgn); + + xform.eM11 = 0.5; /* 50% width */ + xform.eM12 = 0.0; + xform.eM21 = 0.0; + xform.eM22 = 0.5; /* 50% height */ + xform.eDx = 20.0; + xform.eDy = 40.0; + + rgn.data.rdh.dwSize = sizeof(rgn.data.rdh); + + SetLastError(0xdeadbeef); + hrgn = ExtCreateRegion(&xform, sizeof(rgn), &rgn.data); + ok(hrgn != 0, "ExtCreateRegion error %u/%x\n", GetLastError(), GetLastError()); + verify_region(hrgn, &rc_xformed); + DeleteObject(hrgn); +} + START_TEST(clipping) { test_GetRandomRgn(); + test_ExtCreateRegion(); }