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 */
202 /* drop diagonally down and out */
211 movedown
= moveout
= 0;
214 if (r1
.x
+ W
< prevx
)
219 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
221 /* move outwards to encounter edge */
228 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
230 /* drop down one line */
238 /* drop diagonally down and out */
251 r1
.x
-= 1; r1
.width
+= 2;
252 r2
.x
-= 1; r2
.width
+= 2;
258 if (r1
.width
> r
.width
)
259 r1
.width
= r2
.width
= r
.width
;
260 if (r1
.y
== r2
.y
-1) {
262 r1
.width
= r2
.width
= r
.width
;
265 if ((r1
.y
< r
.y
+w
) || (r1
.x
+W
>= r1
.x
+r1
.width
-W
))
267 result
&= app_fill_rect(g
, r1
, pbrush
, TRUE
);
268 result
&= app_fill_rect(g
, r2
, pbrush
, TRUE
);
273 else if (r1
.y
+r1
.height
< r2
.y
)
275 /* draw distinct rectangles */
276 result
&= app_fill_rect(g
, rect(r1
.x
,r1
.y
,
278 result
&= app_fill_rect(g
, rect(
279 r1
.x
+r1
.width
-W
,r1
.y
,W
,1), pbrush
, TRUE
);
280 result
&= app_fill_rect(g
, rect(r2
.x
,
281 r2
.y
,W
,1), pbrush
, TRUE
);
282 result
&= app_fill_rect(g
, rect(
283 r2
.x
+r2
.width
-W
,r2
.y
,W
,1), pbrush
, TRUE
);
296 r1
.x
-= 1; r1
.width
+= 2;
297 r2
.x
-= 1; r2
.width
+= 2;
300 if ((x
<= a
) && (prevy
< r2
.y
)) {
301 /* draw final line */
302 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
306 if (r
.x
+ W
!= prevx
)
311 if (W
+W
>= r
.width
) {
312 result
&= app_fill_rect(g
, rect(r
.x
, r1
.y
,
313 r
.width
, r1
.height
), pbrush
, TRUE
);
317 result
&= app_fill_rect(g
, rect(r
.x
, r1
.y
, W
, r1
.height
), pbrush
, TRUE
);
318 result
&= app_fill_rect(g
, rect(r
.x
+r
.width
-W
, r1
.y
,
319 W
, r1
.height
), pbrush
, TRUE
);
325 * Draw an arc of an ellipse from start_angle anti-clockwise to
326 * end_angle. If the angles coincide, draw nothing; if they
327 * differ by 360 degrees or more, draw a full ellipse.
328 * The shape is drawn with the current line thickness,
329 * completely within the bounding rectangle. The shape is also
330 * axis-aligned, so that the ellipse would be horizontally and
331 * vertically symmetric is it was complete.
333 * The draw_arc algorithm is based on draw_ellipse, but unlike
334 * that algorithm is not symmetric in the general case, since
335 * an angular portion is clipped from the shape.
336 * This clipping is performed by keeping track of two hypothetical
337 * lines joining the centre point to the enclosing rectangle,
338 * at the angles start_angle and end_angle, using a line-intersection
339 * algorithm. Essentially the algorithm just fills the spaces
340 * which are within the arc and also between the angles, going
341 * in an anti-clockwise direction from start_angle to end_angle.
342 * In the top half of the ellipse, this amounts to drawing
343 * to the left of the start_angle line and to the right of
344 * the end_angle line, while in the bottom half of the ellipse,
345 * it involves drawing to the right of the start_angle and to
346 * the left of the end_angle.
350 * Fill a rectangle within an arc, given the centre point p0,
351 * and the two end points of the lines corresponding to the
352 * start_angle and the end_angle. This function takes care of
353 * the logic needed to swap the fill direction below
354 * the central point, and also performs the calculations
355 * needed to intersect the current Y value with each line.
360 app_fill_arc_rect(DC
*g
,
361 Rect r
, // top, left, width, height
371 int start_above
, end_above
;
372 long rise1
, run1
, rise2
, run2
;
381 /* in top half of arc ellipse */
385 /* start_line is in the top half and is */
386 /* intersected by the current Y scan line */
390 x1
= p0
.x
+ (r
.y
-p0
.y
)*run1
/rise1
;
393 else if ((start_angle
>= 0) && (start_angle
<= 180))
395 /* start_line is above middle */
401 /* start_line is below middle */
407 if (x1
> r
.x
+r
.width
)
412 /* end_line is in the top half and is */
413 /* intersected by the current Y scan line */
417 x2
= p0
.x
+ (r
.y
-p0
.y
)*run2
/rise2
;
420 else if ((end_angle
>= 0) && (end_angle
<= 180))
422 /* end_line is above middle */
428 /* end_line is below middle */
433 if (x2
< r
.x
) x2
= r
.x
;
435 if (x2
> r
.x
+r
.width
) x2
= r
.x
+r
.width
;
437 if (start_above
&& end_above
)
439 if (start_angle
> end_angle
)
441 /* fill outsides of wedge */
442 if (! app_fill_rect(g
, rect(r
.x
, r
.y
,
443 x1
-r
.x
, r
.height
), pbrush
, Pen
))
445 return app_fill_rect(g
, rect(x2
, r
.y
,
446 r
.x
+r
.width
-x2
, r
.height
), pbrush
, Pen
);
450 /* fill inside of wedge */
453 return app_fill_rect(g
, r
, pbrush
, Pen
);
456 else if (start_above
)
458 /* fill to the left of the start_line */
460 return app_fill_rect(g
, r
, pbrush
, Pen
);
464 /* fill right of end_line */
465 r
.width
= r
.x
+r
.width
-x2
;
467 return app_fill_rect(g
, r
, pbrush
, Pen
);
471 if (start_angle
> end_angle
)
472 return app_fill_rect(g
,r
, pbrush
, Pen
);
479 /* in lower half of arc ellipse */
483 /* start_line is in the lower half and is */
484 /* intersected by the current Y scan line */
488 x1
= p0
.x
+ (r
.y
-p0
.y
)*run1
/rise1
;
491 else if ((start_angle
>= 180) && (start_angle
<= 360))
493 /* start_line is below middle */
499 /* start_line is above middle */
505 if (x1
> r
.x
+r
.width
)
510 /* end_line is in the lower half and is */
511 /* intersected by the current Y scan line */
515 x2
= p0
.x
+ (r
.y
-p0
.y
)*run2
/rise2
;
518 else if ((end_angle
>= 180) && (end_angle
<= 360))
520 /* end_line is below middle */
526 /* end_line is above middle */
532 if (x2
> r
.x
+r
.width
)
535 if (start_above
&& end_above
)
537 if (start_angle
> end_angle
)
538 return app_fill_rect(g
,r
, pbrush
, Pen
);
542 else if (start_above
)
544 /* fill to the left of end_line */
546 return app_fill_rect(g
,r
, pbrush
, Pen
);
550 /* fill right of start_line */
551 r
.width
= r
.x
+r
.width
-x1
;
553 return app_fill_rect(g
,r
, pbrush
, Pen
);
557 if (start_angle
> end_angle
)
559 /* fill outsides of wedge */
560 if (! app_fill_rect(g
, rect(r
.x
, r
.y
,
561 x2
-r
.x
, r
.height
), pbrush
, Pen
))
563 return app_fill_rect(g
, rect(x1
, r
.y
,
564 r
.x
+r
.width
-x1
, r
.height
), pbrush
, Pen
);
568 /* fill inside of wedge */
571 return app_fill_rect(g
, r
, pbrush
, Pen
);
578 * To fill an axis-aligned ellipse, we use a scan-line algorithm.
579 * We walk downwards from the top Y co-ordinate, calculating
580 * the width of the ellipse using incremental integer arithmetic.
581 * To save calculation, we observe that the top and bottom halves
582 * of the ellipsoid are mirror-images, therefore we can draw the
583 * top and bottom halves by reflection. As a result, this algorithm
584 * draws rectangles inwards from the top and bottom edges of the
585 * bounding rectangle.
587 * To save rendering time, draw as few rectangles as possible.
588 * Other ellipse-drawing algorithms assume we want to draw each
589 * line, using a draw_pixel operation, or a draw_horizontal_line
590 * operation. This approach is slower than it needs to be in
591 * circumstances where a fill_rect operation is more efficient
592 * (such as in X-Windows, where there is a communication overhead
593 * to the X-Server). For this reason, the algorithm accumulates
594 * rectangles on adjacent lines which have the same width into a
595 * single larger rectangle.
597 * This algorithm forms the basis of the later, more complex,
598 * draw_ellipse algorithm, which renders the rectangular spaces
599 * between an outer and inner ellipse, and also the draw_arc and
600 * fill_arc operations which additionally clip drawing between
601 * a start_angle and an end_angle.
607 app_fill_ellipse(DC
*g
, Rect r
, PBRUSH pbrush
)
609 /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
612 int b
= r
.height
/ 2;
617 long xcrit
= (3 * a2
/ 4) + 1;
618 long ycrit
= (3 * b2
/ 4) + 1;
619 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
620 long dxt
= b2
*(3+x
+x
);
621 long dyt
= a2
*(3-y
-y
);
629 if ((r
.width
<= 2) || (r
.height
<= 2))
630 return app_fill_rect(g
, r
, pbrush
, FALSE
);
634 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
638 r2
.y
= r
.y
+ r
.height
- 1;
642 if (t
+ a2
*y
< xcrit
) { /* e(x+1,y-1/2) <= 0 */
643 /* move outwards to encounter edge */
649 r1
.x
-= 1; r1
.width
+= 2;
650 r2
.x
-= 1; r2
.width
+= 2;
652 else if (t
- b2
*x
>= ycrit
) { /* e(x+1/2,y-1) > 0 */
653 /* drop down one line */
658 /* enlarge rectangles */
660 r2
.height
+= 1; r2
.y
-= 1;
663 /* drop diagonally down and out */
670 if ((r1
.width
> 0) && (r1
.height
> 0))
672 /* draw rectangles first */
674 if (r1
.y
+r1
.height
< r2
.y
) {
675 /* distinct rectangles */
676 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
677 result
&= app_fill_rect(g
, r2
, pbrush
, FALSE
);
681 r1
.y
+= r1
.height
; r1
.height
= 1;
682 r2
.y
-= 1; r2
.height
= 1;
685 /* skipped pixels on initial diagonal */
687 /* enlarge, rather than moving down */
689 r2
.height
+= 1; r2
.y
-= 1;
693 r1
.x
-= 1; r1
.width
+= 2;
694 r2
.x
-= 1; r2
.width
+= 2;
701 r1
.height
= r2
.y
+r2
.height
-r1
.y
;
702 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
705 /* crossover, draw final line */
708 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
710 result
&= app_fill_rect(g
, r1
, pbrush
, FALSE
);
718 app_boundary_point(Rect r
, int angle
)
732 return pt(r
.x
+r
.width
, cy
);
733 else if (angle
== 45)
734 return pt(r
.x
+r
.width
, r
.y
);
735 else if (angle
== 90)
737 else if (angle
== 135)
739 else if (angle
== 180)
741 else if (angle
== 225)
742 return pt(r
.x
, r
.y
+r
.height
);
743 else if (angle
== 270)
744 return pt(cx
, r
.y
+r
.height
);
745 else if (angle
== 315)
746 return pt(r
.x
+r
.width
, r
.y
+r
.height
);
748 tangent
= tan(DEGREES_TO_RADIANS(angle
));
750 if ((angle
> 45) && (angle
< 135))
751 return pt((int)(cx
+r
.height
/tangent
/2), r
.y
);
752 else if ((angle
> 225) && (angle
< 315))
753 return pt((int)(cx
-r
.height
/tangent
/2), r
.y
+r
.height
);
754 else if ((angle
> 135) && (angle
< 225))
755 return pt(r
.x
, (int)(cy
+r
.width
*tangent
/2));
757 return pt(r
.x
+r
.width
, (int)(cy
-r
.width
*tangent
/2));
762 app_fill_arc(DC
*g
, Rect r
, int start_angle
, int end_angle
, PBRUSH pbrush
, BOOL Chord
)
764 /* e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
767 int b
= r
.height
/ 2;
772 long xcrit
= (3 * a2
/ 4) + 1;
773 long ycrit
= (3 * b2
/ 4) + 1;
774 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
775 long dxt
= b2
*(3+x
+x
);
776 long dyt
= a2
*(3-y
-y
);
780 int movedown
, moveout
;
783 /* line descriptions */
788 /* if angles differ by 360 degrees or more, close the shape */
789 if ((start_angle
+ 360 <= end_angle
) ||
790 (start_angle
- 360 >= end_angle
))
792 return app_fill_ellipse(g
, r
, pbrush
);
795 /* make start_angle >= 0 and <= 360 */
796 while (start_angle
< 0)
800 /* make end_angle >= 0 and <= 360 */
801 while (end_angle
< 0)
805 /* draw nothing if the angles are equal */
806 if (start_angle
== end_angle
)
809 /* find arc wedge line end points */
810 p1
= app_boundary_point(r
, start_angle
);
811 p2
= app_boundary_point(r
, end_angle
);
813 p0
= pt((p1
.x
+p2
.x
)/2,(p1
.y
+p2
.y
)/2);
815 p0
= pt(r
.x
+ r
.width
/2, r
.y
+ r
.height
/2);
817 /* initialise rectangles to be drawn */
820 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
824 r2
.y
= r
.y
+ r
.height
- 1;
828 moveout
= movedown
= 0;
830 if (t
+ a2
*y
< xcrit
) { /* e(x+1,y-1/2) <= 0 */
831 /* move outwards to encounter edge */
838 else if (t
- b2
*x
>= ycrit
) { /* e(x+1/2,y-1) > 0 */
839 /* drop down one line */
847 /* drop diagonally down and out */
860 r1
.x
-= 1; r1
.width
+= 2;
861 r2
.x
-= 1; r2
.width
+= 2;
867 if (r1
.width
> r
.width
)
868 r1
.width
= r2
.width
= r
.width
;
869 if (r1
.y
== r2
.y
-1) {
871 r1
.width
= r2
.width
= r
.width
;
874 if ((r1
.width
> 0) && (r1
.y
+r1
.height
< r2
.y
)) {
875 /* distinct rectangles */
876 result
&= app_fill_arc_rect(g
, r1
,
878 start_angle
, end_angle
, pbrush
, FALSE
);
879 result
&= app_fill_arc_rect(g
, r2
,
881 start_angle
, end_angle
, pbrush
, FALSE
);
891 r1
.x
-= 1; r1
.width
+= 2;
892 r2
.x
-= 1; r2
.width
+= 2;
899 r1
.height
= r2
.y
+r2
.height
-r1
.y
;
900 while (r1
.height
> 0) {
901 result
&= app_fill_arc_rect(g
,
902 rect(r1
.x
, r1
.y
, r1
.width
, 1),
903 p0
, p1
, p2
, start_angle
, end_angle
, pbrush
, FALSE
);
909 /* crossover, draw final line */
912 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
914 while (r1
.height
> 0) {
915 result
&= app_fill_arc_rect(g
,
916 rect(r1
.x
, r1
.y
, r1
.width
, 1),
917 p0
, p1
, p2
, start_angle
, end_angle
, pbrush
, FALSE
);
925 int app_draw_arc(DC
*g
, Rect r
, int start_angle
, int end_angle
, PBRUSH pbrushPen
, BOOL Chord
)
927 /* Outer ellipse: e(x,y) = b*b*x*x + a*a*y*y - a*a*b*b */
930 int b
= r
.height
/ 2;
935 long xcrit
= (3 * a2
/ 4) + 1;
936 long ycrit
= (3 * b2
/ 4) + 1;
937 long t
= b2
+ a2
- 2*a2
*b
; /* t = e(x+1,y-1) */
938 long dxt
= b2
*(3+x
+x
);
939 long dyt
= a2
*(3-y
-y
);
943 int w
= pbrushPen
->ptPenWidth
.x
;
945 /* Inner ellipse: E(X,Y) = B*B*X*X + A*A*Y*Y - A*A*B*B */
947 int A
= a
-w
> 0 ? a
-w
: 0;
948 int B
= b
-w
> 0 ? b
-w
: 0;
953 long XCRIT
= (3 * A2
/ 4) + 1;
954 long YCRIT
= (3 * B2
/ 4) + 1;
955 long T
= B2
+ A2
- 2*A2
*B
; /* T = E(X+1,Y-1) */
956 long DXT
= B2
*(3+X
+X
);
957 long DYT
= A2
*(3-Y
-Y
);
961 /* arc rectangle calculations */
962 int movedown
, moveout
;
963 int innerX
= 0, prevx
, prevy
, W
;
967 /* line descriptions */
972 /* if angles differ by 360 degrees or more, close the shape */
973 if ((start_angle
+ 360 <= end_angle
) ||
974 (start_angle
- 360 >= end_angle
))
976 return app_draw_ellipse(g
, r
, pbrushPen
);
979 /* make start_angle >= 0 and <= 360 */
980 while (start_angle
< 0)
984 /* make end_angle >= 0 and <= 360 */
985 while (end_angle
< 0)
989 /* draw nothing if the angles are equal */
990 if (start_angle
== end_angle
)
993 /* find arc wedge line end points */
994 p1
= app_boundary_point(r
, start_angle
);
995 p2
= app_boundary_point(r
, end_angle
);
997 p0
= pt((p1
.x
+p2
.x
)/2,(p1
.y
+p2
.y
)/2);
999 p0
= pt(r
.x
+ r
.width
/2, r
.y
+ r
.height
/2);
1001 /* determine ellipse rectangles */
1004 r1
.width
= r
.width
& 1; /* i.e. if width is odd */
1008 r2
.y
= r
.y
+ r
.height
- 1;
1019 if (T
+ A2
*Y
< XCRIT
) /* E(X+1,Y-1/2) <= 0 */
1021 /* move outwards to encounter edge */
1026 else if (T
- B2
*X
>= YCRIT
) /* e(x+1/2,y-1) > 0 */
1028 /* drop down one line */
1034 /* drop diagonally down and out */
1043 movedown
= moveout
= 0;
1046 if (r1
.x
+ W
< prevx
)
1051 if (t
+ a2
*y
< xcrit
) /* e(x+1,y-1/2) <= 0 */
1053 /* move outwards to encounter edge */
1060 else if (t
- b2
*x
>= ycrit
) /* e(x+1/2,y-1) > 0 */
1062 /* drop down one line */
1070 /* drop diagonally down and out */
1082 if (r1
.width
== 0) {
1083 r1
.x
-= 1; r1
.width
+= 2;
1084 r2
.x
-= 1; r2
.width
+= 2;
1090 if (r1
.width
> r
.width
)
1091 r1
.width
= r2
.width
= r
.width
;
1092 if (r1
.y
== r2
.y
-1) {
1094 r1
.width
= r2
.width
= r
.width
;
1097 if ((r1
.y
< r
.y
+w
) || (r1
.x
+W
>= r1
.x
+r1
.width
-W
))
1099 result
&= app_fill_arc_rect(g
, r1
,
1101 start_angle
, end_angle
, pbrushPen
, TRUE
);
1102 result
&= app_fill_arc_rect(g
, r2
,
1104 start_angle
, end_angle
, pbrushPen
, TRUE
);
1109 else if (r1
.y
+r1
.height
< r2
.y
)
1111 /* draw distinct rectangles */
1112 result
&= app_fill_arc_rect(g
, rect(
1115 start_angle
, end_angle
, pbrushPen
, TRUE
);
1116 result
&= app_fill_arc_rect(g
, rect(
1117 r1
.x
+r1
.width
-W
,r1
.y
,W
,1),
1119 start_angle
, end_angle
, pbrushPen
, TRUE
);
1120 result
&= app_fill_arc_rect(g
, rect(
1123 start_angle
, end_angle
, pbrushPen
, TRUE
);
1124 result
&= app_fill_arc_rect(g
, rect(
1125 r2
.x
+r2
.width
-W
,r2
.y
,W
,1),
1127 start_angle
, end_angle
, pbrushPen
, TRUE
);
1140 r1
.x
-= 1; r1
.width
+= 2;
1141 r2
.x
-= 1; r2
.width
+= 2;
1144 if ((x
<= a
) && (prevy
< r2
.y
)) {
1145 /* draw final lines */
1146 r1
.height
= r1
.y
+r1
.height
-r2
.y
;
1150 if (r
.x
+ W
!= prevx
)
1155 if (W
+W
>= r
.width
) {
1156 while (r1
.height
> 0) {
1157 result
&= app_fill_arc_rect(g
, rect(r
.x
,
1158 r1
.y
, r
.width
, 1), p0
, p1
, p2
,
1159 start_angle
, end_angle
, pbrushPen
, TRUE
);
1166 while (r1
.height
> 0) {
1167 result
&= app_fill_arc_rect(g
, rect(r
.x
, r1
.y
,
1169 start_angle
, end_angle
, pbrushPen
, TRUE
);
1170 result
&= app_fill_arc_rect(g
, rect(r
.x
+r
.width
-W
,
1171 r1
.y
, W
, 1), p0
, p1
, p2
,
1172 start_angle
, end_angle
, pbrushPen
, TRUE
);
1181 /* ReactOS Interface *********************************************************/
1185 IntFillRect( DC
*dc
,
1193 DWORD ROP
= PATCOPY
;
1202 psurf
= dc
->dclevel
.pSurface
;
1205 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1209 if (!(pbrush
->flAttrs
& GDIBRUSH_IS_NULL
))
1211 pdcattr
= dc
->pdcattr
;
1213 /* fix negative spaces */
1222 Height
= 0 - Height
;
1225 DestRect
.left
= XLeft
;
1226 DestRect
.right
= XLeft
+ Width
;
1228 DestRect
.top
= YLeft
;
1229 DestRect
.bottom
= YLeft
+ Height
;
1231 BrushOrigin
.x
= pbrush
->ptOrigin
.x
;
1232 BrushOrigin
.y
= pbrush
->ptOrigin
.y
;
1234 if (pdcattr
->jROP2
== R2_XORPEN
)
1243 dc
->rosdc
.CombinedClip
,
1248 Pen
? &dc
->eboLine
.BrushObject
: &dc
->eboFill
.BrushObject
,
1269 int Start
= ceil(StartArc
);
1270 int End
= ceil(EndArc
);
1271 BOOL Chord
= (arctype
== GdiTypeChord
), ret
;
1273 pdcattr
= dc
->pdcattr
;
1275 pbrush
= BRUSH_LockBrush(pdcattr
->hbrush
);
1278 DPRINT1("FillArc Fail\n");
1279 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1282 // Sort out alignment here.
1283 ret
= app_fill_arc(dc
, rect( XLeft
, YLeft
, Width
, Height
),
1284 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -End
: -Start
,
1285 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -Start
: -End
,
1288 BRUSH_UnlockBrush(pbrush
);
1304 int Start
= ceil(StartArc
);
1305 int End
= ceil(EndArc
);
1306 BOOL Chord
= (arctype
== GdiTypeChord
);
1307 // Sort out alignment here.
1308 return app_draw_arc(dc
, rect( XLeft
, YLeft
, Width
, Height
),
1309 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -End
: -Start
,
1310 (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
) ? -Start
: -End
,
1316 IntDrawEllipse( PDC dc
,
1323 return (BOOL
)app_draw_ellipse(dc
, rect( XLeft
, YLeft
, Width
, Height
), pbrush
);
1328 IntFillEllipse( PDC dc
,
1335 return (BOOL
)app_fill_ellipse(dc
, rect( XLeft
, YLeft
, Width
, Height
), pbrush
);
1340 IntFillRoundRect( PDC dc
,
1350 int rx
, ry
; /* radius in x and y directions */
1353 r
= rect( Left
, Top
, abs(Right
-Left
), abs(Bottom
-Top
));
1357 if (Wellipse
> r
.width
)
1359 if (Hellipse
> r
.height
) // > W > H
1360 app_fill_ellipse(dc
, r
, pbrush
);
1363 app_fill_arc(dc
, rect( r
.x
, r
.y
, r
.width
- 1, Hellipse
),
1364 0, 180, pbrush
,FALSE
);
1365 app_fill_arc(dc
, rect(r
.x
, Bottom
- Hellipse
- 1, r
.width
- 1, Hellipse
),
1366 180, 360, pbrush
, FALSE
);
1369 else if(Hellipse
> r
.height
) // < W > H
1371 app_fill_arc(dc
, rect(r
.x
, r
.y
, Wellipse
, r
.height
- 1),
1372 90, 270, pbrush
, FALSE
);
1373 app_fill_arc(dc
, rect(Right
- Wellipse
- 1, r
.y
, Wellipse
, r
.height
- 1),
1374 270, 90, pbrush
,FALSE
);
1378 app_fill_arc(dc
, rect(r
.x
, r
.y
, rx
+rx
, ry
+ry
),
1379 90, 180, pbrush
, FALSE
);
1381 app_fill_arc(dc
, rect(r
.x
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1382 180, 270, pbrush
, FALSE
);
1384 app_fill_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1385 270, 360, pbrush
,FALSE
);
1387 app_fill_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
, rx
+rx
, ry
+ry
),
1388 0, 90, pbrush
,FALSE
);
1390 if (Wellipse
< r
.width
)
1392 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
, r
.width
-rx
-rx
, ry
+1), pbrush
, FALSE
);
1393 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
+r
.height
-ry
+1, r
.width
-rx
-rx
, ry
-1), pbrush
, FALSE
);
1395 if (Hellipse
< r
.height
)
1397 app_fill_rect(dc
, rect(r
.x
, r
.y
+ry
+1, r
.width
, r
.height
-ry
-ry
), pbrush
, FALSE
);
1406 IntDrawRoundRect( PDC dc
,
1416 int rx
, ry
; /* radius in x and y directions */
1417 int w
= pbrushPen
->ptPenWidth
.x
;
1419 r
= rect( Left
, Top
, abs(Right
-Left
), abs(Bottom
-Top
));
1423 if (Wellipse
> r
.width
)
1425 if (Hellipse
> r
.height
) // > W > H
1426 app_draw_ellipse(dc
, r
, pbrushPen
);
1429 app_draw_arc(dc
, rect( r
.x
, r
.y
, r
.width
- 1, Hellipse
- 1),
1430 0, 180, pbrushPen
, FALSE
);
1431 app_draw_arc(dc
, rect(r
.x
, Bottom
- Hellipse
, r
.width
- 1, Hellipse
- 1),
1432 180, 360, pbrushPen
, FALSE
);
1435 else if(Hellipse
> r
.height
) // < W > H
1437 app_draw_arc(dc
, rect(r
.x
, r
.y
, Wellipse
- 1, r
.height
- 1),
1438 90, 270, pbrushPen
, FALSE
);
1439 app_draw_arc(dc
, rect(Right
- Wellipse
, r
.y
, Wellipse
- 1, r
.height
- 1),
1440 270, 90, pbrushPen
, FALSE
);
1444 app_draw_arc(dc
, rect(r
.x
, r
.y
, rx
+rx
, ry
+ry
),
1445 90, 180, pbrushPen
, FALSE
);
1447 app_draw_arc(dc
, rect(r
.x
,r
.y
+r
.height
-ry
-ry
,rx
+rx
,ry
+ry
),
1448 180, 270, pbrushPen
, FALSE
);
1450 app_draw_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
, r
.y
+r
.height
-ry
-ry
, rx
+rx
, ry
+ry
),
1451 270, 360, pbrushPen
, FALSE
);
1453 app_draw_arc(dc
, rect(r
.x
+r
.width
-rx
-rx
,r
.y
,rx
+rx
,ry
+ry
),
1454 0, 90, pbrushPen
, FALSE
);
1456 if ( Hellipse
< r
.height
)
1458 app_fill_rect(dc
, rect(r
.x
, r
.y
+ry
+1, w
, r
.height
-ry
-ry
), pbrushPen
, TRUE
);
1461 app_fill_rect(dc
, rect(r
.x
+r
.width
-w
, r
.y
+ry
+1, w
, r
.height
-ry
-ry
),
1464 if ( Wellipse
< r
.width
)
1466 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
+r
.height
-w
, r
.width
-rx
-rx
, w
),
1469 app_fill_rect(dc
, rect(r
.x
+rx
, r
.y
, r
.width
-rx
-rx
, w
), pbrushPen
, TRUE
);