1.python bindings updated to reflect symbolizers changes

2.added label collision detector ( TODO - proper impl!)
This commit is contained in:
Artem Pavlenko 2006-02-25 11:03:30 +00:00
parent 1728bdbc7e
commit 9de253198b
21 changed files with 482 additions and 91 deletions

View file

@ -29,7 +29,7 @@ from _mapnik import *
from paths import inputpluginspath
# The base Boost.Python class
BoostPythonMetaclass = coord.__class__
BoostPythonMetaclass = Coord.__class__
class _injector(object):
class __metaclass__(BoostPythonMetaclass):
@ -40,23 +40,23 @@ class _injector(object):
setattr(b,k,v)
return type.__init__(self, name, bases, dict)
class _coord(coord,_injector):
class _Coord(Coord,_injector):
def __repr__(self):
return 'coord(%s,%s)' % (self.x, self.y)
return 'Coord(%s,%s)' % (self.x, self.y)
class _envelope(envelope,_injector):
class _Envelope(Envelope,_injector):
def __repr__(self):
return 'envelope(%s,%s,%s,%s)' % \
return 'Envelope(%s,%s,%s,%s)' % \
(self.minx,self.miny,self.maxx,self.maxy)
class _color(color,_injector):
class _Color(Color,_injector):
def __repr__(self):
return 'color(%s,%s,%s,%s)' % \
return 'Color(%s,%s,%s,%s)' % \
(self.r,self.g,self.b,self.a)
#register datasources
from mapnik import datasource_cache
datasource_cache.instance().register_datasources('%s' % inputpluginspath)
from mapnik import DatasourceCache
DatasourceCache.instance().register_datasources('%s' % inputpluginspath)
#set dlopen flags back to the original
setdlopenflags(flags)

View file

@ -103,7 +103,7 @@ void export_layer()
class_<std::vector<std::string> >("Styles")
.def(vector_indexing_suite<std::vector<std::string>,true >())
;
//class_<Layer>("layer",init<const Parameters&>("Layer constructor"))
class_<Layer>("Layer",no_init)
.def("name",&Layer::name,return_value_policy<copy_const_reference>())
.def("params",&Layer::params,return_value_policy<reference_existing_object>())

View file

