Fix spurious warning/error reported by GCC 4.4.0.
[reactos.git] / reactos / subsystems / win32 / win32k / objects / arc.c
1 #include <w32k.h>
2
3 #define NDEBUG
4 #include <debug.h>
5
6 /*
7 * a couple macros to fill a single pixel or a line
8 */
9 #define PUTPIXEL(x,y,BrushInst) \
10 ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
11 dc->CombinedClip, \
12 &BrushInst.BrushObject, \
13 x, y, (x)+1, y, \
14 &RectBounds, \
15 ROP2_TO_MIX(Dc_Attr->jROP2));
16
17 #define PUTLINE(x1,y1,x2,y2,BrushInst) \
18 ret = ret && IntEngLineTo(&BitmapObj->SurfObj, \
19 dc->CombinedClip, \
20 &BrushInst.BrushObject, \
21 x1, y1, x2, y2, \
22 &RectBounds, \
23 ROP2_TO_MIX(Dc_Attr->jROP2));
24
25 #define Rsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
26 #define Rcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
27
28 BOOL FASTCALL IntFillArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype);
29 BOOL FASTCALL IntDrawArc( PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype, PGDIBRUSHOBJ PenBrushObj);
30
31 static
32 BOOL
33 FASTCALL
34 IntArc( DC *dc,
35 int Left,
36 int Top,
37 int Right,
38 int Bottom,
39 int XRadialStart,
40 int YRadialStart,
41 int XRadialEnd,
42 int YRadialEnd,
43 ARCTYPE arctype)
44 {
45 PDC_ATTR Dc_Attr;
46 RECTL RectBounds, RectSEpts;
47 PGDIBRUSHOBJ PenBrushObj;
48 GDIBRUSHINST PenBrushInst;
49 BITMAPOBJ *BitmapObj;
50 BOOL ret = TRUE;
51 LONG PenWidth, PenOrigWidth;
52 double AngleStart, AngleEnd;
53 LONG RadiusX, RadiusY, CenterX, CenterY;
54 LONG SfCx, SfCy, EfCx, EfCy;
55
56 if (Right < Left)
57 {
58 INT tmp = Right; Right = Left; Left = tmp;
59 }
60 if (Bottom < Top)
61 {
62 INT tmp = Bottom; Bottom = Top; Top = tmp;
63 }
64 if ((Left == Right) ||
65 (Top == Bottom) ||
66 (((arctype != GdiTypeArc) || (arctype != GdiTypeArcTo)) &&
67 ((Right - Left == 1) ||
68 (Bottom - Top == 1))))
69 return TRUE;
70
71 Dc_Attr = dc->pDc_Attr;
72 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
73
74 PenBrushObj = PENOBJ_LockPen(Dc_Attr->hpen);
75 if (NULL == PenBrushObj)
76 {
77 DPRINT1("Arc Fail 1\n");
78 SetLastWin32Error(ERROR_INTERNAL_ERROR);
79 return FALSE;
80 }
81
82 PenOrigWidth = PenWidth = PenBrushObj->ptPenWidth.x;
83 if (PenBrushObj->ulPenStyle == PS_NULL) PenWidth = 0;
84
85 if (PenBrushObj->ulPenStyle == PS_INSIDEFRAME)
86 {
87 if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
88 if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
89 Left += PenWidth / 2;
90 Right -= (PenWidth - 1) / 2;
91 Top += PenWidth / 2;
92 Bottom -= (PenWidth - 1) / 2;
93 }
94
95 if (!PenWidth) PenWidth = 1;
96 PenBrushObj->ptPenWidth.x = PenWidth;
97
98 RectBounds.left = Left;
99 RectBounds.right = Right;
100 RectBounds.top = Top;
101 RectBounds.bottom = Bottom;
102
103 RectSEpts.left = XRadialStart;
104 RectSEpts.top = YRadialStart;
105 RectSEpts.right = XRadialEnd;
106 RectSEpts.bottom = YRadialEnd;
107
108 IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
109 IntLPtoDP(dc, (LPPOINT)&RectSEpts, 2);
110
111 RectBounds.left += dc->ptlDCOrig.x;
112 RectBounds.right += dc->ptlDCOrig.x;
113 RectBounds.top += dc->ptlDCOrig.y;
114 RectBounds.bottom += dc->ptlDCOrig.y;
115
116 RectSEpts.left += dc->ptlDCOrig.x;
117 RectSEpts.top += dc->ptlDCOrig.y;
118 RectSEpts.right += dc->ptlDCOrig.x;
119 RectSEpts.bottom += dc->ptlDCOrig.y;
120
121 DPRINT("1: StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
122 RectSEpts.left,RectSEpts.top,RectSEpts.right,RectSEpts.bottom);
123
124 DPRINT("1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
125 RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom);
126
127 RadiusX = max((RectBounds.right - RectBounds.left) / 2, 1);
128 RadiusY = max((RectBounds.bottom - RectBounds.top) / 2, 1);
129 CenterX = (RectBounds.right + RectBounds.left) / 2;
130 CenterY = (RectBounds.bottom + RectBounds.top) / 2;
131 AngleEnd = atan2((RectSEpts.bottom - CenterY), RectSEpts.right - CenterX)*(360.0/(M_PI*2));
132 AngleStart = atan2((RectSEpts.top - CenterY), RectSEpts.left - CenterX)*(360.0/(M_PI*2));
133
134 SfCx = (Rcos(AngleStart) * RadiusX);
135 SfCy = (Rsin(AngleStart) * RadiusY);
136 EfCx = (Rcos(AngleEnd) * RadiusX);
137 EfCy = (Rsin(AngleEnd) * RadiusY);
138
139 if ((arctype == GdiTypePie) || (arctype == GdiTypeChord))
140 {
141 ret = IntFillArc( dc,
142 RectBounds.left,
143 RectBounds.top,
144 abs(RectBounds.right-RectBounds.left), // Width
145 abs(RectBounds.bottom-RectBounds.top), // Height
146 AngleStart,
147 AngleEnd,
148 arctype);
149 }
150
151 ret = IntDrawArc( dc,
152 RectBounds.left,
153 RectBounds.top,
154 abs(RectBounds.right-RectBounds.left), // Width
155 abs(RectBounds.bottom-RectBounds.top), // Height
156 AngleStart,
157 AngleEnd,
158 arctype,
159 PenBrushObj);
160
161 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
162 if (NULL == BitmapObj)
163 {
164 DPRINT1("Arc Fail 2\n");
165 PENOBJ_UnlockPen(PenBrushObj);
166 SetLastWin32Error(ERROR_INTERNAL_ERROR);
167 return FALSE;
168 }
169
170 IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
171
172 if (arctype == GdiTypePie)
173 {
174 PUTLINE(CenterX, CenterY, SfCx + CenterX, SfCy + CenterY, PenBrushInst);
175 PUTLINE(EfCx + CenterX, EfCy + CenterY, CenterX, CenterY, PenBrushInst);
176 }
177 if (arctype == GdiTypeChord)
178 PUTLINE(EfCx + CenterX, EfCy + CenterY, SfCx + CenterX, SfCy + CenterY, PenBrushInst);
179
180 PenBrushObj->ptPenWidth.x = PenOrigWidth;
181 BITMAPOBJ_UnlockBitmap(BitmapObj);
182 PENOBJ_UnlockPen(PenBrushObj);
183 DPRINT("IntArc Exit.\n");
184 return ret;
185 }
186
187
188 BOOL FASTCALL
189 IntGdiArcInternal(
190 ARCTYPE arctype,
191 DC *dc,
192 int LeftRect,
193 int TopRect,
194 int RightRect,
195 int BottomRect,
196 int XStartArc,
197 int YStartArc,
198 int XEndArc,
199 int YEndArc)
200 {
201 BOOL Ret;
202 PDC_ATTR pDc_Attr;
203
204 DPRINT("StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
205 XStartArc,YStartArc,XEndArc,YEndArc);
206 DPRINT("Left: %d, Top: %d, Right: %d, Bottom: %d\n",
207 LeftRect,TopRect,RightRect,BottomRect);
208
209 if ((LeftRect == RightRect) || (TopRect == BottomRect)) return TRUE;
210
211 if (PATH_IsPathOpen(dc->DcLevel))
212 {
213 return PATH_Arc( dc,
214 LeftRect,
215 TopRect,
216 RightRect,
217 BottomRect,
218 XStartArc,
219 YStartArc,
220 XEndArc,
221 YEndArc,
222 arctype);
223 }
224
225 pDc_Attr = dc->pDc_Attr;
226 if (!pDc_Attr) pDc_Attr = &dc->Dc_Attr;
227
228 if (pDc_Attr->ulDirty_ & DC_BRUSH_DIRTY)
229 IntGdiSelectBrush(dc,pDc_Attr->hbrush);
230
231 if (pDc_Attr->ulDirty_ & DC_PEN_DIRTY)
232 IntGdiSelectPen(dc,pDc_Attr->hpen);
233
234 if (arctype == GdiTypeArcTo)
235 {
236 if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
237 IntGdiLineTo(dc, XEndArc, YEndArc);
238 else
239 IntGdiLineTo(dc, XStartArc, YStartArc);
240 }
241
242 Ret = IntArc( dc,
243 LeftRect,
244 TopRect,
245 RightRect,
246 BottomRect,
247 XStartArc,
248 YStartArc,
249 XEndArc,
250 YEndArc,
251 arctype);
252
253 if (arctype == GdiTypeArcTo)
254 {
255 if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
256 IntGdiMoveToEx(dc, XStartArc, YStartArc, NULL);
257 else
258 IntGdiMoveToEx(dc, XEndArc, YEndArc, NULL);
259 }
260 return Ret;
261 }
262
263 BOOL
264 FASTCALL
265 IntGdiAngleArc( PDC pDC,
266 INT x,
267 INT y,
268 DWORD dwRadius,
269 FLOAT eStartAngle,
270 FLOAT eSweepAngle)
271 {
272 INT x1, y1, x2, y2, arcdir;
273 BOOL result;
274
275 /* Calculate the end point */
276 x2 = x + (INT)(cos(((eStartAngle+eSweepAngle)/360)*(M_PI*2)) * dwRadius);
277 y2 = y - (INT)(sin(((eStartAngle+eSweepAngle)/360)*(M_PI*2)) * dwRadius);
278
279 x1 = x + (INT)(cos((eStartAngle/360)*(M_PI*2)) * dwRadius);
280 y1 = y - (INT)(sin((eStartAngle/360)*(M_PI*2)) * dwRadius);
281
282 arcdir = pDC->DcLevel.flPath & DCPATH_CLOCKWISE;
283 if (eSweepAngle >= 0)
284 pDC->DcLevel.flPath &= ~DCPATH_CLOCKWISE;
285 else
286 pDC->DcLevel.flPath |= DCPATH_CLOCKWISE;
287
288 result = IntGdiArcInternal( GdiTypeArcTo,
289 pDC,
290 x-dwRadius,
291 y-dwRadius,
292 x+dwRadius,
293 y+dwRadius,
294 x1,
295 y1,
296 x2,
297 y2 );
298
299 pDC->DcLevel.flPath |= (arcdir & DCPATH_CLOCKWISE);
300
301 if (result)
302 {
303 IntGdiMoveToEx(pDC, x2, y2, NULL); // Dont forget Path.
304 }
305 return result;
306 }
307
308 /* FUNCTIONS *****************************************************************/
309
310 BOOL
311 APIENTRY
312 NtGdiAngleArc(
313 IN HDC hDC,
314 IN INT x,
315 IN INT y,
316 IN DWORD dwRadius,
317 IN DWORD dwStartAngle,
318 IN DWORD dwSweepAngle)
319 {
320 DC *pDC;
321 BOOL Ret = FALSE;
322 gxf_long worker, worker1;
323
324 pDC = DC_LockDc (hDC);
325 if(!pDC)
326 {
327 SetLastWin32Error(ERROR_INVALID_HANDLE);
328 return FALSE;
329 }
330 if (pDC->DC_Type == DC_TYPE_INFO)
331 {
332 DC_UnlockDc(pDC);
333 /* Yes, Windows really returns TRUE in this case */
334 return TRUE;
335 }
336 worker.l = dwStartAngle;
337 worker1.l = dwSweepAngle;
338 Ret = IntGdiAngleArc( pDC, x, y, dwRadius, worker.f, worker1.f);
339 DC_UnlockDc( pDC );
340 return Ret;
341 }
342
343 BOOL
344 APIENTRY
345 NtGdiArcInternal(
346 ARCTYPE arctype,
347 HDC hDC,
348 int LeftRect,
349 int TopRect,
350 int RightRect,
351 int BottomRect,
352 int XStartArc,
353 int YStartArc,
354 int XEndArc,
355 int YEndArc)
356 {
357 DC *dc;
358 BOOL Ret;
359
360 dc = DC_LockDc (hDC);
361 if(!dc)
362 {
363 SetLastWin32Error(ERROR_INVALID_HANDLE);
364 return FALSE;
365 }
366 if (dc->DC_Type == DC_TYPE_INFO)
367 {
368 DC_UnlockDc(dc);
369 /* Yes, Windows really returns TRUE in this case */
370 return TRUE;
371 }
372
373 Ret = IntGdiArcInternal(
374 arctype,
375 dc,
376 LeftRect,
377 TopRect,
378 RightRect,
379 BottomRect,
380 XStartArc,
381 YStartArc,
382 XEndArc,
383 YEndArc);
384
385 DC_UnlockDc( dc );
386 return Ret;
387 }
388