4 This package includes software which is copyright (c) L. Patrick.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. You may not sell this software package.
17 4. You may include this software in a distribution of other software,
18 and you may charge a nominal fee for the media used.
19 5. You may sell derivative programs, providing that such programs
20 simply use this software in a compiled form.
21 6. You may sell derivative programs which use a compiled, modified
22 version of this software, provided that you have attempted as
23 best as you can to propagate all modifications made to the source
24 code files of this software package back to the original author(s)
27 THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS AS IS, AND
28 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
31 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 /* Copyright (c) L. Patrick
41 This file is part of the App cross-platform programming package.
42 You may redistribute it and/or modify it under the terms of the
43 App Software License. See the file LICENSE.TXT for details.
45 http://enchantia.com/software/graphapp/
46 http://www.it.usyd.edu.au/~graphapp/
53 #define _USE_MATH_DEFINES
60 #define DEGREES_TO_RADIANS(deg) ((deg)*2*M_PI/360)
64 int x
, y
; /* top-left point inside rect */
65 int width
, height
; /* width and height of rect */
68 int FASTCALL
IntFillRect(DC
*dc
, INT XLeft
, INT YLeft
, INT Width
, INT Height
, PBRUSH pbrush
, BOOL Pen
);
69 //int FASTCALL app_fill_rect(DC *dc, Rect r, PBRUSH pbrush, BOOL Pen);
74 app_new_point(int x
, int y
)
81 #define pt(x,y) app_new_point((x),(y))
86 rect(int x
, int y
, int width
, int height
)
98 * app_window_fill_rect:
100 * Fill a rectangle with colour, in a window.
102 * This function implements client-side clipping, so that
103 * we never rely on the GDI system to do clipping, except if
104 * the destination is a window which is partially obscured.
105 * In that situation we must rely on the GDI system because there
106 * is no way for the program to know which portions of the
107 * window are currently obscured.
109 #define app_fill_rect( dc, r, BrushObj, Pen) \
110 IntFillRect(dc, r.x, r.y, r.width, r.height, BrushObj, Pen)
113 * Drawing an ellipse with a certain line thickness.
114 * Use an inner and and outer ellipse and fill the spaces between.
115 * The inner ellipse uses all UPPERCASE letters, the outer lowercase.
117 * This algorithm is based on the fill_ellipse algorithm presented
118 * above, but uses two ellipse calculations, and some fix-up code
119 * to avoid pathological cases where the inner ellipse is almost
120 * the same size as the outer (in which case the border of the
121 * elliptical curve might otherwise have appeared broken).
126 app_draw_ellipse(DC
*g
, Rect r
, PBRUSH pbrush
)
128 /* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
131 int b
= r
.height
/ 2;
136 long xcrit
= (3 * a2
/ 4) + 1;
137 long ycrit
= (3 * b2
/ 4) + 1;
138 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
139 long dxt
= b2
*(3+x
+x
);
140 long dyt
= a2
*(3-y
-y
);
144 int w
= pbrush
->ptPenWidth
.x
;
146 /* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
148 int A
= a
-w
> 0 ? a
-w
: 0;
149 int B
= b
-w
> 0 ? b
-w
: 0;
154 long XCRIT
= (3 * A2
/ 4) + 1;
155 long YCRIT
= (3 * B2
/ 4) + 1;
156 long T
= B2
+ A2
- 2*A2
*B
; /* T = E(X+1,Y-1) */
157 long DXT
= B2
*(3+X
+X
);
158 long DYT
= A2
*(3-Y
-Y
);
162 int movedown
, moveout
;
163 int innerX
= 0, prevx
, prevy
, W
;
169 if ((r
.width
<= 2) || (r
.height
<= 2))
170 return app_fill_rect(g
, r
, pbrush
, TRUE
);
174 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
178 r2
.y
= r
.y
+ r
.height
- 1;
189 if (T
+ A2
*Y
< XCRIT
) /* E(X+1,Y-1/2) <= 0 */
191 /* move outwards to encounter edge */
196 else if (T
- B2
*X
>= YCRIT
) /* e(x+1/2,y-1) > 0 */
198 /* drop down one line */
205 /* drop diagonally down and out */
214 movedown
= moveout
= 0;
217 if (r1
.x
+ W
< prevx
)
222 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
224 /* move outwards to encounter edge */
231 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
233 /* drop down one line */
242 /* drop diagonally down and out */
266 if (r1
.width
> r
.width
)
267 r1
.width
= r2
.width
= r
.width
;
271 r1
.width
= r2
.width
= r
.width
;
274 if ((r1
.y
< r
.y
+w
) || (r1
.x
+W
>= r1
.x
+r1
.width
-W
))
276 result
&= app_fill_rect(g
, r1
, pbrush
, TRUE
);
277 result
&= app_fill_rect(g
, r2
, pbrush
, TRUE
);
282 else if (r1
.y
+r1
.height
< r2
.y
)
284 /* draw distinct rectangles */
285 result
&= app_fill_rect(g
, rect(r1
.x
,r1
.y
,
287 result
&= app_fill_rect(g
, rect(
288 r1
.x
+r1
.width
-W
,r1
.y
,W
,1), pbrush
, TRUE
);
289 result
&= app_fill_rect(g
, rect(r2
.x
,
290 r2
.y
,W
,1), pbrush
, TRUE
);
291 result
&= app_fill_rect(g
, rect(
292 r2
.x
+r2
.width
-W
,r2
.y
,W
,1), pbrush
, TRUE
);
312 if ((x
<= a
) && (prevy
< r2
.y
))
314 /* draw final line */
315 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
319 if (r
.x
+ W
!= prevx
)
326 result
&= app_fill_rect(g
, rect(r
.x
, r1
.y
,
327 r
.width
, r1
.height
), pbrush
, TRUE
);
331 result
&= app_fill_rect(g
, rect(r
.x
, r1
.y
, W
, r1
.height
), pbrush
, TRUE
);
332 result
&= app_fill_rect(g
, rect(r
.x
+r
.width
-W
, r1
.y
,
333 W
, r1
.height
), pbrush
, TRUE
);
339 * Draw an arc of an ellipse from start_angle anti-clockwise to
340 * end_angle. If the angles coincide, draw nothing; if they
341 * differ by 360 degrees or more, draw a full ellipse.
342 * The shape is drawn with the current line thickness,
343 * completely within the bounding rectangle. The shape is also
344 * axis-aligned, so that the ellipse would be horizontally and
345 * vertically symmetric is it was complete.
347 * The draw_arc algorithm is based on draw_ellipse, but unlike
348 * that algorithm is not symmetric in the general case, since
349 * an angular portion is clipped from the shape.
350 * This clipping is performed by keeping track of two hypothetical
351 * lines joining the centre point to the enclosing rectangle,
352 * at the angles start_angle and end_angle, using a line-intersection
353 * algorithm. Essentially the algorithm just fills the spaces
354 * which are within the arc and also between the angles, going
355 * in an anti-clockwise direction from start_angle to end_angle.
356 * In the top half of the ellipse, this amounts to drawing
357 * to the left of the start_angle line and to the right of
358 * the end_angle line, while in the bottom half of the ellipse,
359 * it involves drawing to the right of the start_angle and to
360 * the left of the end_angle.
364 * Fill a rectangle within an arc, given the centre point p0,
365 * and the two end points of the lines corresponding to the
366 * start_angle and the end_angle. This function takes care of
367 * the logic needed to swap the fill direction below
368 * the central point, and also performs the calculations
369 * needed to intersect the current Y value with each line.
374 app_fill_arc_rect(DC
*g
,
375 Rect r
, // top, left, width, height
385 int start_above
, end_above
;
386 long rise1
, run1
, rise2
, run2
;
395 /* in top half of arc ellipse */
399 /* start_line is in the top half and is */
400 /* intersected by the current Y scan line */
404 x1
= p0
.x
+ (r
.y
-p0
.y
)*run1
/rise1
;
407 else if ((start_angle
>= 0) && (start_angle
<= 180))
409 /* start_line is above middle */
415 /* start_line is below middle */
421 if (x1
> r
.x
+r
.width
)
426 /* end_line is in the top half and is */
427 /* intersected by the current Y scan line */
431 x2
= p0
.x
+ (r
.y
-p0
.y
)*run2
/rise2
;
434 else if ((end_angle
>= 0) && (end_angle
<= 180))
436 /* end_line is above middle */
442 /* end_line is below middle */
447 if (x2
< r
.x
) x2
= r
.x
;
449 if (x2
> r
.x
+r
.width
) x2
= r
.x
+r
.width
;
451 if (start_above
&& end_above
)
453 if (start_angle
> end_angle
)
455 /* fill outsides of wedge */
456 if (! app_fill_rect(g
, rect(r
.x
, r
.y
,
457 x1
-r
.x
, r
.height
), pbrush
, Pen
))
459 return app_fill_rect(g
, rect(x2
, r
.y
,
460 r
.x
+r
.width
-x2
, r
.height
), pbrush
, Pen
);
464 /* fill inside of wedge */
467 return app_fill_rect(g
, r
, pbrush
, Pen
);
470 else if (start_above
)
472 /* fill to the left of the start_line */
474 return app_fill_rect(g
, r
, pbrush
, Pen
);
478 /* fill right of end_line */
479 r
.width
= r
.x
+r
.width
-x2
;
481 return app_fill_rect(g
, r
, pbrush
, Pen
);
485 if (start_angle
> end_angle
)
486 return app_fill_rect(g
,r
, pbrush
, Pen
);
493 /* in lower half of arc ellipse */
497 /* start_line is in the lower half and is */
498 /* intersected by the current Y scan line */
502 x1
= p0
.x
+ (r
.y
-p0
.y
)*run1
/rise1
;
505 else if ((start_angle
>= 180) && (start_angle
<= 360))
507 /* start_line is below middle */
513 /* start_line is above middle */
519 if (x1
> r
.x
+r
.width
)
524 /* end_line is in the lower half and is */
525 /* intersected by the current Y scan line */
529 x2
= p0
.x
+ (r
.y
-p0
.y
)*run2
/rise2
;
532 else if ((end_angle
>= 180) && (end_angle
<= 360))
534 /* end_line is below middle */
540 /* end_line is above middle */
546 if (x2
> r
.x
+r
.width
)
549 if (start_above
&& end_above
)
551 if (start_angle
> end_angle
)
552 return app_fill_rect(g
,r
, pbrush
, Pen
);
556 else if (start_above
)
558 /* fill to the left of end_line */
560 return app_fill_rect(g
,r
, pbrush
, Pen
);
564 /* fill right of start_line */
565 r
.width
= r
.x
+r
.width
-x1
;
567 return app_fill_rect(g
,r
, pbrush
, Pen
);
571 if (start_angle
> end_angle
)
573 /* fill outsides of wedge */
574 if (! app_fill_rect(g
, rect(r
.x
, r
.y
,
575 x2
-r
.x
, r
.height
), pbrush
, Pen
))
577 return app_fill_rect(g
, rect(x1
, r
.y
,
578 r
.x
+r
.width
-x1
, r
.height
), pbrush
, Pen
);
582 /* fill inside of wedge */
585 return app_fill_rect(g
, r
, pbrush
, Pen
);
592 * To fill an axis-aligned ellipse, we use a scan-line algorithm.
593 * We walk downwards from the top Y co-ordinate, calculating
594 * the width of the ellipse using incremental integer arithmetic.
595 * To save calculation, we observe that the top and bottom halves
596 * of the ellipsoid are mirror-images, therefore we can draw the
597 * top and bottom halves by reflection. As a result, this algorithm
598 * draws rectangles inwards from the top and bottom edges of the
599 * bounding rectangle.
601 * To save rendering time, draw as few rectangles as possible.
602 * Other ellipse-drawing algorithms assume we want to draw each
603 * line, using a draw_pixel operation, or a draw_horizontal_line
604 * operation. This approach is slower than it needs to be in
605 * circumstances where a fill_rect operation is more efficient
606 * (such as in X-Windows, where there is a communication overhead
607 * to the X-Server). For this reason, the algorithm accumulates
608 * rectangles on adjacent lines which have the same width into a
609 * single larger rectangle.
611 * This algorithm forms the basis of the later, more complex,
612 * draw_ellipse algorithm, which renders the rectangular spaces
613 * between an outer and inner ellipse, and also the draw_arc and
614 * fill_arc operations which additionally clip drawing between
615 * a start_angle and an end_angle.
621 app_fill_ellipse(DC
*g
, Rect r
, PBRUSH pbrush
)
623 /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
626 int b
= r
.height
/ 2;
631 long xcrit
= (3 * a2
/ 4) + 1;
632 long ycrit
= (3 * b2
/ 4) + 1;
633 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
634 long dxt
= b2
*(3+x
+x
);
635 long dyt
= a2
*(3-y
-y
);
643 if ((r
.width
<= 2) || (r
.height
<= 2))
644 return app_fill_rect(g
, r
, pbrush
, FALSE
);
648 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
652 r2
.y
= r
.y
+ r
.height
- 1;
656 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
658 /* move outwards to encounter edge */
669 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
671 /* drop down one line */
676 /* enlarge rectangles */
683 /* drop diagonally down and out */
690 if ((r1
.width
> 0) && (r1
.height
> 0))
692 /* draw rectangles first */
694 if (r1
.y
+r1
.height
< r2
.y
)
696 /* distinct rectangles */
697 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
698 result
&= app_fill_rect(g
, r2
, pbrush
, FALSE
);
709 /* skipped pixels on initial diagonal */
711 /* enlarge, rather than moving down */
729 r1
.height
= r2
.y
+r2
.height
-r1
.y
;
730 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
734 /* crossover, draw final line */
737 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
739 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
747 app_boundary_point(Rect r
, int angle
)
761 return pt(r
.x
+r
.width
, cy
);
762 else if (angle
== 45)
763 return pt(r
.x
+r
.width
, r
.y
);
764 else if (angle
== 90)
766 else if (angle
== 135)
768 else if (angle
== 180)
770 else if (angle
== 225)
771 return pt(r
.x
, r
.y
+r
.height
);
772 else if (angle
== 270)
773 return pt(cx
, r
.y
+r
.height
);
774 else if (angle
== 315)
775 return pt(r
.x
+r
.width
, r
.y
+r
.height
);
777 tangent
= tan(DEGREES_TO_RADIANS(angle
));
779 if ((angle
> 45) && (angle
< 135))
780 return pt((int)(cx
+r
.height
/tangent
/2), r
.y
);
781 else if ((angle
> 225) && (angle
< 315))
782 return pt((int)(cx
-r
.height
/tangent
/2), r
.y
+r
.height
);
783 else if ((angle
> 135) && (angle
< 225))
784 return pt(r
.x
, (int)(cy
+r
.width
*tangent
/2));
786 return pt(r
.x
+r
.width
, (int)(cy
-r
.width
*tangent
/2));
791 app_fill_arc(DC
*g
, Rect r
, int start_angle
, int end_angle
, PBRUSH pbrush
, BOOL Chord
)
793 /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
796 int b
= r
.height
/ 2;
801 long xcrit
= (3 * a2
/ 4) + 1;
802 long ycrit
= (3 * b2
/ 4) + 1;
803 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
804 long dxt
= b2
*(3+x
+x
);
805 long dyt
= a2
*(3-y
-y
);
809 int movedown
, moveout
;
812 /* line descriptions */
817 /* if angles differ by 360 degrees or more, close the shape */
818 if ((start_angle
+ 360 <= end_angle
) ||
819 (start_angle
- 360 >= end_angle
))
821 return app_fill_ellipse(g
, r
, pbrush
);
824 /* make start_angle >= 0 and <= 360 */
825 while (start_angle
< 0)
829 /* make end_angle >= 0 and <= 360 */
830 while (end_angle
< 0)
834 /* draw nothing if the angles are equal */
835 if (start_angle
== end_angle
)
838 /* find arc wedge line end points */
839 p1
= app_boundary_point(r
, start_angle
);
840 p2
= app_boundary_point(r
, end_angle
);
842 p0
= pt((p1
.x
+p2
.x
)/2,(p1
.y
+p2
.y
)/2);
844 p0
= pt(r
.x
+ r
.width
/2, r
.y
+ r
.height
/2);
846 /* initialise rectangles to be drawn */
849 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
853 r2
.y
= r
.y
+ r
.height
- 1;
857 moveout
= movedown
= 0;
859 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
861 /* move outwards to encounter edge */
868 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
870 /* drop down one line */
879 /* drop diagonally down and out */
903 if (r1
.width
> r
.width
)
904 r1
.width
= r2
.width
= r
.width
;
908 r1
.width
= r2
.width
= r
.width
;
911 if ((r1
.width
> 0) && (r1
.y
+r1
.height
< r2
.y
))
913 /* distinct rectangles */
914 result
&= app_fill_arc_rect(g
, r1
,
916 start_angle
, end_angle
, pbrush
, FALSE
);
917 result
&= app_fill_arc_rect(g
, r2
,
919 start_angle
, end_angle
, pbrush
, FALSE
);
941 r1
.height
= r2
.y
+r2
.height
-r1
.y
;
942 while (r1
.height
> 0)
944 result
&= app_fill_arc_rect(g
,
945 rect(r1
.x
, r1
.y
, r1
.width
, 1),
946 p0
, p1
, p2
, start_angle
, end_angle
, pbrush
, FALSE
);
953 /* crossover, draw final line */
956 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
958 while (r1
.height
> 0)
960 result
&= app_fill_arc_rect(g
,
961 rect(r1
.x
, r1
.y
, r1
.width
, 1),
962 p0
, p1
, p2
, start_angle
, end_angle
, pbrush
, FALSE
);
970 int app_draw_arc(DC
*g
, Rect r
, int start_angle
, int end_angle
, PBRUSH pbrushPen
, BOOL Chord
)
972 /* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
975 int b
= r
.height
/ 2;
980 long xcrit
= (3 * a2
/ 4) + 1;
981 long ycrit
= (3 * b2
/ 4) + 1;
982 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
983 long dxt
= b2
*(3+x
+x
);
984 long dyt
= a2
*(3-y
-y
);
988 int w
= pbrushPen
->ptPenWidth
.x
;
990 /* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
992 int A
= a
-w
> 0 ? a
-w
: 0;
993 int B
= b
-w
> 0 ? b
-w
: 0;
998 long XCRIT
= (3 * A2
/ 4) + 1;
999 long YCRIT
= (3 * B2
/ 4) + 1;
1000 long T
= B2
+ A2
- 2*A2
*B
; /* T = E(X+1,Y-1) */
1001 long DXT
= B2
*(3+X
+X
);
1002 long DYT
= A2
*(3-Y
-Y
);
1006 /* arc rectangle calculations */
1007 int movedown
, moveout
;
1008 int innerX
= 0, prevx
, prevy
, W
;
1012 /* line descriptions */
1017 /* if angles differ by 360 degrees or more, close the shape */
1018 if ((start_angle
+ 360 <= end_angle
) ||
1019 (start_angle
- 360 >= end_angle
))
1021 return app_draw_ellipse(g
, r
, pbrushPen
);
1024 /* make start_angle >= 0 and <= 360 */
1025 while (start_angle
< 0)
1029 /* make end_angle >= 0 and <= 360 */
1030 while (end_angle
< 0)
1034 /* draw nothing if the angles are equal */
1035 if (start_angle
== end_angle
)
1038 /* find arc wedge line end points */
1039 p1
= app_boundary_point(r
, start_angle
);
1040 p2
= app_boundary_point(r
, end_angle
);
1042 p0
= pt((p1
.x
+p2
.x
)/2,(p1
.y
+p2
.y
)/2);
1044 p0
= pt(r
.x
+ r
.width
/2, r
.y
+ r
.height
/2);
1046 /* determine ellipse rectangles */
1049 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
1053 r2
.y
= r
.y
+ r
.height
- 1;
1064 if (T
+ A2
*Y
< XCRIT
) /* E(X+1,Y-1/2) <= 0 */
1066 /* move outwards to encounter edge */
1071 else if (T
- B2
*X
>= YCRIT
) /* e(x+1/2,y-1) > 0 */
1073 /* drop down one line */
1080 /* drop diagonally down and out */
1089 movedown
= moveout
= 0;
1092 if (r1
.x
+ W
< prevx
)
1097 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
1099 /* move outwards to encounter edge */
1106 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
1108 /* drop down one line */
1117 /* drop diagonally down and out */
1141 if (r1
.width
> r
.width
)
1142 r1
.width
= r2
.width
= r
.width
;
1146 r1
.width
= r2
.width
= r
.width
;
1149 if ((r1
.y
< r
.y
+w
) || (r1
.x
+W
>= r1
.x
+r1
.width
-W
))
1151 result
&= app_fill_arc_rect(g
, r1
,
1153 start_angle
, end_angle
, pbrushPen
, TRUE
);
1154 result
&= app_fill_arc_rect(g
, r2
,
1156 start_angle
, end_angle
, pbrushPen
, TRUE
);
1161 else if (r1
.y
+r1
.height
< r2
.y
)
1163 /* draw distinct rectangles */
1164 result
&= app_fill_arc_rect(g
, rect(
1167 start_angle
, end_angle
, pbrushPen
, TRUE
);
1168 result
&= app_fill_arc_rect(g
, rect(
1169 r1
.x
+r1
.width
-W
,r1
.y
,W
,1),
1171 start_angle
, end_angle
, pbrushPen
, TRUE
);
1172 result
&= app_fill_arc_rect(g
, rect(
1175 start_angle
, end_angle
, pbrushPen
, TRUE
);
1176 result
&= app_fill_arc_rect(g
, rect(
1177 r2
.x
+r2
.width
-W
,r2
.y
,W
,1),
1179 start_angle
, end_angle
, pbrushPen
, TRUE
);
1199 if ((x
<= a
) && (prevy
< r2
.y
))
1201 /* draw final lines */
1202 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
1206 if (r
.x
+ W
!= prevx
)
1213 while (r1
.height
> 0)
1215 result
&= app_fill_arc_rect(g
, rect(r
.x
,
1216 r1
.y
, r
.width
, 1), p0
, p1
, p2
,
1217 start_angle
, end_angle
, pbrushPen
, TRUE
);
1224 while (r1
.height
> 0)
1226 result
&= app_fill_arc_rect(g
, rect(r
.x
, r1
.y
,
1228 start_angle
, end_angle
, pbrushPen
, TRUE
);
1229 result
&= app_fill_arc_rect(g
, rect(r
.x
+r
.width
-W
,
1230 r1
.y
, W
, 1), p0
, p1
, p2
,
1231 start_angle
, end_angle
, pbrushPen
, TRUE
);
1240 /* ReactOS Interface *********************************************************/
1244 IntFillRect( DC
*dc
,
1252 DWORD ROP
= ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY
);
1261 psurf
= dc
->dclevel
.pSurface
;
1264 EngSetLastError(ERROR_INVALID_HANDLE
);
1268 if (!(pbrush
->flAttrs
& GDIBRUSH_IS_NULL
))
1270 pdcattr
= dc
->pdcattr
;
1272 /* fix negative spaces */
1281 Height
= 0 - Height
;
1284 DestRect
.left
= XLeft
;
1285 DestRect
.right
= XLeft
+ Width
;
1287 DestRect
.top
= YLeft
;
1288 DestRect
.bottom
= YLeft
+ Height
;
1290 BrushOrigin
.x
= pbrush
->ptOrigin
.x
;
1291 BrushOrigin
.y
= pbrush
->ptOrigin
.y
;
1293 if (pdcattr
->jROP2
== R2_XORPEN
)
1294 ROP
= ROP4_FROM_INDEX(R3_OPINDEX_PATINVERT
);
1300 dc
->rosdc
.CombinedClip
,
1305 Pen
? &dc
->eboLine
.BrushObject
: &dc
->eboFill
.BrushObject
,
1326 int Start
= ceil(StartArc
);
1327 int End
= ceil(EndArc
);
1328 BOOL Chord
= (arctype
== GdiTypeChord
), ret
;
1330 pdcattr
= dc
->pdcattr
;
1332 pbrush
= BRUSH_LockBrush(pdcattr
->hbrush
);
1335 DPRINT1("FillArc Fail\n");
1336 EngSetLastError(ERROR_INTERNAL_ERROR
);
1339 // Sort out alignment here.
1340 ret
= app_fill_arc(dc
, rect( XLeft
, YLeft
, Width
, Height
),
1341 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -End
: -Start
,
1342 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -Start
: -End
,
1345 BRUSH_UnlockBrush(pbrush
);
1361 int Start
= ceil(StartArc
);
1362 int End
= ceil(EndArc
);
1363 BOOL Chord
= (arctype
== GdiTypeChord
);
1364 // Sort out alignment here.
1365 return app_draw_arc(dc
, rect( XLeft
, YLeft
, Width
, Height
),
1366 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -End
: -Start
,
1367 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -Start
: -End
,
1373 IntDrawEllipse( PDC dc
,
1380 return (BOOL
)app_draw_ellipse(dc
, rect( XLeft
, YLeft
, Width
, Height
), pbrush
);
1385 IntFillEllipse( PDC dc
,
1392 return (BOOL
)app_fill_ellipse(dc
, rect( XLeft
, YLeft
, Width
, Height
), pbrush
);
1397 IntFillRoundRect( PDC dc
,
1407 int rx
, ry
; /* radius in x and y directions */
1410 r
= rect( Left
, Top
, abs(Right
-Left
), abs(Bottom
-Top
));
1414 if (Wellipse
> r
.width
)
1416 if (Hellipse
> r
.height
) // > W > H
1417 app_fill_ellipse(dc
, r
, pbrush
);
1420 app_fill_arc(dc
, rect( r
.x
, r
.y
, r
.width
- 1, Hellipse
),
1421 0, 180, pbrush
,FALSE
);
1422 app_fill_arc(dc
, rect(r
.x
, Bottom
- Hellipse
- 1, r
.width
- 1, Hellipse
),
1423 180, 360, pbrush
, FALSE
);
1426 else if(Hellipse
> r
.height
) // < W > H
1428 app_fill_arc(dc
, rect(r
.x
, r
.y
, Wellipse
, r
.height
- 1),
1429 90, 270, pbrush
, FALSE
);
1430 app_fill_arc(dc
, rect(Right
- Wellipse
- 1, r
.y
, Wellipse
, r
.height
- 1),
1431 270, 90, pbrush
,FALSE
);
1435 app_fill_arc(dc
, rect(r
.x
, r
.y
, rx
+rx
, ry
+ry
),
1436 90, 180, pbrush
, FALSE
);
1438 app_fill_arc(dc
, rect(r
.x
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1439 180, 270, pbrush
, FALSE
);
1441 app_fill_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1442 270, 360, pbrush
,FALSE
);
1444 app_fill_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
, rx
+rx
, ry
+ry
),
1445 0, 90, pbrush
,FALSE
);
1447 if (Wellipse
< r
.width
)
1449 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
, r
.width
-rx
-rx
, ry
+1), pbrush
, FALSE
);
1450 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
+r
.height
-ry
+1, r
.width
-rx
-rx
, ry
-1), pbrush
, FALSE
);
1452 if (Hellipse
< r
.height
)
1454 app_fill_rect(dc
, rect(r
.x
, r
.y
+ry
+1, r
.width
, r
.height
-ry
-ry
), pbrush
, FALSE
);
1463 IntDrawRoundRect( PDC dc
,
1473 int rx
, ry
; /* radius in x and y directions */
1474 int w
= pbrushPen
->ptPenWidth
.x
;
1476 r
= rect( Left
, Top
, abs(Right
-Left
), abs(Bottom
-Top
));
1480 if (Wellipse
> r
.width
)
1482 if (Hellipse
> r
.height
) // > W > H
1483 app_draw_ellipse(dc
, r
, pbrushPen
);
1486 app_draw_arc(dc
, rect( r
.x
, r
.y
, r
.width
- 1, Hellipse
- 1),
1487 0, 180, pbrushPen
, FALSE
);
1488 app_draw_arc(dc
, rect(r
.x
, Bottom
- Hellipse
, r
.width
- 1, Hellipse
- 1),
1489 180, 360, pbrushPen
, FALSE
);
1492 else if(Hellipse
> r
.height
) // < W > H
1494 app_draw_arc(dc
, rect(r
.x
, r
.y
, Wellipse
- 1, r
.height
- 1),
1495 90, 270, pbrushPen
, FALSE
);
1496 app_draw_arc(dc
, rect(Right
- Wellipse
, r
.y
, Wellipse
- 1, r
.height
- 1),
1497 270, 90, pbrushPen
, FALSE
);
1501 app_draw_arc(dc
, rect(r
.x
, r
.y
, rx
+rx
, ry
+ry
),
1502 90, 180, pbrushPen
, FALSE
);
1504 app_draw_arc(dc
, rect(r
.x
,r
.y
+r
.height
-ry
-ry
,rx
+rx
,ry
+ry
),
1505 180, 270, pbrushPen
, FALSE
);
1507 app_draw_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1508 270, 360, pbrushPen
, FALSE
);
1510 app_draw_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
,r
.y
,rx
+rx
,ry
+ry
),
1511 0, 90, pbrushPen
, FALSE
);
1513 if ( Hellipse
< r
.height
)
1515 app_fill_rect(dc
, rect(r
.x
, r
.y
+ry
+1, w
, r
.height
-ry
-ry
), pbrushPen
, TRUE
);
1518 app_fill_rect(dc
, rect(r
.x
+r
.width
-w
, r
.y
+ry
+1, w
, r
.height
-ry
-ry
),
1521 if ( Wellipse
< r
.width
)
1523 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
+r
.height
-w
, r
.width
-rx
-rx
, w
),
1526 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
, r
.width
-rx
-rx
, w
), pbrushPen
, TRUE
);