diff --git a/include/mapnik/svg/agg_svg_path_renderer.h b/include/mapnik/svg/agg_svg_path_renderer.h deleted file mode 100644 index 742cfe7b2..000000000 --- a/include/mapnik/svg/agg_svg_path_renderer.h +++ /dev/null @@ -1,327 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// SVG path renderer. -// -//---------------------------------------------------------------------------- -#ifndef AGG_SVG_PATH_RENDERER_INCLUDED -#define AGG_SVG_PATH_RENDERER_INCLUDED - -#include "agg_path_storage.h" -#include "agg_conv_transform.h" -#include "agg_conv_stroke.h" -#include "agg_conv_contour.h" -#include "agg_conv_curve.h" -#include "agg_color_rgba.h" -#include "agg_renderer_scanline.h" -#include "agg_bounding_rect.h" -#include "agg_rasterizer_scanline_aa.h" - -namespace agg -{ -namespace svg -{ - template class conv_count - { - public: - conv_count(VertexSource& vs) : m_source(&vs), m_count(0) {} - - void count(unsigned n) { m_count = n; } - unsigned count() const { return m_count; } - - void rewind(unsigned path_id) { m_source->rewind(path_id); } - unsigned vertex(double* x, double* y) - { - ++m_count; - return m_source->vertex(x, y); - } - - private: - VertexSource* m_source; - unsigned m_count; - }; - - - - - //============================================================================ - // Basic path attributes - struct path_attributes - { - unsigned index; - rgba8 fill_color; - rgba8 stroke_color; - bool fill_flag; - bool stroke_flag; - bool even_odd_flag; - line_join_e line_join; - line_cap_e line_cap; - double miter_limit; - double stroke_width; - trans_affine transform; - - // Empty constructor - path_attributes() : - index(0), - fill_color(rgba(0,0,0)), - stroke_color(rgba(0,0,0)), - fill_flag(true), - stroke_flag(false), - even_odd_flag(false), - line_join(miter_join), - line_cap(butt_cap), - miter_limit(4.0), - stroke_width(1.0), - transform() - { - } - - // Copy constructor - path_attributes(const path_attributes& attr) : - index(attr.index), - fill_color(attr.fill_color), - stroke_color(attr.stroke_color), - fill_flag(attr.fill_flag), - stroke_flag(attr.stroke_flag), - even_odd_flag(attr.even_odd_flag), - line_join(attr.line_join), - line_cap(attr.line_cap), - miter_limit(attr.miter_limit), - stroke_width(attr.stroke_width), - transform(attr.transform) - { - } - - // Copy constructor with new index value - path_attributes(const path_attributes& attr, unsigned idx) : - index(idx), - fill_color(attr.fill_color), - stroke_color(attr.stroke_color), - fill_flag(attr.fill_flag), - stroke_flag(attr.stroke_flag), - even_odd_flag(attr.even_odd_flag), - line_join(attr.line_join), - line_cap(attr.line_cap), - miter_limit(attr.miter_limit), - stroke_width(attr.stroke_width), - transform(attr.transform) - { - } - }; - - - //============================================================================ - // Path container and renderer. - class path_renderer - { - public: - typedef pod_bvector attr_storage; - - typedef conv_curve curved; - typedef conv_count curved_count; - - typedef conv_stroke curved_stroked; - typedef conv_transform curved_stroked_trans; - - typedef conv_transform curved_trans; - typedef conv_contour curved_trans_contour; - - path_renderer(); - - void remove_all(); - - // Use these functions as follows: - // begin_path() when the XML tag comes ("start_element" handler) - // parse_path() on "d=" tag attribute - // end_path() when parsing of the entire tag is done. - void begin_path(); - //void parse_path(path_tokenizer& tok); - void end_path(); - - // The following functions are essentially a "reflection" of - // the respective SVG path commands. - void move_to(double x, double y, bool rel=false); // M, m - void line_to(double x, double y, bool rel=false); // L, l - void hline_to(double x, bool rel=false); // H, h - void vline_to(double y, bool rel=false); // V, v - void curve3(double x1, double y1, // Q, q - double x, double y, bool rel=false); - void curve3(double x, double y, bool rel=false); // T, t - void curve4(double x1, double y1, // C, c - double x2, double y2, - double x, double y, bool rel=false); - void curve4(double x2, double y2, // S, s - double x, double y, bool rel=false); - - void arc_to(double rx, double ry, // A, a - double angle, - bool large_arc_flag, - bool sweep_flag, - double x, double y,bool rel=false); - - void close_subpath(); // Z, z - -// template -// void add_path(VertexSource& vs, -// unsigned path_id = 0, -// bool solid_path = true) -// { -// m_storage.add_path(vs, path_id, solid_path); -// } - - - unsigned vertex_count() const { return m_curved_count.count(); } - - - // Call these functions on tag (start_element, end_element respectively) - void push_attr(); - void pop_attr(); - - // Attribute setting functions. - void fill(const rgba8& f); - void stroke(const rgba8& s); - void even_odd(bool flag); - void stroke_width(double w); - void fill_none(); - void stroke_none(); - void fill_opacity(double op); - void stroke_opacity(double op); - void line_join(line_join_e join); - void line_cap(line_cap_e cap); - void miter_limit(double ml); - trans_affine& transform(); - - // Make all polygons CCW-oriented - void arrange_orientations() - { - m_storage.arrange_orientations_all_paths(path_flags_ccw); - } - - // Expand all polygons - void expand(double value) - { - m_curved_trans_contour.width(value); - } - - unsigned operator [](unsigned idx) - { - m_transform = m_attr_storage[idx].transform; - return m_attr_storage[idx].index; - } - - void bounding_rect(double* x1, double* y1, double* x2, double* y2) - { - agg::conv_transform trans(m_storage, m_transform); - agg::bounding_rect(trans, *this, 0, m_attr_storage.size(), x1, y1, x2, y2); - } - - // Rendering. One can specify two additional parameters: - // trans_affine and opacity. They can be used to transform the whole - // image and/or to make it translucent. - template - void render(Rasterizer& ras, - Scanline& sl, - Renderer& ren, - const trans_affine& mtx, - const rect_i& cb, - double opacity=1.0) - { - unsigned i; - - ras.clip_box(cb.x1, cb.y1, cb.x2, cb.y2); - m_curved_count.count(0); - - for(i = 0; i < m_attr_storage.size(); i++) - { - const path_attributes& attr = m_attr_storage[i]; - m_transform = attr.transform; - m_transform *= mtx; - double scl = m_transform.scale(); - //m_curved.approximation_method(curve_inc); - m_curved.approximation_scale(scl); - m_curved.angle_tolerance(0.0); - - rgba8 color; - - if(attr.fill_flag) - { - ras.reset(); - ras.filling_rule(attr.even_odd_flag ? fill_even_odd : fill_non_zero); - if(fabs(m_curved_trans_contour.width()) < 0.0001) - { - ras.add_path(m_curved_trans, attr.index); - } - else - { - m_curved_trans_contour.miter_limit(attr.miter_limit); - ras.add_path(m_curved_trans_contour, attr.index); - } - - color = attr.fill_color; - color.opacity(color.opacity() * opacity); - ren.color(color); - agg::render_scanlines(ras, sl, ren); - } - - if(attr.stroke_flag) - { - m_curved_stroked.width(attr.stroke_width); - //m_curved_stroked.line_join((attr.line_join == miter_join) ? miter_join_round : attr.line_join); - m_curved_stroked.line_join(attr.line_join); - m_curved_stroked.line_cap(attr.line_cap); - m_curved_stroked.miter_limit(attr.miter_limit); - m_curved_stroked.inner_join(inner_round); - m_curved_stroked.approximation_scale(scl); - - // If the *visual* line width is considerable we - // turn on processing of curve cusps. - //--------------------- - if(attr.stroke_width * scl > 1.0) - { - m_curved.angle_tolerance(0.2); - } - ras.reset(); - ras.filling_rule(fill_non_zero); - ras.add_path(m_curved_stroked_trans, attr.index); - color = attr.stroke_color; - color.opacity(color.opacity() * opacity); - ren.color(color); - agg::render_scanlines(ras, sl, ren); - } - } - } - - private: - path_attributes& cur_attr(); - - path_storage m_storage; - attr_storage m_attr_storage; - attr_storage m_attr_stack; - trans_affine m_transform; - - curved m_curved; - curved_count m_curved_count; - - curved_stroked m_curved_stroked; - curved_stroked_trans m_curved_stroked_trans; - - curved_trans m_curved_trans; - curved_trans_contour m_curved_trans_contour; - }; - -} -} - -#endif diff --git a/include/mapnik/svg/marker_cache.hpp b/include/mapnik/svg/marker_cache.hpp index 7d38607c4..6237f1a73 100644 --- a/include/mapnik/svg/marker_cache.hpp +++ b/include/mapnik/svg/marker_cache.hpp @@ -28,8 +28,10 @@ // mapnik #include #include -#include - +#include +#include +// agg +#include "agg_path_storage.h" // boost #include #include @@ -40,7 +42,10 @@ namespace mapnik { -typedef boost::shared_ptr path_ptr; +typedef agg::path_storage path_storage; +typedef agg::pod_bvector attr_storage; +typedef mapnik::svg::svg_storage svg_storage_type; +typedef boost::shared_ptr path_ptr; struct MAPNIK_DECL marker_cache : public singleton , diff --git a/include/mapnik/svg/svg_converter.hpp b/include/mapnik/svg/svg_converter.hpp new file mode 100644 index 000000000..1e9fd80c7 --- /dev/null +++ b/include/mapnik/svg/svg_converter.hpp @@ -0,0 +1,297 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2010 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// $Id$ + +#ifndef MAPNIK_SVG_CONVERTER_HPP +#define MAPNIK_SVG_CONVERTER_HPP + +#include +#include + +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_conv_contour.h" +#include "agg_conv_curve.h" +#include "agg_color_rgba.h" +#include "agg_bounding_rect.h" + +#include + +namespace mapnik { +namespace svg { + +template +class svg_converter : boost::noncopyable +{ +public: + + svg_converter(VertexSource & source, AttributeSource & attributes) + : source_(source), + attributes_(attributes) {} + + void begin_path() + { + push_attr(); + unsigned idx = source_.start_new_path(); + attributes_.add(path_attributes(cur_attr(), idx)); + } + + void end_path() + { + if(attributes_.size() == 0) + { + throw std::runtime_error("end_path : The path was not begun"); + } + path_attributes attr = cur_attr(); + unsigned idx = attributes_[attributes_.size() - 1].index; + attr.index = idx; + attributes_[attributes_.size() - 1] = attr; + pop_attr(); + } + + void move_to(double x, double y, bool rel=false) // M, m + { + if(rel) source_.rel_to_abs(&x, &y); + source_.move_to(x, y); + } + + void line_to(double x, double y, bool rel=false) // L, l + { + if(rel) source_.rel_to_abs(&x, &y); + source_.line_to(x, y); + } + + void hline_to(double x, bool rel=false) // H, h + { + double x2 = 0.0; + double y2 = 0.0; + if(source_.total_vertices()) + { + source_.vertex(source_.total_vertices() - 1, &x2, &y2); + if(rel) x += x2; + source_.line_to(x, y2); + } + } + + void vline_to(double y, bool rel=false) // V, v + { + double x2 = 0.0; + double y2 = 0.0; + if(source_.total_vertices()) + { + source_.vertex(source_.total_vertices() - 1, &x2, &y2); + if(rel) y += y2; + source_.line_to(x2, y); + } + } + void curve3(double x1, double y1, // Q, q + double x, double y, bool rel=false) + { + if(rel) + { + source_.rel_to_abs(&x1, &y1); + source_.rel_to_abs(&x, &y); + } + source_.curve3(x1, y1, x, y); + } + + void curve3(double x, double y, bool rel=false) // T, t + { + if(rel) + { + source_.curve3_rel(x, y); + } else + { + source_.curve3(x, y); + } + } + + void curve4(double x1, double y1, // C, c + double x2, double y2, + double x, double y, bool rel=false) + { + if(rel) + { + source_.rel_to_abs(&x1, &y1); + source_.rel_to_abs(&x2, &y2); + source_.rel_to_abs(&x, &y); + } + source_.curve4(x1, y1, x2, y2, x, y); + } + + void curve4(double x2, double y2, // S, s + double x, double y, bool rel=false) + { + if(rel) + { + source_.curve4_rel(x2, y2, x, y); + } else + { + source_.curve4(x2, y2, x, y); + } + } + + void arc_to(double rx, double ry, // A, a + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y,bool rel=false) + { + + if(rel) + { + source_.arc_rel(rx, ry, angle, large_arc_flag, sweep_flag, x, y); + } + else + { + source_.arc_to(rx, ry, angle, large_arc_flag, sweep_flag, x, y); + + } + } + + void close_subpath() // Z, z + { + source_.end_poly(agg::path_flags_close); + } + + void push_attr() + { + attr_stack_.add(attr_stack_.size() ? + attr_stack_[attr_stack_.size() - 1] : + path_attributes()); + } + void pop_attr() + { + if(attr_stack_.size() == 0) + { + throw std::runtime_error("pop_attr : Attribute stack is empty"); + } + attr_stack_.remove_last(); + } + + // Attribute setting functions. + void fill(const agg::rgba8& f) + { + path_attributes& attr = cur_attr(); + attr.fill_color = f; + attr.fill_flag = true; + } + + void stroke(const agg::rgba8& s) + { + path_attributes& attr = cur_attr(); + attr.stroke_color = s; + attr.stroke_flag = true; + } + + void even_odd(bool flag) + { + cur_attr().even_odd_flag = flag; + } + + void stroke_width(double w) + { + cur_attr().stroke_width = w; + } + void fill_none() + { + cur_attr().fill_flag = false; + } + + void stroke_none() + { + cur_attr().stroke_flag = false; + } + + void fill_opacity(double op) + { + cur_attr().fill_color.opacity(op); + } + void stroke_opacity(double op) + { + cur_attr().stroke_color.opacity(op); + } + + void line_join(agg::line_join_e join) + { + cur_attr().line_join = join; + } + + void line_cap(agg::line_cap_e cap) + { + cur_attr().line_cap = cap; + } + void miter_limit(double ml) + { + cur_attr().miter_limit = ml; + } + + // Make all polygons CCW-oriented + void arrange_orientations() + { + source_.arrange_orientations_all_paths(agg::path_flags_ccw); + } + + // FIXME!!!! + unsigned operator [](unsigned idx) + { + transform_ = attributes_[idx].transform; + return attributes_[idx].index; + } + + void bounding_rect(double* x1, double* y1, double* x2, double* y2) + { + agg::conv_transform trans(source_, transform_); + agg::bounding_rect(trans, *this, 0, attributes_.size(), x1, y1, x2, y2); + } + + agg::trans_affine& transform() + { + return cur_attr().transform; + } + + path_attributes& cur_attr() + { + if(attr_stack_.size() == 0) + { + throw std::runtime_error("cur_attr : Attribute stack is empty"); + } + return attr_stack_[attr_stack_.size() - 1]; + } + +private: + + VertexSource & source_; + AttributeSource & attributes_; + AttributeSource attr_stack_; + agg::trans_affine transform_; +}; + + +typedef svg_converter > svg_converter_type; + +}} + + +#endif // #ifndef MAPNIK_SVG_CONVERTER_HPP diff --git a/include/mapnik/svg/svg_parser.hpp b/include/mapnik/svg/svg_parser.hpp index 8cc39b62c..ba3c217c2 100644 --- a/include/mapnik/svg/svg_parser.hpp +++ b/include/mapnik/svg/svg_parser.hpp @@ -23,38 +23,44 @@ #ifndef MAPNIK_SVG_PARSER_HPP #define MAPNIK_SVG_PARSER_HPP +// mapnik +#include +#include +// boost #include #include -#include "agg_svg_path_renderer.h" +// agg +#include "agg_path_storage.h" namespace mapnik { namespace svg { - class svg_parser : private boost::noncopyable - { - public: - explicit svg_parser(agg::svg::path_renderer & path); - ~svg_parser(); +class svg_parser : private boost::noncopyable +{ +public: +explicit svg_parser(svg_converter > & path); +~svg_parser(); - void parse(std::string const& filename); - private: - void process_node(xmlTextReaderPtr reader); - void start_element(xmlTextReaderPtr reader); - void end_element(xmlTextReaderPtr reader); - void parse_path(xmlTextReaderPtr reader); - void parse_polygon(xmlTextReaderPtr reader); - void parse_polyline(xmlTextReaderPtr reader); - void parse_line(xmlTextReaderPtr reader); - void parse_rect(xmlTextReaderPtr reader); - void parse_circle(xmlTextReaderPtr reader); - void parse_ellipse(xmlTextReaderPtr reader); - void parse_attr(xmlTextReaderPtr reader); - void parse_attr(const xmlChar * name, const xmlChar * value ); +void parse(std::string const& filename); +private: + void process_node(xmlTextReaderPtr reader); + void start_element(xmlTextReaderPtr reader); + void end_element(xmlTextReaderPtr reader); + void parse_path(xmlTextReaderPtr reader); + void parse_polygon(xmlTextReaderPtr reader); + void parse_polyline(xmlTextReaderPtr reader); + void parse_line(xmlTextReaderPtr reader); + void parse_rect(xmlTextReaderPtr reader); + void parse_circle(xmlTextReaderPtr reader); + void parse_ellipse(xmlTextReaderPtr reader); + void parse_attr(xmlTextReaderPtr reader); + void parse_attr(const xmlChar * name, const xmlChar * value ); + +private: + svg_converter > & path_; +}; - private: - agg::svg::path_renderer & path_; - }; - - }} +}} #endif // MAPNIK_SVG_PARSER_HPP diff --git a/include/mapnik/svg/svg_path_attributes.hpp b/include/mapnik/svg/svg_path_attributes.hpp new file mode 100644 index 000000000..ea236132b --- /dev/null +++ b/include/mapnik/svg/svg_path_attributes.hpp @@ -0,0 +1,97 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2010 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// $Id$ + +#ifndef MAPNIK_SVG_PATH_ATTRIBUTES_HPP +#define MAPNIK_SVG_PATH_ATTRIBUTES_HPP + +#include "agg_math_stroke.h" +#include "agg_color_rgba.h" +#include "agg_pixfmt_rgba.h" +#include "agg_trans_affine.h" + +namespace mapnik { +namespace svg { + +struct path_attributes +{ + unsigned index; + agg::rgba8 fill_color; + agg::rgba8 stroke_color; + bool fill_flag; + bool stroke_flag; + bool even_odd_flag; + agg::line_join_e line_join; + agg::line_cap_e line_cap; + double miter_limit; + double stroke_width; + agg::trans_affine transform; + + // Empty constructor + path_attributes() : + index(0), + fill_color(agg::rgba(0,0,0)), + stroke_color(agg::rgba(0,0,0)), + fill_flag(true), + stroke_flag(false), + even_odd_flag(false), + line_join(agg::miter_join), + line_cap(agg::butt_cap), + miter_limit(4.0), + stroke_width(1.0), + transform() + { + } + + // Copy constructor + path_attributes(const path_attributes& attr) + : index(attr.index), + fill_color(attr.fill_color), + stroke_color(attr.stroke_color), + fill_flag(attr.fill_flag), + stroke_flag(attr.stroke_flag), + even_odd_flag(attr.even_odd_flag), + line_join(attr.line_join), + line_cap(attr.line_cap), + miter_limit(attr.miter_limit), + stroke_width(attr.stroke_width), + transform(attr.transform) {} + + // Copy constructor with new index value + path_attributes(path_attributes const& attr, unsigned idx) + : index(idx), + fill_color(attr.fill_color), + stroke_color(attr.stroke_color), + fill_flag(attr.fill_flag), + stroke_flag(attr.stroke_flag), + even_odd_flag(attr.even_odd_flag), + line_join(attr.line_join), + line_cap(attr.line_cap), + miter_limit(attr.miter_limit), + stroke_width(attr.stroke_width), + transform(attr.transform) {} +}; + +}} + +#endif // MAPNIK_SVG_PATH_ATTRIBUTES_HPP diff --git a/include/mapnik/svg/svg_renderer.hpp b/include/mapnik/svg/svg_renderer.hpp new file mode 100644 index 000000000..245f95af7 --- /dev/null +++ b/include/mapnik/svg/svg_renderer.hpp @@ -0,0 +1,148 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2010 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef MAPNIK_SVG_RENDERER_HPP +#define MAPNIK_SVG_RENDERER_HPP + +#include + +#include + +#include "agg_path_storage.h" +#include "agg_conv_transform.h" +#include "agg_conv_stroke.h" +#include "agg_conv_contour.h" +#include "agg_conv_curve.h" +#include "agg_color_rgba.h" +#include "agg_renderer_scanline.h" +#include "agg_bounding_rect.h" +#include "agg_rasterizer_scanline_aa.h" + +namespace mapnik { +namespace svg { + +template +class svg_renderer : boost::noncopyable +{ + typedef agg::conv_curve curved_type; + typedef agg::conv_stroke curved_stroked_type; + typedef agg::conv_transform curved_stroked_trans_type; + typedef agg::conv_transform curved_trans_type; + typedef agg::conv_contour curved_trans_contour_type; + +public: + svg_renderer(VertexSource & source, AttributeSource const& attributes) + : source_(source), + curved_(source_), + curved_stroked_(curved_), + attributes_(attributes) {} + + template + void render(Rasterizer& ras, + Scanline& sl, + Renderer& ren, + agg::trans_affine const& mtx, + agg::rect_i const& cb, + double opacity=1.0) + + { + using namespace agg; + + ras.clip_box(cb.x1, cb.y1, cb.x2, cb.y2); + trans_affine transform; + curved_stroked_trans_type curved_stroked_trans(curved_stroked_,transform); + curved_trans_type curved_trans(curved_,transform); + curved_trans_contour_type curved_trans_contour(curved_trans); + + curved_trans_contour.auto_detect_orientation(false); + + for(unsigned i = 0; i < attributes_.size(); ++i) + { + mapnik::svg::path_attributes const& attr = attributes_[i]; + transform = attr.transform; + transform *= mtx; + double scl = transform.scale(); + //m_curved.approximation_method(curve_inc); + curved_.approximation_scale(scl); + curved_.angle_tolerance(0.0); + + rgba8 color; + + if(attr.fill_flag) + { + ras.reset(); + ras.filling_rule(attr.even_odd_flag ? fill_even_odd : fill_non_zero); + if(fabs(curved_trans_contour.width()) < 0.0001) + { + ras.add_path(curved_trans, attr.index); + } + else + { + curved_trans_contour.miter_limit(attr.miter_limit); + ras.add_path(curved_trans_contour, attr.index); + } + + color = attr.fill_color; + color.opacity(color.opacity() * opacity); + ren.color(color); + render_scanlines(ras, sl, ren); + } + + if(attr.stroke_flag) + { + curved_stroked_.width(attr.stroke_width); + //m_curved_stroked.line_join((attr.line_join == miter_join) ? miter_join_round : attr.line_join); + curved_stroked_.line_join(attr.line_join); + curved_stroked_.line_cap(attr.line_cap); + curved_stroked_.miter_limit(attr.miter_limit); + curved_stroked_.inner_join(inner_round); + curved_stroked_.approximation_scale(scl); + + // If the *visual* line width is considerable we + // turn on processing of curve cusps. + //--------------------- + if(attr.stroke_width * scl > 1.0) + { + curved_.angle_tolerance(0.2); + } + ras.reset(); + ras.filling_rule(fill_non_zero); + ras.add_path(curved_stroked_trans, attr.index); + color = attr.stroke_color; + color.opacity(color.opacity() * opacity); + ren.color(color); + render_scanlines(ras, sl, ren); + } + } + } + +private: + + VertexSource & source_; + curved_type curved_; + curved_stroked_type curved_stroked_; + AttributeSource const& attributes_; +}; + +}} + +#endif //MAPNIK_SVG_RENDERER_HPP diff --git a/include/mapnik/svg/svg_storage.hpp b/include/mapnik/svg/svg_storage.hpp new file mode 100644 index 000000000..ca40537d8 --- /dev/null +++ b/include/mapnik/svg/svg_storage.hpp @@ -0,0 +1,57 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2010 Artem Pavlenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// $Id$ + +#ifndef MAPNIK_SVG_STORAGE_HPP +#define MAPNIK_SVG_STORAGE_HPP + +#include + +namespace mapnik { +namespace svg { + +template +class svg_storage : boost::noncopyable +{ +public: + svg_storage() {} + + VertexSource & source() // FIXME!! make const + { + return source_; + } + + AttributeSource & attributes() // FIXME!! make const + { + return attributes_; + } +private: + VertexSource source_; + AttributeSource attributes_; + +}; + +}} + + +#endif // MAPNIK_SVG_STORAGE_HPP diff --git a/src/SConscript b/src/SConscript index 44c6d7119..a6140dfcf 100644 --- a/src/SConscript +++ b/src/SConscript @@ -126,7 +126,6 @@ if True : # agg backend agg/process_point_symbolizer.cpp agg/process_shield_symbolizer.cpp agg/process_markers_symbolizer.cpp - agg_svg_path_renderer.cpp svg_parser.cpp svg_path_parser.cpp svg_points_parser.cpp diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index e04789f1e..4c7c32cfc 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -79,11 +80,11 @@ void agg_renderer::process(markers_symbolizer const& sym, if (!filename.empty()) { marker = mapnik::marker_cache::instance()->find(filename, true); - if (marker && *marker) + if (0)//marker && *marker) { svg_marker = true; double x1, y1, x2, y2; - (*marker)->bounding_rect(&x1, &y1, &x2, &y2); +//(*marker)->bounding_rect(&x1, &y1, &x2, &y2); extent.init(x1, y1, x2, y2); } } @@ -105,7 +106,7 @@ void agg_renderer::process(markers_symbolizer const& sym, agg::trans_affine matrix = tr * agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x, y); if (svg_marker) { - (*marker)->render(*ras_ptr, sl, ren, matrix, renb.clip_box(), 1.0); +//(*marker)->render(*ras_ptr, sl, ren, matrix, renb.clip_box(), 1.0); } else { diff --git a/src/agg/process_point_symbolizer.cpp b/src/agg/process_point_symbolizer.cpp index 269573f55..fcefe711b 100644 --- a/src/agg/process_point_symbolizer.cpp +++ b/src/agg/process_point_symbolizer.cpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" @@ -77,10 +79,19 @@ void agg_renderer::process(point_symbolizer const& sym, box2d extent; marker = marker_cache::instance()->find(filename, true); + if (marker && *marker) { double x1, y1, x2, y2; - (*marker)->bounding_rect(&x1, &y1, &x2, &y2); + // FIXME: Cache bounding box ///////////// + mapnik::svg::svg_converter_type svg_converter((*marker)->source(), + (*marker)->attributes()); + + svg_converter.bounding_rect(&x1, &y1, &x2, &y2); + ///////////////////// + mapnik::svg::svg_renderer > svg_renderer((*marker)->source(), + (*marker)->attributes()); for (unsigned i=0; i::process(point_symbolizer const& sym, detector_.has_placement(extent)) { - (*marker)->render(*ras_ptr, sl, ren, tr, renb.clip_box(), sym.get_opacity()); + + svg_renderer.render(*ras_ptr, sl, ren, tr, renb.clip_box(), sym.get_opacity()); + detector_.insert(extent); } } diff --git a/src/agg/process_shield_symbolizer.cpp b/src/agg/process_shield_symbolizer.cpp index 3e7572486..1e436beec 100644 --- a/src/agg/process_shield_symbolizer.cpp +++ b/src/agg/process_shield_symbolizer.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include "agg_basics.h" #include "agg_rendering_buffer.h" @@ -83,7 +85,16 @@ void agg_renderer::process(shield_symbolizer const& sym, { face_set_ptr faces; double x1, y1, x2, y2; - (*marker)->bounding_rect(&x1, &y1, &x2, &y2); + + // FIXME: Cache bounding box ///////////// + mapnik::svg::svg_converter_type svg_converter((*marker)->source(), + (*marker)->attributes()); + + svg_converter.bounding_rect(&x1, &y1, &x2, &y2); + ///////////////////// + mapnik::svg::svg_renderer > svg_renderer((*marker)->source(), + (*marker)->attributes()); // TODO : apply transform int w = int(x2 - x1); int h = int(y2 - y1); @@ -175,7 +186,7 @@ void agg_renderer::process(shield_symbolizer const& sym, if ( sym.get_allow_overlap() || detector_.has_placement(label_ext) ) { agg::trans_affine matrix = agg::trans_affine_translation(px, py); - (*marker)->render(*ras_ptr, sl, ren, matrix, renb.clip_box(), sym.get_opacity()); + svg_renderer.render(*ras_ptr, sl, ren, matrix, renb.clip_box(), sym.get_opacity()); box2d dim = text_ren.prepare_glyphs(&text_placement.placements[0]); text_ren.render(x,y); detector_.insert(label_ext); @@ -193,14 +204,14 @@ void agg_renderer::process(shield_symbolizer const& sym, for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii) { - + double x = text_placement.placements[ii].starting_x; double y = text_placement.placements[ii].starting_y; - int px=int(x - (w/2)); - int py=int(y - (h/2)); + int px=int(floor(x - (w/2))); + int py=int(floor(y - (h/2))); agg::trans_affine matrix = agg::trans_affine_translation(px, py); - (*marker)->render(*ras_ptr, sl, ren, matrix, renb.clip_box(), sym.get_opacity()); + svg_renderer.render(*ras_ptr, sl, ren, matrix, renb.clip_box(), sym.get_opacity()); box2d dim = text_ren.prepare_glyphs(&text_placement.placements[ii]); text_ren.render(x,y); } diff --git a/src/agg_svg_path_renderer.cpp b/src/agg_svg_path_renderer.cpp deleted file mode 100644 index 9d0ce63e5..000000000 --- a/src/agg_svg_path_renderer.cpp +++ /dev/null @@ -1,299 +0,0 @@ -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.3 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. -// This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -//---------------------------------------------------------------------------- -// Contact: mcseem@antigrain.com -// mcseemagg@yahoo.com -// http://www.antigrain.com -//---------------------------------------------------------------------------- -// -// SVG path renderer. -// -//---------------------------------------------------------------------------- - -#include -#include -#include - -namespace agg -{ -namespace svg -{ - -//------------------------------------------------------------------------ -path_renderer::path_renderer() : - m_curved(m_storage), - m_curved_count(m_curved), - - m_curved_stroked(m_curved_count), - m_curved_stroked_trans(m_curved_stroked, m_transform), - - m_curved_trans(m_curved_count, m_transform), - m_curved_trans_contour(m_curved_trans) -{ - m_curved_trans_contour.auto_detect_orientation(false); -} - - -//------------------------------------------------------------------------ -void path_renderer::remove_all() -{ - m_storage.remove_all(); - m_attr_storage.remove_all(); - m_attr_stack.remove_all(); - m_transform.reset(); -} - -//------------------------------------------------------------------------ -void path_renderer::begin_path() -{ - push_attr(); - unsigned idx = m_storage.start_new_path(); - m_attr_storage.add(path_attributes(cur_attr(), idx)); -} - -//------------------------------------------------------------------------ -void path_renderer::end_path() -{ - if(m_attr_storage.size() == 0) - { - throw std::runtime_error("end_path : The path was not begun"); - } - path_attributes attr = cur_attr(); - unsigned idx = m_attr_storage[m_attr_storage.size() - 1].index; - attr.index = idx; - m_attr_storage[m_attr_storage.size() - 1] = attr; - pop_attr(); -} - -//------------------------------------------------------------------------ -void path_renderer::move_to(double x, double y, bool rel) // M, m -{ - if(rel) m_storage.rel_to_abs(&x, &y); - m_storage.move_to(x, y); -} - -//------------------------------------------------------------------------ -void path_renderer::line_to(double x, double y, bool rel) // L, l -{ - if(rel) m_storage.rel_to_abs(&x, &y); - m_storage.line_to(x, y); -} - -//------------------------------------------------------------------------ -void path_renderer::hline_to(double x, bool rel) // H, h -{ - double x2 = 0.0; - double y2 = 0.0; - if(m_storage.total_vertices()) - { - m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2); - if(rel) x += x2; - m_storage.line_to(x, y2); - } -} - -//------------------------------------------------------------------------ -void path_renderer::vline_to(double y, bool rel) // V, v -{ - double x2 = 0.0; - double y2 = 0.0; - if(m_storage.total_vertices()) - { - m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2); - if(rel) y += y2; - m_storage.line_to(x2, y); - } -} - -//------------------------------------------------------------------------ -void path_renderer::curve3(double x1, double y1, // Q, q - double x, double y, bool rel) -{ - if(rel) - { - m_storage.rel_to_abs(&x1, &y1); - m_storage.rel_to_abs(&x, &y); - } - m_storage.curve3(x1, y1, x, y); -} - -//------------------------------------------------------------------------ -void path_renderer::curve3(double x, double y, bool rel) // T, t -{ -// throw std::runtime_error("curve3(x, y) : NOT IMPLEMENTED YET"); - if(rel) - { - m_storage.curve3_rel(x, y); - } else - { - m_storage.curve3(x, y); - } -} - -//------------------------------------------------------------------------ -void path_renderer::curve4(double x1, double y1, // C, c - double x2, double y2, - double x, double y, bool rel) -{ - if(rel) - { - m_storage.rel_to_abs(&x1, &y1); - m_storage.rel_to_abs(&x2, &y2); - m_storage.rel_to_abs(&x, &y); - } - m_storage.curve4(x1, y1, x2, y2, x, y); -} - -//------------------------------------------------------------------------ -void path_renderer::curve4(double x2, double y2, // S, s - double x, double y, bool rel) -{ - if(rel) - { - m_storage.curve4_rel(x2, y2, x, y); - } else - { - m_storage.curve4(x2, y2, x, y); - } -} - -//------------------------------------------------------------------------ -void path_renderer::arc_to(double rx, double ry, // A, a - double angle, - bool large_arc_flag, - bool sweep_flag, - double x, double y, - bool rel) -{ - if(rel) - { - m_storage.arc_rel(rx, ry, angle, large_arc_flag, sweep_flag, x, y); - } - else - { - m_storage.arc_to(rx, ry, angle, large_arc_flag, sweep_flag, x, y); - - } -} - -//------------------------------------------------------------------------ -void path_renderer::close_subpath() -{ - m_storage.end_poly(path_flags_close); -} - -//------------------------------------------------------------------------ -path_attributes& path_renderer::cur_attr() -{ - if(m_attr_stack.size() == 0) - { - throw std::runtime_error("cur_attr : Attribute stack is empty"); - } - return m_attr_stack[m_attr_stack.size() - 1]; -} - -//------------------------------------------------------------------------ -void path_renderer::push_attr() -{ - m_attr_stack.add(m_attr_stack.size() ? - m_attr_stack[m_attr_stack.size() - 1] : - path_attributes()); -} - -//------------------------------------------------------------------------ -void path_renderer::pop_attr() -{ - if(m_attr_stack.size() == 0) - { - throw std::runtime_error("pop_attr : Attribute stack is empty"); - } - m_attr_stack.remove_last(); -} - -//------------------------------------------------------------------------ -void path_renderer::fill(const rgba8& f) -{ - path_attributes& attr = cur_attr(); - attr.fill_color = f; - attr.fill_flag = true; -} - -//------------------------------------------------------------------------ -void path_renderer::stroke(const rgba8& s) -{ - path_attributes& attr = cur_attr(); - attr.stroke_color = s; - attr.stroke_flag = true; -} - -//------------------------------------------------------------------------ -void path_renderer::even_odd(bool flag) -{ - cur_attr().even_odd_flag = flag; -} - -//------------------------------------------------------------------------ -void path_renderer::stroke_width(double w) -{ - cur_attr().stroke_width = w; -} - -//------------------------------------------------------------------------ -void path_renderer::fill_none() -{ - cur_attr().fill_flag = false; -} - -//------------------------------------------------------------------------ -void path_renderer::stroke_none() -{ - cur_attr().stroke_flag = false; -} - -//------------------------------------------------------------------------ -void path_renderer::fill_opacity(double op) -{ - cur_attr().fill_color.opacity(op); -} - -//------------------------------------------------------------------------ -void path_renderer::stroke_opacity(double op) -{ - cur_attr().stroke_color.opacity(op); -} - -//------------------------------------------------------------------------ -void path_renderer::line_join(line_join_e join) -{ - cur_attr().line_join = join; -} - -//------------------------------------------------------------------------ -void path_renderer::line_cap(line_cap_e cap) -{ - cur_attr().line_cap = cap; -} - -//------------------------------------------------------------------------ -void path_renderer::miter_limit(double ml) -{ - cur_attr().miter_limit = ml; -} - -//------------------------------------------------------------------------ -trans_affine& path_renderer::transform() -{ - return cur_attr().transform; -} - - -} -} - diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 1468b9d25..243bd8d0f 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -25,6 +25,8 @@ // mapnik #include #include +#include +#include // boost #include @@ -64,12 +66,14 @@ boost::optional marker_cache::find(std::string const& uri, bool update { try { - mapnik::path_ptr marker(new agg::svg::path_renderer); - svg::svg_parser p(*marker); + mapnik::path_ptr marker(new svg_storage_type); + svg::svg_converter_type svg(marker->source(),marker->attributes()); + + svg::svg_parser p(svg); p.parse(uri); - marker->arrange_orientations(); + svg.arrange_orientations(); double lox,loy,hix,hiy; - marker->bounding_rect(&lox, &loy, &hix, &hiy); //TODO: store bbox! + svg.bounding_rect(&lox, &loy, &hix, &hiy); //TODO: store bbox! if (update_cache) { cache_.insert(std::make_pair(uri,marker)); diff --git a/src/svg_parser.cpp b/src/svg_parser.cpp index 349621813..ba717e086 100644 --- a/src/svg_parser.cpp +++ b/src/svg_parser.cpp @@ -21,10 +21,10 @@ *****************************************************************************/ #include + #include #include -#include "agg_color_rgba.h" #include #include #include @@ -37,27 +37,27 @@ namespace mapnik { namespace svg { - namespace qi = boost::spirit::qi; +namespace qi = boost::spirit::qi; - typedef std::vector > pairs_type; +typedef std::vector > pairs_type; - template - struct key_value_sequence_ordered - : qi::grammar +template +struct key_value_sequence_ordered + : qi::grammar +{ + key_value_sequence_ordered() + : key_value_sequence_ordered::base_type(query) { - key_value_sequence_ordered() - : key_value_sequence_ordered::base_type(query) - { - query = pair >> *( qi::lit(';') >> pair); - pair = key >> -(':' >> value); - key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9-"); - value = +(qi::char_ - qi::lit(';')); - } + query = pair >> *( qi::lit(';') >> pair); + pair = key >> -(':' >> value); + key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9-"); + value = +(qi::char_ - qi::lit(';')); + } - qi::rule query; - qi::rule(), SkipType> pair; - qi::rule key, value; - }; + qi::rule query; + qi::rule(), SkipType> pair; + qi::rule key, value; +}; agg::rgba8 parse_color(const char* str) { @@ -89,7 +89,7 @@ bool parse_style (const char* str, pairs_type & v) return phrase_parse(str, str + strlen(str), kv_parser, skip_type(), v); } -svg_parser::svg_parser(agg::svg::path_renderer & path) +svg_parser::svg_parser(svg_converter > & path) : path_(path) {} svg_parser::~svg_parser() {} diff --git a/src/svg_path_parser.cpp b/src/svg_path_parser.cpp index fbba2b9fa..a3ea96b71 100644 --- a/src/svg_path_parser.cpp +++ b/src/svg_path_parser.cpp @@ -21,27 +21,31 @@ *****************************************************************************/ // mapnik +#include #include #include +#include +#include // agg -#include +#include "agg_path_storage.h" + // stl #include namespace mapnik { namespace svg { - template - bool parse_path(std::string const& wkt, PathType & p) - { - using namespace boost::spirit; - typedef std::string::const_iterator iterator_type; - typedef ascii::space_type skip_type; - svg_path_grammar g(p); - iterator_type first = wkt.begin(); - iterator_type last = wkt.end(); - return qi::phrase_parse(first, last, g, skip_type()); - } +template +bool parse_path(std::string const& wkt, PathType & p) +{ + using namespace boost::spirit; + typedef std::string::const_iterator iterator_type; + typedef ascii::space_type skip_type; + svg_path_grammar g(p); + iterator_type first = wkt.begin(); + iterator_type last = wkt.end(); + return qi::phrase_parse(first, last, g, skip_type()); +} - template bool parse_path(std::string const&, agg::svg::path_renderer&) ; +template bool parse_path(std::string const&, svg_converter_type&); - }} +}} diff --git a/src/svg_points_parser.cpp b/src/svg_points_parser.cpp index a9f688c8b..e773d60fc 100644 --- a/src/svg_points_parser.cpp +++ b/src/svg_points_parser.cpp @@ -23,25 +23,24 @@ // mapnik #include #include -// agg -#include +#include // stl #include namespace mapnik { namespace svg { - template - bool parse_points(std::string const& wkt, PathType & p) - { - using namespace boost::spirit; - typedef std::string::const_iterator iterator_type; - typedef ascii::space_type skip_type; - svg_points_grammar g(p); - iterator_type first = wkt.begin(); - iterator_type last = wkt.end(); - return qi::phrase_parse(first, last, g, skip_type()); - } +template +bool parse_points(std::string const& wkt, PathType & p) +{ + using namespace boost::spirit; + typedef std::string::const_iterator iterator_type; + typedef ascii::space_type skip_type; + svg_points_grammar g(p); + iterator_type first = wkt.begin(); + iterator_type last = wkt.end(); + return qi::phrase_parse(first, last, g, skip_type()); +} - template bool parse_points(std::string const&, agg::svg::path_renderer&); +template bool parse_points(std::string const&, svg_converter_type&); - }} +}}