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:
parent
9507f1bbf2
commit
d1a345a3d2
20 changed files with 314 additions and 199 deletions
31
INSTALL
31
INSTALL
|
@ -9,9 +9,9 @@ First, here is a quick list of the software dependencies:
|
|||
|
||||
- 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
|
||||
- wserialization
|
||||
- system (boost >= 1.35 only)
|
||||
- filesystem
|
||||
- regex
|
||||
- (Optional) program_options
|
||||
|
@ -24,9 +24,9 @@ First, here is a quick list of the software dependencies:
|
|||
- libfreetype2
|
||||
- (Optional) PostgreSQL libraries (For PostGIS support)
|
||||
- (Optional) PROJ.4 (More on this below)
|
||||
|
||||
- (Optional) GDAL
|
||||
- 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.
|
||||
|
||||
|
@ -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:
|
||||
|
||||
$ /path/to/python scons/scons.py -h
|
||||
$ /path/to/python scons/scons -h
|
||||
|
||||
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
|
||||
----------------------------
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
>>> from mapnik import Projection
|
||||
registered datasource : raster
|
||||
registered datasource : shape
|
||||
registered datasource : postgis
|
||||
>>> p = Projection(['init=epsg:42304'])
|
||||
>>> p.Inverse(12345.245,143225.56)
|
||||
[-94.825927695613018, 50.290732340975467]
|
||||
>>> from mapnik import Projection,Coord
|
||||
>>> p = Projection('init=epsg:27700') # British National Grid
|
||||
>>> p.foward(Coord(-1.125,51.75))
|
||||
Coord(460396.904482,206113.130999)
|
||||
>>>
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
@ -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
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> from mapnik import *
|
||||
registered datasource : shape
|
||||
registered datasource : raster
|
||||
registered datasource : postgis
|
||||
>>>
|
||||
|
||||
|
|
|
@ -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('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('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('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))
|
||||
|
@ -130,7 +130,7 @@ if env['BIDI'] : C_LIBSHEADERS.append(['fribidi','fribidi/fribidi.h',True])
|
|||
|
||||
BOOST_LIBSHEADERS = [
|
||||
['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],
|
||||
['regex', 'boost/regex.hpp', True],
|
||||
['program_options', 'boost/program_options.hpp', False]
|
||||
|
@ -228,7 +228,7 @@ env = conf.Finish()
|
|||
if env['PLATFORM'] == 'Darwin': 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']:
|
||||
env.Append(CXXFLAGS = common_cxx_flags + '-O0 -fno-inline -g -DDEBUG -DMAPNIK_DEBUG')
|
||||
|
|
|
@ -52,6 +52,16 @@ void LayerTab::dataChanged(const QModelIndex &topLeft,
|
|||
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()
|
||||
{
|
||||
qDebug("Layer info");
|
||||
|
|
|
@ -33,11 +33,13 @@ class LayerTab : public QListView
|
|||
void paintEvent(QPaintEvent *e);
|
||||
signals:
|
||||
void update_mapwidget();
|
||||
void layerSelected(int) const;
|
||||
public slots:
|
||||
void layerInfo();
|
||||
void layerInfo2(QModelIndex const&);
|
||||
protected slots:
|
||||
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
|
||||
void selectionChanged(const QItemSelection & selected, const QItemSelection &);
|
||||
};
|
||||
|
||||
class StyleTab : public QTreeView
|
||||
|
|
|
@ -32,9 +32,9 @@ int main( int argc, char **argv )
|
|||
|
||||
datasource_cache::instance()->register_datasources("/usr/local/lib/mapnik/input");
|
||||
|
||||
freetype_engine::instance()->register_font("/usr/local/lib/mapnik/fonts/DejaVuSans.ttf");
|
||||
freetype_engine::instance()->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/DejaVuSans.ttf");
|
||||
freetype_engine::register_font("/usr/local/lib/mapnik/fonts/DejaVuSans-Bold.ttf");
|
||||
freetype_engine::register_font("/usr/local/lib/mapnik/fonts/DejaVuSansMono.ttf");
|
||||
|
||||
|
||||
QApplication app( argc, argv );
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <QSlider>
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/config_error.hpp>
|
||||
#include <mapnik/load_map.hpp>
|
||||
|
||||
#include "mainwindow.hpp"
|
||||
|
@ -92,6 +93,8 @@ MainWindow::MainWindow()
|
|||
connect(slider_,SIGNAL(valueChanged(int)),mapWidget_,SLOT(zoomToLevel(int)));
|
||||
//
|
||||
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));
|
||||
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->addAction(aboutAct);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -62,18 +62,19 @@ double scales [] = {279541132.014,
|
|||
533.182395962};
|
||||
|
||||
MapWidget::MapWidget(QWidget *parent)
|
||||
:QWidget(parent),
|
||||
map_(),
|
||||
selected_(1),
|
||||
extent_(),
|
||||
cur_tool_(ZoomToBox),
|
||||
start_x_(0),
|
||||
start_y_(0),
|
||||
end_x_(0),
|
||||
end_y_(0),
|
||||
drag_(false),
|
||||
first_(true),
|
||||
pen_(QColor(0,0,255,96))
|
||||
: QWidget(parent),
|
||||
map_(),
|
||||
selected_(1),
|
||||
extent_(),
|
||||
cur_tool_(ZoomToBox),
|
||||
start_x_(0),
|
||||
start_y_(0),
|
||||
end_x_(0),
|
||||
end_y_(0),
|
||||
drag_(false),
|
||||
first_(true),
|
||||
pen_(QColor(0,0,255,96)),
|
||||
selectedLayer_(-1)
|
||||
{
|
||||
pen_.setWidth(3);
|
||||
pen_.setCapStyle(Qt::RoundCap);
|
||||
|
@ -140,19 +141,23 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
|
|||
{
|
||||
QVector<QPair<QString,QString> > info;
|
||||
|
||||
projection proj(map_->srs()); // map projection
|
||||
double scale_denom = scale_denominator(*map_,proj.is_geographic());
|
||||
projection map_proj(map_->srs()); // map projection
|
||||
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)
|
||||
{
|
||||
if (int(index) != selectedLayer_) continue;
|
||||
|
||||
Layer & layer = map_->layers()[index];
|
||||
if (!layer.isVisible(scale_denom)) continue;
|
||||
std::string name = layer.name();
|
||||
double x = e->x();
|
||||
double y = e->y();
|
||||
std::cout << "query at " << x << "," << y << "\n";
|
||||
|
||||
std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource);
|
||||
projection layer_proj(layer.srs());
|
||||
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);
|
||||
|
||||
if (fs)
|
||||
|
@ -170,24 +175,38 @@ void MapWidget::mousePressEvent(QMouseEvent* e)
|
|||
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);
|
||||
(*feat)["mapnik:geometry"] = geom.type();
|
||||
data->push(feat);
|
||||
mapnik::geometry2d & geom = feat->get_geometry(i);
|
||||
path_type path(t,geom,prj_trans);
|
||||
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_dlg.exec();
|
||||
break;
|
||||
|
@ -421,6 +440,7 @@ void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::strin
|
|||
//image.saveToFile(filename,type);
|
||||
}
|
||||
|
||||
|
||||
void MapWidget::updateMap()
|
||||
{
|
||||
if (map_)
|
||||
|
@ -450,3 +470,9 @@ void MapWidget::setMap(boost::shared_ptr<Map> map)
|
|||
{
|
||||
map_ = map;
|
||||
}
|
||||
|
||||
|
||||
void MapWidget::layerSelected(int index)
|
||||
{
|
||||
selectedLayer_ = index;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
#include <QPen>
|
||||
#include <QItemSelection>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
@ -56,6 +57,7 @@ class MapWidget : public QWidget
|
|||
bool drag_;
|
||||
bool first_;
|
||||
QPen pen_;
|
||||
int selectedLayer_;
|
||||
public:
|
||||
MapWidget(QWidget *parent=0);
|
||||
void setTool(eTool tool);
|
||||
|
@ -72,7 +74,8 @@ class MapWidget : public QWidget
|
|||
void panDown();
|
||||
public slots:
|
||||
void zoomToLevel(int level);
|
||||
void updateMap();
|
||||
void updateMap();
|
||||
void layerSelected(int);
|
||||
signals:
|
||||
void mapViewChanged();
|
||||
protected:
|
||||
|
|
|
@ -171,7 +171,7 @@ struct symbolizer_icon : public boost::static_visitor<QIcon>
|
|||
|
||||
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)
|
||||
{
|
||||
QImage image(symbol->getBytes(),symbol->width(),symbol->height(),QImage::Format_ARGB32);
|
||||
|
@ -322,7 +322,7 @@ StyleModel::~StyleModel() {}
|
|||
// interface
|
||||
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;
|
||||
|
||||
if (!parent.isValid())
|
||||
|
@ -349,7 +349,7 @@ QModelIndex StyleModel::parent (QModelIndex const& index) const
|
|||
|
||||
int StyleModel::rowCount(QModelIndex const& parent) const
|
||||
{
|
||||
qDebug("rowCount");
|
||||
//qDebug("rowCount");
|
||||
node * parent_node;
|
||||
if (parent.column() > 0) return 0;
|
||||
if (!parent.isValid())
|
||||
|
@ -366,7 +366,7 @@ int StyleModel::columnCount( QModelIndex const&) 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())
|
||||
return QVariant();
|
||||
node * cur_node = static_cast<node*>(index.internalPointer());
|
||||
|
|
|
@ -85,6 +85,7 @@ namespace mapnik {
|
|||
agg::row_ptr_cache<agg::int8u> buf_;
|
||||
agg::pixfmt_rgba32 pixf_;
|
||||
CoordTransform t_;
|
||||
freetype_engine font_engine_;
|
||||
face_manager<freetype_engine> font_manager_;
|
||||
label_collision_detector4 detector_;
|
||||
placement_finder<label_collision_detector4> finder_;
|
||||
|
|
|
@ -144,7 +144,7 @@ namespace mapnik {
|
|||
{
|
||||
return scale_;
|
||||
}
|
||||
|
||||
|
||||
inline void forward(double * x, double * y) const
|
||||
{
|
||||
*x = (*x - extent_.minx()) * scale_ - offset_x_;
|
||||
|
@ -156,13 +156,13 @@ namespace mapnik {
|
|||
*x = extent_.minx() + (*x + offset_x_)/scale_;
|
||||
*y = extent_.maxy() - (*y + offset_y_)/scale_;
|
||||
}
|
||||
|
||||
|
||||
inline coord2d& forward(coord2d& c) const
|
||||
{
|
||||
forward(&c.x,&c.y);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
inline coord2d& backward(coord2d& c) const
|
||||
{
|
||||
backward(&c.x,&c.y);
|
||||
|
@ -208,6 +208,10 @@ namespace mapnik {
|
|||
}
|
||||
return coords;
|
||||
}
|
||||
inline Envelope<double> const& extent() const
|
||||
{
|
||||
return extent_;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -66,8 +66,7 @@ namespace mapnik
|
|||
public:
|
||||
feature_style_processor(Map const& m)
|
||||
: m_(m) {}
|
||||
|
||||
|
||||
|
||||
void apply()
|
||||
{
|
||||
#ifdef MAPNIK_DEBUG
|
||||
|
|
|
@ -33,24 +33,26 @@ extern "C"
|
|||
#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
|
||||
#include <mapnik/color.hpp>
|
||||
#include <mapnik/utils.hpp>
|
||||
#include <mapnik/ctrans.hpp>
|
||||
#include <mapnik/geometry.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
|
||||
{
|
||||
class font_face : boost::noncopyable
|
||||
|
@ -105,22 +107,20 @@ namespace mapnik
|
|||
FT_Face face_;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<font_face> face_ptr;
|
||||
|
||||
class MAPNIK_DECL freetype_engine : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>,
|
||||
private boost::noncopyable
|
||||
typedef boost::shared_ptr<font_face> face_ptr;
|
||||
class MAPNIK_DECL freetype_engine // : public mapnik::singleton<freetype_engine,mapnik::CreateStatic>,
|
||||
// private boost::noncopyable
|
||||
{
|
||||
friend class mapnik::CreateStatic<freetype_engine>;
|
||||
public:
|
||||
|
||||
// friend class mapnik::CreateStatic<freetype_engine>;
|
||||
public:
|
||||
static bool register_font(std::string const& file_name);
|
||||
static std::vector<std::string> face_names ();
|
||||
static face_ptr create_face(std::string const& family_name);
|
||||
|
||||
private:
|
||||
freetype_engine();
|
||||
face_ptr create_face(std::string const& family_name);
|
||||
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_;
|
||||
};
|
||||
|
||||
|
@ -129,8 +129,11 @@ namespace mapnik
|
|||
{
|
||||
typedef T font_engine_type;
|
||||
typedef std::map<std::string,face_ptr> faces;
|
||||
|
||||
|
||||
public:
|
||||
face_manager(T & engine)
|
||||
: engine_(engine) {}
|
||||
|
||||
face_ptr get_face(std::string const& name)
|
||||
{
|
||||
typename faces::iterator itr;
|
||||
|
@ -141,7 +144,7 @@ namespace mapnik
|
|||
}
|
||||
else
|
||||
{
|
||||
face_ptr face = font_engine_type::instance()->create_face(name);
|
||||
face_ptr face = engine_.create_face(name);
|
||||
if (face)
|
||||
{
|
||||
faces_.insert(make_pair(name,face));
|
||||
|
@ -151,6 +154,7 @@ namespace mapnik
|
|||
}
|
||||
private:
|
||||
faces faces_;
|
||||
font_engine_type & engine_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace mapnik
|
|||
|
||||
struct placement : boost::noncopyable
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
typedef coord_transform2<CoordTransform,geometry2d> path_type;
|
||||
|
||||
template <typename SymbolizerT>
|
||||
placement(string_info *info_,
|
||||
|
|
|
@ -62,14 +62,17 @@ namespace mapnik
|
|||
|
||||
struct MAPNIK_DECL building_symbolizer
|
||||
{
|
||||
explicit building_symbolizer()
|
||||
: fill_(Color(128,128,128)),
|
||||
opacity_(1.0) {}
|
||||
explicit building_symbolizer()
|
||||
: fill_(Color(128,128,128)),
|
||||
height_(0),
|
||||
opacity_(1.0)
|
||||
{}
|
||||
|
||||
building_symbolizer(Color const& fill)
|
||||
: fill_(fill),
|
||||
opacity_(1.0) {}
|
||||
|
||||
building_symbolizer(Color const& fill,double height)
|
||||
: fill_(fill),
|
||||
height_(height),
|
||||
opacity_(1.0) {}
|
||||
|
||||
Color const& get_fill() const
|
||||
{
|
||||
return fill_;
|
||||
|
@ -78,6 +81,14 @@ namespace mapnik
|
|||
{
|
||||
fill_ = fill;
|
||||
}
|
||||
double height() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
void set_height(double height)
|
||||
{
|
||||
height_=height;
|
||||
}
|
||||
void set_opacity(float opacity)
|
||||
{
|
||||
opacity_ = opacity;
|
||||
|
@ -88,6 +99,7 @@ namespace mapnik
|
|||
}
|
||||
private:
|
||||
Color fill_;
|
||||
double height_;
|
||||
float opacity_;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_pattern_filters_rgba.h"
|
||||
#include "agg_renderer_outline_image.h"
|
||||
#include "agg_vpgen_clip_polyline.h"
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/image_util.hpp>
|
||||
#include <mapnik/agg_renderer.hpp>
|
||||
|
@ -100,6 +102,8 @@ namespace mapnik
|
|||
buf_(pixmap_.raw_data(),width_,height_, width_ * 4),
|
||||
pixf_(buf_),
|
||||
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)),
|
||||
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_scanline_aa_solid<ren_base> renderer;
|
||||
|
||||
|
||||
ren_base renb(pixf_);
|
||||
Color const& fill_ = sym.get_fill();
|
||||
unsigned r=fill_.red();
|
||||
|
@ -207,7 +210,7 @@ namespace mapnik
|
|||
agg::scanline_u8 sl;
|
||||
ras_.reset();
|
||||
|
||||
int height = 60 << 8;
|
||||
double height = 0.7071 * sym.height(); // height in meters
|
||||
|
||||
for (unsigned i=0;i<feature.num_geometries();++i)
|
||||
{
|
||||
|
@ -215,12 +218,12 @@ namespace mapnik
|
|||
if (geom.num_points() > 2)
|
||||
{
|
||||
boost::scoped_ptr<geometry2d> frame(new line_string_impl);
|
||||
|
||||
boost::scoped_ptr<geometry2d> roof(new polygon_impl);
|
||||
std::deque<segment_t> face_segments;
|
||||
double x0(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;
|
||||
unsigned cm = geom.vertex(&x,&y);
|
||||
|
@ -251,7 +254,7 @@ namespace mapnik
|
|||
|
||||
path_type faces_path (t_,*faces,prj_trans);
|
||||
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);
|
||||
ras_.reset();
|
||||
|
||||
|
@ -602,6 +605,7 @@ namespace mapnik
|
|||
ren.set_halo_fill(sym.get_halo_fill());
|
||||
ren.set_halo_radius(sym.get_halo_radius());
|
||||
|
||||
Envelope<double> ext = t_.extent();
|
||||
string_info info(text);
|
||||
ren.get_string_info(&info);
|
||||
unsigned num_geom = feature.num_geometries();
|
||||
|
@ -610,9 +614,39 @@ namespace mapnik
|
|||
geometry2d const& geom = feature.get_geometry(i);
|
||||
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);
|
||||
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 y = text_placement.placements[ii].starting_y;
|
||||
|
|
|
@ -88,7 +88,12 @@ namespace mapnik
|
|||
throw std::runtime_error(string("Cannot load symbols: ") +
|
||||
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());
|
||||
|
||||
#ifdef MAPNIK_DEBUG
|
||||
|
|
|
@ -23,72 +23,78 @@
|
|||
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
freetype_engine::freetype_engine()
|
||||
{
|
||||
FT_Error error = FT_Init_FreeType( &library_ );
|
||||
if (error)
|
||||
{
|
||||
throw std::runtime_error("Failed to initialize FreeType2 library");
|
||||
}
|
||||
}
|
||||
freetype_engine::freetype_engine()
|
||||
{
|
||||
FT_Error error = FT_Init_FreeType( &library_ );
|
||||
if (error)
|
||||
{
|
||||
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()
|
||||
{
|
||||
FT_Done_FreeType(library_);
|
||||
}
|
||||
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);
|
||||
|
||||
bool freetype_engine::register_font(std::string const& file_name)
|
||||
{
|
||||
mutex::scoped_lock lock(mapnik::singleton<freetype_engine,
|
||||
mapnik::CreateStatic>::mutex_);
|
||||
//cerr << "freetype_engine::register_font() '" << file_name << "'" << endl;
|
||||
FT_Face face;
|
||||
FT_Error error = FT_New_Face (library_,file_name.c_str(),0,&face);
|
||||
if ( !error )
|
||||
{
|
||||
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 );
|
||||
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_;
|
||||
if (!error)
|
||||
{
|
||||
return face_ptr (new font_face(face));
|
||||
}
|
||||
}
|
||||
return face_ptr();
|
||||
}
|
||||
|
||||
//FT_Library freetype_engine::library_;
|
||||
boost::mutex freetype_engine::mutex_;
|
||||
std::map<std::string,std::string> freetype_engine::name2file_;
|
||||
}
|
||||
|
|
|
@ -53,32 +53,35 @@ using std::endl;
|
|||
|
||||
namespace mapnik
|
||||
{
|
||||
using boost::optional;
|
||||
using boost::optional;
|
||||
|
||||
class map_parser {
|
||||
public:
|
||||
map_parser( bool strict ) : strict_( strict ) {};
|
||||
|
||||
void parse_map( Map & map, ptree const & sty);
|
||||
private:
|
||||
void parse_style( Map & map, ptree const & sty);
|
||||
void parse_layer( Map & map, ptree const & lay);
|
||||
|
||||
void parse_rule( feature_type_style & style, ptree const & r);
|
||||
|
||||
void parse_point_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_line_pattern_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_polygon_pattern_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_text_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_shield_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 parse_building_symbolizer( rule_type & rule, ptree const & sym );
|
||||
|
||||
void ensure_font_face( const text_symbolizer & text_symbol );
|
||||
|
||||
bool strict_;
|
||||
face_manager<freetype_engine> font_manager_;
|
||||
class map_parser : boost::noncopyable {
|
||||
public:
|
||||
map_parser( bool strict ) :
|
||||
strict_( strict ),
|
||||
font_manager_(font_engine_) {}
|
||||
|
||||
void parse_map( Map & map, ptree const & sty);
|
||||
private:
|
||||
void parse_style( Map & map, ptree const & sty);
|
||||
void parse_layer( Map & map, ptree const & lay);
|
||||
|
||||
void parse_rule( feature_type_style & style, ptree const & r);
|
||||
|
||||
void parse_point_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_line_pattern_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_polygon_pattern_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_text_symbolizer( rule_type & rule, ptree const & sym);
|
||||
void parse_shield_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 parse_building_symbolizer( rule_type & rule, ptree const & sym );
|
||||
|
||||
void ensure_font_face( const text_symbolizer & text_symbol );
|
||||
|
||||
bool strict_;
|
||||
freetype_engine font_engine_;
|
||||
face_manager<freetype_engine> font_manager_;
|
||||
};
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ namespace mapnik
|
|||
old_y = new_y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return total_distance_;
|
||||
}
|
||||
|
||||
|
@ -213,15 +213,20 @@ namespace mapnik
|
|||
|
||||
int num_labels = 0;
|
||||
if (p->label_spacing && p->label_placement == LINE_PLACEMENT)
|
||||
{
|
||||
num_labels = static_cast<int> (floor(distance / (p->label_spacing + string_width)));
|
||||
}
|
||||
else if (p->label_spacing && p->label_placement == POINT_PLACEMENT)
|
||||
{
|
||||
num_labels = static_cast<int> (floor(distance / p->label_spacing));
|
||||
|
||||
}
|
||||
|
||||
if (p->force_odd_labels && num_labels%2 == 0)
|
||||
num_labels--;
|
||||
if (num_labels <= 0)
|
||||
num_labels = 1;
|
||||
|
||||
|
||||
|
||||
double ideal_spacing = distance/num_labels;
|
||||
|
||||
double middle; //try draw text centered
|
||||
|
|
Loading…
Reference in a new issue