branch update for HEAD-2003050101
[reactos.git] / subsys / win32k / objects / line.c
1 // Some code from the WINE project source (www.winehq.com)
2
3 #undef WIN32_LEAN_AND_MEAN
4 #include <windows.h>
5 #include <internal/safe.h>
6 #include <ddk/ntddk.h>
7 #include <win32k/dc.h>
8 #include <win32k/line.h>
9 #include <win32k/path.h>
10 #include <win32k/pen.h>
11 #include <win32k/region.h>
12 #include <include/inteng.h>
13
14 #define NDEBUG
15 #include <win32k/debug1.h>
16
17
18 BOOL
19 STDCALL
20 W32kAngleArc(HDC  hDC,
21                    int  X,
22                    int  Y,
23                    DWORD  Radius,
24                    FLOAT  StartAngle,
25                    FLOAT  SweepAngle)
26 {
27   UNIMPLEMENTED;
28 }
29
30 BOOL
31 STDCALL
32 W32kArc(HDC  hDC,
33               int  LeftRect,
34               int  TopRect,
35               int  RightRect,
36               int  BottomRect,
37               int  XStartArc,
38               int  YStartArc,
39               int  XEndArc,
40               int  YEndArc)
41 {
42   DC *dc = DC_HandleToPtr(hDC);
43   if(!dc) return FALSE;
44
45   if(PATH_IsPathOpen(dc->w.path))
46     return PATH_Arc(hDC, LeftRect, TopRect, RightRect, BottomRect,
47                     XStartArc, YStartArc, XEndArc, YEndArc);
48
49   DC_ReleasePtr( hDC );
50 //   EngArc(dc, LeftRect, TopRect, RightRect, BottomRect, UNIMPLEMENTED
51 //          XStartArc, YStartArc, XEndArc, YEndArc);
52 }
53
54 BOOL
55 STDCALL
56 W32kArcTo(HDC  hDC,
57                 int  LeftRect,
58                 int  TopRect,
59                 int  RightRect,
60                 int  BottomRect,
61                 int  XRadial1,
62                 int  YRadial1,
63                 int  XRadial2,
64                 int  YRadial2)
65 {
66   BOOL result;
67   DC *dc = DC_HandleToPtr(hDC);
68   if(!dc) return FALSE;
69
70   // Line from current position to starting point of arc
71   W32kLineTo(hDC, XRadial1, YRadial1);
72
73   // Then the arc is drawn.
74   result = W32kArc(hDC, LeftRect, TopRect, RightRect, BottomRect,
75                    XRadial1, YRadial1, XRadial2, YRadial2);
76
77   // If no error occured, the current position is moved to the ending point of the arc.
78   if(result)
79   {
80     W32kMoveToEx(hDC, XRadial2, YRadial2, NULL);
81   }
82   DC_ReleasePtr( hDC );
83   return result;
84 }
85
86 INT
87 STDCALL
88 W32kGetArcDirection(HDC  hDC)
89 {
90   PDC dc;
91   int ret;
92
93   dc = DC_HandleToPtr (hDC);
94   if (!dc)
95   {
96     return 0;
97   }
98
99   ret = dc->w.ArcDirection;
100   DC_ReleasePtr( hDC );
101   return ret;
102 }
103
104 BOOL
105 STDCALL
106 W32kLineTo(HDC  hDC,
107                  int  XEnd,
108                  int  YEnd)
109 {
110   DC            *dc = DC_HandleToPtr(hDC);
111   SURFOBJ       *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface);
112   BOOL ret;
113   PPENOBJ   pen;
114   PROSRGNDATA  reg;
115 #ifndef TODO
116   RECT defaultrect;
117 #endif
118
119   if(!dc) return FALSE;
120
121   if(PATH_IsPathOpen(dc->w.path)) {
122     ret = PATH_LineTo(hDC, XEnd, YEnd);
123   } else {
124         pen = (PPENOBJ) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
125         reg = (PROSRGNDATA)GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
126
127         ASSERT( pen );
128         // not yet implemented ASSERT( reg );
129 #ifndef TODO
130   if (NULL == reg) {
131     defaultrect.left = 0;
132     defaultrect.top = 0;
133     defaultrect.right = 640;
134     defaultrect.bottom = 480;
135
136     reg = &defaultrect;
137   }
138 #endif
139
140     /* Draw the line according to the DC origin */
141     ret = IntEngLineTo(SurfObj,
142                        NULL, // ClipObj
143                        PenToBrushObj(dc, pen),
144                        dc->w.DCOrgX + dc->w.CursPosX, dc->w.DCOrgY + dc->w.CursPosY,
145                        dc->w.DCOrgX + XEnd,           dc->w.DCOrgY + YEnd,
146                        reg, // Bounding rectangle
147                        dc->w.ROPmode); // MIX
148
149     GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC );
150     GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
151   }
152   if(ret) {
153     dc->w.CursPosX = XEnd;
154     dc->w.CursPosY = YEnd;
155   }
156   DC_ReleasePtr( hDC );
157   return ret;
158 }
159
160 BOOL
161 STDCALL
162 W32kMoveToEx(HDC  hDC,
163                    int  X,
164                    int  Y,
165                    LPPOINT  Point)
166 {
167   DC *dc = DC_HandleToPtr( hDC );
168
169   if(!dc) return FALSE;
170
171   if(Point) {
172     Point->x = dc->w.CursPosX;
173     Point->y = dc->w.CursPosY;
174   }
175   dc->w.CursPosX = X;
176   dc->w.CursPosY = Y;
177
178   if(PATH_IsPathOpen(dc->w.path)){
179         DC_ReleasePtr( hDC );
180     return PATH_MoveTo(hDC);
181   }
182   DC_ReleasePtr( hDC );
183   return FALSE;
184 }
185
186 BOOL
187 STDCALL
188 W32kPolyBezier(HDC  hDC,
189                      CONST LPPOINT  pt,
190                      DWORD  Count)
191 {
192   DC *dc = DC_HandleToPtr(hDC);
193   if(!dc) return FALSE;
194
195   if(PATH_IsPathOpen(dc->w.path)){
196         DC_ReleasePtr( hDC );
197     return PATH_PolyBezier(hDC, pt, Count);
198   }
199
200   /* We'll convert it into line segments and draw them using Polyline */
201   {
202     POINT *Pts;
203     INT nOut;
204     BOOL ret;
205
206     Pts = GDI_Bezier(pt, Count, &nOut);
207     if(!Pts) return FALSE;
208     DbgPrint("Pts = %p, no = %d\n", Pts, nOut);
209     ret = W32kPolyline(dc->hSelf, Pts, nOut);
210     ExFreePool(Pts);
211         DC_ReleasePtr( hDC );
212     return ret;
213   }
214 }
215
216 BOOL
217 STDCALL
218 W32kPolyBezierTo(HDC  hDC,
219                        CONST LPPOINT  pt,
220                        DWORD  Count)
221 {
222   DC *dc = DC_HandleToPtr(hDC);
223   BOOL ret;
224
225   if(!dc) return FALSE;
226
227   if(PATH_IsPathOpen(dc->w.path))
228     ret = PATH_PolyBezierTo(hDC, pt, Count);
229   else { /* We'll do it using PolyBezier */
230     POINT *npt;
231     npt = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1));
232     if(!npt) return FALSE;
233     npt[0].x = dc->w.CursPosX;
234     npt[0].y = dc->w.CursPosY;
235     memcpy(npt + 1, pt, sizeof(POINT) * Count);
236     ret = W32kPolyBezier(dc->hSelf, npt, Count+1);
237     ExFreePool(npt);
238   }
239   if(ret) {
240     dc->w.CursPosX = pt[Count-1].x;
241     dc->w.CursPosY = pt[Count-1].y;
242   }
243   DC_ReleasePtr( hDC );
244   return ret;
245 }
246
247 BOOL
248 STDCALL
249 W32kPolyDraw(HDC  hDC,
250                    CONST LPPOINT  pt,
251                    CONST LPBYTE  Types,
252                    int  Count)
253 {
254   UNIMPLEMENTED;
255 }
256
257 BOOL
258 STDCALL
259 W32kPolyline(HDC  hDC,
260                    CONST LPPOINT  pt,
261                    int  Count)
262 {
263   DC            *dc = DC_HandleToPtr(hDC);
264   SURFOBJ       *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface);
265   BOOL ret;
266   LONG i;
267   PPENOBJ   pen;
268   PROSRGNDATA  reg;
269   POINT *pts;
270
271   if (!dc) 
272     return(FALSE);
273
274   if(PATH_IsPathOpen(dc->w.path))
275   {
276     ret = PATH_Polyline(hDC, pt, Count);
277   }
278   else
279   {
280     pen = (PPENOBJ) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
281     reg = (PROSRGNDATA)GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
282
283     ASSERT( pen );
284
285     //FIXME: Do somthing with reg...
286
287     //Allocate "Count" bytes of memory to hold a safe copy of pt
288     if (!(pts=ExAllocatePool(NonPagedPool, sizeof(POINT) * Count))) 
289     {
290       GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC );
291       GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
292       DC_ReleasePtr( hDC );
293       return(FALSE);
294     }
295  
296     //safly copy pt to local version
297     if (STATUS_SUCCESS!=MmCopyFromCaller(pts, pt, sizeof(POINT) * Count))
298     {
299       ExFreePool(pts);
300       GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC );
301       GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
302       DC_ReleasePtr( hDC );
303       return(FALSE);
304     }
305  
306     //offset the array of point by the dc->w.DCOrg
307     for(i=0; i<Count; i++)
308     {
309       pts[i].x += dc->w.DCOrgX;
310       pts[i].y += dc->w.DCOrgY;
311     }
312   
313     //get IntEngPolyline to do the drawing.
314     ret = IntEngPolyline(SurfObj,
315                          NULL,
316                          PenToBrushObj(dc, pen),
317                          pts,
318                          Count,
319                          dc->w.ROPmode);
320
321     //Clean up
322     ExFreePool(pts);
323     GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC );
324     GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
325   }
326
327   DC_ReleasePtr( hDC );
328   return(ret);
329 }
330
331 BOOL
332 STDCALL
333 W32kPolylineTo(HDC  hDC,
334                      CONST LPPOINT  pt,
335                      DWORD  Count)
336 {
337   DC *dc = DC_HandleToPtr(hDC);
338   BOOL ret;
339
340   if(!dc) return FALSE;
341
342   if(PATH_IsPathOpen(dc->w.path))
343   {
344     ret = PATH_PolylineTo(hDC, pt, Count);
345   }
346   else { /* do it using Polyline */
347     POINT *pts = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1));
348     if(!pts) return FALSE;
349
350     pts[0].x = dc->w.CursPosX;
351     pts[0].y = dc->w.CursPosY;
352     memcpy( pts + 1, pt, sizeof(POINT) * Count);
353     ret = W32kPolyline(hDC, pts, Count + 1);
354     ExFreePool(pts);
355   }
356   if(ret) {
357     dc->w.CursPosX = pt[Count-1].x;
358     dc->w.CursPosY = pt[Count-1].y;
359   }
360   DC_ReleasePtr( hDC );
361   return ret;
362 }
363
364 BOOL
365 STDCALL
366 W32kPolyPolyline(HDC  hDC,
367                        CONST LPPOINT  pt,
368                        CONST LPDWORD  PolyPoints,
369                        DWORD  Count)
370 {
371    UNIMPLEMENTED;
372 }
373
374 int
375 STDCALL
376 W32kSetArcDirection(HDC  hDC,
377                          int  ArcDirection)
378 {
379   PDC  dc;
380   INT  nOldDirection;
381
382   dc = DC_HandleToPtr (hDC);
383   if (!dc)
384   {
385     return 0;
386   }
387   if (ArcDirection != AD_COUNTERCLOCKWISE && ArcDirection != AD_CLOCKWISE)
388   {
389 //    SetLastError(ERROR_INVALID_PARAMETER);
390         DC_ReleasePtr( hDC );
391     return 0;
392   }
393
394   nOldDirection = dc->w.ArcDirection;
395   dc->w.ArcDirection = ArcDirection;
396   DC_ReleasePtr( hDC );
397   return nOldDirection;
398 }