+/*
+ * ReactOS W32 Subsystem
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id$ */
#undef WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ddk/ntddk.h>
#include <win32k/fillshap.h>
+#include <win32k/brush.h>
#include <win32k/dc.h>
#include <win32k/pen.h>
+#include <win32k/region.h>
+#include <include/error.h>
#include <include/object.h>
#include <include/inteng.h>
+#include <include/path.h>
+#include <include/paint.h>
+#include <internal/safe.h>
#define NDEBUG
#include <win32k/debug1.h>
+/*
+ * a couple macros to fill a single pixel or a line
+ */
+#define PUTPIXEL(x,y,brushObj) \
+ ret = ret && IntEngLineTo(SurfObj, \
+ dc->CombinedClip, \
+ brushObj, \
+ x, y, (x)+1, y, \
+ &RectBounds, \
+ dc->w.ROPmode);
+
+#define PUTLINE(x1,y1,x2,y2,brushObj) \
+ ret = ret && IntEngLineTo(SurfObj, \
+ dc->CombinedClip, \
+ brushObj, \
+ x1, y1, x2, y2, \
+ &RectBounds, \
+ dc->w.ROPmode);
+
BOOL
STDCALL
-W32kChord(HDC hDC,
+NtGdiChord(HDC hDC,
int LeftRect,
int TopRect,
int RightRect,
BOOL
STDCALL
-W32kEllipse(HDC hDC,
- int LeftRect,
- int TopRect,
- int RightRect,
- int BottomRect)
+NtGdiEllipse(HDC hDC,
+ int Left,
+ int Top,
+ int Right,
+ int Bottom)
{
- UNIMPLEMENTED;
+ PDC dc;
+ int X, X18, X27, X36, X45;
+ int Y, Y14, Y23, Y58, Y67;
+ int d, Radius;
+ RECTL RectBounds;
+ PSURFOBJ SurfObj;
+ BRUSHOBJ PenBrushObj;
+ PBRUSHOBJ FillBrushObj;
+ BOOL ret = TRUE;
+
+ if (Right <= Left || Bottom <= Top)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if (Right - Left != Bottom - Top)
+ {
+ UNIMPLEMENTED;
+ }
+
+ dc = DC_LockDc ( hDC );
+ if (NULL == dc)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ FillBrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
+ if (NULL == FillBrushObj)
+ {
+ DC_UnlockDc(hDC);
+ SetLastWin32Error(ERROR_INTERNAL_ERROR);
+ return FALSE;
+ }
+
+ Left += dc->w.DCOrgX;
+ Right += dc->w.DCOrgX;
+ Top += dc->w.DCOrgY;
+ Bottom += dc->w.DCOrgY;
+
+ RectBounds.left = Left;
+ RectBounds.right = Right;
+ RectBounds.top = Top;
+ RectBounds.bottom = Bottom;
+
+ SurfObj = (PSURFOBJ) AccessUserObject((ULONG)dc->Surface);
+ HPenToBrushObj(&PenBrushObj, dc->w.hPen);
+ Radius = (Right - Left) / 2;
+ X = 0;
+ Y = Radius;
+ X18 = Right;
+ X27 = (Left + Right) / 2;
+ X36 = (Left + Right) / 2;
+ X45 = Left;
+ Y14 = Top + Radius;
+ Y23 = Top;
+ Y58 = Top + Radius;
+ Y67 = Top + (Right - Left);
+ d = 1 - Radius;
+ PUTLINE(X45 + 1, Y14, X18, Y58, FillBrushObj);
+ PUTPIXEL(X27, Y23, &PenBrushObj);
+ PUTPIXEL(X45, Y14, &PenBrushObj);
+ PUTPIXEL(X18, Y58, &PenBrushObj);
+ PUTPIXEL(X27, Y67, &PenBrushObj);
+
+ while (X < Y)
+ {
+ if (d < 0)
+ {
+ d += 2 * X + 3;
+
+ X27++;
+ X36--;
+ Y14--;
+ Y58++;
+ }
+ else
+ {
+ d += 2 * (X - Y) + 5;
+ Y--;
+
+ Y23++;
+ Y67--;
+ X18--;
+ X45++;
+ X27++;
+ X36--;
+ Y14--;
+ Y58++;
+ PUTLINE(X36 + 1, Y23, X27, Y23, FillBrushObj);
+ PUTLINE(X36 + 1, Y67, X27, Y67, FillBrushObj);
+ }
+ X++;
+
+ PUTLINE(X45 + 1, Y14, X18, Y14, FillBrushObj);
+ PUTLINE(X45 + 1, Y58, X18, Y58, FillBrushObj);
+ PUTPIXEL(X27, Y23, &PenBrushObj);
+ PUTPIXEL(X36, Y23, &PenBrushObj);
+ PUTPIXEL(X18, Y14, &PenBrushObj);
+ PUTPIXEL(X45, Y14, &PenBrushObj);
+ PUTPIXEL(X18, Y58, &PenBrushObj);
+ PUTPIXEL(X45, Y58, &PenBrushObj);
+ PUTPIXEL(X27, Y67, &PenBrushObj);
+ PUTPIXEL(X36, Y67, &PenBrushObj);
+ }
+
+ BRUSHOBJ_UnlockBrush(dc->w.hBrush);
+ DC_UnlockDc(hDC);
+
+ return TRUE;
}
BOOL
STDCALL
-W32kPie(HDC hDC,
+NtGdiPie(HDC hDC,
int LeftRect,
int TopRect,
int RightRect,
UNIMPLEMENTED;
}
-//ALTERNATE Selects alternate mode (fills the area between odd-numbered and even-numbered
-//polygon sides on each scan line).
+#if 0
+
//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.
-extern BOOL FillPolygon_ALTERNATE(SURFOBJ *SurfObj,
- PBRUSHOBJ BrushObj,
- MIX RopMode,
- CONST PPOINT Points,
- int Count,
- RECTL BoundRect,
- int OrigX,
- int OrigY);
-
//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.
+//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.
-extern BOOL FillPolygon_WINDING(SURFOBJ *SurfObj,
- PBRUSHOBJ BrushObj,MIX RopMode,
- CONST PPOINT Points,
- int Count,
- RECTL BoundRect,
- int OrigX,
- int OrigY);
-
-//This implementation is blatantly ripped off from W32kRectangle
+
+extern BOOL FillPolygon(PDC dc,
+ SURFOBJ *SurfObj,
+ PBRUSHOBJ BrushObj,
+ MIX RopMode,
+ CONST PPOINT Points,
+ int Count,
+ RECTL BoundRect);
+
+#endif
+
BOOL
-STDCALL
-W32kPolygon(HDC hDC,
- CONST PPOINT Points,
- int Count)
+FASTCALL
+IntPolygon(PDC dc,
+ 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;
-
- DPRINT("In W32kPolygon()\n");
-
- if(0 == dc)
- return FALSE;
-
- if(0 == Points)
- return FALSE;
-
- if (2 > Count)
- return FALSE;
-
- 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))
- {
- ret = PATH_Polygon(hDC, Points, Count);
- }
- else
+ SURFOBJ *SurfObj;
+ BRUSHOBJ PenBrushObj, *FillBrushObj;
+ BOOL ret = FALSE; // default to failure
+ PRECTL RectBounds;
+ RECTL DestRect;
+ int CurrentPoint;
+ PPOINT Points;
+ NTSTATUS Status;
+
+ ASSERT(dc); // caller's responsibility to pass a valid dc
+
+ if ( NULL == UnsafePoints || Count < 2 )
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
+ ASSERT(SurfObj);
+
+ /* Copy points from userspace to kernelspace */
+ Points = ExAllocatePool(PagedPool, Count * sizeof(POINT));
+ if (NULL == Points)
+ SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+ else
{
- //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)
+ Status = MmCopyFromCaller(Points, UnsafePoints, Count * sizeof(POINT));
+ if ( !NT_SUCCESS(Status) )
+ SetLastNtError(Status);
+ else
+ {
+ /* Convert to screen coordinates */
+ for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++)
+ {
+ Points[CurrentPoint].x += dc->w.DCOrgX;
+ Points[CurrentPoint].y += dc->w.DCOrgY;
+ }
+
+ RectBounds = (PRECTL) RGNDATA_LockRgn(dc->w.hGCClipRgn);
+ //ei not yet implemented ASSERT(RectBounds);
+
+ if (PATH_IsPathOpen(dc->w.path))
+ ret = PATH_Polygon(dc, Points, Count );
+ else
{
- DestRect.bottom = MAX(DestRect.bottom, Points[CurrentPoint].y + dc->w.DCOrgY);
- DestRect.top = MIN(DestRect.top, Points[CurrentPoint].y + dc->w.DCOrgY);
- DestRect.right = MAX(DestRect.right, Points[CurrentPoint].y + dc->w.DCOrgX);
- DestRect.left = MIN(DestRect.left, Points[CurrentPoint].y + dc->w.DCOrgX);
- }//for
-
- //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);
- // 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)
- {
- To = Points[CurrentPoint];
- From = Points[0];
- }
- else
- {
- From = Points[CurrentPoint];
- To = Points[CurrentPoint + 1];
- }
- 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
-
- }//for
- GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC );
- }// else
-
- GDIOBJ_UnlockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
- DC_ReleasePtr( hDC );
+ 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);
+ }
+
+#if 1
+ /* Now fill the polygon with the current brush. */
+ FillBrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
+ ASSERT(FillBrushObj);
+ if ( FillBrushObj->logbrush.lbStyle != BS_NULL )
+ ret = FillPolygon ( dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect );
+ BRUSHOBJ_UnlockBrush(dc->w.hBrush);
+#endif
+
+ /* make BRUSHOBJ from current pen. */
+ HPenToBrushObj ( &PenBrushObj, dc->w.hPen );
+
+ // Draw the Polygon Edges with the current pen ( if not a NULL pen )
+ if ( PenBrushObj.logbrush.lbStyle != BS_NULL )
+ {
+ 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];
+
+ //DPRINT("Polygon Making line from (%d,%d) to (%d,%d)\n", From.x, From.y, To.x, To.y );
+ ret = IntEngLineTo(SurfObj,
+ dc->CombinedClip,
+ &PenBrushObj,
+ From.x,
+ From.y,
+ To.x,
+ To.y,
+ &DestRect,
+ dc->w.ROPmode); /* MIX */
+ }
+ }
+#if 0
+ /* Now fill the polygon with the current brush. */
+ FillBrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
+ ASSERT(FillBrushObj);
+ if ( FillBrushObj->logbrush.lbStyle != BS_NULL )
+ ret = FillPolygon ( dc, SurfObj, FillBrushObj, dc->w.ROPmode, Points, Count, DestRect );
+ BRUSHOBJ_UnlockBrush(dc->w.hBrush);
+#endif
+ }
+
+ RGNDATA_UnlockRgn(dc->w.hGCClipRgn);
+ }
+ ExFreePool ( Points );
+ }
return ret;
}
-
+//This implementation is blatantly ripped off from NtGdiRectangle
BOOL
STDCALL
-W32kPolyPolygon(HDC hDC,
- CONST LPPOINT Points,
- CONST LPINT PolyCounts,
- int Count)
+NtGdiPolygon(HDC hDC,
+ CONST PPOINT UnsafePoints,
+ int Count)
{
- UNIMPLEMENTED;
+ DC *dc;
+ BOOL ret = FALSE; // default to failure
+
+ //DPRINT("In NtGdiPolygon()\n");
+
+ dc = DC_LockDc ( hDC );
+
+ if ( !dc )
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ else
+ {
+ ret = IntPolygon ( dc, UnsafePoints, Count );
+ DC_UnlockDc ( hDC );
+ }
+
+ return ret;
}
+
BOOL
STDCALL
-W32kRectangle(HDC hDC,
- int LeftRect,
- int TopRect,
- int RightRect,
- int BottomRect)
+NtGdiPolyPolygon(HDC hDC,
+ CONST LPPOINT Points,
+ CONST LPINT PolyCounts,
+ int Count)
+{
+ DC *dc;
+ int i;
+ LPPOINT pt;
+ LPINT pc;
+ BOOL ret = FALSE; // default to failure
+
+ dc = DC_LockDc ( hDC );
+ pt = Points;
+ pc = PolyCounts;
+ if ( !dc )
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ else
+ {
+ for (i=0;i<Count;i++)
+ {
+ ret = IntPolygon ( dc, pt, *pc );
+ if (ret == FALSE)
+ {
+ DC_UnlockDc ( hDC );
+ return ret;
+ }
+ pt+=*pc++;
+ }
+ DC_UnlockDc ( hDC );
+ }
+
+ return ret;
+}
+
+BOOL
+FASTCALL
+IntRectangle(PDC dc,
+ int LeftRect,
+ int TopRect,
+ int RightRect,
+ int BottomRect)
{
- DC *dc = DC_HandleToPtr(hDC);
- SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
- PBRUSHOBJ BrushObj;
- BOOL ret;
- PRECTL RectBounds;
- PENOBJ * pen;
- RECTL DestRect;
-
- if(!dc)
- return FALSE;
-
- RectBounds = GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
+ SURFOBJ *SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
+ BRUSHOBJ PenBrushObj, *FillBrushObj;
+ BOOL ret = FALSE; // default to failure
+ PRECTL RectBounds;
+ RECTL DestRect;
+
+ ASSERT ( dc ); // caller's responsibility to set this up
+
+ RectBounds = (PRECTL) RGNDATA_LockRgn(dc->w.hGCClipRgn);
//ei not yet implemented ASSERT(RectBounds);
- if(PATH_IsPathOpen(dc->w.path)) {
- ret = PATH_Rectangle(hDC, LeftRect, TopRect, RightRect, BottomRect);
- } else {
+ if ( PATH_IsPathOpen(dc->w.path) )
+ {
+ ret = PATH_Rectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
+ }
+ else
+ {
+ LeftRect += dc->w.DCOrgX;
+ RightRect += dc->w.DCOrgX - 1;
+ TopRect += dc->w.DCOrgY;
+ BottomRect += dc->w.DCOrgY - 1;
+
+ FillBrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
+
+ ASSERT(FillBrushObj); // FIXME - I *think* this should always happen...
+ // it would be nice to remove the following if statement if that proves to be true
+ if ( FillBrushObj )
+ {
+ if ( FillBrushObj->logbrush.lbStyle != BS_NULL )
+ {
+ DestRect.left = LeftRect;
+ DestRect.right = RightRect;
+ DestRect.top = TopRect;
+ DestRect.bottom = BottomRect;
+ ret = ret && IntEngBitBlt(SurfObj,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &DestRect,
+ NULL,
+ NULL,
+ FillBrushObj,
+ NULL,
+ PATCOPY);
+ }
+ }
+
+ BRUSHOBJ_UnlockBrush(dc->w.hBrush);
+
+ /* make BRUSHOBJ from current pen. */
+ HPenToBrushObj ( &PenBrushObj, dc->w.hPen );
+
// Draw the rectangle with the current pen
- pen = (PENOBJ*) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
- ASSERT(pen);
- BrushObj = (PBRUSHOBJ)PenToBrushObj(dc, pen);
- GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC );
-
- LeftRect += dc->w.DCOrgX;
- RightRect += dc->w.DCOrgX;
- TopRect += dc->w.DCOrgY;
- BottomRect += dc->w.DCOrgY;
-
- ret = IntEngLineTo(SurfObj,
- NULL, // ClipObj,
- BrushObj,
- LeftRect, TopRect, RightRect, TopRect,
- RectBounds, // Bounding rectangle
- dc->w.ROPmode); // MIX
-
- ret = IntEngLineTo(SurfObj,
- NULL, // ClipObj,
- BrushObj,
- RightRect, TopRect, RightRect, BottomRect,
- RectBounds, // Bounding rectangle
- dc->w.ROPmode); // MIX
-
- ret = IntEngLineTo(SurfObj,
- NULL, // ClipObj,
- BrushObj,
- LeftRect, BottomRect, RightRect, BottomRect,
- RectBounds, // Bounding rectangle
- dc->w.ROPmode); // MIX
-
- ret = IntEngLineTo(SurfObj,
- NULL, // ClipObj,
- BrushObj,
- LeftRect, TopRect, LeftRect, BottomRect,
- RectBounds, // Bounding rectangle
- dc->w.ROPmode); // MIX */
-
- // FIXME: BrushObj is obtained above; decide which one is correct
- BrushObj = (BRUSHOBJ*) GDIOBJ_LockObj(dc->w.hBrush, GO_BRUSH_MAGIC);
-
- if (BrushObj)
+
+ ret = TRUE; // change default to success
+
+ if ( PenBrushObj.logbrush.lbStyle != BS_NULL )
{
- if (BrushObj->logbrush.lbStyle != BS_NULL)
- {
- DestRect.left = LeftRect + 1;
- DestRect.right = RightRect - 1;
- DestRect.top = TopRect + 1;
- DestRect.bottom = BottomRect - 1;
- ret = EngBitBlt(SurfObj,
- NULL,
- NULL,
- NULL,
- NULL,
- &DestRect,
- NULL,
- NULL,
- BrushObj,
- NULL,
- PATCOPY);
- }
+ ret = ret && IntEngLineTo(SurfObj,
+ dc->CombinedClip,
+ &PenBrushObj,
+ LeftRect, TopRect, RightRect, TopRect,
+ RectBounds, // Bounding rectangle
+ dc->w.ROPmode); // MIX
+
+ ret = ret && IntEngLineTo(SurfObj,
+ dc->CombinedClip,
+ &PenBrushObj,
+ RightRect, TopRect, RightRect, BottomRect,
+ RectBounds, // Bounding rectangle
+ dc->w.ROPmode); // MIX
+
+ ret = ret && IntEngLineTo(SurfObj,
+ dc->CombinedClip,
+ &PenBrushObj,
+ RightRect, BottomRect, LeftRect, BottomRect,
+ RectBounds, // Bounding rectangle
+ dc->w.ROPmode); // MIX
+
+ ret = ret && IntEngLineTo(SurfObj,
+ dc->CombinedClip,
+ &PenBrushObj,
+ LeftRect, BottomRect, LeftRect, TopRect,
+ RectBounds, // Bounding rectangle
+ dc->w.ROPmode); // MIX */
}
- GDIOBJ_UnlockObj( dc->w.hBrush, GO_BRUSH_MAGIC );
}
-// FIXME: Move current position in DC?
- GDIOBJ_UnlockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
- DC_ReleasePtr( hDC );
+ // Move current position in DC?
+ // MSDN: The current position is neither used nor updated by Rectangle.
+ RGNDATA_UnlockRgn(dc->w.hGCClipRgn);
return TRUE;
}
BOOL
STDCALL
-W32kRoundRect(HDC hDC,
- int LeftRect,
- int TopRect,
- int RightRect,
- int BottomRect,
- int Width,
- int Height)
+NtGdiRectangle(HDC hDC,
+ int LeftRect,
+ int TopRect,
+ int RightRect,
+ int BottomRect)
{
- UNIMPLEMENTED;
+ DC *dc = DC_LockDc(hDC);
+ BOOL ret = FALSE; // default to failure
+
+ if ( dc )
+ {
+ ret = IntRectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
+ DC_UnlockDc ( hDC );
+ }
+
+ return ret;
+}
+
+
+BOOL
+FASTCALL
+IntRoundRect(
+ PDC dc,
+ int left,
+ int top,
+ int right,
+ int bottom,
+ int xradius,
+ int yradius)
+{
+ SURFOBJ *SurfObj;
+ BRUSHOBJ PenBrush, *PenBrushObj, *FillBrushObj;
+ RECTL RectBounds;
+ int i, col, row, width, height, x1, x1start, x2, x2start, y1, y2;
+ //float aspect_square;
+ long a_square, b_square,
+ two_a_square, two_b_square,
+ four_a_square, four_b_square,
+ d, dinc, ddec;
+ BOOL first,
+ ret = TRUE; // default to success
+
+ ASSERT ( dc ); // caller's responsibility to set this up
+
+ if ( PATH_IsPathOpen(dc->w.path) )
+ return PATH_RoundRect ( dc, left, top, right, bottom, xradius, yradius );
+
+ left += dc->w.DCOrgX;
+ right += dc->w.DCOrgX;
+ top += dc->w.DCOrgY;
+ bottom += dc->w.DCOrgY;
+
+ RectBounds.left = left;
+ RectBounds.right = right;
+ RectBounds.top = top;
+ RectBounds.bottom = bottom;
+
+ SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
+
+ FillBrushObj = BRUSHOBJ_LockBrush(dc->w.hBrush);
+ ASSERT(FillBrushObj);
+ if ( FillBrushObj->logbrush.lbStyle == BS_NULL )
+ FillBrushObj = NULL; // make null brush check simpler...
+
+ HPenToBrushObj ( &PenBrush, dc->w.hPen );
+ if ( PenBrush.logbrush.lbStyle != BS_NULL )
+ PenBrushObj = &PenBrush;
+ else
+ PenBrushObj = NULL;
+
+ right--;
+ bottom--;
+
+ width = right - left;
+ height = bottom - top;
+
+ if ( (xradius<<1) > width )
+ xradius = width >> 1;
+ if ( (yradius<<1) > height )
+ yradius = height >> 1;
+
+ b_square = yradius * yradius;
+ a_square = xradius * xradius;
+ row = yradius;
+ col = 0;
+ two_a_square = a_square << 1;
+ four_a_square = a_square << 2;
+ four_b_square = b_square << 2;
+ two_b_square = b_square << 1;
+ d = two_a_square * ((row - 1) * (row))
+ + a_square
+ + two_b_square * (1 - a_square);
+
+ x1 = left+xradius;
+ x2 = right-xradius;
+ y1 = top;
+ y2 = bottom;
+
+ x1start = x1;
+ x2start = x2;
+
+ dinc = two_b_square*3; /* two_b_square * (3 + (col << 1)); */
+ ddec = four_a_square * row;
+
+ first = TRUE;
+ for ( ;; )
+ {
+ if ( d >= 0 )
+ {
+ if ( FillBrushObj )
+ PUTLINE ( x1, y1, x2, y1, FillBrushObj );
+ if ( first )
+ {
+ if ( PenBrushObj )
+ {
+ if ( x1start > x1 )
+ {
+ PUTLINE ( x1, y1, x1start, y1, PenBrushObj );
+ PUTLINE ( x2start+1, y2, x2+1, y2, PenBrushObj );
+ }
+ else
+ {
+ PUTPIXEL ( x1, y1, PenBrushObj );
+ PUTPIXEL ( x2, y2, PenBrushObj );
+ }
+ }
+ first = FALSE;
+ }
+ else
+ {
+ if ( FillBrushObj )
+ PUTLINE ( x1, y2, x2, y2, FillBrushObj );
+ if ( PenBrushObj )
+ {
+ if ( x1start >= x1 )
+ {
+ PUTLINE ( x1, y1, x1start+1, y1, PenBrushObj );
+ PUTLINE ( x2start, y2, x2+1, y2, PenBrushObj );
+ }
+ else
+ {
+ PUTPIXEL ( x1, y1, PenBrushObj );
+ PUTPIXEL ( x2, y2, PenBrushObj );
+ }
+ }
+ }
+ if ( PenBrushObj )
+ {
+ if ( x1start > x1 )
+ {
+ PUTLINE ( x1, y2, x1start+1, y2, PenBrushObj );
+ PUTLINE ( x2start, y1, x2+1, y1, PenBrushObj );
+ }
+ else
+ {
+ PUTPIXEL ( x1, y2, PenBrushObj );
+ PUTPIXEL ( x2, y1, PenBrushObj );
+ }
+ }
+ x1start = x1-1;
+ x2start = x2+1;
+ row--, y1++, y2--, ddec -= four_a_square;
+ d -= ddec;
+ }
+
+ int potential_steps = ( a_square * row ) / b_square - col + 1;
+ while ( d < 0 && potential_steps-- )
+ {
+ d += dinc; /* two_b_square * (3 + (col << 1)); */
+ col++, x1--, x2++, dinc += four_b_square;
+ }
+
+ if ( a_square * row <= b_square * col )
+ break;
+ };
+
+ d = two_b_square * (col + 1) * col
+ + two_a_square * (row * (row - 2) + 1)
+ + (1 - two_a_square) * b_square;
+ dinc = ddec; /* four_b_square * col; */
+ ddec = two_a_square * ((row << 1) - 3);
+
+ while ( row )
+ {
+ if ( FillBrushObj )
+ {
+ PUTLINE ( x1, y1, x2, y1, FillBrushObj );
+ PUTLINE ( x1, y2, x2, y2, FillBrushObj );
+ }
+ if ( PenBrushObj )
+ {
+ PUTPIXEL ( x2, y1, PenBrushObj );
+ PUTPIXEL ( x1, y2, PenBrushObj );
+ PUTPIXEL ( x2, y2, PenBrushObj );
+ PUTPIXEL ( x1, y1, PenBrushObj );
+ }
+
+ if ( d <= 0 )
+ {
+ col++, x1--, x2++, dinc += four_b_square;
+ d += dinc; //four_b_square * col;
+ }
+
+ row--, y1++, y2--, ddec -= four_a_square;
+ d -= ddec; //two_a_square * ((row << 1) - 3);
+ }
+
+ if ( FillBrushObj )
+ {
+ PUTLINE ( left, y1, right, y1, FillBrushObj );
+ PUTLINE ( left, y2, right, y2, FillBrushObj );
+ }
+ if ( PenBrushObj )
+ {
+ if ( x1 > (left+1) )
+ {
+ PUTLINE ( left, y1, x1, y1, PenBrushObj );
+ PUTLINE ( x2+1, y1, right, y1, PenBrushObj );
+ PUTLINE ( left+1, y2, x1, y2, PenBrushObj );
+ PUTLINE ( x2+1, y2, right+1, y2, PenBrushObj );
+ }
+ else
+ {
+ PUTPIXEL ( left, y1, PenBrushObj );
+ PUTPIXEL ( right, y2, PenBrushObj );
+ }
+ }
+
+ x1 = left+xradius;
+ x2 = right-xradius;
+ y1 = top+yradius;
+ y2 = bottom-yradius;
+
+ if ( FillBrushObj )
+ {
+ for ( i = y1+1; i < y2; i++ )
+ PUTLINE ( left, i, right, i, FillBrushObj );
+ }
+
+ if ( PenBrushObj )
+ {
+ PUTLINE ( x1, top, x2, top, PenBrushObj );
+ PUTLINE ( right, y1, right, y2, PenBrushObj );
+ PUTLINE ( x2, bottom, x1, bottom, PenBrushObj );
+ PUTLINE ( left, y2, left, y1, PenBrushObj );
+ }
+
+ BRUSHOBJ_UnlockBrush(dc->w.hBrush);
+
+ return ret;
+}
+
+BOOL
+STDCALL
+NtGdiRoundRect(
+ HDC hDC,
+ int LeftRect,
+ int TopRect,
+ int RightRect,
+ int BottomRect,
+ int Width,
+ int Height)
+{
+ DC *dc = DC_LockDc(hDC);
+ BOOL ret = FALSE; /* default to failure */
+
+ DPRINT("NtGdiRoundRect(0x%x,%i,%i,%i,%i,%i,%i)\n",hDC,LeftRect,TopRect,RightRect,BottomRect,Width,Height);
+ if ( !dc )
+ {
+ DPRINT1("NtGdiRoundRect() - hDC is invalid\n");
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ }
+ else
+ {
+ ret = IntRoundRect ( dc, LeftRect, TopRect, RightRect, BottomRect, Width, Height );
+ DC_UnlockDc ( hDC );
+ }
+
+ return ret;
}
+/* EOF */