add grid_renderer backend
This commit is contained in:
parent
6d7ca1ac6f
commit
5eea164b5a
24 changed files with 3094 additions and 33 deletions
|
@ -14,6 +14,9 @@ For a complete change history, see the SVN log.
|
|||
Mapnik Trunk
|
||||
------------
|
||||
|
||||
- Added new rendering backend, grid_renderer, that collects the attributes of rendered features and
|
||||
burns their ids into a grid buffer.
|
||||
|
||||
- Added optional 'maximum-extent' parameter to map object. If set will be used, instead of combined
|
||||
layer extents, for return value of map.zoom_all(). Useful in cases where the combined layer extents
|
||||
cannot possibly be projected into the map srs or the user wishes to control map bounds without
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
// Windows DLL support
|
||||
|
||||
#define MAPNIK_SUPPORTS_GRID_RENDERER
|
||||
|
||||
#ifdef _WINDOWS
|
||||
# define MAPNIK_EXP __declspec (dllexport)
|
||||
# define MAPNIK_IMP __declspec (dllimport)
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
scale_factor_(scale_factor) {}
|
||||
|
||||
/*!
|
||||
* @return apply renderer to all maps layers.
|
||||
* @return apply renderer to all map layers.
|
||||
*/
|
||||
void apply()
|
||||
{
|
||||
|
@ -124,6 +124,30 @@ public:
|
|||
p.end_map_processing(m_);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @return apply renderer to a single layer, providing pre-populated set of query attribute names.
|
||||
*/
|
||||
void apply(mapnik::layer const& lyr, std::set<std::string>& names)
|
||||
{
|
||||
Processor & p = static_cast<Processor&>(*this);
|
||||
p.start_map_processing(m_);
|
||||
try
|
||||
{
|
||||
projection proj(m_.srs());
|
||||
double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic());
|
||||
scale_denom *= scale_factor_;
|
||||
|
||||
if (lyr.isVisible(scale_denom))
|
||||
{
|
||||
apply_to_layer(lyr, p, proj, scale_denom, names);
|
||||
}
|
||||
}
|
||||
catch (proj_init_error& ex)
|
||||
{
|
||||
std::clog << "proj_init_error:" << ex.what() << "\n";
|
||||
}
|
||||
p.end_map_processing(m_);
|
||||
}
|
||||
private:
|
||||
/*!
|
||||
* @return initialize metawriters for a given map and projection.
|
||||
|
@ -153,7 +177,7 @@ private:
|
|||
}
|
||||
|
||||
/*!
|
||||
* @return render a layer given a projection and scale
|
||||
* @return render a layer given a projection and scale.
|
||||
*/
|
||||
void apply_to_layer(layer const& lay, Processor & p,
|
||||
projection const& proj0,
|
||||
|
|
|
@ -54,6 +54,7 @@ extern "C"
|
|||
#include <vector>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
// icu
|
||||
#include <unicode/ubidi.h>
|
||||
|
@ -490,6 +491,42 @@ struct text_renderer : private boost::noncopyable
|
|||
}
|
||||
}
|
||||
|
||||
void render_id(int feature_id,double x0, double y0, double min_radius=1.0)
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Vector start;
|
||||
unsigned height = pixmap_.height();
|
||||
|
||||
start.x = static_cast<FT_Pos>(x0 * (1 << 6));
|
||||
start.y = static_cast<FT_Pos>((height - y0) * (1 << 6));
|
||||
|
||||
// now render transformed glyphs
|
||||
typename glyphs_t::iterator pos;
|
||||
|
||||
stroker_.init(std::max(halo_radius_,min_radius));
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
{
|
||||
FT_Glyph g;
|
||||
error = FT_Glyph_Copy(pos->image, &g);
|
||||
if (!error)
|
||||
{
|
||||
FT_Glyph_Transform(g,0,&start);
|
||||
FT_Glyph_Stroke(&g,stroker_.get(),1);
|
||||
error = FT_Glyph_To_Bitmap( &g,FT_RENDER_MODE_NORMAL,0,1);
|
||||
//error = FT_Glyph_To_Bitmap( &g,FT_RENDER_MODE_MONO,0,1);
|
||||
if ( ! error )
|
||||
{
|
||||
|
||||
FT_BitmapGlyph bit = (FT_BitmapGlyph)g;
|
||||
render_bitmap_id(&bit->bitmap, feature_id,
|
||||
bit->left,
|
||||
height - bit->top);
|
||||
}
|
||||
}
|
||||
FT_Done_Glyph(g);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// unused currently, stroker is the new method for drawing halos
|
||||
|
@ -535,6 +572,26 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void render_bitmap_id(FT_Bitmap *bitmap,int feature_id,int x,int y)
|
||||
{
|
||||
int x_max=x+bitmap->width;
|
||||
int y_max=y+bitmap->rows;
|
||||
int i,p,j,q;
|
||||
|
||||
for (i=x,p=0;i<x_max;++i,++p)
|
||||
{
|
||||
for (j=y,q=0;j<y_max;++j,++q)
|
||||
{
|
||||
int gray=bitmap->buffer[q*bitmap->width+p];
|
||||
if (gray)
|
||||
{
|
||||
pixmap_.setPixel(i,j,feature_id);
|
||||
//pixmap_.blendPixel2(i,j,rgba,gray,opacity_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pixmap_type & pixmap_;
|
||||
face_set_ptr faces_;
|
||||
stroker & stroker_;
|
||||
|
|
269
include/mapnik/grid/grid.hpp
Normal file
269
include/mapnik/grid/grid.hpp
Normal file
|
@ -0,0 +1,269 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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_GRID_HPP
|
||||
#define MAPNIK_GRID_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/image_data.hpp>
|
||||
#include <mapnik/box2d.hpp>
|
||||
#include <mapnik/image_view.hpp>
|
||||
#include <mapnik/global.hpp>
|
||||
#include <mapnik/value.hpp>
|
||||
|
||||
// stl
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class MAPNIK_DECL hit_grid
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef mapnik::ImageData<value_type> data_type;
|
||||
typedef std::string lookup_type;
|
||||
// mapping between pixel id and join_field
|
||||
typedef std::map<value_type, lookup_type> feature_key_type;
|
||||
typedef std::map<lookup_type, value_type> key_type;
|
||||
typedef std::map<std::string, mapnik::value> feature_properties_type;
|
||||
// note: feature_type is not the same as a mapnik::Feature as it lacks a geometry
|
||||
typedef std::map<std::string, feature_properties_type > feature_type;
|
||||
|
||||
private:
|
||||
unsigned width_;
|
||||
unsigned height_;
|
||||
std::string join_field_;
|
||||
key_type keys_;
|
||||
std::vector<std::string> key_order_;
|
||||
feature_key_type f_keys_;
|
||||
feature_type features_;
|
||||
data_type data_;
|
||||
std::set<std::string> names_;
|
||||
unsigned int step_;
|
||||
|
||||
public:
|
||||
|
||||
//value_type feature_count_;
|
||||
std::string id_name_;
|
||||
|
||||
hit_grid(int width, int height, std::string const& join_field, unsigned step)
|
||||
:width_(width),
|
||||
height_(height),
|
||||
join_field_(join_field),
|
||||
data_(width,height),
|
||||
step_(step),
|
||||
//feature_count_(0),
|
||||
id_name_("__id__") {
|
||||
f_keys_[0] = "";
|
||||
}
|
||||
|
||||
hit_grid(const hit_grid<T>& rhs)
|
||||
:width_(rhs.width_),
|
||||
height_(rhs.height_),
|
||||
join_field_(rhs.join_field_),
|
||||
data_(rhs.data_),
|
||||
//feature_count_(0),
|
||||
step_(rhs.step_),
|
||||
id_name_("__id__") {
|
||||
f_keys_[0] = "";
|
||||
}
|
||||
|
||||
~hit_grid() {}
|
||||
|
||||
void add_feature(Feature const& feature)
|
||||
{
|
||||
|
||||
// copies feature props
|
||||
std::map<std::string,value> fprops = feature.props();
|
||||
lookup_type lookup_value;
|
||||
if (join_field_ == id_name_)
|
||||
{
|
||||
// TODO - this will break if lookup_type is not a string
|
||||
std::stringstream s;
|
||||
s << feature.id();
|
||||
lookup_value = s.str();
|
||||
// add this as a proper feature so filtering works later on
|
||||
fprops[id_name_] = feature.id();
|
||||
//fprops[id_name_] = tr_->transcode(lookup_value));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::map<std::string,value>::const_iterator const& itr = fprops.find(join_field_);
|
||||
if (itr != fprops.end())
|
||||
{
|
||||
lookup_value = itr->second.to_string();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::clog << "should not get here: join_field '" << join_field_ << "' not found in feature properties\n";
|
||||
}
|
||||
}
|
||||
|
||||
// what good is an empty lookup key?
|
||||
if (!lookup_value.empty())
|
||||
{
|
||||
// TODO - consider shortcutting f_keys if feature_id == lookup_value
|
||||
// create a mapping between the pixel id and the feature join_field
|
||||
f_keys_.insert(std::make_pair(feature.id(),lookup_value));
|
||||
// if extra fields have been supplied, push them into grid memory
|
||||
if (!names_.empty()) {
|
||||
// TODO - add ability to push WKT/WKB of geometry into grid storage
|
||||
features_.insert(std::make_pair(lookup_value,fprops));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::clog << "### Warning: join_field '" << join_field_ << "' was blank for " << feature << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void add_property_name(std::string const& name)
|
||||
{
|
||||
names_.insert(name);
|
||||
}
|
||||
|
||||
std::set<std::string> property_names() const
|
||||
{
|
||||
return names_;
|
||||
}
|
||||
|
||||
inline const feature_type& get_grid_features() const
|
||||
{
|
||||
return features_;
|
||||
}
|
||||
|
||||
inline feature_type& get_grid_features()
|
||||
{
|
||||
return features_;
|
||||
}
|
||||
|
||||
inline const feature_key_type& get_feature_keys() const
|
||||
{
|
||||
return f_keys_;
|
||||
}
|
||||
|
||||
inline feature_key_type& get_feature_keys()
|
||||
{
|
||||
return f_keys_;
|
||||
}
|
||||
|
||||
inline const std::string& get_join_field() const
|
||||
{
|
||||
return join_field_;
|
||||
}
|
||||
|
||||
inline unsigned int get_step() const
|
||||
{
|
||||
return step_;
|
||||
}
|
||||
|
||||
inline const data_type& data() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
inline data_type& data()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
inline const T* raw_data() const
|
||||
{
|
||||
return data_.getData();
|
||||
}
|
||||
|
||||
inline T* raw_data()
|
||||
{
|
||||
return data_.getData();
|
||||
}
|
||||
|
||||
// TODO - make 'views' generic
|
||||
inline image_view<data_type> get_view(unsigned x,unsigned y, unsigned w,unsigned h)
|
||||
{
|
||||
return image_view<data_type>(x,y,w,h,data_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline bool checkBounds(unsigned x, unsigned y) const
|
||||
{
|
||||
return (x < width_ && y < height_);
|
||||
}
|
||||
|
||||
hit_grid& operator=(const hit_grid&);
|
||||
|
||||
public:
|
||||
inline void setPixel(int x,int y,value_type feature_id)
|
||||
{
|
||||
if (checkBounds(x,y))
|
||||
{
|
||||
data_(x,y) = feature_id;
|
||||
}
|
||||
}
|
||||
inline unsigned width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
inline unsigned height() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
inline void set_rectangle(value_type id,image_data_32 const& data,int x0,int y0)
|
||||
{
|
||||
box2d<int> ext0(0,0,width_,height_);
|
||||
box2d<int> ext1(x0,y0,x0+data.width(),y0+data.height());
|
||||
|
||||
if (ext0.intersects(ext1))
|
||||
{
|
||||
box2d<int> box = ext0.intersect(ext1);
|
||||
for (int y = box.miny(); y < box.maxy(); ++y)
|
||||
{
|
||||
value_type* row_to = data_.getRow(y);
|
||||
unsigned int const * row_from = data.getRow(y-y0);
|
||||
|
||||
for (int x = box.minx(); x < box.maxx(); ++x)
|
||||
{
|
||||
if (row_from[x-x0] & 0xff000000)
|
||||
{
|
||||
row_to[x] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//typedef uint16_t value_type;
|
||||
//typedef unsigned char value_type;
|
||||
typedef hit_grid<uint16_t> grid;
|
||||
|
||||
}
|
||||
#endif //MAPNIK_GRID_HPP
|
170
include/mapnik/grid/grid_pixel.hpp
Normal file
170
include/mapnik/grid/grid_pixel.hpp
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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_GRID_PIXEL_HPP
|
||||
#define MAPNIK_GRID_PIXEL_HPP
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
//==================================================================gray16
|
||||
struct gray16
|
||||
{
|
||||
typedef agg::int16u value_type;
|
||||
typedef agg::int32u calc_type;
|
||||
typedef agg::int64 long_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = 16,
|
||||
base_scale = 1 << base_shift,
|
||||
base_mask = base_scale - 1
|
||||
};
|
||||
typedef gray16 self_type;
|
||||
|
||||
value_type v;
|
||||
value_type a;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16() {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(unsigned v_, unsigned a_=base_mask) :
|
||||
v(agg::int16u(v_)), a(agg::int16u(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
gray16(const self_type& c, unsigned a_) :
|
||||
v(c.v), a(value_type(a_)) {}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void clear()
|
||||
{
|
||||
v = a = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& transparent()
|
||||
{
|
||||
a = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void opacity(double a_)
|
||||
{
|
||||
if(a_ < 0.0) a_ = 0.0;
|
||||
if(a_ > 1.0) a_ = 1.0;
|
||||
a = (value_type)agg::uround(a_ * double(base_mask));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
double opacity() const
|
||||
{
|
||||
return double(a) / double(base_mask);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
v = value_type((calc_type(v) * a) >> base_shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& premultiply(unsigned a_)
|
||||
{
|
||||
if(a == base_mask && a_ >= base_mask) return *this;
|
||||
if(a == 0 || a_ == 0)
|
||||
{
|
||||
v = a = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * a_) / a;
|
||||
v = value_type((v_ > a_) ? a_ : v_);
|
||||
a = value_type(a_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
const self_type& demultiply()
|
||||
{
|
||||
if(a == base_mask) return *this;
|
||||
if(a == 0)
|
||||
{
|
||||
v = 0;
|
||||
return *this;
|
||||
}
|
||||
calc_type v_ = (calc_type(v) * base_mask) / a;
|
||||
v = value_type((v_ > base_mask) ? base_mask : v_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
self_type gradient(self_type c, double k) const
|
||||
{
|
||||
self_type ret;
|
||||
calc_type ik = agg::uround(k * base_scale);
|
||||
ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift));
|
||||
ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift));
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void add(const self_type& c, unsigned cover)
|
||||
{
|
||||
calc_type cv, ca;
|
||||
if(cover == agg::cover_mask)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*this = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cv = v + ((c.v * cover + agg::cover_mask/2) >> agg::cover_shift);
|
||||
ca = a + ((c.a * cover + agg::cover_mask/2) >> agg::cover_shift);
|
||||
v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv;
|
||||
a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
static self_type no_color() { return self_type(0,0); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
640
include/mapnik/grid/grid_pixfmt.hpp
Normal file
640
include/mapnik/grid/grid_pixfmt.hpp
Normal file
|
@ -0,0 +1,640 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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_GRID_PIXFMT_HPP
|
||||
#define MAPNIK_GRID_PIXFMT_HPP
|
||||
|
||||
#include <string.h>
|
||||
#include "agg_basics.h"
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid_rendering_buffer.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
//============================================================blender_gray
|
||||
template<class ColorT> struct blender_gray
|
||||
{
|
||||
typedef ColorT color_type;
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e { base_shift = color_type::base_shift };
|
||||
|
||||
static AGG_INLINE void blend_pix(value_type* p, unsigned cv,
|
||||
unsigned alpha, unsigned cover=0)
|
||||
{
|
||||
*p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================apply_gamma_dir_gray
|
||||
template<class ColorT, class GammaLut> class apply_gamma_dir_gray
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
*p = m_gamma.dir(*p);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=====================================================apply_gamma_inv_gray
|
||||
template<class ColorT, class GammaLut> class apply_gamma_inv_gray
|
||||
{
|
||||
public:
|
||||
typedef typename ColorT::value_type value_type;
|
||||
|
||||
apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {}
|
||||
|
||||
AGG_INLINE void operator () (value_type* p)
|
||||
{
|
||||
*p = m_gamma.inv(*p);
|
||||
}
|
||||
|
||||
private:
|
||||
const GammaLut& m_gamma;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=================================================pixfmt_alpha_blend_gray
|
||||
template<class Blender, class RenBuf, unsigned Step=1, unsigned Offset=0>
|
||||
class pixfmt_alpha_blend_gray
|
||||
{
|
||||
public:
|
||||
typedef RenBuf rbuf_type;
|
||||
typedef typename rbuf_type::row_data row_data;
|
||||
typedef Blender blender_type;
|
||||
typedef typename blender_type::color_type color_type;
|
||||
typedef int order_type; // A fake one
|
||||
typedef typename color_type::value_type value_type;
|
||||
typedef typename color_type::calc_type calc_type;
|
||||
enum base_scale_e
|
||||
{
|
||||
base_shift = color_type::base_shift,
|
||||
base_scale = color_type::base_scale,
|
||||
base_mask = color_type::base_mask,
|
||||
pix_width = sizeof(value_type),
|
||||
pix_step = Step,
|
||||
pix_offset = Offset
|
||||
};
|
||||
|
||||
private:
|
||||
//--------------------------------------------------------------------
|
||||
static AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c,
|
||||
unsigned cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static AGG_INLINE void copy_or_blend_pix(value_type* p,
|
||||
const color_type& c)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
if(c.a == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, c.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------
|
||||
explicit pixfmt_alpha_blend_gray(rbuf_type& rb) :
|
||||
m_rbuf(&rb)
|
||||
{}
|
||||
void attach(rbuf_type& rb) { m_rbuf = &rb; }
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
template<class PixFmt>
|
||||
bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
agg::rect_i r(x1, y1, x2, y2);
|
||||
if(r.clip(agg::rect_i(0, 0, pixf.width()-1, pixf.height()-1)))
|
||||
{
|
||||
int stride = pixf.stride();
|
||||
m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1),
|
||||
(r.x2 - r.x1) + 1,
|
||||
(r.y2 - r.y1) + 1,
|
||||
stride);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE unsigned width() const { return m_rbuf->width(); }
|
||||
AGG_INLINE unsigned height() const { return m_rbuf->height(); }
|
||||
AGG_INLINE int stride() const { return m_rbuf->stride(); }
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
agg::int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); }
|
||||
const agg::int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); }
|
||||
row_data row(int y) const { return m_rbuf->row(y); }
|
||||
|
||||
const agg::int8u* pix_ptr(int x, int y) const
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
}
|
||||
|
||||
agg::int8u* pix_ptr(int x, int y)
|
||||
{
|
||||
return m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE static void make_pix(agg::int8u* p, const color_type& c)
|
||||
{
|
||||
*(value_type*)p = c.v;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE color_type pixel(int x, int y) const
|
||||
{
|
||||
value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset;
|
||||
return color_type(*p);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_pixel(int x, int y, const color_type& c)
|
||||
{
|
||||
*((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void blend_pixel(int x, int y, const color_type& c, agg::int8u cover)
|
||||
{
|
||||
copy_or_blend_pix((value_type*)
|
||||
m_rbuf->row_ptr(x, y, 1) + x * Step + Offset,
|
||||
c,
|
||||
cover);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
*p = c.v;
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
AGG_INLINE void copy_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
*p = c.v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_hline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
agg::int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
*p = c.v;
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_vline(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
agg::int8u cover)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p;
|
||||
calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
*p = c.v;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
Blender::blend_pix(p, c.v, alpha, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const agg::int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, *covers);
|
||||
}
|
||||
p += Step;
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_solid_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type& c,
|
||||
const agg::int8u* covers)
|
||||
{
|
||||
if (c.a)
|
||||
{
|
||||
do
|
||||
{
|
||||
calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8;
|
||||
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
if(alpha == base_mask)
|
||||
{
|
||||
*p = c.v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Blender::blend_pix(p, c.v, alpha, *covers);
|
||||
}
|
||||
++covers;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
*p = colors->v;
|
||||
p += Step;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void copy_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors)
|
||||
{
|
||||
do
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
*p = colors->v;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_hspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const agg::int8u* covers,
|
||||
agg::int8u cover)
|
||||
{
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y, len) + x * Step + Offset;
|
||||
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
if(colors->a == base_mask)
|
||||
{
|
||||
*p = colors->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_or_blend_pix(p, *colors);
|
||||
}
|
||||
p += Step;
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void blend_color_vspan(int x, int y,
|
||||
unsigned len,
|
||||
const color_type* colors,
|
||||
const agg::int8u* covers,
|
||||
agg::int8u cover)
|
||||
{
|
||||
value_type* p;
|
||||
if(covers)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, *covers++);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(cover == 255)
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
if(colors->a == base_mask)
|
||||
{
|
||||
*p = colors->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_or_blend_pix(p, *colors);
|
||||
}
|
||||
++colors;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
p = (value_type*)
|
||||
m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset;
|
||||
|
||||
copy_or_blend_pix(p, *colors++, cover);
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class Function> void for_each_pixel(Function f)
|
||||
{
|
||||
unsigned y;
|
||||
for(y = 0; y < height(); ++y)
|
||||
{
|
||||
row_data r = m_rbuf->row(y);
|
||||
if(r.ptr)
|
||||
{
|
||||
unsigned len = r.x2 - r.x1 + 1;
|
||||
|
||||
value_type* p = (value_type*)
|
||||
m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset;
|
||||
|
||||
do
|
||||
{
|
||||
f(p);
|
||||
p += Step;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_dir(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_dir_gray<color_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class GammaLut> void apply_gamma_inv(const GammaLut& g)
|
||||
{
|
||||
for_each_pixel(apply_gamma_inv_gray<color_type, GammaLut>(g));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class RenBuf2>
|
||||
void copy_from(const RenBuf2& from,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len)
|
||||
{
|
||||
const agg::int8u* p = from.row_ptr(ysrc);
|
||||
if(p)
|
||||
{
|
||||
memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width,
|
||||
p + xsrc * pix_width,
|
||||
len * pix_width);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_color(const SrcPixelFormatRenderer& from,
|
||||
const color_type& color,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
agg::int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst,
|
||||
color,
|
||||
(*psrc * cover + base_mask) >> base_shift);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
template<class SrcPixelFormatRenderer>
|
||||
void blend_from_lut(const SrcPixelFormatRenderer& from,
|
||||
const color_type* color_lut,
|
||||
int xdst, int ydst,
|
||||
int xsrc, int ysrc,
|
||||
unsigned len,
|
||||
agg::int8u cover)
|
||||
{
|
||||
typedef typename SrcPixelFormatRenderer::value_type src_value_type;
|
||||
const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc);
|
||||
if(psrc)
|
||||
{
|
||||
value_type* pdst =
|
||||
(value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst;
|
||||
do
|
||||
{
|
||||
copy_or_blend_pix(pdst, color_lut[*psrc], cover);
|
||||
++psrc;
|
||||
++pdst;
|
||||
}
|
||||
while(--len);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
rbuf_type* m_rbuf;
|
||||
};
|
||||
|
||||
typedef blender_gray<gray16> blender_gray16;
|
||||
|
||||
typedef pixfmt_alpha_blend_gray<blender_gray16,
|
||||
mapnik::grid_rendering_buffer> pixfmt_gray16; //----pixfmt_gray16
|
||||
}
|
||||
|
||||
#endif
|
||||
|
36
include/mapnik/grid/grid_rasterizer.hpp
Normal file
36
include/mapnik/grid/grid_rasterizer.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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_GRID_RASTERIZER_HPP
|
||||
#define MAPNIK_GRID_RASTERIZER_HPP
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
struct grid_rasterizer : agg::rasterizer_scanline_aa<>, boost::noncopyable {};
|
||||
|
||||
}
|
||||
|
||||
#endif //MAPNIK_AGG_RASTERIZER_HPP
|
125
include/mapnik/grid/grid_renderer.hpp
Normal file
125
include/mapnik/grid/grid_renderer.hpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 GRID_RENDERER_HPP
|
||||
#define GRID_RENDERER_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/feature_style_processor.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
#include <mapnik/label_collision_detector.hpp>
|
||||
#include <mapnik/placement_finder.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
//#include <mapnik/marker.hpp>
|
||||
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
// FIXME
|
||||
// forward declare so that
|
||||
// apps using mapnik do not
|
||||
// need agg headers
|
||||
namespace agg {
|
||||
struct trans_affine;
|
||||
}
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
class marker;
|
||||
|
||||
struct grid_rasterizer;
|
||||
|
||||
template <typename T>
|
||||
class MAPNIK_DECL grid_renderer : public feature_style_processor<grid_renderer<T> >,
|
||||
private boost::noncopyable
|
||||
{
|
||||
|
||||
public:
|
||||
grid_renderer(Map const& m, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
|
||||
~grid_renderer();
|
||||
void start_map_processing(Map const& map);
|
||||
void end_map_processing(Map const& map);
|
||||
void start_layer_processing(layer const& lay);
|
||||
void end_layer_processing(layer const& lay);
|
||||
void render_marker(Feature const& feature, unsigned int step, const int x, const int y, marker &marker, const agg::trans_affine & tr, double opacity);
|
||||
|
||||
void process(point_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(line_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(line_pattern_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(polygon_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(polygon_pattern_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(raster_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(shield_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(text_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(building_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(markers_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(glyph_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
inline bool process(rule::symbolizers const& /*syms*/,
|
||||
Feature const& /*feature*/,
|
||||
proj_transform const& /*prj_trans*/)
|
||||
{
|
||||
// grid renderer doesn't support processing of multiple symbolizers.
|
||||
return false;
|
||||
};
|
||||
|
||||
private:
|
||||
T & pixmap_;
|
||||
unsigned width_;
|
||||
unsigned height_;
|
||||
double scale_factor_;
|
||||
CoordTransform t_;
|
||||
freetype_engine font_engine_;
|
||||
face_manager<freetype_engine> font_manager_;
|
||||
label_collision_detector4 detector_;
|
||||
boost::scoped_ptr<grid_rasterizer> ras_ptr;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //GRID_RENDERER_HPP
|
36
include/mapnik/grid/grid_rendering_buffer.hpp
Normal file
36
include/mapnik/grid/grid_rendering_buffer.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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_GRID_RENDERING_BUFFER_HPP
|
||||
#define MAPNIK_GRID_RENDERING_BUFFER_HPP
|
||||
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
#include "agg_rendering_buffer.h"
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
typedef agg::row_ptr_cache<mapnik::grid::value_type> grid_rendering_buffer;
|
||||
|
||||
}
|
||||
|
||||
#endif //MAPNIK_AGG_RASTERIZER_HPP
|
|
@ -26,6 +26,7 @@
|
|||
#include <mapnik/svg/svg_path_attributes.hpp>
|
||||
#include <mapnik/gradient.hpp>
|
||||
#include <mapnik/box2d.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
|
@ -343,6 +344,93 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Rasterizer, typename Scanline, typename Renderer>
|
||||
void render_id(Rasterizer& ras,
|
||||
Scanline& sl,
|
||||
Renderer& ren,
|
||||
int feature_id,
|
||||
agg::trans_affine const& mtx,
|
||||
double opacity,
|
||||
const box2d<double> &symbol_bbox)
|
||||
|
||||
{
|
||||
using namespace agg;
|
||||
|
||||
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(true);
|
||||
|
||||
for(unsigned i = 0; i < attributes_.size(); ++i)
|
||||
{
|
||||
mapnik::svg::path_attributes const& attr = attributes_[i];
|
||||
if (!attr.visibility_flag)
|
||||
continue;
|
||||
|
||||
transform = attr.transform;
|
||||
|
||||
double bx1,by1,bx2,by2;
|
||||
bounding_rect_single(curved_trans, attr.index, &bx1, &by1, &bx2, &by2);
|
||||
box2d<double> path_bbox(bx1,by1,bx2,by2);
|
||||
|
||||
transform *= mtx;
|
||||
double scl = transform.scale();
|
||||
//curved_.approximation_method(curve_inc);
|
||||
curved_.approximation_scale(scl);
|
||||
curved_.angle_tolerance(0.0);
|
||||
|
||||
mapnik::gray16 color(feature_id);
|
||||
|
||||
if (attr.fill_flag || attr.fill_gradient.get_gradient_type() != NO_GRADIENT)
|
||||
{
|
||||
ras.reset();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ras.filling_rule(attr.even_odd_flag ? fill_even_odd : fill_non_zero);
|
||||
renderer_solid ren_s(ren);
|
||||
ren_s.color(color);
|
||||
render_scanlines(ras, sl, ren_s);
|
||||
}
|
||||
|
||||
if (attr.stroke_flag || attr.stroke_gradient.get_gradient_type() != NO_GRADIENT)
|
||||
{
|
||||
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.add_path(curved_stroked_trans, attr.index);
|
||||
|
||||
ras.filling_rule(fill_non_zero);
|
||||
renderer_solid ren_s(ren);
|
||||
ren_s.color(color);
|
||||
render_scanlines(ras, sl, ren_s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
VertexSource & source_;
|
||||
|
|
|
@ -144,10 +144,14 @@ source = Split(
|
|||
metawriter_inmem.cpp
|
||||
metawriter_factory.cpp
|
||||
mapped_memory_cache.cpp
|
||||
marker_cache.cpp
|
||||
svg_parser.cpp
|
||||
svg_path_parser.cpp
|
||||
svg_points_parser.cpp
|
||||
svg_transform_parser.cpp
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
# add the datasource_cache.cpp with custom LIBTOOL flag if needed
|
||||
if env['LIBTOOL_SUPPORTS_ADVISE']:
|
||||
env3 = lib_env.Clone()
|
||||
|
@ -162,8 +166,8 @@ if env['JPEG']:
|
|||
jpeg_reader.cpp
|
||||
""")
|
||||
|
||||
if True : # agg backend
|
||||
source += Split(
|
||||
# agg backend
|
||||
source += Split(
|
||||
"""
|
||||
agg/agg_renderer.cpp
|
||||
agg/process_building_symbolizer.cpp
|
||||
|
@ -177,14 +181,47 @@ if True : # agg backend
|
|||
agg/process_raster_symbolizer.cpp
|
||||
agg/process_shield_symbolizer.cpp
|
||||
agg/process_markers_symbolizer.cpp
|
||||
svg_parser.cpp
|
||||
svg_path_parser.cpp
|
||||
svg_points_parser.cpp
|
||||
svg_transform_parser.cpp
|
||||
marker_cache.cpp
|
||||
"""
|
||||
)
|
||||
|
||||
# grid backend
|
||||
source += Split(
|
||||
"""
|
||||
grid/grid_renderer.cpp
|
||||
grid/process_building_symbolizer.cpp
|
||||
grid/process_glyph_symbolizer.cpp
|
||||
grid/process_line_pattern_symbolizer.cpp
|
||||
grid/process_line_symbolizer.cpp
|
||||
grid/process_markers_symbolizer.cpp
|
||||
grid/process_point_symbolizer.cpp
|
||||
grid/process_polygon_pattern_symbolizer.cpp
|
||||
grid/process_polygon_symbolizer.cpp
|
||||
grid/process_raster_symbolizer.cpp
|
||||
grid/process_shield_symbolizer.cpp
|
||||
grid/process_text_symbolizer.cpp
|
||||
""")
|
||||
|
||||
if env['SVG_RENDERER']: # svg backend
|
||||
source += Split(
|
||||
"""
|
||||
svg/svg_renderer.cpp
|
||||
svg/svg_generator.cpp
|
||||
svg/svg_output_attributes.cpp
|
||||
svg/process_symbolizers.cpp
|
||||
svg/process_building_symbolizer.cpp
|
||||
svg/process_glyph_symbolizer.cpp
|
||||
svg/process_line_pattern_symbolizer.cpp
|
||||
svg/process_line_symbolizer.cpp
|
||||
svg/process_markers_symbolizer.cpp
|
||||
svg/process_point_symbolizer.cpp
|
||||
svg/process_polygon_pattern_symbolizer.cpp
|
||||
svg/process_polygon_symbolizer.cpp
|
||||
svg/process_raster_symbolizer.cpp
|
||||
svg/process_shield_symbolizer.cpp
|
||||
svg/process_text_symbolizer.cpp
|
||||
""")
|
||||
lib_env.Append(CXXFLAGS = '-DSVG_RENDERER')
|
||||
|
||||
if env['HAS_CAIRO']:
|
||||
# attach libs to library linking environment
|
||||
try:
|
||||
|
@ -223,27 +260,6 @@ elif env['XMLPARSER'] == 'libxml2' and env['HAS_LIBXML2']:
|
|||
source.remove(cpp)
|
||||
source.insert(0,env2.SharedObject(cpp))
|
||||
|
||||
if env['SVG_RENDERER']: # svg backend
|
||||
source += Split(
|
||||
"""
|
||||
svg/svg_renderer.cpp
|
||||
svg/svg_generator.cpp
|
||||
svg/svg_output_attributes.cpp
|
||||
svg/process_symbolizers.cpp
|
||||
svg/process_building_symbolizer.cpp
|
||||
svg/process_glyph_symbolizer.cpp
|
||||
svg/process_line_pattern_symbolizer.cpp
|
||||
svg/process_line_symbolizer.cpp
|
||||
svg/process_markers_symbolizer.cpp
|
||||
svg/process_point_symbolizer.cpp
|
||||
svg/process_polygon_pattern_symbolizer.cpp
|
||||
svg/process_polygon_symbolizer.cpp
|
||||
svg/process_raster_symbolizer.cpp
|
||||
svg/process_shield_symbolizer.cpp
|
||||
svg/process_text_symbolizer.cpp
|
||||
""")
|
||||
lib_env.Append(CXXFLAGS = '-DSVG_RENDERER')
|
||||
|
||||
if env['CUSTOM_LDFLAGS']:
|
||||
linkflags = '%s %s' % (env['CUSTOM_LDFLAGS'], mapnik_lib_link_flag)
|
||||
else:
|
||||
|
@ -299,16 +315,20 @@ else:
|
|||
includes = glob.glob('../include/mapnik/*.hpp')
|
||||
svg_includes = glob.glob('../include/mapnik/svg/*.hpp')
|
||||
wkt_includes = glob.glob('../include/mapnik/wkt/*.hpp')
|
||||
grid_includes = glob.glob('../include/mapnik/grid/*.hpp')
|
||||
|
||||
inc_target = os.path.normpath(install_prefix+'/include/mapnik')
|
||||
svg_inc_target = os.path.normpath(install_prefix+'/include/mapnik/svg')
|
||||
wkt_inc_target = os.path.normpath(install_prefix+'/include/mapnik/wkt')
|
||||
grid_inc_target = os.path.normpath(install_prefix+'/include/mapnik/grid')
|
||||
|
||||
if 'uninstall' not in COMMAND_LINE_TARGETS:
|
||||
env.Alias(target='install', source=env.Install(inc_target, includes))
|
||||
env.Alias(target='install', source=env.Install(svg_inc_target, svg_includes))
|
||||
env.Alias(target='install', source=env.Install(wkt_inc_target, wkt_includes))
|
||||
env.Alias(target='install', source=env.Install(grid_inc_target, grid_includes))
|
||||
|
||||
env['create_uninstall_target'](env, inc_target)
|
||||
env['create_uninstall_target'](env, svg_inc_target)
|
||||
env['create_uninstall_target'](env, wkt_inc_target)
|
||||
env['create_uninstall_target'](env, grid_inc_target)
|
||||
|
|
162
src/grid/grid_renderer.cpp
Normal file
162
src/grid/grid_renderer.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
#include <mapnik/marker_cache.hpp>
|
||||
#include <mapnik/unicode.hpp>
|
||||
#include <mapnik/placement_finder.hpp>
|
||||
#include <mapnik/config_error.hpp>
|
||||
#include <mapnik/font_set.hpp>
|
||||
#include <mapnik/parse_path.hpp>
|
||||
#include <mapnik/text_path.hpp>
|
||||
#include <mapnik/svg/svg_converter.hpp>
|
||||
#include <mapnik/svg/svg_renderer.hpp>
|
||||
#include <mapnik/svg/svg_path_adapter.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
// stl
|
||||
#ifdef MAPNIK_DEBUG
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
//#include <cmath>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
grid_renderer<T>::grid_renderer(Map const& m, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y)
|
||||
: feature_style_processor<grid_renderer>(m, scale_factor),
|
||||
pixmap_(pixmap),
|
||||
width_(pixmap_.width()),
|
||||
height_(pixmap_.height()),
|
||||
scale_factor_(scale_factor),
|
||||
t_(pixmap_.width(),pixmap_.width(),m.get_current_extent(),offset_x,offset_y),
|
||||
font_engine_(),
|
||||
font_manager_(font_engine_),
|
||||
detector_(box2d<double>(-m.buffer_size(), -m.buffer_size(), pixmap_.width() + m.buffer_size(), pixmap_.height() + m.buffer_size())),
|
||||
ras_ptr(new grid_rasterizer)
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "scale=" << m.scale() << "\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
grid_renderer<T>::~grid_renderer() {}
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::start_map_processing(Map const& map)
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "start map processing bbox="
|
||||
<< map.get_current_extent() << "\n";
|
||||
#endif
|
||||
ras_ptr->clip_box(0,0,width_,height_);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::end_map_processing(Map const& )
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "end map processing\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::start_layer_processing(layer const& lay)
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "start layer processing : " << lay.name() << "\n";
|
||||
std::clog << "datasource = " << lay.datasource().get() << "\n";
|
||||
#endif
|
||||
if (lay.clear_label_cache())
|
||||
{
|
||||
detector_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::end_layer_processing(layer const&)
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
std::clog << "end layer processing\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::render_marker(Feature const& feature, unsigned int step, const int x, const int y, marker &marker, const agg::trans_affine & tr, double opacity)
|
||||
{
|
||||
if (marker.is_vector())
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
agg::scanline_u8 sl;
|
||||
|
||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||
mapnik::pixfmt_gray16 pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear(0.0, 0.0));
|
||||
|
||||
|
||||
box2d<double> const& bbox = (*marker.get_vector_data())->bounding_box();
|
||||
coord<double,2> c = bbox.center();
|
||||
// center the svg marker on '0,0'
|
||||
agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y);
|
||||
// apply symbol transformation to get to map space
|
||||
mtx *= tr;
|
||||
mtx *= agg::trans_affine_scaling(scale_factor_*(1.0/step));
|
||||
// render the marker at the center of the marker box
|
||||
mtx.translate(x+0.5 * marker.width(), y+0.5 * marker.height());
|
||||
|
||||
vertex_stl_adapter<svg_path_storage> stl_storage((*marker.get_vector_data())->source());
|
||||
svg_path_adapter svg_path(stl_storage);
|
||||
svg_renderer<svg_path_adapter,
|
||||
agg::pod_bvector<path_attributes>, mapnik::pixfmt_gray16 > svg_renderer(svg_path,
|
||||
(*marker.get_vector_data())->attributes());
|
||||
|
||||
svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), mtx, opacity, bbox);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
pixmap_.set_rectangle(feature.id(), **marker.get_bitmap_data(), x, y);
|
||||
}
|
||||
pixmap_.add_feature(feature);
|
||||
}
|
||||
|
||||
template class grid_renderer<grid>;
|
||||
}
|
160
src/grid/process_building_symbolizer.cpp
Normal file
160
src/grid/process_building_symbolizer.cpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
#include <mapnik/segment.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
|
||||
// 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
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(building_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
agg::scanline_u8 sl;
|
||||
|
||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||
mapnik::pixfmt_gray16 pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear(0.0, 0.0));
|
||||
|
||||
double height = sym.height() * scale_factor_;
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 2)
|
||||
{
|
||||
boost::scoped_ptr<geometry_type> frame(new geometry_type(LineString));
|
||||
boost::scoped_ptr<geometry_type> roof(new geometry_type(Polygon));
|
||||
std::deque<segment_t> face_segments;
|
||||
double x0(0);
|
||||
double y0(0);
|
||||
unsigned cm = geom.vertex(&x0,&y0);
|
||||
for (unsigned j=1;j<geom.num_points();++j)
|
||||
{
|
||||
double x(0);
|
||||
double y(0);
|
||||
cm = geom.vertex(&x,&y);
|
||||
if (cm == SEG_MOVETO)
|
||||
{
|
||||
frame->move_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<segment_t>::const_iterator itr=face_segments.begin();
|
||||
for (;itr!=face_segments.end();++itr)
|
||||
{
|
||||
boost::scoped_ptr<geometry_type> faces(new geometry_type(Polygon));
|
||||
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(mapnik::gray16(feature.id()));
|
||||
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;j<geom.num_points();++j)
|
||||
{
|
||||
double x,y;
|
||||
unsigned cm = geom.vertex(&x,&y);
|
||||
if (cm == SEG_MOVETO)
|
||||
{
|
||||
frame->move_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<path_type> stroke(path);
|
||||
ras_ptr->add_path(stroke);
|
||||
ren.color(mapnik::gray16(feature.id()));
|
||||
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(mapnik::gray16(feature.id()));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
}
|
||||
}
|
||||
pixmap_.add_feature(feature);
|
||||
}
|
||||
|
||||
template void grid_renderer<grid>::process(building_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
41
src/grid/process_glyph_symbolizer.cpp
Normal file
41
src/grid/process_glyph_symbolizer.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_renderer.hpp>
|
||||
#include <iostream>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(glyph_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
std::clog << "grid_renderer does not yet support glyph_symbolizer\n";
|
||||
}
|
||||
|
||||
template void grid_renderer<grid>::process(glyph_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
}
|
93
src/grid/process_line_pattern_symbolizer.cpp
Normal file
93
src/grid/process_line_pattern_symbolizer.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_p.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_dash.h"
|
||||
|
||||
// stl
|
||||
#include <string>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(line_pattern_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
agg::scanline_p8 sl;
|
||||
|
||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||
mapnik::pixfmt_gray16 pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear(0.0, 0.0));
|
||||
|
||||
// TODO - actually handle image dimensions
|
||||
int stroke_width = 2;
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 1)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
agg::conv_stroke<path_type> stroke(path);
|
||||
stroke.generator().miter_limit(4.0);
|
||||
stroke.generator().width(stroke_width * scale_factor_);
|
||||
ras_ptr->add_path(stroke);
|
||||
}
|
||||
}
|
||||
|
||||
// render id
|
||||
ren.color(mapnik::gray16(feature.id()));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
|
||||
// add feature properties to grid cache
|
||||
pixmap_.add_feature(feature);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template void grid_renderer<grid>::process(line_pattern_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
||||
|
153
src/grid/process_line_symbolizer.cpp
Normal file
153
src/grid/process_line_symbolizer.cpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_p.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_dash.h"
|
||||
|
||||
// stl
|
||||
#include <string>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(line_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
//agg::scanline_u8 sl;
|
||||
agg::scanline_p8 sl;
|
||||
|
||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||
mapnik::pixfmt_gray16 pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear(0.0, 0.0));
|
||||
|
||||
stroke const& stroke_ = sym.get_stroke();
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 1)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
|
||||
if (stroke_.has_dash())
|
||||
{
|
||||
agg::conv_dash<path_type> dash(path);
|
||||
dash_array const& d = stroke_.get_dash_array();
|
||||
dash_array::const_iterator itr = d.begin();
|
||||
dash_array::const_iterator end = d.end();
|
||||
for (;itr != end;++itr)
|
||||
{
|
||||
dash.add_dash(itr->first * scale_factor_,
|
||||
itr->second * scale_factor_);
|
||||
}
|
||||
|
||||
agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash);
|
||||
|
||||
line_join_e join=stroke_.get_line_join();
|
||||
if ( join == MITER_JOIN)
|
||||
stroke.generator().line_join(agg::miter_join);
|
||||
else if( join == MITER_REVERT_JOIN)
|
||||
stroke.generator().line_join(agg::miter_join);
|
||||
else if( join == ROUND_JOIN)
|
||||
stroke.generator().line_join(agg::round_join);
|
||||
else
|
||||
stroke.generator().line_join(agg::bevel_join);
|
||||
|
||||
line_cap_e cap=stroke_.get_line_cap();
|
||||
if (cap == BUTT_CAP)
|
||||
stroke.generator().line_cap(agg::butt_cap);
|
||||
else if (cap == SQUARE_CAP)
|
||||
stroke.generator().line_cap(agg::square_cap);
|
||||
else
|
||||
stroke.generator().line_cap(agg::round_cap);
|
||||
|
||||
stroke.generator().miter_limit(4.0);
|
||||
stroke.generator().width(stroke_.get_width() * scale_factor_);
|
||||
|
||||
ras_ptr->add_path(stroke);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
agg::conv_stroke<path_type> stroke(path);
|
||||
line_join_e join=stroke_.get_line_join();
|
||||
if ( join == MITER_JOIN)
|
||||
stroke.generator().line_join(agg::miter_join);
|
||||
else if( join == MITER_REVERT_JOIN)
|
||||
stroke.generator().line_join(agg::miter_join);
|
||||
else if( join == ROUND_JOIN)
|
||||
stroke.generator().line_join(agg::round_join);
|
||||
else
|
||||
stroke.generator().line_join(agg::bevel_join);
|
||||
|
||||
line_cap_e cap=stroke_.get_line_cap();
|
||||
if (cap == BUTT_CAP)
|
||||
stroke.generator().line_cap(agg::butt_cap);
|
||||
else if (cap == SQUARE_CAP)
|
||||
stroke.generator().line_cap(agg::square_cap);
|
||||
else
|
||||
stroke.generator().line_cap(agg::round_cap);
|
||||
|
||||
stroke.generator().miter_limit(4.0);
|
||||
stroke.generator().width(stroke_.get_width() * scale_factor_);
|
||||
ras_ptr->add_path(stroke);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// render id
|
||||
ren.color(mapnik::gray16(feature.id()));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
|
||||
// add feature properties to grid cache
|
||||
pixmap_.add_feature(feature);
|
||||
|
||||
}
|
||||
|
||||
|
||||
template void grid_renderer<grid>::process(line_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
||||
|
263
src/grid/process_markers_symbolizer.cpp
Normal file
263
src/grid/process_markers_symbolizer.cpp
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
#include <mapnik/marker_cache.hpp>
|
||||
#include <mapnik/svg/svg_renderer.hpp>
|
||||
#include <mapnik/svg/svg_path_adapter.hpp>
|
||||
#include <mapnik/markers_placement.hpp>
|
||||
#include <mapnik/arrow.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_u.h"
|
||||
#include "agg_scanline_p.h"
|
||||
#include "agg_path_storage.h"
|
||||
#include "agg_ellipse.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
|
||||
// stl
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(markers_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
agg::scanline_u8 sl;
|
||||
agg::scanline_p8 sl_line;
|
||||
|
||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||
mapnik::pixfmt_gray16 pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear(0.0, 0.0));
|
||||
|
||||
agg::trans_affine tr;
|
||||
boost::array<double,6> const& m = sym.get_transform();
|
||||
tr.load_from(&m[0]);
|
||||
tr = agg::trans_affine_scaling(scale_factor_*(1.0/pixmap_.get_step())) * tr;
|
||||
std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature);
|
||||
marker_placement_e placement_method = sym.get_marker_placement();
|
||||
marker_type_e marker_type = sym.get_marker_type();
|
||||
|
||||
if (!filename.empty())
|
||||
{
|
||||
boost::optional<marker_ptr> mark = mapnik::marker_cache::instance()->find(filename, true);
|
||||
if (mark && *mark && (*mark)->is_vector())
|
||||
{
|
||||
boost::optional<path_ptr> marker = (*mark)->get_vector_data();
|
||||
box2d<double> const& bbox = (*marker)->bounding_box();
|
||||
double x1 = bbox.minx();
|
||||
double y1 = bbox.miny();
|
||||
double x2 = bbox.maxx();
|
||||
double y2 = bbox.maxy();
|
||||
|
||||
agg::trans_affine recenter = agg::trans_affine_translation(-0.5*(x1+x2),-0.5*(y1+y2));
|
||||
tr.transform(&x1,&y1);
|
||||
tr.transform(&x2,&y2);
|
||||
box2d<double> extent(x1,y1,x2,y2);
|
||||
using namespace mapnik::svg;
|
||||
vertex_stl_adapter<svg_path_storage> stl_storage((*marker)->source());
|
||||
svg_path_adapter svg_path(stl_storage);
|
||||
svg_renderer<svg_path_adapter,
|
||||
agg::pod_bvector<path_attributes>, mapnik::pixfmt_gray16 > svg_renderer(svg_path,(*marker)->attributes());
|
||||
|
||||
bool placed = false;
|
||||
for (unsigned i=0; i<feature.num_geometries(); ++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() <= 1)
|
||||
{
|
||||
std::clog << "### Warning svg markers not supported yet for points within markers_symbolizer\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
path_type path(t_,geom,prj_trans);
|
||||
markers_placement<path_type, label_collision_detector4> placement(path, extent, detector_,
|
||||
sym.get_spacing() * scale_factor_,
|
||||
sym.get_max_error(),
|
||||
sym.get_allow_overlap());
|
||||
double x, y, angle;
|
||||
|
||||
while (placement.get_point(&x, &y, &angle))
|
||||
{
|
||||
placed = true;
|
||||
agg::trans_affine matrix = recenter * tr *agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x, y);
|
||||
svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), matrix, sym.get_opacity(),bbox);
|
||||
}
|
||||
}
|
||||
if (placed)
|
||||
pixmap_.add_feature(feature);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stroke const& stroke_ = sym.get_stroke();
|
||||
double strk_width = stroke_.get_width();
|
||||
|
||||
// clamp to at least 4 px otherwise interactive pixels can be too small
|
||||
double min = static_cast<double>(4/pixmap_.get_step());
|
||||
double w = std::max(sym.get_width()/pixmap_.get_step(),min);
|
||||
double h = std::max(sym.get_height()/pixmap_.get_step(),min);
|
||||
|
||||
arrow arrow_;
|
||||
box2d<double> extent;
|
||||
|
||||
double dx = w + (2*strk_width);
|
||||
double dy = h + (2*strk_width);
|
||||
|
||||
if (marker_type == ARROW)
|
||||
{
|
||||
extent = arrow_.extent();
|
||||
double x1 = extent.minx();
|
||||
double y1 = extent.miny();
|
||||
double x2 = extent.maxx();
|
||||
double y2 = extent.maxy();
|
||||
tr.transform(&x1,&y1);
|
||||
tr.transform(&x2,&y2);
|
||||
extent.init(x1,y1,x2,y2);
|
||||
}
|
||||
else
|
||||
{
|
||||
double x1 = -1 *(dx);
|
||||
double y1 = -1 *(dy);
|
||||
double x2 = dx;
|
||||
double y2 = dy;
|
||||
tr.transform(&x1,&y1);
|
||||
tr.transform(&x2,&y2);
|
||||
extent.init(x1,y1,x2,y2);
|
||||
}
|
||||
|
||||
double x;
|
||||
double y;
|
||||
double z=0;
|
||||
|
||||
for (unsigned i=0; i<feature.num_geometries(); ++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (placement_method == MARKER_POINT_PLACEMENT || geom.num_points() <= 1)
|
||||
{
|
||||
geom.label_position(&x,&y);
|
||||
prj_trans.backward(x,y,z);
|
||||
t_.forward(&x,&y);
|
||||
int px = int(floor(x - 0.5 * dx));
|
||||
int py = int(floor(y - 0.5 * dy));
|
||||
box2d<double> label_ext (px, py, px + dx +1, py + dy +1);
|
||||
|
||||
if (sym.get_allow_overlap() ||
|
||||
detector_.has_placement(label_ext))
|
||||
{
|
||||
agg::ellipse c(x, y, w, h);
|
||||
agg::path_storage marker;
|
||||
marker.concat_path(c);
|
||||
ras_ptr->add_path(marker);
|
||||
|
||||
// outline
|
||||
if (strk_width)
|
||||
{
|
||||
agg::conv_stroke<agg::path_storage> outline(marker);
|
||||
outline.generator().width(strk_width * scale_factor_);
|
||||
ras_ptr->add_path(outline);
|
||||
}
|
||||
|
||||
detector_.insert(label_ext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
agg::path_storage marker;
|
||||
if (marker_type == ARROW)
|
||||
marker.concat_path(arrow_);
|
||||
|
||||
path_type path(t_,geom,prj_trans);
|
||||
markers_placement<path_type, label_collision_detector4> placement(path, extent, detector_,
|
||||
sym.get_spacing() * scale_factor_,
|
||||
sym.get_max_error(),
|
||||
sym.get_allow_overlap());
|
||||
double x_t, y_t, angle;
|
||||
|
||||
while (placement.get_point(&x_t, &y_t, &angle))
|
||||
{
|
||||
agg::trans_affine matrix;
|
||||
|
||||
if (marker_type == ELLIPSE)
|
||||
{
|
||||
// todo proper bbox - this is buggy
|
||||
agg::ellipse c(x_t, y_t, w, h);
|
||||
marker.concat_path(c);
|
||||
agg::trans_affine matrix;
|
||||
matrix *= agg::trans_affine_translation(-x_t,-y_t);
|
||||
matrix *= agg::trans_affine_rotation(angle);
|
||||
matrix *= agg::trans_affine_translation(x_t,y_t);
|
||||
marker.transform(matrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
matrix = tr * agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x_t, y_t);
|
||||
}
|
||||
|
||||
agg::conv_transform<agg::path_storage, agg::trans_affine> trans(marker, matrix);
|
||||
|
||||
// fill
|
||||
ras_ptr->add_path(trans);
|
||||
|
||||
// outline
|
||||
if (strk_width)
|
||||
{
|
||||
agg::conv_stroke<agg::conv_transform<agg::path_storage, agg::trans_affine> > outline(trans);
|
||||
outline.generator().width(strk_width * scale_factor_);
|
||||
ras_ptr->add_path(outline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ren.color(mapnik::gray16(feature.id()));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
pixmap_.add_feature(feature);
|
||||
}
|
||||
}
|
||||
|
||||
template void grid_renderer<grid>::process(markers_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
}
|
99
src/grid/process_point_symbolizer.cpp
Normal file
99
src/grid/process_point_symbolizer.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
#include <mapnik/marker_cache.hpp>
|
||||
|
||||
// stl
|
||||
#include <string>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(point_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature);
|
||||
|
||||
boost::optional<mapnik::marker_ptr> marker;
|
||||
if ( !filename.empty() )
|
||||
{
|
||||
marker = marker_cache::instance()->find(filename, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
marker.reset(boost::shared_ptr<mapnik::marker> (new mapnik::marker()));
|
||||
}
|
||||
|
||||
if (marker)
|
||||
{
|
||||
for (unsigned i=0; i<feature.num_geometries(); ++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
double x;
|
||||
double y;
|
||||
double z=0;
|
||||
if (sym.get_point_placement() == CENTROID_POINT_PLACEMENT)
|
||||
geom.label_position(&x, &y);
|
||||
else
|
||||
geom.label_interior_position(&x, &y);
|
||||
|
||||
prj_trans.backward(x,y,z);
|
||||
t_.forward(&x,&y);
|
||||
|
||||
int w = (*marker)->width();
|
||||
int h = (*marker)->height();
|
||||
|
||||
int px = int(floor(x - 0.5 * w));
|
||||
int py = int(floor(y - 0.5 * h));
|
||||
box2d<double> label_ext (px, py, px + w, py + h);
|
||||
if (sym.get_allow_overlap() ||
|
||||
detector_.has_placement(label_ext))
|
||||
{
|
||||
agg::trans_affine tr;
|
||||
boost::array<double,6> const& m = sym.get_transform();
|
||||
tr.load_from(&m[0]);
|
||||
|
||||
render_marker(feature,pixmap_.get_step(),px,py,**marker,tr, sym.get_opacity());
|
||||
|
||||
if (!sym.get_ignore_placement())
|
||||
detector_.insert(label_ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template void grid_renderer<grid>::process(point_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
||||
|
84
src/grid/process_polygon_pattern_symbolizer.cpp
Normal file
84
src/grid/process_polygon_pattern_symbolizer.cpp
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_u.h"
|
||||
|
||||
// stl
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(polygon_pattern_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
agg::scanline_u8 sl;
|
||||
|
||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||
mapnik::pixfmt_gray16 pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear(0.0, 0.0));
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 2)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
ras_ptr->add_path(path);
|
||||
}
|
||||
}
|
||||
|
||||
// render id
|
||||
ren.color(mapnik::gray16(feature.id()));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
|
||||
// add feature properties to grid cache
|
||||
pixmap_.add_feature(feature);
|
||||
}
|
||||
|
||||
|
||||
template void grid_renderer<grid>::process(polygon_pattern_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
||||
|
87
src/grid/process_polygon_symbolizer.cpp
Normal file
87
src/grid/process_polygon_symbolizer.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_u.h"
|
||||
|
||||
// stl
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(polygon_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base;
|
||||
typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
|
||||
agg::scanline_u8 sl;
|
||||
|
||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||
mapnik::pixfmt_gray16 pixf(buf);
|
||||
|
||||
ren_base renb(pixf);
|
||||
renderer ren(renb);
|
||||
|
||||
ras_ptr->reset();
|
||||
ras_ptr->gamma(agg::gamma_linear(0.0, 0.0));
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 2)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
ras_ptr->add_path(path);
|
||||
}
|
||||
}
|
||||
|
||||
// render id
|
||||
ren.color(mapnik::gray16(feature.id()));
|
||||
agg::render_scanlines(*ras_ptr, sl, ren);
|
||||
|
||||
// add feature properties to grid cache
|
||||
pixmap_.add_feature(feature);
|
||||
|
||||
// increment feature count
|
||||
//++pixmap_.feature_count_;
|
||||
}
|
||||
|
||||
|
||||
template void grid_renderer<grid>::process(polygon_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
||||
|
42
src/grid/process_raster_symbolizer.cpp
Normal file
42
src/grid/process_raster_symbolizer.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_renderer.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(raster_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
std::clog << "grid_renderer does not yet support raster_symbolizer\n";
|
||||
}
|
||||
|
||||
template void grid_renderer<grid>::process(raster_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
251
src/grid/process_shield_symbolizer.cpp
Normal file
251
src/grid/process_shield_symbolizer.cpp
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_rasterizer.hpp>
|
||||
#include <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/grid/grid_pixfmt.hpp>
|
||||
#include <mapnik/grid/grid_pixel.hpp>
|
||||
#include <mapnik/grid/grid.hpp>
|
||||
|
||||
#include <mapnik/marker_cache.hpp>
|
||||
#include <mapnik/svg/svg_converter.hpp>
|
||||
#include <mapnik/svg/svg_renderer.hpp>
|
||||
#include <mapnik/svg/svg_path_adapter.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_scanline_u.h"
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(shield_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
|
||||
bool placement_found = false;
|
||||
|
||||
text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info();
|
||||
placement_options->next();
|
||||
placement_options->next_position_only();
|
||||
|
||||
UnicodeString text;
|
||||
if( sym.get_no_text() )
|
||||
text = UnicodeString( " " ); // TODO: fix->use 'space' as the text to render
|
||||
else
|
||||
{
|
||||
expression_ptr name_expr = sym.get_name();
|
||||
if (!name_expr) return;
|
||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*name_expr);
|
||||
text = result.to_unicode();
|
||||
}
|
||||
|
||||
if ( sym.get_text_transform() == UPPERCASE)
|
||||
{
|
||||
text = text.toUpper();
|
||||
}
|
||||
else if ( sym.get_text_transform() == LOWERCASE)
|
||||
{
|
||||
text = text.toLower();
|
||||
}
|
||||
else if ( sym.get_text_transform() == CAPITALIZE)
|
||||
{
|
||||
text = text.toTitle(NULL);
|
||||
}
|
||||
|
||||
agg::trans_affine tr;
|
||||
boost::array<double,6> const& m = sym.get_transform();
|
||||
tr.load_from(&m[0]);
|
||||
tr = agg::trans_affine_scaling(scale_factor_) * tr;
|
||||
|
||||
std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature);
|
||||
boost::optional<mapnik::marker_ptr> marker;
|
||||
if ( !filename.empty() )
|
||||
{
|
||||
marker = marker_cache::instance()->find(filename, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
marker.reset(boost::shared_ptr<mapnik::marker> (new mapnik::marker()));
|
||||
}
|
||||
|
||||
if (text.length() > 0 && marker)
|
||||
{
|
||||
face_set_ptr faces;
|
||||
|
||||
if (sym.get_fontset().size() > 0)
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_fontset());
|
||||
}
|
||||
else
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_face_name());
|
||||
}
|
||||
|
||||
stroker_ptr strk = font_manager_.get_stroker();
|
||||
if (strk && faces->size() > 0)
|
||||
{
|
||||
text_renderer<T> ren(pixmap_, faces, *strk);
|
||||
|
||||
ren.set_pixel_size(sym.get_text_size() * scale_factor_ * (1.0/pixmap_.get_step()));
|
||||
ren.set_fill(sym.get_fill());
|
||||
ren.set_halo_fill(sym.get_halo_fill());
|
||||
ren.set_halo_radius(sym.get_halo_radius() * scale_factor_);
|
||||
ren.set_opacity(sym.get_text_opacity());
|
||||
|
||||
placement_finder<label_collision_detector4> finder(detector_);
|
||||
|
||||
string_info info(text);
|
||||
|
||||
faces->get_string_info(info);
|
||||
|
||||
// TODO- clamp to at least 4 px otherwise interactivity is too small
|
||||
int w = (*marker)->width()/pixmap_.get_step();
|
||||
int h = (*marker)->height()/pixmap_.get_step();
|
||||
|
||||
for (unsigned i = 0; i < feature.num_geometries(); ++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 0 )
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
|
||||
label_placement_enum how_placed = sym.get_label_placement();
|
||||
if (how_placed == POINT_PLACEMENT || how_placed == VERTEX_PLACEMENT || how_placed == INTERIOR_PLACEMENT)
|
||||
{
|
||||
// for every vertex, try and place a shield/text
|
||||
geom.rewind(0);
|
||||
placement text_placement(info, sym, placement_options, scale_factor_, w, h, false);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
text_placement.allow_overlap = sym.get_allow_overlap();
|
||||
position const& pos = sym.get_displacement();
|
||||
position const& shield_pos = sym.get_shield_displacement();
|
||||
for( unsigned jj = 0; jj < geom.num_points(); jj++ )
|
||||
{
|
||||
double label_x;
|
||||
double label_y;
|
||||
double z=0.0;
|
||||
|
||||
if( how_placed == VERTEX_PLACEMENT )
|
||||
geom.vertex(&label_x,&label_y); // by vertex
|
||||
else if( how_placed == INTERIOR_PLACEMENT )
|
||||
geom.label_interior_position(&label_x,&label_y);
|
||||
else
|
||||
geom.label_position(&label_x, &label_y); // by middle of line or by point
|
||||
prj_trans.backward(label_x,label_y, z);
|
||||
t_.forward(&label_x,&label_y);
|
||||
|
||||
label_x += boost::get<0>(shield_pos);
|
||||
label_y += boost::get<1>(shield_pos);
|
||||
|
||||
finder.find_point_placement( text_placement,label_x,label_y,0.0,
|
||||
sym.get_vertical_alignment(),
|
||||
sym.get_line_spacing(),
|
||||
sym.get_character_spacing(),
|
||||
sym.get_horizontal_alignment(),
|
||||
sym.get_justify_alignment() );
|
||||
|
||||
// check to see if image overlaps anything too, there is only ever 1 placement found for points and verticies
|
||||
if( text_placement.placements.size() > 0)
|
||||
{
|
||||
placement_found = true;
|
||||
double x = floor(text_placement.placements[0].starting_x);
|
||||
double y = floor(text_placement.placements[0].starting_y);
|
||||
int px;
|
||||
int py;
|
||||
box2d<double> label_ext;
|
||||
|
||||
if( !sym.get_unlock_image() )
|
||||
{
|
||||
// center image at text center position
|
||||
// remove displacement from image label
|
||||
double lx = x - boost::get<0>(pos);
|
||||
double ly = y - boost::get<1>(pos);
|
||||
px=int(floor(lx - (0.5 * w)));
|
||||
py=int(floor(ly - (0.5 * h)));
|
||||
label_ext.init( floor(lx - 0.5 * w), floor(ly - 0.5 * h), ceil (lx + 0.5 * w), ceil (ly + 0.5 * h) );
|
||||
}
|
||||
else
|
||||
{ // center image at reference location
|
||||
px=int(floor(label_x - 0.5 * w));
|
||||
py=int(floor(label_y - 0.5 * h));
|
||||
label_ext.init( floor(label_x - 0.5 * w), floor(label_y - 0.5 * h), ceil (label_x + 0.5 * w), ceil (label_y + 0.5 * h));
|
||||
}
|
||||
|
||||
if ( sym.get_allow_overlap() || detector_.has_placement(label_ext) )
|
||||
{
|
||||
render_marker(feature,pixmap_.get_step(),px,py,**marker,tr,sym.get_opacity());
|
||||
|
||||
box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[0]);
|
||||
ren.render_id(feature.id(),x,y,2);
|
||||
detector_.insert(label_ext);
|
||||
finder.update_detector(text_placement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (geom.num_points() > 1 && how_placed == LINE_PLACEMENT)
|
||||
{
|
||||
placement text_placement(info, sym, placement_options, scale_factor_, w, h, true);
|
||||
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
finder.find_point_placements<path_type>(text_placement,path);
|
||||
|
||||
position const& pos = sym.get_displacement();
|
||||
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii)
|
||||
{
|
||||
placement_found= true;
|
||||
double x = floor(text_placement.placements[ii].starting_x);
|
||||
double y = floor(text_placement.placements[ii].starting_y);
|
||||
|
||||
double lx = x - boost::get<0>(pos);
|
||||
double ly = y - boost::get<1>(pos);
|
||||
int px=int(floor(lx - (0.5*w)));
|
||||
int py=int(floor(ly - (0.5*h)));
|
||||
|
||||
render_marker(feature,pixmap_.get_step(),px,py,**marker,tr,sym.get_opacity());
|
||||
|
||||
box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
|
||||
ren.render_id(feature.id(),x,y,2);
|
||||
}
|
||||
finder.update_detector(text_placement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (placement_found)
|
||||
pixmap_.add_feature(feature);
|
||||
|
||||
}
|
||||
|
||||
template void grid_renderer<grid>::process(shield_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
156
src/grid/process_text_symbolizer.cpp
Normal file
156
src/grid/process_text_symbolizer.cpp
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 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 <mapnik/grid/grid_renderer.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename T>
|
||||
void grid_renderer<T>::process(text_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
|
||||
bool placement_found = false;
|
||||
text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info();
|
||||
while (!placement_found && placement_options->next())
|
||||
{
|
||||
expression_ptr name_expr = sym.get_name();
|
||||
if (!name_expr) return;
|
||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*name_expr);
|
||||
UnicodeString text = result.to_unicode();
|
||||
|
||||
if ( sym.get_text_transform() == UPPERCASE)
|
||||
{
|
||||
text = text.toUpper();
|
||||
}
|
||||
else if ( sym.get_text_transform() == LOWERCASE)
|
||||
{
|
||||
text = text.toLower();
|
||||
}
|
||||
else if ( sym.get_text_transform() == CAPITALIZE)
|
||||
{
|
||||
text = text.toTitle(NULL);
|
||||
}
|
||||
|
||||
if ( text.length() <= 0 ) continue;
|
||||
color const& fill = sym.get_fill();
|
||||
|
||||
face_set_ptr faces;
|
||||
|
||||
if (sym.get_fontset().size() > 0)
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_fontset());
|
||||
}
|
||||
else
|
||||
{
|
||||
faces = font_manager_.get_face_set(sym.get_face_name());
|
||||
}
|
||||
|
||||
stroker_ptr strk = font_manager_.get_stroker();
|
||||
if (!(faces->size() > 0 && strk))
|
||||
{
|
||||
throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'");
|
||||
}
|
||||
text_renderer<T> ren(pixmap_, faces, *strk);
|
||||
ren.set_pixel_size(placement_options->text_size * (scale_factor_ * (1.0/pixmap_.get_step())));
|
||||
ren.set_fill(fill);
|
||||
ren.set_halo_fill(sym.get_halo_fill());
|
||||
ren.set_halo_radius(sym.get_halo_radius() * scale_factor_);
|
||||
ren.set_opacity(sym.get_text_opacity());
|
||||
|
||||
// /pixmap_.get_step() ?
|
||||
box2d<double> dims(0,0,width_,height_);
|
||||
placement_finder<label_collision_detector4> finder(detector_,dims);
|
||||
|
||||
string_info info(text);
|
||||
|
||||
faces->get_string_info(info);
|
||||
unsigned num_geom = feature.num_geometries();
|
||||
for (unsigned i=0; i<num_geom; ++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() == 0) continue; // don't bother with empty geometries
|
||||
while (!placement_found && placement_options->next_position_only())
|
||||
{
|
||||
placement text_placement(info, sym, placement_options, scale_factor_);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT ||
|
||||
sym.get_label_placement() == INTERIOR_PLACEMENT)
|
||||
{
|
||||
double label_x, label_y, z=0.0;
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT)
|
||||
geom.label_position(&label_x, &label_y);
|
||||
else
|
||||
geom.label_interior_position(&label_x, &label_y);
|
||||
prj_trans.backward(label_x,label_y, z);
|
||||
t_.forward(&label_x,&label_y);
|
||||
|
||||
double angle = 0.0;
|
||||
expression_ptr angle_expr = sym.get_orientation();
|
||||
if (angle_expr)
|
||||
{
|
||||
// apply rotation
|
||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*angle_expr);
|
||||
angle = result.to_double();
|
||||
}
|
||||
|
||||
finder.find_point_placement(text_placement,label_x,label_y,
|
||||
angle, sym.get_vertical_alignment(),sym.get_line_spacing(),
|
||||
sym.get_character_spacing(),sym.get_horizontal_alignment(),
|
||||
sym.get_justify_alignment());
|
||||
|
||||
finder.update_detector(text_placement);
|
||||
}
|
||||
else if ( geom.num_points() > 1 && sym.get_label_placement() == LINE_PLACEMENT)
|
||||
{
|
||||
path_type path(t_,geom,prj_trans);
|
||||
finder.find_line_placements<path_type>(text_placement,path);
|
||||
}
|
||||
|
||||
if (!text_placement.placements.size()) continue;
|
||||
placement_found = true;
|
||||
|
||||
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;
|
||||
ren.prepare_glyphs(&text_placement.placements[ii]);
|
||||
ren.render_id(feature.id(),x,y,2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (placement_found)
|
||||
pixmap_.add_feature(feature);
|
||||
}
|
||||
|
||||
template void grid_renderer<grid>::process(text_symbolizer const&,
|
||||
Feature const&,
|
||||
proj_transform const&);
|
||||
|
||||
}
|
||||
|
Loading…
Reference in a new issue