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/
58 #define DEGREES_TO_RADIANS(deg) ((deg)*2*M_PI/360)
62 int x
, y
; /* Top-left point inside rect */
63 int width
, height
; /* Width and height of rect */
66 int FASTCALL
IntFillRect(DC
*dc
, INT XLeft
, INT YLeft
, INT Width
, INT Height
, PBRUSH pbrush
, BOOL Pen
);
67 //int FASTCALL app_fill_rect(DC *dc, Rect r, PBRUSH pbrush, BOOL Pen);
72 app_new_point(int x
, int y
)
79 #define pt(x,y) app_new_point((x),(y))
84 rect(int x
, int y
, int width
, int height
)
96 * app_window_fill_rect:
98 * Fill a rectangle with colour, in a window.
100 * This function implements client-side clipping, so that
101 * we never rely on the GDI system to do clipping, except if
102 * the destination is a window which is partially obscured.
103 * In that situation we must rely on the GDI system because there
104 * is no way for the program to know which portions of the
105 * window are currently obscured.
107 #define app_fill_rect( dc, r, BrushObj, Pen) \
108 IntFillRect(dc, r.x, r.y, r.width, r.height, BrushObj, Pen)
111 * Drawing an ellipse with a certain line thickness.
112 * Use an inner and and outer ellipse and fill the spaces between.
113 * The inner ellipse uses all UPPERCASE letters, the outer lowercase.
115 * This algorithm is based on the fill_ellipse algorithm presented
116 * above, but uses two ellipse calculations, and some fix-up code
117 * to avoid pathological cases where the inner ellipse is almost
118 * the same size as the outer (in which case the border of the
119 * elliptical curve might otherwise have appeared broken).
124 app_draw_ellipse(DC
*g
, Rect r
, PBRUSH pbrush
)
126 /* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
129 int b
= r
.height
/ 2;
134 long xcrit
= (3 * a2
/ 4) + 1;
135 long ycrit
= (3 * b2
/ 4) + 1;
136 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
137 long dxt
= b2
*(3+x
+x
);
138 long dyt
= a2
*(3-y
-y
);
142 int w
= pbrush
->lWidth
;
144 /* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
146 int A
= a
-w
> 0 ? a
-w
: 0;
147 int B
= b
-w
> 0 ? b
-w
: 0;
152 long XCRIT
= (3 * A2
/ 4) + 1;
153 long YCRIT
= (3 * B2
/ 4) + 1;
154 long T
= B2
+ A2
- 2*A2
*B
; /* T = E(X+1,Y-1) */
155 long DXT
= B2
*(3+X
+X
);
156 long DYT
= A2
*(3-Y
-Y
);
160 int movedown
, moveout
;
161 int innerX
= 0, prevx
, prevy
, W
;
165 if ((r
.width
<= 2) || (r
.height
<= 2))
166 return app_fill_rect(g
, r
, pbrush
, TRUE
);
170 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
174 r2
.y
= r
.y
+ r
.height
- 1;
185 if (T
+ A2
*Y
< XCRIT
) /* E(X+1,Y-1/2) <= 0 */
187 /* Move outwards to encounter edge */
192 else if (T
- B2
*X
>= YCRIT
) /* e(x+1/2,y-1) > 0 */
194 /* Drop down one line */
201 /* Drop diagonally down and out */
210 movedown
= moveout
= 0;
213 if (r1
.x
+ W
< prevx
)
218 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
220 /* Move outwards to encounter edge */
227 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
229 /* Drop down one line */
238 /* Drop diagonally down and out */
262 if (r1
.width
> r
.width
)
263 r1
.width
= r2
.width
= r
.width
;
267 r1
.width
= r2
.width
= r
.width
;
270 if ((r1
.y
< r
.y
+w
) || (r1
.x
+W
>= r1
.x
+r1
.width
-W
))
272 result
&= app_fill_rect(g
, r1
, pbrush
, TRUE
);
273 result
&= app_fill_rect(g
, r2
, pbrush
, TRUE
);
278 else if (r1
.y
+r1
.height
< r2
.y
)
280 /* Draw distinct rectangles */
281 result
&= app_fill_rect(g
, rect(r1
.x
,r1
.y
,
283 result
&= app_fill_rect(g
, rect(
284 r1
.x
+r1
.width
-W
,r1
.y
,W
,1), pbrush
, TRUE
);
285 result
&= app_fill_rect(g
, rect(r2
.x
,
286 r2
.y
,W
,1), pbrush
, TRUE
);
287 result
&= app_fill_rect(g
, rect(
288 r2
.x
+r2
.width
-W
,r2
.y
,W
,1), pbrush
, TRUE
);
308 if ((x
<= a
) && (prevy
< r2
.y
))
310 /* Draw final line */
311 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
315 if (r
.x
+ W
!= prevx
)
322 result
&= app_fill_rect(g
, rect(r
.x
, r1
.y
,
323 r
.width
, r1
.height
), pbrush
, TRUE
);
327 result
&= app_fill_rect(g
, rect(r
.x
, r1
.y
, W
, r1
.height
), pbrush
, TRUE
);
328 result
&= app_fill_rect(g
, rect(r
.x
+r
.width
-W
, r1
.y
,
329 W
, r1
.height
), pbrush
, TRUE
);
335 * Draw an arc of an ellipse from start_angle anti-clockwise to
336 * end_angle. If the angles coincide, draw nothing; if they
337 * differ by 360 degrees or more, draw a full ellipse.
338 * The shape is drawn with the current line thickness,
339 * completely within the bounding rectangle. The shape is also
340 * axis-aligned, so that the ellipse would be horizontally and
341 * vertically symmetric is it was complete.
343 * The draw_arc algorithm is based on draw_ellipse, but unlike
344 * that algorithm is not symmetric in the general case, since
345 * an angular portion is clipped from the shape.
346 * This clipping is performed by keeping track of two hypothetical
347 * lines joining the centre point to the enclosing rectangle,
348 * at the angles start_angle and end_angle, using a line-intersection
349 * algorithm. Essentially the algorithm just fills the spaces
350 * which are within the arc and also between the angles, going
351 * in an anti-clockwise direction from start_angle to end_angle.
352 * In the top half of the ellipse, this amounts to drawing
353 * to the left of the start_angle line and to the right of
354 * the end_angle line, while in the bottom half of the ellipse,
355 * it involves drawing to the right of the start_angle and to
356 * the left of the end_angle.
360 * Fill a rectangle within an arc, given the centre point p0,
361 * and the two end points of the lines corresponding to the
362 * start_angle and the end_angle. This function takes care of
363 * the logic needed to swap the fill direction below
364 * the central point, and also performs the calculations
365 * needed to intersect the current Y value with each line.
370 app_fill_arc_rect(DC
*g
,
371 Rect r
, // top, left, width, height
381 int start_above
, end_above
;
382 long rise1
, run1
, rise2
, run2
;
391 /* In top half of arc ellipse */
395 /* Start_line is in the top half and is */
396 /* intersected by the current Y scan line */
400 x1
= p0
.x
+ (r
.y
-p0
.y
)*run1
/rise1
;
403 else if ((start_angle
>= 0) && (start_angle
<= 180))
405 /* Start_line is above middle */
411 /* Start_line is below middle */
417 if (x1
> r
.x
+r
.width
)
422 /* end_line is in the top half and is */
423 /* intersected by the current Y scan line */
427 x2
= p0
.x
+ (r
.y
-p0
.y
)*run2
/rise2
;
430 else if ((end_angle
>= 0) && (end_angle
<= 180))
432 /* end_line is above middle */
438 /* end_line is below middle */
443 if (x2
< r
.x
) x2
= r
.x
;
445 if (x2
> r
.x
+r
.width
) x2
= r
.x
+r
.width
;
447 if (start_above
&& end_above
)
449 if (start_angle
> end_angle
)
451 /* Fill outsides of wedge */
452 if (! app_fill_rect(g
, rect(r
.x
, r
.y
,
453 x1
-r
.x
, r
.height
), pbrush
, Pen
))
455 return app_fill_rect(g
, rect(x2
, r
.y
,
456 r
.x
+r
.width
-x2
, r
.height
), pbrush
, Pen
);
460 /* Fill inside of wedge */
463 return app_fill_rect(g
, r
, pbrush
, Pen
);
466 else if (start_above
)
468 /* Fill to the left of the start_line */
470 return app_fill_rect(g
, r
, pbrush
, Pen
);
474 /* Fill right of end_line */
475 r
.width
= r
.x
+r
.width
-x2
;
477 return app_fill_rect(g
, r
, pbrush
, Pen
);
481 if (start_angle
> end_angle
)
482 return app_fill_rect(g
,r
, pbrush
, Pen
);
489 /* In lower half of arc ellipse */
493 /* start_line is in the lower half and is */
494 /* intersected by the current Y scan line */
498 x1
= p0
.x
+ (r
.y
-p0
.y
)*run1
/rise1
;
501 else if ((start_angle
>= 180) && (start_angle
<= 360))
503 /* start_line is below middle */
509 /* start_line is above middle */
515 if (x1
> r
.x
+r
.width
)
520 /* end_line is in the lower half and is */
521 /* intersected by the current Y scan line */
525 x2
= p0
.x
+ (r
.y
-p0
.y
)*run2
/rise2
;
528 else if ((end_angle
>= 180) && (end_angle
<= 360))
530 /* end_line is below middle */
536 /* end_line is above middle */
542 if (x2
> r
.x
+r
.width
)
545 if (start_above
&& end_above
)
547 if (start_angle
> end_angle
)
548 return app_fill_rect(g
,r
, pbrush
, Pen
);
552 else if (start_above
)
554 /* Fill to the left of end_line */
556 return app_fill_rect(g
,r
, pbrush
, Pen
);
560 /* Fill right of start_line */
561 r
.width
= r
.x
+r
.width
-x1
;
563 return app_fill_rect(g
,r
, pbrush
, Pen
);
567 if (start_angle
> end_angle
)
569 /* Fill outsides of wedge */
570 if (! app_fill_rect(g
, rect(r
.x
, r
.y
,
571 x2
-r
.x
, r
.height
), pbrush
, Pen
))
573 return app_fill_rect(g
, rect(x1
, r
.y
,
574 r
.x
+r
.width
-x1
, r
.height
), pbrush
, Pen
);
578 /* Fill inside of wedge */
581 return app_fill_rect(g
, r
, pbrush
, Pen
);
588 * To fill an axis-aligned ellipse, we use a scan-line algorithm.
589 * We walk downwards from the top Y co-ordinate, calculating
590 * the width of the ellipse using incremental integer arithmetic.
591 * To save calculation, we observe that the top and bottom halves
592 * of the ellipsoid are mirror-images, therefore we can draw the
593 * top and bottom halves by reflection. As a result, this algorithm
594 * draws rectangles inwards from the top and bottom edges of the
595 * bounding rectangle.
597 * To save rendering time, draw as few rectangles as possible.
598 * Other ellipse-drawing algorithms assume we want to draw each
599 * line, using a draw_pixel operation, or a draw_horizontal_line
600 * operation. This approach is slower than it needs to be in
601 * circumstances where a fill_rect operation is more efficient
602 * (such as in X-Windows, where there is a communication overhead
603 * to the X-Server). For this reason, the algorithm accumulates
604 * rectangles on adjacent lines which have the same width into a
605 * single larger rectangle.
607 * This algorithm forms the basis of the later, more complex,
608 * draw_ellipse algorithm, which renders the rectangular spaces
609 * between an outer and inner ellipse, and also the draw_arc and
610 * fill_arc operations which additionally clip drawing between
611 * a start_angle and an end_angle.
617 app_fill_ellipse(DC
*g
, Rect r
, PBRUSH pbrush
)
619 /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
622 int b
= r
.height
/ 2;
627 long xcrit
= (3 * a2
/ 4) + 1;
628 long ycrit
= (3 * b2
/ 4) + 1;
629 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
630 long dxt
= b2
*(3+x
+x
);
631 long dyt
= a2
*(3-y
-y
);
637 if ((r
.width
<= 2) || (r
.height
<= 2))
638 return app_fill_rect(g
, r
, pbrush
, FALSE
);
642 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
646 r2
.y
= r
.y
+ r
.height
- 1;
650 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
652 /* Move outwards to encounter edge */
663 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
665 /* Drop down one line */
670 /* Enlarge rectangles */
677 /* Drop diagonally down and out */
684 if ((r1
.width
> 0) && (r1
.height
> 0))
686 /* Draw rectangles first */
688 if (r1
.y
+r1
.height
< r2
.y
)
690 /* Distinct rectangles */
691 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
692 result
&= app_fill_rect(g
, r2
, pbrush
, FALSE
);
703 /* Skipped pixels on initial diagonal */
705 /* Enlarge, rather than moving down */
723 r1
.height
= r2
.y
+r2
.height
-r1
.y
;
724 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
728 /* Crossover, draw final line */
731 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
733 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
741 app_boundary_point(Rect r
, int angle
)
755 return pt(r
.x
+r
.width
, cy
);
756 else if (angle
== 45)
757 return pt(r
.x
+r
.width
, r
.y
);
758 else if (angle
== 90)
760 else if (angle
== 135)
762 else if (angle
== 180)
764 else if (angle
== 225)
765 return pt(r
.x
, r
.y
+r
.height
);
766 else if (angle
== 270)
767 return pt(cx
, r
.y
+r
.height
);
768 else if (angle
== 315)
769 return pt(r
.x
+r
.width
, r
.y
+r
.height
);
771 tangent
= tan(DEGREES_TO_RADIANS(angle
));
773 if ((angle
> 45) && (angle
< 135))
774 return pt((int)(cx
+r
.height
/tangent
/2), r
.y
);
775 else if ((angle
> 225) && (angle
< 315))
776 return pt((int)(cx
-r
.height
/tangent
/2), r
.y
+r
.height
);
777 else if ((angle
> 135) && (angle
< 225))
778 return pt(r
.x
, (int)(cy
+r
.width
*tangent
/2));
780 return pt(r
.x
+r
.width
, (int)(cy
-r
.width
*tangent
/2));
785 app_fill_arc(DC
*g
, Rect r
, int start_angle
, int end_angle
, PBRUSH pbrush
, BOOL Chord
)
787 /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
790 int b
= r
.height
/ 2;
795 long xcrit
= (3 * a2
/ 4) + 1;
796 long ycrit
= (3 * b2
/ 4) + 1;
797 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
798 long dxt
= b2
*(3+x
+x
);
799 long dyt
= a2
*(3-y
-y
);
803 int movedown
, moveout
;
806 /* Line descriptions */
809 /* If angles differ by 360 degrees or more, close the shape */
810 if ((start_angle
+ 360 <= end_angle
) ||
811 (start_angle
- 360 >= end_angle
))
813 return app_fill_ellipse(g
, r
, pbrush
);
816 /* Make start_angle >= 0 and <= 360 */
817 while (start_angle
< 0)
821 /* Make end_angle >= 0 and <= 360 */
822 while (end_angle
< 0)
826 /* Draw nothing if the angles are equal */
827 if (start_angle
== end_angle
)
830 /* Find arc wedge line end points */
831 p1
= app_boundary_point(r
, start_angle
);
832 p2
= app_boundary_point(r
, end_angle
);
834 p0
= pt((p1
.x
+p2
.x
)/2,(p1
.y
+p2
.y
)/2);
836 p0
= pt(r
.x
+ r
.width
/2, r
.y
+ r
.height
/2);
838 /* Initialise rectangles to be drawn */
841 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
845 r2
.y
= r
.y
+ r
.height
- 1;
849 moveout
= movedown
= 0;
851 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
853 /* Move outwards to encounter edge */
860 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
862 /* Drop down one line */
871 /* Drop diagonally down and out */
895 if (r1
.width
> r
.width
)
896 r1
.width
= r2
.width
= r
.width
;
900 r1
.width
= r2
.width
= r
.width
;
903 if ((r1
.width
> 0) && (r1
.y
+r1
.height
< r2
.y
))
905 /* Distinct rectangles */
906 result
&= app_fill_arc_rect(g
, r1
,
908 start_angle
, end_angle
, pbrush
, FALSE
);
909 result
&= app_fill_arc_rect(g
, r2
,
911 start_angle
, end_angle
, pbrush
, FALSE
);
933 r1
.height
= r2
.y
+r2
.height
-r1
.y
;
934 while (r1
.height
> 0)
936 result
&= app_fill_arc_rect(g
,
937 rect(r1
.x
, r1
.y
, r1
.width
, 1),
938 p0
, p1
, p2
, start_angle
, end_angle
, pbrush
, FALSE
);
945 /* Crossover, draw final line */
948 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
950 while (r1
.height
> 0)
952 result
&= app_fill_arc_rect(g
,
953 rect(r1
.x
, r1
.y
, r1
.width
, 1),
954 p0
, p1
, p2
, start_angle
, end_angle
, pbrush
, FALSE
);
962 int app_draw_arc(DC
*g
, Rect r
, int start_angle
, int end_angle
, PBRUSH pbrushPen
, BOOL Chord
)
964 /* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
967 int b
= r
.height
/ 2;
972 long xcrit
= (3 * a2
/ 4) + 1;
973 long ycrit
= (3 * b2
/ 4) + 1;
974 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
975 long dxt
= b2
*(3+x
+x
);
976 long dyt
= a2
*(3-y
-y
);
980 int w
= pbrushPen
->lWidth
;
982 /* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
984 int A
= a
-w
> 0 ? a
-w
: 0;
985 int B
= b
-w
> 0 ? b
-w
: 0;
990 long XCRIT
= (3 * A2
/ 4) + 1;
991 long YCRIT
= (3 * B2
/ 4) + 1;
992 long T
= B2
+ A2
- 2*A2
*B
; /* T = E(X+1,Y-1) */
993 long DXT
= B2
*(3+X
+X
);
994 long DYT
= A2
*(3-Y
-Y
);
998 /* Arc rectangle calculations */
999 int movedown
, moveout
;
1000 int innerX
= 0, prevx
, prevy
, W
;
1004 /* Line descriptions */
1007 /* If angles differ by 360 degrees or more, close the shape */
1008 if ((start_angle
+ 360 <= end_angle
) ||
1009 (start_angle
- 360 >= end_angle
))
1011 return app_draw_ellipse(g
, r
, pbrushPen
);
1014 /* Make start_angle >= 0 and <= 360 */
1015 while (start_angle
< 0)
1019 /* Make end_angle >= 0 and <= 360 */
1020 while (end_angle
< 0)
1024 /* Draw nothing if the angles are equal */
1025 if (start_angle
== end_angle
)
1028 /* Find arc wedge line end points */
1029 p1
= app_boundary_point(r
, start_angle
);
1030 p2
= app_boundary_point(r
, end_angle
);
1032 p0
= pt((p1
.x
+p2
.x
)/2,(p1
.y
+p2
.y
)/2);
1034 p0
= pt(r
.x
+ r
.width
/2, r
.y
+ r
.height
/2);
1036 /* Determine ellipse rectangles */
1039 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
1043 r2
.y
= r
.y
+ r
.height
- 1;
1054 if (T
+ A2
*Y
< XCRIT
) /* E(X+1,Y-1/2) <= 0 */
1056 /* Move outwards to encounter edge */
1061 else if (T
- B2
*X
>= YCRIT
) /* e(x+1/2,y-1) > 0 */
1063 /* Drop down one line */
1070 /* Drop diagonally down and out */
1079 movedown
= moveout
= 0;
1082 if (r1
.x
+ W
< prevx
)
1087 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
1089 /* Move outwards to encounter edge */
1096 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
1098 /* Drop down one line */
1107 /* Drop diagonally down and out */
1131 if (r1
.width
> r
.width
)
1132 r1
.width
= r2
.width
= r
.width
;
1136 r1
.width
= r2
.width
= r
.width
;
1139 if ((r1
.y
< r
.y
+w
) || (r1
.x
+W
>= r1
.x
+r1
.width
-W
))
1141 result
&= app_fill_arc_rect(g
, r1
,
1143 start_angle
, end_angle
, pbrushPen
, TRUE
);
1144 result
&= app_fill_arc_rect(g
, r2
,
1146 start_angle
, end_angle
, pbrushPen
, TRUE
);
1151 else if (r1
.y
+r1
.height
< r2
.y
)
1153 /* Draw distinct rectangles */
1154 result
&= app_fill_arc_rect(g
, rect(
1157 start_angle
, end_angle
, pbrushPen
, TRUE
);
1158 result
&= app_fill_arc_rect(g
, rect(
1159 r1
.x
+r1
.width
-W
,r1
.y
,W
,1),
1161 start_angle
, end_angle
, pbrushPen
, TRUE
);
1162 result
&= app_fill_arc_rect(g
, rect(
1165 start_angle
, end_angle
, pbrushPen
, TRUE
);
1166 result
&= app_fill_arc_rect(g
, rect(
1167 r2
.x
+r2
.width
-W
,r2
.y
,W
,1),
1169 start_angle
, end_angle
, pbrushPen
, TRUE
);
1189 if ((x
<= a
) && (prevy
< r2
.y
))
1191 /* Draw final lines */
1192 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
1196 if (r
.x
+ W
!= prevx
)
1203 while (r1
.height
> 0)
1205 result
&= app_fill_arc_rect(g
, rect(r
.x
,
1206 r1
.y
, r
.width
, 1), p0
, p1
, p2
,
1207 start_angle
, end_angle
, pbrushPen
, TRUE
);
1214 while (r1
.height
> 0)
1216 result
&= app_fill_arc_rect(g
, rect(r
.x
, r1
.y
,
1218 start_angle
, end_angle
, pbrushPen
, TRUE
);
1219 result
&= app_fill_arc_rect(g
, rect(r
.x
+r
.width
-W
,
1220 r1
.y
, W
, 1), p0
, p1
, p2
,
1221 start_angle
, end_angle
, pbrushPen
, TRUE
);
1230 /* ReactOS Interface *********************************************************/
1234 IntFillRect( DC
*dc
,
1242 DWORD ROP
= ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY
);
1250 ASSERT_DC_PREPARED(dc
);
1252 psurf
= dc
->dclevel
.pSurface
;
1255 EngSetLastError(ERROR_INVALID_HANDLE
);
1259 if (!(pbrush
->flAttrs
& BR_IS_NULL
))
1261 pdcattr
= dc
->pdcattr
;
1263 /* Fix negative spaces */
1272 Height
= 0 - Height
;
1275 DestRect
.left
= XLeft
;
1276 DestRect
.right
= XLeft
+ Width
;
1278 DestRect
.top
= YLeft
;
1279 DestRect
.bottom
= YLeft
+ Height
;
1281 BrushOrigin
.x
= pbrush
->ptOrigin
.x
;
1282 BrushOrigin
.y
= pbrush
->ptOrigin
.y
;
1284 if (pdcattr
->jROP2
== R2_XORPEN
)
1285 ROP
= ROP4_FROM_INDEX(R3_OPINDEX_PATINVERT
);
1296 Pen
? &dc
->eboLine
.BrushObject
: &dc
->eboFill
.BrushObject
,
1311 double StartArc
, // FIXME: don't use floating point!
1317 int Start
= (int)ceil(StartArc
);
1318 int End
= (int)ceil(EndArc
);
1319 BOOL Chord
= (arctype
== GdiTypeChord
), ret
;
1321 pdcattr
= dc
->pdcattr
;
1323 pbrush
= BRUSH_ShareLockBrush(pdcattr
->hbrush
);
1326 DPRINT1("FillArc Fail\n");
1327 EngSetLastError(ERROR_INTERNAL_ERROR
);
1330 // Sort out alignment here.
1331 ret
= app_fill_arc(dc
, rect( XLeft
, YLeft
, Width
, Height
),
1332 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -End
: -Start
,
1333 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -Start
: -End
,
1336 BRUSH_ShareUnlockBrush(pbrush
);
1347 double StartArc
, // FIXME: don't use floating point!
1352 int Start
= (int)ceil(StartArc
);
1353 int End
= (int)ceil(EndArc
);
1354 BOOL Chord
= (arctype
== GdiTypeChord
);
1355 // Sort out alignment here.
1356 return app_draw_arc(dc
, rect( XLeft
, YLeft
, Width
, Height
),
1357 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -End
: -Start
,
1358 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -Start
: -End
,
1364 IntDrawEllipse( PDC dc
,
1371 return (BOOL
)app_draw_ellipse(dc
, rect( XLeft
, YLeft
, Width
, Height
), pbrush
);
1376 IntFillEllipse( PDC dc
,
1383 return (BOOL
)app_fill_ellipse(dc
, rect( XLeft
, YLeft
, Width
, Height
), pbrush
);
1388 IntFillRoundRect( PDC dc
,
1398 int rx
, ry
; /* Radius in x and y directions */
1401 r
= rect( Left
, Top
, abs(Right
-Left
), abs(Bottom
-Top
));
1405 if (Wellipse
> r
.width
)
1407 if (Hellipse
> r
.height
) // > W > H
1408 app_fill_ellipse(dc
, r
, pbrush
);
1411 app_fill_arc(dc
, rect( r
.x
, r
.y
, r
.width
- 1, Hellipse
),
1412 0, 180, pbrush
,FALSE
);
1413 app_fill_arc(dc
, rect(r
.x
, Bottom
- Hellipse
- 1, r
.width
- 1, Hellipse
),
1414 180, 360, pbrush
, FALSE
);
1417 else if(Hellipse
> r
.height
) // < W > H
1419 app_fill_arc(dc
, rect(r
.x
, r
.y
, Wellipse
, r
.height
- 1),
1420 90, 270, pbrush
, FALSE
);
1421 app_fill_arc(dc
, rect(Right
- Wellipse
- 1, r
.y
, Wellipse
, r
.height
- 1),
1422 270, 90, pbrush
,FALSE
);
1426 app_fill_arc(dc
, rect(r
.x
, r
.y
, rx
+rx
, ry
+ry
),
1427 90, 180, pbrush
, FALSE
);
1429 app_fill_arc(dc
, rect(r
.x
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1430 180, 270, pbrush
, FALSE
);
1432 app_fill_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1433 270, 360, pbrush
,FALSE
);
1435 app_fill_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
, rx
+rx
, ry
+ry
),
1436 0, 90, pbrush
,FALSE
);
1438 if (Wellipse
< r
.width
)
1440 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
, r
.width
-rx
-rx
, ry
+1), pbrush
, FALSE
);
1441 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
+r
.height
-ry
+1, r
.width
-rx
-rx
, ry
-1), pbrush
, FALSE
);
1443 if (Hellipse
< r
.height
)
1445 app_fill_rect(dc
, rect(r
.x
, r
.y
+ry
+1, r
.width
, r
.height
-ry
-ry
), pbrush
, FALSE
);
1454 IntDrawRoundRect( PDC dc
,
1464 int rx
, ry
; /* Radius in x and y directions */
1465 int w
= pbrushPen
->lWidth
;
1467 r
= rect( Left
, Top
, abs(Right
-Left
), abs(Bottom
-Top
));
1471 if (Wellipse
> r
.width
)
1473 if (Hellipse
> r
.height
) // > W > H
1474 app_draw_ellipse(dc
, r
, pbrushPen
);
1477 app_draw_arc(dc
, rect( r
.x
, r
.y
, r
.width
- 1, Hellipse
- 1),
1478 0, 180, pbrushPen
, FALSE
);
1479 app_draw_arc(dc
, rect(r
.x
, Bottom
- Hellipse
, r
.width
- 1, Hellipse
- 1),
1480 180, 360, pbrushPen
, FALSE
);
1483 else if(Hellipse
> r
.height
) // < W > H
1485 app_draw_arc(dc
, rect(r
.x
, r
.y
, Wellipse
- 1, r
.height
- 1),
1486 90, 270, pbrushPen
, FALSE
);
1487 app_draw_arc(dc
, rect(Right
- Wellipse
, r
.y
, Wellipse
- 1, r
.height
- 1),
1488 270, 90, pbrushPen
, FALSE
);
1492 app_draw_arc(dc
, rect(r
.x
, r
.y
, rx
+rx
, ry
+ry
),
1493 90, 180, pbrushPen
, FALSE
);
1495 app_draw_arc(dc
, rect(r
.x
,r
.y
+r
.height
-ry
-ry
,rx
+rx
,ry
+ry
),
1496 180, 270, pbrushPen
, FALSE
);
1498 app_draw_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1499 270, 360, pbrushPen
, FALSE
);
1501 app_draw_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
,r
.y
,rx
+rx
,ry
+ry
),
1502 0, 90, pbrushPen
, FALSE
);
1504 if ( Hellipse
< r
.height
)
1506 app_fill_rect(dc
, rect(r
.x
, r
.y
+ry
+1, w
, r
.height
-ry
-ry
), pbrushPen
, TRUE
);
1509 app_fill_rect(dc
, rect(r
.x
+r
.width
-w
, r
.y
+ry
+1, w
, r
.height
-ry
-ry
),
1512 if ( Wellipse
< r
.width
)
1514 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
+r
.height
-w
, r
.width
-rx
-rx
, w
),
1517 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
, r
.width
-rx
-rx
, w
), pbrushPen
, TRUE
);