1.don't share FT_Library object between threads (TODO : implement freetype_engine pool)

2. merged changes with latest load_map
This commit is contained in:
Artem Pavlenko 2007-10-05 11:27:00 +00:00
parent 9507f1bbf2
commit d1a345a3d2
20 changed files with 314 additions and 199 deletions

31
INSTALL
View file

@ -9,9 +9,9 @@ First, here is a quick list of the software dependencies:
- Linux/UNIX with g++ compiler - Linux/UNIX with g++ compiler
- libboost 1.32.0 or greater with the following libraries included: - libboost 1.33.0 or greater with the following libraries included:
- thread - thread
- wserialization - system (boost >= 1.35 only)
- filesystem - filesystem
- regex - regex
- (Optional) program_options - (Optional) program_options
@ -24,9 +24,9 @@ First, here is a quick list of the software dependencies:
- libfreetype2 - libfreetype2
- (Optional) PostgreSQL libraries (For PostGIS support) - (Optional) PostgreSQL libraries (For PostGIS support)
- (Optional) PROJ.4 (More on this below) - (Optional) PROJ.4 (More on this below)
- (Optional) GDAL
- Python 1.5.2 or greater to build Mapnik - Python 1.5.2 or greater to build Mapnik
- (Optional) Python 2.2 or greater for the Python language bindings - (Optional) Python 2.4 or greater for the Python language bindings
All of these will normally come with any modern Linux distribution. All of these will normally come with any modern Linux distribution.
@ -51,7 +51,7 @@ Note that the python used to run "scons" does NOT have to be the same as the one
To see the list of available options, from the root of the source distribution, run: To see the list of available options, from the root of the source distribution, run:
$ /path/to/python scons/scons.py -h $ /path/to/python scons/scons -h
You will get: You will get:
@ -159,24 +159,18 @@ If you're using the default PREFIX, you will most likely need to be root to perf
A note on projection support A note on projection support
---------------------------- ----------------------------
At this time Mapnik's core C++ library and map rendering engine does NOT support on-the-fly cartographic Mapnik's core C++ library and map rendering engine support on-the-fly cartographic
reprojections. reprojections.
Mapnik can however be configured to build the Python API to the PROJ.4 library. This provides projection
support through Python, and is used by the WMS ogcserver feature, since that server is written in Python.
Here is an example on how to use it: Here is an example on how to use it:
>>> from mapnik import Projection >>> from mapnik import Projection,Coord
registered datasource : raster >>> p = Projection('init=epsg:27700') # British National Grid
registered datasource : shape >>> p.foward(Coord(-1.125,51.75))
registered datasource : postgis Coord(460396.904482,206113.130999)
>>> p = Projection(['init=epsg:42304'])
>>> p.Inverse(12345.245,143225.56)
[-94.825927695613018, 50.290732340975467]
>>> >>>
The Projection() instance provides Inverse() and Forward() methods. For details on the possible parameters, The Projection() instance provides inverse() and forward() methods. For details on the possible parameters,
see the PROJ.4 documentation. see the PROJ.4 documentation.
@ -192,8 +186,5 @@ Python 2.4.2 (#1, Jan 11 2006, 10:59:28)
[GCC 3.4.4 20050721 (Red Hat 3.4.4-2)] on linux2 [GCC 3.4.4 20050721 (Red Hat 3.4.4-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information. Type "help", "copyright", "credits" or "license" for more information.
>>> from mapnik import * >>> from mapnik import *
registered datasource : shape
registered datasource : raster
registered datasource : postgis
>>> >>>

View file

@ -46,7 +46,7 @@ opts.Add(PathOption('PGSQL_INCLUDES', 'Search path for PostgreSQL include files'
opts.Add(PathOption('PGSQL_LIBS', 'Search path for PostgreSQL library files', '/usr/' + LIBDIR_SCHEMA)) opts.Add(PathOption('PGSQL_LIBS', 'Search path for PostgreSQL library files', '/usr/' + LIBDIR_SCHEMA))
opts.Add(PathOption('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/local/include')) opts.Add(PathOption('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/local/include'))
opts.Add(PathOption('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/local/' + LIBDIR_SCHEMA)) opts.Add(PathOption('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/local/' + LIBDIR_SCHEMA))
opts.Add(PathOption('GDAL_INCLUDES', 'Search path for GDAL include files', '/usr/include/gdal')) opts.Add(PathOption('GDAL_INCLUDES', 'Search path for GDAL include files', '/usr/include'))
opts.Add(PathOption('GDAL_LIBS', 'Search path for GDAL library files', '/usr/' + LIBDIR_SCHEMA)) opts.Add(PathOption('GDAL_LIBS', 'Search path for GDAL library files', '/usr/' + LIBDIR_SCHEMA))
opts.Add(PathOption('GIGABASE_INCLUDES', 'Search path for Gigabase include files', '/usr/local/include')) opts.Add(PathOption('GIGABASE_INCLUDES', 'Search path for Gigabase include files', '/usr/local/include'))
opts.Add(PathOption('GIGABASE_LIBS', 'Search path for Gigabase library files', '/usr/local/' + LIBDIR_SCHEMA)) opts.Add(PathOption('GIGABASE_LIBS', 'Search path for Gigabase library files', '/usr/local/' + LIBDIR_SCHEMA))
@ -130,7 +130,7 @@ if env['BIDI'] : C_LIBSHEADERS.append(['fribidi','fribidi/fribidi.h',True])
BOOST_LIBSHEADERS = [ BOOST_LIBSHEADERS = [
['thread', 'boost/thread/mutex.hpp', True], ['thread', 'boost/thread/mutex.hpp', True],
# ['system', 'boost/system/system_error.hpp', True], # uncomment this on Darwin + boost_1_35 ['system', 'boost/system/system_error.hpp', True], # uncomment this on Darwin + boost_1_35
['filesystem', 'boost/filesystem/operations.hpp', True], ['filesystem', 'boost/filesystem/operations.hpp', True],
['regex', 'boost/regex.hpp', True], ['regex', 'boost/regex.hpp', True],
['program_options', 'boost/program_options.hpp', False] ['program_options', 'boost/program_options.hpp', False]
@ -228,7 +228,7 @@ env = conf.Finish()
if env['PLATFORM'] == 'Darwin': pthread = '' if env['PLATFORM'] == 'Darwin': pthread = ''
else: pthread = '-pthread' else: pthread = '-pthread'
common_cxx_flags = '-ansi -Wall %s -ftemplate-depth-100 -D%s ' % (pthread, env['PLATFORM'].upper()); common_cxx_flags = '-ansi -Wall %s -ftemplate-depth-100 -D%s -DBOOST_SPIRIT_THREADSAFE ' % (pthread, env['PLATFORM'].upper());
if env['DEBUG']: if env['DEBUG']:
env.Append(CXXFLAGS = common_cxx_flags + '-O0 -fno-inline -g -DDEBUG -DMAPNIK_DEBUG') env.Append(CXXFLAGS = common_cxx_flags + '-O0 -fno-inline -g -DDEBUG -DMAPNIK_DEBUG')

View file

@ -52,6 +52,16 @@ void LayerTab::dataChanged(const QModelIndex &topLeft,
emit update_mapwidget(); emit update_mapwidget();
} }
void LayerTab::selectionChanged(const QItemSelection & selected, const QItemSelection &)
{
QModelIndexList list = selected.indexes();
if (list.size() != 0)
{
std::cout << "SELECTED LAYER ->" << list[0].row() << "\n";
emit layerSelected(list[0].row());
}
}
void LayerTab::layerInfo() void LayerTab::layerInfo()
{ {
qDebug("Layer info"); qDebug("Layer info");

View file

@ -33,11 +33,13 @@ class LayerTab : public QListView
void paintEvent(QPaintEvent *e); void paintEvent(QPaintEvent *e);
signals: signals:
void update_mapwidget(); void update_mapwidget();
void layerSelected(int) const;
public slots: public slots:
void layerInfo(); void layerInfo();
void layerInfo2(QModelIndex const&); void layerInfo2(QModelIndex const&);
protected slots: protected slots:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
void selectionChanged(const QItemSelection & selected, const QItemSelection &);
}; };
class StyleTab : public QTreeView class StyleTab : public QTreeView

View file

@ -32,9 +32,9 @@ int main( int argc, char **argv )
datasource_cache::instance()->register_datasources("/usr/local/lib/mapnik/input"); datasource_cache::instance()->register_datasources("/usr/local/lib/mapnik/input");
freetype_engine::instance()->register_font("/usr/local/lib/mapnik/fonts/DejaVuSans.ttf"); freetype_engine::register_font("/usr/local/lib/mapnik/fonts/DejaVuSans.ttf");
freetype_engine::instance()->register_font("/usr/local/lib/mapnik/fonts/DejaVuSans-Bold.ttf"); freetype_engine::register_font("/usr/local/lib/mapnik/fonts/DejaVuSans-Bold.ttf");
freetype_engine::instance()->register_font("/usr/local/lib/mapnik/fonts/DejaVuSansMono.ttf"); freetype_engine::register_font("/usr/local/lib/mapnik/fonts/DejaVuSansMono.ttf");
QApplication app( argc, argv ); QApplication app( argc, argv );

View file

@ -32,6 +32,7 @@
#include <QSlider> #include <QSlider>
// mapnik // mapnik
#include <mapnik/config_error.hpp>
#include <mapnik/load_map.hpp> #include <mapnik/load_map.hpp>
#include "mainwindow.hpp" #include "mainwindow.hpp"
@ -92,6 +93,8 @@ MainWindow::MainWindow()
connect(slider_,SIGNAL(valueChanged(int)),mapWidget_,SLOT(zoomToLevel(int))); connect(slider_,SIGNAL(valueChanged(int)),mapWidget_,SLOT(zoomToLevel(int)));
// //
connect(layerTab_,SIGNAL(update_mapwidget()),mapWidget_,SLOT(updateMap())); connect(layerTab_,SIGNAL(update_mapwidget()),mapWidget_,SLOT(updateMap()));
connect(layerTab_,SIGNAL(layerSelected(int)),
mapWidget_,SLOT(layerSelected(int)));
} }
@ -171,9 +174,9 @@ void MainWindow::load_map_file(QString const& filename)
layerTab_->setModel(new LayerListModel(map,this)); layerTab_->setModel(new LayerListModel(map,this));
styleTab_->setModel(new StyleModel(map,this)); styleTab_->setModel(new StyleModel(map,this));
} }
catch (...) catch (mapnik::config_error & ex)
{ {
std::cout << "Unexpected Exception\n"; std::cout << ex.what() << "\n";
} }
} }
@ -366,3 +369,5 @@ void MainWindow::createToolBars()
fileToolBar->addWidget(slider_); fileToolBar->addWidget(slider_);
fileToolBar->addAction(aboutAct); fileToolBar->addAction(aboutAct);
} }

