From 76042a17009971f1d5fc040ae410bfe4063d9bfa Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Mar 2013 17:40:19 -0800 Subject: [PATCH] parse and setup ability to known original, declared svg width/height - refs #1122 --- include/mapnik/marker.hpp | 4 ++-- include/mapnik/marker_helpers.hpp | 16 ++++++++++----- include/mapnik/svg/svg_converter.hpp | 18 +++++++++++++++++ include/mapnik/svg/svg_parser.hpp | 1 + include/mapnik/svg/svg_storage.hpp | 22 ++++++++++++++++++++- src/agg/process_markers_symbolizer.cpp | 4 ++-- src/cairo_renderer.cpp | 2 +- src/grid/process_markers_symbolizer.cpp | 4 ++-- src/marker_cache.cpp | 1 + src/svg/svg_parser.cpp | 26 +++++++++++++++++++++++++ 10 files changed, 85 insertions(+), 13 deletions(-) diff --git a/include/mapnik/marker.hpp b/include/mapnik/marker.hpp index aac1a3660..d9c1fe970 100644 --- a/include/mapnik/marker.hpp +++ b/include/mapnik/marker.hpp @@ -102,7 +102,7 @@ public: if (is_bitmap()) return (*bitmap_data_)->width(); else if (is_vector()) - return (*vector_data_)->bounding_box().width(); + return (*vector_data_)->width(); return 0; } inline double height() const @@ -110,7 +110,7 @@ public: if (is_bitmap()) return (*bitmap_data_)->height(); else if (is_vector()) - return (*vector_data_)->bounding_box().height(); + return (*vector_data_)->height(); return 0; } diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index a7031621c..88c6377e6 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -365,6 +365,8 @@ void build_ellipse(T const& sym, mapnik::feature_impl const& feature, svg_storag styled_svg.pop_attr(); double lox,loy,hix,hiy; styled_svg.bounding_rect(&lox, &loy, &hix, &hiy); + styled_svg.set_dimensions(width,height); + marker_ellipse.set_dimensions(width,height); marker_ellipse.set_bounding_box(lox,loy,hix,hiy); } @@ -419,7 +421,11 @@ bool push_explicit_style(Attr const& src, Attr & dst, markers_symbolizer const& } template -void setup_transform_scaling(agg::trans_affine & tr, box2d const& bbox, mapnik::feature_impl const& feature, T const& sym) +void setup_transform_scaling(agg::trans_affine & tr, + double svg_width, + double svg_height, + mapnik::feature_impl const& feature, + T const& sym) { double width = 0; double height = 0; @@ -434,18 +440,18 @@ void setup_transform_scaling(agg::trans_affine & tr, box2d const& bbox, if (width > 0 && height > 0) { - double sx = width/bbox.width(); - double sy = height/bbox.height(); + double sx = width/svg_width; + double sy = height/svg_height; tr *= agg::trans_affine_scaling(sx,sy); } else if (width > 0) { - double sx = width/bbox.width(); + double sx = width/svg_width; tr *= agg::trans_affine_scaling(sx); } else if (height > 0) { - double sy = height/bbox.height(); + double sy = height/svg_height; tr *= agg::trans_affine_scaling(sy); } } diff --git a/include/mapnik/svg/svg_converter.hpp b/include/mapnik/svg/svg_converter.hpp index d67c6c2ca..d0e7dfcb5 100644 --- a/include/mapnik/svg/svg_converter.hpp +++ b/include/mapnik/svg/svg_converter.hpp @@ -308,6 +308,22 @@ public: agg::bounding_rect(trans, *this, 0, attributes_.size(), x1, y1, x2, y2); } + void set_dimensions(double w, double h) + { + svg_width_ = w; + svg_height_ = h; + } + + double width() + { + return svg_width_; + } + + double height() + { + return svg_height_; + } + VertexSource & storage() { return source_; @@ -333,6 +349,8 @@ private: AttributeSource & attributes_; AttributeSource attr_stack_; agg::trans_affine transform_; + double svg_width_; + double svg_height_; }; diff --git a/include/mapnik/svg/svg_parser.hpp b/include/mapnik/svg/svg_parser.hpp index 68f151bf2..333949ec4 100644 --- a/include/mapnik/svg/svg_parser.hpp +++ b/include/mapnik/svg/svg_parser.hpp @@ -51,6 +51,7 @@ namespace mapnik { namespace svg { void start_element(xmlTextReaderPtr reader); void end_element(xmlTextReaderPtr reader); void parse_path(xmlTextReaderPtr reader); + void parse_dimensions(xmlTextReaderPtr reader); void parse_polygon(xmlTextReaderPtr reader); void parse_polyline(xmlTextReaderPtr reader); void parse_line(xmlTextReaderPtr reader); diff --git a/include/mapnik/svg/svg_storage.hpp b/include/mapnik/svg/svg_storage.hpp index a0827972a..89e6ebca4 100644 --- a/include/mapnik/svg/svg_storage.hpp +++ b/include/mapnik/svg/svg_storage.hpp @@ -34,7 +34,9 @@ template class svg_storage : mapnik::noncopyable { public: - svg_storage() {} + svg_storage() : + svg_width_(0), + svg_height_(0) {} VertexSource & source() // FIXME!! make const { @@ -61,11 +63,29 @@ public: return bounding_box_; } + double width() const + { + return svg_width_; + } + + double height() const + { + return svg_height_; + } + + void set_dimensions(double w, double h) + { + svg_width_ = w; + svg_height_ = h; + } + private: VertexSource source_; AttributeSource attributes_; box2d bounding_box_; + double svg_width_; + double svg_height_; }; diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index 8aa7311d4..d001fbbd7 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -152,7 +152,7 @@ void agg_renderer::process(markers_symbolizer const& sym, else { box2d const& bbox = (*mark)->bounding_box(); - setup_transform_scaling(tr, bbox, feature, sym); + setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym); evaluate_transform(tr, feature, sym.get_image_transform()); coord2d center = bbox.center(); agg::trans_affine_translation recenter(-center.x, -center.y); @@ -193,7 +193,7 @@ void agg_renderer::process(markers_symbolizer const& sym, else // raster markers { box2d const& bbox = (*mark)->bounding_box(); - setup_transform_scaling(tr, bbox, feature, sym); + setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym); evaluate_transform(tr, feature, sym.get_image_transform()); coord2d center = bbox.center(); agg::trans_affine_translation recenter(-center.x, -center.y); diff --git a/src/cairo_renderer.cpp b/src/cairo_renderer.cpp index b3d3fd9c3..7316ccbdd 100644 --- a/src/cairo_renderer.cpp +++ b/src/cairo_renderer.cpp @@ -1162,7 +1162,7 @@ void cairo_renderer_base::process(markers_symbolizer const& sym, agg::trans_affine geom_tr; evaluate_transform(geom_tr, feature, sym.get_transform()); box2d const& bbox = (*mark)->bounding_box(); - setup_transform_scaling(tr, bbox, feature, sym); + setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym); evaluate_transform(tr, feature, sym.get_image_transform()); if ((*mark)->is_vector()) diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 1cf09ead5..256a8753f 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -167,7 +167,7 @@ void grid_renderer::process(markers_symbolizer const& sym, else { box2d const& bbox = (*mark)->bounding_box(); - setup_transform_scaling(tr, bbox, feature, sym); + setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym); evaluate_transform(tr, feature, sym.get_image_transform()); // TODO - clamping to >= 4 pixels coord2d center = bbox.center(); @@ -210,7 +210,7 @@ void grid_renderer::process(markers_symbolizer const& sym, else // raster markers { box2d const& bbox = (*mark)->bounding_box(); - setup_transform_scaling(tr, bbox, feature, sym); + setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym); evaluate_transform(tr, feature, sym.get_image_transform()); // - clamp sizes to > 4 pixels of interactivity coord2d center = bbox.center(); diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 526fffb6c..d483d7b47 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -151,6 +151,7 @@ boost::optional marker_cache::find(std::string const& uri, double lox,loy,hix,hiy; svg.bounding_rect(&lox, &loy, &hix, &hiy); marker_path->set_bounding_box(lox,loy,hix,hiy); + marker_path->set_dimensions(svg.width(),svg.height()); marker_ptr mark(boost::make_shared(marker_path)); result.reset(mark); if (update_cache) diff --git a/src/svg/svg_parser.cpp b/src/svg/svg_parser.cpp index 5ec93e07e..ed6b23979 100644 --- a/src/svg/svg_parser.cpp +++ b/src/svg/svg_parser.cpp @@ -265,6 +265,10 @@ void svg_parser::start_element(xmlTextReaderPtr reader) { parse_ellipse(reader); } + else if (xmlStrEqual(name, BAD_CAST "svg")) + { + parse_dimensions(reader); + } #ifdef MAPNIK_LOG else if (!xmlStrEqual(name, BAD_CAST "svg")) { @@ -451,6 +455,28 @@ void svg_parser::parse_attr(xmlTextReaderPtr reader) } xmlTextReaderMoveToElement(reader); } + +void svg_parser::parse_dimensions(xmlTextReaderPtr reader) +{ + xmlChar *value; + double width = 0; + double height = 0; + value = xmlTextReaderGetAttribute(reader, BAD_CAST "width"); + if (value) + { + width = parse_double((const char*)value); + xmlFree(value); + } + xmlChar *value2; + value2 = xmlTextReaderGetAttribute(reader, BAD_CAST "width"); + if (value2) + { + height = parse_double((const char*)value2); + xmlFree(value2); + } + path_.set_dimensions(width,height); + +} void svg_parser::parse_path(xmlTextReaderPtr reader) { xmlChar *value;