From 91e44fd8595c3e60fb212254a153783421ed4fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Wed, 25 Jun 2003 16:55:33 +0000 Subject: [PATCH] Fix polygon outline special case and min/max caption buttons svn path=/trunk/; revision=4965 --- reactos/lib/user32/windows/draw.c | 4 +- reactos/subsys/win32k/include/paint.h | 6 +- reactos/subsys/win32k/objects/fillshap.c | 218 ++++++++++++++--------- reactos/subsys/win32k/objects/polyfill.c | 116 ++++++------ 4 files changed, 204 insertions(+), 140 deletions(-) diff --git a/reactos/lib/user32/windows/draw.c b/reactos/lib/user32/windows/draw.c index dd63408f953..e98a85ae724 100644 --- a/reactos/lib/user32/windows/draw.c +++ b/reactos/lib/user32/windows/draw.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: draw.c,v 1.11 2003/05/12 19:30:00 jfilby Exp $ +/* $Id: draw.c,v 1.12 2003/06/25 16:55:32 gvg Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/input.c @@ -983,7 +983,7 @@ static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags) return TRUE; case DFCS_CAPTIONMIN: - Line1[0].x = Line1[3].x = myr.left + 96*SmallDiam/750+2; + Line1[0].x = Line1[3].x = myr.left + 96*SmallDiam/750+3; /* Wine uses +2 here?? */ Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750; Line1[0].y = Line1[1].y = myr.top + 563*SmallDiam/750+1; Line1[2].y = Line1[3].y = Line1[0].y + 92*SmallDiam/750; diff --git a/reactos/subsys/win32k/include/paint.h b/reactos/subsys/win32k/include/paint.h index 7c5f6f3626b..3eb8a796ffa 100644 --- a/reactos/subsys/win32k/include/paint.h +++ b/reactos/subsys/win32k/include/paint.h @@ -2,7 +2,7 @@ #define __WIN32K_PAINT_H BOOL STDCALL FillSolid (PSURFOBJ Surface, PRECTL Dimensions, ULONG iColor); -BOOL STDCALL FillPolygon_ALTERNATE (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect, INT OrigX, INT OrigY); -BOOL STDCALL FillPolygon_WINDING (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect, INT OrigX, INT OrigY); +BOOL STDCALL FillPolygon_ALTERNATE (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect); +BOOL STDCALL FillPolygon_WINDING (PSURFOBJ SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, INT Count, RECTL BoundRect); -#endif /* __WIN32K_DIB_H */ +#endif /* __WIN32K_PAINT_H */ diff --git a/reactos/subsys/win32k/objects/fillshap.c b/reactos/subsys/win32k/objects/fillshap.c index 8e84b6053f7..29c047e6bb9 100644 --- a/reactos/subsys/win32k/objects/fillshap.c +++ b/reactos/subsys/win32k/objects/fillshap.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: fillshap.c,v 1.19 2003/06/06 10:27:43 gvg Exp $ */ +/* $Id: fillshap.c,v 1.20 2003/06/25 16:55:33 gvg Exp $ */ #undef WIN32_LEAN_AND_MEAN #include @@ -24,10 +24,12 @@ #include #include #include +#include #include #include #include #include +#include #define NDEBUG #include @@ -85,9 +87,7 @@ extern BOOL FillPolygon_ALTERNATE(SURFOBJ *SurfObj, MIX RopMode, CONST PPOINT Points, int Count, - RECTL BoundRect, - int OrigX, - int OrigY); + RECTL BoundRect); //WINDING Selects winding mode (fills any region with a nonzero winding value). @@ -98,110 +98,168 @@ extern BOOL FillPolygon_WINDING(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CONST PPOINT Points, int Count, - RECTL BoundRect, - int OrigX, - int OrigY); + RECTL BoundRect); #endif //This implementation is blatantly ripped off from W32kRectangle BOOL STDCALL W32kPolygon(HDC hDC, - CONST PPOINT Points, - int Count) + CONST PPOINT UnsafePoints, + int Count) { - DC *dc = DC_HandleToPtr(hDC); - SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface); - PBRUSHOBJ OutBrushObj, FillBrushObj; - BOOL ret; - PRECTL RectBounds; - PENOBJ *pen; - RECTL DestRect; - int CurrentPoint; + DC *dc = DC_HandleToPtr(hDC); + SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface); + PBRUSHOBJ OutBrushObj, FillBrushObj; + BOOL ret; + PRECTL RectBounds; + PENOBJ *pen; + RECTL DestRect; + int CurrentPoint; + PPOINT Points; + NTSTATUS Status; DPRINT("In W32kPolygon()\n"); - if(0 == dc) - return FALSE; + if (NULL == dc || NULL == Points || Count < 2) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return FALSE; + } - if(0 == Points) - return FALSE; + /* Copy points from userspace to kernelspace */ + Points = ExAllocatePool(PagedPool, Count * sizeof(POINT)); + if (NULL == Points) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + Status = MmCopyFromCaller(Points, UnsafePoints, Count * sizeof(POINT)); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + ExFreePool(Points); + return FALSE; + } - if (2 > Count) - return FALSE; + /* Convert to screen coordinates */ + for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++) + { + Points[CurrentPoint].x += dc->w.DCOrgX; + Points[CurrentPoint].y += dc->w.DCOrgY; + } RectBounds = GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); //ei not yet implemented ASSERT(RectBounds); - - DestRect.bottom = Points[0].y + dc->w.DCOrgY + 1; - DestRect.top = Points[0].y + dc->w.DCOrgY; - DestRect.right = Points[0].y + dc->w.DCOrgX; - DestRect.left = Points[0].y + dc->w.DCOrgX + 1; - - - if(PATH_IsPathOpen(dc->w.path)) - { + if (PATH_IsPathOpen(dc->w.path)) + { ret = PATH_Polygon(hDC, Points, Count); - } + } else - { - //Get the current pen. - pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); + { + /* Get the current pen. */ + pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); ASSERT(pen); - OutBrushObj = (PBRUSHOBJ)PenToBrushObj(dc, pen); - GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC ); - - // Draw the Polygon Edges with the current pen - for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint) - { - DestRect.bottom = MAX(DestRect.bottom, Points[CurrentPoint].y); - DestRect.top = MIN(DestRect.top, Points[CurrentPoint].y); - DestRect.right = MAX(DestRect.right, Points[CurrentPoint].y); - DestRect.left = MIN(DestRect.left, Points[CurrentPoint].y); - }//for + OutBrushObj = (PBRUSHOBJ) PenToBrushObj(dc, pen); + GDIOBJ_UnlockObj(dc->w.hPen, GO_PEN_MAGIC); - //Now fill the polygon with the current brush. - FillBrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); - // determine the fill mode to fill the polygon. - if (dc->w.polyFillMode == WINDING) - ret = FillPolygon_WINDING(SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect, dc->w.DCOrgX, dc->w.DCOrgY); - else//default - ret = FillPolygon_ALTERNATE(SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect, dc->w.DCOrgX, dc->w.DCOrgY); + DestRect.left = Points[0].x; + DestRect.right = Points[0].x; + DestRect.top = Points[0].y; + DestRect.bottom = Points[0].y; + + for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) + { + DestRect.left = MIN(DestRect.left, Points[CurrentPoint].x); + DestRect.right = MAX(DestRect.right, Points[CurrentPoint].x); + DestRect.top = MIN(DestRect.top, Points[CurrentPoint].y); + DestRect.bottom = MAX(DestRect.bottom, Points[CurrentPoint].y); + } + + /* Now fill the polygon with the current brush. */ + FillBrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); + /* determine the fill mode to fill the polygon. */ + if (WINDING == dc->w.polyFillMode) + { + ret = FillPolygon_WINDING(SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect); + } + else /* default */ + { + ret = FillPolygon_ALTERNATE(SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect); + } + // Draw the Polygon Edges with the current pen - for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint) - { - POINT To,From; - //Let CurrentPoint be i - //if i+1 > Count, Draw a line from Points[i] to Points[0] - //Draw a line from Points[i] to Points[i+1] - if (CurrentPoint + 1 >= Count) + for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint) + { + POINT To, From, Next; + + /* Let CurrentPoint be i + * if i+1 > Count, Draw a line from Points[i] to Points[0] + * Draw a line from Points[i] to Points[i+1] + */ + From = Points[CurrentPoint]; + if (Count <= CurrentPoint + 1) + { + To = Points[0]; + } + else + { + To = Points[CurrentPoint + 1]; + } + + /* Special handling of lower right corner of a rectangle. If we + * don't treat it specially, it will end up looking like this: + * + * * + * * + * * + * ********* + */ + if (3 < Count) + { + if (Count <= CurrentPoint + 2) { - To = Points[CurrentPoint]; - From = Points[0]; + Next = Points[CurrentPoint + 2 - Count]; } - else + else { - From = Points[CurrentPoint]; - To = Points[CurrentPoint + 1]; + Next = Points[CurrentPoint + 2]; } - DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y ); - ret = EngLineTo(SurfObj, - NULL, // ClipObj, - OutBrushObj, - From.x + dc->w.DCOrgX, - From.y + dc->w.DCOrgY, - To.x + dc->w.DCOrgX, - To.y + dc->w.DCOrgY, - RectBounds, // Bounding rectangle - dc->w.ROPmode); // MIX + if (From.x == To.x && + From.y <= To.y && + To.y == Next.y && + Next.x <= To.x) + { + To.y++; + } + else if (From.y == To.y && + From.x <= To.x && + To.x == Next.x && + Next.y <= To.y) + { + To.x++; + } + } + DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y ); + ret = IntEngLineTo(SurfObj, + NULL, /* ClipObj */ + OutBrushObj, + From.x, + From.y, + To.x, + To.y, + &DestRect, + dc->w.ROPmode); /* MIX */ - }//for - GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC ); - }// else + } + GDIOBJ_UnlockObj(dc->w.hBrush, GO_BRUSH_MAGIC); + } GDIOBJ_UnlockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); - DC_ReleasePtr( hDC ); + DC_ReleasePtr(hDC); + ExFreePool(Points); + return ret; } diff --git a/reactos/subsys/win32k/objects/polyfill.c b/reactos/subsys/win32k/objects/polyfill.c index 2874a1122d0..4fbece0e1b1 100644 --- a/reactos/subsys/win32k/objects/polyfill.c +++ b/reactos/subsys/win32k/objects/polyfill.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: polyfill.c,v 1.3 2003/05/18 17:16:18 ea Exp $ +/* $Id: polyfill.c,v 1.4 2003/06/25 16:55:33 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -487,41 +487,41 @@ static void STDCALL POLYGONFILL_UpdateActiveEdges(int Scanline, PFILL_EDGE_LIST ** This method fills the portion of the polygon that intersects with the scanline ** Scanline. */ -static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, int OrigX, int OrigY) +static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST ActiveEdges, SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode) { - BOOL OnOdd = TRUE; - RECTL BoundRect; - int XInterceptOdd,XInterceptEven,ret; - PPFILL_EDGE pThis = ActiveEdges; + BOOL OnOdd = TRUE; + RECTL BoundRect; + int XInterceptOdd,XInterceptEven,ret; + PPFILL_EDGE pThis = ActiveEdges; - while (0 != pThis) + while (NULL != pThis) { - if (OnOdd) - { - XInterceptOdd = pThis->XIntercept; - OnOdd = FALSE; - } - else - { - BoundRect.top = ScanLine + OrigY - 1; - BoundRect.bottom = ScanLine + OrigY + 1; - BoundRect.left = XInterceptOdd + OrigX - 2; - BoundRect.right = XInterceptEven + OrigX; + if (OnOdd) + { + XInterceptOdd = pThis->XIntercept; + OnOdd = FALSE; + } + else + { + BoundRect.top = ScanLine - 1; + BoundRect.bottom = ScanLine + 1; + BoundRect.left = XInterceptOdd - 2; + BoundRect.right = XInterceptEven; - XInterceptEven = pThis->XIntercept; - DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1,ScanLine ,XInterceptEven - 1,ScanLine ); - ret = EngLineTo(SurfObj, - NULL, // ClipObj, - BrushObj, - XInterceptOdd + OrigX - 1, - ScanLine + OrigY, - XInterceptEven + OrigX - 1, - ScanLine + OrigY, - &BoundRect, // Bounding rectangle - RopMode); // MIX - OnOdd = TRUE; - } - pThis = pThis->pNext; + XInterceptEven = pThis->XIntercept; + DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1, ScanLine, XInterceptEven - 1, ScanLine); + ret = EngLineTo(SurfObj, + NULL, /* ClipObj */ + BrushObj, + XInterceptOdd - 1, + ScanLine, + XInterceptEven - 1, + ScanLine, + &BoundRect, /* Bounding rectangle */ + RopMode); /* MIX */ + OnOdd = TRUE; + } + pThis = pThis->pNext; } } @@ -530,40 +530,46 @@ static void STDCALL POLYGONFILL_FillScanLine(int ScanLine, PFILL_EDGE_LIST Activ //When the fill mode is ALTERNATE, GDI fills the area between odd-numbered and //even-numbered polygon sides on each scan line. That is, GDI fills the area between the //first and second side, between the third and fourth side, and so on. -BOOL STDCALL FillPolygon_ALTERNATE(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect, int OrigX, int OrigY) +BOOL STDCALL FillPolygon_ALTERNATE(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj, MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect) { - PFILL_EDGE_LIST list = 0; - PFILL_EDGE_LIST ActiveEdges = 0; - int ScanLine; - DPRINT("FillPolygon_ALTERNATE\n"); + PFILL_EDGE_LIST list = 0; + PFILL_EDGE_LIST ActiveEdges = 0; + int ScanLine; + + DPRINT("FillPolygon_ALTERNATE\n"); - //Create Edge List. - list = POLYGONFILL_MakeEdgeList(Points, Count); - //DEBUG_PRINT_EDGELIST(list); - if (0 == list) return FALSE; + /* Create Edge List. */ + list = POLYGONFILL_MakeEdgeList(Points, Count); + /* DEBUG_PRINT_EDGELIST(list); */ + if (NULL == list) + { + return FALSE; + } - //For each Scanline from BoundRect.bottom to BoundRect.top, - //determine line segments to draw - for (ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom ; ++ScanLine) - { - POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges); - //DEBUG_PRINT_EDGELIST(ActiveEdges); - POLYGONFILL_FillScanLine(ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode, OrigX, OrigY); - } + /* For each Scanline from BoundRect.bottom to BoundRect.top, + * determine line segments to draw + */ + for (ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom ; ++ScanLine) + { + POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges); + /* DEBUG_PRINT_EDGELIST(ActiveEdges); */ + POLYGONFILL_FillScanLine(ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode); + } - //Free Edge List. If any are left. - POLYGONFILL_DestroyEdgeList(list); + /* Free Edge List. If any are left. */ + POLYGONFILL_DestroyEdgeList(list); - return TRUE; + return TRUE; } //WINDING Selects winding mode (fills any region with a nonzero winding value). //When the fill mode is WINDING, GDI fills any region that has a nonzero winding value. //This value is defined as the number of times a pen used to draw the polygon would go around the region. //The direction of each edge of the polygon is important. -BOOL STDCALL FillPolygon_WINDING(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect, int OrigX, int OrigY) +BOOL STDCALL FillPolygon_WINDING(SURFOBJ *SurfObj, PBRUSHOBJ BrushObj,MIX RopMode, CONST PPOINT Points, int Count, RECTL BoundRect) { - DPRINT("FillPolygon_WINDING\n"); - return FALSE; + DPRINT("FillPolygon_WINDING\n"); + + return FALSE; } /* EOF */