Simplify code by always returning the same data type no matter what placement type is used.
This commit is contained in:
parent
b062af211a
commit
2b6cc00806
9 changed files with 209 additions and 114 deletions
|
@ -1,3 +1,24 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef MAPNIK_PATH_PROCESSOR_HPP
|
||||
#define MAPNIK_PATH_PROCESSOR_HPP
|
||||
|
||||
|
|
|
@ -58,14 +58,13 @@ public:
|
|||
/** Return next placement.
|
||||
* If no more placements are found false is returned.
|
||||
*/
|
||||
glyph_positions_ptr next();
|
||||
placements_list const& get();
|
||||
|
||||
protected:
|
||||
glyph_positions_ptr next_point_placement();
|
||||
glyph_positions_ptr next_line_placement();
|
||||
bool next_point_placement();
|
||||
bool next_line_placement();
|
||||
void initialize_geometries();
|
||||
void initialize_points();
|
||||
void update_detector(glyph_positions_ptr glyphs);
|
||||
|
||||
//Input
|
||||
text_symbolizer const& sym_;
|
||||
|
|
|
@ -25,14 +25,11 @@
|
|||
//mapnik
|
||||
#include <mapnik/box2d.hpp>
|
||||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/text/glyph_info.hpp>
|
||||
#include <mapnik/text/layout.hpp>
|
||||
#include <mapnik/text_placements/base.hpp>
|
||||
#include <mapnik/expression_evaluator.hpp>
|
||||
#include <mapnik/text/placements_list.hpp>
|
||||
|
||||
//stl
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
//boost
|
||||
#include <boost/utility.hpp>
|
||||
|
@ -47,48 +44,6 @@ typedef label_collision_detector4 DetectorType;
|
|||
class feature_impl;
|
||||
typedef feature_impl Feature;
|
||||
|
||||
struct glyph_position
|
||||
{
|
||||
glyph_position(glyph_info const& glyph, pixel_position const& pos, double angle)
|
||||
: glyph(&glyph), pos(pos), angle(angle) { }
|
||||
glyph_info const* glyph;
|
||||
pixel_position pos;
|
||||
double angle;
|
||||
};
|
||||
|
||||
/** Stores positions of glphys.
|
||||
*
|
||||
* The actual glyphs and their format is stored in text_layout.
|
||||
*/
|
||||
class glyph_positions
|
||||
{
|
||||
public:
|
||||
typedef std::vector<glyph_position>::const_iterator const_iterator;
|
||||
glyph_positions();
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
void push_back(glyph_info const& glyph, pixel_position offset, double angle);
|
||||
|
||||
/** Is each character rotated by the same angle?
|
||||
* This function is used to avoid costly trigonometric function calls when not necessary. */
|
||||
bool is_constant_angle() const;
|
||||
double get_angle() const;
|
||||
|
||||
pixel_position const& get_base_point() const;
|
||||
void set_base_point(pixel_position base_point);
|
||||
private:
|
||||
std::vector<glyph_position> data_;
|
||||
pixel_position base_point_;
|
||||
double angle_;
|
||||
bool const_angle_;
|
||||
};
|
||||
typedef boost::shared_ptr<glyph_positions> glyph_positions_ptr;
|
||||
|
||||
typedef std::list<glyph_positions_ptr> placements_list;
|
||||
typedef boost::shared_ptr<placements_list> placements_list_ptr;
|
||||
|
||||
class placement_finder_ng : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
@ -100,15 +55,17 @@ public:
|
|||
double scale_factor);
|
||||
|
||||
/** Try to place a single label at the given point. */
|
||||
glyph_positions_ptr find_point_placement(pixel_position pos);
|
||||
bool find_point_placement(pixel_position pos);
|
||||
/** Iterate over the given path, placing line-following labels with respect to label_spacing. */
|
||||
template <typename T>
|
||||
placements_list_ptr find_line_placements(T & path);
|
||||
bool find_line_placements(T & path);
|
||||
/** Iterate over the given path, placing point labels with respect to label_spacing. */
|
||||
template <typename T>
|
||||
placements_list_ptr find_point_on_line_placements(T & path);
|
||||
bool find_point_on_line_placements(T & path);
|
||||
/** Try next position alternative from placement_info. */
|
||||
bool next_position();
|
||||
|
||||
placements_list const& placements() const;
|
||||
private:
|
||||
void init_alignment();
|
||||
pixel_position alignment_offset() const;
|
||||
|
@ -127,6 +84,8 @@ private:
|
|||
horizontal_alignment_e halign_;
|
||||
justify_alignment_e jalign_;
|
||||
double scale_factor_;
|
||||
|
||||
placements_list placements_;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<placement_finder_ng> placement_finder_ng_ptr;
|
||||
|
|
94
include/mapnik/text/placements_list.hpp
Normal file
94
include/mapnik/text/placements_list.hpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef MAPNIK_PLACEMENTS_LIST_HPP
|
||||
#define MAPNIK_PLACEMENTS_LIST_HPP
|
||||
//mapnik
|
||||
#include <mapnik/box2d.hpp>
|
||||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/text/glyph_info.hpp>
|
||||
|
||||
//stl
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
struct glyph_info;
|
||||
|
||||
struct glyph_position
|
||||
{
|
||||
glyph_position(glyph_info const& glyph, pixel_position const& pos, double angle)
|
||||
: glyph(&glyph), pos(pos), angle(angle) { }
|
||||
glyph_info const* glyph;
|
||||
pixel_position pos;
|
||||
double angle;
|
||||
};
|
||||
|
||||
/** Stores positions of glphys.
|
||||
*
|
||||
* The actual glyphs and their format is stored in text_layout.
|
||||
*/
|
||||
class glyph_positions
|
||||
{
|
||||
public:
|
||||
typedef std::vector<glyph_position>::const_iterator const_iterator;
|
||||
glyph_positions();
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
void push_back(glyph_info const& glyph, pixel_position offset, double angle);
|
||||
|
||||
/** Is each character rotated by the same angle?
|
||||
* This function is used to avoid costly trigonometric function calls when not necessary. */
|
||||
bool is_constant_angle() const;
|
||||
double get_angle() const;
|
||||
|
||||
pixel_position const& get_base_point() const;
|
||||
void set_base_point(pixel_position base_point);
|
||||
private:
|
||||
std::vector<glyph_position> data_;
|
||||
pixel_position base_point_;
|
||||
double angle_;
|
||||
bool const_angle_;
|
||||
};
|
||||
typedef boost::shared_ptr<glyph_positions> glyph_positions_ptr;
|
||||
|
||||
#if 0
|
||||
class placements_list
|
||||
{
|
||||
public:
|
||||
placements_list();
|
||||
void push_back(glyph_positions_ptr glyphs);
|
||||
typedef std::list<glyph_positions_ptr> list_type;
|
||||
typedef list_type::const_iterator const_iterator;
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
private:
|
||||
list_type placements_;
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef std::list<glyph_positions_ptr> placements_list;
|
||||
}
|
||||
#endif // PLACEMENTS_LIST_HPP
|
|
@ -25,6 +25,7 @@
|
|||
#include <mapnik/agg_rasterizer.hpp>
|
||||
#include <mapnik/symbolizer_helpers.hpp>
|
||||
#include <mapnik/text/renderer.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
|
@ -43,8 +44,8 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
|
||||
text_renderer<T> ren(*current_buffer_, font_manager_, sym.comp_op(), scale_factor_);
|
||||
|
||||
glyph_positions_ptr glyphs;
|
||||
while ((glyphs = helper.next()))
|
||||
placements_list const& placements = helper.get();
|
||||
BOOST_FOREACH(glyph_positions_ptr glyphs, placements)
|
||||
{
|
||||
ren.render(glyphs);
|
||||
}
|
||||
|
|
|
@ -1485,8 +1485,8 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
|
|||
cairo_context context(context_);
|
||||
context.set_operator(sym.comp_op());
|
||||
|
||||
glyph_positions_ptr glyphs;
|
||||
while ((glyphs = helper.next()))
|
||||
placements_list const& placements = helper.get();
|
||||
BOOST_FOREACH(glyph_positions_ptr glyphs, placements)
|
||||
{
|
||||
context.add_text(glyphs, face_manager_, font_manager_, scale_factor_);
|
||||
}
|
||||
|
|
|
@ -50,23 +50,28 @@ text_symbolizer_helper<FaceManagerT, DetectorT>::text_symbolizer_helper(const te
|
|||
}
|
||||
|
||||
template <typename FaceManagerT, typename DetectorT>
|
||||
glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next()
|
||||
placements_list const& text_symbolizer_helper<FaceManagerT, DetectorT>::get()
|
||||
{
|
||||
if (point_placement_)
|
||||
return next_point_placement();
|
||||
{
|
||||
while (next_point_placement());
|
||||
}
|
||||
else
|
||||
return next_line_placement();
|
||||
{
|
||||
while (next_line_placement());
|
||||
}
|
||||
return finder_.placements();
|
||||
}
|
||||
|
||||
template <typename FaceManagerT, typename DetectorT>
|
||||
glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
|
||||
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
|
||||
{
|
||||
while (!geometries_to_process_.empty())
|
||||
{
|
||||
if (geo_itr_ == geometries_to_process_.end())
|
||||
{
|
||||
//Just processed the last geometry. Try next placement.
|
||||
if (!finder_.next_position()) return glyph_positions_ptr(); //No more placements
|
||||
if (!finder_.next_position()) return false; //No more placements
|
||||
//Start again from begin of list
|
||||
geo_itr_ = geometries_to_process_.begin();
|
||||
continue; //Reexecute size check
|
||||
|
@ -79,51 +84,43 @@ glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_p
|
|||
clipped.clip_box(query_extent_.minx(), query_extent_.miny(),
|
||||
query_extent_.maxx(), query_extent_.maxy());
|
||||
path_type path(t_, clipped, prj_trans_);
|
||||
glyph_positions_ptr glyphs;
|
||||
bool success;
|
||||
if (points_on_line_) {
|
||||
#if 0
|
||||
finder_.find_point_on_line_placements(path);
|
||||
#endif
|
||||
success = finder_.find_point_on_line_placements(path);
|
||||
} else {
|
||||
glyphs = finder_.find_line_placements(path);
|
||||
success = finder_.find_line_placements(path);
|
||||
}
|
||||
if (glyphs)
|
||||
if (success)
|
||||
{
|
||||
//Found a placement
|
||||
#if 0
|
||||
if (points_on_line_)
|
||||
{
|
||||
finder_->update_detector();
|
||||
}
|
||||
|
||||
geo_itr_ = geometries_to_process_.erase(geo_itr_);
|
||||
#if 0
|
||||
if (writer_.first) writer_.first->add_text(
|
||||
finder_->get_results(), finder_->get_extents(),
|
||||
feature_, t_, writer_.second);
|
||||
#endif
|
||||
return glyphs;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
//No placement for this geometry. Keep it in geometries_to_process_ for next try.
|
||||
geo_itr_++;
|
||||
}
|
||||
return glyph_positions_ptr();
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename FaceManagerT, typename DetectorT>
|
||||
glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
|
||||
bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
|
||||
{
|
||||
while (!points_.empty())
|
||||
{
|
||||
if (point_itr_ == points_.end())
|
||||
{
|
||||
//Just processed the last point. Try next placement.
|
||||
if (!finder_.next_position()) return glyph_positions_ptr(); //No more placements
|
||||
if (!finder_.next_position()) return false; //No more placements
|
||||
//Start again from begin of list
|
||||
point_itr_ = points_.begin();
|
||||
continue; //Reexecute size check
|
||||
}
|
||||
glyph_positions_ptr glyphs = finder_.find_point_placement(*point_itr_);
|
||||
if (glyphs)
|
||||
if (finder_.find_point_placement(*point_itr_))
|
||||
{
|
||||
//Found a placement
|
||||
point_itr_ = points_.erase(point_itr_);
|
||||
|
@ -132,13 +129,12 @@ glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_
|
|||
finder_->get_results(), finder_->get_extents(),
|
||||
feature_, t_, writer_.second);
|
||||
#endif
|
||||
update_detector(glyphs);
|
||||
return glyphs;
|
||||
return true;
|
||||
}
|
||||
//No placement for this point. Keep it in points_ for next try.
|
||||
point_itr_++;
|
||||
}
|
||||
return glyph_positions_ptr();
|
||||
return false;
|
||||
}
|
||||
|
||||
struct largest_bbox_first
|
||||
|
@ -245,14 +241,6 @@ void text_symbolizer_helper<FaceManagerT, DetectorT>::initialize_points()
|
|||
point_itr_ = points_.begin();
|
||||
}
|
||||
|
||||
template <typename FaceManagerT, typename DetectorT>
|
||||
void text_symbolizer_helper<FaceManagerT, DetectorT>::update_detector(glyph_positions_ptr glyphs)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
@ -294,8 +282,7 @@ bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
|
|||
pixel_position const& text_disp = placement_->properties.displacement;
|
||||
pixel_position label_pos = *point_itr_ + shield_pos;
|
||||
|
||||
glyph_positions_ptr glyphs = finder_.find_point_placement(label_pos);
|
||||
if (!glyphs)
|
||||
if (!finder_.find_point_placement(label_pos))
|
||||
{
|
||||
//No placement for this point. Keep it in points_ for next try.
|
||||
point_itr_++;
|
||||
|
@ -325,7 +312,6 @@ bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
|
|||
if (placement_->properties.allow_overlap || detector_.has_placement(marker_ext_))
|
||||
{
|
||||
detector_.insert(marker_ext_);
|
||||
this->update_detector(glyphs);
|
||||
#if 0
|
||||
if (writer_.first) {
|
||||
writer_.first->add_box(marker_ext_, feature_, t_, writer_.second);
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
#include <mapnik/text/placement_finder_ng.hpp>
|
||||
#include <mapnik/text/layout.hpp>
|
||||
#include <mapnik/text_properties.hpp>
|
||||
#include <mapnik/text/placements_list.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
#include <mapnik/label_collision_detector.hpp>
|
||||
#include <mapnik/ctrans.hpp>
|
||||
#include <mapnik/path_processor.hpp>
|
||||
#include <mapnik/expression_evaluator.hpp>
|
||||
|
||||
//boost
|
||||
#include <boost/make_shared.hpp>
|
||||
|
@ -38,7 +40,7 @@ namespace mapnik
|
|||
{
|
||||
|
||||
placement_finder_ng::placement_finder_ng(Feature const& feature, DetectorType &detector, box2d<double> const& extent, text_placement_info_ptr placement_info, face_manager_freetype &font_manager, double scale_factor)
|
||||
: feature_(feature), detector_(detector), extent_(extent), layout_(font_manager), info_(placement_info), valid_(true), scale_factor_(scale_factor)
|
||||
: feature_(feature), detector_(detector), extent_(extent), layout_(font_manager), info_(placement_info), valid_(true), scale_factor_(scale_factor), placements_()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -73,6 +75,11 @@ bool placement_finder_ng::next_position()
|
|||
return true;
|
||||
}
|
||||
|
||||
const placements_list &placement_finder_ng::placements() const
|
||||
{
|
||||
return placements_;
|
||||
}
|
||||
|
||||
|
||||
void placement_finder_ng::init_alignment()
|
||||
{
|
||||
|
@ -163,11 +170,10 @@ static pixel_position rotate(pixel_position pos, double sina, double cosa)
|
|||
}
|
||||
|
||||
|
||||
glyph_positions_ptr placement_finder_ng::find_point_placement(pixel_position pos)
|
||||
bool placement_finder_ng::find_point_placement(pixel_position pos)
|
||||
{
|
||||
if (!layout_.size()) return true; //No text => placement always succeeds.
|
||||
glyph_positions_ptr glyphs = boost::make_shared<glyph_positions>();
|
||||
if (!layout_.size()) return glyphs; /* No data. Don't return NULL pointer, which would mean
|
||||
that not enough space was available. */
|
||||
|
||||
pixel_position displacement = scale_factor_ * info_->properties.displacement + alignment_offset();
|
||||
if (info_->properties.rotate_displacement) displacement = rotate(displacement, sina_, cosa_);
|
||||
|
@ -181,7 +187,7 @@ glyph_positions_ptr placement_finder_ng::find_point_placement(pixel_position pos
|
|||
(!info_->properties.allow_overlap &&
|
||||
!detector_.has_point_placement(bbox, info_->properties.minimum_distance * scale_factor_)))
|
||||
{
|
||||
return glyph_positions_ptr(); //Not enough space for this text
|
||||
return false; //Not enough space for this text
|
||||
}
|
||||
detector_.insert(bbox, layout_.get_text());
|
||||
|
||||
|
@ -218,20 +224,19 @@ glyph_positions_ptr placement_finder_ng::find_point_placement(pixel_position pos
|
|||
x += glyph_itr->width + glyph_itr->format->character_spacing;
|
||||
}
|
||||
}
|
||||
return glyphs;
|
||||
placements_.push_back(glyphs);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
placements_list_ptr placement_finder_ng::find_point_on_line_placements(T & path)
|
||||
bool placement_finder_ng::find_point_on_line_placements(T & path)
|
||||
{
|
||||
path_processor<T> pp(path);
|
||||
placements_list_ptr list = boost::make_shared<placements_list>();
|
||||
if (!pp.valid() || !layout_.size()) return list;
|
||||
if (!pp.valid() || !layout_.size()) return true;
|
||||
if (pp.length() == 0.0)
|
||||
{
|
||||
list->push_back(find_point_placement(pp.current_point()));
|
||||
return list;
|
||||
return find_point_placement(pp.current_point());
|
||||
}
|
||||
|
||||
int num_labels = 1;
|
||||
|
@ -245,17 +250,18 @@ placements_list_ptr placement_finder_ng::find_point_on_line_placements(T & path)
|
|||
|
||||
double spacing = pp.length() / num_labels;
|
||||
pp.skip(spacing/2.); // first label should be placed at half the spacing
|
||||
bool success = false;
|
||||
do
|
||||
{
|
||||
list->push_back(find_point_placement(pp.current_point()));
|
||||
success = find_point_placement(pp.current_point()) || success;
|
||||
} while (pp.skip(spacing));
|
||||
return list;
|
||||
return success;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
placements_list_ptr placement_finder_ng::find_line_placements(T & path)
|
||||
bool placement_finder_ng::find_line_placements(T & path)
|
||||
{
|
||||
return placements_list_ptr();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -316,10 +322,10 @@ void glyph_positions::set_base_point(pixel_position base_point)
|
|||
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;
|
||||
typedef coord_transform<CoordTransform,clipped_geometry_type> ClippedPathType;
|
||||
typedef coord_transform<CoordTransform,geometry_type> PathType;
|
||||
template placements_list_ptr placement_finder_ng::find_point_on_line_placements<ClippedPathType>(ClippedPathType &);
|
||||
template placements_list_ptr placement_finder_ng::find_line_placements<ClippedPathType>(ClippedPathType &);
|
||||
template placements_list_ptr placement_finder_ng::find_point_on_line_placements<PathType>(PathType &);
|
||||
template placements_list_ptr placement_finder_ng::find_line_placements<PathType>(PathType &);
|
||||
template bool placement_finder_ng::find_point_on_line_placements<ClippedPathType>(ClippedPathType &);
|
||||
template bool placement_finder_ng::find_line_placements<ClippedPathType>(ClippedPathType &);
|
||||
template bool placement_finder_ng::find_point_on_line_placements<PathType>(PathType &);
|
||||
template bool placement_finder_ng::find_line_placements<PathType>(PathType &);
|
||||
|
||||
|
||||
}// ns mapnik
|
||||
|
|
29
src/text/placements_list.cpp
Normal file
29
src/text/placements_list.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <mapnik/text/placements_list.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue