📄 fillshap.c
字号:
}
}
else
{
for (i = 0; i < deltax; i++)
{
SETPOINT(x, y, Type);
x = x + xchange;
error = error + deltay;
if (deltax <= error)
{
y = y + ychange;
error = error - deltax;
}
}
}
}
}
STATIC int
CDECL
CompareShapePoints(const void *pv1, const void *pv2)
{
if (((const PSHAPEPOINT) pv1)->Y < ((const PSHAPEPOINT) pv2)->Y)
{
return -1;
}
else if (((const PSHAPEPOINT) pv2)->Y < ((const PSHAPEPOINT) pv1)->Y)
{
return +1;
}
else if (((const PSHAPEPOINT) pv1)->X < ((const PSHAPEPOINT) pv2)->X)
{
return -1;
}
else if (((const PSHAPEPOINT) pv2)->X < ((const PSHAPEPOINT) pv1)->X)
{
return +1;
}
else
{
return 0;
}
}
#endif
BOOL
STDCALL
NtGdiPie(HDC hDC,
int Left,
int Top,
int Right,
int Bottom,
int XRadialStart,
int YRadialStart,
int XRadialEnd,
int YRadialEnd)
{
#ifdef TODO
PDC dc;
RECTL RectBounds;
SURFOBJ *SurfObj;
BRUSHOBJ PenBrushObj;
PBRUSHOBJ FillBrushObj;
PSHAPEPOINT ShapePoints;
UINT Point, PointCount;
BOOL ret = TRUE;
int Y, CircleStart, CircleEnd, LineStart, LineEnd;
BOOL FullFill;
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_HANDLE);
return FALSE;
}
if (dc->IsIC)
{
DC_UnlockDc(dc);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
FillBrushObj = BRUSHOBJ_LockBrush(dc->Dc_Attr.hbrush);
if (NULL == FillBrushObj)
{
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INTERNAL_ERROR);
return FALSE;
}
Left += dc->w.DCOrgX;
Right += dc->w.DCOrgX;
Top += dc->w.DCOrgY;
Bottom += dc->w.DCOrgY;
XRadialStart += dc->w.DCOrgX;
YRadialStart += dc->w.DCOrgY;
XRadialEnd += dc->w.DCOrgX;
YRadialEnd += dc->w.DCOrgY;
RectBounds.left = Left;
RectBounds.right = Right;
RectBounds.top = Top;
RectBounds.bottom = Bottom;
SurfObj = (SURFOBJ*) AccessUserObject((ULONG)dc->Surface);
HPenToBrushObj(&PenBrushObj, dc->Dc_Attr.hpen);
/* Number of points for the circle is 4 * sqrt(2) * Radius, start
and end line have at most Radius points, so allocate at least
that much */
ShapePoints = ExAllocatePoolWithTag(PagedPool, 8 * (Right - Left + 1) / 2 * sizeof(SHAPEPOINT), TAG_SHAPE);
if (NULL == ShapePoints)
{
BRUSHOBJ_UnlockBrush(FillBrushObj);
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
if (Left == Right)
{
PUTPIXEL(Left, Top, &PenBrushObj);
BRUSHOBJ_UnlockBrush(FillBrushObj);
DC_UnlockDc(dc);
return ret;
}
PointCount = 0;
CirclePoints(&PointCount, ShapePoints, Left, Top, Right, Bottom);
LinePoints(&PointCount, ShapePoints, Left, Top, Right, Bottom,
XRadialStart, YRadialStart, TRUE);
LinePoints(&PointCount, ShapePoints, Left, Top, Right, Bottom,
XRadialEnd, YRadialEnd, FALSE);
ASSERT(PointCount <= 8 * (Right - Left + 1) / 2);
EngSort((PBYTE) ShapePoints, sizeof(SHAPEPOINT), PointCount, CompareShapePoints);
FullFill = TRUE;
Point = 0;
while (Point < PointCount)
{
Y = ShapePoints[Point].Y;
/* Skip any line pixels before circle */
while (Point < PointCount && ShapePoints[Point].Y == Y
&& SHAPEPOINT_TYPE_CIRCLE != ShapePoints[Point].Type)
{
Point++;
}
/* Handle left side of circle */
if (Point < PointCount && ShapePoints[Point].Y == Y)
{
CircleStart = ShapePoints[Point].X;
Point++;
while (Point < PointCount && ShapePoints[Point].Y == Y
&& ShapePoints[Point].X == ShapePoints[Point - 1].X + 1
&& SHAPEPOINT_TYPE_CIRCLE == ShapePoints[Point].Type)
{
Point++;
}
CircleEnd = ShapePoints[Point - 1].X;
PUTLINE(CircleStart, Y, CircleEnd + 1, Y, &PenBrushObj);
}
/* Handle line(s) (max 2) inside the circle */
while (Point < PointCount && ShapePoints[Point].Y == Y
&& SHAPEPOINT_TYPE_CIRCLE != ShapePoints[Point].Type)
{
LineStart = ShapePoints[Point].X;
Point++;
while (Point < PointCount && ShapePoints[Point].Y == Y
&& ShapePoints[Point].X == ShapePoints[Point - 1].X + 1
&& ShapePoints[Point].Type == ShapePoints[Point - 1].Type)
{
Point++;
}
LineEnd = ShapePoints[Point - 1].X;
PUTLINE(LineStart, Y, LineEnd + 1, Y, &PenBrushObj);
}
/* Handle right side of circle */
while (Point < PointCount && ShapePoints[Point].Y == Y
&& SHAPEPOINT_TYPE_CIRCLE == ShapePoints[Point].Type)
{
CircleStart = ShapePoints[Point].X;
Point++;
while (Point < PointCount && ShapePoints[Point].Y == Y
&& ShapePoints[Point].X == ShapePoints[Point - 1].X + 1
&& SHAPEPOINT_TYPE_CIRCLE == ShapePoints[Point].Type)
{
Point++;
}
CircleEnd = ShapePoints[Point - 1].X;
PUTLINE(CircleStart, Y, CircleEnd + 1, Y, &PenBrushObj);
}
/* Skip any line pixels after circle */
while (Point < PointCount && ShapePoints[Point].Y == Y)
{
Point++;
}
}
ExFreePool(ShapePoints);
BRUSHOBJ_UnlockBrush(FillBrushObj);
DC_UnlockDc(dc);
return ret;
#else
return TRUE;
#endif
}
#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.
//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.
extern BOOL FillPolygon(PDC dc,
SURFOBJ *SurfObj,
PBRUSHOBJ BrushObj,
MIX RopMode,
CONST PPOINT Points,
int Count,
RECTL BoundRect);
#endif
BOOL
STDCALL
NtGdiPolygon(HDC hDC,
CONST PPOINT UnsafePoints,
int Count)
{
DC *dc;
LPPOINT Safept;
NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret = FALSE;
if ( Count < 2 )
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
_SEH_TRY
{
ProbeForRead(UnsafePoints,
Count * sizeof(POINT),
1);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
}
dc = DC_LockDc(hDC);
if(!dc)
SetLastWin32Error(ERROR_INVALID_HANDLE);
else
{
if (dc->IsIC)
{
DC_UnlockDc(dc);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
Safept = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * Count, TAG_SHAPE);
if(!Safept)
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
else
{
_SEH_TRY
{
/* pointer was already probed! */
RtlCopyMemory(Safept,
UnsafePoints,
Count * sizeof(POINT));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
SetLastNtError(Status);
else
Ret = IntGdiPolygon(dc, Safept, Count);
ExFreePool(Safept);
}
DC_UnlockDc(dc);
}
return Ret;
}
BOOL
STDCALL
NtGdiPolyPolygon(HDC hDC,
CONST LPPOINT Points,
CONST LPINT PolyCounts,
int Count)
{
DC *dc;
LPPOINT Safept;
LPINT SafePolyPoints;
NTSTATUS Status = STATUS_SUCCESS;
BOOL Ret;
dc = DC_LockDc(hDC);
if(!dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
if (dc->IsIC)
{
DC_UnlockDc(dc);
/* Yes, Windows really returns TRUE in this case */
return TRUE;
}
if(Count > 0)
{
_SEH_TRY
{
ProbeForRead(Points,
Count * sizeof(POINT),
1);
ProbeForRead(PolyCounts,
Count * sizeof(INT),
1);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status))
{
DC_UnlockDc(dc);
SetLastNtError(Status);
return FALSE;
}
Safept = ExAllocatePoolWithTag(PagedPool, (sizeof(POINT) + sizeof(INT)) * Count, TAG_SHAPE);
if(!Safept)
{
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
SafePolyPoints = (LPINT)&Safept[Count];
_SEH_TRY
{
/* pointers already probed! */
RtlCopyMemory(Safept,
Points,
Count * sizeof(POINT));
RtlCopyMemory(SafePolyPoints,
PolyCounts,
Count * sizeof(INT));
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
DC_UnlockDc(dc);
ExFreePool(Safept);
SetLastNtError(Status);
return FALSE;
}
}
else
{
DC_UnlockDc(dc);
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
Ret = IntGdiPolyPolygon(dc, Safept, SafePolyPoints, Count);
ExFreePool(Safept);
DC_UnlockDc(dc);
return Ret;
}
ULONG_PTR
STDCALL
NtGdiPolyPolyDraw( IN HDC hdc,
IN PPOINT ppt,
IN PULONG pcpt,
IN ULONG ccpt,
IN INT iFunc )
{
return (ULONG_PTR) 0;
}
BOOL
FASTCALL
IntRectangle(PDC dc,
int LeftRect,
int TopRect,
int RightRect,
int BottomRect)
{
BITMAPOBJ *BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
PGDIBRUSHOBJ PenBrushObj, FillBrushObj;
GDIBRUSHINST PenBrushInst, FillBrushInst;
BOOL ret = FALSE; // default to failure
RECTL DestRect;
MIX Mix;
ASSERT ( dc ); // caller's responsibility to set this up
/* FIXME - BitmapObj can be NULL!!! Don't assert but handle this case gracefully! */
ASSERT ( BitmapObj );
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;
DestRect.left = LeftRect;
DestRect.right = RightRect;
DestRect.top = TopRect;
DestRect.bottom = BottomRect;
FillBrushObj = BRUSHOBJ_LockBrush(dc->Dc_Attr.hbrush);
if ( FillBrushObj )
{
if (!(FillBrushObj->flAttrs & GDIBRUSH_IS_NULL))
{
IntGdiInitBrushInstance(&FillBrushInst, FillBrushObj, dc->XlateBrush);
ret = IntEngBitBlt(&BitmapObj->SurfObj,
NULL,
NULL,
dc->CombinedClip,
NULL,
&DestRect,
NULL,
NULL,
&FillBrushInst.BrushObject,
NULL,
ROP3_TO_ROP4(PATCOPY));
}
}
BRUSHOBJ_UnlockBrush(FillBrushObj);
/* get BRUSHOBJ from current pen. */
PenBrushObj = PENOBJ_LockPen(dc->Dc_Attr.hpen);
if (PenBrushObj == NULL)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
BITMAPOBJ_UnlockBitmap(BitmapObj);
return FALSE;
}
IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
// Draw the rectangle with the current pen
ret = TRUE; // change default to success
if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
{
Mix = ROP2_TO_MIX(dc->Dc_Attr.jROP2);
ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
dc->CombinedClip,
&PenBrushInst.BrushObject,
LeftRect, TopRect, RightRect, TopRect,
&DestRect, // Bounding rectangle
Mix);
ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
dc->CombinedClip,
&PenBrushInst.BrushObject,
RightRect, TopRect, RightRect, BottomRect,
&DestRect, // Bounding rectangle
Mix);
ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
dc->CombinedClip,
&PenBrushInst.BrushObject,
RightRect, BottomRect, LeftRect, BottomRect,
&DestRect, // Bounding rectangle
Mix);
ret = ret && IntEngLineTo(&BitmapObj->SurfObj,
dc->CombinedClip,
&PenBrushInst.BrushObject,
LeftRect, BottomRect, LeftRect, TopRect,
&DestRect, // Bounding rectangle
Mix);
}
PENOBJ_UnlockPen(PenBrushObj);
}
BITMAPOBJ_UnlockBitmap(BitmapObj);
/* Move current position in DC?
MSDN: The current position is neither used nor updated by Rectangle. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -