Add ability to scale SVGs by specifying different image dimensions.

This commit is contained in:
Daniel Patterson 2015-06-18 08:59:39 -07:00
parent 776436db6e
commit f6a858b6c9
2 changed files with 33 additions and 10 deletions

View file

@ -178,7 +178,7 @@ boost::optional<box2d<double> > svg_reader<T>::bounding_box() const
}
template <typename T>
void svg_reader<T>::read(unsigned x0, unsigned y0,image_rgba8& image)
void svg_reader<T>::read(unsigned x0, unsigned y0, image_rgba8& image)
{
using pixfmt = agg::pixfmt_rgba32_pre;
using renderer_base = agg::renderer_base<pixfmt>;
@ -187,12 +187,11 @@ void svg_reader<T>::read(unsigned x0, unsigned y0,image_rgba8& image)
agg::scanline_u8 sl;
double opacity = 1;
int w = width_;
int h = height_;
unsigned w = std::min(unsigned(image.width()),width_ - x0);
unsigned h = std::min(unsigned(image.height()),height_ - y0);
// 10 pixel buffer to avoid edge clipping of 100% svg's
mapnik::image_rgba8 im(w+0,h+0);
agg::rendering_buffer buf(im.bytes(), im.width(), im.height(), im.row_size());
agg::rendering_buffer buf(image.bytes(), image.width(), image.height(), image.row_size());
pixfmt pixf(buf);
renderer_base renb(pixf);
@ -200,8 +199,10 @@ void svg_reader<T>::read(unsigned x0, unsigned y0,image_rgba8& image)
mapnik::coord<double,2> c = bbox.center();
// center the svg marker on '0,0'
agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
// Scale if necessary
mtx.scale((double)w / width_, (double)h / height_);
// render the marker at the center of the marker box
mtx.translate(0.5 * im.width(), 0.5 * im.height());
mtx.translate(0.5 * image.width(), 0.5 * image.height());
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(marker->get_data()->source());
mapnik::svg::svg_path_adapter svg_path(stl_storage);
@ -213,9 +214,7 @@ void svg_reader<T>::read(unsigned x0, unsigned y0,image_rgba8& image)
svg_renderer_this.render(ras_ptr, sl, renb, mtx, opacity, bbox);
demultiply_alpha(im);
image = im;
demultiply_alpha(image);
}

View file

@ -42,7 +42,7 @@ SECTION("svg_empty")
CHECK(height == 0);
}
SECTION("svg_blank")
SECTION("svg_simple")
{
std::string imagedata = "<svg width='100' height='100'><g id='a'><ellipse fill='#FFFFFF' stroke='#000000' stroke-width='4' cx='50' cy='50' rx='25' ry='25'/></g></svg>";
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(imagedata.c_str(), imagedata.length()));
@ -62,5 +62,29 @@ SECTION("svg_blank")
} // END SECTION
SECTION("svg_scaled")
{
std::string imagedata = "<svg width='100' height='100'><g id='a'><ellipse fill='#FFFFFF' stroke='#000000' stroke-width='4' cx='50' cy='50' rx='25' ry='25'/></g></svg>";
std::unique_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(imagedata.c_str(), imagedata.length()));
CHECK(reader.get());
unsigned width = reader->width();
unsigned height = reader->height();
CHECK(width == 100);
CHECK(height == 100);
mapnik::image_any im = reader->read(0,0,width/2,height/2);
mapnik::image_rgba8 raw = im.get<mapnik::image_rgba8>();
CHECK(im.width() == 50);
CHECK(im.height() == 50);
std::string pngdata = mapnik::save_to_string<mapnik::image_rgba8>(raw,"png");
mapnik::save_to_file<mapnik::image_rgba8>(raw,"test.png","png");
CHECK(pngdata.length() == 1270);
} // END SECTION
} // END TEST CASE