SVG parser unit test - add attribute comparison framework + test data
This commit is contained in:
parent
0b62415225
commit
d29aeb2ddb
2 changed files with 101 additions and 65 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit 5206bfd11f122bc8fe81519d39768b30108da03a
|
Subproject commit 95789262db507872c5976756777ee4cf64457ea5
|
|
@ -30,59 +30,124 @@
|
||||||
#include <mapnik/svg/svg_converter.hpp>
|
#include <mapnik/svg/svg_converter.hpp>
|
||||||
#include <mapnik/svg/svg_path_adapter.hpp>
|
#include <mapnik/svg/svg_path_adapter.hpp>
|
||||||
#include <mapnik/svg/svg_path_attributes.hpp>
|
#include <mapnik/svg/svg_path_attributes.hpp>
|
||||||
|
#include <mapnik/util/fs.hpp>
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
// boost
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
#include <boost/property_tree/xml_parser.hpp>
|
||||||
|
#include <boost/property_tree/json_parser.hpp>
|
||||||
|
|
||||||
namespace // internal
|
namespace // internal
|
||||||
{
|
{
|
||||||
template<int MAX>
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, agg::rgba8 const& c)
|
||||||
|
{
|
||||||
|
os << mapnik::color{c.r, c.g, c.b, c.a};
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, mapnik::gradient const& gr)
|
||||||
|
{
|
||||||
|
double cx, cy, fx, fy, r;
|
||||||
|
gr.get_control_points(fx, fy, cx, cy, r);
|
||||||
|
|
||||||
|
os << "<gradient cx=\"" << cx << "\" cy=\"" << cy << "\""
|
||||||
|
<< " fx=\"" << fx << "\" fy=\"" << fy << "\" r=\"" << r << "\">\n";
|
||||||
|
for (auto const& stop : gr.get_stop_array())
|
||||||
|
{
|
||||||
|
os << " <stop offset=\"" << std::get<0>(stop) << "\" color=\"" << std::get<1>(stop) << "\"/>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
os << "</gradient>\n";
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, agg::trans_affine const& tr)
|
||||||
|
{
|
||||||
|
os << "<transform>matrix(" << tr.sx << "," << tr.shy << ","
|
||||||
|
<< tr.shx << "," << tr.sy << "," << tr.tx << ","
|
||||||
|
<< tr.ty << ")</transform>";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
struct group_attribute_visitor
|
struct group_attribute_visitor
|
||||||
{
|
{
|
||||||
group_attribute_visitor(int& index)
|
group_attribute_visitor(std::stringstream& ss, unsigned padding)
|
||||||
: index_(index)
|
: ss_(ss), padding_(padding)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(mapnik::svg::group const& g) const
|
void operator()(mapnik::svg::group const& g) const
|
||||||
{
|
{
|
||||||
std::cerr << " <g opacity=" << g.opacity << ">" << std::endl;
|
padding_ += 2;
|
||||||
|
//ss_ << "padding=>" << padding_ << std::endl;
|
||||||
|
std::string pad(padding_, ' ');
|
||||||
|
ss_ << pad << "<g opacity=\"" << g.opacity << "\">" << std::endl;
|
||||||
for (auto const& elem : g.elements)
|
for (auto const& elem : g.elements)
|
||||||
{
|
{
|
||||||
mapbox::util::apply_visitor(group_attribute_visitor<MAX>(index_), elem);
|
mapbox::util::apply_visitor(group_attribute_visitor(ss_, padding_), elem);
|
||||||
}
|
}
|
||||||
std::cerr << " </g>" << std::endl;
|
ss_ << pad << "</g>" << std::endl;
|
||||||
|
padding_ -= 2;
|
||||||
}
|
}
|
||||||
void operator()(mapnik::svg::path_attributes const& attr) const
|
void operator()(mapnik::svg::path_attributes const& attr) const
|
||||||
{
|
{
|
||||||
if (index_++ == MAX)
|
padding_ += 2;
|
||||||
|
std::string pad(padding_, ' ');
|
||||||
|
ss_ << pad << "<attribute index=\"" << attr.index << "\">" << std::endl;
|
||||||
|
ss_ << pad << attr.transform << std::endl;
|
||||||
|
if (!attr.fill_gradient.get_stop_array().empty())
|
||||||
|
ss_ << pad << attr.fill_gradient;
|
||||||
|
if (!attr.stroke_gradient.get_stop_array().empty())
|
||||||
|
ss_ << pad << attr.stroke_gradient;
|
||||||
|
|
||||||
|
ss_ << pad << " <opacity>" << attr.opacity << "</opacity>" << std::endl;
|
||||||
|
ss_ << pad << " <fill>" << attr.fill_color << "</fill>" << std::endl;
|
||||||
|
ss_ << pad << " <fill-opacity>" << attr.fill_opacity << "</fill-opacity>" << std::endl;
|
||||||
|
ss_ << pad << " <stroke>" << attr.stroke_color << "</stroke>" << std::endl;
|
||||||
|
ss_ << pad << " <stroke-width>" << attr.stroke_width << "</stroke-width>" << std::endl;
|
||||||
|
ss_ << pad << " <stroke-opacity>" << attr.stroke_opacity << "</stroke-opacity>" << std::endl;
|
||||||
|
ss_ << pad << "</attribute>" << std::endl;
|
||||||
|
padding_ -=2;
|
||||||
|
}
|
||||||
|
std::stringstream& ss_;
|
||||||
|
mutable unsigned padding_;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool check_equal_attributes(std::string const& svg_file, mapnik::svg::group const& g)
|
||||||
|
{
|
||||||
|
unsigned padding = 0;
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "<svg opacity=\"" << g.opacity << "\">" << std::endl;
|
||||||
|
for (auto const& elem : g.elements)
|
||||||
{
|
{
|
||||||
std::cerr << " <attribute index=" << attr.index << ">" << std::endl;
|
mapbox::util::apply_visitor(group_attribute_visitor(ss, padding), elem);
|
||||||
std::cerr << " <opacity>" << attr.opacity << "</opacity>" << std::endl;
|
}
|
||||||
// std::cerr << " <fill>" << attr.fill_color << "</fill>" << std::endl;
|
ss << "</svg>" << std::endl;
|
||||||
std::cerr << " <fill-opacity>" << attr.fill_opacity << "</fill-opacity>" << std::endl;
|
|
||||||
// std::cerr << " <stroke>" << attr.stroke_color << "</stroke>" << std::endl;
|
std::string well_known_xml = svg_file + ".xml";
|
||||||
std::cerr << " <stroke-width>" << attr.stroke_width << "</stroke-width>" << std::endl;
|
if (!mapnik::util::exists(well_known_xml))
|
||||||
std::cerr << " <stroke-opacity>" << attr.stroke_opacity << "</stroke-opacity>" << std::endl;
|
{
|
||||||
std::cerr << " </attribute>" << std::endl;
|
std::cerr << "Well-known-xml-filename:" << well_known_xml << std::endl;
|
||||||
|
std::cerr << ss.str() << std::endl;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << " </skip>" << std::endl;
|
boost::property_tree::ptree t0, t1;
|
||||||
}
|
boost::property_tree::read_xml(well_known_xml, t0, boost::property_tree::xml_parser::trim_whitespace);
|
||||||
}
|
boost::property_tree::read_xml(ss, t1, boost::property_tree::xml_parser::trim_whitespace);
|
||||||
int& index_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<int MAX>
|
if (t0 != t1)
|
||||||
void group_attribute_printer(mapnik::svg::group const& g)
|
|
||||||
{
|
|
||||||
std::cerr << "<svg opacity=" << g.opacity << ">" << std::endl;
|
|
||||||
int index = 0;
|
|
||||||
for (auto const& elem : g.elements)
|
|
||||||
{
|
{
|
||||||
mapbox::util::apply_visitor(group_attribute_visitor<MAX>(index), elem);
|
std::cerr << ss.str() << std::endl;
|
||||||
|
}
|
||||||
|
return (t0 == t1);
|
||||||
}
|
}
|
||||||
std::cerr << "</svg>" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct test_parser
|
struct test_parser
|
||||||
|
@ -312,11 +377,9 @@ TEST_CASE("SVG parser")
|
||||||
|
|
||||||
auto const& group_attrs = storage->svg_group();
|
auto const& group_attrs = storage->svg_group();
|
||||||
agg::line_cap_e expected_cap(agg::square_cap);
|
agg::line_cap_e expected_cap(agg::square_cap);
|
||||||
REQUIRE(group_attrs.elements.size() == 1);
|
|
||||||
// FIXME
|
|
||||||
|
|
||||||
// REQUIRE(attrs[0].line_cap == expected_cap);
|
REQUIRE(check_equal_attributes(svg_name, group_attrs));
|
||||||
group_attribute_printer<0>(group_attrs);
|
|
||||||
double x, y;
|
double x, y;
|
||||||
unsigned cmd;
|
unsigned cmd;
|
||||||
std::vector<std::tuple<double, double, unsigned>> vec;
|
std::vector<std::tuple<double, double, unsigned>> vec;
|
||||||
|
@ -480,9 +543,7 @@ TEST_CASE("SVG parser")
|
||||||
|
|
||||||
auto const& group_attrs = storage->svg_group();
|
auto const& group_attrs = storage->svg_group();
|
||||||
agg::line_join_e expected_join(agg::bevel_join);
|
agg::line_join_e expected_join(agg::bevel_join);
|
||||||
REQUIRE(group_attrs.elements.size() == 1);
|
REQUIRE(check_equal_attributes(svg_name, group_attrs));
|
||||||
// FIXME
|
|
||||||
// REQUIRE(attrs[0].line_join == expected_join);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG <line>")
|
SECTION("SVG <line>")
|
||||||
|
@ -717,10 +778,7 @@ TEST_CASE("SVG parser")
|
||||||
|
|
||||||
auto const& group_attrs = storage->svg_group();
|
auto const& group_attrs = storage->svg_group();
|
||||||
|
|
||||||
// REQUIRE(group_attrs.elements.size() == 3);
|
REQUIRE(check_equal_attributes(svg_name, group_attrs));
|
||||||
// FIXME
|
|
||||||
// REQUIRE(attrs[1].fill_gradient == attrs[2].fill_gradient);
|
|
||||||
|
|
||||||
mapnik::svg::svg_path_adapter path(stl_storage);
|
mapnik::svg::svg_path_adapter path(stl_storage);
|
||||||
double x, y;
|
double x, y;
|
||||||
unsigned cmd;
|
unsigned cmd;
|
||||||
|
@ -768,13 +826,7 @@ TEST_CASE("SVG parser")
|
||||||
REQUIRE(storage);
|
REQUIRE(storage);
|
||||||
|
|
||||||
auto const& group_attrs = storage->svg_group();
|
auto const& group_attrs = storage->svg_group();
|
||||||
// FIXME
|
REQUIRE(check_equal_attributes(svg_name, group_attrs));
|
||||||
// REQUIRE(attrs.size() == 3);
|
|
||||||
// REQUIRE(attrs[1].fill_gradient == attrs[2].fill_gradient);
|
|
||||||
// REQUIRE(attrs[1].fill_gradient.get_gradient_type() == mapnik::RADIAL);
|
|
||||||
agg::trans_affine transform;
|
|
||||||
transform *= agg::trans_affine_translation(240, 155);
|
|
||||||
// REQUIRE(attrs[1].fill_gradient.get_transform() == transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG <gradient> with xlink:href")
|
SECTION("SVG <gradient> with xlink:href")
|
||||||
|
@ -790,11 +842,7 @@ TEST_CASE("SVG parser")
|
||||||
REQUIRE(storage);
|
REQUIRE(storage);
|
||||||
|
|
||||||
auto const& group_attrs = storage->svg_group();
|
auto const& group_attrs = storage->svg_group();
|
||||||
// FIXME
|
REQUIRE(check_equal_attributes(svg_name, group_attrs));
|
||||||
// REQUIRE(attrs.elements.size() == 2);
|
|
||||||
// REQUIRE(attrs[0].fill_gradient.get_gradient_type() == mapnik::LINEAR);
|
|
||||||
// REQUIRE(attrs[1].fill_gradient.get_gradient_type() == mapnik::LINEAR);
|
|
||||||
// REQUIRE(attrs[1].fill_gradient.has_stop());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG <gradient> with radial percents")
|
SECTION("SVG <gradient> with radial percents")
|
||||||
|
@ -808,19 +856,7 @@ TEST_CASE("SVG parser")
|
||||||
REQUIRE(bbox == mapnik::box2d<double>(0, 0, 200, 200));
|
REQUIRE(bbox == mapnik::box2d<double>(0, 0, 200, 200));
|
||||||
auto storage = svg.get_data();
|
auto storage = svg.get_data();
|
||||||
REQUIRE(storage);
|
REQUIRE(storage);
|
||||||
|
REQUIRE(check_equal_attributes(svg_name, storage->svg_group()));
|
||||||
double x1, x2, y1, y2, r;
|
|
||||||
// FIXME
|
|
||||||
// auto const& attrs = storage->attributes();
|
|
||||||
// REQUIRE(attrs.size() == 1);
|
|
||||||
// REQUIRE(attrs[0].fill_gradient.get_gradient_type() == mapnik::RADIAL);
|
|
||||||
// REQUIRE(attrs[0].fill_gradient.has_stop());
|
|
||||||
// attrs[0].fill_gradient.get_control_points(x1, y1, x2, y2, r);
|
|
||||||
// REQUIRE(x1 == 0);
|
|
||||||
// REQUIRE(y1 == 0.25);
|
|
||||||
// REQUIRE(x2 == 0.10);
|
|
||||||
// REQUIRE(y2 == 0.10);
|
|
||||||
// REQUIRE(r == 0.75);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("SVG <clipPath>")
|
SECTION("SVG <clipPath>")
|
||||||
|
|
Loading…
Reference in a new issue