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
,
512 SetLastWin32Error(ERROR_INVALID_HANDLE
);
518 /* Yes, Windows really returns TRUE in this case */
524 Status
= MmCopyFromCaller(&SafePoint
, Point
, sizeof(POINT
));
525 if(!NT_SUCCESS(Status
))
528 SetLastNtError(Status
);
533 Ret
= IntGdiMoveToEx(dc
, X
, Y
, (Point
? &SafePoint
: NULL
));
541 NtGdiPolyBezier(HDC hDC
,
553 SetLastWin32Error(ERROR_INVALID_HANDLE
);
559 /* Yes, Windows really returns TRUE in this case */
565 Safept
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * Count
, TAG_BEZIER
);
569 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
573 Status
= MmCopyFromCaller(Safept
, pt
, sizeof(POINT
) * Count
);
574 if(!NT_SUCCESS(Status
))
577 SetLastNtError(Status
);
584 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
588 Ret
= IntGdiPolyBezier(dc
, Safept
, Count
);
598 NtGdiPolyBezierTo(HDC hDC
,
610 SetLastWin32Error(ERROR_INVALID_HANDLE
);
616 /* Yes, Windows really returns TRUE in this case */
622 Safept
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * Count
, TAG_BEZIER
);
626 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
630 Status
= MmCopyFromCaller(Safept
, pt
, sizeof(POINT
) * Count
);
631 if(!NT_SUCCESS(Status
))
634 SetLastNtError(Status
);
641 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
645 Ret
= IntGdiPolyBezierTo(dc
, Safept
, Count
);
655 NtGdiPolyDraw(HDC hDC
,
666 NtGdiPolyline(HDC hDC
,
678 SetLastWin32Error(ERROR_INVALID_HANDLE
);
684 /* Yes, Windows really returns TRUE in this case */
690 Safept
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * Count
, TAG_SHAPE
);
694 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
698 Status
= MmCopyFromCaller(Safept
, pt
, sizeof(POINT
) * Count
);
699 if(!NT_SUCCESS(Status
))
702 SetLastNtError(Status
);
709 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
713 Ret
= IntGdiPolyline(dc
, Safept
, Count
);
723 NtGdiPolylineTo(HDC hDC
,
735 SetLastWin32Error(ERROR_INVALID_HANDLE
);
741 /* Yes, Windows really returns TRUE in this case */
747 Safept
= ExAllocatePoolWithTag(PagedPool
, sizeof(POINT
) * Count
, TAG_SHAPE
);
751 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
755 Status
= MmCopyFromCaller(Safept
, pt
, sizeof(POINT
) * Count
);
756 if(!NT_SUCCESS(Status
))
759 SetLastNtError(Status
);
766 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
770 Ret
= IntGdiPolylineTo(dc
, Safept
, Count
);
780 NtGdiPolyPolyline(HDC hDC
,
782 CONST LPDWORD PolyPoints
,
787 LPDWORD SafePolyPoints
;
794 SetLastWin32Error(ERROR_INVALID_HANDLE
);
800 /* Yes, Windows really returns TRUE in this case */
806 Safept
= ExAllocatePoolWithTag(PagedPool
, (sizeof(POINT
) + sizeof(DWORD
)) * Count
, TAG_SHAPE
);
810 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
814 SafePolyPoints
= (LPDWORD
)&Safept
[Count
];
816 Status
= MmCopyFromCaller(Safept
, pt
, sizeof(POINT
) * Count
);
817 if(!NT_SUCCESS(Status
))
821 SetLastNtError(Status
);
824 Status
= MmCopyFromCaller(SafePolyPoints
, PolyPoints
, sizeof(DWORD
) * Count
);
825 if(!NT_SUCCESS(Status
))
829 SetLastNtError(Status
);
836 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
840 Ret
= IntGdiPolyPolyline(dc
, Safept
, SafePolyPoints
, Count
);
850 NtGdiSetArcDirection(HDC hDC
,
854 INT nOldDirection
= 0; // default to FAILURE
856 dc
= DC_LockDc (hDC
);
859 if ( ArcDirection
== AD_COUNTERCLOCKWISE
|| ArcDirection
== AD_CLOCKWISE
)
861 nOldDirection
= dc
->w
.ArcDirection
;
862 dc
->w
.ArcDirection
= ArcDirection
;
866 return nOldDirection
;