commit
7e604ed8b0
7 changed files with 95 additions and 43 deletions
14
deps/agg/src/agg_bezier_arc.cpp
vendored
14
deps/agg/src/agg_bezier_arc.cpp
vendored
|
@ -22,7 +22,6 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "agg_bezier_arc.h"
|
#include "agg_bezier_arc.h"
|
||||||
|
|
||||||
|
|
||||||
namespace agg
|
namespace agg
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -144,7 +143,7 @@ void bezier_arc_svg::init(double x0, double y0,
|
||||||
m_radii_ok = true;
|
m_radii_ok = true;
|
||||||
|
|
||||||
if(rx < 0.0) rx = -rx;
|
if(rx < 0.0) rx = -rx;
|
||||||
if(ry < 0.0) ry = -rx;
|
if(ry < 0.0) ry = -ry;
|
||||||
|
|
||||||
// Calculate the middle point between
|
// Calculate the middle point between
|
||||||
// the current and the final points
|
// the current and the final points
|
||||||
|
@ -178,7 +177,6 @@ void bezier_arc_svg::init(double x0, double y0,
|
||||||
pry = ry * ry;
|
pry = ry * ry;
|
||||||
if(radii_check > 10.0) m_radii_ok = false;
|
if(radii_check > 10.0) m_radii_ok = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate (cx1, cy1)
|
// Calculate (cx1, cy1)
|
||||||
//------------------------
|
//------------------------
|
||||||
double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0;
|
double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0;
|
||||||
|
@ -222,15 +220,15 @@ void bezier_arc_svg::init(double x0, double y0,
|
||||||
if(v < -1.0) v = -1.0;
|
if(v < -1.0) v = -1.0;
|
||||||
if(v > 1.0) v = 1.0;
|
if(v > 1.0) v = 1.0;
|
||||||
double sweep_angle = sign * std::acos(v);
|
double sweep_angle = sign * std::acos(v);
|
||||||
|
if (std::fabs(sweep_angle) < pi * 1e-6) m_radii_ok = false;
|
||||||
if(!sweep_flag && sweep_angle > 0)
|
if(!sweep_flag && sweep_angle > 0)
|
||||||
{
|
{
|
||||||
sweep_angle -= pi * 2.0;
|
sweep_angle -= pi * 2.0;
|
||||||
}
|
}
|
||||||
else
|
else if (sweep_flag && sweep_angle < 0)
|
||||||
if (sweep_flag && sweep_angle < 0)
|
{
|
||||||
{
|
sweep_angle += pi * 2.0;
|
||||||
sweep_angle += pi * 2.0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// We can now build and transform the resulting arc
|
// We can now build and transform the resulting arc
|
||||||
//------------------------
|
//------------------------
|
||||||
|
|
|
@ -444,12 +444,13 @@ void path_adapter<VC>::curve3(double x_to, double y_to)
|
||||||
{
|
{
|
||||||
double x0;
|
double x0;
|
||||||
double y0;
|
double y0;
|
||||||
if(is_vertex(vertices_.last_vertex(&x0, &y0)))
|
unsigned last_cmd = last_vertex(&x0, &y0);
|
||||||
|
if (is_vertex(last_cmd))
|
||||||
{
|
{
|
||||||
double x_ctrl;
|
double x_ctrl;
|
||||||
double y_ctrl;
|
double y_ctrl;
|
||||||
unsigned cmd = vertices_.prev_vertex(&x_ctrl, &y_ctrl);
|
unsigned prev_cmd = prev_vertex(&x_ctrl, &y_ctrl);
|
||||||
if(is_curve(cmd))
|
if (is_curve(last_cmd) && is_curve(prev_cmd))
|
||||||
{
|
{
|
||||||
x_ctrl = x0 + x0 - x_ctrl;
|
x_ctrl = x0 + x0 - x_ctrl;
|
||||||
y_ctrl = y0 + y0 - y_ctrl;
|
y_ctrl = y0 + y0 - y_ctrl;
|
||||||
|
@ -491,9 +492,7 @@ void path_adapter<VC>::curve4_rel(double dx_ctrl1, double dy_ctrl1,
|
||||||
rel_to_abs(&dx_ctrl1, &dy_ctrl1);
|
rel_to_abs(&dx_ctrl1, &dy_ctrl1);
|
||||||
rel_to_abs(&dx_ctrl2, &dy_ctrl2);
|
rel_to_abs(&dx_ctrl2, &dy_ctrl2);
|
||||||
rel_to_abs(&dx_to, &dy_to);
|
rel_to_abs(&dx_to, &dy_to);
|
||||||
vertices_.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4);
|
curve4(dx_ctrl1, dy_ctrl1, dx_ctrl2, dy_ctrl2, dx_to, dy_to);
|
||||||
vertices_.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4);
|
|
||||||
vertices_.add_vertex(dx_to, dy_to, path_cmd_curve4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
@ -503,12 +502,13 @@ void path_adapter<VC>::curve4(double x_ctrl2, double y_ctrl2,
|
||||||
{
|
{
|
||||||
double x0;
|
double x0;
|
||||||
double y0;
|
double y0;
|
||||||
if(is_vertex(last_vertex(&x0, &y0)))
|
unsigned last_cmd = last_vertex(&x0, &y0);
|
||||||
|
if (is_vertex(last_cmd))
|
||||||
{
|
{
|
||||||
double x_ctrl1;
|
double x_ctrl1;
|
||||||
double y_ctrl1;
|
double y_ctrl1;
|
||||||
unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1);
|
unsigned prev_cmd = prev_vertex(&x_ctrl1, &y_ctrl1);
|
||||||
if(is_curve(cmd))
|
if (is_curve(last_cmd) && is_curve(prev_cmd))
|
||||||
{
|
{
|
||||||
x_ctrl1 = x0 + x0 - x_ctrl1;
|
x_ctrl1 = x0 + x0 - x_ctrl1;
|
||||||
y_ctrl1 = y0 + y0 - y_ctrl1;
|
y_ctrl1 = y0 + y0 - y_ctrl1;
|
||||||
|
|
|
@ -83,9 +83,9 @@ auto const curve4 = [] (auto const& ctx)
|
||||||
auto const& p1 = boost::fusion::at_c<1>(attr);
|
auto const& p1 = boost::fusion::at_c<1>(attr);
|
||||||
auto const& p2 = boost::fusion::at_c<2>(attr);
|
auto const& p2 = boost::fusion::at_c<2>(attr);
|
||||||
extract_path(ctx).curve4(std::get<0>(p0),std::get<1>(p0),
|
extract_path(ctx).curve4(std::get<0>(p0),std::get<1>(p0),
|
||||||
std::get<0>(p1),std::get<1>(p1),
|
std::get<0>(p1),std::get<1>(p1),
|
||||||
std::get<0>(p2),std::get<1>(p2),
|
std::get<0>(p2),std::get<1>(p2),
|
||||||
x3::get<relative_tag>(ctx));
|
x3::get<relative_tag>(ctx));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto const curve4_smooth = [] (auto const& ctx)
|
auto const curve4_smooth = [] (auto const& ctx)
|
||||||
|
@ -94,8 +94,8 @@ auto const curve4_smooth = [] (auto const& ctx)
|
||||||
auto const& p0 = boost::fusion::at_c<0>(attr);
|
auto const& p0 = boost::fusion::at_c<0>(attr);
|
||||||
auto const& p1 = boost::fusion::at_c<1>(attr);
|
auto const& p1 = boost::fusion::at_c<1>(attr);
|
||||||
extract_path(ctx).curve4(std::get<0>(p0),std::get<1>(p0),
|
extract_path(ctx).curve4(std::get<0>(p0),std::get<1>(p0),
|
||||||
std::get<0>(p1),std::get<1>(p1),
|
std::get<0>(p1),std::get<1>(p1),
|
||||||
x3::get<relative_tag>(ctx));
|
x3::get<relative_tag>(ctx));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto const curve3 = [] (auto const& ctx)
|
auto const curve3 = [] (auto const& ctx)
|
||||||
|
@ -104,15 +104,16 @@ auto const curve3 = [] (auto const& ctx)
|
||||||
auto const& p0 = boost::fusion::at_c<0>(attr);
|
auto const& p0 = boost::fusion::at_c<0>(attr);
|
||||||
auto const& p1 = boost::fusion::at_c<1>(attr);
|
auto const& p1 = boost::fusion::at_c<1>(attr);
|
||||||
extract_path(ctx).curve3(std::get<0>(p0),std::get<1>(p0),
|
extract_path(ctx).curve3(std::get<0>(p0),std::get<1>(p0),
|
||||||
std::get<0>(p1),std::get<1>(p1),
|
std::get<0>(p1),std::get<1>(p1),
|
||||||
x3::get<relative_tag>(ctx));
|
x3::get<relative_tag>(ctx));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto const curve3_smooth = [] (auto const& ctx)
|
auto const curve3_smooth = [] (auto const& ctx)
|
||||||
{
|
{
|
||||||
auto const& attr = _attr(ctx);
|
auto const& attr = _attr(ctx);
|
||||||
extract_path(ctx).curve3(std::get<0>(attr),std::get<1>(attr),
|
extract_path(ctx).curve3(std::get<0>(attr),
|
||||||
x3::get<relative_tag>(ctx));
|
std::get<1>(attr),
|
||||||
|
x3::get<relative_tag>(ctx));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -125,10 +126,10 @@ auto const arc_to = [] (auto & ctx)
|
||||||
bool sweep_flag = boost::fusion::at_c<3>(attr);
|
bool sweep_flag = boost::fusion::at_c<3>(attr);
|
||||||
auto const& v = boost::fusion::at_c<4>(attr);
|
auto const& v = boost::fusion::at_c<4>(attr);
|
||||||
extract_path(ctx).arc_to(std::get<0>(p), std::get<1>(p),
|
extract_path(ctx).arc_to(std::get<0>(p), std::get<1>(p),
|
||||||
util::radians(angle),
|
util::radians(angle),
|
||||||
large_arc_flag, sweep_flag,
|
large_arc_flag, sweep_flag,
|
||||||
std::get<0>(v),std::get<1>(v),
|
std::get<0>(v),std::get<1>(v),
|
||||||
x3::get<relative_tag>(ctx));
|
x3::get<relative_tag>(ctx));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto const close_path = [] (auto const& ctx)
|
auto const close_path = [] (auto const& ctx)
|
||||||
|
|
|
@ -602,7 +602,7 @@ void parse_fill(svg_parser& parser, char const* value)
|
||||||
traverse_tree(parser, gradient_node);
|
traverse_tree(parser, gradient_node);
|
||||||
if (parser.gradient_map_.count(id) > 0)
|
if (parser.gradient_map_.count(id) > 0)
|
||||||
{
|
{
|
||||||
parser.path_.add_stroke_gradient(parser.gradient_map_[id]);
|
parser.path_.add_fill_gradient(parser.gradient_map_[id]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1360,7 +1360,6 @@ void parse_radial_gradient(svg_parser & parser, rapidxml::xml_node<char> const*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parser.gradient_map_[id] = gr;
|
parser.gradient_map_[id] = gr;
|
||||||
//MAPNIK_LOG_DEBUG(svg_parser) << "Found Radial Gradient: " << " " << cx << " " << cy << " " << fx << " " << fy << " " << r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_linear_gradient(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
void parse_linear_gradient(svg_parser & parser, rapidxml::xml_node<char> const* node)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 901ee22d4cdbe1a7caff3f92e10f38ec784b9caa
|
Subproject commit 54a2c2595c81e838810e413d42a57f09fcf41331
|
|
@ -161,4 +161,33 @@ TEST_CASE("SVG path parser") {
|
||||||
std::make_tuple(1050, 125, 2)};
|
std::make_tuple(1050, 125, 2)};
|
||||||
test_path_parser(str, expected);
|
test_path_parser(str, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("Quadratic Bézier")
|
||||||
|
{
|
||||||
|
std::string str = "M200,300 Q400,50 600,300 T1000,300";
|
||||||
|
|
||||||
|
std::vector<std::tuple<double,double,unsigned>> expected = {
|
||||||
|
std::make_tuple(200, 300, 1),
|
||||||
|
std::make_tuple(400, 50, 3),
|
||||||
|
std::make_tuple(600, 300, 3),
|
||||||
|
std::make_tuple(800, 550, 3),
|
||||||
|
std::make_tuple(1000, 300, 3)};
|
||||||
|
test_path_parser(str, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Cubic Bézier")
|
||||||
|
{
|
||||||
|
std::string str = "M100,200 C100,100 250,100 250,200S400,300 400,200";
|
||||||
|
|
||||||
|
std::vector<std::tuple<double,double,unsigned>> expected = {
|
||||||
|
std::make_tuple(100, 200, 1),
|
||||||
|
std::make_tuple(100, 100, 4),
|
||||||
|
std::make_tuple(250, 100, 4),
|
||||||
|
std::make_tuple(250, 200, 4),
|
||||||
|
std::make_tuple(250, 300, 4),
|
||||||
|
std::make_tuple(400, 300, 4),
|
||||||
|
std::make_tuple(400, 200, 4)};
|
||||||
|
|
||||||
|
test_path_parser(str, expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include <mapnik/version.hpp>
|
#include <mapnik/version.hpp>
|
||||||
#include <mapnik/debug.hpp>
|
#include <mapnik/debug.hpp>
|
||||||
|
@ -54,9 +55,11 @@
|
||||||
struct main_marker_visitor
|
struct main_marker_visitor
|
||||||
{
|
{
|
||||||
main_marker_visitor(std::string const& svg_name,
|
main_marker_visitor(std::string const& svg_name,
|
||||||
|
double scale_factor,
|
||||||
bool verbose,
|
bool verbose,
|
||||||
bool auto_open)
|
bool auto_open)
|
||||||
: svg_name_(svg_name),
|
: svg_name_(svg_name),
|
||||||
|
scale_factor_(scale_factor),
|
||||||
verbose_(verbose),
|
verbose_(verbose),
|
||||||
auto_open_(auto_open) {}
|
auto_open_(auto_open) {}
|
||||||
|
|
||||||
|
@ -71,17 +74,33 @@ struct main_marker_visitor
|
||||||
double opacity = 1;
|
double opacity = 1;
|
||||||
double w, h;
|
double w, h;
|
||||||
std::tie(w, h) = marker.dimensions();
|
std::tie(w, h) = marker.dimensions();
|
||||||
|
|
||||||
|
|
||||||
|
double svg_width = w * scale_factor_;
|
||||||
|
double svg_height = h * scale_factor_;
|
||||||
|
|
||||||
|
int output_width = static_cast<int>(std::round(svg_width));
|
||||||
|
int output_height = static_cast<int>(std::round(svg_height));
|
||||||
if (verbose_)
|
if (verbose_)
|
||||||
{
|
{
|
||||||
std::clog << "found width of '" << w << "' and height of '" << h << "'\n";
|
std::clog << "Found width of '" << w << "' and height of '" << h << "'\n";
|
||||||
|
auto b = marker.bounding_box();
|
||||||
|
std::clog << "SVG BBOX:" << b << std::endl;
|
||||||
|
std::clog << "Output image dimensions:[" << output_width << "," << output_height << "]" << std::endl;
|
||||||
}
|
}
|
||||||
mapnik::image_rgba8 im(static_cast<int>(w + 0.5), static_cast<int>(h + 0.5));
|
mapnik::image_rgba8 im(output_width, output_height, true, true);
|
||||||
agg::rendering_buffer buf(im.bytes(), im.width(), im.height(), im.row_size());
|
agg::rendering_buffer buf(im.bytes(), im.width(), im.height(), im.row_size());
|
||||||
pixfmt pixf(buf);
|
pixfmt pixf(buf);
|
||||||
renderer_base renb(pixf);
|
renderer_base renb(pixf);
|
||||||
|
|
||||||
mapnik::box2d<double> const& bbox = {0, 0, w, h};
|
mapnik::box2d<double> const& bbox = {0, 0, svg_width, svg_height};
|
||||||
agg::trans_affine mtx = {};
|
// center the svg marker on '0,0'
|
||||||
|
agg::trans_affine mtx = agg::trans_affine_translation(-0.5 * w, -0.5 * h);
|
||||||
|
// Scale the image
|
||||||
|
mtx.scale(scale_factor_);
|
||||||
|
// render the marker at the center of the marker box
|
||||||
|
mtx.translate(0.5 * svg_width, 0.5 * svg_height);
|
||||||
|
|
||||||
mapnik::svg::vertex_stl_adapter<mapnik::svg::svg_path_storage> stl_storage(marker.get_data()->source());
|
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);
|
mapnik::svg::svg_path_adapter svg_path(stl_storage);
|
||||||
mapnik::svg::renderer_agg<
|
mapnik::svg::renderer_agg<
|
||||||
|
@ -124,6 +143,7 @@ struct main_marker_visitor
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string svg_name_;
|
std::string svg_name_;
|
||||||
|
double scale_factor_ = 1.0;
|
||||||
bool verbose_;
|
bool verbose_;
|
||||||
bool auto_open_;
|
bool auto_open_;
|
||||||
};
|
};
|
||||||
|
@ -138,7 +158,8 @@ int main (int argc,char** argv)
|
||||||
int status = 0;
|
int status = 0;
|
||||||
std::vector<std::string> svg_files;
|
std::vector<std::string> svg_files;
|
||||||
mapnik::logger::instance().set_severity(mapnik::logger::error);
|
mapnik::logger::instance().set_severity(mapnik::logger::error);
|
||||||
|
double scale_factor = 1.0;
|
||||||
|
std::string usage = "Usage: svg2png [options] <svg-file(s)>";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
po::options_description desc("svg2png utility");
|
po::options_description desc("svg2png utility");
|
||||||
|
@ -148,6 +169,7 @@ int main (int argc,char** argv)
|
||||||
("verbose,v","verbose output")
|
("verbose,v","verbose output")
|
||||||
("open,o","automatically open the file after rendering (os x only)")
|
("open,o","automatically open the file after rendering (os x only)")
|
||||||
("strict,s","enables strict SVG parsing")
|
("strict,s","enables strict SVG parsing")
|
||||||
|
("scale-factor", po::value<double>(), "provide scaling factor (default: 1.0)")
|
||||||
("svg",po::value<std::vector<std::string> >(),"svg file to read")
|
("svg",po::value<std::vector<std::string> >(),"svg file to read")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -166,6 +188,7 @@ int main (int argc,char** argv)
|
||||||
if (vm.count("help"))
|
if (vm.count("help"))
|
||||||
{
|
{
|
||||||
std::clog << desc << std::endl;
|
std::clog << desc << std::endl;
|
||||||
|
std::clog << usage << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,24 +206,26 @@ int main (int argc,char** argv)
|
||||||
{
|
{
|
||||||
strict = true;
|
strict = true;
|
||||||
}
|
}
|
||||||
|
if (vm.count("scale-factor"))
|
||||||
|
{
|
||||||
|
scale_factor = vm["scale-factor"].as<double>();
|
||||||
|
}
|
||||||
if (vm.count("svg"))
|
if (vm.count("svg"))
|
||||||
{
|
{
|
||||||
svg_files=vm["svg"].as< std::vector<std::string> >();
|
svg_files=vm["svg"].as< std::vector<std::string> >();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::clog << "please provide an svg file!" << std::endl;
|
std::clog << usage << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>::const_iterator itr = svg_files.begin();
|
std::vector<std::string>::const_iterator itr = svg_files.begin();
|
||||||
if (itr == svg_files.end())
|
if (itr == svg_files.end())
|
||||||
{
|
{
|
||||||
std::clog << "no svg files to render" << std::endl;
|
std::clog << usage << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (itr != svg_files.end())
|
while (itr != svg_files.end())
|
||||||
{
|
{
|
||||||
std::string svg_name (*itr++);
|
std::string svg_name (*itr++);
|
||||||
|
@ -209,7 +234,7 @@ int main (int argc,char** argv)
|
||||||
std::clog << "found: " << svg_name << "\n";
|
std::clog << "found: " << svg_name << "\n";
|
||||||
}
|
}
|
||||||
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false, strict);
|
std::shared_ptr<mapnik::marker const> marker = mapnik::marker_cache::instance().find(svg_name, false, strict);
|
||||||
main_marker_visitor visitor(svg_name, verbose, auto_open);
|
main_marker_visitor visitor(svg_name, scale_factor, verbose, auto_open);
|
||||||
status = mapnik::util::apply_visitor(visitor, *marker);
|
status = mapnik::util::apply_visitor(visitor, *marker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue