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:
Artem Pavlenko 2006-10-27 17:29:39 +00:00
parent f0e6e58a8a
commit d7fcefc848
11 changed files with 592 additions and 347 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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