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
->ptPenWidth
.x
;
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
;
167 if ((r
.width
<= 2) || (r
.height
<= 2))
168 return app_fill_rect(g
, r
, pbrush
, TRUE
);
172 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
176 r2
.y
= r
.y
+ r
.height
- 1;
187 if (T
+ A2
*Y
< XCRIT
) /* E(X+1,Y-1/2) <= 0 */
189 /* Move outwards to encounter edge */
194 else if (T
- B2
*X
>= YCRIT
) /* e(x+1/2,y-1) > 0 */
196 /* Drop down one line */
203 /* Drop diagonally down and out */
212 movedown
= moveout
= 0;
215 if (r1
.x
+ W
< prevx
)
220 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
222 /* Move outwards to encounter edge */
229 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
231 /* Drop down one line */
240 /* Drop diagonally down and out */
264 if (r1
.width
> r
.width
)
265 r1
.width
= r2
.width
= r
.width
;
269 r1
.width
= r2
.width
= r
.width
;
272 if ((r1
.y
< r
.y
+w
) || (r1
.x
+W
>= r1
.x
+r1
.width
-W
))
274 result
&= app_fill_rect(g
, r1
, pbrush
, TRUE
);
275 result
&= app_fill_rect(g
, r2
, pbrush
, TRUE
);
280 else if (r1
.y
+r1
.height
< r2
.y
)
282 /* Draw distinct rectangles */
283 result
&= app_fill_rect(g
, rect(r1
.x
,r1
.y
,
285 result
&= app_fill_rect(g
, rect(
286 r1
.x
+r1
.width
-W
,r1
.y
,W
,1), pbrush
, TRUE
);
287 result
&= app_fill_rect(g
, rect(r2
.x
,
288 r2
.y
,W
,1), pbrush
, TRUE
);
289 result
&= app_fill_rect(g
, rect(
290 r2
.x
+r2
.width
-W
,r2
.y
,W
,1), pbrush
, TRUE
);
310 if ((x
<= a
) && (prevy
< r2
.y
))
312 /* Draw final line */
313 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
317 if (r
.x
+ W
!= prevx
)
324 result
&= app_fill_rect(g
, rect(r
.x
, r1
.y
,
325 r
.width
, r1
.height
), pbrush
, TRUE
);
329 result
&= app_fill_rect(g
, rect(r
.x
, r1
.y
, W
, r1
.height
), pbrush
, TRUE
);
330 result
&= app_fill_rect(g
, rect(r
.x
+r
.width
-W
, r1
.y
,
331 W
, r1
.height
), pbrush
, TRUE
);
337 * Draw an arc of an ellipse from start_angle anti-clockwise to
338 * end_angle. If the angles coincide, draw nothing; if they
339 * differ by 360 degrees or more, draw a full ellipse.
340 * The shape is drawn with the current line thickness,
341 * completely within the bounding rectangle. The shape is also
342 * axis-aligned, so that the ellipse would be horizontally and
343 * vertically symmetric is it was complete.
345 * The draw_arc algorithm is based on draw_ellipse, but unlike
346 * that algorithm is not symmetric in the general case, since
347 * an angular portion is clipped from the shape.
348 * This clipping is performed by keeping track of two hypothetical
349 * lines joining the centre point to the enclosing rectangle,
350 * at the angles start_angle and end_angle, using a line-intersection
351 * algorithm. Essentially the algorithm just fills the spaces
352 * which are within the arc and also between the angles, going
353 * in an anti-clockwise direction from start_angle to end_angle.
354 * In the top half of the ellipse, this amounts to drawing
355 * to the left of the start_angle line and to the right of
356 * the end_angle line, while in the bottom half of the ellipse,
357 * it involves drawing to the right of the start_angle and to
358 * the left of the end_angle.
362 * Fill a rectangle within an arc, given the centre point p0,
363 * and the two end points of the lines corresponding to the
364 * start_angle and the end_angle. This function takes care of
365 * the logic needed to swap the fill direction below
366 * the central point, and also performs the calculations
367 * needed to intersect the current Y value with each line.
372 app_fill_arc_rect(DC
*g
,
373 Rect r
, // top, left, width, height
383 int start_above
, end_above
;
384 long rise1
, run1
, rise2
, run2
;
393 /* In top half of arc ellipse */
397 /* Start_line is in the top half and is */
398 /* intersected by the current Y scan line */
402 x1
= p0
.x
+ (r
.y
-p0
.y
)*run1
/rise1
;
405 else if ((start_angle
>= 0) && (start_angle
<= 180))
407 /* Start_line is above middle */
413 /* Start_line is below middle */
419 if (x1
> r
.x
+r
.width
)
424 /* end_line is in the top half and is */
425 /* intersected by the current Y scan line */
429 x2
= p0
.x
+ (r
.y
-p0
.y
)*run2
/rise2
;
432 else if ((end_angle
>= 0) && (end_angle
<= 180))
434 /* end_line is above middle */
440 /* end_line is below middle */
445 if (x2
< r
.x
) x2
= r
.x
;
447 if (x2
> r
.x
+r
.width
) x2
= r
.x
+r
.width
;
449 if (start_above
&& end_above
)
451 if (start_angle
> end_angle
)
453 /* Fill outsides of wedge */
454 if (! app_fill_rect(g
, rect(r
.x
, r
.y
,
455 x1
-r
.x
, r
.height
), pbrush
, Pen
))
457 return app_fill_rect(g
, rect(x2
, r
.y
,
458 r
.x
+r
.width
-x2
, r
.height
), pbrush
, Pen
);
462 /* Fill inside of wedge */
465 return app_fill_rect(g
, r
, pbrush
, Pen
);
468 else if (start_above
)
470 /* Fill to the left of the start_line */
472 return app_fill_rect(g
, r
, pbrush
, Pen
);
476 /* Fill right of end_line */
477 r
.width
= r
.x
+r
.width
-x2
;
479 return app_fill_rect(g
, r
, pbrush
, Pen
);
483 if (start_angle
> end_angle
)
484 return app_fill_rect(g
,r
, pbrush
, Pen
);
491 /* In lower half of arc ellipse */
495 /* start_line is in the lower half and is */
496 /* intersected by the current Y scan line */
500 x1
= p0
.x
+ (r
.y
-p0
.y
)*run1
/rise1
;
503 else if ((start_angle
>= 180) && (start_angle
<= 360))
505 /* start_line is below middle */
511 /* start_line is above middle */
517 if (x1
> r
.x
+r
.width
)
522 /* end_line is in the lower half and is */
523 /* intersected by the current Y scan line */
527 x2
= p0
.x
+ (r
.y
-p0
.y
)*run2
/rise2
;
530 else if ((end_angle
>= 180) && (end_angle
<= 360))
532 /* end_line is below middle */
538 /* end_line is above middle */
544 if (x2
> r
.x
+r
.width
)
547 if (start_above
&& end_above
)
549 if (start_angle
> end_angle
)
550 return app_fill_rect(g
,r
, pbrush
, Pen
);
554 else if (start_above
)
556 /* Fill to the left of end_line */
558 return app_fill_rect(g
,r
, pbrush
, Pen
);
562 /* Fill right of start_line */
563 r
.width
= r
.x
+r
.width
-x1
;
565 return app_fill_rect(g
,r
, pbrush
, Pen
);
569 if (start_angle
> end_angle
)
571 /* Fill outsides of wedge */
572 if (! app_fill_rect(g
, rect(r
.x
, r
.y
,
573 x2
-r
.x
, r
.height
), pbrush
, Pen
))
575 return app_fill_rect(g
, rect(x1
, r
.y
,
576 r
.x
+r
.width
-x1
, r
.height
), pbrush
, Pen
);
580 /* Fill inside of wedge */
583 return app_fill_rect(g
, r
, pbrush
, Pen
);
590 * To fill an axis-aligned ellipse, we use a scan-line algorithm.
591 * We walk downwards from the top Y co-ordinate, calculating
592 * the width of the ellipse using incremental integer arithmetic.
593 * To save calculation, we observe that the top and bottom halves
594 * of the ellipsoid are mirror-images, therefore we can draw the
595 * top and bottom halves by reflection. As a result, this algorithm
596 * draws rectangles inwards from the top and bottom edges of the
597 * bounding rectangle.
599 * To save rendering time, draw as few rectangles as possible.
600 * Other ellipse-drawing algorithms assume we want to draw each
601 * line, using a draw_pixel operation, or a draw_horizontal_line
602 * operation. This approach is slower than it needs to be in
603 * circumstances where a fill_rect operation is more efficient
604 * (such as in X-Windows, where there is a communication overhead
605 * to the X-Server). For this reason, the algorithm accumulates
606 * rectangles on adjacent lines which have the same width into a
607 * single larger rectangle.
609 * This algorithm forms the basis of the later, more complex,
610 * draw_ellipse algorithm, which renders the rectangular spaces
611 * between an outer and inner ellipse, and also the draw_arc and
612 * fill_arc operations which additionally clip drawing between
613 * a start_angle and an end_angle.
619 app_fill_ellipse(DC
*g
, Rect r
, PBRUSH pbrush
)
621 /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
624 int b
= r
.height
/ 2;
629 long xcrit
= (3 * a2
/ 4) + 1;
630 long ycrit
= (3 * b2
/ 4) + 1;
631 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
632 long dxt
= b2
*(3+x
+x
);
633 long dyt
= a2
*(3-y
-y
);
641 if ((r
.width
<= 2) || (r
.height
<= 2))
642 return app_fill_rect(g
, r
, pbrush
, FALSE
);
646 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
650 r2
.y
= r
.y
+ r
.height
- 1;
654 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
656 /* Move outwards to encounter edge */
667 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
669 /* Drop down one line */
674 /* Enlarge rectangles */
681 /* Drop diagonally down and out */
688 if ((r1
.width
> 0) && (r1
.height
> 0))
690 /* Draw rectangles first */
692 if (r1
.y
+r1
.height
< r2
.y
)
694 /* Distinct rectangles */
695 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
696 result
&= app_fill_rect(g
, r2
, pbrush
, FALSE
);
707 /* Skipped pixels on initial diagonal */
709 /* Enlarge, rather than moving down */
727 r1
.height
= r2
.y
+r2
.height
-r1
.y
;
728 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
732 /* Crossover, draw final line */
735 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
737 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
745 app_boundary_point(Rect r
, int angle
)
759 return pt(r
.x
+r
.width
, cy
);
760 else if (angle
== 45)
761 return pt(r
.x
+r
.width
, r
.y
);
762 else if (angle
== 90)
764 else if (angle
== 135)
766 else if (angle
== 180)
768 else if (angle
== 225)
769 return pt(r
.x
, r
.y
+r
.height
);
770 else if (angle
== 270)
771 return pt(cx
, r
.y
+r
.height
);
772 else if (angle
== 315)
773 return pt(r
.x
+r
.width
, r
.y
+r
.height
);
775 tangent
= tan(DEGREES_TO_RADIANS(angle
));
777 if ((angle
> 45) && (angle
< 135))
778 return pt((int)(cx
+r
.height
/tangent
/2), r
.y
);
779 else if ((angle
> 225) && (angle
< 315))
780 return pt((int)(cx
-r
.height
/tangent
/2), r
.y
+r
.height
);
781 else if ((angle
> 135) && (angle
< 225))
782 return pt(r
.x
, (int)(cy
+r
.width
*tangent
/2));
784 return pt(r
.x
+r
.width
, (int)(cy
-r
.width
*tangent
/2));
789 app_fill_arc(DC
*g
, Rect r
, int start_angle
, int end_angle
, PBRUSH pbrush
, BOOL Chord
)
791 /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
794 int b
= r
.height
/ 2;
799 long xcrit
= (3 * a2
/ 4) + 1;
800 long ycrit
= (3 * b2
/ 4) + 1;
801 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
802 long dxt
= b2
*(3+x
+x
);
803 long dyt
= a2
*(3-y
-y
);
807 int movedown
, moveout
;
810 /* Line descriptions */
815 /* If angles differ by 360 degrees or more, close the shape */
816 if ((start_angle
+ 360 <= end_angle
) ||
817 (start_angle
- 360 >= end_angle
))
819 return app_fill_ellipse(g
, r
, pbrush
);
822 /* Make start_angle >= 0 and <= 360 */
823 while (start_angle
< 0)
827 /* Make end_angle >= 0 and <= 360 */
828 while (end_angle
< 0)
832 /* Draw nothing if the angles are equal */
833 if (start_angle
== end_angle
)
836 /* Find arc wedge line end points */
837 p1
= app_boundary_point(r
, start_angle
);
838 p2
= app_boundary_point(r
, end_angle
);
840 p0
= pt((p1
.x
+p2
.x
)/2,(p1
.y
+p2
.y
)/2);
842 p0
= pt(r
.x
+ r
.width
/2, r
.y
+ r
.height
/2);
844 /* Initialise rectangles to be drawn */
847 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
851 r2
.y
= r
.y
+ r
.height
- 1;
855 moveout
= movedown
= 0;
857 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
859 /* Move outwards to encounter edge */
866 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
868 /* Drop down one line */
877 /* Drop diagonally down and out */
901 if (r1
.width
> r
.width
)
902 r1
.width
= r2
.width
= r
.width
;
906 r1
.width
= r2
.width
= r
.width
;
909 if ((r1
.width
> 0) && (r1
.y
+r1
.height
< r2
.y
))
911 /* Distinct rectangles */
912 result
&= app_fill_arc_rect(g
, r1
,
914 start_angle
, end_angle
, pbrush
, FALSE
);
915 result
&= app_fill_arc_rect(g
, r2
,
917 start_angle
, end_angle
, pbrush
, FALSE
);
939 r1
.height
= r2
.y
+r2
.height
-r1
.y
;
940 while (r1
.height
> 0)
942 result
&= app_fill_arc_rect(g
,
943 rect(r1
.x
, r1
.y
, r1
.width
, 1),
944 p0
, p1
, p2
, start_angle
, end_angle
, pbrush
, FALSE
);
951 /* Crossover, draw final line */
954 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
956 while (r1
.height
> 0)
958 result
&= app_fill_arc_rect(g
,
959 rect(r1
.x
, r1
.y
, r1
.width
, 1),
960 p0
, p1
, p2
, start_angle
, end_angle
, pbrush
, FALSE
);
968 int app_draw_arc(DC
*g
, Rect r
, int start_angle
, int end_angle
, PBRUSH pbrushPen
, BOOL Chord
)
970 /* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
973 int b
= r
.height
/ 2;
978 long xcrit
= (3 * a2
/ 4) + 1;
979 long ycrit
= (3 * b2
/ 4) + 1;
980 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
981 long dxt
= b2
*(3+x
+x
);
982 long dyt
= a2
*(3-y
-y
);
986 int w
= pbrushPen
->ptPenWidth
.x
;
988 /* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
990 int A
= a
-w
> 0 ? a
-w
: 0;
991 int B
= b
-w
> 0 ? b
-w
: 0;
996 long XCRIT
= (3 * A2
/ 4) + 1;
997 long YCRIT
= (3 * B2
/ 4) + 1;
998 long T
= B2
+ A2
- 2*A2
*B
; /* T = E(X+1,Y-1) */
999 long DXT
= B2
*(3+X
+X
);
1000 long DYT
= A2
*(3-Y
-Y
);
1004 /* Arc rectangle calculations */
1005 int movedown
, moveout
;
1006 int innerX
= 0, prevx
, prevy
, W
;
1010 /* Line descriptions */
1015 /* If angles differ by 360 degrees or more, close the shape */
1016 if ((start_angle
+ 360 <= end_angle
) ||
1017 (start_angle
- 360 >= end_angle
))
1019 return app_draw_ellipse(g
, r
, pbrushPen
);
1022 /* Make start_angle >= 0 and <= 360 */
1023 while (start_angle
< 0)
1027 /* Make end_angle >= 0 and <= 360 */
1028 while (end_angle
< 0)
1032 /* Draw nothing if the angles are equal */
1033 if (start_angle
== end_angle
)
1036 /* Find arc wedge line end points */
1037 p1
= app_boundary_point(r
, start_angle
);
1038 p2
= app_boundary_point(r
, end_angle
);
1040 p0
= pt((p1
.x
+p2
.x
)/2,(p1
.y
+p2
.y
)/2);
1042 p0
= pt(r
.x
+ r
.width
/2, r
.y
+ r
.height
/2);
1044 /* Determine ellipse rectangles */
1047 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
1051 r2
.y
= r
.y
+ r
.height
- 1;
1062 if (T
+ A2
*Y
< XCRIT
) /* E(X+1,Y-1/2) <= 0 */
1064 /* Move outwards to encounter edge */
1069 else if (T
- B2
*X
>= YCRIT
) /* e(x+1/2,y-1) > 0 */
1071 /* Drop down one line */
1078 /* Drop diagonally down and out */
1087 movedown
= moveout
= 0;
1090 if (r1
.x
+ W
< prevx
)
1095 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
1097 /* Move outwards to encounter edge */
1104 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
1106 /* Drop down one line */
1115 /* Drop diagonally down and out */
1139 if (r1
.width
> r
.width
)
1140 r1
.width
= r2
.width
= r
.width
;
1144 r1
.width
= r2
.width
= r
.width
;
1147 if ((r1
.y
< r
.y
+w
) || (r1
.x
+W
>= r1
.x
+r1
.width
-W
))
1149 result
&= app_fill_arc_rect(g
, r1
,
1151 start_angle
, end_angle
, pbrushPen
, TRUE
);
1152 result
&= app_fill_arc_rect(g
, r2
,
1154 start_angle
, end_angle
, pbrushPen
, TRUE
);
1159 else if (r1
.y
+r1
.height
< r2
.y
)
1161 /* Draw distinct rectangles */
1162 result
&= app_fill_arc_rect(g
, rect(
1165 start_angle
, end_angle
, pbrushPen
, TRUE
);
1166 result
&= app_fill_arc_rect(g
, rect(
1167 r1
.x
+r1
.width
-W
,r1
.y
,W
,1),
1169 start_angle
, end_angle
, pbrushPen
, TRUE
);
1170 result
&= app_fill_arc_rect(g
, rect(
1173 start_angle
, end_angle
, pbrushPen
, TRUE
);
1174 result
&= app_fill_arc_rect(g
, rect(
1175 r2
.x
+r2
.width
-W
,r2
.y
,W
,1),
1177 start_angle
, end_angle
, pbrushPen
, TRUE
);
1197 if ((x
<= a
) && (prevy
< r2
.y
))
1199 /* Draw final lines */
1200 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
1204 if (r
.x
+ W
!= prevx
)
1211 while (r1
.height
> 0)
1213 result
&= app_fill_arc_rect(g
, rect(r
.x
,
1214 r1
.y
, r
.width
, 1), p0
, p1
, p2
,
1215 start_angle
, end_angle
, pbrushPen
, TRUE
);
1222 while (r1
.height
> 0)
1224 result
&= app_fill_arc_rect(g
, rect(r
.x
, r1
.y
,
1226 start_angle
, end_angle
, pbrushPen
, TRUE
);
1227 result
&= app_fill_arc_rect(g
, rect(r
.x
+r
.width
-W
,
1228 r1
.y
, W
, 1), p0
, p1
, p2
,
1229 start_angle
, end_angle
, pbrushPen
, TRUE
);
1238 /* ReactOS Interface *********************************************************/
1242 IntFillRect( DC
*dc
,
1250 DWORD ROP
= ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY
);
1259 psurf
= dc
->dclevel
.pSurface
;
1262 EngSetLastError(ERROR_INVALID_HANDLE
);
1266 if (!(pbrush
->flAttrs
& GDIBRUSH_IS_NULL
))
1268 pdcattr
= dc
->pdcattr
;
1270 /* Fix negative spaces */
1279 Height
= 0 - Height
;
1282 DestRect
.left
= XLeft
;
1283 DestRect
.right
= XLeft
+ Width
;
1285 DestRect
.top
= YLeft
;
1286 DestRect
.bottom
= YLeft
+ Height
;
1288 BrushOrigin
.x
= pbrush
->ptOrigin
.x
;
1289 BrushOrigin
.y
= pbrush
->ptOrigin
.y
;
1291 if (pdcattr
->jROP2
== R2_XORPEN
)
1292 ROP
= ROP4_FROM_INDEX(R3_OPINDEX_PATINVERT
);
1298 dc
->rosdc
.CombinedClip
,
1303 Pen
? &dc
->eboLine
.BrushObject
: &dc
->eboFill
.BrushObject
,
1318 double StartArc
, // FIXME: don't use floating point!
1324 int Start
= (int)ceil(StartArc
);
1325 int End
= (int)ceil(EndArc
);
1326 BOOL Chord
= (arctype
== GdiTypeChord
), ret
;
1328 pdcattr
= dc
->pdcattr
;
1330 pbrush
= BRUSH_ShareLockBrush(pdcattr
->hbrush
);
1333 DPRINT1("FillArc Fail\n");
1334 EngSetLastError(ERROR_INTERNAL_ERROR
);
1337 // Sort out alignment here.
1338 ret
= app_fill_arc(dc
, rect( XLeft
, YLeft
, Width
, Height
),
1339 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -End
: -Start
,
1340 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -Start
: -End
,
1343 BRUSH_ShareUnlockBrush(pbrush
);
1354 double StartArc
, // FIXME: don't use floating point!
1359 int Start
= (int)ceil(StartArc
);
1360 int End
= (int)ceil(EndArc
);
1361 BOOL Chord
= (arctype
== GdiTypeChord
);
1362 // Sort out alignment here.
1363 return app_draw_arc(dc
, rect( XLeft
, YLeft
, Width
, Height
),
1364 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -End
: -Start
,
1365 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -Start
: -End
,
1371 IntDrawEllipse( PDC dc
,
1378 return (BOOL
)app_draw_ellipse(dc
, rect( XLeft
, YLeft
, Width
, Height
), pbrush
);
1383 IntFillEllipse( PDC dc
,
1390 return (BOOL
)app_fill_ellipse(dc
, rect( XLeft
, YLeft
, Width
, Height
), pbrush
);
1395 IntFillRoundRect( PDC dc
,
1405 int rx
, ry
; /* Radius in x and y directions */
1408 r
= rect( Left
, Top
, abs(Right
-Left
), abs(Bottom
-Top
));
1412 if (Wellipse
> r
.width
)
1414 if (Hellipse
> r
.height
) // > W > H
1415 app_fill_ellipse(dc
, r
, pbrush
);
1418 app_fill_arc(dc
, rect( r
.x
, r
.y
, r
.width
- 1, Hellipse
),
1419 0, 180, pbrush
,FALSE
);
1420 app_fill_arc(dc
, rect(r
.x
, Bottom
- Hellipse
- 1, r
.width
- 1, Hellipse
),
1421 180, 360, pbrush
, FALSE
);
1424 else if(Hellipse
> r
.height
) // < W > H
1426 app_fill_arc(dc
, rect(r
.x
, r
.y
, Wellipse
, r
.height
- 1),
1427 90, 270, pbrush
, FALSE
);
1428 app_fill_arc(dc
, rect(Right
- Wellipse
- 1, r
.y
, Wellipse
, r
.height
- 1),
1429 270, 90, pbrush
,FALSE
);
1433 app_fill_arc(dc
, rect(r
.x
, r
.y
, rx
+rx
, ry
+ry
),
1434 90, 180, pbrush
, FALSE
);
1436 app_fill_arc(dc
, rect(r
.x
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1437 180, 270, pbrush
, FALSE
);
1439 app_fill_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1440 270, 360, pbrush
,FALSE
);
1442 app_fill_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
, rx
+rx
, ry
+ry
),
1443 0, 90, pbrush
,FALSE
);
1445 if (Wellipse
< r
.width
)
1447 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
, r
.width
-rx
-rx
, ry
+1), pbrush
, FALSE
);
1448 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
+r
.height
-ry
+1, r
.width
-rx
-rx
, ry
-1), pbrush
, FALSE
);
1450 if (Hellipse
< r
.height
)
1452 app_fill_rect(dc
, rect(r
.x
, r
.y
+ry
+1, r
.width
, r
.height
-ry
-ry
), pbrush
, FALSE
);
1461 IntDrawRoundRect( PDC dc
,
1471 int rx
, ry
; /* Radius in x and y directions */
1472 int w
= pbrushPen
->ptPenWidth
.x
;
1474 r
= rect( Left
, Top
, abs(Right
-Left
), abs(Bottom
-Top
));
1478 if (Wellipse
> r
.width
)
1480 if (Hellipse
> r
.height
) // > W > H
1481 app_draw_ellipse(dc
, r
, pbrushPen
);
1484 app_draw_arc(dc
, rect( r
.x
, r
.y
, r
.width
- 1, Hellipse
- 1),
1485 0, 180, pbrushPen
, FALSE
);
1486 app_draw_arc(dc
, rect(r
.x
, Bottom
- Hellipse
, r
.width
- 1, Hellipse
- 1),
1487 180, 360, pbrushPen
, FALSE
);
1490 else if(Hellipse
> r
.height
) // < W > H
1492 app_draw_arc(dc
, rect(r
.x
, r
.y
, Wellipse
- 1, r
.height
- 1),
1493 90, 270, pbrushPen
, FALSE
);
1494 app_draw_arc(dc
, rect(Right
- Wellipse
, r
.y
, Wellipse
- 1, r
.height
- 1),
1495 270, 90, pbrushPen
, FALSE
);
1499 app_draw_arc(dc
, rect(r
.x
, r
.y
, rx
+rx
, ry
+ry
),
1500 90, 180, pbrushPen
, FALSE
);
1502 app_draw_arc(dc
, rect(r
.x
,r
.y
+r
.height
-ry
-ry
,rx
+rx
,ry
+ry
),
1503 180, 270, pbrushPen
, FALSE
);
1505 app_draw_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1506 270, 360, pbrushPen
, FALSE
);
1508 app_draw_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
,r
.y
,rx
+rx
,ry
+ry
),
1509 0, 90, pbrushPen
, FALSE
);
1511 if ( Hellipse
< r
.height
)
1513 app_fill_rect(dc
, rect(r
.x
, r
.y
+ry
+1, w
, r
.height
-ry
-ry
), pbrushPen
, TRUE
);
1516 app_fill_rect(dc
, rect(r
.x
+r
.width
-w
, r
.y
+ry
+1, w
, r
.height
-ry
-ry
),
1519 if ( Wellipse
< r
.width
)
1521 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
+r
.height
-w
, r
.width
-rx
-rx
, w
),
1524 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
, r
.width
-rx
-rx
, w
), pbrushPen
, TRUE
);