4c092fb58bf21f8b9d7b8e4c99895f813d6c1cfa
[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 <ddk/ntddk.h>
6 #include <win32k/dc.h>
7 #include <win32k/line.h>
8 #include <win32k/path.h>
9 #include <win32k/pen.h>
10 #include <win32k/region.h>
11
12 // #define NDEBUG
13 #include <win32k/debug1.h>
14
15 BOOL
16 STDCALL
17 W32kAngleArc(HDC  hDC,
18                    int  X,
19                    int  Y,
20                    DWORD  Radius,
21                    FLOAT  StartAngle,
22                    FLOAT  SweepAngle)
23 {
24   UNIMPLEMENTED;
25 }
26
27 BOOL
28 STDCALL
29 W32kArc(HDC  hDC,
30               int  LeftRect,
31               int  TopRect,
32               int  RightRect,
33               int  BottomRect,
34               int  XStartArc,
35               int  YStartArc,
36               int  XEndArc,
37               int  YEndArc)
38 {
39   DC *dc = DC_HandleToPtr(hDC);
40   if(!dc) return FALSE;
41
42   if(PATH_IsPathOpen(dc->w.path))
43     return PATH_Arc(hDC, LeftRect, TopRect, RightRect, BottomRect,
44                     XStartArc, YStartArc, XEndArc, YEndArc);
45
46   DC_ReleasePtr( hDC );
47 //   EngArc(dc, LeftRect, TopRect, RightRect, BottomRect, UNIMPLEMENTED
48 //          XStartArc, YStartArc, XEndArc, YEndArc);
49 }
50
51 BOOL
52 STDCALL
53 W32kArcTo(HDC  hDC,
54                 int  LeftRect,
55                 int  TopRect,
56                 int  RightRect,
57                 int  BottomRect,
58                 int  XRadial1,
59                 int  YRadial1,
60                 int  XRadial2,
61                 int  YRadial2)
62 {
63   BOOL result;
64   DC *dc = DC_HandleToPtr(hDC);
65   if(!dc) return FALSE;
66
67   // Line from current position to starting point of arc
68   W32kLineTo(hDC, XRadial1, YRadial1);
69
70   // Then the arc is drawn.
71   result = W32kArc(hDC, LeftRect, TopRect, RightRect, BottomRect,
72                    XRadial1, YRadial1, XRadial2, YRadial2);
73
74   // If no error occured, the current position is moved to the ending point of the arc.
75   if(result)
76   {
77     W32kMoveToEx(hDC, XRadial2, YRadial2, NULL);
78   }
79   DC_ReleasePtr( hDC );
80   return result;
81 }
82
83 INT
84 STDCALL
85 W32kGetArcDirection(HDC  hDC)
86 {
87   PDC dc;
88   int ret;
89
90   dc = DC_HandleToPtr (hDC);
91   if (!dc)
92   {
93     return 0;
94   }
95
96   ret = dc->w.ArcDirection;
97   DC_ReleasePtr( hDC );
98   return ret;
99 }
100
101 BOOL
102 STDCALL
103 W32kLineTo(HDC  hDC,
104                  int  XEnd,
105                  int  YEnd)
106 {
107   DC            *dc = DC_HandleToPtr(hDC);
108   SURFOBJ       *SurfObj = (SURFOBJ*)AccessUserObject(dc->Surface);
109   BOOL ret;
110   PPENOBJ   pen;
111   PROSRGNDATA  reg;
112
113   if(!dc) return FALSE;
114
115   if(PATH_IsPathOpen(dc->w.path)) {
116     ret = PATH_LineTo(hDC, XEnd, YEnd);
117   } else {
118         pen = (PPENOBJ) GDIOBJ_LockObj(dc->w.hPen, GO_PEN_MAGIC);
119         reg = (PROSRGNDATA)GDIOBJ_LockObj(dc->w.hGCClipRgn, GO_REGION_MAGIC);
120
121         ASSERT( pen );
122         // not yet implemented ASSERT( reg );
123
124     ret = EngLineTo(SurfObj,
125                     NULL, // ClipObj
126                     PenToBrushObj(dc, pen),
127                     dc->w.CursPosX, dc->w.CursPosY, XEnd, YEnd,
128                     reg, // Bounding rectangle
129                     dc->w.ROPmode); // MIX
130
131         GDIOBJ_UnlockObj( dc->w.hGCClipRgn, GO_REGION_MAGIC );
132         GDIOBJ_UnlockObj( dc->w.hPen, GO_PEN_MAGIC);
133   }
134   if(ret) {
135     dc->w.CursPosX = XEnd;
136     dc->w.CursPosY = YEnd;
137   }
138   DC_ReleasePtr( hDC );
139   return ret;
140 }
141
142 BOOL
143 STDCALL
144 W32kMoveToEx(HDC  hDC,
145                    int  X,
146                    int  Y,
147                    LPPOINT  Point)
148 {
149   DC *dc = DC_HandleToPtr( hDC );
150
151   if(!dc) return FALSE;
152
153   if(Point) {
154     Point->x = dc->w.CursPosX;
155     Point->y = dc->w.CursPosY;
156   }
157   dc->w.CursPosX = X;
158   dc->w.CursPosY = Y;
159
160   if(PATH_IsPathOpen(dc->w.path)){
161         DC_ReleasePtr( hDC );
162     return PATH_MoveTo(hDC);
163   }
164   DC_ReleasePtr( hDC );
165   return FALSE;
166 }
167
168 BOOL
169 STDCALL
170 W32kPolyBezier(HDC  hDC,
171                      CONST LPPOINT  pt,
172                      DWORD  Count)
173 {
174   DC *dc = DC_HandleToPtr(hDC);
175   if(!dc) return FALSE;
176
177   if(PATH_IsPathOpen(dc->w.path)){
178         DC_ReleasePtr( hDC );
179     return PATH_PolyBezier(hDC, pt, Count);
180   }
181
182   /* We'll convert it into line segments and draw them using Polyline */
183   {
184     POINT *Pts;
185     INT nOut;
186     BOOL ret;
187
188     Pts = GDI_Bezier(pt, Count, &nOut);
189     if(!Pts) return FALSE;
190     DbgPrint("Pts = %p, no = %d\n", Pts, nOut);
191     ret = W32kPolyline(dc->hSelf, Pts, nOut);
192     ExFreePool(Pts);
193         DC_ReleasePtr( hDC );
194     return ret;
195   }
196 }
197
198 BOOL
199 STDCALL
200 W32kPolyBezierTo(HDC  hDC,
201                        CONST LPPOINT  pt,
202                        DWORD  Count)
203 {
204   DC *dc = DC_HandleToPtr(hDC);
205   BOOL ret;
206
207   if(!dc) return FALSE;
208
209   if(PATH_IsPathOpen(dc->w.path))
210     ret = PATH_PolyBezierTo(hDC, pt, Count);
211   else { /* We'll do it using PolyBezier */
212     POINT *npt;
213     npt = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1));
214     if(!npt) return FALSE;
215     npt[0].x = dc->w.CursPosX;
216     npt[0].y = dc->w.CursPosY;
217     memcpy(npt + 1, pt, sizeof(POINT) * Count);
218     ret = W32kPolyBezier(dc->hSelf, npt, Count+1);
219     ExFreePool(npt);
220   }
221   if(ret) {
222     dc->w.CursPosX = pt[Count-1].x;
223     dc->w.CursPosY = pt[Count-1].y;
224   }
225   DC_ReleasePtr( hDC );
226   return ret;
227 }
228
229 BOOL
230 STDCALL
231 W32kPolyDraw(HDC  hDC,
232                    CONST LPPOINT  pt,
233                    CONST LPBYTE  Types,
234                    int  Count)
235 {
236   UNIMPLEMENTED;
237 }
238
239 BOOL
240 STDCALL
241 W32kPolyline(HDC  hDC,
242                    CONST LPPOINT  pt,
243                    int  Count)
244 {
245    UNIMPLEMENTED;
246 }
247
248 BOOL
249 STDCALL
250 W32kPolylineTo(HDC  hDC,
251                      CONST LPPOINT  pt,
252                      DWORD  Count)
253 {
254   DC *dc = DC_HandleToPtr(hDC);
255   BOOL ret;
256
257   if(!dc) return FALSE;
258
259   if(PATH_IsPathOpen(dc->w.path))
260   {
261     ret = PATH_PolylineTo(hDC, pt, Count);
262   }
263   else { /* do it using Polyline */
264     POINT *pts = ExAllocatePool(NonPagedPool, sizeof(POINT) * (Count + 1));
265     if(!pts) return FALSE;
266
267     pts[0].x = dc->w.CursPosX;
268     pts[0].y = dc->w.CursPosY;
269     memcpy( pts + 1, pt, sizeof(POINT) * Count);
270     ret = W32kPolyline(hDC, pts, Count + 1);
271     ExFreePool(pts);
272   }
273   if(ret) {
274     dc->w.CursPosX = pt[Count-1].x;
275     dc->w.CursPosY = pt[Count-1].y;
276   }
277   DC_ReleasePtr( hDC );
278   return ret;
279 }
280
281 BOOL
282 STDCALL
283 W32kPolyPolyline(HDC  hDC,
284                        CONST LPPOINT  pt,
285                        CONST LPDWORD  PolyPoints,
286                        DWORD  Count)
287 {
288    UNIMPLEMENTED;
289 }
290
291 int
292 STDCALL
293 W32kSetArcDirection(HDC  hDC,
294                          int  ArcDirection)
295 {
296   PDC  dc;
297   INT  nOldDirection;
298
299   dc = DC_HandleToPtr (hDC);
300   if (!dc)
301   {
302     return 0;
303   }
304   if (ArcDirection != AD_COUNTERCLOCKWISE && ArcDirection != AD_CLOCKWISE)
305   {
306 //    SetLastError(ERROR_INVALID_PARAMETER);
307         DC_ReleasePtr( hDC );
308     return 0;
309   }
310
311   nOldDirection = dc->w.ArcDirection;
312   dc->w.ArcDirection = ArcDirection;
313   DC_ReleasePtr( hDC );
314   return nOldDirection;
315 }