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
- 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
>>>

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('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')

View file

@ -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");

View file

@ -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

View file

@ -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 );

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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:

View file

@ -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());

View file

@ -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_;

View file

@ -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_;
}
};
}

View file

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

View file

@ -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>

View file

@ -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_,

View file

@ -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_;
};
}

View file

@ -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;

View file

@ -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

View file

@ -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_;
}

View file

@ -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);
}

View file

@ -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