Fix polygon outline special case and min/max caption buttons

svn path=/trunk/; revision=4965
This commit is contained in:
Gé van Geldorp 2003-06-25 16:55:33 +00:00
parent a547aaf0c5
commit 91e44fd859
4 changed files with 204 additions and 140 deletions

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/input.c * FILE: lib/user32/windows/input.c
@ -983,7 +983,7 @@ static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
return TRUE; return TRUE;
case DFCS_CAPTIONMIN: 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[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750;
Line1[0].y = Line1[1].y = myr.top + 563*SmallDiam/750+1; Line1[0].y = Line1[1].y = myr.top + 563*SmallDiam/750+1;
Line1[2].y = Line1[3].y = Line1[0].y + 92*SmallDiam/750; Line1[2].y = Line1[3].y = Line1[0].y + 92*SmallDiam/750;

View file

@ -2,7 +2,7 @@
#define __WIN32K_PAINT_H #define __WIN32K_PAINT_H
BOOL STDCALL FillSolid (PSURFOBJ Surface, PRECTL Dimensions, ULONG iColor); 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_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, INT OrigX, INT OrigY); 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 */

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 #undef WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
@ -24,10 +24,12 @@
#include <win32k/fillshap.h> #include <win32k/fillshap.h>
#include <win32k/dc.h> #include <win32k/dc.h>
#include <win32k/pen.h> #include <win32k/pen.h>
#include <include/error.h>
#include <include/object.h> #include <include/object.h>
#include <include/inteng.h> #include <include/inteng.h>
#include <include/path.h> #include <include/path.h>
#include <include/paint.h> #include <include/paint.h>
#include <internal/safe.h>
#define NDEBUG #define NDEBUG
#include <win32k/debug1.h> #include <win32k/debug1.h>
@ -85,9 +87,7 @@ extern BOOL FillPolygon_ALTERNATE(SURFOBJ *SurfObj,
MIX RopMode, MIX RopMode,
CONST PPOINT Points, CONST PPOINT Points,
int Count, int Count,
RECTL BoundRect, RECTL BoundRect);
int OrigX,
int OrigY);
//WINDING Selects winding mode (fills any region with a nonzero winding value). //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, PBRUSHOBJ BrushObj,MIX RopMode,
CONST PPOINT Points, CONST PPOINT Points,
int Count, int Count,
RECTL BoundRect, RECTL BoundRect);
int OrigX,
int OrigY);
#endif #endif
//This implementation is blatantly ripped off from W32kRectangle //This implementation is blatantly ripped off from W32kRectangle
BOOL BOOL
STDCALL STDCALL
W32kPolygon(HDC hDC, W32kPolygon(HDC hDC,
CONST PPOINT Points, CONST PPOINT UnsafePoints,
int Count) int Count)
{ {
DC *dc = DC_HandleToPtr(hDC); DC *dc = DC_HandleToPtr(hDC);
SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface); SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
PBRUSHOBJ OutBrushObj, FillBrushObj; PBRUSHOBJ OutBrushObj, FillBrushObj;
BOOL ret; BOOL ret;
PRECTL RectBounds; PRECTL RectBounds;
PENOBJ *pen; PENOBJ *pen;
RECTL DestRect; RECTL DestRect;
int CurrentPoint; int CurrentPoint;
PPOINT Points;
NTSTATUS Status;
DPRINT("In W32kPolygon()\n"); DPRINT("In W32kPolygon()\n");
if(0 == dc) if (NULL == dc || NULL == Points || Count < 2)
return FALSE; {
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
if(0 == Points) /* Copy points from userspace to kernelspace */
return FALSE; 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) /* Convert to screen coordinates */
return FALSE; 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); RectBounds = GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
//ei not yet implemented ASSERT(RectBounds); //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); ret = PATH_Polygon(hDC, Points, Count);
} }
else else
{ {
//Get the current pen. /* Get the current pen. */
pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC); pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
ASSERT(pen); ASSERT(pen);
OutBrushObj = (PBRUSHOBJ)PenToBrushObj(dc, pen); OutBrushObj = (PBRUSHOBJ) PenToBrushObj(dc, pen);
GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC ); 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
//Now fill the polygon with the current brush. DestRect.left = Points[0].x;
FillBrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC); DestRect.right = Points[0].x;
// determine the fill mode to fill the polygon. DestRect.top = Points[0].y;
if (dc->w.polyFillMode == WINDING) DestRect.bottom = Points[0].y;
ret = FillPolygon_WINDING(SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect, dc->w.DCOrgX, dc->w.DCOrgY);
else//default for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint)
ret = FillPolygon_ALTERNATE(SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect, dc->w.DCOrgX, dc->w.DCOrgY); {
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 // Draw the Polygon Edges with the current pen
for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint) for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint)
{ {
POINT To,From; POINT To, From, Next;
//Let CurrentPoint be i
//if i+1 > Count, Draw a line from Points[i] to Points[0] /* Let CurrentPoint be i
//Draw a line from Points[i] to Points[i+1] * if i+1 > Count, Draw a line from Points[i] to Points[0]
if (CurrentPoint + 1 >= Count) * 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]; Next = Points[CurrentPoint + 2 - Count];
From = Points[0];
} }
else else
{ {
From = Points[CurrentPoint]; Next = Points[CurrentPoint + 2];
To = Points[CurrentPoint + 1];
} }
DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y ); if (From.x == To.x &&
ret = EngLineTo(SurfObj, From.y <= To.y &&
NULL, // ClipObj, To.y == Next.y &&
OutBrushObj, Next.x <= To.x)
From.x + dc->w.DCOrgX, {
From.y + dc->w.DCOrgY, To.y++;
To.x + dc->w.DCOrgX, }
To.y + dc->w.DCOrgY, else if (From.y == To.y &&
RectBounds, // Bounding rectangle From.x <= To.x &&
dc->w.ROPmode); // MIX 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 ); GDIOBJ_UnlockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
}// else }
GDIOBJ_UnlockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC); GDIOBJ_UnlockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
DC_ReleasePtr( hDC ); DC_ReleasePtr(hDC);
ExFreePool(Points);
return ret; return ret;
} }

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * 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 ** This method fills the portion of the polygon that intersects with the scanline
** 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; BOOL OnOdd = TRUE;
RECTL BoundRect; RECTL BoundRect;
int XInterceptOdd,XInterceptEven,ret; int XInterceptOdd,XInterceptEven,ret;
PPFILL_EDGE pThis = ActiveEdges; PPFILL_EDGE pThis = ActiveEdges;
while (0 != pThis) while (NULL != pThis)
{ {
if (OnOdd) if (OnOdd)
{ {
XInterceptOdd = pThis->XIntercept; XInterceptOdd = pThis->XIntercept;
OnOdd = FALSE; OnOdd = FALSE;
} }
else else
{ {
BoundRect.top = ScanLine + OrigY - 1; BoundRect.top = ScanLine - 1;
BoundRect.bottom = ScanLine + OrigY + 1; BoundRect.bottom = ScanLine + 1;
BoundRect.left = XInterceptOdd + OrigX - 2; BoundRect.left = XInterceptOdd - 2;
BoundRect.right = XInterceptEven + OrigX; BoundRect.right = XInterceptEven;
XInterceptEven = pThis->XIntercept; XInterceptEven = pThis->XIntercept;
DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1,ScanLine ,XInterceptEven - 1,ScanLine ); DPRINT("Fill Line (%d, %d) to (%d, %d)\n",XInterceptOdd - 1, ScanLine, XInterceptEven - 1, ScanLine);
ret = EngLineTo(SurfObj, ret = EngLineTo(SurfObj,
NULL, // ClipObj, NULL, /* ClipObj */
BrushObj, BrushObj,
XInterceptOdd + OrigX - 1, XInterceptOdd - 1,
ScanLine + OrigY, ScanLine,
XInterceptEven + OrigX - 1, XInterceptEven - 1,
ScanLine + OrigY, ScanLine,
&BoundRect, // Bounding rectangle &BoundRect, /* Bounding rectangle */
RopMode); // MIX RopMode); /* MIX */
OnOdd = TRUE; OnOdd = TRUE;
} }
pThis = pThis->pNext; 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 //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 //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. //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 list = 0;
PFILL_EDGE_LIST ActiveEdges = 0; PFILL_EDGE_LIST ActiveEdges = 0;
int ScanLine; int ScanLine;
DPRINT("FillPolygon_ALTERNATE\n");
DPRINT("FillPolygon_ALTERNATE\n");
//Create Edge List. /* Create Edge List. */
list = POLYGONFILL_MakeEdgeList(Points, Count); list = POLYGONFILL_MakeEdgeList(Points, Count);
//DEBUG_PRINT_EDGELIST(list); /* DEBUG_PRINT_EDGELIST(list); */
if (0 == list) return FALSE; if (NULL == list)
{
return FALSE;
}
//For each Scanline from BoundRect.bottom to BoundRect.top, /* For each Scanline from BoundRect.bottom to BoundRect.top,
//determine line segments to draw * determine line segments to draw
for (ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom ; ++ScanLine) */
{ for (ScanLine = BoundRect.top + 1; ScanLine < BoundRect.bottom ; ++ScanLine)
POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges); {
//DEBUG_PRINT_EDGELIST(ActiveEdges); POLYGONFILL_UpdateActiveEdges(ScanLine, &list, &ActiveEdges);
POLYGONFILL_FillScanLine(ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode, OrigX, OrigY); /* DEBUG_PRINT_EDGELIST(ActiveEdges); */
} POLYGONFILL_FillScanLine(ScanLine, ActiveEdges, SurfObj, BrushObj, RopMode);
}
//Free Edge List. If any are left. /* Free Edge List. If any are left. */
POLYGONFILL_DestroyEdgeList(list); POLYGONFILL_DestroyEdgeList(list);
return TRUE; return TRUE;
} }
//WINDING Selects winding mode (fills any region with a nonzero winding value). //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. //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. //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. //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"); DPRINT("FillPolygon_WINDING\n");
return FALSE;
return FALSE;
} }
/* EOF */ /* EOF */