7 typedef struct tagSHAPEPOINT
12 } SHAPEPOINT
, *PSHAPEPOINT
;
14 #define SHAPEPOINT_TYPE_CIRCLE 'C'
15 #define SHAPEPOINT_TYPE_LINE_RIGHT 'R' /* Fill at right side of line */
16 #define SHAPEPOINT_TYPE_LINE_LEFT 'L' /* Fill at left side of line */
18 #define SETPOINT(x, y, type) \
19 ShapePoints[*PointCount].X = (x); \
20 ShapePoints[*PointCount].Y = (y); \
21 ShapePoints[*PointCount].Type = (type); \
24 #define SETCIRCLEPOINT(x, y) \
25 SETPOINT(x, y, SHAPEPOINT_TYPE_CIRCLE)
30 CirclePoints(UINT
*PointCount
, PSHAPEPOINT ShapePoints
, int Left
, int Top
,
31 int Right
, int Bottom
)
33 int X
, X18
, X27
, X36
, X45
;
34 int Y
, Y14
, Y23
, Y58
, Y67
;
38 Even
= (0 == (Right
- Left
) % 2);
41 Radius
= (Right
- Left
) >> 1;
49 X27
= ((Left
+ Right
) >> 1) + 1;
50 X36
= (Left
+ Right
) >> 1;
54 Y58
= Top
+ Radius
+ 1;
55 Y67
= Top
+ (Right
- Left
);
56 ShapePoints
[*PointCount
].X
= X27
;
57 SETCIRCLEPOINT(X27
, Y23
);
58 SETCIRCLEPOINT(X36
, Y23
);
59 SETCIRCLEPOINT(X18
, Y14
);
60 SETCIRCLEPOINT(X45
, Y14
);
61 SETCIRCLEPOINT(X18
, Y58
);
62 SETCIRCLEPOINT(X45
, Y58
);
63 SETCIRCLEPOINT(X27
, Y67
);
64 SETCIRCLEPOINT(X36
, Y67
);
72 X27
= (Left
+ Right
) >> 1;
73 X36
= (Left
+ Right
) >> 1;
78 Y67
= Top
+ (Right
- Left
);
79 SETCIRCLEPOINT(X27
, Y23
);
80 SETCIRCLEPOINT(X45
, Y14
);
81 SETCIRCLEPOINT(X18
, Y58
);
82 SETCIRCLEPOINT(X27
, Y67
);
89 d
+= (X
<< 1) + (Even
? 4 : 3);
98 d
+= ((X
- Y
) << 1) + 5;
112 SETCIRCLEPOINT(X27
, Y23
);
113 SETCIRCLEPOINT(X36
, Y23
);
114 SETCIRCLEPOINT(X18
, Y14
);
115 SETCIRCLEPOINT(X45
, Y14
);
116 SETCIRCLEPOINT(X18
, Y58
);
117 SETCIRCLEPOINT(X45
, Y58
);
118 SETCIRCLEPOINT(X27
, Y67
);
119 SETCIRCLEPOINT(X36
, Y67
);
124 LinePoints(UINT
*PointCount
, PSHAPEPOINT ShapePoints
, int Left
, int Top
,
125 int Right
, int Bottom
, int XTo
, int YTo
, BOOL Start
)
127 LONG x
, y
, deltax
, deltay
, i
, xchange
, ychange
, error
;
130 x
= (Right
+ Left
) >> 1;
131 y
= (Bottom
+ Top
) >> 1;
151 Type
= (Start
? SHAPEPOINT_TYPE_LINE_LEFT
: SHAPEPOINT_TYPE_LINE_RIGHT
);
156 Type
= (Start
? SHAPEPOINT_TYPE_LINE_RIGHT
: SHAPEPOINT_TYPE_LINE_LEFT
);
161 for (i
= x
; i
<= XTo
; i
++)
163 SETPOINT(i
, y
, Type
);
168 for (i
= y
; i
<= YTo
; i
++)
170 SETPOINT(x
, i
, Type
);
179 for (i
= 0; i
< deltay
; i
++)
181 SETPOINT(x
, y
, Type
);
183 error
= error
+ deltax
;
188 error
= error
- deltay
;
194 for (i
= 0; i
< deltax
; i
++)
196 SETPOINT(x
, y
, Type
);
198 error
= error
+ deltay
;
202 error
= error
- deltax
;
211 CompareShapePoints(const void *pv1
, const void *pv2
)
213 if (((const PSHAPEPOINT
) pv1
)->Y
< ((const PSHAPEPOINT
) pv2
)->Y
)
217 else if (((const PSHAPEPOINT
) pv2
)->Y
< ((const PSHAPEPOINT
) pv1
)->Y
)
221 else if (((const PSHAPEPOINT
) pv1
)->X
< ((const PSHAPEPOINT
) pv2
)->X
)
225 else if (((const PSHAPEPOINT
) pv2
)->X
< ((const PSHAPEPOINT
) pv1
)->X
)
254 BRUSHOBJ PenBrushObj
;
255 PBRUSHOBJ FillBrushObj
;
256 PSHAPEPOINT ShapePoints
;
257 UINT Point
, PointCount
;
259 int Y
, CircleStart
, CircleEnd
, LineStart
, LineEnd
;
262 if (Right
<= Left
|| Bottom
<= Top
)
264 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
268 if (Right
- Left
!= Bottom
- Top
)
273 dc
= DC_LockDc ( hDC
);
276 SetLastWin32Error(ERROR_INVALID_HANDLE
);
279 if (dc
->DC_Type
== DC_TYPE_INFO
)
282 /* Yes, Windows really returns TRUE in this case */
286 Dc_Attr
= dc
->pDc_Attr
;
287 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
289 FillBrushObj
= BRUSHOBJ_LockBrush(Dc_Attr
->hbrush
);
290 if (NULL
== FillBrushObj
)
293 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
297 Left
+= dc
->ptlDCOrig
.x
;
298 Right
+= dc
->ptlDCOrig
.x
;
299 Top
+= dc
->ptlDCOrig
.y
;
300 Bottom
+= dc
->ptlDCOrig
.y
;
301 XRadialStart
+= dc
->ptlDCOrig
.x
;
302 YRadialStart
+= dc
->ptlDCOrig
.y
;
303 XRadialEnd
+= dc
->ptlDCOrig
.x
;
304 YRadialEnd
+= dc
->ptlDCOrig
.y
;
306 RectBounds
.left
= Left
;
307 RectBounds
.right
= Right
;
308 RectBounds
.top
= Top
;
309 RectBounds
.bottom
= Bottom
;
311 SurfObj
= (SURFOBJ
*) AccessUserObject((ULONG
)dc
->Surface
);
312 HPenToBrushObj(&PenBrushObj
, Dc_Attr
->hpen
);
314 /* Number of points for the circle is 4 * sqrt(2) * Radius, start
315 and end line have at most Radius points, so allocate at least
317 ShapePoints
= ExAllocatePoolWithTag(PagedPool
, 8 * (Right
- Left
+ 1) / 2 * sizeof(SHAPEPOINT
), TAG_SHAPE
);
318 if (NULL
== ShapePoints
)
320 BRUSHOBJ_UnlockBrush(FillBrushObj
);
323 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
329 PUTPIXEL(Left
, Top
, &PenBrushObj
);
330 BRUSHOBJ_UnlockBrush(FillBrushObj
);
337 CirclePoints(&PointCount
, ShapePoints
, Left
, Top
, Right
, Bottom
);
338 LinePoints(&PointCount
, ShapePoints
, Left
, Top
, Right
, Bottom
,
339 XRadialStart
, YRadialStart
, TRUE
);
340 LinePoints(&PointCount
, ShapePoints
, Left
, Top
, Right
, Bottom
,
341 XRadialEnd
, YRadialEnd
, FALSE
);
342 ASSERT(PointCount
<= 8 * (Right
- Left
+ 1) / 2);
343 EngSort((PBYTE
) ShapePoints
, sizeof(SHAPEPOINT
), PointCount
, CompareShapePoints
);
347 while (Point
< PointCount
)
349 Y
= ShapePoints
[Point
].Y
;
351 /* Skip any line pixels before circle */
352 while (Point
< PointCount
&& ShapePoints
[Point
].Y
== Y
353 && SHAPEPOINT_TYPE_CIRCLE
!= ShapePoints
[Point
].Type
)
358 /* Handle left side of circle */
359 if (Point
< PointCount
&& ShapePoints
[Point
].Y
== Y
)
361 CircleStart
= ShapePoints
[Point
].X
;
363 while (Point
< PointCount
&& ShapePoints
[Point
].Y
== Y
364 && ShapePoints
[Point
].X
== ShapePoints
[Point
- 1].X
+ 1
365 && SHAPEPOINT_TYPE_CIRCLE
== ShapePoints
[Point
].Type
)
369 CircleEnd
= ShapePoints
[Point
- 1].X
;
371 PUTLINE(CircleStart
, Y
, CircleEnd
+ 1, Y
, &PenBrushObj
);
374 /* Handle line(s) (max 2) inside the circle */
375 while (Point
< PointCount
&& ShapePoints
[Point
].Y
== Y
376 && SHAPEPOINT_TYPE_CIRCLE
!= ShapePoints
[Point
].Type
)
378 LineStart
= ShapePoints
[Point
].X
;
380 while (Point
< PointCount
&& ShapePoints
[Point
].Y
== Y
381 && ShapePoints
[Point
].X
== ShapePoints
[Point
- 1].X
+ 1
382 && ShapePoints
[Point
].Type
== ShapePoints
[Point
- 1].Type
)
386 LineEnd
= ShapePoints
[Point
- 1].X
;
388 PUTLINE(LineStart
, Y
, LineEnd
+ 1, Y
, &PenBrushObj
);
391 /* Handle right side of circle */
392 while (Point
< PointCount
&& ShapePoints
[Point
].Y
== Y
393 && SHAPEPOINT_TYPE_CIRCLE
== ShapePoints
[Point
].Type
)
395 CircleStart
= ShapePoints
[Point
].X
;
397 while (Point
< PointCount
&& ShapePoints
[Point
].Y
== Y
398 && ShapePoints
[Point
].X
== ShapePoints
[Point
- 1].X
+ 1
399 && SHAPEPOINT_TYPE_CIRCLE
== ShapePoints
[Point
].Type
)
403 CircleEnd
= ShapePoints
[Point
- 1].X
;
405 PUTLINE(CircleStart
, Y
, CircleEnd
+ 1, Y
, &PenBrushObj
);
408 /* Skip any line pixels after circle */
409 while (Point
< PointCount
&& ShapePoints
[Point
].Y
== Y
)
415 ExFreePool(ShapePoints
);
416 BRUSHOBJ_UnlockBrush(FillBrushObj
);
427 IntArc( DC
*dc
, int LeftRect
, int TopRect
, int RightRect
, int BottomRect
,
428 int XStartArc
, int YStartArc
, int XEndArc
, int YEndArc
, ARCTYPE arctype
)
449 if(PATH_IsPathOpen(dc
->w
.path
))
452 if (arctype
== GdiTypeArcTo
) type
= GdiTypeArc
;
453 return PATH_Arc(dc
, LeftRect
, TopRect
, RightRect
, BottomRect
,
454 XStartArc
, YStartArc
, XEndArc
, YEndArc
, type
);
457 IntGdiSetRect(&rc
, LeftRect
, TopRect
, RightRect
, BottomRect
);
458 IntGdiSetRect(&rc1
, XStartArc
, YStartArc
, XEndArc
, YEndArc
);
460 rx
= (rc
.right
- rc
.left
)/2 - 1;
461 ry
= (rc
.bottom
- rc
.top
)/2 -1;
465 return IntArc( dc
, rc
.left
, rc
.top
, rx
, ry
,
466 rc1
.left
, rc1
.top
, rc1
.right
, rc1
.bottom
, arctype
);
486 dc
= DC_LockDc (hDC
);
489 SetLastWin32Error(ERROR_INVALID_HANDLE
);
492 if (dc
->DC_Type
== DC_TYPE_INFO
)
495 /* Yes, Windows really returns TRUE in this case */
499 if (arctype
== GdiTypeArcTo
)
501 // Line from current position to starting point of arc
502 if ( !IntGdiLineTo(dc
, XStartArc
, YStartArc
) )
509 Ret
= IntGdiArcInternal(
521 if (arctype
== GdiTypeArcTo
)
523 // If no error occured, the current position is moved to the ending point of the arc.
525 IntGdiMoveToEx(dc
, XEndArc
, YEndArc
, NULL
);