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 #ifndef AGG_SPAN_GOURAUD_INCLUDED 17 #define AGG_SPAN_GOURAUD_INCLUDED 18 19 #include "agg_basics.h" 20 #include "agg_math.h" 21 22 namespace agg 23 { 24 25 //============================================================span_gouraud 26 template<class ColorT> class span_gouraud 27 { 28 public: 29 typedef ColorT color_type; 30 31 struct coord_type 32 { 33 double x; 34 double y; 35 color_type color; 36 }; 37 38 //-------------------------------------------------------------------- span_gouraud()39 span_gouraud() : 40 m_vertex(0) 41 { 42 m_cmd[0] = path_cmd_stop; 43 } 44 45 //-------------------------------------------------------------------- span_gouraud(const color_type & c1,const color_type & c2,const color_type & c3,double x1,double y1,double x2,double y2,double x3,double y3,double d)46 span_gouraud(const color_type& c1, 47 const color_type& c2, 48 const color_type& c3, 49 double x1, double y1, 50 double x2, double y2, 51 double x3, double y3, 52 double d) : 53 m_vertex(0) 54 { 55 colors(c1, c2, c3); 56 triangle(x1, y1, x2, y2, x3, y3, d); 57 } 58 59 //-------------------------------------------------------------------- colors(ColorT c1,ColorT c2,ColorT c3)60 void colors(ColorT c1, ColorT c2, ColorT c3) 61 { 62 m_coord[0].color = c1; 63 m_coord[1].color = c2; 64 m_coord[2].color = c3; 65 } 66 67 //-------------------------------------------------------------------- 68 // Sets the triangle and dilates it if needed. 69 // The trick here is to calculate beveled joins in the vertices of the 70 // triangle and render it as a 6-vertex polygon. 71 // It's necessary to achieve numerical stability. 72 // However, the coordinates to interpolate colors are calculated 73 // as miter joins (calc_intersection). triangle(double x1,double y1,double x2,double y2,double x3,double y3,double d)74 void triangle(double x1, double y1, 75 double x2, double y2, 76 double x3, double y3, 77 double d) 78 { 79 m_coord[0].x = m_x[0] = x1; 80 m_coord[0].y = m_y[0] = y1; 81 m_coord[1].x = m_x[1] = x2; 82 m_coord[1].y = m_y[1] = y2; 83 m_coord[2].x = m_x[2] = x3; 84 m_coord[2].y = m_y[2] = y3; 85 m_cmd[0] = path_cmd_move_to; 86 m_cmd[1] = path_cmd_line_to; 87 m_cmd[2] = path_cmd_line_to; 88 m_cmd[3] = path_cmd_stop; 89 90 if(d != 0.0) 91 { 92 dilate_triangle(m_coord[0].x, m_coord[0].y, 93 m_coord[1].x, m_coord[1].y, 94 m_coord[2].x, m_coord[2].y, 95 m_x, m_y, d); 96 97 calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5], 98 m_x[0], m_y[0], m_x[1], m_y[1], 99 &m_coord[0].x, &m_coord[0].y); 100 101 calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1], 102 m_x[2], m_y[2], m_x[3], m_y[3], 103 &m_coord[1].x, &m_coord[1].y); 104 105 calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3], 106 m_x[4], m_y[4], m_x[5], m_y[5], 107 &m_coord[2].x, &m_coord[2].y); 108 m_cmd[3] = path_cmd_line_to; 109 m_cmd[4] = path_cmd_line_to; 110 m_cmd[5] = path_cmd_line_to; 111 m_cmd[6] = path_cmd_stop; 112 } 113 } 114 115 //-------------------------------------------------------------------- 116 // Vertex Source Interface to feed the coordinates to the rasterizer rewind(unsigned)117 void rewind(unsigned) 118 { 119 m_vertex = 0; 120 } 121 122 //-------------------------------------------------------------------- vertex(double * x,double * y)123 unsigned vertex(double* x, double* y) 124 { 125 *x = m_x[m_vertex]; 126 *y = m_y[m_vertex]; 127 return m_cmd[m_vertex++]; 128 } 129 130 protected: 131 //-------------------------------------------------------------------- arrange_vertices(coord_type * coord)132 void arrange_vertices(coord_type* coord) const 133 { 134 coord[0] = m_coord[0]; 135 coord[1] = m_coord[1]; 136 coord[2] = m_coord[2]; 137 138 if(m_coord[0].y > m_coord[2].y) 139 { 140 coord[0] = m_coord[2]; 141 coord[2] = m_coord[0]; 142 } 143 144 coord_type tmp; 145 if(coord[0].y > coord[1].y) 146 { 147 tmp = coord[1]; 148 coord[1] = coord[0]; 149 coord[0] = tmp; 150 } 151 152 if(coord[1].y > coord[2].y) 153 { 154 tmp = coord[2]; 155 coord[2] = coord[1]; 156 coord[1] = tmp; 157 } 158 } 159 160 private: 161 //-------------------------------------------------------------------- 162 coord_type m_coord[3]; 163 double m_x[8]; 164 double m_y[8]; 165 unsigned m_cmd[8]; 166 unsigned m_vertex; 167 }; 168 169 } 170 171 #endif 172 173