mirror of
https://github.com/mapnik/mapnik.git
synced 2025-12-08 20:13:09 +00:00
1. applied text-wrap patch from Robert Coup. Thanks!
2. by default use tinyxml as a property_tree parser 3. modified load_map.cpp to allow to test new features
This commit is contained in:
parent
f0e6e58a8a
commit
d7fcefc848
@ -110,6 +110,7 @@ void export_map()
|
||||
.add_property("layers",make_function
|
||||
(&Map::layers,return_value_policy<reference_existing_object>()),
|
||||
"Get the list of layers in this map.")
|
||||
.def("find_style",&Map::find_style,return_value_policy<copy_const_reference>())
|
||||
.def_pickle(map_pickle_suite())
|
||||
;
|
||||
}
|
||||
|
||||
@ -36,13 +36,19 @@ void export_text_symbolizer()
|
||||
.value("LINE_PLACEMENT",mapnik::line_placement)
|
||||
.value("POINT_PLACEMENT",mapnik::point_placement)
|
||||
;
|
||||
|
||||
|
||||
class_<text_symbolizer>("TextSymbolizer",
|
||||
init<std::string const&,std::string const&, unsigned,Color const&>())
|
||||
.add_property("halo_fill",make_function(
|
||||
&text_symbolizer::get_halo_fill,
|
||||
return_value_policy<copy_const_reference>()),
|
||||
&text_symbolizer::set_halo_fill)
|
||||
.add_property("wrap_width",
|
||||
&text_symbolizer::get_wrap_width,
|
||||
&text_symbolizer::set_wrap_width)
|
||||
.add_property("text_ratio",
|
||||
&text_symbolizer::get_text_ratio,
|
||||
&text_symbolizer::set_text_ratio)
|
||||
.add_property("halo_radius",
|
||||
&text_symbolizer::get_halo_radius,
|
||||
&text_symbolizer::set_halo_radius)
|
||||
|
||||
@ -264,6 +264,8 @@ namespace mapnik
|
||||
double x, y, angle;
|
||||
|
||||
path->vertex(&c, &x, &y, &angle);
|
||||
// std::clog << " prepare_glyph: " << (unsigned char)c << "," << x << "," << y << "," << angle << std::endl;
|
||||
|
||||
|
||||
FT_BBox glyph_bbox;
|
||||
FT_Glyph image;
|
||||
@ -363,8 +365,8 @@ namespace mapnik
|
||||
|
||||
width += char_dim.first;
|
||||
height = char_dim.second > height ? char_dim.second : height;
|
||||
|
||||
}
|
||||
|
||||
info->set_dimensions(width, height);
|
||||
}
|
||||
|
||||
@ -376,10 +378,14 @@ namespace mapnik
|
||||
|
||||
start.x = unsigned(x0 * (1 << 6));
|
||||
start.y = unsigned((height - y0) * (1 << 6));
|
||||
|
||||
// std::clog << "Render text at: " << x0 << "," << y0 << " " << start.x << "," << start.y << std::endl;
|
||||
|
||||
// now render transformed glyphs
|
||||
typename glyphs_t::iterator pos;
|
||||
|
||||
if (halo_radius_ > 0)
|
||||
|
||||
//make sure we've got reasonable values.
|
||||
if (halo_radius_ > 0 && halo_radius_ < 256)
|
||||
{
|
||||
//render halo
|
||||
for ( pos = glyphs_.begin(); pos != glyphs_.end();++pos)
|
||||
@ -463,6 +469,8 @@ namespace mapnik
|
||||
mapnik::Color fill_;
|
||||
mapnik::Color halo_fill_;
|
||||
int halo_radius_;
|
||||
unsigned text_ratio_;
|
||||
unsigned wrap_width_;
|
||||
glyphs_t glyphs_;
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ namespace mapnik
|
||||
line_pattern_symbolizer(std::string const& file,
|
||||
std::string const& type,
|
||||
unsigned width,unsigned height);
|
||||
|
||||
|
||||
line_pattern_symbolizer(line_pattern_symbolizer const& rhs);
|
||||
ImageData32 const& get_pattern() const;
|
||||
private:
|
||||
|
||||
@ -67,7 +67,7 @@ namespace mapnik
|
||||
double starting_y;
|
||||
|
||||
text_path path;
|
||||
|
||||
|
||||
|
||||
//helpers
|
||||
std::pair<double, double> get_position_at_distance(double target_distance);
|
||||
@ -75,6 +75,9 @@ namespace mapnik
|
||||
void clear_envelopes();
|
||||
|
||||
double total_distance_; //cache for distance
|
||||
|
||||
int wrap_width;
|
||||
int text_ratio;
|
||||
};
|
||||
|
||||
class placement_finder : boost::noncopyable
|
||||
|
||||
@ -38,12 +38,17 @@ namespace mapnik
|
||||
|
||||
struct MAPNIK_DECL text_symbolizer
|
||||
{
|
||||
text_symbolizer(std::string const& name,std::string const& face_name, unsigned size,Color const& fill);
|
||||
text_symbolizer(std::string const& name,std::string const& face_name,
|
||||
unsigned size,Color const& fill);
|
||||
text_symbolizer(text_symbolizer const& rhs);
|
||||
text_symbolizer& operator=(text_symbolizer const& rhs);
|
||||
std::string const& get_name() const;
|
||||
unsigned get_text_ratio() const; // target ratio for text bounding box in pixels
|
||||
void set_text_ratio(unsigned ratio);
|
||||
unsigned get_wrap_width() const; // target ratio for text bounding box in pixels
|
||||
void set_wrap_width(unsigned ratio);
|
||||
unsigned get_text_size() const;
|
||||
std::string const& get_face_name() const;
|
||||
std::string const& get_face_name() const;
|
||||
Color const& get_fill() const;
|
||||
void set_halo_fill(Color const& fill);
|
||||
Color const& get_halo_fill() const;
|
||||
@ -57,8 +62,10 @@ namespace mapnik
|
||||
position const& get_displacement() const;
|
||||
private:
|
||||
std::string name_;
|
||||
std::string face_name_;
|
||||
std::string face_name_;
|
||||
unsigned size_;
|
||||
unsigned text_ratio_;
|
||||
unsigned wrap_width_;
|
||||
Color fill_;
|
||||
Color halo_fill_;
|
||||
unsigned halo_radius_;
|
||||
|
||||
@ -62,9 +62,16 @@ source = Split(
|
||||
scale_denominator.cpp
|
||||
"""
|
||||
)
|
||||
source += Split(
|
||||
"""
|
||||
../tinyxml/tinystr.cpp
|
||||
../tinyxml/tinyxml.cpp
|
||||
../tinyxml/tinyxmlerror.cpp
|
||||
../tinyxml/tinyxmlparser.cpp
|
||||
""")
|
||||
|
||||
mapnik = env.SharedLibrary('mapnik', source, LIBS=libraries, LINKFLAGS=linkflags)
|
||||
|
||||
env.Alias(target='install', source=env.Install(prefix + '/' + env['LIBDIR_SCHEMA'], mapnik))
|
||||
includes = glob.glob('../include/mapnik' + '/*.hpp')
|
||||
includes = glob.glob('../include/mapnik/*.hpp')
|
||||
env.Alias(target='install', source=env.Install(prefix+'/include/mapnik', includes))
|
||||
|
||||
@ -502,6 +502,8 @@ namespace mapnik
|
||||
ren.get_string_info(text, &info);
|
||||
|
||||
placement text_placement(&info, &t_, &prj_trans, geom, sym.get_label_placement());
|
||||
text_placement.text_ratio = sym.get_text_ratio();
|
||||
text_placement.wrap_width = sym.get_wrap_width();
|
||||
|
||||
bool found = finder_.find_placement(&text_placement);
|
||||
if (!found) {
|
||||
|
||||
@ -27,9 +27,6 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
// use tinyxml
|
||||
#define BOOST_PROPERTY_TREE_XML_PARSER_TINYXML
|
||||
#include <boost/property_tree/xml_parser.hpp>
|
||||
|
||||
// mapnik
|
||||
@ -166,6 +163,37 @@ namespace mapnik
|
||||
{
|
||||
text_symbol.set_label_placement(line_placement);
|
||||
}
|
||||
// halo fill and radius
|
||||
boost::optional<std::string> halo_fill =
|
||||
sym.second.get_optional<std::string>("<xmlattr>.halo_fill");
|
||||
|
||||
if (halo_fill)
|
||||
{
|
||||
text_symbol.set_halo_fill
|
||||
(color_factory::from_string(halo_fill->c_str()));
|
||||
}
|
||||
boost::optional<unsigned> halo_radius =
|
||||
sym.second.get_optional<unsigned>("<xmlattr>.halo_radius");
|
||||
if (halo_radius)
|
||||
{
|
||||
text_symbol.set_halo_radius(*halo_radius);
|
||||
}
|
||||
|
||||
// text ratio and wrap width
|
||||
boost::optional<unsigned> text_ratio =
|
||||
sym.second.get_optional<unsigned>("<xmlattr>.text_ratio");
|
||||
|
||||
if (text_ratio)
|
||||
{
|
||||
text_symbol.set_text_ratio(*text_ratio);
|
||||
}
|
||||
|
||||
boost::optional<unsigned> wrap_width =
|
||||
sym.second.get_optional<unsigned>("<xmlattr>.wrap_width");
|
||||
if (wrap_width)
|
||||
{
|
||||
text_symbol.set_wrap_width(*wrap_width);
|
||||
}
|
||||
|
||||
rule.append(text_symbol);
|
||||
}
|
||||
|
||||
@ -40,339 +40,340 @@
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
placement::placement(string_info *info_, CoordTransform *ctrans_, const proj_transform *proj_trans_, geometry_ptr geom_, std::pair<double, double> dimensions_)
|
||||
: info(info_), ctrans(ctrans_), proj_trans(proj_trans_), geom(geom_), label_placement(point_placement), dimensions(dimensions_), has_dimensions(true), shape_path(*ctrans_, *geom_, *proj_trans_), total_distance_(-1.0)
|
||||
{
|
||||
}
|
||||
|
||||
//For text
|
||||
placement::placement(string_info *info_, CoordTransform *ctrans_, const proj_transform *proj_trans_, geometry_ptr geom_, label_placement_e placement_)
|
||||
: info(info_), ctrans(ctrans_), proj_trans(proj_trans_), geom(geom_), label_placement(placement_), has_dimensions(false), shape_path(*ctrans_, *geom_, *proj_trans_), total_distance_(-1.0)
|
||||
{
|
||||
}
|
||||
|
||||
placement::~placement()
|
||||
{
|
||||
}
|
||||
|
||||
std::pair<double, double> placement::get_position_at_distance(double target_distance)
|
||||
{
|
||||
double old_x, old_y, new_x, new_y;
|
||||
double x, y;
|
||||
x = y = 0.0;
|
||||
|
||||
double distance = 0.0;
|
||||
|
||||
shape_path.rewind(0);
|
||||
shape_path.vertex(&new_x,&new_y);
|
||||
for (unsigned i = 0; i < geom->num_points() - 1; i++)
|
||||
placement::placement(string_info *info_, CoordTransform *ctrans_, const proj_transform *proj_trans_, geometry_ptr geom_, std::pair<double, double> dimensions_)
|
||||
: info(info_), ctrans(ctrans_), proj_trans(proj_trans_), geom(geom_), label_placement(point_placement), dimensions(dimensions_), has_dimensions(true), shape_path(*ctrans_, *geom_, *proj_trans_), total_distance_(-1.0), wrap_width(0), text_ratio(0)
|
||||
{
|
||||
double dx, dy;
|
||||
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
|
||||
shape_path.vertex(&new_x,&new_y);
|
||||
|
||||
dx = new_x - old_x;
|
||||
dy = new_y - old_y;
|
||||
|
||||
double segment_length = sqrt(dx*dx + dy*dy);
|
||||
|
||||
distance += segment_length;
|
||||
if (distance > target_distance)
|
||||
{
|
||||
x = new_x - dx*(distance - target_distance)/segment_length;
|
||||
y = new_y - dy*(distance - target_distance)/segment_length;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return std::pair<double, double>(x, y);
|
||||
}
|
||||
|
||||
double placement::get_total_distance()
|
||||
{
|
||||
if (total_distance_ < 0.0)
|
||||
//For text
|
||||
placement::placement(string_info *info_, CoordTransform *ctrans_, const proj_transform *proj_trans_, geometry_ptr geom_, label_placement_e placement_)
|
||||
: info(info_), ctrans(ctrans_), proj_trans(proj_trans_), geom(geom_), label_placement(placement_), has_dimensions(false), shape_path(*ctrans_, *geom_, *proj_trans_), total_distance_(-1.0), wrap_width(0), text_ratio(0)
|
||||
{
|
||||
double old_x, old_y, new_x, new_y;
|
||||
|
||||
shape_path.rewind(0);
|
||||
|
||||
shape_path.vertex(&old_x,&old_y);
|
||||
|
||||
total_distance_ = 0.0;
|
||||
|
||||
for (unsigned i = 0; i < geom->num_points() - 1; i++)
|
||||
{
|
||||
double dx, dy;
|
||||
|
||||
shape_path.vertex(&new_x,&new_y);
|
||||
|
||||
dx = new_x - old_x;
|
||||
dy = new_y - old_y;
|
||||
|
||||
total_distance_ += sqrt(dx*dx + dy*dy);
|
||||
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
}
|
||||
}
|
||||
|
||||
return total_distance_;
|
||||
}
|
||||
|
||||
void placement::clear_envelopes()
|
||||
{
|
||||
while (!envelopes.empty())
|
||||
envelopes.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
placement_finder::placement_finder(Envelope<double> e)
|
||||
: detector_(e)
|
||||
{
|
||||
}
|
||||
|
||||
bool placement_finder::find_placement(placement *p)
|
||||
{
|
||||
if (p->label_placement == point_placement)
|
||||
placement::~placement()
|
||||
{
|
||||
return find_placement_horizontal(p);
|
||||
}
|
||||
else if (p->label_placement == line_placement)
|
||||
|
||||
std::pair<double, double> placement::get_position_at_distance(double target_distance)
|
||||
{
|
||||
return find_placement_follow(p);
|
||||
}
|
||||
double old_x, old_y, new_x, new_y;
|
||||
double x, y;
|
||||
x = y = 0.0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool placement_finder::find_placement_follow(placement *p)
|
||||
{
|
||||
std::pair<double, double> string_dimensions = p->info->get_dimensions();
|
||||
double string_width = string_dimensions.first;
|
||||
// double string_height = string_dimensions.second;
|
||||
double distance = 0.0;
|
||||
|
||||
double distance = p->get_total_distance();
|
||||
|
||||
//~ double delta = string_width/distance;
|
||||
double delta = distance/100.0;
|
||||
|
||||
for (double i = 0; i < (distance - string_width)/2.0; i += delta)
|
||||
{
|
||||
p->clear_envelopes();
|
||||
|
||||
if ( build_path_follow(p, (distance - string_width)/2.0 + i) ) {
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
p->clear_envelopes();
|
||||
|
||||
if ( build_path_follow(p, (distance - string_width)/2.0 - i) ) {
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
p->starting_x = 0;
|
||||
p->starting_y = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool placement_finder::find_placement_horizontal(placement *p)
|
||||
{
|
||||
double distance = p->get_total_distance();
|
||||
//~ double delta = string_width/distance;
|
||||
double delta = distance/100.0;
|
||||
|
||||
for (double i = 0; i < distance/2.0; i += delta)
|
||||
{
|
||||
p->clear_envelopes();
|
||||
|
||||
if ( build_path_horizontal(p, distance/2.0 + i) ) {
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
p->clear_envelopes();
|
||||
|
||||
if ( build_path_horizontal(p, distance/2.0 - i) ) {
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
p->starting_x = 0;
|
||||
p->starting_y = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void placement_finder::update_detector(placement *p)
|
||||
{
|
||||
while (!p->envelopes.empty())
|
||||
{
|
||||
Envelope<double> e = p->envelopes.front();
|
||||
|
||||
detector_.insert(e);
|
||||
|
||||
p->envelopes.pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool placement_finder::build_path_follow(placement *p, double target_distance)
|
||||
{
|
||||
double new_x, new_y, old_x, old_y;
|
||||
unsigned cur_node = 0;
|
||||
|
||||
double angle = 0.0;
|
||||
int orientation = 0;
|
||||
|
||||
p->path.clear();
|
||||
|
||||
double x, y;
|
||||
x = y = 0.0;
|
||||
|
||||
double distance = 0.0;
|
||||
|
||||
std::pair<double, double> string_dimensions = p->info->get_dimensions();
|
||||
// double string_width = string_dimensions.first;
|
||||
double string_height = string_dimensions.second;
|
||||
|
||||
p->shape_path.rewind(0);
|
||||
p->shape_path.vertex(&new_x,&new_y);
|
||||
for (unsigned i = 0; i < p->geom->num_points() - 1; i++)
|
||||
{
|
||||
double dx, dy;
|
||||
|
||||
cur_node++;
|
||||
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
|
||||
p->shape_path.vertex(&new_x,&new_y);
|
||||
|
||||
dx = new_x - old_x;
|
||||
dy = new_y - old_y;
|
||||
|
||||
double segment_length = sqrt(dx*dx + dy*dy);
|
||||
|
||||
distance += segment_length;
|
||||
if (distance > target_distance)
|
||||
shape_path.rewind(0);
|
||||
shape_path.vertex(&new_x,&new_y);
|
||||
for (unsigned i = 0; i < geom->num_points() - 1; i++)
|
||||
{
|
||||
p->starting_x = new_x - dx*(distance - target_distance)/segment_length;
|
||||
p->starting_y = new_y - dy*(distance - target_distance)/segment_length;
|
||||
double dx, dy;
|
||||
|
||||
angle = atan2(-dy, dx);
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
|
||||
if (angle > M_PI/2 || angle <= -M_PI/2) {
|
||||
orientation = -1;
|
||||
}
|
||||
else {
|
||||
orientation = 1;
|
||||
shape_path.vertex(&new_x,&new_y);
|
||||
|
||||
dx = new_x - old_x;
|
||||
dy = new_y - old_y;
|
||||
|
||||
double segment_length = sqrt(dx*dx + dy*dy);
|
||||
|
||||
distance += segment_length;
|
||||
if (distance > target_distance)
|
||||
{
|
||||
x = new_x - dx*(distance - target_distance)/segment_length;
|
||||
y = new_y - dy*(distance - target_distance)/segment_length;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return std::pair<double, double>(x, y);
|
||||
}
|
||||
|
||||
double placement::get_total_distance()
|
||||
{
|
||||
if (total_distance_ < 0.0)
|
||||
{
|
||||
double old_x, old_y, new_x, new_y;
|
||||
|
||||
shape_path.rewind(0);
|
||||
|
||||
shape_path.vertex(&old_x,&old_y);
|
||||
|
||||
distance -= target_distance;
|
||||
|
||||
break;
|
||||
total_distance_ = 0.0;
|
||||
|
||||
for (unsigned i = 0; i < geom->num_points() - 1; i++)
|
||||
{
|
||||
double dx, dy;
|
||||
|
||||
shape_path.vertex(&new_x,&new_y);
|
||||
|
||||
dx = new_x - old_x;
|
||||
dy = new_y - old_y;
|
||||
|
||||
total_distance_ += sqrt(dx*dx + dy*dy);
|
||||
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
}
|
||||
}
|
||||
|
||||
return total_distance_;
|
||||
}
|
||||
|
||||
void placement::clear_envelopes()
|
||||
{
|
||||
while (!envelopes.empty())
|
||||
envelopes.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
placement_finder::placement_finder(Envelope<double> e)
|
||||
: detector_(e)
|
||||
{
|
||||
}
|
||||
|
||||
bool placement_finder::find_placement(placement *p)
|
||||
{
|
||||
if (p->label_placement == point_placement)
|
||||
{
|
||||
return find_placement_horizontal(p);
|
||||
}
|
||||
else if (p->label_placement == line_placement)
|
||||
{
|
||||
return find_placement_follow(p);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool placement_finder::find_placement_follow(placement *p)
|
||||
{
|
||||
std::pair<double, double> string_dimensions = p->info->get_dimensions();
|
||||
double string_width = string_dimensions.first;
|
||||
// double string_height = string_dimensions.second;
|
||||
|
||||
double distance = p->get_total_distance();
|
||||
|
||||
//~ double delta = string_width/distance;
|
||||
double delta = distance/100.0;
|
||||
|
||||
for (double i = 0; i < (distance - string_width)/2.0; i += delta)
|
||||
{
|
||||
p->clear_envelopes();
|
||||
|
||||
if ( build_path_follow(p, (distance - string_width)/2.0 + i) ) {
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
p->clear_envelopes();
|
||||
|
||||
if ( build_path_follow(p, (distance - string_width)/2.0 - i) ) {
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
p->starting_x = 0;
|
||||
p->starting_y = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool placement_finder::find_placement_horizontal(placement *p)
|
||||
{
|
||||
double distance = p->get_total_distance();
|
||||
//~ double delta = string_width/distance;
|
||||
double delta = distance/100.0;
|
||||
|
||||
for (double i = 0; i < distance/2.0; i += delta)
|
||||
{
|
||||
p->clear_envelopes();
|
||||
|
||||
if ( build_path_horizontal(p, distance/2.0 + i) ) {
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
p->clear_envelopes();
|
||||
|
||||
if ( build_path_horizontal(p, distance/2.0 - i) ) {
|
||||
update_detector(p);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
p->starting_x = 0;
|
||||
p->starting_y = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void placement_finder::update_detector(placement *p)
|
||||
{
|
||||
while (!p->envelopes.empty())
|
||||
{
|
||||
Envelope<double> e = p->envelopes.front();
|
||||
|
||||
detector_.insert(e);
|
||||
|
||||
p->envelopes.pop();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
||||
bool placement_finder::build_path_follow(placement *p, double target_distance)
|
||||
{
|
||||
character_info ci;
|
||||
unsigned c;
|
||||
|
||||
while (distance <= 0) {
|
||||
double new_x, new_y, old_x, old_y;
|
||||
unsigned cur_node = 0;
|
||||
|
||||
double angle = 0.0;
|
||||
int orientation = 0;
|
||||
|
||||
p->path.clear();
|
||||
|
||||
double x, y;
|
||||
x = y = 0.0;
|
||||
|
||||
double distance = 0.0;
|
||||
|
||||
std::pair<double, double> string_dimensions = p->info->get_dimensions();
|
||||
// double string_width = string_dimensions.first;
|
||||
double string_height = string_dimensions.second;
|
||||
|
||||
p->shape_path.rewind(0);
|
||||
p->shape_path.vertex(&new_x,&new_y);
|
||||
for (unsigned i = 0; i < p->geom->num_points() - 1; i++)
|
||||
{
|
||||
double dx, dy;
|
||||
|
||||
cur_node++;
|
||||
|
||||
if (cur_node >= p->geom->num_points()) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
|
||||
p->shape_path.vertex(&new_x,&new_y);
|
||||
|
||||
|
||||
dx = new_x - old_x;
|
||||
dy = new_y - old_y;
|
||||
|
||||
double segment_length = sqrt(dx*dx + dy*dy);
|
||||
|
||||
distance += segment_length;
|
||||
if (distance > target_distance)
|
||||
{
|
||||
p->starting_x = new_x - dx*(distance - target_distance)/segment_length;
|
||||
p->starting_y = new_y - dy*(distance - target_distance)/segment_length;
|
||||
|
||||
angle = atan2(-dy, dx );
|
||||
angle = atan2(-dy, dx);
|
||||
|
||||
if (angle > M_PI/2 || angle <= -M_PI/2) {
|
||||
orientation = -1;
|
||||
}
|
||||
else {
|
||||
orientation = 1;
|
||||
}
|
||||
|
||||
distance -= target_distance;
|
||||
|
||||
distance += sqrt(dx*dx+dy*dy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (orientation == -1) {
|
||||
ci = p->info->at(p->info->num_characters() - i - 1);
|
||||
}
|
||||
else
|
||||
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
||||
{
|
||||
ci = p->info->at(i);
|
||||
}
|
||||
c = ci.character;
|
||||
character_info ci;
|
||||
unsigned c;
|
||||
|
||||
while (distance <= 0) {
|
||||
double dx, dy;
|
||||
|
||||
Envelope<double> e;
|
||||
if (p->has_dimensions)
|
||||
{
|
||||
e.init(x, y, x + p->dimensions.first, y + p->dimensions.second);
|
||||
}
|
||||
cur_node++;
|
||||
|
||||
if (cur_node >= p->geom->num_points()) {
|
||||
break;
|
||||
}
|
||||
|
||||
old_x = new_x;
|
||||
old_y = new_y;
|
||||
|
||||
if (orientation == -1) {
|
||||
x = new_x - (distance - ci.width)*cos(angle);
|
||||
y = new_y + (distance - ci.width)*sin(angle);
|
||||
p->shape_path.vertex(&new_x,&new_y);
|
||||
|
||||
//Center the text on the line.
|
||||
x += (((double)string_height/2.0) - 1.0)*cos(angle+M_PI/2);
|
||||
y -= (((double)string_height/2.0) - 1.0)*sin(angle+M_PI/2);
|
||||
dx = new_x - old_x;
|
||||
dy = new_y - old_y;
|
||||
|
||||
angle = atan2(-dy, dx );
|
||||
|
||||
distance += sqrt(dx*dx+dy*dy);
|
||||
}
|
||||
|
||||
if (orientation == -1) {
|
||||
ci = p->info->at(p->info->num_characters() - i - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ci = p->info->at(i);
|
||||
}
|
||||
c = ci.character;
|
||||
|
||||
Envelope<double> e;
|
||||
if (p->has_dimensions)
|
||||
{
|
||||
e.init(x, y, x + p->dimensions.first, y + p->dimensions.second);
|
||||
}
|
||||
|
||||
if (orientation == -1) {
|
||||
x = new_x - (distance - ci.width)*cos(angle);
|
||||
y = new_y + (distance - ci.width)*sin(angle);
|
||||
|
||||
//Center the text on the line.
|
||||
x += (((double)string_height/2.0) - 1.0)*cos(angle+M_PI/2);
|
||||
y -= (((double)string_height/2.0) - 1.0)*sin(angle+M_PI/2);
|
||||
|
||||
if (!p->has_dimensions)
|
||||
{
|
||||
e.init(x, y, x + ci.width*cos(angle+M_PI), y - ci.width*sin(angle+M_PI));
|
||||
e.expand_to_include(x - ci.height*sin(angle+M_PI), y - ci.height*cos(angle+M_PI));
|
||||
e.expand_to_include(x + (ci.width*cos(angle+M_PI) - ci.height*sin(angle+M_PI)), y - (ci.width*sin(angle+M_PI) + ci.height*cos(angle+M_PI)));
|
||||
if (!p->has_dimensions)
|
||||
{
|
||||
e.init(x, y, x + ci.width*cos(angle+M_PI), y - ci.width*sin(angle+M_PI));
|
||||
e.expand_to_include(x - ci.height*sin(angle+M_PI), y - ci.height*cos(angle+M_PI));
|
||||
e.expand_to_include(x + (ci.width*cos(angle+M_PI) - ci.height*sin(angle+M_PI)), y - (ci.width*sin(angle+M_PI) + ci.height*cos(angle+M_PI)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = new_x - distance*cos(angle);
|
||||
y = new_y + distance*sin(angle);
|
||||
|
||||
//Center the text on the line.
|
||||
x += (((double)string_height/2.0) - 1.0)*cos(angle-M_PI/2);
|
||||
y -= (((double)string_height/2.0) - 1.0)*sin(angle-M_PI/2);
|
||||
|
||||
if (!p->has_dimensions)
|
||||
else
|
||||
{
|
||||
e.init(x, y, x + ci.width*cos(angle), y - ci.width*sin(angle));
|
||||
e.expand_to_include(x - ci.height*sin(angle), y - ci.height*cos(angle));
|
||||
e.expand_to_include(x + (ci.width*cos(angle) - ci.height*sin(angle)), y - (ci.width*sin(angle) + ci.height*cos(angle)));
|
||||
x = new_x - distance*cos(angle);
|
||||
y = new_y + distance*sin(angle);
|
||||
|
||||
//Center the text on the line.
|
||||
x += (((double)string_height/2.0) - 1.0)*cos(angle-M_PI/2);
|
||||
y -= (((double)string_height/2.0) - 1.0)*sin(angle-M_PI/2);
|
||||
|
||||
if (!p->has_dimensions)
|
||||
{
|
||||
e.init(x, y, x + ci.width*cos(angle), y - ci.width*sin(angle));
|
||||
e.expand_to_include(x - ci.height*sin(angle), y - ci.height*cos(angle));
|
||||
e.expand_to_include(x + (ci.width*cos(angle) - ci.height*sin(angle)), y - (ci.width*sin(angle) + ci.height*cos(angle)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!detector_.has_placement(e))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
p->envelopes.push(e);
|
||||
|
||||
p->path.add_node(c, x - p->starting_x, -y + p->starting_y, (orientation == -1 ? angle + M_PI : angle));
|
||||
|
||||
distance -= ci.width;
|
||||
}
|
||||
|
||||
if (!detector_.has_placement(e))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
p->envelopes.push(e);
|
||||
|
||||
p->path.add_node(c, x - p->starting_x, -y + p->starting_y, (orientation == -1 ? angle + M_PI : angle));
|
||||
|
||||
distance -= ci.width;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool placement_finder::build_path_horizontal(placement *p, double target_distance)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
bool placement_finder::build_path_horizontal(placement *p, double target_distance)
|
||||
{
|
||||
double x, y;
|
||||
|
||||
@ -433,7 +434,159 @@ namespace mapnik
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
bool placement_finder::build_path_horizontal(placement *p, double target_distance)
|
||||
{
|
||||
|
||||
p->path.clear();
|
||||
|
||||
std::pair<double, double> string_dimensions = p->info->get_dimensions();
|
||||
double string_width = string_dimensions.first;
|
||||
double string_height = string_dimensions.second;
|
||||
|
||||
// check if we need to wrap the string
|
||||
double wrap_at = string_width + 1;
|
||||
if (p->wrap_width && string_width > p->wrap_width)
|
||||
{
|
||||
if (p->text_ratio)
|
||||
for (int i = 1; ((wrap_at = string_width/i)/(string_height*i)) > p->text_ratio && (string_width/i) > p->wrap_width; ++i);
|
||||
else
|
||||
wrap_at = p->wrap_width;
|
||||
//std::clog << "Wrapping string at" << wrap_at << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// work out where our line breaks need to be
|
||||
std::vector<int> line_breaks;
|
||||
std::vector<double> line_widths;
|
||||
if (wrap_at < string_width && p->info->num_characters() > 0)
|
||||
{
|
||||
int line_count=0;
|
||||
int last_space = 0;
|
||||
string_width = 0;
|
||||
string_height = 0;
|
||||
double line_width = 0;
|
||||
double line_height = 0;
|
||||
double word_width = 0;
|
||||
double word_height = 0;
|
||||
for (unsigned int ii = 0; ii < p->info->num_characters(); ii++)
|
||||
{
|
||||
character_info ci;
|
||||
ci = p->info->at(ii);
|
||||
|
||||
unsigned c = ci.character;
|
||||
word_width += ci.width;
|
||||
word_height = word_height > ci.height ? word_height : ci.height;
|
||||
++line_count;
|
||||
|
||||
if (c == ' ')
|
||||
{
|
||||
last_space = ii;
|
||||
line_width += word_width;
|
||||
line_height = line_height > word_height ? line_height : word_height;
|
||||
word_width = 0;
|
||||
word_height = 0;
|
||||
}
|
||||
if (line_width > 0 && line_width > wrap_at)
|
||||
{
|
||||
string_width = string_width > line_width ? string_width : line_width;
|
||||
string_height += line_height;
|
||||
line_breaks.push_back(last_space);
|
||||
line_widths.push_back(line_width);
|
||||
ii = last_space;
|
||||
line_count = 0;
|
||||
line_width = 0;
|
||||
line_height = 0;
|
||||
word_width = 0;
|
||||
word_height = 0;
|
||||
}
|
||||
}
|
||||
line_width += word_width;
|
||||
string_width = string_width > line_width ? string_width : line_width;
|
||||
line_breaks.push_back(p->info->num_characters() + 1);
|
||||
line_widths.push_back(line_width);
|
||||
}
|
||||
if (line_breaks.size() == 0)
|
||||
{
|
||||
line_breaks.push_back(p->info->num_characters() + 1);
|
||||
line_widths.push_back(string_width);
|
||||
}
|
||||
|
||||
p->info->set_dimensions(string_width, string_height);
|
||||
|
||||
if (p->geom->type() == LineString)
|
||||
{
|
||||
std::pair<double, double> starting_pos = p->get_position_at_distance(target_distance);
|
||||
|
||||
p->starting_x = starting_pos.first;
|
||||
p->starting_y = starting_pos.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->geom->label_position(&p->starting_x, &p->starting_y);
|
||||
// TODO:
|
||||
// We would only want label position in final 'paper' coords.
|
||||
// Move view and proj transforms to e.g. label_position(x,y,proj_trans,ctrans)?
|
||||
double z=0;
|
||||
p->proj_trans->backward(p->starting_x, p->starting_y, z);
|
||||
p->ctrans->forward(&p->starting_x, &p->starting_y);
|
||||
}
|
||||
|
||||
double line_height = 0;
|
||||
unsigned int line_number = 0;
|
||||
unsigned int index_to_wrap_at = line_breaks[line_number];
|
||||
double line_width = line_widths[line_number];
|
||||
|
||||
double x = -line_width/2.0;
|
||||
double y = -string_height/2.0 + 1.0;
|
||||
|
||||
for (unsigned i = 0; i < p->info->num_characters(); i++)
|
||||
{
|
||||
character_info ci;
|
||||
ci = p->info->at(i);
|
||||
|
||||
unsigned c = ci.character;
|
||||
|
||||
if (i == index_to_wrap_at)
|
||||
{
|
||||
index_to_wrap_at = line_breaks[++line_number];
|
||||
line_width = line_widths[line_number];
|
||||
y -= line_height;
|
||||
x = -line_width/2.0;
|
||||
line_height = 0;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->path.add_node(c, x, y, 0.0);
|
||||
|
||||
Envelope<double> e;
|
||||
if (p->has_dimensions)
|
||||
{
|
||||
e.init(p->starting_x - (p->dimensions.first/2.0),
|
||||
p->starting_y - (p->dimensions.second/2.0),
|
||||
p->starting_x + (p->dimensions.first/2.0),
|
||||
p->starting_y + (p->dimensions.second/2.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
e.init(p->starting_x + x,
|
||||
p->starting_y - y,
|
||||
p->starting_x + x + ci.width,
|
||||
p->starting_y - y - ci.height);
|
||||
}
|
||||
|
||||
if (!detector_.has_placement(e))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
p->envelopes.push(e);
|
||||
}
|
||||
x += ci.width;
|
||||
line_height = line_height > ci.height ? line_height : ci.height;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,113 +22,143 @@
|
||||
|
||||
//$Id$
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <mapnik/text_symbolizer.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
text_symbolizer::text_symbolizer(std::string const& name, std::string const& face_name, unsigned size,Color const& fill)
|
||||
: name_(name),
|
||||
face_name_(face_name),
|
||||
size_(size),
|
||||
fill_(fill),
|
||||
halo_fill_(Color(255,255,255)),
|
||||
halo_radius_(0),
|
||||
label_p_(point_placement),
|
||||
anchor_(0.0,0.5),
|
||||
displacement_(0.0,0.0) {}
|
||||
: name_(name),
|
||||
face_name_(face_name),
|
||||
size_(size),
|
||||
text_ratio_(0),
|
||||
wrap_width_(0),
|
||||
fill_(fill),
|
||||
halo_fill_(Color(255,255,255)),
|
||||
halo_radius_(0),
|
||||
label_p_(point_placement),
|
||||
anchor_(0.0,0.5),
|
||||
displacement_(0.0,0.0) {}
|
||||
|
||||
text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
||||
: name_(rhs.name_),
|
||||
face_name_(rhs.face_name_),
|
||||
size_(rhs.size_),
|
||||
fill_(rhs.fill_),
|
||||
halo_fill_(rhs.halo_fill_),
|
||||
halo_radius_(rhs.halo_radius_),
|
||||
label_p_(rhs.label_p_),
|
||||
anchor_(rhs.anchor_),
|
||||
displacement_(rhs.displacement_) {}
|
||||
: name_(rhs.name_),
|
||||
face_name_(rhs.face_name_),
|
||||
size_(rhs.size_),
|
||||
text_ratio_(rhs.text_ratio_),
|
||||
wrap_width_(rhs.wrap_width_),
|
||||
fill_(rhs.fill_),
|
||||
halo_fill_(rhs.halo_fill_),
|
||||
halo_radius_(rhs.halo_radius_),
|
||||
label_p_(rhs.label_p_),
|
||||
anchor_(rhs.anchor_),
|
||||
displacement_(rhs.displacement_) {}
|
||||
|
||||
text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
name_ = other.name_;
|
||||
face_name_ = other.face_name_;
|
||||
size_ = other.size_;
|
||||
fill_ = other.fill_;
|
||||
halo_fill_ = other.halo_fill_;
|
||||
label_p_ = other.label_p_;
|
||||
anchor_ = other.anchor_;
|
||||
displacement_ = other.displacement_;
|
||||
return *this;
|
||||
if (this == &other)
|
||||
return *this;
|
||||
name_ = other.name_;
|
||||
face_name_ = other.face_name_;
|
||||
size_ = other.size_;
|
||||
text_ratio_ = other.text_ratio_;
|
||||
wrap_width_ = other.wrap_width_;
|
||||
fill_ = other.fill_;
|
||||
halo_fill_ = other.halo_fill_;
|
||||
halo_radius_ = other.halo_radius_;
|
||||
label_p_ = other.label_p_;
|
||||
anchor_ = other.anchor_;
|
||||
displacement_ = other.displacement_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string const& text_symbolizer::get_name() const
|
||||
{
|
||||
return name_;
|
||||
return name_;
|
||||
}
|
||||
|
||||
std::string const& text_symbolizer::get_face_name() const
|
||||
{
|
||||
return face_name_;
|
||||
return face_name_;
|
||||
}
|
||||
|
||||
unsigned text_symbolizer::get_text_ratio() const
|
||||
{
|
||||
return text_ratio_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_text_ratio(unsigned ratio)
|
||||
{
|
||||
text_ratio_ = ratio;
|
||||
}
|
||||
|
||||
unsigned text_symbolizer::get_wrap_width() const
|
||||
{
|
||||
return wrap_width_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_wrap_width(unsigned width)
|
||||
{
|
||||
wrap_width_ = width;
|
||||
}
|
||||
|
||||
unsigned text_symbolizer::get_text_size() const
|
||||
{
|
||||
return size_;
|
||||
return size_;
|
||||
}
|
||||
|
||||
Color const& text_symbolizer::get_fill() const
|
||||
{
|
||||
return fill_;
|
||||
return fill_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_halo_fill(Color const& fill)
|
||||
{
|
||||
halo_fill_ = fill;
|
||||
halo_fill_ = fill;
|
||||
}
|
||||
|
||||
Color const& text_symbolizer::get_halo_fill() const
|
||||
{
|
||||
return halo_fill_;
|
||||
return halo_fill_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_halo_radius(unsigned radius)
|
||||
{
|
||||
halo_radius_ = radius;
|
||||
halo_radius_ = radius;
|
||||
}
|
||||
|
||||
unsigned text_symbolizer::get_halo_radius() const
|
||||
{
|
||||
return halo_radius_;
|
||||
return halo_radius_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_label_placement(label_placement_e label_p)
|
||||
{
|
||||
label_p_ = label_p;
|
||||
label_p_ = label_p;
|
||||
}
|
||||
|
||||
label_placement_e text_symbolizer::get_label_placement() const
|
||||
{
|
||||
return label_p_;
|
||||
return label_p_;
|
||||
}
|
||||
|
||||
void text_symbolizer::set_anchor(double x, double y)
|
||||
{
|
||||
anchor_ = boost::make_tuple(x,y);
|
||||
anchor_ = boost::make_tuple(x,y);
|
||||
}
|
||||
|
||||
position const& text_symbolizer::get_anchor () const
|
||||
{
|
||||
return anchor_;
|
||||
return anchor_;
|
||||
}
|
||||
void text_symbolizer::set_displacement(double x, double y)
|
||||
{
|
||||
displacement_ = boost::make_tuple(x,y);
|
||||
displacement_ = boost::make_tuple(x,y);
|
||||
}
|
||||
|
||||
position const& text_symbolizer::get_displacement() const
|
||||
{
|
||||
return displacement_;
|
||||
return displacement_;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user