41
42
std::vector<gradient_stop> stops;
42
43
gradient_type_e gradient_type;
43
44
gradient_spread_e spread_method;
45
gradient_units_e units;
48
agg::trans_affine affine_mtx;
45
51
gradient(gradient_type_e gradient_type);
46
52
gradient(gradient_type_e gradient_type,
47
53
std::vector<point> points,
48
54
std::vector<gradient_stop> stops,
49
const char* spread_method);
55
const char* spread_method,
56
const char* units="userSpaceOnUse");
52
59
template <typename pixfmt_type>
59
66
if (this->points[0].first == this->points[1].first)
61
68
agg::gradient_y grad_func;
62
this->_apply(pixfmt, ras, rbase, grad_func);
70
// apply the proper fill adapter based on the spread method
72
if (this->spread_method == kiva::reflect)
74
agg::gradient_reflect_adaptor<agg::gradient_y> adaptor(grad_func);
75
this->_apply(pixfmt, ras, rbase, adaptor);
77
else if (this->spread_method == kiva::repeat)
79
agg::gradient_repeat_adaptor<agg::gradient_y> adaptor(grad_func);
80
this->_apply(pixfmt, ras, rbase, adaptor);
84
this->_apply(pixfmt, ras, rbase, grad_func);
64
87
else if (this->points[0].second == this->points[1].second)
66
89
agg::gradient_x grad_func;
67
this->_apply(pixfmt, ras, rbase, grad_func);
91
// apply the proper fill adapter based on the spread method
93
if (this->spread_method == kiva::reflect)
95
agg::gradient_reflect_adaptor<agg::gradient_x> adaptor(grad_func);
96
this->_apply(pixfmt, ras, rbase, adaptor);
98
else if (this->spread_method == kiva::repeat)
100
agg::gradient_repeat_adaptor<agg::gradient_x> adaptor(grad_func);
101
this->_apply(pixfmt, ras, rbase, adaptor);
105
this->_apply(pixfmt, ras, rbase, grad_func);
71
110
agg::gradient_x grad_func;
72
this->_apply(pixfmt, ras, rbase, grad_func);
112
// apply the proper fill adapter based on the spread method
114
if (this->spread_method == kiva::reflect)
116
agg::gradient_reflect_adaptor<agg::gradient_x> adaptor(grad_func);
117
this->_apply(pixfmt, ras, rbase, adaptor);
119
else if (this->spread_method == kiva::repeat)
121
agg::gradient_repeat_adaptor<agg::gradient_x> adaptor(grad_func);
122
this->_apply(pixfmt, ras, rbase, adaptor);
126
this->_apply(pixfmt, ras, rbase, grad_func);
77
132
agg::gradient_radial_focus grad_func(points[1].first,
78
133
points[2].first - points[0].first,
79
134
points[2].second - points[0].second);
80
this->_apply(pixfmt, ras, rbase, grad_func);
136
if (this->spread_method == kiva::reflect)
138
agg::gradient_reflect_adaptor<agg::gradient_radial_focus> adaptor(grad_func);
139
this->_apply(pixfmt, ras, rbase, adaptor);
141
else if (this->spread_method == kiva::repeat)
143
agg::gradient_repeat_adaptor<agg::gradient_radial_focus> adaptor(grad_func);
144
this->_apply(pixfmt, ras, rbase, adaptor);
148
this->_apply(pixfmt, ras, rbase, grad_func);
153
void set_ctm(const agg::trans_affine& mtx)
155
this->affine_mtx = mtx;
86
160
template <class pixfmt_type, class gradient_func_type>
117
191
double d2 = sqrt(dx * dx + dy * dy);
193
if (this->units == kiva::user_space)
195
gradient_mtx *= this->affine_mtx;
197
// scale the translation part of the transform, otherwise Agg
198
// will draw the gradient at the wrong location
200
double x, y, scale_x, scale_y;
201
kiva::get_translation(this->affine_mtx, &x, &y);
202
kiva::get_scale(this->affine_mtx, &scale_x, &scale_y);
203
double scaled_trans_x = x*scale_x;
204
double scaled_trans_y = -y*scale_y;
206
// std::cout << "translations: " << x << ", " << y << std::endl;
207
// std::cout << "scaled: " << scale_x << ", " << scale_y << std::endl;
208
// std::cout << "scaled translations: " << scaled_trans_x << ", " << scaled_trans_y << std::endl;
211
gradient_mtx.store_to(temp);
212
temp[4] = scaled_trans_x;
213
temp[5] = scaled_trans_y;
214
gradient_mtx.load_from(temp);
217
// std::cout << "starting with affine matrix " << gradient_mtx.m0
218
// << ", " << gradient_mtx.m1
219
// << ", " << gradient_mtx.m2
220
// << ", " << gradient_mtx.m3
221
// << ", " << gradient_mtx.m4
222
// << ", " << gradient_mtx.m5 << std::endl;
224
gradient_mtx *= agg::trans_affine_translation(-points[0].first, -points[0].second);
119
226
if ((this->gradient_type == kiva::grad_radial) && (this->points.size() >2))
121
228
d2 = points[1].first;
122
gradient_mtx *= agg::trans_affine_translation(-points[0].first, -points[0].second);
123
229
// TOOD: apply scaling transform here, determined by dx and dy of the bounding box,
124
230
// if appropriate
128
234
if (points[0].first == points[1].first)
130
gradient_mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / (d2-d1));
131
gradient_mtx *= agg::trans_affine_rotation(atan2(dx, dy));
132
gradient_mtx *= agg::trans_affine_translation(-points[0].first, -points[0].second);
236
gradient_mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / (d2-d1));
237
gradient_mtx *= agg::trans_affine_rotation(atan2(dx, dy));
134
239
else if (points[0].second == points[1].second)
136
241
// No need to rotate
137
gradient_mtx *= agg::trans_affine_translation(-points[0].first, -points[0].second);
141
245
// general case: scale, rotate and translate
142
246
gradient_mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / (d2-d1));
143
247
gradient_mtx *= agg::trans_affine_rotation(atan2(-dy, dx));
144
gradient_mtx *= agg::trans_affine_translation(-points[0].first, -points[0].second);
251
// std::cout << "drawing with affine matrix " << gradient_mtx.m0
252
// << ", " << gradient_mtx.m1
253
// << ", " << gradient_mtx.m2
254
// << ", " << gradient_mtx.m3
255
// << ", " << gradient_mtx.m4
256
// << ", " << gradient_mtx.m5 << std::endl;
148
258
span_gradient_type span_gradient(span_interpolator,
187
297
offset = i/double(array.size());
191
if (this->spread_method == kiva::pad)
193
for (; i < array.size(); i++)
195
array[i] = this->stops.back().color;
198
else if (this->spread_method == kiva::reflect)
200
// TODO: handle 'reflect' spread method
204
// TODO: handle 'repeat' spread method