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 Dc_Attr
= dc
->pDc_Attr
;
37 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
40 if ( Dc_Attr
->ulDirty_
& DIRTY_PTLCURRENT
) // Double hit!
42 Point
->x
= Dc_Attr
->ptfxCurrent
.x
; // ret prev before change.
43 Point
->y
= Dc_Attr
->ptfxCurrent
.y
;
44 IntDPtoLP ( dc
, Point
, 1); // reconvert back.
48 Point
->x
= Dc_Attr
->ptlCurrent
.x
;
49 Point
->y
= Dc_Attr
->ptlCurrent
.y
;
52 Dc_Attr
->ptlCurrent
.x
= X
;
53 Dc_Attr
->ptlCurrent
.y
= Y
;
54 Dc_Attr
->ptfxCurrent
= Dc_Attr
->ptlCurrent
;
55 CoordLPtoDP(dc
, &Dc_Attr
->ptfxCurrent
); // Update fx
56 Dc_Attr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
58 PathIsOpen
= PATH_IsPathOpen(dc
->DcLevel
);
61 return PATH_MoveTo ( dc
);
66 // Should use Fx in pt
69 IntGetCurrentPositionEx(PDC dc
, LPPOINT pt
)
71 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
72 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
76 if (Dc_Attr
->ulDirty_
& DIRTY_PTFXCURRENT
)
78 Dc_Attr
->ptfxCurrent
= Dc_Attr
->ptlCurrent
;
79 CoordLPtoDP(dc
, &Dc_Attr
->ptfxCurrent
); // Update fx
80 Dc_Attr
->ulDirty_
&= ~(DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
82 pt
->x
= Dc_Attr
->ptlCurrent
.x
;
83 pt
->y
= Dc_Attr
->ptlCurrent
.y
;
94 PGDIBRUSHOBJ PenBrushObj
;
95 GDIBRUSHINST PenBrushInst
;
98 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
100 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
102 if (PATH_IsPathOpen(dc
->DcLevel
))
104 Ret
= PATH_LineTo(dc
, XEnd
, YEnd
);
107 // FIXME - PATH_LineTo should maybe do this? No
108 Dc_Attr
->ptlCurrent
.x
= XEnd
;
109 Dc_Attr
->ptlCurrent
.y
= YEnd
;
110 Dc_Attr
->ptfxCurrent
= Dc_Attr
->ptlCurrent
;
111 CoordLPtoDP(dc
, &Dc_Attr
->ptfxCurrent
); // Update fx
112 Dc_Attr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
118 if (Dc_Attr
->ulDirty_
& DC_BRUSH_DIRTY
)
119 IntGdiSelectBrush(dc
,Dc_Attr
->hbrush
);
121 if (Dc_Attr
->ulDirty_
& DC_PEN_DIRTY
)
122 IntGdiSelectPen(dc
,Dc_Attr
->hpen
);
124 BitmapObj
= BITMAPOBJ_LockBitmap ( dc
->w
.hBitmap
);
125 if (NULL
== BitmapObj
)
127 SetLastWin32Error(ERROR_INVALID_HANDLE
);
131 Points
[0].x
= Dc_Attr
->ptlCurrent
.x
;
132 Points
[0].y
= Dc_Attr
->ptlCurrent
.y
;
136 IntLPtoDP(dc
, Points
, 2);
138 /* The DCOrg is in device coordinates */
139 Points
[0].x
+= dc
->ptlDCOrig
.x
;
140 Points
[0].y
+= dc
->ptlDCOrig
.y
;
141 Points
[1].x
+= dc
->ptlDCOrig
.x
;
142 Points
[1].y
+= dc
->ptlDCOrig
.y
;
144 Bounds
.left
= min(Points
[0].x
, Points
[1].x
);
145 Bounds
.top
= min(Points
[0].y
, Points
[1].y
);
146 Bounds
.right
= max(Points
[0].x
, Points
[1].x
);
147 Bounds
.bottom
= max(Points
[0].y
, Points
[1].y
);
149 /* get BRUSHOBJ from current pen. */
150 PenBrushObj
= PENOBJ_LockPen( Dc_Attr
->hpen
);
153 /* default to BLACK_PEN */
154 PenBrushObj
= PENOBJ_LockPen(NtGdiGetStockObject(BLACK_PEN
));
158 if (!(PenBrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
160 IntGdiInitBrushInstance(&PenBrushInst
, PenBrushObj
, dc
->XlatePen
);
161 Ret
= IntEngLineTo(&BitmapObj
->SurfObj
,
163 &PenBrushInst
.BrushObject
,
164 Points
[0].x
, Points
[0].y
,
165 Points
[1].x
, Points
[1].y
,
167 ROP2_TO_MIX(Dc_Attr
->jROP2
));
170 BITMAPOBJ_UnlockBitmap ( BitmapObj
);
171 PENOBJ_UnlockPen( PenBrushObj
);
176 Dc_Attr
->ptlCurrent
.x
= XEnd
;
177 Dc_Attr
->ptlCurrent
.y
= YEnd
;
178 Dc_Attr
->ptfxCurrent
= Dc_Attr
->ptlCurrent
;
179 CoordLPtoDP(dc
, &Dc_Attr
->ptfxCurrent
); // Update fx
180 Dc_Attr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
187 IntGdiPolyBezier(DC
*dc
,
191 BOOL ret
= FALSE
; // default to FAILURE
193 if ( PATH_IsPathOpen(dc
->DcLevel
) )
195 return PATH_PolyBezier ( dc
, pt
, Count
);
198 /* We'll convert it into line segments and draw them using Polyline */
203 Pts
= GDI_Bezier ( pt
, Count
, &nOut
);
206 ret
= IntGdiPolyline(dc
, Pts
, nOut
);
207 ExFreePoolWithTag(Pts
, TAG_BEZIER
);
215 IntGdiPolyBezierTo(DC
*dc
,
219 BOOL ret
= FALSE
; // default to failure
220 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
222 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
223 if ( PATH_IsPathOpen(dc
->DcLevel
) )
224 ret
= PATH_PolyBezierTo ( dc
, pt
, Count
);
225 else /* We'll do it using PolyBezier */
228 npt
= ExAllocatePoolWithTag(PagedPool
,
229 sizeof(POINT
) * (Count
+ 1),
233 npt
[0].x
= Dc_Attr
->ptlCurrent
.x
;
234 npt
[0].y
= Dc_Attr
->ptlCurrent
.y
;
235 memcpy(npt
+ 1, pt
, sizeof(POINT
) * Count
);
236 ret
= IntGdiPolyBezier(dc
, npt
, Count
+1);
237 ExFreePoolWithTag(npt
, TAG_BEZIER
);
242 Dc_Attr
->ptlCurrent
.x
= pt
[Count
-1].x
;
243 Dc_Attr
->ptlCurrent
.y
= pt
[Count
-1].y
;
244 Dc_Attr
->ptfxCurrent
= Dc_Attr
->ptlCurrent
;
245 CoordLPtoDP(dc
, &Dc_Attr
->ptfxCurrent
); // Update fx
246 Dc_Attr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
253 IntGdiPolyline(DC
*dc
,
257 BITMAPOBJ
*BitmapObj
;
258 GDIBRUSHOBJ
*PenBrushObj
;
259 GDIBRUSHINST PenBrushInst
;
263 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
265 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
267 if (PATH_IsPathOpen(dc
->DcLevel
))
268 return PATH_Polyline(dc
, pt
, Count
);
270 if (Dc_Attr
->ulDirty_
& DC_BRUSH_DIRTY
)
271 IntGdiSelectBrush(dc
,Dc_Attr
->hbrush
);
273 if (Dc_Attr
->ulDirty_
& DC_PEN_DIRTY
)
274 IntGdiSelectPen(dc
,Dc_Attr
->hpen
);
276 /* Get BRUSHOBJ from current pen. */
277 PenBrushObj
= PENOBJ_LockPen(Dc_Attr
->hpen
);
278 /* FIXME - PenBrushObj can be NULL! Don't assert here! */
281 if (!(PenBrushObj
->flAttrs
& GDIBRUSH_IS_NULL
))
283 Points
= EngAllocMem(0, Count
* sizeof(POINT
), TAG_COORD
);
286 BitmapObj
= BITMAPOBJ_LockBitmap(dc
->w
.hBitmap
);
287 /* FIXME - BitmapObj can be NULL!!!!
288 Don't assert but handle this case gracefully! */
291 RtlCopyMemory(Points
, pt
, Count
* sizeof(POINT
));
292 IntLPtoDP(dc
, Points
, Count
);
294 /* Offset the array of point by the dc->w.DCOrg */
295 for (i
= 0; i
< Count
; i
++)
297 Points
[i
].x
+= dc
->ptlDCOrig
.x
;
298 Points
[i
].y
+= dc
->ptlDCOrig
.y
;
301 IntGdiInitBrushInstance(&PenBrushInst
, PenBrushObj
, dc
->XlatePen
);
302 Ret
= IntEngPolyline(&BitmapObj
->SurfObj
,
304 &PenBrushInst
.BrushObject
,
307 ROP2_TO_MIX(Dc_Attr
->jROP2
));
309 BITMAPOBJ_UnlockBitmap(BitmapObj
);
318 PENOBJ_UnlockPen(PenBrushObj
);
324 IntGdiPolylineTo(DC
*dc
,
328 BOOL ret
= FALSE
; // default to failure
329 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
331 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
332 if (PATH_IsPathOpen(dc
->DcLevel
))
334 ret
= PATH_PolylineTo(dc
, pt
, Count
);
336 else /* do it using Polyline */
338 POINT
*pts
= ExAllocatePoolWithTag(PagedPool
,
339 sizeof(POINT
) * (Count
+ 1),
343 pts
[0].x
= Dc_Attr
->ptlCurrent
.x
;
344 pts
[0].y
= Dc_Attr
->ptlCurrent
.y
;
345 memcpy( pts
+ 1, pt
, sizeof(POINT
) * Count
);
346 ret
= IntGdiPolyline(dc
, pts
, Count
+ 1);
347 ExFreePoolWithTag(pts
, TAG_SHAPE
);
352 Dc_Attr
->ptlCurrent
.x
= pt
[Count
-1].x
;
353 Dc_Attr
->ptlCurrent
.y
= pt
[Count
-1].y
;
354 Dc_Attr
->ptfxCurrent
= Dc_Attr
->ptlCurrent
;
355 CoordLPtoDP(dc
, &Dc_Attr
->ptfxCurrent
); // Update fx
356 Dc_Attr
->ulDirty_
&= ~(DIRTY_PTLCURRENT
|DIRTY_PTFXCURRENT
|DIRTY_STYLESTATE
);
364 IntGdiPolyPolyline(DC
*dc
,
372 BOOL ret
= FALSE
; // default to failure
376 if (PATH_IsPathOpen(dc
->DcLevel
))
377 return PATH_PolyPolyline( dc
, pt
, PolyPoints
, Count
);
379 for (i
= 0; i
< Count
; i
++)
381 ret
= IntGdiPolyline ( dc
, pts
, *pc
);
392 /******************************************************************************/
406 SetLastWin32Error(ERROR_INVALID_HANDLE
);
409 if (dc
->DC_Type
== DC_TYPE_INFO
)
412 /* Yes, Windows really returns TRUE in this case */
416 Ret
= IntGdiLineTo(dc
, XEnd
, YEnd
);
435 PDC_ATTR Dc_Attr
= NULL
;
438 if (!dc
) return FALSE
;
439 Dc_Attr
= dc
->pDc_Attr
;
440 if (!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
444 ProbeArrayForRead(lppt
, sizeof(POINT
), cCount
, sizeof(LONG
));
445 ProbeArrayForRead(lpbTypes
, sizeof(BYTE
), cCount
, sizeof(BYTE
));
447 /* check for each bezierto if there are two more points */
448 for ( i
= 0; i
< cCount
; i
++ )
450 if ( lpbTypes
[i
] != PT_MOVETO
&&
451 lpbTypes
[i
] & PT_BEZIERTO
)
453 if ( cCount
< i
+3 ) _SEH_LEAVE
;
458 /* if no moveto occurs, we will close the figure here */
459 lastmove
.x
= Dc_Attr
->ptlCurrent
.x
;
460 lastmove
.y
= Dc_Attr
->ptlCurrent
.y
;
463 for ( i
= 0; i
< cCount
; i
++ )
465 if ( lpbTypes
[i
] == PT_MOVETO
)
467 IntGdiMoveToEx( dc
, lppt
[i
].x
, lppt
[i
].y
, NULL
);
468 lastmove
.x
= Dc_Attr
->ptlCurrent
.x
;
469 lastmove
.y
= Dc_Attr
->ptlCurrent
.y
;
471 else if ( lpbTypes
[i
] & PT_LINETO
)
472 IntGdiLineTo( dc
, lppt
[i
].x
, lppt
[i
].y
);
473 else if ( lpbTypes
[i
] & PT_BEZIERTO
)
476 pts
[0].x
= Dc_Attr
->ptlCurrent
.x
;
477 pts
[0].y
= Dc_Attr
->ptlCurrent
.y
;
478 RtlCopyMemory(pts
+ 1, &lppt
[i
], sizeof(POINT
) * 3);
479 IntGdiPolyBezier(dc
, pts
, 4);
484 if ( lpbTypes
[i
] & PT_CLOSEFIGURE
)
486 if ( PATH_IsPathOpen(dc
->DcLevel
) )
488 pPath
= PATH_LockPath( dc
->DcLevel
.hPath
);
491 IntGdiCloseFigure( pPath
);
492 PATH_UnlockPath( pPath
);
495 else IntGdiLineTo( dc
, lastmove
.x
, lastmove
.y
);
503 SetLastNtError(_SEH_GetExceptionCode());
521 OUT OPTIONAL LPPOINT pptOut
)