ReactOS  0.4.14-dev-50-g13bb5e2
arc.c
Go to the documentation of this file.
1 #include <win32k.h>
2 
3 #define NDEBUG
4 #include <debug.h>
5 
6 /*
7  * A couple of macros to fill a single pixel or a line
8  */
9 #define PUTPIXEL(x,y,BrushInst) \
10  ret = ret && IntEngLineTo(&psurf->SurfObj, \
11  (CLIPOBJ *)&dc->co, \
12  &BrushInst.BrushObject, \
13  x, y, (x)+1, y, \
14  &RectBounds, \
15  ROP2_TO_MIX(pdcattr->jROP2));
16 
17 #define PUTLINE(x1,y1,x2,y2,BrushInst) \
18  ret = ret && IntEngLineTo(&psurf->SurfObj, \
19  (CLIPOBJ *)&dc->co, \
20  &BrushInst.BrushObject, \
21  x1, y1, x2, y2, \
22  &RectBounds, \
23  ROP2_TO_MIX(pdcattr->jROP2));
24 
25 static
26 BOOL
29  int Left,
30  int Top,
31  int Right,
32  int Bottom,
33  int XRadialStart,
34  int YRadialStart,
35  int XRadialEnd,
36  int YRadialEnd,
37  ARCTYPE arctype)
38 {
39  PDC_ATTR pdcattr;
40  RECTL RectBounds, RectSEpts;
41  PBRUSH pbrPen;
42  SURFACE *psurf;
43  BOOL ret = TRUE;
44  LONG PenWidth, PenOrigWidth;
45  double AngleStart, AngleEnd;
46  LONG CenterX, CenterY;
47 
48  if (Right < Left)
49  {
50  INT tmp = Right; Right = Left; Left = tmp;
51  }
52  if (Bottom < Top)
53  {
54  INT tmp = Bottom; Bottom = Top; Top = tmp;
55  }
56 
57  /* Check if the target rect is empty */
58  if ((Left == Right) || (Top == Bottom)) return TRUE;
59 
60  // FIXME: this needs to be verified
61  if ((arctype == GdiTypeChord ) || (arctype == GdiTypePie))
62  {
63  if ((Right - Left == 1) || (Bottom - Top == 1))
64  return TRUE;
65  }
66 
67 
68  pdcattr = dc->pdcattr;
69 
70  pbrPen = PEN_ShareLockPen(pdcattr->hpen);
71  if (!pbrPen)
72  {
73  DPRINT1("Arc Fail 1\n");
75  return FALSE;
76  }
77 
78  PenOrigWidth = PenWidth = pbrPen->lWidth;
79  if (pbrPen->ulPenStyle == PS_NULL) PenWidth = 0;
80 
81  if (pbrPen->ulPenStyle == PS_INSIDEFRAME)
82  {
83  if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2;
84  if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2;
85  Left += PenWidth / 2;
86  Right -= (PenWidth - 1) / 2;
87  Top += PenWidth / 2;
88  Bottom -= (PenWidth - 1) / 2;
89  }
90 
91  if (!PenWidth) PenWidth = 1;
92  pbrPen->lWidth = PenWidth;
93 
94  RectBounds.left = Left;
95  RectBounds.right = Right;
96  RectBounds.top = Top;
97  RectBounds.bottom = Bottom;
98 
99  RectSEpts.left = XRadialStart;
100  RectSEpts.top = YRadialStart;
101  RectSEpts.right = XRadialEnd;
102  RectSEpts.bottom = YRadialEnd;
103 
104  IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
105  IntLPtoDP(dc, (LPPOINT)&RectSEpts, 2);
106 
107  RectBounds.left += dc->ptlDCOrig.x;
108  RectBounds.right += dc->ptlDCOrig.x;
109  RectBounds.top += dc->ptlDCOrig.y;
110  RectBounds.bottom += dc->ptlDCOrig.y;
111 
112  RectSEpts.left += dc->ptlDCOrig.x;
113  RectSEpts.top += dc->ptlDCOrig.y;
114  RectSEpts.right += dc->ptlDCOrig.x;
115  RectSEpts.bottom += dc->ptlDCOrig.y;
116 
117  DPRINT("1: StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
118  RectSEpts.left,RectSEpts.top,RectSEpts.right,RectSEpts.bottom);
119 
120  DPRINT("1: Left: %d, Top: %d, Right: %d, Bottom: %d\n",
121  RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom);
122 
123  CenterX = (RectBounds.right + RectBounds.left) / 2;
124  CenterY = (RectBounds.bottom + RectBounds.top) / 2;
125  AngleEnd = atan2((RectSEpts.bottom - CenterY), RectSEpts.right - CenterX)*(360.0/(M_PI*2));
126  AngleStart = atan2((RectSEpts.top - CenterY), RectSEpts.left - CenterX)*(360.0/(M_PI*2));
127 
128  /* Edge Case: Check if the start segments overlaps(is equal) the end segment */
129  if (AngleEnd == AngleStart)
130  {
131  AngleStart = AngleEnd + 360.0; // Arc(), ArcTo(), Pie() and Chord() are counterclockwise APIs.
132  }
133 
134  if ((arctype == GdiTypePie) || (arctype == GdiTypeChord))
135  {
136  ret = IntFillArc( dc,
137  RectBounds.left,
138  RectBounds.top,
139  abs(RectBounds.right-RectBounds.left), // Width
140  abs(RectBounds.bottom-RectBounds.top), // Height
141  AngleStart,
142  AngleEnd,
143  arctype);
144  }
145 
146  if(ret)
147  {
148  ret = IntDrawArc( dc,
149  RectBounds.left,
150  RectBounds.top,
151  abs(RectBounds.right-RectBounds.left), // Width
152  abs(RectBounds.bottom-RectBounds.top), // Height
153  AngleStart,
154  AngleEnd,
155  arctype,
156  pbrPen);
157  }
158 
159  psurf = dc->dclevel.pSurface;
160  if (NULL == psurf)
161  {
162  DPRINT1("Arc Fail 2\n");
163  PEN_ShareUnlockPen(pbrPen);
165  return FALSE;
166  }
167 
168  if (arctype == GdiTypePie)
169  {
170  PUTLINE(CenterX, CenterY, RectSEpts.left, RectSEpts.top, dc->eboLine);
171  PUTLINE(RectSEpts.right, RectSEpts.bottom, CenterX, CenterY, dc->eboLine);
172  }
173  if (arctype == GdiTypeChord)
174  PUTLINE(RectSEpts.right, RectSEpts.bottom, RectSEpts.left, RectSEpts.top, dc->eboLine);
175 
176  pbrPen->lWidth = PenOrigWidth;
177  PEN_ShareUnlockPen(pbrPen);
178  DPRINT("IntArc Exit.\n");
179  return ret;
180 }
181 
182 
185  ARCTYPE arctype,
186  DC *dc,
187  int LeftRect,
188  int TopRect,
189  int RightRect,
190  int BottomRect,
191  int XStartArc,
192  int YStartArc,
193  int XEndArc,
194  int YEndArc)
195 {
196  BOOL Ret;
197  //PDC_ATTR pdcattr;
198 
199  DPRINT("StartX: %d, StartY: %d, EndX: %d, EndY: %d\n",
200  XStartArc,YStartArc,XEndArc,YEndArc);
201  DPRINT("Left: %d, Top: %d, Right: %d, Bottom: %d\n",
202  LeftRect,TopRect,RightRect,BottomRect);
203 
204  if ((LeftRect == RightRect) || (TopRect == BottomRect)) return TRUE;
205 
206  if (PATH_IsPathOpen(dc->dclevel))
207  {
208  return PATH_Arc( dc,
209  LeftRect,
210  TopRect,
211  RightRect,
212  BottomRect,
213  XStartArc,
214  YStartArc,
215  XEndArc,
216  YEndArc,
217  0,
218  arctype);
219  }
220 
221  //pdcattr = dc->pdcattr;
222 
223  if (arctype == GdiTypeArcTo)
224  {
225  if (dc->dclevel.flPath & DCPATH_CLOCKWISE)
226  IntGdiLineTo(dc, XEndArc, YEndArc);
227  else
228  IntGdiLineTo(dc, XStartArc, YStartArc);
229  }
230 
231  Ret = IntArc( dc,
232  LeftRect,
233  TopRect,
234  RightRect,
235  BottomRect,
236  XStartArc,
237  YStartArc,
238  XEndArc,
239  YEndArc,
240  arctype);
241 
242  if (arctype == GdiTypeArcTo)
243  {
244  if (dc->dclevel.flPath & DCPATH_CLOCKWISE)
245  IntGdiMoveToEx(dc, XStartArc, YStartArc, NULL);
246  else
247  IntGdiMoveToEx(dc, XEndArc, YEndArc, NULL);
248  }
249  return Ret;
250 }
251 
252 BOOL
253 FASTCALL
255  INT x,
256  INT y,
257  DWORD dwRadius,
258  FLOAT eStartAngle,
259  FLOAT eSweepAngle)
260 {
261  INT x1, y1, x2, y2, arcdir;
262  BOOL result;
263 
264  /* Calculate the end point */
265  x2 = x + (INT)(cos(((eStartAngle+eSweepAngle)/360)*(M_PI*2)) * dwRadius);
266  y2 = y - (INT)(sin(((eStartAngle+eSweepAngle)/360)*(M_PI*2)) * dwRadius);
267 
268  x1 = x + (INT)(cos((eStartAngle/360)*(M_PI*2)) * dwRadius);
269  y1 = y - (INT)(sin((eStartAngle/360)*(M_PI*2)) * dwRadius);
270 
271  arcdir = pDC->dclevel.flPath & DCPATH_CLOCKWISE;
272  if (eSweepAngle >= 0)
273  pDC->dclevel.flPath &= ~DCPATH_CLOCKWISE;
274  else
275  pDC->dclevel.flPath |= DCPATH_CLOCKWISE;
276 
278  pDC,
279  x-dwRadius,
280  y-dwRadius,
281  x+dwRadius,
282  y+dwRadius,
283  x1,
284  y1,
285  x2,
286  y2 );
287 
288  pDC->dclevel.flPath |= (arcdir & DCPATH_CLOCKWISE);
289 
290  if (result)
291  {
292  IntGdiMoveToEx(pDC, x2, y2, NULL);
293  }
294  return result;
295 }
296 
297 /* FUNCTIONS *****************************************************************/
298 
299 BOOL
300 APIENTRY
302  IN HDC hDC,
303  IN INT x,
304  IN INT y,
305  IN DWORD dwRadius,
306  IN DWORD dwStartAngle,
307  IN DWORD dwSweepAngle)
308 {
309  DC *pDC;
310  BOOL Ret = FALSE;
311  gxf_long worker, worker1;
312  KFLOATING_SAVE FloatSave;
314 
315  pDC = DC_LockDc (hDC);
316  if(!pDC)
317  {
319  return FALSE;
320  }
321 
322  status = KeSaveFloatingPointState(&FloatSave);
323  if (!NT_SUCCESS(status))
324  {
325  DC_UnlockDc( pDC );
326  return FALSE;
327  }
328 
329  worker.l = dwStartAngle;
330  worker1.l = dwSweepAngle;
332  if (pDC->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
333  DC_vUpdateFillBrush(pDC);
334  if (pDC->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
335  DC_vUpdateLineBrush(pDC);
336  Ret = IntGdiAngleArc( pDC, x, y, dwRadius, worker.f, worker1.f);
337  DC_vFinishBlit(pDC, NULL);
338  DC_UnlockDc( pDC );
339 
340  KeRestoreFloatingPointState(&FloatSave);
341 
342  return Ret;
343 }
344 
345 BOOL
346 APIENTRY
348  ARCTYPE arctype,
349  HDC hDC,
350  int LeftRect,
351  int TopRect,
352  int RightRect,
353  int BottomRect,
354  int XStartArc,
355  int YStartArc,
356  int XEndArc,
357  int YEndArc)
358 {
359  DC *dc;
360  BOOL Ret;
361  KFLOATING_SAVE FloatSave;
363 
364  dc = DC_LockDc (hDC);
365  if(!dc)
366  {
368  return FALSE;
369  }
370  if (arctype > GdiTypePie)
371  {
372  DC_UnlockDc(dc);
374  return FALSE;
375  }
376 
378 
379  if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
381 
382  if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
384 
385  status = KeSaveFloatingPointState(&FloatSave);
386  if (!NT_SUCCESS(status))
387  {
388  DC_UnlockDc( dc );
389  return FALSE;
390  }
391 
392  Ret = IntGdiArcInternal(
393  arctype,
394  dc,
395  LeftRect,
396  TopRect,
397  RightRect,
398  BottomRect,
399  XStartArc,
400  YStartArc,
401  XEndArc,
402  YEndArc);
403 
404  KeRestoreFloatingPointState(&FloatSave);
406  DC_UnlockDc( dc );
407  return Ret;
408 }
409 
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG y1
Definition: winddi.h:3706
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
FLOAT f
Definition: ntgdityp.h:425
#define abs(i)
Definition: fconv.c:206
#define IN
Definition: typedefs.h:38
ULONG l
Definition: ntgdityp.h:426
#define TRUE
Definition: types.h:120
valarray< _Tp > atan2(const valarray< _Tp > &__x, const valarray< _Tp > &__y)
Definition: _valarray.h:928
VOID FASTCALL DC_vUpdateLineBrush(PDC pdc)
Definition: dcobjs.c:62
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:219
#define ERROR_INTERNAL_ERROR
Definition: winerror.h:840
BOOL FASTCALL IntDrawArc(PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype, PBRUSH pbrush)
Definition: drawing.c:1342
HANDLE hpen
Definition: ntgdihdl.h:300
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG x1
Definition: winddi.h:3706
#define DC_PEN_DIRTY
Definition: ntgdihdl.h:158
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
LONG NTSTATUS
Definition: precomp.h:26
#define INT
Definition: polytest.cpp:20
static HDC
Definition: imagelist.c:92
long bottom
Definition: polytest.cpp:53
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
HDC dc
Definition: cylfrac.c:34
#define FASTCALL
Definition: nt_native.h:50
int32_t INT
Definition: typedefs.h:56
BOOL FASTCALL IntFillArc(PDC dc, INT XLeft, INT YLeft, INT Width, INT Height, double StartArc, double EndArc, ARCTYPE arctype)
Definition: drawing.c:1306
long right
Definition: polytest.cpp:53
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
long top
Definition: polytest.cpp:53
_STLP_DECLSPEC complex< float > _STLP_CALL cos(const complex< float > &)
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
#define PUTLINE(x1, y1, x2, y2, BrushInst)
Definition: arc.c:17
long left
Definition: polytest.cpp:53
Definition: types.h:100
#define KeRestoreFloatingPointState(x)
Definition: kmixer.h:33
#define PATH_IsPathOpen(dclevel)
Definition: path.h:74
Definition: polytest.cpp:40
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOL FASTCALL IntGdiAngleArc(PDC pDC, INT x, INT y, DWORD dwRadius, FLOAT eStartAngle, FLOAT eSweepAngle)
Definition: arc.c:254
BOOL FASTCALL IntGdiArcInternal(ARCTYPE arctype, DC *dc, int LeftRect, int TopRect, int RightRect, int BottomRect, int XStartArc, int YStartArc, int XEndArc, int YEndArc)
Definition: arc.c:184
BOOL APIENTRY NtGdiArcInternal(ARCTYPE arctype, HDC hDC, int LeftRect, int TopRect, int RightRect, int BottomRect, int XStartArc, int YStartArc, int XEndArc, int YEndArc)
Definition: arc.c:347
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IntLPtoDP(pdc, ppt, count)
Definition: coord.h:7
int ret
#define DIRTY_FILL
Definition: ntgdihdl.h:145
#define KeSaveFloatingPointState(x)
Definition: kmixer.h:32
#define PEN_ShareUnlockPen(ppen)
Definition: pen.h:18
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG _In_ LONG y2
Definition: winddi.h:3706
#define PS_INSIDEFRAME
Definition: wingdi.h:592
static BOOL FASTCALL IntArc(DC *dc, int Left, int Top, int Right, int Bottom, int XRadialStart, int YRadialStart, int XRadialEnd, int YRadialEnd, ARCTYPE arctype)
Definition: arc.c:28
static HDC hDC
Definition: 3dtext.c:33
static LPHIST_ENTRY Bottom
Definition: history.c:54
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:237
BOOL FASTCALL IntGdiLineTo(DC *dc, int XEnd, int YEnd)
Definition: line.c:146
BOOL FASTCALL PATH_Arc(PDC dc, INT x1, INT y1, INT x2, INT y2, INT xStart, INT yStart, INT xEnd, INT yEnd, INT direction, INT lines)
Definition: path.c:902
enum _ARCTYPE ARCTYPE
#define M_PI
Definition: macros.h:263
#define PS_NULL
Definition: wingdi.h:590
#define DC_BRUSH_DIRTY
Definition: ntgdihdl.h:157
VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdcDest, const RECT *rcDest, PDC pdcSrc, const RECT *rcSrc)
Definition: dclife.c:505
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
_In_ CLIPOBJ _In_ BRUSHOBJ _In_ LONG _In_ LONG _In_ LONG x2
Definition: winddi.h:3706
#define DPRINT1
Definition: precomp.h:8
VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2)
Definition: dclife.c:614
float FLOAT
Definition: typedefs.h:67
BOOL FASTCALL IntGdiMoveToEx(DC *dc, int X, int Y, LPPOINT Point)
Definition: line.c:78
#define DIRTY_LINE
Definition: ntgdihdl.h:146
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
BOOL APIENTRY NtGdiAngleArc(IN HDC hDC, IN INT x, IN INT y, IN DWORD dwRadius, IN DWORD dwStartAngle, IN DWORD dwSweepAngle)
Definition: arc.c:301
PBRUSH FASTCALL PEN_ShareLockPen(HPEN hobj)
Definition: pen.c:61
GLuint64EXT * result
Definition: glext.h:11304
static SERVICE_STATUS status
Definition: service.c:31
static LPHIST_ENTRY Top
Definition: history.c:53
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
#define APIENTRY
Definition: api.h:79
VOID FASTCALL DC_vUpdateFillBrush(PDC pdc)
Definition: dcobjs.c:16
Definition: ps.c:97