True global pattern alignment, fixed local alignment
This commit is contained in:
parent
692fc7f107
commit
776fa0d2f8
5 changed files with 130 additions and 103 deletions
|
@ -29,6 +29,7 @@
|
|||
#include <mapnik/renderer_common/apply_vertex_converter.hpp>
|
||||
#include <mapnik/renderer_common/clipping_extent.hpp>
|
||||
#include <mapnik/vertex_converters.hpp>
|
||||
#include <mapnik/safe_cast.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore_agg.hpp>
|
||||
|
@ -107,29 +108,14 @@ struct agg_polygon_pattern : agg_pattern_base
|
|||
|
||||
void render(renderer_base & ren_base, rasterizer & ras)
|
||||
{
|
||||
pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(
|
||||
sym_, feature_, common_.vars_);
|
||||
unsigned offset_x=0;
|
||||
unsigned offset_y=0;
|
||||
|
||||
if (alignment == LOCAL_ALIGNMENT)
|
||||
{
|
||||
double x0 = 0;
|
||||
double y0 = 0;
|
||||
using apply_local_alignment = detail::apply_local_alignment;
|
||||
apply_local_alignment apply(common_.t_, prj_trans_, clip_box_, x0, y0);
|
||||
util::apply_visitor(geometry::vertex_processor<apply_local_alignment>(apply), feature_.get_geometry());
|
||||
|
||||
offset_x = unsigned(ren_base.width() - x0);
|
||||
offset_y = unsigned(ren_base.height() - y0);
|
||||
}
|
||||
|
||||
coord<double, 2> offset(pattern_offset(sym_, feature_, prj_trans_, common_,
|
||||
pattern_img_.width(), pattern_img_.height()));
|
||||
agg::rendering_buffer pattern_rbuf((agg::int8u*)pattern_img_.bytes(),
|
||||
pattern_img_.width(), pattern_img_.height(),
|
||||
pattern_img_.width() * 4);
|
||||
agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
|
||||
img_source_type img_src(pixf_pattern);
|
||||
span_gen_type sg(img_src, offset_x, offset_y);
|
||||
span_gen_type sg(img_src, safe_cast<unsigned>(offset.x), safe_cast<unsigned>(offset.y));
|
||||
|
||||
agg::span_allocator<agg::rgba8> sa;
|
||||
value_double opacity = get<double, keys::opacity>(sym_, feature_, common_.vars_);
|
||||
|
|
|
@ -37,44 +37,30 @@ namespace mapnik {
|
|||
|
||||
struct cairo_renderer_process_visitor_p
|
||||
{
|
||||
cairo_renderer_process_visitor_p(cairo_context & context,
|
||||
agg::trans_affine & image_tr,
|
||||
unsigned offset_x,
|
||||
unsigned offset_y,
|
||||
float opacity)
|
||||
: context_(context),
|
||||
image_tr_(image_tr),
|
||||
offset_x_(offset_x),
|
||||
offset_y_(offset_y),
|
||||
opacity_(opacity) {}
|
||||
cairo_renderer_process_visitor_p(agg::trans_affine & image_tr)
|
||||
: image_tr_(image_tr)
|
||||
{}
|
||||
|
||||
void operator() (marker_null const&) {}
|
||||
image_rgba8 operator() (marker_null const&)
|
||||
{
|
||||
return image_rgba8();
|
||||
}
|
||||
|
||||
void operator() (marker_svg const& marker)
|
||||
image_rgba8 operator() (marker_svg const& marker)
|
||||
{
|
||||
mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr_;
|
||||
mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
|
||||
render_pattern<image_rgba8>(marker, image_tr_, 1.0, image);
|
||||
cairo_pattern pattern(image, opacity_);
|
||||
pattern.set_extend(CAIRO_EXTEND_REPEAT);
|
||||
pattern.set_origin(offset_x_, offset_y_);
|
||||
context_.set_pattern(pattern);
|
||||
return image;
|
||||
}
|
||||
|
||||
void operator() (marker_rgba8 const& marker)
|
||||
image_rgba8 operator() (marker_rgba8 const& marker)
|
||||
{
|
||||
cairo_pattern pattern(marker.get_data(), opacity_);
|
||||
pattern.set_extend(CAIRO_EXTEND_REPEAT);
|
||||
pattern.set_origin(offset_x_, offset_y_);
|
||||
context_.set_pattern(pattern);
|
||||
return marker.get_data();
|
||||
}
|
||||
|
||||
private:
|
||||
cairo_context & context_;
|
||||
agg::trans_affine & image_tr_;
|
||||
unsigned offset_x_;
|
||||
unsigned offset_y_;
|
||||
float opacity_;
|
||||
};
|
||||
|
||||
struct cairo_pattern_base
|
||||
|
@ -122,20 +108,6 @@ struct cairo_polygon_pattern : cairo_pattern_base
|
|||
|
||||
void render(cairo_fill_rule_t fill_rule, cairo_context & context)
|
||||
{
|
||||
unsigned offset_x=0;
|
||||
unsigned offset_y=0;
|
||||
pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym_, feature_, common_.vars_);
|
||||
if (alignment == LOCAL_ALIGNMENT)
|
||||
{
|
||||
double x0 = 0.0;
|
||||
double y0 = 0.0;
|
||||
using apply_local_alignment = detail::apply_local_alignment;
|
||||
apply_local_alignment apply(common_.t_, prj_trans_, clip_box_, x0, y0);
|
||||
util::apply_visitor(geometry::vertex_processor<apply_local_alignment>(apply), feature_.get_geometry());
|
||||
offset_x = std::abs(clip_box_.width() - x0);
|
||||
offset_y = std::abs(clip_box_.height() - y0);
|
||||
}
|
||||
|
||||
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
|
||||
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
|
||||
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
|
||||
|
@ -149,8 +121,13 @@ struct cairo_polygon_pattern : cairo_pattern_base
|
|||
cairo_save_restore guard(context);
|
||||
context.set_operator(comp_op);
|
||||
|
||||
util::apply_visitor(cairo_renderer_process_visitor_p(
|
||||
context, image_tr, offset_x, offset_y, opacity), marker_);
|
||||
image_rgba8 pattern_img(util::apply_visitor(cairo_renderer_process_visitor_p(image_tr), marker_));
|
||||
coord<double, 2> offset(pattern_offset(sym_, feature_, prj_trans_, common_,
|
||||
pattern_img.width(), pattern_img.height()));
|
||||
cairo_pattern pattern(pattern_img, opacity);
|
||||
pattern.set_extend(CAIRO_EXTEND_REPEAT);
|
||||
pattern.set_origin(-offset.x, -offset.y);
|
||||
context.set_pattern(pattern);
|
||||
|
||||
using apply_vertex_converter_type = detail::apply_vertex_converter<VertexConverter, cairo_context>;
|
||||
using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
|
||||
|
|
|
@ -20,56 +20,26 @@
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef MAPNIK_PATTERN_ALIGNMENT_HPP
|
||||
#define MAPNIK_PATTERN_ALIGNMENT_HPP
|
||||
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/vertex_adapters.hpp>
|
||||
#include <mapnik/transform_path_adapter.hpp>
|
||||
#include <mapnik/coord.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore_agg.hpp>
|
||||
#include "agg_conv_clip_polygon.h"
|
||||
#pragma GCC diagnostic pop
|
||||
namespace mapnik {
|
||||
|
||||
namespace mapnik { namespace detail {
|
||||
class symbolizer_base;
|
||||
class feature_impl;
|
||||
class proj_transform;
|
||||
class renderer_common;
|
||||
|
||||
struct apply_local_alignment
|
||||
{
|
||||
apply_local_alignment(view_transform const& t,
|
||||
proj_transform const& prj_trans,
|
||||
box2d<double> const& clip_box,
|
||||
double & x, double & y)
|
||||
: t_(t),
|
||||
prj_trans_(prj_trans),
|
||||
clip_box_(clip_box),
|
||||
x_(x),
|
||||
y_(y) {}
|
||||
|
||||
void operator() (geometry::polygon_vertex_adapter<double> & va)
|
||||
{
|
||||
using clipped_geometry_type = agg::conv_clip_polygon<geometry::polygon_vertex_adapter<double> >;
|
||||
using path_type = transform_path_adapter<view_transform,clipped_geometry_type>;
|
||||
clipped_geometry_type clipped(va);
|
||||
clipped.clip_box(clip_box_.minx(),clip_box_.miny(),clip_box_.maxx(),clip_box_.maxy());
|
||||
path_type path(t_, clipped, prj_trans_);
|
||||
path.vertex(&x_,&y_);
|
||||
}
|
||||
coord<double, 2> pattern_offset(
|
||||
symbolizer_base const & sym,
|
||||
feature_impl const & feature,
|
||||
proj_transform const & prj_trans,
|
||||
renderer_common const & common,
|
||||
unsigned pattern_width,
|
||||
unsigned pattern_height);
|
||||
|
||||
template <typename Adapter>
|
||||
void operator() (Adapter &)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
view_transform const& t_;
|
||||
proj_transform const& prj_trans_;
|
||||
box2d<double> const& clip_box_;
|
||||
double & x_;
|
||||
double & y_;
|
||||
};
|
||||
|
||||
}}
|
||||
}
|
||||
|
||||
#endif // MAPNIK_PATTERN_ALIGNMENT_HPP
|
||||
|
|
|
@ -269,6 +269,7 @@ source = Split(
|
|||
renderer_common/render_markers_symbolizer.cpp
|
||||
renderer_common/render_pattern.cpp
|
||||
renderer_common/render_thunk_extractor.cpp
|
||||
renderer_common/pattern_alignment.cpp
|
||||
util/math.cpp
|
||||
value.cpp
|
||||
"""
|
||||
|
|
93
src/renderer_common/pattern_alignment.cpp
Normal file
93
src/renderer_common/pattern_alignment.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/view_transform.hpp>
|
||||
#include <mapnik/vertex_adapters.hpp>
|
||||
#include <mapnik/vertex_processor.hpp>
|
||||
#include <mapnik/transform_path_adapter.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/renderer_common.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
namespace {
|
||||
|
||||
struct apply_local_alignment
|
||||
{
|
||||
apply_local_alignment(view_transform const& t,
|
||||
proj_transform const& prj_trans,
|
||||
double & x, double & y)
|
||||
: t_(t),
|
||||
prj_trans_(prj_trans),
|
||||
x_(x),
|
||||
y_(y) {}
|
||||
|
||||
void operator() (geometry::polygon_vertex_adapter<double> & va)
|
||||
{
|
||||
using path_type = transform_path_adapter<view_transform, decltype(va)>;
|
||||
path_type path(t_, va, prj_trans_);
|
||||
path.rewind(0);
|
||||
path.vertex(&x_, &y_);
|
||||
}
|
||||
|
||||
template <typename Adapter>
|
||||
void operator() (Adapter &)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
view_transform const& t_;
|
||||
proj_transform const& prj_trans_;
|
||||
double & x_;
|
||||
double & y_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
coord<double, 2> pattern_offset(
|
||||
symbolizer_base const & sym,
|
||||
mapnik::feature_impl const & feature,
|
||||
proj_transform const & prj_trans,
|
||||
renderer_common const & common,
|
||||
unsigned pattern_width,
|
||||
unsigned pattern_height)
|
||||
{
|
||||
coord<double, 2> reference_position(0, 0);
|
||||
pattern_alignment_enum alignment_type = get<pattern_alignment_enum, keys::alignment>(sym, feature, common.vars_);
|
||||
|
||||
if (alignment_type == LOCAL_ALIGNMENT)
|
||||
{
|
||||
apply_local_alignment apply(common.t_, prj_trans, reference_position.x, reference_position.y);
|
||||
util::apply_visitor(geometry::vertex_processor<apply_local_alignment>(apply), feature.get_geometry());
|
||||
}
|
||||
else
|
||||
{
|
||||
common.t_.forward(&reference_position.x, &reference_position.y);
|
||||
}
|
||||
|
||||
return coord<double, 2>(
|
||||
std::fmod(-reference_position.x, pattern_width) + pattern_width,
|
||||
std::fmod(-reference_position.y, pattern_height) + pattern_height);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue