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 // Adaptation for high precision colors has been sponsored by
17 // Liberty Technology Systems, Inc., visit http://lib-sys.com
19 // Liberty Technology Systems, Inc. is the provider of
20 // PostScript and PDF technology for software developers.
22 //----------------------------------------------------------------------------
24 #ifndef AGG_SPAN_GOURAUD_RGBA_INCLUDED
25 #define AGG_SPAN_GOURAUD_RGBA_INCLUDED
27 #include "agg_basics.h"
28 #include "agg_color_rgba.h"
29 #include "agg_dda_line.h"
30 #include "agg_span_gouraud.h"
35 //=======================================================span_gouraud_rgba
36 template<class ColorT
> class span_gouraud_rgba
: public span_gouraud
<ColorT
>
39 typedef ColorT color_type
;
40 typedef typename
ColorT::value_type value_type
;
41 typedef span_gouraud
<color_type
> base_type
;
42 typedef typename
base_type::coord_type coord_type
;
46 subpixel_scale
= 1 << subpixel_shift
50 //--------------------------------------------------------------------
53 void init(const coord_type
& c1
, const coord_type
& c2
)
58 double dy
= c2
.y
- c1
.y
;
59 m_1dy
= (dy
< 1e-5) ? 1e5
: 1.0 / dy
;
64 m_dr
= c2
.color
.r
- m_r1
;
65 m_dg
= c2
.color
.g
- m_g1
;
66 m_db
= c2
.color
.b
- m_b1
;
67 m_da
= c2
.color
.a
- m_a1
;
72 double k
= (y
- m_y1
) * m_1dy
;
75 m_r
= m_r1
+ iround(m_dr
* k
);
76 m_g
= m_g1
+ iround(m_dg
* k
);
77 m_b
= m_b1
+ iround(m_db
* k
);
78 m_a
= m_a1
+ iround(m_da
* k
);
79 m_x
= iround((m_x1
+ m_dx
* k
) * subpixel_scale
);
103 //--------------------------------------------------------------------
104 span_gouraud_rgba() {}
105 span_gouraud_rgba(const color_type
& c1
,
106 const color_type
& c2
,
107 const color_type
& c3
,
108 double x1
, double y1
,
109 double x2
, double y2
,
110 double x3
, double y3
,
112 base_type(c1
, c2
, c3
, x1
, y1
, x2
, y2
, x3
, y3
, d
)
115 //--------------------------------------------------------------------
119 base_type::arrange_vertices(coord
);
121 m_y2
= int(coord
[1].y
);
123 m_swap
= cross_product(coord
[0].x
, coord
[0].y
,
124 coord
[2].x
, coord
[2].y
,
125 coord
[1].x
, coord
[1].y
) < 0.0;
127 m_rgba1
.init(coord
[0], coord
[2]);
128 m_rgba2
.init(coord
[0], coord
[1]);
129 m_rgba3
.init(coord
[1], coord
[2]);
132 //--------------------------------------------------------------------
133 void generate(color_type
* span
, int x
, int y
, unsigned len
)
135 m_rgba1
.calc(y
);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y);
136 const rgba_calc
* pc1
= &m_rgba1
;
137 const rgba_calc
* pc2
= &m_rgba2
;
141 // Bottom part of the triangle (first subtriangle)
142 //-------------------------
143 m_rgba2
.calc(y
+ m_rgba2
.m_1dy
);
147 // Upper part (second subtriangle)
148 m_rgba3
.calc(y
- m_rgba3
.m_1dy
);
149 //-------------------------
155 // It means that the triangle is oriented clockwise,
156 // so that we need to swap the controlling structures
157 //-------------------------
158 const rgba_calc
* t
= pc2
;
163 // Get the horizontal length with subpixel accuracy
164 // and protect it from division by zero
165 //-------------------------
166 int nlen
= abs(pc2
->m_x
- pc1
->m_x
);
167 if(nlen
<= 0) nlen
= 1;
169 dda_line_interpolator
<14> r(pc1
->m_r
, pc2
->m_r
, nlen
);
170 dda_line_interpolator
<14> g(pc1
->m_g
, pc2
->m_g
, nlen
);
171 dda_line_interpolator
<14> b(pc1
->m_b
, pc2
->m_b
, nlen
);
172 dda_line_interpolator
<14> a(pc1
->m_a
, pc2
->m_a
, nlen
);
174 // Calculate the starting point of the gradient with subpixel
175 // accuracy and correct (roll back) the interpolators.
176 // This operation will also clip the beginning of the span
178 //-------------------------
179 int start
= pc1
->m_x
- (x
<< subpixel_shift
);
187 enum lim_e
{ lim
= color_type::base_mask
};
189 // Beginning part of the span. Since we rolled back the
190 // interpolators, the color values may have overflow.
191 // So that, we render the beginning part with checking
192 // for overflow. It lasts until "start" is positive;
193 // typically it's 1-2 pixels, but may be more in some cases.
194 //-------------------------
195 while(len
&& start
> 0)
201 if(vr
< 0) vr
= 0; if(vr
> lim
) vr
= lim
;
202 if(vg
< 0) vg
= 0; if(vg
> lim
) vg
= lim
;
203 if(vb
< 0) vb
= 0; if(vb
> lim
) vb
= lim
;
204 if(va
< 0) va
= 0; if(va
> lim
) va
= lim
;
205 span
->r
= (value_type
)vr
;
206 span
->g
= (value_type
)vg
;
207 span
->b
= (value_type
)vb
;
208 span
->a
= (value_type
)va
;
213 nlen
-= subpixel_scale
;
214 start
-= subpixel_scale
;
219 // Middle part, no checking for overflow.
220 // Actual spans can be longer than the calculated length
221 // because of anti-aliasing, thus, the interpolators can
222 // overflow. But while "nlen" is positive we are safe.
223 //-------------------------
224 while(len
&& nlen
> 0)
226 span
->r
= (value_type
)r
.y();
227 span
->g
= (value_type
)g
.y();
228 span
->b
= (value_type
)b
.y();
229 span
->a
= (value_type
)a
.y();
234 nlen
-= subpixel_scale
;
239 // Ending part; checking for overflow.
240 // Typically it's 1-2 pixels, but may be more in some cases.
241 //-------------------------
248 if(vr
< 0) vr
= 0; if(vr
> lim
) vr
= lim
;
249 if(vg
< 0) vg
= 0; if(vg
> lim
) vg
= lim
;
250 if(vb
< 0) vb
= 0; if(vb
> lim
) vb
= lim
;
251 if(va
< 0) va
= 0; if(va
> lim
) va
= lim
;
252 span
->r
= (value_type
)vr
;
253 span
->g
= (value_type
)vg
;
254 span
->b
= (value_type
)vb
;
255 span
->a
= (value_type
)va
;