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)
27 // Should use Fx in Point
30 IntGdiMoveToEx(DC
*dc
,
36 PDC_ATTR pdcattr
= dc
->pdcattr
;
39 if ( pdcattr
->ulDirty_
& DIRTY_PTLCURRENT
) // Double hit!
41 Point
->x
= pdcattr
->ptfxCurrent
.x
; // ret prev before change.
42 Point
->y
= pdcattr
->ptfxCurrent
.y
;
43 IntDPtoLP ( dc
, Point
, 1); // reconvert back.
47 Point
->x
= pdcattr
->ptlCurrent
.x
;
48 Point
->y
= pdcattr
->ptlCurrent
.y
;
51 pdcattr
->ptlCurrent
.x
= X
;
52 pdcattr
->ptlCurrent
.y
= Y
;
53 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
54 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
55 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
57 PathIsOpen
= PATH_IsPathOpen(dc
->dclevel
);
60 return PATH_MoveTo ( dc
);
65 // Should use Fx in pt
68 IntGetCurrentPositionEx(PDC dc
, LPPOINT pt
)
70 PDC_ATTR pdcattr
= dc
->pdcattr
;
74 if (pdcattr
->ulDirty_
& DIRTY_PTFXCURRENT
)
76 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
77 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
78 pdcattr
->ulDirty_
&= ~(DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
80 pt
->x
= pdcattr
->ptlCurrent
.x
;
81 pt
->y
= pdcattr
->ptlCurrent
.y
;
96 PDC_ATTR pdcattr
= dc
->pdcattr
;
99 if (PATH_IsPathOpen(dc
->dclevel
))
101 Ret
= PATH_LineTo(dc
, XEnd
, YEnd
);
104 // FIXME - PATH_LineTo should maybe do this? No
105 pdcattr
->ptlCurrent
.x
= XEnd
;
106 pdcattr
->ptlCurrent
.y
= YEnd
;
107 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
108 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
109 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
115 if (pdcattr
->ulDirty_
& DC_BRUSH_DIRTY
)
116 IntGdiSelectBrush(dc
,pdcattr
->hbrush
);
118 if (pdcattr
->ulDirty_
& DC_PEN_DIRTY
)
119 IntGdiSelectPen(dc
,pdcattr
->hpen
);
121 psurf
= SURFACE_LockSurface( dc
->rosdc
.hBitmap
);
124 SetLastWin32Error(ERROR_INVALID_HANDLE
);
128 Points
[0].x
= pdcattr
->ptlCurrent
.x
;
129 Points
[0].y
= pdcattr
->ptlCurrent
.y
;
133 IntLPtoDP(dc
, Points
, 2);
135 /* The DCOrg is in device coordinates */
136 Points
[0].x
+= dc
->ptlDCOrig
.x
;
137 Points
[0].y
+= dc
->ptlDCOrig
.y
;
138 Points
[1].x
+= dc
->ptlDCOrig
.x
;
139 Points
[1].y
+= dc
->ptlDCOrig
.y
;
141 Bounds
.left
= min(Points
[0].x
, Points
[1].x
);
142 Bounds
.top
= min(Points
[0].y
, Points
[1].y
);
143 Bounds
.right
= max(Points
[0].x
, Points
[1].x
);
144 Bounds
.bottom
= max(Points
[0].y
, Points
[1].y
);
146 /* get BRUSH from current pen. */
147 pbrushLine
= PENOBJ_LockPen( pdcattr
->hpen
);
150 /* default to BLACK_PEN */
151 pbrushLine
= PENOBJ_LockPen(NtGdiGetStockObject(BLACK_PEN
));
155 if (!(pbrushLine
->flAttrs
& GDIBRUSH_IS_NULL
))
157 EBRUSHOBJ_vInit(&eboLine
, pbrushLine
, dc
->rosdc
.XlatePen
);
158 Ret
= IntEngLineTo(&psurf
->SurfObj
,
159 dc
->rosdc
.CombinedClip
,
160 &eboLine
.BrushObject
,
161 Points
[0].x
, Points
[0].y
,
162 Points
[1].x
, Points
[1].y
,
164 ROP2_TO_MIX(pdcattr
->jROP2
));
167 SURFACE_UnlockSurface(psurf
);
168 PENOBJ_UnlockPen( pbrushLine
);
173 pdcattr
->ptlCurrent
.x
= XEnd
;
174 pdcattr
->ptlCurrent
.y
= YEnd
;
175 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
176 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
177 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
184 IntGdiPolyBezier(DC
*dc
,
188 BOOL ret
= FALSE
; // default to FAILURE
190 if ( PATH_IsPathOpen(dc
->dclevel
) )
192 return PATH_PolyBezier ( dc
, pt
, Count
);
195 /* We'll convert it into line segments and draw them using Polyline */
200 Pts
= GDI_Bezier ( pt
, Count
, &nOut
);
203 ret
= IntGdiPolyline(dc
, Pts
, nOut
);
204 ExFreePoolWithTag(Pts
, TAG_BEZIER
);
212 IntGdiPolyBezierTo(DC
*dc
,
216 BOOL ret
= FALSE
; // default to failure
217 PDC_ATTR pdcattr
= dc
->pdcattr
;
219 if ( PATH_IsPathOpen(dc
->dclevel
) )
220 ret
= PATH_PolyBezierTo ( dc
, pt
, Count
);
221 else /* We'll do it using PolyBezier */
224 npt
= ExAllocatePoolWithTag(PagedPool
,
225 sizeof(POINT
) * (Count
+ 1),
229 npt
[0].x
= pdcattr
->ptlCurrent
.x
;
230 npt
[0].y
= pdcattr
->ptlCurrent
.y
;
231 memcpy(npt
+ 1, pt
, sizeof(POINT
) * Count
);
232 ret
= IntGdiPolyBezier(dc
, npt
, Count
+1);
233 ExFreePoolWithTag(npt
, TAG_BEZIER
);
238 pdcattr
->ptlCurrent
.x
= pt
[Count
-1].x
;
239 pdcattr
->ptlCurrent
.y
= pt
[Count
-1].y
;
240 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
241 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
242 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
249 IntGdiPolyline(DC
*dc
,
259 PDC_ATTR pdcattr
= dc
->pdcattr
;
261 if (PATH_IsPathOpen(dc
->dclevel
))
262 return PATH_Polyline(dc
, pt
, Count
);
264 if (pdcattr
->ulDirty_
& DC_BRUSH_DIRTY
)
265 IntGdiSelectBrush(dc
,pdcattr
->hbrush
);
267 if (pdcattr
->ulDirty_
& DC_PEN_DIRTY
)
268 IntGdiSelectPen(dc
,pdcattr
->hpen
);
270 /* Get BRUSHOBJ from current pen. */
271 pbrushLine
= PENOBJ_LockPen(pdcattr
->hpen
);
272 /* FIXME - pbrushLine can be NULL! Don't assert here! */
275 if (!(pbrushLine
->flAttrs
& GDIBRUSH_IS_NULL
))
277 Points
= EngAllocMem(0, Count
* sizeof(POINT
), TAG_COORD
);
280 psurf
= SURFACE_LockSurface(dc
->rosdc
.hBitmap
);
281 /* FIXME - psurf can be NULL!!!!
282 Don't assert but handle this case gracefully! */
285 RtlCopyMemory(Points
, pt
, Count
* sizeof(POINT
));
286 IntLPtoDP(dc
, Points
, Count
);
288 /* Offset the array of point by the dc->rosdc.DCOrg */
289 for (i
= 0; i
< Count
; i
++)
291 Points
[i
].x
+= dc
->ptlDCOrig
.x
;
292 Points
[i
].y
+= dc
->ptlDCOrig
.y
;
295 EBRUSHOBJ_vInit(&eboLine
, pbrushLine
, dc
->rosdc
.XlatePen
);
296 Ret
= IntEngPolyline(&psurf
->SurfObj
,
297 dc
->rosdc
.CombinedClip
,
298 &eboLine
.BrushObject
,
301 ROP2_TO_MIX(pdcattr
->jROP2
));
303 SURFACE_UnlockSurface(psurf
);
312 PENOBJ_UnlockPen(pbrushLine
);
318 IntGdiPolylineTo(DC
*dc
,
322 BOOL ret
= FALSE
; // default to failure
323 PDC_ATTR pdcattr
= dc
->pdcattr
;
325 if (PATH_IsPathOpen(dc
->dclevel
))
327 ret
= PATH_PolylineTo(dc
, pt
, Count
);
329 else /* do it using Polyline */
331 POINT
*pts
= ExAllocatePoolWithTag(PagedPool
,
332 sizeof(POINT
) * (Count
+ 1),
336 pts
[0].x
= pdcattr
->ptlCurrent
.x
;
337 pts
[0].y
= pdcattr
->ptlCurrent
.y
;
338 memcpy( pts
+ 1, pt
, sizeof(POINT
) * Count
);
339 ret
= IntGdiPolyline(dc
, pts
, Count
+ 1);
340 ExFreePoolWithTag(pts
, TAG_SHAPE
);
345 pdcattr
->ptlCurrent
.x
= pt
[Count
-1].x
;
346 pdcattr
->ptlCurrent
.y
= pt
[Count
-1].y
;
347 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
348 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
349 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
357 IntGdiPolyPolyline(DC
*dc
,
365 BOOL ret
= FALSE
; // default to failure
369 if (PATH_IsPathOpen(dc
->dclevel
))
370 return PATH_PolyPolyline( dc
, pt
, PolyPoints
, Count
);
372 for (i
= 0; i
< Count
; i
++)
374 ret
= IntGdiPolyline ( dc
, pts
, *pc
);
385 /******************************************************************************/
399 SetLastWin32Error(ERROR_INVALID_HANDLE
);
402 if (dc
->dctype
== DC_TYPE_INFO
)
405 /* Yes, Windows really returns TRUE in this case */
409 Ret
= IntGdiLineTo(dc
, XEnd
, YEnd
);
431 if (!dc
) return FALSE
;
432 pdcattr
= dc
->pdcattr
;
436 ProbeArrayForRead(lppt
, sizeof(POINT
), cCount
, sizeof(LONG
));
437 ProbeArrayForRead(lpbTypes
, sizeof(BYTE
), cCount
, sizeof(BYTE
));
439 /* check for each bezierto if there are two more points */
440 for ( i
= 0; i
< cCount
; i
++ )
442 if ( lpbTypes
[i
] != PT_MOVETO
&&
443 lpbTypes
[i
] & PT_BEZIERTO
)
445 if ( cCount
< i
+3 ) _SEH2_LEAVE
;
450 /* if no moveto occurs, we will close the figure here */
451 lastmove
.x
= pdcattr
->ptlCurrent
.x
;
452 lastmove
.y
= pdcattr
->ptlCurrent
.y
;
455 for ( i
= 0; i
< cCount
; i
++ )
457 if ( lpbTypes
[i
] == PT_MOVETO
)
459 IntGdiMoveToEx( dc
, lppt
[i
].x
, lppt
[i
].y
, NULL
);
460 lastmove
.x
= pdcattr
->ptlCurrent
.x
;
461 lastmove
.y
= pdcattr
->ptlCurrent
.y
;
463 else if ( lpbTypes
[i
] & PT_LINETO
)
464 IntGdiLineTo( dc
, lppt
[i
].x
, lppt
[i
].y
);
465 else if ( lpbTypes
[i
] & PT_BEZIERTO
)
468 pts
[0].x
= pdcattr
->ptlCurrent
.x
;
469 pts
[0].y
= pdcattr
->ptlCurrent
.y
;
470 RtlCopyMemory(pts
+ 1, &lppt
[i
], sizeof(POINT
) * 3);
471 IntGdiPolyBezier(dc
, pts
, 4);
476 if ( lpbTypes
[i
] & PT_CLOSEFIGURE
)
478 if ( PATH_IsPathOpen(dc
->dclevel
) )
480 pPath
= PATH_LockPath( dc
->dclevel
.hPath
);
483 IntGdiCloseFigure( pPath
);
484 PATH_UnlockPath( pPath
);
487 else IntGdiLineTo( dc
, lastmove
.x
, lastmove
.y
);
493 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
495 SetLastNtError(_SEH2_GetExceptionCode());
513 OUT OPTIONAL LPPOINT pptOut
)