@ -0,0 +1,34 @@
/* This file is part of python_mapnik (c++/python mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#include <boost/python.hpp>
#include <mapnik.hpp>
using mapnik::line_pattern_symbolizer;
void export_line_pattern_symbolizer()
{
using namespace boost::python;
class_<line_pattern_symbolizer>("LinePatternSymbolizer",
init<std::string const&,
std::string const&,unsigned,unsigned>("TODO"))
;
}

View file

@ -0,0 +1,38 @@
/* This file is part of python_mapnik (c++/python mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#include <boost/python.hpp>
#include <mapnik.hpp>
using mapnik::line_symbolizer;
using mapnik::stroke;
using mapnik::Color;
void export_line_symbolizer()
{
using namespace boost::python;
class_<line_symbolizer>("LineSymbolizer",init<stroke const&>("TODO"))
.def(init<Color const& ,float>())
.add_property("stroke",make_function
(&line_symbolizer::get_stroke,return_value_policy<reference_existing_object>()),
&line_symbolizer::set_stroke)
;
}

View file

@ -0,0 +1,34 @@
/* This file is part of python_mapnik (c++/python mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#include <boost/python.hpp>
#include <mapnik.hpp>
using mapnik::point_symbolizer;
void export_point_symbolizer()
{
using namespace boost::python;
class_<point_symbolizer>("PointSymbolizer",init<std::string const&,
std::string const&,unsigned,unsigned>("TODO"))
;
}

View file

@ -0,0 +1,35 @@
/* This file is part of python_mapnik (c++/python mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#include <boost/python.hpp>
#include <mapnik.hpp>
using mapnik::polygon_pattern_symbolizer;
void export_polygon_pattern_symbolizer()
{
using namespace boost::python;
class_<polygon_pattern_symbolizer>("PolygonPatternSymbolizer",
init<std::string const&,
std::string const&,
unsigned,unsigned>("TODO"))
;
}

View file

@ -0,0 +1,39 @@
/* This file is part of python_mapnik (c++/python mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#include <boost/python.hpp>
#include <mapnik.hpp>
using mapnik::polygon_symbolizer;
using mapnik::Color;
void export_polygon_symbolizer()
{
using namespace boost::python;
class_<polygon_symbolizer>("PolygonSymbolizer",
init<Color const&>("TODO"))
.add_property("fill",make_function
(&polygon_symbolizer::get_fill,
return_value_policy<reference_existing_object>()),
&polygon_symbolizer::set_fill)
;
}

View file

@ -38,50 +38,28 @@ void export_rule();
void export_style();
void export_stroke();
void export_datasource_cache();
void export_point_symbolizer();
void export_line_symbolizer();
void export_line_pattern_symbolizer();
void export_polygon_symbolizer();
void export_polygon_pattern_symbolizer();
void export_raster_symbolizer();
void export_text_symbolizer();
void render_to_file(const Map& map,const std::string& file,const std::string& format)
{
Image32 image(map.getWidth(),map.getHeight());
Renderer<Image32>::render(map,image);
agg_renderer<Image32> ren(map,image);
ren.apply();
image.saveToFile(file,format);
}
void render(const Map& map,Image32& image)
{
Renderer<Image32>::render(map,image);
agg_renderer<Image32> ren(map,image);
ren.apply();
}
boost::shared_ptr<symbolizer> create_point_symbolizer(std::string const& file,unsigned w,unsigned h)
{
return boost::shared_ptr<symbolizer>(new image_symbolizer(file,"png",w,h));
}
boost::shared_ptr<symbolizer> create_line_symbolizer(const Color& pen,float width)
{
return boost::shared_ptr<symbolizer>(new line_symbolizer(pen,width));
}
boost::shared_ptr<symbolizer> create_line_symbolizer2(stroke const& strk)
{
return boost::shared_ptr<symbolizer>(new line_symbolizer(strk));
}
boost::shared_ptr<symbolizer> create_line_symbolizer3(std::string const& file,unsigned w,unsigned h)
{
return boost::shared_ptr<symbolizer>(new line_pattern_symbolizer(file,"png",w,h));
}
boost::shared_ptr<symbolizer> create_polygon_symbolizer(const Color& fill)
{
return boost::shared_ptr<symbolizer>(new polygon_symbolizer(fill));
}
boost::shared_ptr<symbolizer> create_polygon_symbolizer2(std::string const& file,unsigned w,unsigned h)
{
return boost::shared_ptr<symbolizer>(new polygon_pattern_symbolizer(file,"png",w,h));
}
BOOST_PYTHON_MODULE(_mapnik)
{
using namespace boost::python;
@ -91,12 +69,7 @@ BOOST_PYTHON_MODULE(_mapnik)
.def("envelope",&datasource::envelope,
return_value_policy<reference_existing_object>())
;
class_<symbolizer,boost::noncopyable> ("Symbolizer_",no_init)
;
class_<boost::shared_ptr<symbolizer>,
boost::noncopyable>("Symbolizer",no_init)
;
export_parameters();
export_color();
export_envelope();
@ -107,8 +80,14 @@ BOOST_PYTHON_MODULE(_mapnik)
export_layer();
export_stroke();
export_datasource_cache();
export_point_symbolizer();
export_line_symbolizer();
export_line_pattern_symbolizer();
export_polygon_symbolizer();
export_polygon_pattern_symbolizer();
export_raster_symbolizer();
export_text_symbolizer();
class_<coord<double,2> >("Coord",init<double,double>())
.def_readwrite("x", &coord<double,2>::x)
.def_readwrite("y", &coord<double,2>::y)
@ -118,12 +97,5 @@ BOOST_PYTHON_MODULE(_mapnik)
def("render_to_file",&render_to_file);
def("render",&render);
def("point_symbolizer",&create_point_symbolizer);
def("line_symbolizer",&create_line_symbolizer);
def("line_symbolizer",&create_line_symbolizer2);
def("line_symbolizer",&create_line_symbolizer3);
def("polygon_symbolizer",&create_polygon_symbolizer);
def("polygon_symbolizer",&create_polygon_symbolizer2);
register_ptr_to_python<boost::shared_ptr<symbolizer> >();
register_ptr_to_python<filter_ptr>();
}

View file

@ -0,0 +1,33 @@
/* This file is part of python_mapnik (c++/python mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#include <boost/python.hpp>
#include <mapnik.hpp>
using mapnik::raster_symbolizer;
void export_raster_symbolizer()
{
using namespace boost::python;
class_<raster_symbolizer>("RasterSymbolizer",
init<>("TODO"))
;
}

View file

@ -20,6 +20,7 @@
#include <boost/python.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <mapnik.hpp>
@ -27,17 +28,34 @@ using mapnik::rule_type;
using mapnik::filter;
using mapnik::filter_ptr;
using mapnik::Feature;
using mapnik::point_symbolizer;
using mapnik::line_symbolizer;
using mapnik::line_pattern_symbolizer;
using mapnik::polygon_symbolizer;
using mapnik::polygon_pattern_symbolizer;
using mapnik::raster_symbolizer;
using mapnik::text_symbolizer;
using mapnik::symbolizer;
using mapnik::symbolizers;
void export_rule()
{
using namespace boost::python;
implicitly_convertible<point_symbolizer,symbolizer>();
implicitly_convertible<line_symbolizer,symbolizer>();
implicitly_convertible<line_pattern_symbolizer,symbolizer>();
implicitly_convertible<polygon_symbolizer,symbolizer>();
implicitly_convertible<polygon_pattern_symbolizer,symbolizer>();
implicitly_convertible<raster_symbolizer,symbolizer>();
implicitly_convertible<text_symbolizer,symbolizer>();
class_<symbolizers>("Symbolizers",init<>("TODO"))
.def(vector_indexing_suite<symbolizers>())
;
.def(vector_indexing_suite<symbolizers>())
;
class_<rule_type>("Rule",init<>("default ctor"))
class_<rule_type>("Rule",init<>("default constructor"))
.def(init<std::string const&,
boost::python::optional<std::string const&,double,double> >())
.add_property("name",make_function

View file

@ -0,0 +1,34 @@
/* This file is part of python_mapnik (c++/python mapping toolkit)
* Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#include <boost/python.hpp>
#include <mapnik.hpp>
using mapnik::text_symbolizer;
using mapnik::Color;
void export_text_symbolizer()
{
using namespace boost::python;
class_<text_symbolizer>("TextSymbolizer",
init<std::string const&,Color const&>("TODO"))
;
}

View file

@ -24,6 +24,7 @@
#include "feature_style_processor.hpp"
#include <boost/utility.hpp>
#include "font_engine_freetype.hpp"
#include "label_collision_detector.hpp"
namespace mapnik
{
@ -32,8 +33,8 @@ namespace mapnik
private boost::noncopyable
{
agg_renderer(Map const& m, T & pixmap);
void start_map_processing();
void end_map_processing();
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 process(point_symbolizer const& sym,Feature const& feature);
@ -47,6 +48,7 @@ namespace mapnik
T & pixmap_;
CoordTransform t_;
face_manager<freetype_engine> font_manager_;
label_collision_detector detector_;
};
}

View file

@ -60,7 +60,7 @@ namespace mapnik
timer clock;
Processor & p = static_cast<Processor&>(*this);
p.start_map_processing();
p.start_map_processing(m_);
std::vector<Layer>::const_iterator itr = m_.layers().begin();
while (itr != m_.layers().end())
@ -73,7 +73,7 @@ namespace mapnik
++itr;
}
p.end_map_processing();
p.end_map_processing(m_);
clock.stop();

View file

@ -219,7 +219,57 @@ namespace mapnik
private:
faces faces_;
};
inline std::wstring to_unicode(std::string const& text)
{
std::wstring out;
unsigned long code = 0;
int expect = 0;
std::string::const_iterator itr=text.begin();
while ( itr != text.end())
{
unsigned p = (*itr++) & 0xff;
if ( p >= 0xc0)
{
if ( p < 0xe0) // U+0080 - U+07ff
{
expect = 1;
code = p & 0x1f;
}
else if ( p < 0xf0) // U+0800 - U+ffff
{
expect = 2;
code = p & 0x0f;
}
else if ( p < 0xf8) // U+1000 - U+10ffff
{
expect = 3;
code = p & 0x07;
}
continue;
}
else if (p >= 0x80)
{
--expect;
if (expect >= 0)
{
code <<= 6;
code += p & 0x3f;
}
if (expect > 0)
continue;
expect = 0;
}
else
{
code = p; // U+0000 - U+007f (ascii)
}
out.push_back(code);
}
return out;
}
template <typename T>
struct text_renderer : private boost::noncopyable
{
@ -270,7 +320,7 @@ namespace mapnik
FT_GlyphSlot slot = face->glyph;
FT_UInt glyph_index;
FT_Bool use_kerning;
FT_UInt previous;
FT_UInt previous = 0;
unsigned height = pixmap_.height();
@ -280,12 +330,10 @@ namespace mapnik
pen.y = unsigned((height - y0) * 64);
use_kerning = FT_HAS_KERNING(face);
//unsigned count=1;
for (std::string::const_iterator i=text.begin();i!=text.end();++i)
std::string::const_iterator i;
for (i=text.begin();i!=text.end();++i)
{
matrix.xx = (FT_Fixed)( cos( angle_ ) * 0x10000L );
matrix.xy = (FT_Fixed)(-sin( angle_ ) * 0x10000L );
matrix.yx = (FT_Fixed)( sin( angle_ ) * 0x10000L );
@ -293,7 +341,7 @@ namespace mapnik
FT_Set_Transform (face,&matrix,&pen);
glyph_index = FT_Get_Char_Index( face, *i );
glyph_index = FT_Get_Char_Index( face, unsigned(*i) & 0xff );
if ( use_kerning && previous && glyph_index)
{
FT_Vector delta;
@ -301,7 +349,6 @@ namespace mapnik
FT_KERNING_DEFAULT,&delta);
pen.x += delta.x;
pen.y += delta.y;
std::cout<< "use kerning "<< std::endl;
}
error = FT_Load_Glyph (face,glyph_index,FT_LOAD_DEFAULT);
@ -337,8 +384,8 @@ namespace mapnik
previous = glyph_index;
//angle_ = sin ( 0.1 * count++);
}
std::cout << std::endl;
}
private:

View file

@ -0,0 +1,56 @@
/* This file is part of Mapnik (c++ mapping toolkit)
* Copyright (C) 2006 Artem Pavlenko
*
* Mapnik is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//$Id$
#if !defined LABEL_COLLISION_DETECTOR
#define LABEL_COLLISION_DETECTOR
#include "envelope.hpp"
#include <vector>
namespace mapnik
{
//this needs to be tree structure
//as a proof of a concept _only_ we use sequential scan
struct label_collision_detector
{
typedef std::vector<Envelope<double> > label_placements;
bool allowed_to_render(Envelope<double> const& box)
{
label_placements::const_iterator itr=labels_.begin();
for( ; itr !=labels_.end();++itr)
{
if (itr->intersects(box))
{
return false;
}
}
labels_.push_back(box);
return true;
}
private:
label_placements labels_;
};
}
#endif

View file

@ -38,6 +38,11 @@ namespace mapnik
{
return stroke_;
}
void set_stroke(stroke const& stroke)
{
stroke_ = stroke;
}
private:
stroke stroke_;
};

View file

@ -27,8 +27,7 @@
namespace mapnik
{
struct point_symbolizer
{
{
point_symbolizer(std::string const& file,
std::string const& type,
unsigned width,unsigned height);

View file

@ -34,6 +34,10 @@ namespace mapnik
{
return fill_;
}
void set_fill(Color const& fill)
{
fill_ = fill;
}
private:
Color fill_;
};

View file

@ -28,7 +28,6 @@
#include "text_symbolizer.hpp"
#include "filter.hpp"
#include "filter_visitor.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/variant.hpp>
#include <string>
@ -36,6 +35,45 @@
namespace mapnik
{
inline bool operator==(point_symbolizer const& lhs,
point_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(line_symbolizer const& lhs,
line_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(line_pattern_symbolizer const& lhs,
line_pattern_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(polygon_symbolizer const& lhs,
polygon_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(polygon_pattern_symbolizer const& lhs,
polygon_pattern_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(raster_symbolizer const& lhs,
raster_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(text_symbolizer const& lhs,
text_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
typedef boost::variant<point_symbolizer,
line_symbolizer,
@ -45,6 +83,7 @@ namespace mapnik
raster_symbolizer,
text_symbolizer> symbolizer;
typedef std::vector<symbolizer> symbolizers;
template <typename FeatureT> class all_filter;

View file

@ -21,10 +21,6 @@
#ifndef TEXT_SYMBOLIZER_HPP
#define TEXT_SYMBOLIZER_HPP
//#include "symbolizer.hpp"
//#include "fill.hpp"
//#include "expression.hpp"
namespace mapnik
{
enum label_placement_e {

View file

@ -90,13 +90,13 @@ namespace mapnik
}
template <typename T>
void agg_renderer<T>::start_map_processing()
void agg_renderer<T>::start_map_processing(Map const& map)
{
std::cout << "start map processing" << std::endl;
std::cout << "start map processing bbox=" << map.getCurrentExtent() << std::endl;
}
template <typename T>
void agg_renderer<T>::end_map_processing()
void agg_renderer<T>::end_map_processing(Map const& )
{
std::cout << "end map processing" << std::endl;
}
@ -275,10 +275,16 @@ namespace mapnik
t_.forward_x(&x);
t_.forward_y(&y);
int w=data.width();
int h=data.height();
int px=int(ceil(x - 0.5 * w));
int py=int(ceil(y - 0.5 * h));
pixmap_.set_rectangle_alpha(px,py,data);
int h=data.height();
if (detector_.allowed_to_render(Envelope<double>(x - 0.5 * w,
y - 0.5 * h,
x + 0.5 * w,
y + 0.5 * h)))
{
int px=int(ceil(x - 0.5 * w));
int py=int(ceil(y - 0.5 * h));
pixmap_.set_rectangle_alpha(px,py,data);
}
}
}
@ -412,7 +418,7 @@ namespace mapnik
t_.forward_y(&y);
face_ptr face = font_manager_.get_face("Bitstream Vera Sans Roman");//TODO
//face_ptr face = font_manager_.get_face("Times New Roman Regular");//TODO
if (face)
{
text_renderer<mapnik::Image32> ren(pixmap_,face);
@ -420,7 +426,7 @@ namespace mapnik
ren.set_fill(fill);
ren.set_halo_radius(1);
ren.set_angle(angle);
ren.render(text,x,y);
ren.render(text,x+6,y+6);
}
}
}