diff --git a/reactos/include/win32k/cliprgn.h b/reactos/include/win32k/cliprgn.h index 6a0107e1ddf..e0bbe78a939 100644 --- a/reactos/include/win32k/cliprgn.h +++ b/reactos/include/win32k/cliprgn.h @@ -4,6 +4,14 @@ HRGN WINAPI SaveVisRgn(HDC hdc); INT WINAPI SelectVisRgn(HDC hdc, HRGN hrgn); +int +STDCALL +IntGdiExtSelectClipRgn ( + PDC dc, + HRGN hrgn, + int fnMode + ); + int STDCALL NtGdiExcludeClipRect ( diff --git a/reactos/subsys/win32k/include/path.h b/reactos/subsys/win32k/include/path.h index 2a77fef5d3f..9631b1fc120 100644 --- a/reactos/subsys/win32k/include/path.h +++ b/reactos/subsys/win32k/include/path.h @@ -18,6 +18,6 @@ BOOL FASTCALL PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UI BOOL FASTCALL PATH_PolyPolyline( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines); BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2); BOOL FASTCALL PATH_RoundRect (PDC dc, INT x1, INT y1, INT x2, INT y2, INT xradius, INT yradius); -BOOL FASTCALL PATH_PathToRegion (const GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn); +BOOL FASTCALL PATH_PathToRegion (GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn); #endif /* _WIN32K_PATH_H */ diff --git a/reactos/subsys/win32k/objects/cliprgn.c b/reactos/subsys/win32k/objects/cliprgn.c index 3e8c047c767..1c49d97bc69 100644 --- a/reactos/subsys/win32k/objects/cliprgn.c +++ b/reactos/subsys/win32k/objects/cliprgn.c @@ -99,20 +99,13 @@ NtGdiSelectVisRgn(HDC hdc, HRGN hrgn) return retval; } -int STDCALL NtGdiExtSelectClipRgn(HDC hDC, - HRGN hrgn, - int fnMode) + +int STDCALL IntGdiExtSelectClipRgn(PDC dc, + HRGN hrgn, + int fnMode) { int retval; - DC *dc; - - if (!(dc = DC_LockDc(hDC))) - { - SetLastWin32Error(ERROR_INVALID_HANDLE); - return ERROR; - } - -// dc->w.flags &= ~DC_DIRTY; + // dc->w.flags &= ~DC_DIRTY; if (!hrgn) { @@ -127,7 +120,6 @@ int STDCALL NtGdiExtSelectClipRgn(HDC hDC, } else { - DC_UnlockDc(dc); SetLastWin32Error(ERROR_INVALID_PARAMETER); return ERROR; } @@ -158,8 +150,26 @@ int STDCALL NtGdiExtSelectClipRgn(HDC hDC, } retval = CLIPPING_UpdateGCRegion(dc); - DC_UnlockDc(dc); + return retval; +} + +int STDCALL NtGdiExtSelectClipRgn(HDC hDC, + HRGN hrgn, + int fnMode) +{ + int retval; + DC *dc; + + if (!(dc = DC_LockDc(hDC))) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + return ERROR; + } + + retval = IntGdiExtSelectClipRgn ( dc, hrgn, fnMode ); + + DC_UnlockDc(dc); return retval; } @@ -427,13 +437,6 @@ BOOL STDCALL NtGdiRectVisible(HDC hDC, return Result; } -BOOL STDCALL NtGdiSelectClipPath(HDC hDC, - int Mode) -{ - UNIMPLEMENTED; - return FALSE; -} - INT STDCALL NtGdiSelectClipRgn(HDC hDC, HRGN hRgn) { diff --git a/reactos/subsys/win32k/objects/path.c b/reactos/subsys/win32k/objects/path.c index 7ba72082aab..472b00703f4 100644 --- a/reactos/subsys/win32k/objects/path.c +++ b/reactos/subsys/win32k/objects/path.c @@ -35,7 +35,7 @@ BOOL FASTCALL PATH_FillPath( PDC dc, GdiPath *pPath ); BOOL FASTCALL PATH_FlattenPath (GdiPath *pPath); VOID FASTCALL PATH_GetPathFromDC (PDC dc, GdiPath **ppPath); VOID FASTCALL PATH_NormalizePoint (FLOAT_POINT corners[], const FLOAT_POINT *pPoint, double *pX, double *pY); -BOOL FASTCALL PATH_PathToRegion(const GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn); +BOOL FASTCALL PATH_PathToRegion (GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn); BOOL FASTCALL PATH_ReserveEntries (GdiPath *pPath, INT numEntries); VOID FASTCALL PATH_ScaleNormalizedPoint (FLOAT_POINT corners[], double x, double y, POINT *pPoint); @@ -235,7 +235,37 @@ NtGdiWidenPath(HDC hDC) return FALSE; } +BOOL STDCALL NtGdiSelectClipPath(HDC hDC, + int Mode) +{ + GdiPath *pPath; + HRGN hrgnPath; + BOOL success = FALSE; + PDC dc = DC_LockDc ( hDC ); + if( !dc ) return FALSE; + + PATH_GetPathFromDC ( dc, &pPath ); + + /* Check that path is closed */ + if( pPath->state != PATH_Closed ) + SetLastWin32Error(ERROR_CAN_NOT_COMPLETE); + return FALSE; + /* Construct a region from the path */ + else if( PATH_PathToRegion( pPath, dc->w.polyFillMode, &hrgnPath ) ) + { + success = IntGdiExtSelectClipRgn( dc, hrgnPath, Mode ) != ERROR; + NtGdiDeleteObject( hrgnPath ); + + /* Empty the path */ + if( success ) + PATH_EmptyPath( pPath ); + /* FIXME: Should this function delete the path even if it failed? */ + } + + DC_UnlockDc ( dc ); + return success; +} /*********************************************************************** * Exported functions @@ -243,19 +273,76 @@ NtGdiWidenPath(HDC hDC) /* PATH_FillPath - * unimplemented + * * */ BOOL FASTCALL PATH_FillPath( PDC dc, GdiPath *pPath ) { + INT mapMode, graphicsMode; + SIZE ptViewportExt, ptWindowExt; + POINT ptViewportOrg, ptWindowOrg; + XFORM xform; + HRGN hrgn; + if( pPath->state != PATH_Closed ) { + SetLastWin32Error(ERROR_CAN_NOT_COMPLETE); return FALSE; } - UNIMPLEMENTED; + if( PATH_PathToRegion( pPath, dc->w.polyFillMode, &hrgn )) + { + /* Since PaintRgn interprets the region as being in logical coordinates + * but the points we store for the path are already in device + * coordinates, we have to set the mapping mode to MM_TEXT temporarily. + * Using SaveDC to save information about the mapping mode / world + * transform would be easier but would require more overhead, especially + * now that SaveDC saves the current path. + */ + + /* Save the information about the old mapping mode */ + mapMode = NtGdiGetMapMode( dc->hSelf ); + NtGdiGetViewportExtEx( dc->hSelf, &ptViewportExt ); + NtGdiGetViewportOrgEx( dc->hSelf, &ptViewportOrg ); + NtGdiGetWindowExtEx( dc->hSelf, &ptWindowExt ); + NtGdiGetWindowOrgEx( dc->hSelf, &ptWindowOrg ); + + /* Save world transform + * NB: The Windows documentation on world transforms would lead one to + * believe that this has to be done only in GM_ADVANCED; however, my + * tests show that resetting the graphics mode to GM_COMPATIBLE does + * not reset the world transform. + */ + NtGdiGetWorldTransform( dc->hSelf, &xform ); + + /* Set MM_TEXT */ + NtGdiSetMapMode( dc->hSelf, MM_TEXT ); + NtGdiSetViewportOrgEx( dc->hSelf, 0, 0, NULL ); + NtGdiSetWindowOrgEx( dc->hSelf, 0, 0, NULL ); + graphicsMode = NtGdiGetGraphicsMode( dc->hSelf ); + NtGdiSetGraphicsMode( dc->hSelf, GM_ADVANCED ); + NtGdiModifyWorldTransform( dc->hSelf, &xform, MWT_IDENTITY ); + NtGdiSetGraphicsMode( dc->hSelf, graphicsMode ); + + /* Paint the region */ + NtGdiPaintRgn( dc->hSelf, hrgn ); + NtGdiDeleteObject( hrgn ); + /* Restore the old mapping mode */ + NtGdiSetMapMode( dc->hSelf, mapMode ); + NtGdiSetViewportExtEx( dc->hSelf, ptViewportExt.cx, ptViewportExt.cy, NULL ); + NtGdiSetViewportOrgEx( dc->hSelf, ptViewportOrg.x, ptViewportOrg.y, NULL ); + NtGdiSetWindowExtEx( dc->hSelf, ptWindowExt.cx, ptWindowExt.cy, NULL ); + NtGdiSetWindowOrgEx( dc->hSelf, ptWindowOrg.x, ptWindowOrg.y, NULL ); + + /* Go to GM_ADVANCED temporarily to restore the world transform */ + graphicsMode = NtGdiGetGraphicsMode( dc->hSelf ); + NtGdiSetGraphicsMode( dc->hSelf, GM_ADVANCED ); + NtGdiSetWorldTransform( dc->hSelf, &xform ); + NtGdiSetGraphicsMode( dc->hSelf, graphicsMode ); + return TRUE; + } return FALSE; } @@ -924,15 +1011,11 @@ PATH_FlattenPath(GdiPath *pPath) * error occurs, SetLastError is called with the appropriate value and * FALSE is returned. */ -#if 0 -// FIXME - don't reenable this function until you deal with the -// const pPath being given to PATH_FlattenPath() - which is -// expecting a non-const*. Since this function isn't being called -// at the moment, I'm commenting it out until the issue needs to -// be addressed. + + BOOL FASTCALL -PATH_PathToRegion ( const GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn ) +PATH_PathToRegion ( GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn ) { int numStrokes, iStroke, i; INT *pNumPointsInStroke; @@ -990,7 +1073,6 @@ PATH_PathToRegion ( const GdiPath *pPath, INT nPolyFillMode, HRGN *pHrgn ) *pHrgn=hrgn; return TRUE; } -#endif /* PATH_EmptyPath *