2008-02-23 01:17:53 +01:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
|
|
|
* This file is part of Mapnik (c++ mapping toolkit)
|
|
|
|
*
|
2015-06-16 12:49:16 +02:00
|
|
|
* Copyright (C) 2015 Artem Pavlenko
|
2008-02-23 01:17:53 +01:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2009-06-08 21:43:49 +02:00
|
|
|
#if defined(HAVE_CAIRO)
|
|
|
|
|
2008-02-23 01:17:53 +01:00
|
|
|
// mapnik
|
2013-01-06 20:56:35 +01:00
|
|
|
#include <mapnik/debug.hpp>
|
2012-07-25 03:35:41 +02:00
|
|
|
#include <mapnik/layer.hpp>
|
2013-01-28 05:54:31 +01:00
|
|
|
#include <mapnik/proj_transform.hpp>
|
2014-06-06 14:38:00 +02:00
|
|
|
#include <mapnik/cairo/cairo_renderer.hpp>
|
2014-08-10 22:53:45 +02:00
|
|
|
#include <mapnik/cairo/cairo_render_vector.hpp>
|
2013-01-06 20:56:35 +01:00
|
|
|
#include <mapnik/map.hpp>
|
2011-01-26 02:18:40 +01:00
|
|
|
#include <mapnik/svg/svg_path_adapter.hpp>
|
2013-03-13 00:56:47 +01:00
|
|
|
#include <mapnik/pixel_position.hpp>
|
2014-05-14 03:24:17 +02:00
|
|
|
#include <mapnik/attribute.hpp>
|
2014-08-10 22:53:45 +02:00
|
|
|
#include <mapnik/request.hpp>
|
|
|
|
#include <mapnik/label_collision_detector.hpp>
|
|
|
|
#include <mapnik/marker.hpp>
|
|
|
|
#include <mapnik/marker_cache.hpp>
|
2016-08-03 14:53:24 +02:00
|
|
|
#include <mapnik/feature_type_style.hpp>
|
2008-02-23 01:17:53 +01:00
|
|
|
|
2012-03-08 12:07:13 +01:00
|
|
|
// agg
|
2014-08-10 22:53:45 +02:00
|
|
|
#include "agg/include/agg_trans_affine.h" // for trans_affine, etc
|
2012-03-28 01:21:11 +02:00
|
|
|
|
2012-10-04 21:03:40 +02:00
|
|
|
// stl
|
2013-11-06 00:53:07 +01:00
|
|
|
#include <cmath>
|
2012-10-04 21:03:40 +02:00
|
|
|
|
2008-02-23 01:17:53 +01:00
|
|
|
namespace mapnik
|
|
|
|
{
|
2012-02-02 02:53:35 +01:00
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
class feature_type_style;
|
2011-01-26 02:18:40 +01:00
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
cairo_renderer<T>::cairo_renderer(Map const& m,
|
|
|
|
T const& cairo,
|
|
|
|
double scale_factor,
|
|
|
|
unsigned offset_x,
|
|
|
|
unsigned offset_y)
|
|
|
|
: feature_style_processor<cairo_renderer>(m, scale_factor),
|
|
|
|
m_(m),
|
2013-01-09 18:00:30 +01:00
|
|
|
context_(cairo),
|
2014-08-10 22:53:45 +02:00
|
|
|
common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor),
|
2016-08-03 14:53:24 +02:00
|
|
|
face_manager_(common_.shared_font_library_),
|
|
|
|
style_level_compositing_(false)
|
2012-08-25 11:43:31 +02:00
|
|
|
{
|
2013-02-21 02:55:53 +01:00
|
|
|
setup(m);
|
2012-08-25 11:43:31 +02:00
|
|
|
}
|
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
cairo_renderer<T>::cairo_renderer(Map const& m,
|
|
|
|
request const& req,
|
|
|
|
attributes const& vars,
|
|
|
|
T const& cairo,
|
|
|
|
double scale_factor,
|
|
|
|
unsigned offset_x,
|
|
|
|
unsigned offset_y)
|
|
|
|
: feature_style_processor<cairo_renderer>(m, scale_factor),
|
|
|
|
m_(m),
|
2013-02-26 21:05:44 +01:00
|
|
|
context_(cairo),
|
2014-09-26 07:37:43 +02:00
|
|
|
common_(m, req, vars, offset_x, offset_y, req.width(), req.height(), scale_factor),
|
2016-08-03 14:53:24 +02:00
|
|
|
face_manager_(common_.shared_font_library_),
|
|
|
|
style_level_compositing_(false)
|
|
|
|
|
2013-02-26 21:05:44 +01:00
|
|
|
{
|
|
|
|
setup(m);
|
|
|
|
}
|
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
cairo_renderer<T>::cairo_renderer(Map const& m,
|
|
|
|
T const& cairo,
|
|
|
|
std::shared_ptr<label_collision_detector4> detector,
|
|
|
|
double scale_factor,
|
|
|
|
unsigned offset_x,
|
|
|
|
unsigned offset_y)
|
|
|
|
: feature_style_processor<cairo_renderer>(m, scale_factor),
|
|
|
|
m_(m),
|
2013-01-09 18:00:30 +01:00
|
|
|
context_(cairo),
|
2014-08-10 22:53:45 +02:00
|
|
|
common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor, detector),
|
2016-08-03 14:53:24 +02:00
|
|
|
face_manager_(common_.shared_font_library_),
|
|
|
|
style_level_compositing_(false)
|
|
|
|
|
2009-12-16 21:02:06 +01:00
|
|
|
{
|
2014-08-10 22:53:45 +02:00
|
|
|
setup(m);
|
2009-12-16 21:02:06 +01:00
|
|
|
}
|
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
cairo_renderer<T>::~cairo_renderer() {}
|
2012-08-25 11:43:31 +02:00
|
|
|
|
2015-02-19 05:58:33 +01:00
|
|
|
struct setup_marker_visitor
|
|
|
|
{
|
|
|
|
setup_marker_visitor(cairo_context & context, renderer_common const& common)
|
|
|
|
: context_(context), common_(common) {}
|
|
|
|
|
2016-01-27 14:50:17 +01:00
|
|
|
void operator() (marker_null const &) const{}
|
|
|
|
void operator() (marker_svg const &) const {}
|
2015-02-19 05:58:33 +01:00
|
|
|
|
2016-01-27 14:50:17 +01:00
|
|
|
void operator() (marker_rgba8 const& marker) const
|
2015-02-19 05:58:33 +01:00
|
|
|
{
|
|
|
|
mapnik::image_rgba8 const& bg_image = marker.get_data();
|
2015-06-16 04:36:36 +02:00
|
|
|
std::size_t w = bg_image.width();
|
|
|
|
std::size_t h = bg_image.height();
|
2015-02-19 05:58:33 +01:00
|
|
|
if ( w > 0 && h > 0)
|
|
|
|
{
|
|
|
|
// repeat background-image both vertically and horizontally
|
2015-06-16 04:36:36 +02:00
|
|
|
std::size_t x_steps = std::size_t(std::ceil(common_.width_/double(w)));
|
|
|
|
std::size_t y_steps = std::size_t(std::ceil(common_.height_/double(h)));
|
|
|
|
for (std::size_t x=0;x<x_steps;++x)
|
2015-02-19 05:58:33 +01:00
|
|
|
{
|
2015-06-16 04:36:36 +02:00
|
|
|
for (std::size_t y=0;y<y_steps;++y)
|
2015-02-19 05:58:33 +01:00
|
|
|
{
|
|
|
|
agg::trans_affine matrix = agg::trans_affine_translation(
|
|
|
|
x*w,
|
|
|
|
y*h);
|
|
|
|
context_.add_image(matrix, bg_image, 1.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
cairo_context & context_;
|
|
|
|
renderer_common const& common_;
|
|
|
|
};
|
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
void cairo_renderer<T>::setup(Map const& map)
|
2013-02-21 02:55:53 +01:00
|
|
|
{
|
|
|
|
boost::optional<color> bg = m_.background();
|
|
|
|
if (bg)
|
|
|
|
{
|
2014-07-31 01:11:06 +02:00
|
|
|
cairo_save_restore guard(context_);
|
|
|
|
context_.set_color(*bg);
|
|
|
|
context_.paint();
|
2013-02-21 02:55:53 +01:00
|
|
|
}
|
|
|
|
boost::optional<std::string> const& image_filename = map.background_image();
|
|
|
|
if (image_filename)
|
|
|
|
{
|
2014-07-31 01:11:06 +02:00
|
|
|
// NOTE: marker_cache returns premultiplied image, if needed
|
2015-05-04 21:11:41 +02:00
|
|
|
std::shared_ptr<mapnik::marker const> bg_marker = mapnik::marker_cache::instance().find(*image_filename,true);
|
|
|
|
util::apply_visitor(setup_marker_visitor(context_, common_), *bg_marker);
|
2013-02-21 02:55:53 +01:00
|
|
|
}
|
2014-08-10 22:53:45 +02:00
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Scale=" << map.scale();
|
2013-02-21 02:55:53 +01:00
|
|
|
}
|
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
void cairo_renderer<T>::start_map_processing(Map const& map)
|
2009-12-16 21:02:06 +01:00
|
|
|
{
|
2014-08-10 22:53:45 +02:00
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Start map processing bbox=" << map.get_current_extent();
|
2013-12-05 19:39:09 +01:00
|
|
|
box2d<double> bounds = common_.t_.forward(common_.t_.extent());
|
2013-01-09 18:00:30 +01:00
|
|
|
context_.rectangle(bounds.minx(), bounds.miny(), bounds.maxx(), bounds.maxy());
|
|
|
|
context_.clip();
|
2012-07-04 15:50:11 +02:00
|
|
|
}
|
2009-02-06 01:46:29 +01:00
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
void cairo_renderer<T>::end_map_processing(Map const&)
|
2012-07-04 15:50:11 +02:00
|
|
|
{
|
2014-08-10 22:53:45 +02:00
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: End map processing";
|
2012-07-04 15:50:11 +02:00
|
|
|
}
|
2012-04-09 21:41:56 +02:00
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
void cairo_renderer<T>::start_layer_processing(layer const& lay, box2d<double> const& query_extent)
|
2012-07-04 15:50:11 +02:00
|
|
|
{
|
2014-08-10 22:53:45 +02:00
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Start processing layer=" << lay.name() ;
|
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: -- datasource=" << lay.datasource().get();
|
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: -- query_extent=" << query_extent;
|
2012-03-13 15:56:11 +01:00
|
|
|
|
2012-07-04 15:50:11 +02:00
|
|
|
if (lay.clear_label_cache())
|
2012-02-02 02:53:35 +01:00
|
|
|
{
|
2014-07-31 01:11:06 +02:00
|
|
|
common_.detector_->clear();
|
2012-02-02 02:53:35 +01:00
|
|
|
}
|
2013-12-05 19:39:09 +01:00
|
|
|
common_.query_extent_ = query_extent;
|
2012-07-04 15:50:11 +02:00
|
|
|
}
|
2008-02-23 01:17:53 +01:00
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
|
|
|
void cairo_renderer<T>::end_layer_processing(layer const&)
|
2012-07-04 15:50:11 +02:00
|
|
|
{
|
2014-08-10 22:53:45 +02:00
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: End layer processing";
|
2012-07-04 15:50:11 +02:00
|
|
|
}
|
2012-05-03 13:17:37 +02:00
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
2016-08-03 14:53:24 +02:00
|
|
|
void cairo_renderer<T>::start_style_processing(feature_type_style const & st)
|
2012-07-04 15:50:11 +02:00
|
|
|
{
|
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:start style processing";
|
2016-08-03 14:53:24 +02:00
|
|
|
|
|
|
|
style_level_compositing_ = st.comp_op() || st.get_opacity() < 1;
|
|
|
|
|
|
|
|
if (style_level_compositing_)
|
|
|
|
{
|
|
|
|
context_.push_group();
|
|
|
|
}
|
2012-07-04 15:50:11 +02:00
|
|
|
}
|
2012-04-18 16:09:12 +02:00
|
|
|
|
2014-08-10 22:53:45 +02:00
|
|
|
template <typename T>
|
2016-08-03 14:53:24 +02:00
|
|
|
void cairo_renderer<T>::end_style_processing(feature_type_style const & st)
|
2012-07-04 15:50:11 +02:00
|
|
|
{
|
|
|
|
MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:end style processing";
|
2016-08-03 14:53:24 +02:00
|
|
|
|
|
|
|
if (style_level_compositing_)
|
|
|
|
{
|
|
|
|
context_.pop_group();
|
|
|
|
composite_mode_e comp_op = st.comp_op() ? *st.comp_op() : src_over;
|
|
|
|
context_.set_operator(comp_op);
|
|
|
|
context_.paint(st.get_opacity());
|
|
|
|
}
|
2012-07-04 15:50:11 +02:00
|
|
|
}
|
|
|
|
|
2015-02-19 05:58:33 +01:00
|
|
|
struct cairo_render_marker_visitor
|
2012-08-09 18:46:55 +02:00
|
|
|
{
|
2015-02-19 05:58:33 +01:00
|
|
|
cairo_render_marker_visitor(cairo_context & context,
|
|
|
|
renderer_common const& common,
|
|
|
|
pixel_position const& pos,
|
|
|
|
agg::trans_affine const& tr,
|
|
|
|
double opacity,
|
|
|
|
bool recenter)
|
|
|
|
: context_(context),
|
|
|
|
common_(common),
|
|
|
|
pos_(pos),
|
|
|
|
tr_(tr),
|
|
|
|
opacity_(opacity),
|
|
|
|
recenter_(recenter) {}
|
|
|
|
|
|
|
|
void operator() (marker_null const&) {}
|
|
|
|
|
|
|
|
void operator() (marker_svg const& marker)
|
2012-08-09 18:46:55 +02:00
|
|
|
{
|
2015-02-19 05:58:33 +01:00
|
|
|
mapnik::svg_path_ptr vmarker = marker.get_data();
|
2014-07-31 01:11:06 +02:00
|
|
|
if (vmarker)
|
|
|
|
{
|
|
|
|
box2d<double> bbox = vmarker->bounding_box();
|
2015-02-19 05:58:33 +01:00
|
|
|
agg::trans_affine marker_tr = tr_;
|
|
|
|
if (recenter_)
|
2014-10-07 01:05:19 +02:00
|
|
|
{
|
|
|
|
coord<double,2> c = bbox.center();
|
|
|
|
marker_tr = agg::trans_affine_translation(-c.x,-c.y);
|
2015-02-19 05:58:33 +01:00
|
|
|
marker_tr *= tr_;
|
2014-10-07 01:05:19 +02:00
|
|
|
}
|
|
|
|
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
|
2014-07-31 01:11:06 +02:00
|
|
|
agg::pod_bvector<svg::path_attributes> const & attributes = vmarker->attributes();
|
|
|
|
svg::vertex_stl_adapter<svg::svg_path_storage> stl_storage(vmarker->source());
|
|
|
|
svg::svg_path_adapter svg_path(stl_storage);
|
2015-02-19 05:58:33 +01:00
|
|
|
marker_tr.translate(pos_.x, pos_.y);
|
|
|
|
render_vector_marker(context_, svg_path, attributes, bbox, marker_tr, opacity_);
|
2014-07-31 01:11:06 +02:00
|
|
|
}
|
2011-01-26 02:18:40 +01:00
|
|
|
}
|
2015-02-19 05:58:33 +01:00
|
|
|
|
|
|
|
void operator() (marker_rgba8 const& marker)
|
2010-03-03 04:26:12 +01:00
|
|
|
{
|
2015-02-19 05:58:33 +01:00
|
|
|
double width = marker.get_data().width();
|
|
|
|
double height = marker.get_data().height();
|
2014-07-31 01:11:06 +02:00
|
|
|
double cx = 0.5 * width;
|
|
|
|
double cy = 0.5 * height;
|
|
|
|
agg::trans_affine marker_tr;
|
|
|
|
marker_tr *= agg::trans_affine_translation(-cx,-cy);
|
2015-02-19 05:58:33 +01:00
|
|
|
marker_tr *= tr_;
|
2014-07-31 01:11:06 +02:00
|
|
|
marker_tr *= agg::trans_affine_scaling(common_.scale_factor_);
|
2015-02-19 05:58:33 +01:00
|
|
|
marker_tr *= agg::trans_affine_translation(pos_.x,pos_.y);
|
|
|
|
context_.add_image(marker_tr, marker.get_data(), opacity_);
|
2012-07-04 15:50:11 +02:00
|
|
|
}
|
2015-02-19 05:58:33 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
cairo_context & context_;
|
|
|
|
renderer_common const& common_;
|
|
|
|
pixel_position const& pos_;
|
|
|
|
agg::trans_affine const& tr_;
|
|
|
|
double opacity_;
|
|
|
|
bool recenter_;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void cairo_renderer<T>::render_marker(pixel_position const& pos,
|
|
|
|
marker const& marker,
|
|
|
|
agg::trans_affine const& tr,
|
|
|
|
double opacity,
|
|
|
|
bool recenter)
|
|
|
|
|
|
|
|
{
|
|
|
|
cairo_save_restore guard(context_);
|
|
|
|
cairo_render_marker_visitor visitor(context_,
|
|
|
|
common_,
|
|
|
|
pos,
|
|
|
|
tr,
|
|
|
|
opacity,
|
|
|
|
recenter);
|
|
|
|
util::apply_visitor(visitor, marker);
|
2012-07-04 15:50:11 +02:00
|
|
|
}
|
2011-01-26 02:18:40 +01:00
|
|
|
|
2013-01-09 18:00:30 +01:00
|
|
|
template class cairo_renderer<cairo_ptr>;
|
2014-08-11 14:40:12 +02:00
|
|
|
|
2008-02-23 01:17:53 +01:00
|
|
|
}
|
2009-06-08 21:43:49 +02:00
|
|
|
|
2012-07-13 12:17:35 +02:00
|
|
|
#endif // HAVE_CAIRO
|