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