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 "agg_rounded_rect.h" 22 23 24 namespace agg 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