2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 // Some code from the WINE project source (www.winehq.com)
29 IntGdiMoveToEx(DC
*dc
,
38 Point
->x
= dc
->w
.CursPosX
;
39 Point
->y
= dc
->w
.CursPosY
;
44 PathIsOpen
= PATH_IsPathOpen(dc
->w
.path
);
47 return PATH_MoveTo ( dc
);
59 PGDIBRUSHOBJ PenBrushObj
;
60 GDIBRUSHINST PenBrushInst
;
64 if (PATH_IsPathOpen(dc
->w
.path
))
66 Ret
= PATH_LineTo(dc
, XEnd
, YEnd
);
69 // FIXME - PATH_LineTo should maybe do this...
70 dc
->w
.CursPosX
= XEnd
;
71 dc
->w
.CursPosY
= YEnd
;
77 BitmapObj
= BITMAPOBJ_LockBitmap ( dc
->w
.hBitmap
);
78 if (NULL
== BitmapObj
)
80 SetLastWin32Error(ERROR_INVALID_HANDLE
);
84 Points
[0].x
= dc
->w
.CursPosX
;
85 Points
[0].y
= dc
->w
.CursPosY
;
89 IntLPtoDP(dc
, Points
, 2);
91 /* FIXME: Is it correct to do this after the transformation? */
92 Points
[0].x
+= dc
->w
.DCOrgX
;
93 Points
[0].y
+= dc
->w
.DCOrgY
;
94 Points
[1].x
+= dc
->w
.DCOrgX
;
95 Points
[1].y
+= dc
->w
.DCOrgY
;
97 Bounds
.left
= min(Points
[0].x
, Points
[1].x
);
98 Bounds
.top
= min(Points
[0].y
, Points
[1].y
);
99 Bounds
.right
= max(Points
[0].x
, Points
[1].x
);
100 Bounds
.bottom
= max(Points
[0].y
, Points
[1].y
);
102 /* get BRUSHOBJ from current pen. */
103 PenBrushObj
= PENOBJ_LockPen( dc
->w
.hPen
);
104 /* FIXME - PenBrushObj can be NULL!!!! Don't assert here! */
107 if (!(PenBrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
109 IntGdiInitBrushInstance(&PenBrushInst
, PenBrushObj
, dc
->XlatePen
);
110 Ret
= IntEngLineTo(&BitmapObj
->SurfObj
,
112 &PenBrushInst
.BrushObject
,
113 Points
[0].x
, Points
[0].y
,
114 Points
[1].x
, Points
[1].y
,
116 ROP2_TO_MIX(dc
->w
.ROPmode
));
119 BITMAPOBJ_UnlockBitmap ( BitmapObj
);
120 PENOBJ_UnlockPen( PenBrushObj
);
125 dc
->w
.CursPosX
= XEnd
;
126 dc
->w
.CursPosY
= YEnd
;
133 IntGdiPolyBezier(DC
*dc
,
137 BOOL ret
= FALSE
; // default to FAILURE
139 if ( PATH_IsPathOpen(dc
->w
.path
) )
141 return PATH_PolyBezier ( dc
, pt
, Count
);
144 /* We'll convert it into line segments and draw them using Polyline */
149 Pts
= GDI_Bezier ( pt
, Count
, &nOut
);
152 DbgPrint("Pts = %p, no = %d\n", Pts
, nOut
);
153 ret
= IntGdiPolyline(dc
, Pts
, nOut
);
162 IntGdiPolyBezierTo(DC
*dc
,
166 BOOL ret
= FALSE
; // default to failure
168 if ( PATH_IsPathOpen(dc
->w
.path
) )
169 ret
= PATH_PolyBezierTo ( dc
, pt
, Count
);
170 else /* We'll do it using PolyBezier */
173 npt
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * (Count
+ 1), TAG_BEZIER
);
176 npt
[0].x
= dc
->w
.CursPosX
;
177 npt
[0].y
= dc
->w
.CursPosY
;
178 memcpy(npt
+ 1, pt
, sizeof(POINT
) * Count
);
179 ret
= IntGdiPolyBezier(dc
, npt
, Count
+1);
185 dc
->w
.CursPosX
= pt
[Count
-1].x
;
186 dc
->w
.CursPosY
= pt
[Count
-1].y
;
193 IntGdiPolyline(DC
*dc
,
197 BITMAPOBJ
*BitmapObj
;
198 GDIBRUSHOBJ
*PenBrushObj
;
199 GDIBRUSHINST PenBrushInst
;
204 if (PATH_IsPathOpen(dc
->w
.path
))
205 return PATH_Polyline(dc
, pt
, Count
);
207 /* Get BRUSHOBJ from current pen. */
208 PenBrushObj
= PENOBJ_LockPen(dc
->w
.hPen
);
209 /* FIXME - PenBrushObj can be NULL! Don't assert here! */
212 if (!(PenBrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
214 Points
= EngAllocMem(0, Count
* sizeof(POINT
), TAG_COORD
);
217 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
218 /* FIXME - BitmapObj can be NULL!!!! Don't assert but handle this case gracefully! */
221 RtlCopyMemory(Points
, pt
, Count
* sizeof(POINT
));
222 IntLPtoDP(dc
, Points
, Count
);
224 /* Offset the array of point by the dc->w.DCOrg */
225 for (i
= 0; i
< Count
; i
++)
227 Points
[i
].x
+= dc
->w
.DCOrgX
;
228 Points
[i
].y
+= dc
->w
.DCOrgY
;
231 IntGdiInitBrushInstance(&PenBrushInst
, PenBrushObj
, dc
->XlatePen
);
232 Ret
= IntEngPolyline(&BitmapObj
->SurfObj
, dc
->CombinedClip
,
233 &PenBrushInst
.BrushObject
, Points
, Count
,
234 ROP2_TO_MIX(dc
->w
.ROPmode
));
236 BITMAPOBJ_UnlockBitmap(BitmapObj
);
245 PENOBJ_UnlockPen(PenBrushObj
);
251 IntGdiPolylineTo(DC
*dc
,
255 BOOL ret
= FALSE
; // default to failure
257 if(PATH_IsPathOpen(dc
->w
.path
))
259 ret
= PATH_PolylineTo(dc
, pt
, Count
);
261 else /* do it using Polyline */
263 POINT
*pts
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * (Count
+ 1), TAG_SHAPE
);
266 pts
[0].x
= dc
->w
.CursPosX
;
267 pts
[0].y
= dc
->w
.CursPosY
;
268 memcpy( pts
+ 1, pt
, sizeof(POINT
) * Count
);
269 ret
= IntGdiPolyline(dc
, pts
, Count
+ 1);
275 dc
->w
.CursPosX
= pt
[Count
-1].x
;
276 dc
->w
.CursPosY
= pt
[Count
-1].y
;
283 IntGdiGetArcDirection(DC
*dc
)
285 return dc
->w
.ArcDirection
;
299 if(PATH_IsPathOpen(dc
->w
.path
))
301 return PATH_Arc(dc
, LeftRect
, TopRect
, RightRect
, BottomRect
,
302 XStartArc
, YStartArc
, XEndArc
, YEndArc
);
306 // EngArc(dc, LeftRect, TopRect, RightRect, BottomRect, UNIMPLEMENTED
307 // XStartArc, YStartArc, XEndArc, YEndArc);
313 IntGdiPolyPolyline(DC
*dc
,
321 BOOL ret
= FALSE
; // default to failure
325 for (i
= 0; i
< Count
; i
++)
327 ret
= IntGdiPolyline ( dc
, pts
, *pc
);
338 /******************************************************************************/
342 NtGdiAngleArc(HDC hDC
,
368 dc
= DC_LockDc (hDC
);
371 SetLastWin32Error(ERROR_INVALID_HANDLE
);
377 /* Yes, Windows really returns TRUE in this case */
410 dc
= DC_LockDc (hDC
);
413 SetLastWin32Error(ERROR_INVALID_HANDLE
);
419 /* Yes, Windows really returns TRUE in this case */
423 // Line from current position to starting point of arc
424 if ( !IntGdiLineTo(dc
, XRadial1
, YRadial1
) )
430 //dc = DC_LockDc(hDC);
432 //if(!dc) return FALSE;
434 // Then the arc is drawn.
435 result
= IntGdiArc(dc
, LeftRect
, TopRect
, RightRect
, BottomRect
,
436 XRadial1
, YRadial1
, XRadial2
, YRadial2
);
440 // If no error occured, the current position is moved to the ending point of the arc.
442 IntGdiMoveToEx(dc
, XRadial2
, YRadial2
, NULL
);
451 NtGdiGetArcDirection(HDC hDC
)
453 PDC dc
= DC_LockDc (hDC
);
454 int ret
= 0; // default to failure
458 ret
= IntGdiGetArcDirection ( dc
);
463 SetLastWin32Error(ERROR_INVALID_HANDLE
);
481 SetLastWin32Error(ERROR_INVALID_HANDLE
);
487 /* Yes, Windows really returns TRUE in this case */
491 Ret
= IntGdiLineTo(dc
, XEnd
, YEnd
);
499 NtGdiMoveToEx(HDC hDC
,
506 NTSTATUS Status
= STATUS_SUCCESS
;
512 SetLastWin32Error(ERROR_INVALID_HANDLE
);
518 /* Yes, Windows really returns TRUE in this case */
533 Status
= _SEH_GetExceptionCode();
537 if(!NT_SUCCESS(Status
))
540 SetLastNtError(Status
);
545 Ret
= IntGdiMoveToEx(dc
, X
, Y
, (Point
? &SafePoint
: NULL
));
553 NtGdiPolyBezier(HDC hDC
,
559 NTSTATUS Status
= STATUS_SUCCESS
;
565 SetLastWin32Error(ERROR_INVALID_HANDLE
);
571 /* Yes, Windows really returns TRUE in this case */
580 Count
* sizeof(POINT
),
585 Status
= _SEH_GetExceptionCode();
589 if (!NT_SUCCESS(Status
))
592 SetLastNtError(Status
);
596 Safept
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * Count
, TAG_BEZIER
);
600 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
606 /* pointers were already probed */
607 RtlCopyMemory(Safept
,
609 Count
* sizeof(POINT
));
613 Status
= _SEH_GetExceptionCode();
617 if(!NT_SUCCESS(Status
))
620 SetLastNtError(Status
);
627 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
631 Ret
= IntGdiPolyBezier(dc
, Safept
, Count
);
641 NtGdiPolyBezierTo(HDC hDC
,
647 NTSTATUS Status
= STATUS_SUCCESS
;
653 SetLastWin32Error(ERROR_INVALID_HANDLE
);
659 /* Yes, Windows really returns TRUE in this case */
668 Count
* sizeof(POINT
),
673 Status
= _SEH_GetExceptionCode();
677 if (!NT_SUCCESS(Status
))
680 SetLastNtError(Status
);
684 Safept
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * Count
, TAG_BEZIER
);
688 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
694 /* pointers were already probed */
695 RtlCopyMemory(Safept
,
697 Count
* sizeof(POINT
));
701 Status
= _SEH_GetExceptionCode();
705 if(!NT_SUCCESS(Status
))
708 SetLastNtError(Status
);
715 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
719 Ret
= IntGdiPolyBezierTo(dc
, Safept
, Count
);
729 NtGdiPolyDraw(HDC hDC
,
740 NtGdiPolyline(HDC hDC
,
746 NTSTATUS Status
= STATUS_SUCCESS
;
752 SetLastWin32Error(ERROR_INVALID_HANDLE
);
758 /* Yes, Windows really returns TRUE in this case */
767 Count
* sizeof(POINT
),
772 Status
= _SEH_GetExceptionCode();
776 if (!NT_SUCCESS(Status
))
779 SetLastNtError(Status
);
783 Safept
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * Count
, TAG_SHAPE
);
787 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
793 /* pointers were already probed */
794 RtlCopyMemory(Safept
,
796 Count
* sizeof(POINT
));
800 Status
= _SEH_GetExceptionCode();
804 if(!NT_SUCCESS(Status
))
807 SetLastNtError(Status
);
814 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
818 Ret
= IntGdiPolyline(dc
, Safept
, Count
);
828 NtGdiPolylineTo(HDC hDC
,
834 NTSTATUS Status
= STATUS_SUCCESS
;
840 SetLastWin32Error(ERROR_INVALID_HANDLE
);
846 /* Yes, Windows really returns TRUE in this case */
855 Count
* sizeof(POINT
),
860 Status
= _SEH_GetExceptionCode();
864 if (!NT_SUCCESS(Status
))
867 SetLastNtError(Status
);
871 Safept
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * Count
, TAG_SHAPE
);
875 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
881 /* pointers were already probed */
882 RtlCopyMemory(Safept
,
884 Count
* sizeof(POINT
));
888 Status
= _SEH_GetExceptionCode();
892 if(!NT_SUCCESS(Status
))
895 SetLastNtError(Status
);
902 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
906 Ret
= IntGdiPolylineTo(dc
, Safept
, Count
);
916 NtGdiPolyPolyline(HDC hDC
,
918 CONST LPDWORD PolyPoints
,
923 LPDWORD SafePolyPoints
;
924 NTSTATUS Status
= STATUS_SUCCESS
;
930 SetLastWin32Error(ERROR_INVALID_HANDLE
);
936 /* Yes, Windows really returns TRUE in this case */
945 Count
* sizeof(POINT
),
947 ProbeForRead(PolyPoints
,
948 Count
* sizeof(DWORD
),
953 Status
= _SEH_GetExceptionCode();
957 if (!NT_SUCCESS(Status
))
960 SetLastNtError(Status
);
964 Safept
= ExAllocatePoolWithTag(PagedPool
, (sizeof(POINT
) + sizeof(DWORD
)) * Count
, TAG_SHAPE
);
968 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
972 SafePolyPoints
= (LPDWORD
)&Safept
[Count
];
976 /* pointers were already probed */
977 RtlCopyMemory(Safept
,
979 Count
* sizeof(POINT
));
980 RtlCopyMemory(SafePolyPoints
,
982 Count
* sizeof(DWORD
));
986 Status
= _SEH_GetExceptionCode();
990 if(!NT_SUCCESS(Status
))
994 SetLastNtError(Status
);
1001 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1005 Ret
= IntGdiPolyPolyline(dc
, Safept
, SafePolyPoints
, Count
);
1015 NtGdiSetArcDirection(HDC hDC
,
1019 INT nOldDirection
= 0; // default to FAILURE
1021 dc
= DC_LockDc (hDC
);
1022 if ( !dc
) return 0;
1024 if ( ArcDirection
== AD_COUNTERCLOCKWISE
|| ArcDirection
== AD_CLOCKWISE
)
1026 nOldDirection
= dc
->w
.ArcDirection
;
1027 dc
->w
.ArcDirection
= ArcDirection
;
1031 return nOldDirection
;