1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // Rounded rectangle vertex generator
17 //
18 //----------------------------------------------------------------------------
19 
20 #include <math.h>
21 #include "../include/agg_rounded_rect.h"
22 
23 
24 namespace mapserver
25 {
26     //------------------------------------------------------------------------
rounded_rect(double x1,double y1,double x2,double y2,double r)27     rounded_rect::rounded_rect(double x1, double y1, double x2, double y2, double r) :
28         m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2),
29         m_rx1(r), m_ry1(r), m_rx2(r), m_ry2(r),
30         m_rx3(r), m_ry3(r), m_rx4(r), m_ry4(r)
31     {
32         if(x1 > x2) { m_x1 = x2; m_x2 = x1; }
33         if(y1 > y2) { m_y1 = y2; m_y2 = y1; }
34     }
35 
36     //--------------------------------------------------------------------
rect(double x1,double y1,double x2,double y2)37     void rounded_rect::rect(double x1, double y1, double x2, double y2)
38     {
39         m_x1 = x1;
40         m_y1 = y1;
41         m_x2 = x2;
42         m_y2 = y2;
43         if(x1 > x2) { m_x1 = x2; m_x2 = x1; }
44         if(y1 > y2) { m_y1 = y2; m_y2 = y1; }
45     }
46 
47     //--------------------------------------------------------------------
radius(double r)48     void rounded_rect::radius(double r)
49     {
50         m_rx1 = m_ry1 = m_rx2 = m_ry2 = m_rx3 = m_ry3 = m_rx4 = m_ry4 = r;
51     }
52 
53     //--------------------------------------------------------------------
radius(double rx,double ry)54     void rounded_rect::radius(double rx, double ry)
55     {
56         m_rx1 = m_rx2 = m_rx3 = m_rx4 = rx;
57         m_ry1 = m_ry2 = m_ry3 = m_ry4 = ry;
58     }
59 
60     //--------------------------------------------------------------------
radius(double rx_bottom,double ry_bottom,double rx_top,double ry_top)61     void rounded_rect::radius(double rx_bottom, double ry_bottom,
62                               double rx_top,    double ry_top)
63     {
64         m_rx1 = m_rx2 = rx_bottom;
65         m_rx3 = m_rx4 = rx_top;
66         m_ry1 = m_ry2 = ry_bottom;
67         m_ry3 = m_ry4 = ry_top;
68     }
69 
70     //--------------------------------------------------------------------
radius(double rx1,double ry1,double rx2,double ry2,double rx3,double ry3,double rx4,double ry4)71     void rounded_rect::radius(double rx1, double ry1, double rx2, double ry2,
72                               double rx3, double ry3, double rx4, double ry4)
73     {
74         m_rx1 = rx1; m_ry1 = ry1; m_rx2 = rx2; m_ry2 = ry2;
75         m_rx3 = rx3; m_ry3 = ry3; m_rx4 = rx4; m_ry4 = ry4;
76     }
77 
78     //--------------------------------------------------------------------
normalize_radius()79     void rounded_rect::normalize_radius()
80     {
81         double dx = fabs(m_y2 - m_y1);
82         double dy = fabs(m_x2 - m_x1);
83 
84         double k = 1.0;
85         double t;
86         t = dx / (m_rx1 + m_rx2); if(t < k) k = t;
87         t = dx / (m_rx3 + m_rx4); if(t < k) k = t;
88         t = dy / (m_ry1 + m_ry2); if(t < k) k = t;
89         t = dy / (m_ry3 + m_ry4); if(t < k) k = t;
90 
91         if(k < 1.0)
92         {
93             m_rx1 *= k; m_ry1 *= k; m_rx2 *= k; m_ry2 *= k;
94             m_rx3 *= k; m_ry3 *= k; m_rx4 *= k; m_ry4 *= k;
95         }
96     }
97 
98     //--------------------------------------------------------------------
rewind(unsigned)99     void rounded_rect::rewind(unsigned)
100     {
101         m_status = 0;
102     }
103 
104     //--------------------------------------------------------------------
vertex(double * x,double * y)105     unsigned rounded_rect::vertex(double* x, double* y)
106     {
107         unsigned cmd = path_cmd_stop;
108         switch(m_status)
109         {
110         case 0:
111             m_arc.init(m_x1 + m_rx1, m_y1 + m_ry1, m_rx1, m_ry1,
112                        pi, pi+pi*0.5);
113             m_arc.rewind(0);
114             m_status++;
115 
116         case 1:
117             cmd = m_arc.vertex(x, y);
118             if(is_stop(cmd)) m_status++;
119             else return cmd;
120 
121         case 2:
122             m_arc.init(m_x2 - m_rx2, m_y1 + m_ry2, m_rx2, m_ry2,
123                        pi+pi*0.5, 0.0);
124             m_arc.rewind(0);
125             m_status++;
126 
127         case 3:
128             cmd = m_arc.vertex(x, y);
129             if(is_stop(cmd)) m_status++;
130             else return path_cmd_line_to;
131 
132         case 4:
133             m_arc.init(m_x2 - m_rx3, m_y2 - m_ry3, m_rx3, m_ry3,
134                        0.0, pi*0.5);
135             m_arc.rewind(0);
136             m_status++;
137 
138         case 5:
139             cmd = m_arc.vertex(x, y);
140             if(is_stop(cmd)) m_status++;
141             else return path_cmd_line_to;
142 
143         case 6:
144             m_arc.init(m_x1 + m_rx4, m_y2 - m_ry4, m_rx4, m_ry4,
145                        pi*0.5, pi);
146             m_arc.rewind(0);
147             m_status++;
148 
149         case 7:
150             cmd = m_arc.vertex(x, y);
151             if(is_stop(cmd)) m_status++;
152             else return path_cmd_line_to;
153 
154         case 8:
155             cmd = path_cmd_end_poly | path_flags_close | path_flags_ccw;
156             m_status++;
157             break;
158         }
159         return cmd;
160     }
161 
162 
163 }
164 
165