Add support for multiple placements.
NOTE: In some places indention is not updated to keep this patch readable. This will be fixed in the next revision.
This commit is contained in:
parent
8ca85c95c6
commit
4af0696b9d
13 changed files with 507 additions and 86 deletions
|
@ -168,9 +168,10 @@ void export_text_symbolizer()
|
|||
.value("INTERIOR_PLACEMENT",INTERIOR_PLACEMENT)
|
||||
;
|
||||
enumeration_<vertical_alignment_e>("vertical_alignment")
|
||||
.value("TOP",TOP)
|
||||
.value("MIDDLE",MIDDLE)
|
||||
.value("BOTTOM",BOTTOM)
|
||||
.value("TOP",V_TOP)
|
||||
.value("MIDDLE",V_MIDDLE)
|
||||
.value("BOTTOM",V_BOTTOM)
|
||||
.value("AUTO",V_AUTO)
|
||||
;
|
||||
|
||||
enumeration_<horizontal_alignment_e>("horizontal_alignment")
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <mapnik/shield_symbolizer.hpp>
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/text_path.hpp>
|
||||
#include <mapnik/text_placements.hpp>
|
||||
|
||||
#include <queue>
|
||||
|
||||
|
@ -41,9 +42,9 @@ typedef text_path placement_element;
|
|||
|
||||
struct placement : boost::noncopyable
|
||||
{
|
||||
placement(string_info & info_, shield_symbolizer const& sym, double scale_factor, unsigned w, unsigned h, bool has_dimensions_= false);
|
||||
placement(string_info & info_, shield_symbolizer const& sym, text_placement_info_ptr placement_option, double scale_factor, unsigned w, unsigned h, bool has_dimensions_= false);
|
||||
|
||||
placement(string_info & info_, text_symbolizer const& sym, double scale_factor);
|
||||
placement(string_info & info_, text_symbolizer const& sym, text_placement_info_ptr placement_option, double scale_factor);
|
||||
|
||||
~placement();
|
||||
|
||||
|
@ -87,7 +88,7 @@ public:
|
|||
placement_finder(DetectorT & detector, box2d<double> const& extent);
|
||||
|
||||
//Try place a single label at the given point
|
||||
void find_point_placement(placement & p, double pos_x, double pos_y, double angle=0.0, vertical_alignment_e = MIDDLE, unsigned line_spacing=0, unsigned character_spacing=0, horizontal_alignment_e = H_MIDDLE, justify_alignment_e = J_MIDDLE);
|
||||
void find_point_placement(placement & p, double pos_x, double pos_y, double angle=0.0, vertical_alignment_e = V_MIDDLE, unsigned line_spacing=0, unsigned character_spacing=0, horizontal_alignment_e = H_MIDDLE, justify_alignment_e = J_MIDDLE);
|
||||
|
||||
//Iterate over the given path, placing point labels with respect to label_spacing
|
||||
template <typename T>
|
||||
|
|
95
include/mapnik/text_placements.hpp
Normal file
95
include/mapnik/text_placements.hpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 Hermann Kraus
|
||||
*
|
||||
* 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 TEXT_PLACEMENTS_HPP
|
||||
#define TEXT_PLACEMENTS_HPP
|
||||
|
||||
//stl
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
//boost
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
typedef boost::tuple<double,double> position;
|
||||
|
||||
class text_placement_info
|
||||
{
|
||||
public:
|
||||
/** Get next placement.
|
||||
* This function is also called before the first placement is tried. */
|
||||
virtual bool next()=0;
|
||||
/** Get next placement position.
|
||||
* This function is also called before the first position is used.
|
||||
* Each class has to return at least one position!
|
||||
* If this functions returns false the placement data should be considered invalid!
|
||||
*/
|
||||
virtual bool next_position_only()=0;
|
||||
|
||||
/* NOTE: Values are public and non-virtual to avoid any performance problems. */
|
||||
position displacement;
|
||||
unsigned text_size;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<text_placement_info> text_placement_info_ptr;
|
||||
|
||||
class text_placements
|
||||
{
|
||||
public:
|
||||
text_placements() : text_size_(10) {}
|
||||
virtual text_placement_info_ptr get_placement_info() const =0;
|
||||
virtual void set_default_text_size(unsigned size) { text_size_ = size; }
|
||||
unsigned get_default_text_size() const { return text_size_; }
|
||||
virtual void set_default_displacement(position const& displacement) { displacement_ = displacement;}
|
||||
position const& get_default_displacement() { return displacement_; }
|
||||
protected:
|
||||
unsigned text_size_;
|
||||
position displacement_;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<text_placements> text_placements_ptr;
|
||||
|
||||
class text_placements_dummy;
|
||||
class text_placement_info_dummy : public text_placement_info
|
||||
{
|
||||
public:
|
||||
text_placement_info_dummy(text_placements_dummy const* parent) : state(0), position_state(0), parent_(parent) {}
|
||||
bool next();
|
||||
bool next_position_only();
|
||||
private:
|
||||
unsigned state;
|
||||
unsigned position_state;
|
||||
text_placements_dummy const* parent_;
|
||||
};
|
||||
|
||||
class text_placements_dummy: public text_placements
|
||||
{
|
||||
public:
|
||||
text_placement_info_ptr get_placement_info() const;
|
||||
friend class text_placement_info_dummy;
|
||||
};
|
||||
|
||||
} //namespace
|
||||
|
||||
#endif // TEXT_PLACEMENTS_HPP
|
73
include/mapnik/text_placements_simple.hpp
Normal file
73
include/mapnik/text_placements_simple.hpp
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 Hermann Kraus
|
||||
*
|
||||
* 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 TEXT_PLACEMENTS_SIMPLE_HPP
|
||||
#define TEXT_PLACEMENTS_SIMPLE_HPP
|
||||
#include <mapnik/text_placements.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
class text_placements_simple;
|
||||
|
||||
typedef enum {
|
||||
NORTH,
|
||||
EAST,
|
||||
SOUTH,
|
||||
WEST,
|
||||
NORTHEAST,
|
||||
SOUTHEAST,
|
||||
NORTHWEST,
|
||||
SOUTHWEST,
|
||||
EXACT_POSITION,
|
||||
} directions_t;
|
||||
|
||||
/** Simple placement strategy.
|
||||
* See parent class for documentation of each function. */
|
||||
class text_placement_info_simple : public text_placement_info
|
||||
{
|
||||
public:
|
||||
text_placement_info_simple(text_placements_simple const* parent) : state(0), position_state(0), parent_(parent) {}
|
||||
bool next();
|
||||
bool next_position_only();
|
||||
private:
|
||||
unsigned state;
|
||||
unsigned position_state;
|
||||
text_placements_simple const* parent_;
|
||||
};
|
||||
|
||||
|
||||
/** Automatically generates placement options from a user selected list of directions and text sizes. */
|
||||
class text_placements_simple: public text_placements
|
||||
{
|
||||
public:
|
||||
text_placements_simple();
|
||||
text_placements_simple(std::string positions);
|
||||
text_placement_info_ptr get_placement_info() const;
|
||||
void set_positions(std::string positions);
|
||||
private:
|
||||
std::string positions_;
|
||||
std::vector<directions_t> direction_;
|
||||
std::vector<int> text_sizes_;
|
||||
friend class text_placement_info_simple;
|
||||
};
|
||||
|
||||
} //namespace
|
||||
#endif
|
|
@ -32,9 +32,9 @@
|
|||
#include <mapnik/graphics.hpp>
|
||||
#include <mapnik/filter_factory.hpp>
|
||||
#include <mapnik/symbolizer.hpp>
|
||||
#include <mapnik/text_placements.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
// stl
|
||||
#include <string>
|
||||
|
@ -53,9 +53,10 @@ DEFINE_ENUM( label_placement_e, label_placement_enum );
|
|||
|
||||
enum vertical_alignment
|
||||
{
|
||||
TOP = 0,
|
||||
MIDDLE,
|
||||
BOTTOM,
|
||||
V_TOP = 0,
|
||||
V_MIDDLE,
|
||||
V_BOTTOM,
|
||||
V_AUTO,
|
||||
vertical_alignment_MAX
|
||||
};
|
||||
|
||||
|
@ -66,6 +67,7 @@ enum horizontal_alignment
|
|||
H_LEFT = 0,
|
||||
H_MIDDLE,
|
||||
H_RIGHT,
|
||||
H_AUTO,
|
||||
horizontal_alignment_MAX
|
||||
};
|
||||
|
||||
|
@ -92,13 +94,14 @@ enum text_transform
|
|||
|
||||
DEFINE_ENUM( text_transform_e, text_transform );
|
||||
|
||||
typedef boost::tuple<double,double> position;
|
||||
|
||||
struct MAPNIK_DECL text_symbolizer : public symbolizer_base
|
||||
{
|
||||
text_symbolizer(expression_ptr name, std::string const& face_name,
|
||||
unsigned size, color const& fill);
|
||||
text_symbolizer(expression_ptr name, unsigned size, color const& fill);
|
||||
unsigned size, color const& fill,
|
||||
text_placements_ptr placements = text_placements_ptr(new text_placements_dummy()));
|
||||
text_symbolizer(expression_ptr name, unsigned size, color const& fill,
|
||||
text_placements_ptr placements = text_placements_ptr(new text_placements_dummy()));
|
||||
text_symbolizer(text_symbolizer const& rhs);
|
||||
text_symbolizer& operator=(text_symbolizer const& rhs);
|
||||
expression_ptr get_name() const;
|
||||
|
@ -165,13 +168,14 @@ struct MAPNIK_DECL text_symbolizer : public symbolizer_base
|
|||
horizontal_alignment_e get_horizontal_alignment() const;
|
||||
void set_justify_alignment(justify_alignment_e valign);
|
||||
justify_alignment_e get_justify_alignment() const;
|
||||
text_placements_ptr get_placement_options() const;
|
||||
void set_placement_options(text_placements_ptr placement_options);
|
||||
|
||||
private:
|
||||
expression_ptr name_;
|
||||
expression_ptr orientation_;
|
||||
std::string face_name_;
|
||||
font_set fontset_;
|
||||
unsigned size_;
|
||||
unsigned text_ratio_;
|
||||
unsigned wrap_width_;
|
||||
unsigned char wrap_char_;
|
||||
|
@ -188,7 +192,6 @@ private:
|
|||
label_placement_e label_p_;
|
||||
vertical_alignment_e valign_;
|
||||
position anchor_;
|
||||
position displacement_;
|
||||
bool avoid_edges_;
|
||||
double minimum_distance_;
|
||||
double minimum_padding_;
|
||||
|
@ -197,6 +200,7 @@ private:
|
|||
bool wrap_before_;
|
||||
horizontal_alignment_e halign_;
|
||||
justify_alignment_e jalign_;
|
||||
text_placements_ptr placement_options_;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ source = Split(
|
|||
glyph_symbolizer.cpp
|
||||
markers_symbolizer.cpp
|
||||
metawriter.cpp
|
||||
text_placements.cpp
|
||||
wkt/wkt_factory.cpp
|
||||
"""
|
||||
)
|
||||
|
@ -302,4 +303,4 @@ if 'uninstall' not in COMMAND_LINE_TARGETS:
|
|||
|
||||
env['create_uninstall_target'](env, inc_target)
|
||||
env['create_uninstall_target'](env, svg_inc_target)
|
||||
env['create_uninstall_target'](env, wkt_inc_target)
|
||||
env['create_uninstall_target'](env, wkt_inc_target)
|
||||
|
|
|
@ -42,6 +42,11 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
|||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
|
||||
|
||||
text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info();
|
||||
placement_options->next();
|
||||
placement_options->next_position_only();
|
||||
|
||||
UnicodeString text;
|
||||
if( sym.get_no_text() )
|
||||
text = UnicodeString( " " ); // TODO: fix->use 'space' as the text to render
|
||||
|
@ -129,7 +134,7 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
|||
{
|
||||
// for every vertex, try and place a shield/text
|
||||
geom.rewind(0);
|
||||
placement text_placement(info, sym, scale_factor_, w, h, false);
|
||||
placement text_placement(info, sym, placement_options, scale_factor_, w, h, false);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
text_placement.allow_overlap = sym.get_allow_overlap();
|
||||
position const& pos = sym.get_displacement();
|
||||
|
@ -204,7 +209,7 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
|
|||
|
||||
else if (geom.num_points() > 1 && how_placed == LINE_PLACEMENT)
|
||||
{
|
||||
placement text_placement(info, sym, scale_factor_, w, h, true);
|
||||
placement text_placement(info, sym, placement_options, scale_factor_, w, h, true);
|
||||
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
finder.find_point_placements<path_type>(text_placement,path);
|
||||
|
|
|
@ -24,14 +24,6 @@
|
|||
// mapnik
|
||||
#include <mapnik/agg_renderer.hpp>
|
||||
#include <mapnik/agg_rasterizer.hpp>
|
||||
/*
|
||||
#include <mapnik/unicode.hpp>
|
||||
#include <mapnik/placement_finder.hpp>
|
||||
#include <mapnik/config_error.hpp>
|
||||
#include <mapnik/font_set.hpp>
|
||||
#include <mapnik/parse_path.hpp>
|
||||
#include <mapnik/text_path.hpp>
|
||||
*/
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
|
@ -42,6 +34,9 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
|
||||
bool placement_found = false;
|
||||
text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info();
|
||||
while (!placement_found && placement_options->next()) {
|
||||
expression_ptr name_expr = sym.get_name();
|
||||
if (!name_expr) return;
|
||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*name_expr);
|
||||
|
@ -79,7 +74,7 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
if (faces->size() > 0 && strk)
|
||||
{
|
||||
text_renderer<T> ren(pixmap_, faces, *strk);
|
||||
ren.set_pixel_size(sym.get_text_size() * scale_factor_);
|
||||
ren.set_pixel_size(placement_options->text_size * scale_factor_);
|
||||
ren.set_fill(fill);
|
||||
ren.set_halo_fill(sym.get_halo_fill());
|
||||
ren.set_halo_radius(sym.get_halo_radius() * scale_factor_);
|
||||
|
@ -95,9 +90,9 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
for (unsigned i=0;i<num_geom;++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
if (geom.num_points() > 0) // don't bother with empty geometries
|
||||
{
|
||||
placement text_placement(info,sym,scale_factor_);
|
||||
if (geom.num_points() == 0) continue; // don't bother with empty geometries
|
||||
while (!placement_found && placement_options->next_position_only()) {
|
||||
placement text_placement(info, sym, placement_options, scale_factor_);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT ||
|
||||
sym.get_label_placement() == INTERIOR_PLACEMENT)
|
||||
|
@ -132,12 +127,14 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
finder.find_line_placements<path_type>(text_placement,path);
|
||||
}
|
||||
|
||||
if (!text_placement.placements.size()) continue;
|
||||
placement_found = true;
|
||||
|
||||
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;
|
||||
box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
|
||||
ren.prepare_glyphs(&text_placement.placements[ii]);
|
||||
ren.render(x,y);
|
||||
}
|
||||
|
||||
|
@ -151,6 +148,7 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void agg_renderer<image_32>::process(text_symbolizer const&,
|
||||
|
|
|
@ -1074,6 +1074,10 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
|||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
|
||||
text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info();
|
||||
placement_options->next();
|
||||
placement_options->next_position_only();
|
||||
|
||||
UnicodeString text;
|
||||
if( sym.get_no_text() )
|
||||
text = UnicodeString( " " ); // TODO: fix->use 'space' as the text to render
|
||||
|
@ -1133,7 +1137,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
|||
|
||||
placement_finder<label_collision_detector4> finder(detector_);
|
||||
|
||||
faces->set_pixel_sizes(sym.get_text_size());
|
||||
faces->set_pixel_sizes(placement_options->text_size);
|
||||
faces->get_string_info(info);
|
||||
|
||||
int w = (*marker)->width();
|
||||
|
@ -1153,7 +1157,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
|||
{
|
||||
// for every vertex, try and place a shield/text
|
||||
geom.rewind(0);
|
||||
placement text_placement(info, sym, 1.0, w, h, false);
|
||||
placement text_placement(info, sym, placement_options, 1.0, w, h, false);
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
text_placement.allow_overlap = sym.get_allow_overlap();
|
||||
position const& pos = sym.get_displacement();
|
||||
|
@ -1216,7 +1220,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
|||
context.add_text(text_placement.placements[ii],
|
||||
face_manager_,
|
||||
faces,
|
||||
sym.get_text_size(),
|
||||
placement_options->text_size,
|
||||
sym.get_fill(),
|
||||
sym.get_halo_radius(),
|
||||
sym.get_halo_fill()
|
||||
|
@ -1234,7 +1238,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
|||
}
|
||||
else if (geom.num_points() > 1 && how_placed == LINE_PLACEMENT)
|
||||
{
|
||||
placement text_placement(info, sym, 1.0, w, h, true);
|
||||
placement text_placement(info, sym, placement_options, 1.0, w, h, true);
|
||||
|
||||
text_placement.avoid_edges = sym.get_avoid_edges();
|
||||
finder.find_point_placements<path_type>(text_placement, path);
|
||||
|
@ -1254,7 +1258,7 @@ void cairo_renderer_base::process(shield_symbolizer const& sym,
|
|||
context.add_text(text_placement.placements[ii],
|
||||
face_manager_,
|
||||
faces,
|
||||
sym.get_text_size(),
|
||||
placement_options->text_size,
|
||||
sym.get_fill(),
|
||||
sym.get_halo_radius(),
|
||||
sym.get_halo_fill()
|
||||
|
@ -1514,6 +1518,11 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
|
|||
proj_transform const& prj_trans)
|
||||
{
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
|
||||
bool placement_found = false;
|
||||
text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info();
|
||||
while (!placement_found && placement_options->next()) {
|
||||
|
||||
expression_ptr name_expr = sym.get_name();
|
||||
if (!name_expr) return;
|
||||
value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*name_expr);
|
||||
|
@ -1532,8 +1541,7 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
|
|||
text = text.toTitle(NULL);
|
||||
}
|
||||
|
||||
if (text.length() > 0)
|
||||
{
|
||||
if (text.length() <= 0) continue;
|
||||
face_set_ptr faces;
|
||||
|
||||
if (sym.get_fontset().size() > 0)
|
||||
|
@ -1550,7 +1558,7 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
|
|||
cairo_context context(context_);
|
||||
string_info info(text);
|
||||
|
||||
faces->set_pixel_sizes(sym.get_text_size());
|
||||
faces->set_pixel_sizes(placement_options->text_size);
|
||||
faces->get_string_info(info);
|
||||
|
||||
placement_finder<label_collision_detector4> finder(detector_);
|
||||
|
@ -1559,10 +1567,11 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
|
|||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
|
||||
if (geom.num_points() > 0) // don't bother with empty geometries
|
||||
if (geom.num_points() == 0) continue;// don't bother with empty geometries
|
||||
while (!placement_found && placement_options->next_position_only())
|
||||
{
|
||||
path_type path(t_, geom, prj_trans);
|
||||
placement text_placement(info, sym, 1.0);
|
||||
placement text_placement(info, sym, placement_options, 1.0);
|
||||
|
||||
if (sym.get_label_placement() == POINT_PLACEMENT ||
|
||||
sym.get_label_placement() == INTERIOR_PLACEMENT)
|
||||
|
@ -1594,13 +1603,15 @@ void cairo_renderer_base::process(text_symbolizer const& sym,
|
|||
{
|
||||
finder.find_line_placements<path_type>(text_placement, path);
|
||||
}
|
||||
if (!text_placement.placements.size()) continue;
|
||||
placement_found = true;
|
||||
|
||||
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii)
|
||||
{
|
||||
context.add_text(text_placement.placements[ii],
|
||||
face_manager_,
|
||||
faces,
|
||||
sym.get_text_size(),
|
||||
placement_options->text_size,
|
||||
sym.get_fill(),
|
||||
sym.get_halo_radius(),
|
||||
sym.get_halo_fill()
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
|
||||
#include <mapnik/metawriter_json.hpp>
|
||||
|
||||
#include <mapnik/text_placements_simple.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -1154,11 +1156,25 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym )
|
|||
<< "spacing,minimum-distance,minimum-padding,"
|
||||
<< "avoid-edges,allow-overlap,opacity,max-char-angle-delta,"
|
||||
<< "horizontal-alignment,justify-alignment,"
|
||||
<< "meta-writer,meta-output";
|
||||
<< "meta-writer,meta-output,"
|
||||
<< "placements,placement-type";
|
||||
|
||||
ensure_attrs(sym, "TextSymbolizer", s.str());
|
||||
try
|
||||
{
|
||||
text_placements_ptr placement_finder;
|
||||
optional<std::string> placement_type = get_opt_attr<std::string>(sym, "placement-type");
|
||||
if (placement_type) {
|
||||
if (*placement_type == "simple") {
|
||||
placement_finder = text_placements_ptr(
|
||||
new text_placements_simple(
|
||||
get_attr<std::string>(sym, "placements", "X")));
|
||||
}
|
||||
}
|
||||
if (!placement_finder) {
|
||||
placement_finder = text_placements_ptr(new text_placements_dummy());
|
||||
}
|
||||
|
||||
std::string name = get_attr<string>(sym, "name");
|
||||
|
||||
optional<std::string> face_name =
|
||||
|
@ -1171,7 +1187,7 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym )
|
|||
|
||||
color c = get_attr(sym, "fill", color(0,0,0));
|
||||
|
||||
text_symbolizer text_symbol = text_symbolizer(parse_expression(name, "utf8"), size, c);
|
||||
text_symbolizer text_symbol = text_symbolizer(parse_expression(name, "utf8"), size, c, placement_finder);
|
||||
|
||||
optional<std::string> orientation = get_opt_attr<std::string>(sym, "orientation");
|
||||
if (orientation)
|
||||
|
@ -1217,15 +1233,7 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym )
|
|||
text_symbol.set_label_placement( placement );
|
||||
|
||||
// vertical alignment
|
||||
vertical_alignment_e default_vertical_alignment = MIDDLE;
|
||||
if (dy > 0.0 )
|
||||
{
|
||||
default_vertical_alignment = BOTTOM;
|
||||
}
|
||||
else if( dy < 0.0 )
|
||||
{
|
||||
default_vertical_alignment = TOP;
|
||||
}
|
||||
vertical_alignment_e default_vertical_alignment = V_AUTO;
|
||||
|
||||
vertical_alignment_e valign = get_attr<vertical_alignment_e>(sym, "vertical-alignment", default_vertical_alignment);
|
||||
text_symbol.set_vertical_alignment(valign);
|
||||
|
@ -1353,7 +1361,7 @@ void map_parser::parse_text_symbolizer( rule & rule, ptree const & sym )
|
|||
}
|
||||
|
||||
// horizontal alignment
|
||||
horizontal_alignment_e halign = get_attr<horizontal_alignment_e>(sym, "horizontal-alignment", H_MIDDLE);
|
||||
horizontal_alignment_e halign = get_attr<horizontal_alignment_e>(sym, "horizontal-alignment", H_AUTO);
|
||||
text_symbol.set_horizontal_alignment(halign);
|
||||
|
||||
// justify alignment
|
||||
|
@ -1514,7 +1522,7 @@ void map_parser::parse_shield_symbolizer( rule & rule, ptree const & sym )
|
|||
}
|
||||
|
||||
// vertical alignment
|
||||
vertical_alignment_e valign = get_attr<vertical_alignment_e>(sym, "vertical-alignment", MIDDLE);
|
||||
vertical_alignment_e valign = get_attr<vertical_alignment_e>(sym, "vertical-alignment", V_MIDDLE);
|
||||
shield_symbol.set_vertical_alignment(valign);
|
||||
|
||||
// horizontal alignment
|
||||
|
|
|
@ -50,11 +50,12 @@ namespace mapnik
|
|||
{
|
||||
placement::placement(string_info & info_,
|
||||
shield_symbolizer const& sym,
|
||||
text_placement_info_ptr placement_options,
|
||||
double scale_factor,
|
||||
unsigned w, unsigned h,
|
||||
bool has_dimensions_)
|
||||
: info(info_),
|
||||
displacement_(sym.get_displacement()),
|
||||
displacement_(placement_options->displacement),
|
||||
scale_factor_(scale_factor),
|
||||
label_placement(sym.get_label_placement()),
|
||||
wrap_width(sym.get_wrap_width()),
|
||||
|
@ -71,13 +72,15 @@ placement::placement(string_info & info_,
|
|||
has_dimensions(has_dimensions_),
|
||||
allow_overlap(false),
|
||||
dimensions(std::make_pair(w,h)),
|
||||
text_size(sym.get_text_size()) {}
|
||||
text_size(placement_options->text_size)
|
||||
{}
|
||||
|
||||
placement::placement(string_info & info_,
|
||||
text_symbolizer const& sym,
|
||||
text_symbolizer const& sym,
|
||||
text_placement_info_ptr placement_options,
|
||||
double scale_factor)
|
||||
: info(info_),
|
||||
displacement_(sym.get_displacement()),
|
||||
displacement_(placement_options->displacement),
|
||||
scale_factor_(scale_factor),
|
||||
label_placement(sym.get_label_placement()),
|
||||
wrap_width(sym.get_wrap_width()),
|
||||
|
@ -94,7 +97,7 @@ placement::placement(string_info & info_,
|
|||
has_dimensions(false),
|
||||
allow_overlap(sym.get_allow_overlap()),
|
||||
dimensions(),
|
||||
text_size(sym.get_text_size())
|
||||
text_size(placement_options->text_size)
|
||||
{}
|
||||
|
||||
|
||||
|
@ -322,28 +325,48 @@ void placement_finder<DetectorT>::find_point_placement(placement & p,
|
|||
// if needed, adjust for desired vertical alignment
|
||||
current_placement->starting_y = label_y; // no adjustment, default is MIDDLE
|
||||
|
||||
if (valign == TOP)
|
||||
vertical_alignment_e real_valign = valign;
|
||||
if (real_valign == V_AUTO) {
|
||||
if (p.displacement_.get<1>() > 0.0)
|
||||
real_valign = V_BOTTOM;
|
||||
else if (p.displacement_.get<1>() < 0.0)
|
||||
real_valign = V_TOP;
|
||||
else
|
||||
real_valign = V_MIDDLE;
|
||||
}
|
||||
|
||||
horizontal_alignment_e real_halign = halign;
|
||||
if (real_halign == H_AUTO) {
|
||||
if (p.displacement_.get<0>() > 0.0)
|
||||
real_halign = H_RIGHT;
|
||||
else if (p.displacement_.get<0>() < 0.0)
|
||||
real_halign = H_LEFT;
|
||||
else
|
||||
real_halign = H_MIDDLE;
|
||||
}
|
||||
|
||||
if (real_valign == V_TOP)
|
||||
current_placement->starting_y -= 0.5 * (string_height + (line_spacing * (total_lines-1))); // move center up by 1/2 the total height
|
||||
|
||||
else if (valign == BOTTOM)
|
||||
else if (real_valign == V_BOTTOM)
|
||||
current_placement->starting_y += 0.5 * (string_height + (line_spacing * (total_lines-1))); // move center down by the 1/2 the total height
|
||||
|
||||
// correct placement for error, but BOTTOM does not need to be adjusted
|
||||
// (text rendering is at text_size, but line placement is by line_height (max_character_height),
|
||||
// and the rendering adds the extra space below the characters)
|
||||
if (valign == TOP )
|
||||
if (real_valign == V_TOP )
|
||||
current_placement->starting_y -= (p.text_size - max_character_height); // move up by the error
|
||||
|
||||
else if (valign == MIDDLE)
|
||||
else if (real_valign == V_MIDDLE)
|
||||
current_placement->starting_y -= ((p.text_size - max_character_height) / 2.0); // move up by 1/2 the error
|
||||
|
||||
// set horizontal position to middle of text
|
||||
current_placement->starting_x = label_x; // no adjustment, default is MIDDLE
|
||||
|
||||
if (halign == H_LEFT)
|
||||
if (real_halign == H_LEFT)
|
||||
current_placement->starting_x -= 0.5 * string_width; // move center left by 1/2 the string width
|
||||
|
||||
else if (halign == H_RIGHT)
|
||||
else if (real_halign == H_RIGHT)
|
||||
current_placement->starting_x += 0.5 * string_width; // move center right by 1/2 the string width
|
||||
|
||||
// adjust text envelope position by user's x-y displacement (dx, dy)
|
||||
|
|
183
src/text_placements.cpp
Normal file
183
src/text_placements.cpp
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2011 Hermann Kraus
|
||||
*
|
||||
* 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.hpp>
|
||||
#include <mapnik/text_placements_simple.hpp>
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_stl.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
namespace qi = boost::spirit::qi;
|
||||
namespace phoenix = boost::phoenix;
|
||||
using boost::spirit::ascii::space;
|
||||
using phoenix::push_back;
|
||||
using phoenix::ref;
|
||||
using qi::_1;
|
||||
|
||||
bool text_placement_info_dummy::next()
|
||||
{
|
||||
displacement = parent_->displacement_;
|
||||
text_size = parent_->text_size_;
|
||||
if (state) return false;
|
||||
state++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool text_placement_info_dummy::next_position_only()
|
||||
{
|
||||
if (position_state) return false;
|
||||
position_state++;
|
||||
return true;
|
||||
}
|
||||
|
||||
text_placement_info_ptr text_placements_dummy::get_placement_info() const
|
||||
{
|
||||
return text_placement_info_ptr(new text_placement_info_dummy(this));
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
bool text_placement_info_simple::next()
|
||||
{
|
||||
position_state = 0;
|
||||
if (state == 0) {
|
||||
text_size = parent_->text_size_;
|
||||
} else {
|
||||
if (state > parent_->text_sizes_.size()) return false;
|
||||
text_size = parent_->text_sizes_[state-1];
|
||||
}
|
||||
std::cerr << "Trying text_size=" << text_size << "\n";
|
||||
state++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool text_placement_info_simple::next_position_only()
|
||||
{
|
||||
if (position_state >= parent_->direction_.size()) return false;
|
||||
directions_t dir = parent_->direction_[position_state];
|
||||
switch (dir) {
|
||||
case EXACT_POSITION:
|
||||
displacement = parent_->displacement_;
|
||||
break;
|
||||
case NORTH:
|
||||
displacement = boost::make_tuple(0, -abs(parent_->displacement_.get<1>()));
|
||||
break;
|
||||
case EAST:
|
||||
displacement = boost::make_tuple(abs(parent_->displacement_.get<0>()), 0);
|
||||
break;
|
||||
case SOUTH:
|
||||
displacement = boost::make_tuple(0, abs(parent_->displacement_.get<1>()));
|
||||
break;
|
||||
case WEST:
|
||||
displacement = boost::make_tuple(-abs(parent_->displacement_.get<0>()), 0);
|
||||
break;
|
||||
case NORTHEAST:
|
||||
displacement = boost::make_tuple(
|
||||
abs(parent_->displacement_.get<0>()),
|
||||
-abs(parent_->displacement_.get<1>()));
|
||||
case SOUTHEAST:
|
||||
displacement = boost::make_tuple(
|
||||
abs(parent_->displacement_.get<0>()),
|
||||
abs(parent_->displacement_.get<1>()));
|
||||
case NORTHWEST:
|
||||
displacement = boost::make_tuple(
|
||||
-abs(parent_->displacement_.get<0>()),
|
||||
-abs(parent_->displacement_.get<1>()));
|
||||
case SOUTHWEST:
|
||||
displacement = boost::make_tuple(
|
||||
-abs(parent_->displacement_.get<0>()),
|
||||
abs(parent_->displacement_.get<1>()));
|
||||
break;
|
||||
default:
|
||||
std::cerr << "WARNING: Unknown placement\n";
|
||||
}
|
||||
position_state++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
text_placement_info_ptr text_placements_simple::get_placement_info() const
|
||||
{
|
||||
return text_placement_info_ptr(new text_placement_info_simple(this));
|
||||
}
|
||||
|
||||
/** Positiion string: [POS][SIZE]
|
||||
* [POS] is any combination of
|
||||
* N, E, S, W, NE, SE, NW, SW, X (exact position) (seprated by commas)
|
||||
* [SIZE] is a list of font sizes, seprated by commas. First fontsize
|
||||
* is always the one given in the TextSymbolizer parameters.
|
||||
* First all directions are tried, then font size is reduced by 1pt
|
||||
* and all directions are tried again. The process ends when a placement is
|
||||
* found or the last fontsize is tried without success.
|
||||
* Example: N,S,15,10,8 (tries placement above, then below and if
|
||||
* that fails it tries the additional font sizes 15, 10 and 8.
|
||||
*/
|
||||
void text_placements_simple::set_positions(std::string positions)
|
||||
{
|
||||
positions_ = positions;
|
||||
struct direction_name_ : qi::symbols<char, directions_t>
|
||||
{
|
||||
direction_name_()
|
||||
{
|
||||
add
|
||||
("N" , NORTH)
|
||||
("E" , EAST)
|
||||
("S" , SOUTH)
|
||||
("W" , WEST)
|
||||
("NE", NORTHEAST)
|
||||
("SE", SOUTHEAST)
|
||||
("NW", NORTHWEST)
|
||||
("SW", SOUTHWEST)
|
||||
("X" , EXACT_POSITION)
|
||||
;
|
||||
}
|
||||
|
||||
} direction_name;
|
||||
|
||||
std::string::iterator first = positions.begin(), last = positions.end();
|
||||
qi::phrase_parse(first, last,
|
||||
(direction_name[push_back(ref(direction_), _1)] % ',') >> *(',' >> qi::int_[push_back(ref(text_sizes_), _1)]),
|
||||
space
|
||||
);
|
||||
if (first != last) {
|
||||
std::cerr << "WARNING: Could not parse text_placement_simple placement string ('" << positions << "').\n";
|
||||
}
|
||||
if (direction_.size() == 0) {
|
||||
std::cerr << "WARNING: text_placements_simple with no valid placments! ('"<< positions<<"')\n";
|
||||
}
|
||||
}
|
||||
|
||||
text_placements_simple::text_placements_simple()
|
||||
{
|
||||
set_positions("X");
|
||||
}
|
||||
|
||||
text_placements_simple::text_placements_simple(std::string positions)
|
||||
{
|
||||
set_positions(positions);
|
||||
}
|
||||
} //namespace
|
|
@ -45,6 +45,7 @@ static const char * vertical_alignment_strings[] = {
|
|||
"top",
|
||||
"middle",
|
||||
"bottom",
|
||||
"auto",
|
||||
""
|
||||
};
|
||||
|
||||
|
@ -55,6 +56,7 @@ static const char * horizontal_alignment_strings[] = {
|
|||
"left",
|
||||
"middle",
|
||||
"right",
|
||||
"auto",
|
||||
""
|
||||
};
|
||||
|
||||
|
@ -84,12 +86,13 @@ IMPLEMENT_ENUM( text_transform_e, text_transform_strings );
|
|||
|
||||
|
||||
|
||||
text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_name, unsigned size, color const& fill)
|
||||
text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_name,
|
||||
unsigned size, color const& fill,
|
||||
text_placements_ptr placements)
|
||||
: symbolizer_base(),
|
||||
name_(name),
|
||||
face_name_(face_name),
|
||||
//fontset_(default_fontset),
|
||||
size_(size),
|
||||
text_ratio_(0),
|
||||
wrap_width_(0),
|
||||
wrap_char_(' '),
|
||||
|
@ -104,9 +107,8 @@ text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_na
|
|||
halo_fill_(color(255,255,255)),
|
||||
halo_radius_(0),
|
||||
label_p_(POINT_PLACEMENT),
|
||||
valign_(MIDDLE),
|
||||
valign_(V_MIDDLE),
|
||||
anchor_(0.0,0.5),
|
||||
displacement_(0.0,0.0),
|
||||
avoid_edges_(false),
|
||||
minimum_distance_(0.0),
|
||||
minimum_padding_(0.0),
|
||||
|
@ -114,14 +116,18 @@ text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_na
|
|||
text_opacity_(1.0),
|
||||
wrap_before_(false),
|
||||
halign_(H_MIDDLE),
|
||||
jalign_(J_MIDDLE) {}
|
||||
jalign_(J_MIDDLE),
|
||||
placement_options_(placements)
|
||||
{
|
||||
set_text_size(size);
|
||||
}
|
||||
|
||||
text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const& fill)
|
||||
text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const& fill,
|
||||
text_placements_ptr placements)
|
||||
: symbolizer_base(),
|
||||
name_(name),
|
||||
//face_name_(""),
|
||||
//fontset_(default_fontset),
|
||||
size_(size),
|
||||
text_ratio_(0),
|
||||
wrap_width_(0),
|
||||
wrap_char_(' '),
|
||||
|
@ -136,9 +142,8 @@ text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const
|
|||
halo_fill_(color(255,255,255)),
|
||||
halo_radius_(0),
|
||||
label_p_(POINT_PLACEMENT),
|
||||
valign_(MIDDLE),
|
||||
valign_(V_MIDDLE),
|
||||
anchor_(0.0,0.5),
|
||||
displacement_(0.0,0.0),
|
||||
avoid_edges_(false),
|
||||
minimum_distance_(0.0),
|
||||
minimum_padding_(0.0),
|
||||
|
@ -146,7 +151,11 @@ text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const
|
|||
text_opacity_(1.0),
|
||||
wrap_before_(false),
|
||||
halign_(H_MIDDLE),
|
||||
jalign_(J_MIDDLE) {}
|
||||
jalign_(J_MIDDLE),
|
||||
placement_options_(placements)
|
||||
{
|
||||
set_text_size(size);
|
||||
}
|
||||
|
||||
text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
||||
: symbolizer_base(rhs),
|
||||
|
@ -154,7 +163,6 @@ text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
|||
orientation_(rhs.orientation_),
|
||||
face_name_(rhs.face_name_),
|
||||
fontset_(rhs.fontset_),
|
||||
size_(rhs.size_),
|
||||
text_ratio_(rhs.text_ratio_),
|
||||
wrap_width_(rhs.wrap_width_),
|
||||
wrap_char_(rhs.wrap_char_),
|
||||
|
@ -171,7 +179,6 @@ text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
|||
label_p_(rhs.label_p_),
|
||||
valign_(rhs.valign_),
|
||||
anchor_(rhs.anchor_),
|
||||
displacement_(rhs.displacement_),
|
||||
avoid_edges_(rhs.avoid_edges_),
|
||||
minimum_distance_(rhs.minimum_distance_),
|
||||
minimum_padding_(rhs.minimum_padding_),
|
||||
|
@ -179,7 +186,8 @@ text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
|||
text_opacity_(rhs.text_opacity_),
|
||||
wrap_before_(rhs.wrap_before_),
|
||||
halign_(rhs.halign_),
|
||||
jalign_(rhs.jalign_) {}
|
||||
jalign_(rhs.jalign_),
|
||||
placement_options_(rhs.placement_options_) {}
|
||||
|
||||
text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
|
||||
{
|
||||
|
@ -189,7 +197,6 @@ text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
|
|||
orientation_ = other.orientation_;
|
||||
face_name_ = other.face_name_;
|
||||
fontset_ = other.fontset_;
|
||||
size_ = other.size_;
|
||||
text_ratio_ = other.text_ratio_;
|
||||
wrap_width_ = other.wrap_width_;
|
||||
wrap_char_ = other.wrap_char_;
|
||||
|
@ -206,7 +213,6 @@ text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
|
|||
label_p_ = other.label_p_;
|
||||
valign_ = other.valign_;
|
||||
anchor_ = other.anchor_;
|
||||
displacement_ = other.displacement_;
|
||||
avoid_edges_ = other.avoid_edges_;
|
||||
minimum_distance_ = other.minimum_distance_;
|
||||
minimum_padding_ = other.minimum_padding_;
|
||||
|
@ -215,6 +221,7 @@ text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
|
|||
wrap_before_ = other.wrap_before_;
|
||||
halign_ = other.halign_;
|
||||
jalign_ = other.jalign_;
|
||||
placement_options_ = other.placement_options_;
|
||||
std::cout << "TODO: Metawriter (text_symbolizer::operator=)\n";
|
||||
return *this;
|
||||
}
|
||||
|
@ -381,12 +388,12 @@ void text_symbolizer::set_max_char_angle_delta(double angle)
|
|||
|
||||
void text_symbolizer::set_text_size(unsigned size)
|
||||
{
|
||||
size_ = size;
|
||||
placement_options_->set_default_text_size(size);
|
||||
}
|
||||
|
||||
unsigned text_symbolizer::get_text_size() const
|
||||
{
|
||||
return size_;
|
||||
return placement_options_->get_default_text_size();
|
||||
}
|
||||
|
||||
void text_symbolizer::set_fill(color const& fill)
|
||||
|
@ -451,12 +458,12 @@ position const& text_symbolizer::get_anchor() const
|
|||
|
||||
void text_symbolizer::set_displacement(double x, double y)
|
||||
{
|
||||
displacement_ = boost::make_tuple(x,y);
|
||||
placement_options_->set_default_displacement(boost::make_tuple(x,y));
|
||||
}
|
||||
|
||||
position const& text_symbolizer::get_displacement() const
|
||||
{
|
||||
return displacement_;
|
||||
return placement_options_->get_default_displacement();
|
||||
}
|
||||
|
||||
bool text_symbolizer::get_avoid_edges() const
|
||||
|
@ -489,7 +496,6 @@ void text_symbolizer::set_minimum_padding(double distance)
|
|||
minimum_padding_ = distance;
|
||||
}
|
||||
|
||||
|
||||
void text_symbolizer::set_allow_overlap(bool overlap)
|
||||
{
|
||||
overlap_ = overlap;
|
||||
|
@ -529,4 +535,16 @@ justify_alignment_e text_symbolizer::get_justify_alignment() const
|
|||
{
|
||||
return jalign_;
|
||||
}
|
||||
|
||||
text_placements_ptr text_symbolizer::get_placement_options() const
|
||||
{
|
||||
return placement_options_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_placement_options(text_placements_ptr placement_options)
|
||||
{
|
||||
placement_options_ = placement_options;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue