04c8c776e5a5512e9ba20b27d5582ab0a8c1d89b
[reactos.git] / reactos / subsys / win32k / objects / line.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: line.c,v 1.21 2003/08/20 07:45:02 gvg Exp $ */
20
21 // Some code from the WINE project source (www.winehq.com)
22
23 #undef WIN32_LEAN_AND_MEAN
24 #include <windows.h>
25 #include <internal/safe.h>
26 #include <ddk/ntddk.h>
27 #include <win32k/dc.h>
28 #include <win32k/line.h>
29 #include <win32k/path.h>
30 #include <win32k/pen.h>
31 #include <win32k/region.h>
32 #include <include/error.h>
33 #include <include/inteng.h>
34 #include <include/object.h>
35 #include <include/path.h>
36
37 #define NDEBUG
38 #include <win32k/debug1.h>
39
40
41 BOOL
42 STDCALL
43 NtGdiAngleArc(HDC hDC,
44 int X,
45 int Y,
46 DWORD Radius,
47 FLOAT StartAngle,
48 FLOAT SweepAngle)
49 {
50 UNIMPLEMENTED;
51 }
52
53 BOOL
54 STDCALL
55 NtGdiArc(HDC hDC,
56 int LeftRect,
57 int TopRect,
58 int RightRect,
59 int BottomRect,
60 int XStartArc,
61 int YStartArc,
62 int XEndArc,
63 int YEndArc)
64 {
65 DC *dc = DC_LockDc(hDC);
66 if(!dc) return FALSE;
67
68 if(PATH_IsPathOpen(dc->w.path))
69 {
70 DC_UnlockDc ( hDC );
71 return PATH_Arc(hDC, LeftRect, TopRect, RightRect, BottomRect,
72 XStartArc, YStartArc, XEndArc, YEndArc);
73 }
74
75 // FIXME
76 // EngArc(dc, LeftRect, TopRect, RightRect, BottomRect, UNIMPLEMENTED
77 // XStartArc, YStartArc, XEndArc, YEndArc);
78
79 DC_UnlockDc( hDC );
80 return TRUE;
81 }
82
83 BOOL
84 STDCALL
85 NtGdiArcTo(HDC hDC,
86 int LeftRect,
87 int TopRect,
88 int RightRect,
89 int BottomRect,
90 int XRadial1,
91 int YRadial1,
92 int XRadial2,
93 int YRadial2)
94 {
95 BOOL result;
96 //DC *dc;
97
98 // Line from current position to starting point of arc
99 if ( !NtGdiLineTo(hDC, XRadial1, YRadial1) )
100 return FALSE;
101
102 //dc = DC_LockDc(hDC);
103
104 //if(!dc) return FALSE;
105
106 // Then the arc is drawn.
107 result = NtGdiArc(hDC, LeftRect, TopRect, RightRect, BottomRect,
108 XRadial1, YRadial1, XRadial2, YRadial2);
109
110 //DC_UnlockDc( hDC );
111
112 // If no error occured, the current position is moved to the ending point of the arc.
113 if(result)
114 NtGdiMoveToEx(hDC, XRadial2, YRadial2, NULL);
115
116 return result;
117 }
118
119 INT
120 FASTCALL
121 IntGetArcDirection ( PDC dc )
122 {
123 ASSERT ( dc );
124 return dc->w.ArcDirection;
125 }
126
127 INT
128 STDCALL
129 NtGdiGetArcDirection(HDC hDC)
130 {
131 PDC dc = DC_LockDc (hDC);
132 int ret = 0; // default to failure
133
134 if ( dc )
135 {
136 ret = IntGetArcDirection ( dc );
137 DC_UnlockDc( hDC );
138 }
139
140 return ret;
141 }
142
143 BOOL
144 STDCALL
145 NtGdiLineTo(HDC hDC,
146 int XEnd,
147 int YEnd)
148 {
149 DC *dc = DC_LockDc(hDC);
150 SURFOBJ *SurfObj;
151 BOOL Ret;
152 BRUSHOBJ PenBrushObj;
153 RECT Bounds;
154
155 if ( !dc )
156 {
157 SetLastWin32Error(ERROR_INVALID_HANDLE);
158 return FALSE;
159 }
160
161 SurfObj = (SURFOBJ*)AccessUserObject ( (ULONG)dc->Surface );
162
163 if (PATH_IsPathOpen(dc->w.path))
164 {
165 DC_UnlockDc(hDC);
166 Ret = PATH_LineTo(hDC, XEnd, YEnd);
167 if (Ret)
168 {
169 // FIXME - PATH_LineTo should maybe do this...
170 dc = DC_LockDc(hDC);
171 dc->w.CursPosX = XEnd;
172 dc->w.CursPosY = YEnd;
173 DC_UnlockDc(hDC);
174 }
175 return Ret;
176 }
177 else
178 {
179 if (dc->w.CursPosX <= XEnd)
180 {
181 Bounds.left = dc->w.CursPosX;
182 Bounds.right = XEnd;
183 }
184 else
185 {
186 Bounds.left = XEnd;
187 Bounds.right = dc->w.CursPosX;
188 }
189 Bounds.left += dc->w.DCOrgX;
190 Bounds.right += dc->w.DCOrgX;
191 if (dc->w.CursPosY <= YEnd)
192 {
193 Bounds.top = dc->w.CursPosY;
194 Bounds.bottom = YEnd;
195 }
196 else
197 {
198 Bounds.top = YEnd;
199 Bounds.bottom = dc->w.CursPosY;
200 }
201 Bounds.top += dc->w.DCOrgY;
202 Bounds.bottom += dc->w.DCOrgY;
203
204 /* make BRUSHOBJ from current pen. */
205 HPenToBrushObj ( &PenBrushObj, dc->w.hPen );
206
207 Ret = IntEngLineTo(SurfObj,
208 dc->CombinedClip,
209 &PenBrushObj,
210 dc->w.DCOrgX + dc->w.CursPosX, dc->w.DCOrgY + dc->w.CursPosY,
211 dc->w.DCOrgX + XEnd, dc->w.DCOrgY + YEnd,
212 &Bounds,
213 dc->w.ROPmode);
214 }
215
216 if (Ret)
217 {
218 dc->w.CursPosX = XEnd;
219 dc->w.CursPosY = YEnd;
220 }
221 DC_UnlockDc(hDC);
222
223 return Ret;
224 }
225
226 BOOL
227 STDCALL
228 NtGdiMoveToEx(HDC hDC,
229 int X,
230 int Y,
231 LPPOINT Point)
232 {
233 DC *dc = DC_LockDc( hDC );
234 BOOL PathIsOpen;
235
236 if ( !dc ) return FALSE;
237
238 if ( Point )
239 {
240 Point->x = dc->w.CursPosX;
241 Point->y = dc->w.CursPosY;
242 }
243 dc->w.CursPosX = X;
244 dc->w.CursPosY = Y;
245
246 PathIsOpen = PATH_IsPathOpen(dc->w.path);
247
248 DC_UnlockDc ( hDC );
249
250 if ( PathIsOpen )
251 return PATH_MoveTo ( hDC );
252
253 return TRUE;
254 }
255
256 BOOL
257 STDCALL
258 NtGdiPolyBezier(HDC hDC,
259 CONST LPPOINT pt,
260 DWORD Count)
261 {
262 DC *dc = DC_LockDc(hDC);
263 BOOL ret = FALSE; // default to FAILURE
264
265 if ( !dc ) return FALSE;
266
267 if ( PATH_IsPathOpen(dc->w.path) )
268 {
269 DC_UnlockDc( hDC );
270 return PATH_PolyBezier ( hDC, pt, Count );
271 }
272
273 /* We'll convert it into line segments and draw them using Polyline */
274 {
275 POINT *Pts;
276 INT nOut;
277
278 Pts = GDI_Bezier ( pt, Count, &nOut );
279 if ( Pts )
280 {
281 DbgPrint("Pts = %p, no = %d\n", Pts, nOut);
282 ret = NtGdiPolyline(dc->hSelf, Pts, nOut);
283 ExFreePool(Pts);
284 }
285 }
286 DC_UnlockDc( hDC );
287 return ret;
288 }
289
290 BOOL
291 STDCALL
292 NtGdiPolyBezierTo(HDC hDC,
293 CONST LPPOINT pt,
294 DWORD Count)
295 {
296 DC *dc = DC_LockDc(hDC);
297 BOOL ret = FALSE; // default to failure
298
299 if ( !dc ) return ret;
300
301 if ( PATH_IsPathOpen(dc->w.path) )
302 ret = PATH_PolyBezierTo ( hDC, pt, Count );
303 else /* We'll do it using PolyBezier */
304 {
305 POINT *npt;
306 npt = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1));
307 if ( npt )
308 {
309 npt[0].x = dc->w.CursPosX;
310 npt[0].y = dc->w.CursPosY;
311 memcpy(npt + 1, pt, sizeof(POINT) * Count);
312 ret = NtGdiPolyBezier(dc->hSelf, npt, Count+1);
313 ExFreePool(npt);
314 }
315 }
316 if ( ret )
317 {
318 dc->w.CursPosX = pt[Count-1].x;
319 dc->w.CursPosY = pt[Count-1].y;
320 }
321 DC_UnlockDc( hDC );
322 return ret;
323 }
324
325 BOOL
326 STDCALL
327 NtGdiPolyDraw(HDC hDC,
328 CONST LPPOINT pt,
329 CONST LPBYTE Types,
330 int Count)
331 {
332 UNIMPLEMENTED;
333 }
334
335 BOOL
336 FASTCALL
337 IntPolyline(PDC dc,
338 CONST LPPOINT pt,
339 int Count)
340 {
341 SURFOBJ *SurfObj = NULL;
342 BOOL ret = FALSE; // default to failure
343 LONG i;
344 PROSRGNDATA reg;
345 BRUSHOBJ PenBrushObj;
346 POINT *pts;
347
348 SurfObj = (SURFOBJ*)AccessUserObject((ULONG)dc->Surface);
349 ASSERT(SurfObj);
350
351 if ( PATH_IsPathOpen ( dc->w.path ) )
352 return PATH_Polyline ( dc, pt, Count );
353
354 reg = RGNDATA_LockRgn(dc->w.hGCClipRgn);
355
356 //FIXME: Do somthing with reg...
357
358 //Allocate "Count" bytes of memory to hold a safe copy of pt
359 pts = (POINT*)ExAllocatePool ( NonPagedPool, sizeof(POINT)*Count );
360 if ( pts )
361 {
362 // safely copy pt to local version
363 if ( STATUS_SUCCESS == MmCopyFromCaller(pts, pt, sizeof(POINT)*Count) )
364 {
365 //offset the array of point by the dc->w.DCOrg
366 for ( i = 0; i < Count; i++ )
367 {
368 pts[i].x += dc->w.DCOrgX;
369 pts[i].y += dc->w.DCOrgY;
370 }
371
372 /* make BRUSHOBJ from current pen. */
373 HPenToBrushObj ( &PenBrushObj, dc->w.hPen );
374
375 //get IntEngPolyline to do the drawing.
376 ret = IntEngPolyline(SurfObj,
377 dc->CombinedClip,
378 &PenBrushObj,
379 pts,
380 Count,
381 dc->w.ROPmode);
382 }
383
384 ExFreePool ( pts );
385 }
386
387 //Clean up
388 RGNDATA_UnlockRgn(dc->w.hGCClipRgn);
389
390 return ret;
391 }
392
393 BOOL
394 STDCALL
395 NtGdiPolyline(HDC hDC,
396 CONST LPPOINT pt,
397 int Count)
398 {
399 DC *dc = DC_LockDc(hDC);
400 BOOL ret = FALSE; // default to failure
401
402 if ( dc )
403 {
404 ret = IntPolyline ( dc, pt, Count );
405
406 DC_UnlockDc( hDC );
407 }
408
409 return ret;
410 }
411
412 BOOL
413 STDCALL
414 NtGdiPolylineTo(HDC hDC,
415 CONST LPPOINT pt,
416 DWORD Count)
417 {
418 DC *dc = DC_LockDc(hDC);
419 BOOL ret = FALSE; // default to failure
420
421 if ( !dc ) return ret;
422
423 if(PATH_IsPathOpen(dc->w.path))
424 {
425 ret = PATH_PolylineTo(hDC, pt, Count);
426 }
427 else /* do it using Polyline */
428 {
429 POINT *pts = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1));
430 if ( pts )
431 {
432 pts[0].x = dc->w.CursPosX;
433 pts[0].y = dc->w.CursPosY;
434 memcpy( pts + 1, pt, sizeof(POINT) * Count);
435 ret = NtGdiPolyline(hDC, pts, Count + 1);
436 ExFreePool(pts);
437 }
438 }
439 if ( ret )
440 {
441 dc->w.CursPosX = pt[Count-1].x;
442 dc->w.CursPosY = pt[Count-1].y;
443 }
444 DC_UnlockDc( hDC );
445 return ret;
446 }
447
448 BOOL
449 STDCALL
450 NtGdiPolyPolyline(HDC hDC,
451 CONST LPPOINT pt,
452 CONST LPDWORD PolyPoints,
453 DWORD Count)
454 {
455 UNIMPLEMENTED;
456 }
457
458 int
459 STDCALL
460 NtGdiSetArcDirection(HDC hDC,
461 int ArcDirection)
462 {
463 PDC dc;
464 INT nOldDirection = 0; // default to FAILURE
465
466 dc = DC_LockDc (hDC);
467 if ( !dc ) return 0;
468
469 if ( ArcDirection == AD_COUNTERCLOCKWISE || ArcDirection == AD_CLOCKWISE )
470 {
471 nOldDirection = dc->w.ArcDirection;
472 dc->w.ArcDirection = ArcDirection;
473 }
474
475 DC_UnlockDc( hDC );
476 return nOldDirection;
477 }
478 /* EOF */