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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 // Some code from the WINE project source (www.winehq.com)
27 // Should use Fx in Point
30 IntGdiMoveToEx(DC
*dc
,
37 PDC_ATTR pdcattr
= dc
->pdcattr
;
40 if ( pdcattr
->ulDirty_
& DIRTY_PTLCURRENT
) // Double hit!
42 Point
->x
= pdcattr
->ptfxCurrent
.x
; // ret prev before change.
43 Point
->y
= pdcattr
->ptfxCurrent
.y
;
44 IntDPtoLP ( dc
, Point
, 1); // reconvert back.
48 Point
->x
= pdcattr
->ptlCurrent
.x
;
49 Point
->y
= pdcattr
->ptlCurrent
.y
;
52 pdcattr
->ptlCurrent
.x
= X
;
53 pdcattr
->ptlCurrent
.y
= Y
;
54 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
55 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
56 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
58 if (BypassPath
) return TRUE
;
60 PathIsOpen
= PATH_IsPathOpen(dc
->dclevel
);
63 return PATH_MoveTo ( dc
);
68 // Should use Fx in pt
71 IntGetCurrentPositionEx(PDC dc
, LPPOINT pt
)
73 PDC_ATTR pdcattr
= dc
->pdcattr
;
77 if (pdcattr
->ulDirty_
& DIRTY_PTFXCURRENT
)
79 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
80 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
81 pdcattr
->ulDirty_
&= ~(DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
83 pt
->x
= pdcattr
->ptlCurrent
.x
;
84 pt
->y
= pdcattr
->ptlCurrent
.y
;
98 PDC_ATTR pdcattr
= dc
->pdcattr
;
100 if (PATH_IsPathOpen(dc
->dclevel
))
102 Ret
= PATH_LineTo(dc
, XEnd
, YEnd
);
105 // FIXME - PATH_LineTo should maybe do this? No
106 pdcattr
->ptlCurrent
.x
= XEnd
;
107 pdcattr
->ptlCurrent
.y
= YEnd
;
108 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
109 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
110 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
116 psurf
= dc
->dclevel
.pSurface
;
119 SetLastWin32Error(ERROR_INVALID_HANDLE
);
123 Points
[0].x
= pdcattr
->ptlCurrent
.x
;
124 Points
[0].y
= pdcattr
->ptlCurrent
.y
;
128 IntLPtoDP(dc
, Points
, 2);
130 /* The DCOrg is in device coordinates */
131 Points
[0].x
+= dc
->ptlDCOrig
.x
;
132 Points
[0].y
+= dc
->ptlDCOrig
.y
;
133 Points
[1].x
+= dc
->ptlDCOrig
.x
;
134 Points
[1].y
+= dc
->ptlDCOrig
.y
;
136 Bounds
.left
= min(Points
[0].x
, Points
[1].x
);
137 Bounds
.top
= min(Points
[0].y
, Points
[1].y
);
138 Bounds
.right
= max(Points
[0].x
, Points
[1].x
);
139 Bounds
.bottom
= max(Points
[0].y
, Points
[1].y
);
141 /* get BRUSH from current pen. */
142 pbrLine
= dc
->dclevel
.pbrLine
;
145 if (!(pbrLine
->flAttrs
& GDIBRUSH_IS_NULL
))
147 Ret
= IntEngLineTo(&psurf
->SurfObj
,
148 dc
->rosdc
.CombinedClip
,
149 &dc
->eboLine
.BrushObject
,
150 Points
[0].x
, Points
[0].y
,
151 Points
[1].x
, Points
[1].y
,
153 ROP2_TO_MIX(pdcattr
->jROP2
));
160 pdcattr
->ptlCurrent
.x
= XEnd
;
161 pdcattr
->ptlCurrent
.y
= YEnd
;
162 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
163 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
164 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
171 IntGdiPolyBezier(DC
*dc
,
175 BOOL ret
= FALSE
; // default to FAILURE
177 if ( PATH_IsPathOpen(dc
->dclevel
) )
179 return PATH_PolyBezier ( dc
, pt
, Count
);
182 /* We'll convert it into line segments and draw them using Polyline */
187 Pts
= GDI_Bezier ( pt
, Count
, &nOut
);
190 ret
= IntGdiPolyline(dc
, Pts
, nOut
);
191 ExFreePoolWithTag(Pts
, TAG_BEZIER
);
199 IntGdiPolyBezierTo(DC
*dc
,
203 BOOL ret
= FALSE
; // default to failure
204 PDC_ATTR pdcattr
= dc
->pdcattr
;
206 if ( PATH_IsPathOpen(dc
->dclevel
) )
207 ret
= PATH_PolyBezierTo ( dc
, pt
, Count
);
208 else /* We'll do it using PolyBezier */
211 npt
= ExAllocatePoolWithTag(PagedPool
,
212 sizeof(POINT
) * (Count
+ 1),
216 npt
[0].x
= pdcattr
->ptlCurrent
.x
;
217 npt
[0].y
= pdcattr
->ptlCurrent
.y
;
218 memcpy(npt
+ 1, pt
, sizeof(POINT
) * Count
);
219 ret
= IntGdiPolyBezier(dc
, npt
, Count
+1);
220 ExFreePoolWithTag(npt
, TAG_BEZIER
);
225 pdcattr
->ptlCurrent
.x
= pt
[Count
-1].x
;
226 pdcattr
->ptlCurrent
.y
= pt
[Count
-1].y
;
227 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
228 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
229 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
236 IntGdiPolyline(DC
*dc
,
245 PDC_ATTR pdcattr
= dc
->pdcattr
;
247 if (PATH_IsPathOpen(dc
->dclevel
))
248 return PATH_Polyline(dc
, pt
, Count
);
250 DC_vPrepareDCsForBlit(dc
, dc
->rosdc
.CombinedClip
->rclBounds
,
251 NULL
, dc
->rosdc
.CombinedClip
->rclBounds
);
253 if (pdcattr
->ulDirty_
& (DIRTY_FILL
| DC_BRUSH_DIRTY
))
254 DC_vUpdateFillBrush(dc
);
256 if (pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
257 DC_vUpdateLineBrush(dc
);
259 /* Get BRUSHOBJ from current pen. */
260 pbrLine
= dc
->dclevel
.pbrLine
;
263 if (!(pbrLine
->flAttrs
& GDIBRUSH_IS_NULL
))
265 Points
= EngAllocMem(0, Count
* sizeof(POINT
), TAG_COORD
);
268 psurf
= dc
->dclevel
.pSurface
;
269 /* FIXME - psurf can be NULL!!!!
270 Don't assert but handle this case gracefully! */
273 RtlCopyMemory(Points
, pt
, Count
* sizeof(POINT
));
274 IntLPtoDP(dc
, Points
, Count
);
276 /* Offset the array of points by the DC origin */
277 for (i
= 0; i
< Count
; i
++)
279 Points
[i
].x
+= dc
->ptlDCOrig
.x
;
280 Points
[i
].y
+= dc
->ptlDCOrig
.y
;
283 Ret
= IntEngPolyline(&psurf
->SurfObj
,
284 dc
->rosdc
.CombinedClip
,
285 &dc
->eboLine
.BrushObject
,
288 ROP2_TO_MIX(pdcattr
->jROP2
));
298 DC_vFinishBlit(dc
, NULL
);
304 IntGdiPolylineTo(DC
*dc
,
308 BOOL ret
= FALSE
; // default to failure
309 PDC_ATTR pdcattr
= dc
->pdcattr
;
311 if (PATH_IsPathOpen(dc
->dclevel
))
313 ret
= PATH_PolylineTo(dc
, pt
, Count
);
315 else /* do it using Polyline */
317 POINT
*pts
= ExAllocatePoolWithTag(PagedPool
,
318 sizeof(POINT
) * (Count
+ 1),
322 pts
[0].x
= pdcattr
->ptlCurrent
.x
;
323 pts
[0].y
= pdcattr
->ptlCurrent
.y
;
324 memcpy( pts
+ 1, pt
, sizeof(POINT
) * Count
);
325 ret
= IntGdiPolyline(dc
, pts
, Count
+ 1);
326 ExFreePoolWithTag(pts
, TAG_SHAPE
);
331 pdcattr
->ptlCurrent
.x
= pt
[Count
-1].x
;
332 pdcattr
->ptlCurrent
.y
= pt
[Count
-1].y
;
333 pdcattr
->ptfxCurrent
= pdcattr
->ptlCurrent
;
334 CoordLPtoDP(dc
, &pdcattr
->ptfxCurrent
); // Update fx
335 pdcattr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
343 IntGdiPolyPolyline(DC
*dc
,
351 BOOL ret
= FALSE
; // default to failure
355 if (PATH_IsPathOpen(dc
->dclevel
))
356 return PATH_PolyPolyline( dc
, pt
, PolyPoints
, Count
);
358 for (i
= 0; i
< Count
; i
++)
360 ret
= IntGdiPolyline ( dc
, pts
, *pc
);
371 /******************************************************************************/
386 SetLastWin32Error(ERROR_INVALID_HANDLE
);
389 if (dc
->dctype
== DC_TYPE_INFO
)
392 /* Yes, Windows really returns TRUE in this case */
396 rcLockRect
.left
= dc
->pdcattr
->ptlCurrent
.x
;
397 rcLockRect
.top
= dc
->pdcattr
->ptlCurrent
.y
;
398 rcLockRect
.right
= XEnd
;
399 rcLockRect
.bottom
= YEnd
;
401 IntLPtoDP(dc
, &rcLockRect
, 2);
403 /* The DCOrg is in device coordinates */
404 rcLockRect
.left
+= dc
->ptlDCOrig
.x
;
405 rcLockRect
.top
+= dc
->ptlDCOrig
.y
;
406 rcLockRect
.right
+= dc
->ptlDCOrig
.x
;
407 rcLockRect
.bottom
+= dc
->ptlDCOrig
.y
;
409 DC_vPrepareDCsForBlit(dc
, rcLockRect
, NULL
, rcLockRect
);
411 if (dc
->pdcattr
->ulDirty_
& (DIRTY_LINE
| DC_PEN_DIRTY
))
412 DC_vUpdateLineBrush(dc
);
414 Ret
= IntGdiLineTo(dc
, XEnd
, YEnd
);
416 DC_vFinishBlit(dc
, NULL
);
438 if (!dc
) return FALSE
;
439 pdcattr
= dc
->pdcattr
;
443 ProbeArrayForRead(lppt
, sizeof(POINT
), cCount
, sizeof(LONG
));
444 ProbeArrayForRead(lpbTypes
, sizeof(BYTE
), cCount
, sizeof(BYTE
));
446 /* check for each bezierto if there are two more points */
447 for ( i
= 0; i
< cCount
; i
++ )
449 if ( lpbTypes
[i
] != PT_MOVETO
&&
450 lpbTypes
[i
] & PT_BEZIERTO
)
452 if ( cCount
< i
+3 ) _SEH2_LEAVE
;
457 /* if no moveto occurs, we will close the figure here */
458 lastmove
.x
= pdcattr
->ptlCurrent
.x
;
459 lastmove
.y
= pdcattr
->ptlCurrent
.y
;
462 for ( i
= 0; i
< cCount
; i
++ )
464 if ( lpbTypes
[i
] == PT_MOVETO
)
466 IntGdiMoveToEx( dc
, lppt
[i
].x
, lppt
[i
].y
, NULL
, FALSE
);
467 lastmove
.x
= pdcattr
->ptlCurrent
.x
;
468 lastmove
.y
= pdcattr
->ptlCurrent
.y
;
470 else if ( lpbTypes
[i
] & PT_LINETO
)
471 IntGdiLineTo( dc
, lppt
[i
].x
, lppt
[i
].y
);
472 else if ( lpbTypes
[i
] & PT_BEZIERTO
)
475 pts
[0].x
= pdcattr
->ptlCurrent
.x
;
476 pts
[0].y
= pdcattr
->ptlCurrent
.y
;
477 RtlCopyMemory(pts
+ 1, &lppt
[i
], sizeof(POINT
) * 3);
478 IntGdiPolyBezier(dc
, pts
, 4);
483 if ( lpbTypes
[i
] & PT_CLOSEFIGURE
)
485 if ( PATH_IsPathOpen(dc
->dclevel
) )
487 pPath
= PATH_LockPath( dc
->dclevel
.hPath
);
490 IntGdiCloseFigure( pPath
);
491 PATH_UnlockPath( pPath
);
494 else IntGdiLineTo( dc
, lastmove
.x
, lastmove
.y
);
500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
502 SetLastNtError(_SEH2_GetExceptionCode());
520 OUT OPTIONAL LPPOINT pptOut
)