1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
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.
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 // mcseemagg@yahoo.com
13 // http://www.antigrain.com
14 //----------------------------------------------------------------------------
16 #ifndef AGG_SPAN_GOURAUD_INCLUDED
17 #define AGG_SPAN_GOURAUD_INCLUDED
19 #include "agg_basics.h"
25 //============================================================span_gouraud
26 template<class ColorT
> class span_gouraud
29 typedef ColorT color_type
;
38 //--------------------------------------------------------------------
42 m_cmd
[0] = path_cmd_stop
;
45 //--------------------------------------------------------------------
46 span_gouraud(const color_type
& c1
,
56 triangle(x1
, y1
, x2
, y2
, x3
, y3
, d
);
59 //--------------------------------------------------------------------
60 void colors(ColorT c1
, ColorT c2
, ColorT c3
)
62 m_coord
[0].color
= c1
;
63 m_coord
[1].color
= c2
;
64 m_coord
[2].color
= c3
;
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).
74 void triangle(double x1
, double y1
,
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
;
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
,
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
);
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
);
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
;
115 //--------------------------------------------------------------------
116 // Vertex Source Interface to feed the coordinates to the rasterizer
117 void rewind(unsigned)
122 //--------------------------------------------------------------------
123 unsigned vertex(double* x
, double* y
)
127 return m_cmd
[m_vertex
++];
131 //--------------------------------------------------------------------
132 void arrange_vertices(coord_type
* coord
) const
134 coord
[0] = m_coord
[0];
135 coord
[1] = m_coord
[1];
136 coord
[2] = m_coord
[2];
138 if(m_coord
[0].y
> m_coord
[2].y
)
140 coord
[0] = m_coord
[2];
141 coord
[2] = m_coord
[0];
145 if(coord
[0].y
> coord
[1].y
)
152 if(coord
[1].y
> coord
[2].y
)
161 //--------------------------------------------------------------------
162 coord_type m_coord
[3];