protect against invalid memory access if agg gradient lookup fails to build
This commit is contained in:
parent
423a8007ba
commit
f4c3620d67
4 changed files with 139 additions and 132 deletions
6
deps/agg/include/agg_gradient_lut.h
vendored
6
deps/agg/include/agg_gradient_lut.h
vendored
|
@ -137,7 +137,7 @@ namespace agg
|
|||
//--------------------------------------------------------------------
|
||||
void remove_all();
|
||||
void add_color(double offset, const color_type& color);
|
||||
void build_lut();
|
||||
bool build_lut();
|
||||
|
||||
// Size-index Interface. This class can be used directly as the
|
||||
// ColorF in span_gradient. All it needs is two access methods
|
||||
|
@ -202,7 +202,7 @@ namespace agg
|
|||
|
||||
//------------------------------------------------------------------------
|
||||
template<class T, unsigned S>
|
||||
void gradient_lut<T,S>::build_lut()
|
||||
bool gradient_lut<T,S>::build_lut()
|
||||
{
|
||||
quick_sort(m_color_profile, offset_less);
|
||||
m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal));
|
||||
|
@ -234,7 +234,9 @@ namespace agg
|
|||
{
|
||||
m_color_lut[end] = c;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -481,75 +481,79 @@ template <typename Src>
|
|||
void apply_filter(Src & src, colorize_alpha const& op)
|
||||
{
|
||||
using namespace boost::gil;
|
||||
|
||||
agg::gradient_lut<agg::color_interpolator<agg::rgba8> > grad_lut;
|
||||
grad_lut.remove_all();
|
||||
std::size_t size = op.size();
|
||||
if (size < 2) return;
|
||||
|
||||
double step = 1.0/(size-1);
|
||||
double offset = 0.0;
|
||||
BOOST_FOREACH( mapnik::filter::color_stop const& stop, op)
|
||||
if (size > 1)
|
||||
{
|
||||
mapnik::color const& c = stop.color;
|
||||
double stop_offset = stop.offset;
|
||||
if (stop_offset == 0)
|
||||
// interpolate multiple stops
|
||||
agg::gradient_lut<agg::color_interpolator<agg::rgba8> > grad_lut;
|
||||
double step = 1.0/(size-1);
|
||||
double offset = 0.0;
|
||||
BOOST_FOREACH( mapnik::filter::color_stop const& stop, op)
|
||||
{
|
||||
stop_offset = offset;
|
||||
}
|
||||
grad_lut.add_color(stop_offset, agg::rgba(c.red()/256.0,
|
||||
c.green()/256.0,
|
||||
c.blue()/256.0,
|
||||
c.alpha()/256.0));
|
||||
offset += step;
|
||||
}
|
||||
grad_lut.build_lut();
|
||||
|
||||
rgba8_view_t src_view = rgba8_view(src);
|
||||
for (int y=0; y<src_view.height(); ++y)
|
||||
{
|
||||
rgba8_view_t::x_iterator src_it = src_view.row_begin(y);
|
||||
for (int x=0; x<src_view.width(); ++x)
|
||||
{
|
||||
uint8_t & r = get_color(src_it[x], red_t());
|
||||
uint8_t & g = get_color(src_it[x], green_t());
|
||||
uint8_t & b = get_color(src_it[x], blue_t());
|
||||
uint8_t & a = get_color(src_it[x], alpha_t());
|
||||
if ( a > 0)
|
||||
mapnik::color const& c = stop.color;
|
||||
double stop_offset = stop.offset;
|
||||
if (stop_offset == 0)
|
||||
{
|
||||
agg::rgba8 c = grad_lut[a];
|
||||
r = (c.r * a + 255) >> 8;
|
||||
g = (c.g * a + 255) >> 8;
|
||||
b = (c.b * a + 255) >> 8;
|
||||
#if 0
|
||||
// rainbow
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
if (a < 64)
|
||||
stop_offset = offset;
|
||||
}
|
||||
grad_lut.add_color(stop_offset, agg::rgba(c.red()/256.0,
|
||||
c.green()/256.0,
|
||||
c.blue()/256.0,
|
||||
c.alpha()/256.0));
|
||||
offset += step;
|
||||
}
|
||||
if (grad_lut.build_lut())
|
||||
{
|
||||
rgba8_view_t src_view = rgba8_view(src);
|
||||
for (int y=0; y<src_view.height(); ++y)
|
||||
{
|
||||
rgba8_view_t::x_iterator src_it = src_view.row_begin(y);
|
||||
for (int x=0; x<src_view.width(); ++x)
|
||||
{
|
||||
g = a * 4;
|
||||
b = 255;
|
||||
uint8_t & r = get_color(src_it[x], red_t());
|
||||
uint8_t & g = get_color(src_it[x], green_t());
|
||||
uint8_t & b = get_color(src_it[x], blue_t());
|
||||
uint8_t & a = get_color(src_it[x], alpha_t());
|
||||
if ( a > 0)
|
||||
{
|
||||
agg::rgba8 c = grad_lut[a];
|
||||
r = (c.r * a + 255) >> 8;
|
||||
g = (c.g * a + 255) >> 8;
|
||||
b = (c.b * a + 255) >> 8;
|
||||
if (r>a) r=a;
|
||||
if (g>a) g=a;
|
||||
if (b>a) b=a;
|
||||
#if 0
|
||||
// rainbow
|
||||
r = 0;
|
||||
g = 0;
|
||||
b = 0;
|
||||
if (a < 64)
|
||||
{
|
||||
g = a * 4;
|
||||
b = 255;
|
||||
}
|
||||
else if (a >= 64 && a < 128)
|
||||
{
|
||||
g = 255;
|
||||
b = 255 - ((a - 64) * 4);
|
||||
}
|
||||
else if (a >= 128 && a < 192)
|
||||
{
|
||||
r = (a - 128) * 4;
|
||||
g = 255;
|
||||
}
|
||||
else // >= 192
|
||||
{
|
||||
r = 255;
|
||||
g = 255 - ((a - 192) * 4);
|
||||
}
|
||||
r = (r * a + 255) >> 8;
|
||||
g = (g * a + 255) >> 8;
|
||||
b = (b * a + 255) >> 8;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (a >= 64 && a < 128)
|
||||
{
|
||||
g = 255;
|
||||
b = 255 - ((a - 64) * 4);
|
||||
}
|
||||
else if (a >= 128 && a < 192)
|
||||
{
|
||||
r = (a - 128) * 4;
|
||||
g = 255;
|
||||
}
|
||||
else // >= 192
|
||||
{
|
||||
r = 255;
|
||||
g = 255 - ((a - 192) * 4);
|
||||
}
|
||||
r = (r * a + 255) >> 8;
|
||||
g = (g * a + 255) >> 8;
|
||||
b = (b * a + 255) >> 8;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,87 +151,88 @@ public:
|
|||
unsigned a = stop_color.alpha();
|
||||
m_gradient_lut.add_color(st.first, agg::rgba8_pre(r, g, b, int(a * opacity)));
|
||||
}
|
||||
m_gradient_lut.build_lut();
|
||||
|
||||
agg::trans_affine transform = mtx;
|
||||
transform.invert();
|
||||
agg::trans_affine tr;
|
||||
tr = grad.get_transform();
|
||||
tr.invert();
|
||||
transform *= tr;
|
||||
|
||||
if (grad.get_units() != USER_SPACE_ON_USE)
|
||||
if (m_gradient_lut.build_lut())
|
||||
{
|
||||
double bx1=symbol_bbox.minx();
|
||||
double by1=symbol_bbox.miny();
|
||||
double bx2=symbol_bbox.maxx();
|
||||
double by2=symbol_bbox.maxy();
|
||||
agg::trans_affine transform = mtx;
|
||||
transform.invert();
|
||||
agg::trans_affine tr;
|
||||
tr = grad.get_transform();
|
||||
tr.invert();
|
||||
transform *= tr;
|
||||
|
||||
if (grad.get_units() == OBJECT_BOUNDING_BOX)
|
||||
if (grad.get_units() != USER_SPACE_ON_USE)
|
||||
{
|
||||
bounding_rect_single(curved_trans, path_id, &bx1, &by1, &bx2, &by2);
|
||||
double bx1=symbol_bbox.minx();
|
||||
double by1=symbol_bbox.miny();
|
||||
double bx2=symbol_bbox.maxx();
|
||||
double by2=symbol_bbox.maxy();
|
||||
|
||||
if (grad.get_units() == OBJECT_BOUNDING_BOX)
|
||||
{
|
||||
bounding_rect_single(curved_trans, path_id, &bx1, &by1, &bx2, &by2);
|
||||
}
|
||||
|
||||
transform.translate(-bx1,-by1);
|
||||
transform.scale(1.0/(bx2-bx1),1.0/(by2-by1));
|
||||
}
|
||||
|
||||
transform.translate(-bx1,-by1);
|
||||
transform.scale(1.0/(bx2-bx1),1.0/(by2-by1));
|
||||
}
|
||||
if (grad.get_gradient_type() == RADIAL)
|
||||
{
|
||||
typedef agg::gradient_radial_focus gradient_adaptor_type;
|
||||
typedef agg::span_gradient<agg::rgba8,
|
||||
interpolator_type,
|
||||
gradient_adaptor_type,
|
||||
color_func_type> span_gradient_type;
|
||||
|
||||
if (grad.get_gradient_type() == RADIAL)
|
||||
{
|
||||
typedef agg::gradient_radial_focus gradient_adaptor_type;
|
||||
typedef agg::span_gradient<agg::rgba8,
|
||||
interpolator_type,
|
||||
gradient_adaptor_type,
|
||||
color_func_type> span_gradient_type;
|
||||
// the agg radial gradient assumes it is centred on 0
|
||||
transform.translate(-x2,-y2);
|
||||
|
||||
// the agg radial gradient assumes it is centred on 0
|
||||
transform.translate(-x2,-y2);
|
||||
// scale everything up since agg turns things into integers a bit too soon
|
||||
int scaleup=255;
|
||||
radius*=scaleup;
|
||||
x1*=scaleup;
|
||||
y1*=scaleup;
|
||||
x2*=scaleup;
|
||||
y2*=scaleup;
|
||||
|
||||
// scale everything up since agg turns things into integers a bit too soon
|
||||
int scaleup=255;
|
||||
radius*=scaleup;
|
||||
x1*=scaleup;
|
||||
y1*=scaleup;
|
||||
x2*=scaleup;
|
||||
y2*=scaleup;
|
||||
transform.scale(scaleup,scaleup);
|
||||
interpolator_type span_interpolator(transform);
|
||||
gradient_adaptor_type gradient_adaptor(radius,(x1-x2),(y1-y2));
|
||||
|
||||
transform.scale(scaleup,scaleup);
|
||||
interpolator_type span_interpolator(transform);
|
||||
gradient_adaptor_type gradient_adaptor(radius,(x1-x2),(y1-y2));
|
||||
span_gradient_type span_gradient(span_interpolator,
|
||||
gradient_adaptor,
|
||||
m_gradient_lut,
|
||||
0, radius);
|
||||
|
||||
span_gradient_type span_gradient(span_interpolator,
|
||||
gradient_adaptor,
|
||||
m_gradient_lut,
|
||||
0, radius);
|
||||
render_scanlines_aa(ras, sl, ren, m_alloc, span_gradient);
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef linear_gradient_from_segment gradient_adaptor_type;
|
||||
typedef agg::span_gradient<agg::rgba8,
|
||||
interpolator_type,
|
||||
gradient_adaptor_type,
|
||||
color_func_type> span_gradient_type;
|
||||
|
||||
render_scanlines_aa(ras, sl, ren, m_alloc, span_gradient);
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef linear_gradient_from_segment gradient_adaptor_type;
|
||||
typedef agg::span_gradient<agg::rgba8,
|
||||
interpolator_type,
|
||||
gradient_adaptor_type,
|
||||
color_func_type> span_gradient_type;
|
||||
// scale everything up since agg turns things into integers a bit too soon
|
||||
int scaleup=255;
|
||||
x1*=scaleup;
|
||||
y1*=scaleup;
|
||||
x2*=scaleup;
|
||||
y2*=scaleup;
|
||||
|
||||
// scale everything up since agg turns things into integers a bit too soon
|
||||
int scaleup=255;
|
||||
x1*=scaleup;
|
||||
y1*=scaleup;
|
||||
x2*=scaleup;
|
||||
y2*=scaleup;
|
||||
transform.scale(scaleup,scaleup);
|
||||
|
||||
transform.scale(scaleup,scaleup);
|
||||
interpolator_type span_interpolator(transform);
|
||||
gradient_adaptor_type gradient_adaptor(x1,y1,x2,y2);
|
||||
|
||||
interpolator_type span_interpolator(transform);
|
||||
gradient_adaptor_type gradient_adaptor(x1,y1,x2,y2);
|
||||
span_gradient_type span_gradient(span_interpolator,
|
||||
gradient_adaptor,
|
||||
m_gradient_lut,
|
||||
0, scaleup);
|
||||
|
||||
span_gradient_type span_gradient(span_interpolator,
|
||||
gradient_adaptor,
|
||||
m_gradient_lut,
|
||||
0, scaleup);
|
||||
|
||||
render_scanlines_aa(ras, sl, ren, m_alloc, span_gradient);
|
||||
render_scanlines_aa(ras, sl, ren, m_alloc, span_gradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</Rule>
|
||||
</Style>
|
||||
|
||||
<Style name="style" image-filters="colorize-alpha(blue 99%,blue)">
|
||||
<Style name="style" image-filters="colorize-alpha(blue 100%,blue)">
|
||||
<Rule>
|
||||
<PointSymbolizer file="../../data/images/marker.png" allow-overlap="true" />
|
||||
</Rule>
|
||||
|
|
Loading…
Add table
Reference in a new issue