True global pattern alignment, fixed local alignment
This commit is contained in:
parent
73b8369178
commit
e472ad965e
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/apply_vertex_converter.hpp>
|
||||||
#include <mapnik/renderer_common/clipping_extent.hpp>
|
#include <mapnik/renderer_common/clipping_extent.hpp>
|
||||||
#include <mapnik/vertex_converters.hpp>
|
#include <mapnik/vertex_converters.hpp>
|
||||||
|
#include <mapnik/safe_cast.hpp>
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#include <mapnik/warning_ignore_agg.hpp>
|
#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)
|
void render(renderer_base & ren_base, rasterizer & ras)
|
||||||
{
|
{
|
||||||
pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(
|
coord<double, 2> offset(pattern_offset(sym_, feature_, prj_trans_, common_,
|
||||||
sym_, feature_, common_.vars_);
|
pattern_img_.width(), pattern_img_.height()));
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
agg::rendering_buffer pattern_rbuf((agg::int8u*)pattern_img_.bytes(),
|
agg::rendering_buffer pattern_rbuf((agg::int8u*)pattern_img_.bytes(),
|
||||||
pattern_img_.width(), pattern_img_.height(),
|
pattern_img_.width(), pattern_img_.height(),
|
||||||
pattern_img_.width() * 4);
|
pattern_img_.width() * 4);
|
||||||
agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
|
agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
|
||||||
img_source_type img_src(pixf_pattern);
|
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;
|
agg::span_allocator<agg::rgba8> sa;
|
||||||
value_double opacity = get<double, keys::opacity>(sym_, feature_, common_.vars_);
|
value_double opacity = get<double, keys::opacity>(sym_, feature_, common_.vars_);
|
||||||
|
|
|
@ -37,44 +37,30 @@ namespace mapnik {
|
||||||
|
|
||||||
struct cairo_renderer_process_visitor_p
|
struct cairo_renderer_process_visitor_p
|
||||||
{
|
{
|
||||||
cairo_renderer_process_visitor_p(cairo_context & context,
|
cairo_renderer_process_visitor_p(agg::trans_affine & image_tr)
|
||||||
agg::trans_affine & image_tr,
|
: image_tr_(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) {}
|
|
||||||
|
|
||||||
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::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr_;
|
||||||
mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
|
mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
|
||||||
render_pattern<image_rgba8>(marker, image_tr_, 1.0, image);
|
render_pattern<image_rgba8>(marker, image_tr_, 1.0, image);
|
||||||
cairo_pattern pattern(image, opacity_);
|
return image;
|
||||||
pattern.set_extend(CAIRO_EXTEND_REPEAT);
|
|
||||||
pattern.set_origin(offset_x_, offset_y_);
|
|
||||||
context_.set_pattern(pattern);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator() (marker_rgba8 const& marker)
|
image_rgba8 operator() (marker_rgba8 const& marker)
|
||||||
{
|
{
|
||||||
cairo_pattern pattern(marker.get_data(), opacity_);
|
return marker.get_data();
|
||||||
pattern.set_extend(CAIRO_EXTEND_REPEAT);
|
|
||||||
pattern.set_origin(offset_x_, offset_y_);
|
|
||||||
context_.set_pattern(pattern);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cairo_context & context_;
|
|
||||||
agg::trans_affine & image_tr_;
|
agg::trans_affine & image_tr_;
|
||||||
unsigned offset_x_;
|
|
||||||
unsigned offset_y_;
|
|
||||||
float opacity_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cairo_pattern_base
|
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)
|
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_);
|
value_double opacity = get<value_double, keys::opacity>(sym_, feature_, common_.vars_);
|
||||||
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
|
agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
|
||||||
auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
|
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);
|
cairo_save_restore guard(context);
|
||||||
context.set_operator(comp_op);
|
context.set_operator(comp_op);
|
||||||
|
|
||||||
util::apply_visitor(cairo_renderer_process_visitor_p(
|
image_rgba8 pattern_img(util::apply_visitor(cairo_renderer_process_visitor_p(image_tr), marker_));
|
||||||
context, image_tr, offset_x, offset_y, opacity), 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 apply_vertex_converter_type = detail::apply_vertex_converter<VertexConverter, cairo_context>;
|
||||||
using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
|
using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
|
||||||
|
|
|
@ -20,56 +20,26 @@
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#ifndef MAPNIK_PATTERN_ALIGNMENT_HPP
|
#ifndef MAPNIK_PATTERN_ALIGNMENT_HPP
|
||||||
#define MAPNIK_PATTERN_ALIGNMENT_HPP
|
#define MAPNIK_PATTERN_ALIGNMENT_HPP
|
||||||
|
|
||||||
#include <mapnik/geometry.hpp>
|
#include <mapnik/coord.hpp>
|
||||||
#include <mapnik/vertex_adapters.hpp>
|
|
||||||
#include <mapnik/transform_path_adapter.hpp>
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
namespace mapnik {
|
||||||
#include <mapnik/warning_ignore_agg.hpp>
|
|
||||||
#include "agg_conv_clip_polygon.h"
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
|
|
||||||
namespace mapnik { namespace detail {
|
class symbolizer_base;
|
||||||
|
class feature_impl;
|
||||||
|
class proj_transform;
|
||||||
|
class renderer_common;
|
||||||
|
|
||||||
struct apply_local_alignment
|
coord<double, 2> pattern_offset(
|
||||||
{
|
symbolizer_base const & sym,
|
||||||
apply_local_alignment(view_transform const& t,
|
feature_impl const & feature,
|
||||||
proj_transform const & prj_trans,
|
proj_transform const & prj_trans,
|
||||||
box2d<double> const& clip_box,
|
renderer_common const & common,
|
||||||
double & x, double & y)
|
unsigned pattern_width,
|
||||||
: t_(t),
|
unsigned pattern_height);
|
||||||
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_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
#endif // MAPNIK_PATTERN_ALIGNMENT_HPP
|
||||||
|
|
|
@ -263,6 +263,7 @@ source = Split(
|
||||||
renderer_common/render_markers_symbolizer.cpp
|
renderer_common/render_markers_symbolizer.cpp
|
||||||
renderer_common/render_pattern.cpp
|
renderer_common/render_pattern.cpp
|
||||||
renderer_common/render_thunk_extractor.cpp
|
renderer_common/render_thunk_extractor.cpp
|
||||||
|
renderer_common/pattern_alignment.cpp
|
||||||
math.cpp
|
math.cpp
|
||||||
value.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