View file

@ -62,18 +62,19 @@ double scales [] = {279541132.014,
533.182395962}; 533.182395962};
MapWidget::MapWidget(QWidget *parent) MapWidget::MapWidget(QWidget *parent)
:QWidget(parent), : QWidget(parent),
map_(), map_(),
selected_(1), selected_(1),
extent_(), extent_(),
cur_tool_(ZoomToBox), cur_tool_(ZoomToBox),
start_x_(0), start_x_(0),
start_y_(0), start_y_(0),
end_x_(0), end_x_(0),
end_y_(0), end_y_(0),
drag_(false), drag_(false),
first_(true), first_(true),
pen_(QColor(0,0,255,96)) pen_(QColor(0,0,255,96)),
selectedLayer_(-1)
{ {
pen_.setWidth(3); pen_.setWidth(3);
pen_.setCapStyle(Qt::RoundCap); pen_.setCapStyle(Qt::RoundCap);
@ -140,19 +141,23 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
{ {
QVector<QPair<QString,QString> > info; QVector<QPair<QString,QString> > info;
projection proj(map_->srs()); // map projection projection map_proj(map_->srs()); // map projection
double scale_denom = scale_denominator(*map_,proj.is_geographic()); double scale_denom = scale_denominator(*map_,map_proj.is_geographic());
CoordTransform t(map_->getWidth(),map_->getHeight(),map_->getCurrentExtent());
for (unsigned index = 0; index < map_->layerCount();++index) for (unsigned index = 0; index < map_->layerCount();++index)
{ {
if (int(index) != selectedLayer_) continue;
Layer & layer = map_->layers()[index]; Layer & layer = map_->layers()[index];
if (!layer.isVisible(scale_denom)) continue; if (!layer.isVisible(scale_denom)) continue;
std::string name = layer.name(); std::string name = layer.name();
double x = e->x(); double x = e->x();
double y = e->y(); double y = e->y();
std::cout << "query at " << x << "," << y << "\n"; std::cout << "query at " << x << "," << y << "\n";
projection layer_proj(layer.srs());
std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource); mapnik::proj_transform prj_trans(map_proj,layer_proj);
//std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource);
mapnik::featureset_ptr fs = map_->query_map_point(index,x,y); mapnik::featureset_ptr fs = map_->query_map_point(index,x,y);
if (fs) if (fs)
@ -170,24 +175,38 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
itr->second.to_string().c_str())); itr->second.to_string().c_str()));
} }
} }
typedef mapnik::coord_transform2<mapnik::CoordTransform,mapnik::geometry2d> path_type;
if (feat->num_geometries() > 0) for (unsigned i=0; i<feat->num_geometries();++i)
{ {
mapnik::geometry2d & geom = feat->get_geometry(0); mapnik::geometry2d & geom = feat->get_geometry(i);
(*feat)["mapnik:geometry"] = geom.type(); path_type path(t,geom,prj_trans);
data->push(feat); if (geom.num_points() > 0)
{
QPainterPath qpath;
double x,y;
path.vertex(&x,&y);
qpath.moveTo(x,y);
for (int j=1; j < geom.num_points(); ++j)
{
path.vertex(&x,&y);
qpath.lineTo(x,y);
}
QPainter painter(&pix_);
QPen pen(QColor(255,0,0,96));
pen.setWidth(3);
pen.setCapStyle(Qt::RoundCap);
pen.setJoinStyle(Qt::RoundJoin);
painter.setPen(pen);
painter.drawPath(qpath);
update();
}
} }
} }
} }
if (data->size()) if (info.size() > 0)
{ {
mapnik::Layer annotations("*annotations*");
annotations.set_srs(map_->layers()[index].srs());
annotations.add_style("mapnik:selection");
annotations.set_datasource(mapnik::datasource_ptr(data.release()));
map_->addLayer(annotations);
updateMap();
info_dialog info_dlg(info,this); info_dialog info_dlg(info,this);
info_dlg.exec(); info_dlg.exec();
break; break;
@ -421,6 +440,7 @@ void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::strin
//image.saveToFile(filename,type); //image.saveToFile(filename,type);
} }
void MapWidget::updateMap() void MapWidget::updateMap()
{ {
if (map_) if (map_)
@ -450,3 +470,9 @@ void MapWidget::setMap(boost::shared_ptr<Map> map)
{ {
map_ = map; map_ = map;
} }
void MapWidget::layerSelected(int index)
{
selectedLayer_ = index;
}

View file

@ -25,6 +25,7 @@
#include <QImage> #include <QImage>
#include <QPixmap> #include <QPixmap>
#include <QPen> #include <QPen>
#include <QItemSelection>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
@ -56,6 +57,7 @@ class MapWidget : public QWidget
bool drag_; bool drag_;
bool first_; bool first_;
QPen pen_; QPen pen_;
int selectedLayer_;
public: public:
MapWidget(QWidget *parent=0); MapWidget(QWidget *parent=0);
void setTool(eTool tool); void setTool(eTool tool);
@ -72,7 +74,8 @@ class MapWidget : public QWidget
void panDown(); void panDown();
public slots: public slots:
void zoomToLevel(int level); void zoomToLevel(int level);
void updateMap(); void updateMap();
void layerSelected(int);
signals: signals:
void mapViewChanged(); void mapViewChanged();
protected: protected:

View file

@ -171,7 +171,7 @@ struct symbolizer_icon : public boost::static_visitor<QIcon>
QIcon operator() (mapnik::point_symbolizer const& sym) const QIcon operator() (mapnik::point_symbolizer const& sym) const
{ {
boost::shared_ptr<mapnik::ImageData32> symbol = sym.get_data(); boost::shared_ptr<mapnik::ImageData32> symbol = sym.get_image();
if (symbol) if (symbol)
{ {
QImage image(symbol->getBytes(),symbol->width(),symbol->height(),QImage::Format_ARGB32); QImage image(symbol->getBytes(),symbol->width(),symbol->height(),QImage::Format_ARGB32);
@ -322,7 +322,7 @@ StyleModel::~StyleModel() {}
// interface // interface
QModelIndex StyleModel::index (int row, int col, QModelIndex const& parent) const QModelIndex StyleModel::index (int row, int col, QModelIndex const& parent) const
{ {
qDebug("index() row=%d col=%d parent::internalId() = %lld", row,col,parent.internalId()); // qDebug("index() row=%d col=%d parent::internalId() = %lld", row,col,parent.internalId());
node * parent_node; node * parent_node;
if (!parent.isValid()) if (!parent.isValid())
@ -349,7 +349,7 @@ QModelIndex StyleModel::parent (QModelIndex const& index) const
int StyleModel::rowCount(QModelIndex const& parent) const int StyleModel::rowCount(QModelIndex const& parent) const
{ {
qDebug("rowCount"); //qDebug("rowCount");
node * parent_node; node * parent_node;
if (parent.column() > 0) return 0; if (parent.column() > 0) return 0;
if (!parent.isValid()) if (!parent.isValid())
@ -366,7 +366,7 @@ int StyleModel::columnCount( QModelIndex const&) const
QVariant StyleModel::data(const QModelIndex & index, int role) const QVariant StyleModel::data(const QModelIndex & index, int role) const
{ {
qDebug("data index::internalId() = %lld", index.internalId()); //qDebug("data index::internalId() = %lld", index.internalId());
if (!index.isValid()) if (!index.isValid())
return QVariant(); return QVariant();
node * cur_node = static_cast<node*>(index.internalPointer()); node * cur_node = static_cast<node*>(index.internalPointer());

View file

@ -85,6 +85,7 @@ namespace mapnik {
agg::row_ptr_cache<agg::int8u> buf_; agg::row_ptr_cache<agg::int8u> buf_;
agg::pixfmt_rgba32 pixf_; agg::pixfmt_rgba32 pixf_;
CoordTransform t_; CoordTransform t_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_; face_manager<freetype_engine> font_manager_;
label_collision_detector4 detector_; label_collision_detector4 detector_;
placement_finder<label_collision_detector4> finder_; placement_finder<label_collision_detector4> finder_;

View file

@ -144,7 +144,7 @@ namespace mapnik {
{ {
return scale_; return scale_;
} }
inline void forward(double * x, double * y) const inline void forward(double * x, double * y) const
{ {
*x = (*x - extent_.minx()) * scale_ - offset_x_; *x = (*x - extent_.minx()) * scale_ - offset_x_;
@ -156,13 +156,13 @@ namespace mapnik {
*x = extent_.minx() + (*x + offset_x_)/scale_; *x = extent_.minx() + (*x + offset_x_)/scale_;
*y = extent_.maxy() - (*y + offset_y_)/scale_; *y = extent_.maxy() - (*y + offset_y_)/scale_;
} }
inline coord2d& forward(coord2d& c) const inline coord2d& forward(coord2d& c) const
{ {
forward(&c.x,&c.y); forward(&c.x,&c.y);
return c; return c;
} }
inline coord2d& backward(coord2d& c) const inline coord2d& backward(coord2d& c) const
{ {
backward(&c.x,&c.y); backward(&c.x,&c.y);
@ -208,6 +208,10 @@ namespace mapnik {
} }
return coords; return coords;
} }
inline Envelope<double> const& extent() const
{
return extent_;
}
}; };
} }

View file

@ -66,8 +66,7 @@ namespace mapnik
public: public:
feature_style_processor(Map const& m) feature_style_processor(Map const& m)
: m_(m) {} : m_(m) {}
void apply() void apply()
{ {
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG

View file

@ -33,24 +33,26 @@ extern "C"
#include FT_GLYPH_H #include FT_GLYPH_H
} }
// stl
#include <string>
#include <vector>
#include <map>
#include <iostream>
// boost
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/thread/mutex.hpp>
// mapnik // mapnik
#include <mapnik/color.hpp> #include <mapnik/color.hpp>
#include <mapnik/utils.hpp> #include <mapnik/utils.hpp>
#include <mapnik/ctrans.hpp> #include <mapnik/ctrans.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/text_path.hpp> #include <mapnik/text_path.hpp>
// boost
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/mutex.hpp>
// stl
#include <string>
#include <vector>
#include <map>
#include <iostream>
namespace mapnik namespace mapnik
{ {
class font_face : boost::noncopyable class font_face : boost::noncopyable
@ -105,22 +107,20 @@ namespace mapnik
FT_Face face_; FT_Face face_;
}; };
typedef boost::shared_ptr<font_face> face_ptr; typedef boost::shared_ptr<font_face> face_ptr;
class MAPNIK_DECL freetype_engine // : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>,
class MAPNIK_DECL freetype_engine : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>, // private boost::noncopyable
private boost::noncopyable
{ {
friend class mapnik::CreateStatic<freetype_engine>; // friend class mapnik::CreateStatic<freetype_engine>;
public: public:
static bool register_font(std::string const& file_name); static bool register_font(std::string const& file_name);
static std::vector<std::string> face_names (); static std::vector<std::string> face_names ();
static face_ptr create_face(std::string const& family_name); face_ptr create_face(std::string const& family_name);
private:
freetype_engine();
virtual ~freetype_engine(); virtual ~freetype_engine();
static FT_Library library_; freetype_engine();
private:
FT_Library library_;
static boost::mutex mutex_;
static std::map<std::string,std::string> name2file_; static std::map<std::string,std::string> name2file_;
}; };
@ -129,8 +129,11 @@ namespace mapnik
{ {
typedef T font_engine_type; typedef T font_engine_type;
typedef std::map<std::string,face_ptr> faces; typedef std::map<std::string,face_ptr> faces;
public: public:
face_manager(T & engine)
: engine_(engine) {}
face_ptr get_face(std::string const& name) face_ptr get_face(std::string const& name)
{ {
typename faces::iterator itr; typename faces::iterator itr;
@ -141,7 +144,7 @@ namespace mapnik
} }
else else
{ {
face_ptr face = font_engine_type::instance()->create_face(name); face_ptr face = engine_.create_face(name);
if (face) if (face)
{ {
faces_.insert(make_pair(name,face)); faces_.insert(make_pair(name,face));
@ -151,6 +154,7 @@ namespace mapnik
} }
private: private:
faces faces_; faces faces_;
font_engine_type & engine_;
}; };
template <typename T> template <typename T>

View file

@ -40,7 +40,7 @@ namespace mapnik
struct placement : boost::noncopyable struct placement : boost::noncopyable
{ {
typedef coord_transform2<CoordTransform,geometry2d> path_type; typedef coord_transform2<CoordTransform,geometry2d> path_type;
template <typename SymbolizerT> template <typename SymbolizerT>
placement(string_info *info_, placement(string_info *info_,

View file

@ -62,14 +62,17 @@ namespace mapnik
struct MAPNIK_DECL building_symbolizer struct MAPNIK_DECL building_symbolizer
{ {
explicit building_symbolizer() explicit building_symbolizer()
: fill_(Color(128,128,128)), : fill_(Color(128,128,128)),
opacity_(1.0) {} height_(0),
opacity_(1.0)
{}
building_symbolizer(Color const& fill) building_symbolizer(Color const& fill,double height)
: fill_(fill), : fill_(fill),
opacity_(1.0) {} height_(height),
opacity_(1.0) {}
Color const& get_fill() const Color const& get_fill() const
{ {
return fill_; return fill_;
@ -78,6 +81,14 @@ namespace mapnik
{ {
fill_ = fill; fill_ = fill;
} }
double height() const
{
return height_;
}
void set_height(double height)
{
height_=height;
}
void set_opacity(float opacity) void set_opacity(float opacity)
{ {
opacity_ = opacity; opacity_ = opacity;
@ -88,6 +99,7 @@ namespace mapnik
} }
private: private:
Color fill_; Color fill_;
double height_;
float opacity_; float opacity_;
}; };
} }

View file

@ -57,6 +57,8 @@
#include "agg_renderer_scanline.h" #include "agg_renderer_scanline.h"
#include "agg_pattern_filters_rgba.h" #include "agg_pattern_filters_rgba.h"
#include "agg_renderer_outline_image.h" #include "agg_renderer_outline_image.h"
#include "agg_vpgen_clip_polyline.h"
// mapnik // mapnik
#include <mapnik/image_util.hpp> #include <mapnik/image_util.hpp>
#include <mapnik/agg_renderer.hpp> #include <mapnik/agg_renderer.hpp>
@ -100,6 +102,8 @@ namespace mapnik
buf_(pixmap_.raw_data(),width_,height_, width_ * 4), buf_(pixmap_.raw_data(),width_,height_, width_ * 4),
pixf_(buf_), pixf_(buf_),
t_(m.getWidth(),m.getHeight(),m.getCurrentExtent(),offset_x,offset_y), t_(m.getWidth(),m.getHeight(),m.getCurrentExtent(),offset_x,offset_y),
font_engine_(),
font_manager_(font_engine_),
detector_(Envelope<double>(-64 ,-64, m.getWidth() + 64 ,m.getHeight() + 64)), detector_(Envelope<double>(-64 ,-64, m.getWidth() + 64 ,m.getHeight() + 64)),
finder_(detector_,Envelope<double>(0 ,0, m.getWidth(), m.getHeight())) finder_(detector_,Envelope<double>(0 ,0, m.getWidth(), m.getHeight()))
{ {
@ -197,7 +201,6 @@ namespace mapnik
typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base; typedef agg::renderer_base<agg::pixfmt_rgba32> ren_base;
typedef agg::renderer_scanline_aa_solid<ren_base> renderer; typedef agg::renderer_scanline_aa_solid<ren_base> renderer;
ren_base renb(pixf_); ren_base renb(pixf_);
Color const& fill_ = sym.get_fill(); Color const& fill_ = sym.get_fill();
unsigned r=fill_.red(); unsigned r=fill_.red();
@ -207,7 +210,7 @@ namespace mapnik
agg::scanline_u8 sl; agg::scanline_u8 sl;
ras_.reset(); ras_.reset();
int height = 60 << 8; double height = 0.7071 * sym.height(); // height in meters
for (unsigned i=0;i<feature.num_geometries();++i) for (unsigned i=0;i<feature.num_geometries();++i)
{ {
@ -215,12 +218,12 @@ namespace mapnik
if (geom.num_points() > 2) if (geom.num_points() > 2)
{ {
boost::scoped_ptr<geometry2d> frame(new line_string_impl); boost::scoped_ptr<geometry2d> frame(new line_string_impl);
boost::scoped_ptr<geometry2d> roof(new polygon_impl); boost::scoped_ptr<geometry2d> roof(new polygon_impl);
std::deque<segment_t> face_segments; std::deque<segment_t> face_segments;
double x0(0); double x0(0);
double y0(0); double y0(0);
for (unsigned j=0;j<geom.num_points();++j) unsigned cm = geom.vertex(&x0,&y0);
for (unsigned j=1;j<geom.num_points();++j)
{ {
double x,y; double x,y;
unsigned cm = geom.vertex(&x,&y); unsigned cm = geom.vertex(&x,&y);
@ -251,7 +254,7 @@ namespace mapnik
path_type faces_path (t_,*faces,prj_trans); path_type faces_path (t_,*faces,prj_trans);
ras_.add_path(faces_path); ras_.add_path(faces_path);
ren.color(agg::rgba8(int(r*0.7), int(g*0.7), int(b*0.7), int(255 * sym.get_opacity()))); ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(255 * sym.get_opacity())));
agg::render_scanlines(ras_, sl, ren); agg::render_scanlines(ras_, sl, ren);
ras_.reset(); ras_.reset();
@ -602,6 +605,7 @@ namespace mapnik
ren.set_halo_fill(sym.get_halo_fill()); ren.set_halo_fill(sym.get_halo_fill());
ren.set_halo_radius(sym.get_halo_radius()); ren.set_halo_radius(sym.get_halo_radius());
Envelope<double> ext = t_.extent();
string_info info(text); string_info info(text);
ren.get_string_info(&info); ren.get_string_info(&info);
unsigned num_geom = feature.num_geometries(); unsigned num_geom = feature.num_geometries();
@ -610,9 +614,39 @@ namespace mapnik
geometry2d const& geom = feature.get_geometry(i); geometry2d const& geom = feature.get_geometry(i);
if (geom.num_points() > 0) // don't bother with empty geometries if (geom.num_points() > 0) // don't bother with empty geometries
{ {
placement text_placement(&info, &t_, &prj_trans, geom, sym); //agg::vpgen_clip_polyline clipped_path;
// clip to the bbox
//clipped_path.clip_box(ext.minx(),ext.miny(),ext.maxx(),ext.maxy());
//for (unsigned j=0;j<geom.num_points();++j)
//{
// double x,y;
/// unsigned c = geom.vertex(&x,&y);
// if (c == SEG_MOVETO)
// clipped_path.move_to(x,y);
// else if (c == SEG_LINETO)
// clipped_path.line_to(x,y);
//}
//line_string_impl line;
//while (1)
//{
// double x,y;
// unsigned cmd = clipped_path.vertex(&x,&y);
// if (cmd == SEG_END) break;
// else if (cmd == SEG_MOVETO)
// {
// line.move_to(x,y);
// }
// else if (cmd == SEG_LINETO)
// {
// line.line_to(x,y);
// }
//}
placement text_placement(&info, &t_, &prj_trans, geom, sym);
finder_.find_placements(&text_placement); finder_.find_placements(&text_placement);
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii) for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii)
{ {
double x = text_placement.placements[ii].starting_x; double x = text_placement.placements[ii].starting_x;
double y = text_placement.placements[ii].starting_y; double y = text_placement.placements[ii].starting_y;

View file

@ -88,7 +88,12 @@ namespace mapnik
throw std::runtime_error(string("Cannot load symbols: ") + throw std::runtime_error(string("Cannot load symbols: ") +
lt_dlerror()); lt_dlerror());
} }
std::cout << "size = " << params.size() << "\n";
parameters::const_iterator i = params.begin();
for (;i!=params.end();++i)
{
std::cout << i->first << "=" << i->second << "\n";
}
ds=datasource_ptr(create_datasource(params), datasource_deleter()); ds=datasource_ptr(create_datasource(params), datasource_deleter());
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG

View file

@ -23,72 +23,78 @@
#include <mapnik/font_engine_freetype.hpp> #include <mapnik/font_engine_freetype.hpp>
using std::cerr;
using std::endl;
namespace mapnik namespace mapnik
{ {
freetype_engine::freetype_engine() freetype_engine::freetype_engine()
{ {
FT_Error error = FT_Init_FreeType( &library_ ); FT_Error error = FT_Init_FreeType( &library_ );
if (error) if (error)
{ {
throw std::runtime_error("Failed to initialize FreeType2 library"); throw std::runtime_error("can not load FreeType2 library");
} }
} }
freetype_engine::~freetype_engine()
{
FT_Done_FreeType(library_);
}
bool freetype_engine::register_font(std::string const& file_name)
{
mutex::scoped_lock lock(mutex_);
FT_Library library;
FT_Error error = FT_Init_FreeType(&library);
if (error)
{
throw std::runtime_error("Failed to initialize FreeType2 library");
}
FT_Face face;
error = FT_New_Face (library,file_name.c_str(),0,&face);
if (error)
{
FT_Done_FreeType(library);
return false;
}
std::string name = std::string(face->family_name) + " " + std::string(face->style_name);
name2file_.insert(std::make_pair(name,file_name));
FT_Done_Face(face );
FT_Done_FreeType(library);
return true;
}
std::vector<std::string> freetype_engine::face_names ()
{
std::vector<std::string> names;
std::map<std::string,std::string>::const_iterator itr;
for (itr = name2file_.begin();itr!=name2file_.end();++itr)
{
names.push_back(itr->first);
}
return names;
}
freetype_engine::~freetype_engine() face_ptr freetype_engine::create_face(std::string const& family_name)
{ {
FT_Done_FreeType(library_); //mutex::scoped_lock lock(mapnik::singleton<freetype_engine,
} // mapnik::CreateStatic>::mutex_);
std::map<std::string,std::string>::iterator itr;
itr = name2file_.find(family_name);
if (itr != name2file_.end())
{
FT_Face face;
FT_Error error = FT_New_Face (library_,itr->second.c_str(),0,&face);
bool freetype_engine::register_font(std::string const& file_name) if (!error)
{ {
mutex::scoped_lock lock(mapnik::singleton<freetype_engine, return face_ptr (new font_face(face));
mapnik::CreateStatic>::mutex_); }
//cerr << "freetype_engine::register_font() '" << file_name << "'" << endl; }
FT_Face face; return face_ptr();
FT_Error error = FT_New_Face (library_,file_name.c_str(),0,&face); }
if ( !error )
{ //FT_Library freetype_engine::library_;
std::string name = std::string(face->family_name) + " " + std::string(face->style_name); boost::mutex freetype_engine::mutex_;
name2file_.insert(std::make_pair(name,file_name)); std::map<std::string,std::string> freetype_engine::name2file_;
FT_Done_Face(face );
return true;
}
return false;
}
std::vector<std::string> freetype_engine::face_names ()
{
std::vector<std::string> names;
std::map<std::string,std::string>::const_iterator itr;
for (itr = name2file_.begin();itr!=name2file_.end();++itr)
{
names.push_back(itr->first);
}
return names;
}
face_ptr freetype_engine::create_face(std::string const& family_name)
{
mutex::scoped_lock lock(mapnik::singleton<freetype_engine,
mapnik::CreateStatic>::mutex_);
std::map<std::string,std::string>::iterator itr;
itr = name2file_.find(family_name);
if (itr != name2file_.end())
{
FT_Face face;
FT_Error error = FT_New_Face (library_,itr->second.c_str(),0,&face);
if (!error)
{
return face_ptr (new font_face(face));
}
}
return face_ptr();
}
FT_Library freetype_engine::library_;
std::map<std::string,std::string> freetype_engine::name2file_;
} }

View file

@ -53,32 +53,35 @@ using std::endl;
namespace mapnik namespace mapnik
{ {
using boost::optional; using boost::optional;
class map_parser { class map_parser : boost::noncopyable {
public: public:
map_parser( bool strict ) : strict_( strict ) {}; map_parser( bool strict ) :
strict_( strict ),
void parse_map( Map & map, ptree const & sty); font_manager_(font_engine_) {}
private:
void parse_style( Map & map, ptree const & sty); void parse_map( Map & map, ptree const & sty);
void parse_layer( Map & map, ptree const & lay); private:
void parse_style( Map & map, ptree const & sty);
void parse_rule( feature_type_style & style, ptree const & r); void parse_layer( Map & map, ptree const & lay);
void parse_point_symbolizer( rule_type & rule, ptree const & sym); void parse_rule( feature_type_style & style, ptree const & r);
void parse_line_pattern_symbolizer( rule_type & rule, ptree const & sym);
void parse_polygon_pattern_symbolizer( rule_type & rule, ptree const & sym); void parse_point_symbolizer( rule_type & rule, ptree const & sym);
void parse_text_symbolizer( rule_type & rule, ptree const & sym); void parse_line_pattern_symbolizer( rule_type & rule, ptree const & sym);
void parse_shield_symbolizer( rule_type & rule, ptree const & sym); void parse_polygon_pattern_symbolizer( rule_type & rule, ptree const & sym);
void parse_line_symbolizer( rule_type & rule, ptree const & sym); void parse_text_symbolizer( rule_type & rule, ptree const & sym);
void parse_polygon_symbolizer( rule_type & rule, ptree const & sym); void parse_shield_symbolizer( rule_type & rule, ptree const & sym);
void parse_building_symbolizer( rule_type & rule, ptree const & sym ); void parse_line_symbolizer( rule_type & rule, ptree const & sym);
void parse_polygon_symbolizer( rule_type & rule, ptree const & sym);
void ensure_font_face( const text_symbolizer & text_symbol ); void parse_building_symbolizer( rule_type & rule, ptree const & sym );
bool strict_; void ensure_font_face( const text_symbolizer & text_symbol );
face_manager<freetype_engine> font_manager_;
bool strict_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
}; };
void load_map(Map & map, std::string const& filename, bool strict) void load_map(Map & map, std::string const& filename, bool strict)
@ -789,6 +792,11 @@ namespace mapnik
float opacity = get_css<float>(css, css_name); float opacity = get_css<float>(css, css_name);
building_sym.set_opacity(opacity); building_sym.set_opacity(opacity);
} }
else if (css_name == "height")
{
float height = get_css<float>(css,css_name);
building_sym.set_height(height);
}
} }
rule.append(building_sym); rule.append(building_sym);
} }

View file

@ -177,7 +177,7 @@ namespace mapnik
old_y = new_y; old_y = new_y;
} }
} }
return total_distance_; return total_distance_;
} }
@ -213,15 +213,20 @@ namespace mapnik
int num_labels = 0; int num_labels = 0;
if (p->label_spacing && p->label_placement == LINE_PLACEMENT) if (p->label_spacing && p->label_placement == LINE_PLACEMENT)
{
num_labels = static_cast<int> (floor(distance / (p->label_spacing + string_width))); num_labels = static_cast<int> (floor(distance / (p->label_spacing + string_width)));
}
else if (p->label_spacing && p->label_placement == POINT_PLACEMENT) else if (p->label_spacing && p->label_placement == POINT_PLACEMENT)
{
num_labels = static_cast<int> (floor(distance / p->label_spacing)); num_labels = static_cast<int> (floor(distance / p->label_spacing));
}
if (p->force_odd_labels && num_labels%2 == 0) if (p->force_odd_labels && num_labels%2 == 0)
num_labels--; num_labels--;
if (num_labels <= 0) if (num_labels <= 0)
num_labels = 1; num_labels = 1;
double ideal_spacing = distance/num_labels; double ideal_spacing = distance/num_labels;
double middle; //try draw text centered double middle; //try draw text centered