diff --git a/include/mapnik/agg_pattern_source.hpp b/include/mapnik/agg_pattern_source.hpp new file mode 100644 index 000000000..1a9046d7d --- /dev/null +++ b/include/mapnik/agg_pattern_source.hpp @@ -0,0 +1,64 @@ +/***************************************************************************** + * + * 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_AGG_PATTERN_SOURCE_HPP +#define MAPNIK_AGG_PATTERN_SOURCE_HPP + +// mapnik +#include +// boost +#include +// agg +#include "agg_color_rgba.h" + +namespace mapnik +{ + +class pattern_source : private boost::noncopyable +{ +public: + pattern_source(image_data_32 const& pattern) + : pattern_(pattern) {} + + unsigned int width() const + { + return pattern_.width(); + } + unsigned int height() const + { + return pattern_.height(); + } + agg::rgba8 pixel(int x, int y) const + { + unsigned c = pattern_(x,y); + return agg::rgba8(c & 0xff, + (c >> 8) & 0xff, + (c >> 16) & 0xff, + (c >> 24) & 0xff); + } +private: + image_data_32 const& pattern_; +}; +} + +#endif //MAPNIK_AGG_PATTERN_SOURCE_HPP diff --git a/src/SConscript b/src/SConscript index 31f67c11d..e66f1f866 100644 --- a/src/SConscript +++ b/src/SConscript @@ -72,7 +72,6 @@ else: # Linux and others source = Split( """ - agg_renderer.cpp datasource_cache.cpp box2d.cpp color.cpp @@ -125,12 +124,16 @@ if env['JPEG']: if True : # agg backend source += Split( """ + agg/agg_renderer.cpp + agg/process_building_symbolizer.cpp agg/process_glyph_symbolizer.cpp agg/process_line_symbolizer.cpp + agg/process_line_pattern_symbolizer.cpp agg/process_text_symbolizer.cpp agg/process_point_symbolizer.cpp agg/process_polygon_symbolizer.cpp agg/process_polygon_pattern_symbolizer.cpp + agg/process_raster_symbolizer.cpp agg/process_shield_symbolizer.cpp agg/process_markers_symbolizer.cpp svg_parser.cpp diff --git a/src/agg_renderer.cpp b/src/agg/agg_renderer.cpp similarity index 69% rename from src/agg_renderer.cpp rename to src/agg/agg_renderer.cpp index 9ceeb1deb..b63813515 100644 --- a/src/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -69,7 +69,7 @@ // boost #include -#include + // stl #ifdef MAPNIK_DEBUG @@ -169,122 +169,6 @@ void agg_renderer::end_layer_processing(layer const&) #endif } -typedef boost::tuple segment_t; -bool y_order(segment_t const& first,segment_t const& second) -{ - double miny0 = std::min(first.get<1>(),first.get<3>()); - double miny1 = std::min(second.get<1>(),second.get<3>()); - return miny0 > miny1; -} - -template -void agg_renderer::process(building_symbolizer const& sym, - Feature const& feature, - proj_transform const& prj_trans) -{ - typedef coord_transform2 path_type; - typedef coord_transform3 path_type_roof; - typedef agg::renderer_base ren_base; - typedef agg::renderer_scanline_aa_solid renderer; - - agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); - agg::pixfmt_rgba32_plain pixf(buf); - ren_base renb(pixf); - - color const& fill_ = sym.get_fill(); - unsigned r=fill_.red(); - unsigned g=fill_.green(); - unsigned b=fill_.blue(); - unsigned a=fill_.alpha(); - renderer ren(renb); - agg::scanline_u8 sl; - - ras_ptr->reset(); - ras_ptr->gamma(agg::gamma_linear()); - - double height = 0.7071 * sym.height(); // height in meters - - for (unsigned i=0;i 2) - { - boost::scoped_ptr frame(new line_string_impl); - boost::scoped_ptr roof(new polygon_impl); - std::deque face_segments; - double x0(0); - double y0(0); - unsigned cm = geom.vertex(&x0,&y0); - for (unsigned j=1;jmove_to(x,y); - } - else if (cm == SEG_LINETO) - { - frame->line_to(x,y); - face_segments.push_back(segment_t(x0,y0,x,y)); - } - - x0 = x; - y0 = y; - } - std::sort(face_segments.begin(),face_segments.end(), y_order); - std::deque::const_iterator itr=face_segments.begin(); - for (;itr!=face_segments.end();++itr) - { - boost::scoped_ptr faces(new polygon_impl); - faces->move_to(itr->get<0>(),itr->get<1>()); - faces->line_to(itr->get<2>(),itr->get<3>()); - faces->line_to(itr->get<2>(),itr->get<3>() + height); - faces->line_to(itr->get<0>(),itr->get<1>() + height); - - path_type faces_path (t_,*faces,prj_trans); - ras_ptr->add_path(faces_path); - ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(a * sym.get_opacity()))); - agg::render_scanlines(*ras_ptr, sl, ren); - ras_ptr->reset(); - - frame->move_to(itr->get<0>(),itr->get<1>()); - frame->line_to(itr->get<0>(),itr->get<1>()+height); - } - - geom.rewind(0); - for (unsigned j=0;jmove_to(x,y+height); - roof->move_to(x,y+height); - } - else if (cm == SEG_LINETO) - { - frame->line_to(x,y+height); - roof->line_to(x,y+height); - } - } - path_type path(t_,*frame,prj_trans); - agg::conv_stroke stroke(path); - ras_ptr->add_path(stroke); - ren.color(agg::rgba8(r * 0.8, g * 0.8 , b * 0.8, int(255 * sym.get_opacity()))); - agg::render_scanlines(*ras_ptr, sl, ren); - ras_ptr->reset(); - - path_type roof_path (t_,*roof,prj_trans); - ras_ptr->add_path(roof_path); - ren.color(agg::rgba8(r, g, b, int(a * sym.get_opacity()))); - agg::render_scanlines(*ras_ptr, sl, ren); - } - } -} - - template void agg_renderer::process(line_pattern_symbolizer const& sym, Feature const& feature, diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp new file mode 100644 index 000000000..64fd1d232 --- /dev/null +++ b/src/agg/process_building_symbolizer.cpp @@ -0,0 +1,163 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2006 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$ + +// mapnik +#include +#include + +// boost +#include +#include + +// agg +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgba.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_conv_stroke.h" + +namespace mapnik +{ + +typedef boost::tuple segment_t; +bool y_order(segment_t const& first,segment_t const& second) +{ + double miny0 = std::min(first.get<1>(),first.get<3>()); + double miny1 = std::min(second.get<1>(),second.get<3>()); + return miny0 > miny1; +} + +template +void agg_renderer::process(building_symbolizer const& sym, + Feature const& feature, + proj_transform const& prj_trans) +{ + typedef coord_transform2 path_type; + typedef coord_transform3 path_type_roof; + typedef agg::renderer_base ren_base; + typedef agg::renderer_scanline_aa_solid renderer; + + agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); + agg::pixfmt_rgba32_plain pixf(buf); + ren_base renb(pixf); + + color const& fill_ = sym.get_fill(); + unsigned r=fill_.red(); + unsigned g=fill_.green(); + unsigned b=fill_.blue(); + unsigned a=fill_.alpha(); + renderer ren(renb); + agg::scanline_u8 sl; + + ras_ptr->reset(); + ras_ptr->gamma(agg::gamma_linear()); + + double height = sym.height(); // height in pixels + + for (unsigned i=0;i 2) + { + boost::scoped_ptr frame(new line_string_impl); + boost::scoped_ptr roof(new polygon_impl); + std::deque face_segments; + double x0(0); + double y0(0); + unsigned cm = geom.vertex(&x0,&y0); + for (unsigned j=1;jmove_to(x,y); + } + else if (cm == SEG_LINETO) + { + frame->line_to(x,y); + face_segments.push_back(segment_t(x0,y0,x,y)); + } + + x0 = x; + y0 = y; + } + std::sort(face_segments.begin(),face_segments.end(), y_order); + std::deque::const_iterator itr=face_segments.begin(); + for (;itr!=face_segments.end();++itr) + { + boost::scoped_ptr faces(new polygon_impl); + faces->move_to(itr->get<0>(),itr->get<1>()); + faces->line_to(itr->get<2>(),itr->get<3>()); + faces->line_to(itr->get<2>(),itr->get<3>() + height); + faces->line_to(itr->get<0>(),itr->get<1>() + height); + + path_type faces_path (t_,*faces,prj_trans); + ras_ptr->add_path(faces_path); + ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(a * sym.get_opacity()))); + agg::render_scanlines(*ras_ptr, sl, ren); + ras_ptr->reset(); + + frame->move_to(itr->get<0>(),itr->get<1>()); + frame->line_to(itr->get<0>(),itr->get<1>()+height); + } + + geom.rewind(0); + for (unsigned j=0;jmove_to(x,y+height); + roof->move_to(x,y+height); + } + else if (cm == SEG_LINETO) + { + frame->line_to(x,y+height); + roof->line_to(x,y+height); + } + } + path_type path(t_,*frame,prj_trans); + agg::conv_stroke stroke(path); + ras_ptr->add_path(stroke); + ren.color(agg::rgba8(r * 0.8, g * 0.8 , b * 0.8, int(255 * sym.get_opacity()))); + agg::render_scanlines(*ras_ptr, sl, ren); + ras_ptr->reset(); + + path_type roof_path (t_,*roof,prj_trans); + ras_ptr->add_path(roof_path); + ren.color(agg::rgba8(r, g, b, int(a * sym.get_opacity()))); + agg::render_scanlines(*ras_ptr, sl, ren); + } + } +} + +template void agg_renderer::process(building_symbolizer const&, + Feature const&, + proj_transform const&); + +} diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp new file mode 100644 index 000000000..beaf34a5e --- /dev/null +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -0,0 +1,88 @@ +/***************************************************************************** + * + * 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$ + +// mapnik +#include +#include +#include +#include + +// agg +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgba.h" +#include "agg_rasterizer_outline.h" +#include "agg_rasterizer_outline_aa.h" +#include "agg_scanline_u.h" +// +#include "agg_renderer_scanline.h" +#include "agg_pattern_filters_rgba.h" +#include "agg_span_allocator.h" +#include "agg_span_pattern_rgba.h" +#include "agg_renderer_outline_image.h" + +namespace mapnik { + +template +void agg_renderer::process(line_pattern_symbolizer const& sym, + Feature const& feature, + proj_transform const& prj_trans) +{ + typedef coord_transform2 path_type; + typedef agg::line_image_pattern pattern_type; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_outline_image renderer_type; + typedef agg::rasterizer_outline_aa rasterizer_type; + + agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); + agg::pixfmt_rgba32_plain pixf(buf); + + std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature); + boost::optional pat = image_cache::instance()->find(filename,true); + + if (!pat) return; + + renderer_base ren_base(pixf); + agg::pattern_filter_bilinear_rgba8 filter; + pattern_source source(*(*pat)); + pattern_type pattern (filter,source); + renderer_type ren(ren_base, pattern); + ren.clip_box(0,0,width_,height_); + rasterizer_type ras(ren); + + for (unsigned i=0;i 1) + { + path_type path(t_,geom,prj_trans); + ras.add_path(path); + } + } +} + +template void agg_renderer::process(line_pattern_symbolizer const&, + Feature const&, + proj_transform const&); + +} diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index 8143e9110..9d421b476 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -34,7 +34,6 @@ // for polygon_symbolizer #include "agg_renderer_scanline.h" - // stl #include diff --git a/src/agg/process_raster_symbolizer.cpp b/src/agg/process_raster_symbolizer.cpp new file mode 100644 index 000000000..1210a63ba --- /dev/null +++ b/src/agg/process_raster_symbolizer.cpp @@ -0,0 +1,108 @@ +/***************************************************************************** + * + * 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$ + +// mapnik +#include +#include +#include + +namespace mapnik { + + +template +void agg_renderer::process(raster_symbolizer const& sym, + Feature const& feature, + proj_transform const& prj_trans) +{ + raster_ptr const& raster=feature.get_raster(); + if (raster) + { + // If there's a colorizer defined, use it to color the raster in-place + raster_colorizer_ptr colorizer = sym.get_colorizer(); + if (colorizer) + colorizer->colorize(raster); + + box2d ext=t_.forward(raster->ext_); + + int start_x = rint(ext.minx()); + int start_y = rint(ext.miny()); + int raster_width = rint(ext.width()); + int raster_height = rint(ext.height()); + int end_x = start_x + raster_width; + int end_y = start_y + raster_height; + double err_offs_x = (ext.minx()-start_x + ext.maxx()-end_x)/2; + double err_offs_y = (ext.miny()-start_y + ext.maxy()-end_y)/2; + + if ( raster_width > 0 && raster_height > 0) + { + image_data_32 target(raster_width,raster_height); + + if (sym.get_scaling() == "fast") { + scale_image(target,raster->data_); + } else if (sym.get_scaling() == "bilinear"){ + scale_image_bilinear(target,raster->data_, err_offs_x, err_offs_y); + } else if (sym.get_scaling() == "bilinear8"){ + scale_image_bilinear8(target,raster->data_, err_offs_x, err_offs_y); + } else { + scale_image(target,raster->data_); + } + + if (sym.get_mode() == "normal"){ + if (sym.get_opacity() == 1.0) { + pixmap_.set_rectangle(start_x,start_y,target); + } else { + pixmap_.set_rectangle_alpha2(target,start_x,start_y, sym.get_opacity()); + } + } else if (sym.get_mode() == "grain_merge"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "grain_merge2"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "multiply"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "multiply2"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "divide"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "divide2"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "screen"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else if (sym.get_mode() == "hard_light"){ + pixmap_.template merge_rectangle (target,start_x,start_y, sym.get_opacity()); + } else { + if (sym.get_opacity() == 1.0){ + pixmap_.set_rectangle(start_x,start_y,target); + } else { + pixmap_.set_rectangle_alpha2(target,start_x,start_y, sym.get_opacity()); + } + } + // TODO: other modes? (add,diff,sub,...) + } + } +} + +template void agg_renderer::process(raster_symbolizer const&, + Feature const&, + proj_transform const&); + +}